Merge branch 'eth2client'

This commit is contained in:
Jim McDonald 2020-11-14 08:38:12 +00:00
commit b8d26c7470
No known key found for this signature in database
GPG Key ID: 89CEB61B2AD2A5E7
57 changed files with 1761 additions and 1252 deletions

63
go.mod
View File

@ -3,57 +3,46 @@ module github.com/attestantio/vouch
go 1.14
require (
cloud.google.com/go v0.69.1 // indirect
cloud.google.com/go v0.72.0 // indirect
github.com/OneOfOne/xxhash v1.2.5 // indirect
github.com/attestantio/dirk v0.9.0
github.com/attestantio/go-eth2-client v0.6.8
github.com/aws/aws-sdk-go v1.35.9
github.com/ferranbt/fastssz v0.0.0-20201016163051-9c5a44b9b68d
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/google/uuid v1.1.2 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.15.2 // indirect
github.com/herumi/bls-eth-go-binary v0.0.0-20201015064056-ab4d637175e8
github.com/magiconair/properties v1.8.4 // indirect
github.com/minio/highwayhash v1.0.1 // indirect
github.com/attestantio/dirk v0.9.3
github.com/attestantio/go-eth2-client v0.6.10
github.com/aws/aws-sdk-go v1.35.28
github.com/ferranbt/fastssz v0.0.0-20201030134205-9b9624098321
github.com/goccy/go-yaml v1.8.4 // indirect
github.com/google/go-cmp v0.5.3 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
github.com/herumi/bls-eth-go-binary v0.0.0-20201104034342-d782bdf735de
github.com/mitchellh/go-homedir v1.1.0
github.com/opentracing/opentracing-go v1.2.0
github.com/pelletier/go-toml v1.8.1 // indirect
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.8.0
github.com/prometheus/common v0.14.0 // indirect
github.com/prometheus/procfs v0.2.0 // indirect
github.com/prysmaticlabs/ethereumapis v0.0.0-20201003171600-a72e5f77d233
github.com/prometheus/common v0.15.0 // indirect
github.com/prysmaticlabs/ethereumapis v0.0.0-20201020182719-7f66dae2bbba
github.com/prysmaticlabs/go-bitfield v0.0.0-20200618145306-2ae0807bef65
github.com/rs/zerolog v1.20.0
github.com/sasha-s/go-deadlock v0.2.0
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.4.1 // indirect
github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/sirupsen/logrus v1.6.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.7.1
github.com/stretchr/testify v1.6.1
github.com/uber/jaeger-client-go v2.25.0+incompatible
github.com/uber/jaeger-lib v2.4.0+incompatible // indirect
github.com/wealdtech/go-bytesutil v1.1.1
github.com/wealdtech/go-eth2-types/v2 v2.5.0
github.com/wealdtech/go-eth2-wallet v1.14.1
github.com/wealdtech/go-eth2-wallet-dirk v1.0.4
github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.1
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.5.1
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.16.1
github.com/wealdtech/go-eth2-wallet-store-scratch v1.6.0
github.com/wealdtech/go-eth2-wallet-types/v2 v2.8.0
github.com/wealdtech/go-eth2-types/v2 v2.5.1
github.com/wealdtech/go-eth2-wallet v1.14.3
github.com/wealdtech/go-eth2-wallet-dirk v1.1.4
github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.2
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.5.3
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.16.13
github.com/wealdtech/go-eth2-wallet-store-scratch v1.6.1
github.com/wealdtech/go-eth2-wallet-types/v2 v2.8.1
github.com/wealdtech/go-majordomo v1.0.1
go.uber.org/atomic v1.7.0 // indirect
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 // indirect
golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0 // indirect
golang.org/x/sync v0.0.0-20201008141435-b3e1573b7520
golang.org/x/sys v0.0.0-20201017003518-b09fb700fbb7 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20201015140912-32ed001d685c // indirect
google.golang.org/grpc v1.33.0
gopkg.in/ini.v1 v1.62.0 // indirect
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9 // indirect
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58 // indirect
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
golang.org/x/sys v0.0.0-20201113233024-12cec1faf1ba // indirect
google.golang.org/genproto v0.0.0-20201113130914-ce600e9a6f9e // indirect
google.golang.org/grpc v1.33.2
gotest.tools v2.2.0+incompatible
)

354
go.sum
View File

@ -11,14 +11,13 @@ cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0 h1:RmDygqvj27Zf3fCQjQRtLyC7KwFcHkeJitcO0OoGOcA=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.66.0 h1:DZeAkuQGQqnm9Xv36SbMJEU8aFBz4wL04UpMWPWwjzg=
cloud.google.com/go v0.66.0/go.mod h1:dgqGAjKCDxyhGTtC9dAREQGUJpkceNm1yt590Qno0Ko=
cloud.google.com/go v0.68.0/go.mod h1:91NO4SCDjUfe1zeC0f4/dpckkUNpuNEyqm4X2KLrzNQ=
cloud.google.com/go v0.69.1 h1:01WAtK12Fes1PhlpkgDf6iifgXbrdczf+6Cec2S+Aa8=
cloud.google.com/go v0.69.1/go.mod h1:nBQK+D2Y4slKAj03c6wkILB3imWdzebeEZgWHEmGREE=
cloud.google.com/go v0.70.0 h1:ujhG1RejZYi+HYfJNlgBh3j/bVKD8DewM7AkJ5UPyBc=
cloud.google.com/go v0.70.0/go.mod h1:/UTKYRQTWjVnSe7nGvoSzxEFUELzSI/yAYd0JQT6cRo=
cloud.google.com/go v0.72.0 h1:eWRCuwubtDrCJG0oSUMgnsbD4CmPFQF2ei4OFbXvwww=
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
@ -38,15 +37,14 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ=
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
github.com/HdrHistogram/hdrhistogram-go v0.9.0 h1:dpujRju0R4M/QZzcnR1LH1qm+TVG3UzkWdp5tH1WMcg=
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/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
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=
@ -68,34 +66,25 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
github.com/attestantio/dirk v0.8.0 h1:N3/djI47sKkXV6BWbhwxfbiO2E4TjA3f3NqTayWXyNE=
github.com/attestantio/dirk v0.9.0 h1:duHmWzjJDALFTu8Fay5nKZ9IXhVf2o6ufE08G7vb1zw=
github.com/attestantio/dirk v0.9.0/go.mod h1:oWsyIb/OXdx9pvDQqS3hdFBB1eFaYnrNjuvLtVwo69w=
github.com/attestantio/go-eth2-client v0.6.4 h1:EfnOCWlPrmLXBxMyctXUOEIcn61/QnYvnIBz5aIH8Bg=
github.com/attestantio/go-eth2-client v0.6.4/go.mod h1:lYEayGHzZma9HMUJgyxFIzDWRck8n2IedP7KTkIwe0g=
github.com/attestantio/go-eth2-client v0.6.5 h1:IaPJfxOTqHdkfmeuy6MntsuLEoJipf7V6m4njBE4F6w=
github.com/attestantio/go-eth2-client v0.6.5/go.mod h1:lYEayGHzZma9HMUJgyxFIzDWRck8n2IedP7KTkIwe0g=
github.com/attestantio/go-eth2-client v0.6.6 h1:rgqG4KDyLDw75vOqnFnJ/nAXzkp6EDFaOctMzPJYNWI=
github.com/attestantio/go-eth2-client v0.6.6/go.mod h1:lYEayGHzZma9HMUJgyxFIzDWRck8n2IedP7KTkIwe0g=
github.com/attestantio/go-eth2-client v0.6.7 h1:QphgX2XL8HMxZ3wo7RSyBhBJr9eKHNJU0GLWtVmxYG8=
github.com/attestantio/go-eth2-client v0.6.7/go.mod h1:lYEayGHzZma9HMUJgyxFIzDWRck8n2IedP7KTkIwe0g=
github.com/attestantio/go-eth2-client v0.6.8 h1:Lsjx5P0pB8ruZBfJUbqy5hpevD4Zt8Z0Lg4V5m2s53E=
github.com/attestantio/go-eth2-client v0.6.8/go.mod h1:lYEayGHzZma9HMUJgyxFIzDWRck8n2IedP7KTkIwe0g=
github.com/attestantio/dirk v0.9.1 h1:oof1Xm0uI4a2T9vhQB+f3Wjlngd2rnfsKi8aj1wqNh0=
github.com/attestantio/dirk v0.9.1/go.mod h1:oWsyIb/OXdx9pvDQqS3hdFBB1eFaYnrNjuvLtVwo69w=
github.com/attestantio/dirk v0.9.3/go.mod h1:EfppeT+VjQXnE9Ti5/vxa6ptZJAN2vMXO6KZojvSOXA=
github.com/attestantio/go-eth2-client v0.6.9/go.mod h1:ODAZ4yS1YYYew/EsgGsVb/siNEoa505CrGsvlVFdkfo=
github.com/attestantio/go-eth2-client v0.6.10 h1:PMNBMLk6xfMEUqhaUnsI0/HZRrstZF18Gt6Dm5GelW4=
github.com/attestantio/go-eth2-client v0.6.10/go.mod h1:ODAZ4yS1YYYew/EsgGsVb/siNEoa505CrGsvlVFdkfo=
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.33.5/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.33.17 h1:vngPRchZs603qLtJH7lh2pBCDqiFxA9+9nDWJ5WYJ5A=
github.com/aws/aws-sdk-go v1.33.17/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.34.31 h1:408wh5EHKzxyby8JpYfnn1w3fsF26AIU0o1kbJoRy7E=
github.com/aws/aws-sdk-go v1.34.31/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
github.com/aws/aws-sdk-go v1.35.7/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
github.com/aws/aws-sdk-go v1.35.8 h1:+S3BTWePYImKLh7DUJxMVm+/FQUnmHADsMzo/psHFr4=
github.com/aws/aws-sdk-go v1.35.8/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
github.com/aws/aws-sdk-go v1.35.9 h1:b1HiUpdkFLJyoOQ7zas36YHzjNHH0ivHx/G5lWBeg+U=
github.com/aws/aws-sdk-go v1.35.9/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
github.com/aws/aws-sdk-go v1.35.14 h1:nucVVXXjAr9UkmYCBWxQWRuYa5KOlaXjuJGg2ulW0K0=
github.com/aws/aws-sdk-go v1.35.14/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
github.com/aws/aws-sdk-go v1.35.26 h1:MawRvDpAp/Ai859dPC1xo1fdU/BIkijoHj0DwXLXXkI=
github.com/aws/aws-sdk-go v1.35.26/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
github.com/aws/aws-sdk-go v1.35.28 h1:S2LuRnfC8X05zgZLC8gy/Sb82TGv2Cpytzbzz7tkeHc=
github.com/aws/aws-sdk-go v1.35.28/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
@ -119,16 +108,13 @@ github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T
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/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.13+incompatible h1:8F3hqu9fGYLBifCmRCJsicFqDx/D68Rt3q1JMazcgBQ=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
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-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
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/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
@ -142,9 +128,7 @@ github.com/dgraph-io/ristretto v0.0.1/go.mod h1:T40EBc7CJke8TkpiYfGGKAeFjSaxuFXh
github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
github.com/dgraph-io/ristretto v0.0.3 h1:jh22xisGBjrEVnRZ1DVTpBVQm0Xndu8sMl0CWDzSIBI=
github.com/dgraph-io/ristretto v0.0.3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y=
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
@ -161,17 +145,19 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/ferranbt/fastssz v0.0.0-20200514094935-99fccaf93472 h1:maoKvILdMk6CSWHanFcUdxXIZGKD9YpWIaVbUQ/4kfg=
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/ferranbt/fastssz v0.0.0-20200514094935-99fccaf93472/go.mod h1:LlFXPmgrgVYsuoFDwV8rDJ9tvt1pLQdjKvU1b5IRES0=
github.com/ferranbt/fastssz v0.0.0-20200728110133-0b6e349af87a/go.mod h1:DyEu2iuLBnb/T51BlsiO3yLYdJC6UbGMrIkqK1KmQxM=
github.com/ferranbt/fastssz v0.0.0-20200826142241-3a913c5a1313 h1:8DS7uDmUkGF6UKNU1HivEsjrTusxLPb05KUr/D8ONWQ=
github.com/ferranbt/fastssz v0.0.0-20200826142241-3a913c5a1313/go.mod h1:DyEu2iuLBnb/T51BlsiO3yLYdJC6UbGMrIkqK1KmQxM=
github.com/ferranbt/fastssz v0.0.0-20201016163051-9c5a44b9b68d h1:gHW6nLqM4iq3m9sHAkWWFvpeSoEfRhzv3HZG4jcm/J8=
github.com/ferranbt/fastssz v0.0.0-20201016163051-9c5a44b9b68d/go.mod h1:DyEu2iuLBnb/T51BlsiO3yLYdJC6UbGMrIkqK1KmQxM=
github.com/ferranbt/fastssz v0.0.0-20201020132831-68dc48984fd3 h1:FnpkCo1TAj/eq0ETLPhAplYYB4KlFQy3kVb8cLludAc=
github.com/ferranbt/fastssz v0.0.0-20201020132831-68dc48984fd3/go.mod h1:DyEu2iuLBnb/T51BlsiO3yLYdJC6UbGMrIkqK1KmQxM=
github.com/ferranbt/fastssz v0.0.0-20201030134205-9b9624098321 h1:9Pkbf8HgETu3xKpz12Sj5clUrVFp2O+ymK7pBsTPYRM=
github.com/ferranbt/fastssz v0.0.0-20201030134205-9b9624098321/go.mod h1:DyEu2iuLBnb/T51BlsiO3yLYdJC6UbGMrIkqK1KmQxM=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
@ -185,9 +171,17 @@ 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.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/goccy/go-yaml v1.8.3 h1:VGzw2KWSUyQX0yXai02S0nttBc+Oa4Kvh6RCFoxt8SE=
github.com/goccy/go-yaml v1.8.3/go.mod h1:wS4gNoLalDSJxo/SpngzPQ2BN4uuZVLCmbM4S3vd4+Y=
github.com/goccy/go-yaml v1.8.4 h1:AOEdR7aQgbgwHznGe3BLkDQVujxCPUpHOZZcQcp8Y3M=
github.com/goccy/go-yaml v1.8.4/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA=
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.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@ -220,7 +214,6 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
@ -233,20 +226,19 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
@ -256,9 +248,9 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200905233945-acf8798be1f7/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20201009210932-67992a1a5a35/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@ -272,7 +264,6 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 h1:FlFbCRLd5Jr4iYXZufAvgWN6Ao0JrI5chLINnUXDDr0=
@ -280,14 +271,11 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaD
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.13.0 h1:sBDQoHXrOlfPobnKw69FIKa1wg9qsLLvvQ/Y19WtFgI=
github.com/grpc-ecosystem/grpc-gateway v1.13.0/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c=
github.com/grpc-ecosystem/grpc-gateway v1.14.7 h1:Nk5kuHrnWUTf/0GL1a/vchH/om9Ap2/HnVna+jYZgTY=
github.com/grpc-ecosystem/grpc-gateway v1.14.7/go.mod h1:oYZKL012gGh6LMyg/xA7Q2yq6j8bu0wa+9w14EEthWU=
github.com/grpc-ecosystem/grpc-gateway v1.15.0 h1:ntPNC9TD/6l2XDenJZe6T5lSMg95thpV9sGAqHX4WU8=
github.com/grpc-ecosystem/grpc-gateway v1.15.0/go.mod h1:vO11I9oWA+KsxmfFQPhLnnIb1VDE24M+pdxZFiuZcA8=
github.com/grpc-ecosystem/grpc-gateway v1.15.2 h1:HC+hWRWf+v5zTMPyoaYTKIJih+4sd4XRWmj0qlG87Co=
github.com/grpc-ecosystem/grpc-gateway v1.15.2/go.mod h1:vO11I9oWA+KsxmfFQPhLnnIb1VDE24M+pdxZFiuZcA8=
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
@ -312,34 +300,28 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/herumi/bls-eth-go-binary v0.0.0-20200706085701-832d8c2c0f7d h1:P8yaFmLwc5ZlUx2sHuawcdQvpv5/0GM+WEGJ07ljN3g=
github.com/herumi/bls-eth-go-binary v0.0.0-20200706085701-832d8c2c0f7d/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U=
github.com/herumi/bls-eth-go-binary v0.0.0-20200722032157-41fc56eba7b4 h1:TfBVK1MJ9vhrMXWVHu5p/MlVHZTeCGgDAEu5RykVZeI=
github.com/herumi/bls-eth-go-binary v0.0.0-20200722032157-41fc56eba7b4/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U=
github.com/herumi/bls-eth-go-binary v0.0.0-20200923072303-32b29e5d8cbf h1:Lw7EOMVxu3O+7Ro5bqn9M20a7GwuCqZQsmdXNzmcKE4=
github.com/herumi/bls-eth-go-binary v0.0.0-20200923072303-32b29e5d8cbf/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U=
github.com/herumi/bls-eth-go-binary v0.0.0-20201008062400-71567a52ad65/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U=
github.com/herumi/bls-eth-go-binary v0.0.0-20201015064056-ab4d637175e8 h1:zkPatN5r+w/I0dO/ivQL3OOHEqSVqoUy2BLbF95uf40=
github.com/herumi/bls-eth-go-binary v0.0.0-20201015064056-ab4d637175e8/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U=
github.com/herumi/bls-eth-go-binary v0.0.0-20201019012252-4b463a10c225 h1:S7pKW74AvYc89WawL6IxGSnJRxF4TkE1GITYqKFyYy4=
github.com/herumi/bls-eth-go-binary v0.0.0-20201019012252-4b463a10c225/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U=
github.com/herumi/bls-eth-go-binary v0.0.0-20201104034342-d782bdf735de h1:qLlwYGvpvAx/nDBnPt2KpZTXGli0oHBGddyYxJHTOds=
github.com/herumi/bls-eth-go-binary v0.0.0-20201104034342-d782bdf735de/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/jackc/puddle v1.1.1 h1:PJAw7H/9hoWC4Kf3J8iNmL1SwA6E8vfsLqBiL+F6CtI=
github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.2 h1:mpQEXihFnWGDy6X98EOTh81JYuxn7txby8ilJ3iIPGM=
github.com/jackc/puddle v1.1.2/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc=
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@ -354,32 +336,40 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
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/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/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY=
github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/minio/highwayhash v1.0.0 h1:iMSDhgUILCr0TNm8LWlSjF8N0ZIj2qbO8WHp6Q/J2BA=
github.com/minio/highwayhash v1.0.0/go.mod h1:xQboMTeM9nY9v/LlAOxFctujiv5+Aq2hR5dxBpaMbdc=
github.com/minio/highwayhash v1.0.1 h1:dZ6IIu8Z14VlC0VpfKofAhCy74wu/Qb5gcn52yWoz/0=
github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
@ -393,17 +383,13 @@ github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eI
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg=
github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8=
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@ -435,10 +421,7 @@ github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw=
github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs=
github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
@ -457,40 +440,34 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.8.0 h1:zvJNkoCFAnYFNC24FV8nW4JdRJ3GIFcLbg65lL/JDcw=
github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.13.0 h1:vJlpe9wPgDRM1Z+7Wj3zUUjY1nr6/1jNKyl7llliccg=
github.com/prometheus/common v0.13.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.14.0 h1:RHRyE8UocrbjU+6UvRzwi6HjiDfxrrBU91TtbKzkGp4=
github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.15.0 h1:4fgOnadei3EZvgRwxJ7RMpG1k1pOZth5Pc13tyspaKM=
github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
@ -498,28 +475,23 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T
github.com/protolambda/zssz v0.1.3/go.mod h1:a4iwOX5FE7/JkKA+J/PH0Mjo9oXftN6P8NZyL28gpag=
github.com/protolambda/zssz v0.1.5 h1:7fjJjissZIIaa2QcvmhS/pZISMX21zVITt49sW1ouek=
github.com/protolambda/zssz v0.1.5/go.mod h1:a4iwOX5FE7/JkKA+J/PH0Mjo9oXftN6P8NZyL28gpag=
github.com/prysmaticlabs/ethereumapis v0.0.0-20200812153649-a842fc47c2c3 h1:0f++UXRfp4/Mrmlfj3UaCnYj2lPr6El0gWWTBb9MD2Y=
github.com/prysmaticlabs/ethereumapis v0.0.0-20200812153649-a842fc47c2c3/go.mod h1:k7b2dxy6RppCG6kmOJkNOXzRpEoTdsPygc2aQhsUsZk=
github.com/prysmaticlabs/ethereumapis v0.0.0-20200826112054-b9e8bd145725 h1:ui38FW8BoWEXQ8VnDGI+4LTrQvRncyojGP7ZCrclIcM=
github.com/prysmaticlabs/ethereumapis v0.0.0-20200826112054-b9e8bd145725/go.mod h1:k7b2dxy6RppCG6kmOJkNOXzRpEoTdsPygc2aQhsUsZk=
github.com/prysmaticlabs/ethereumapis v0.0.0-20200923224139-64c46fb1b0fa h1:UuO9ndtrESi7kHJZZ17aXqpdwA6VDSqgfoQXWKI3dco=
github.com/prysmaticlabs/ethereumapis v0.0.0-20200923224139-64c46fb1b0fa/go.mod h1:k7b2dxy6RppCG6kmOJkNOXzRpEoTdsPygc2aQhsUsZk=
github.com/prysmaticlabs/ethereumapis v0.0.0-20201003171600-a72e5f77d233 h1:dGeuKeaXxCepTbwsz7kYSfP1yazw1uRMn58CqNCcPP4=
github.com/prysmaticlabs/ethereumapis v0.0.0-20201003171600-a72e5f77d233/go.mod h1:k7b2dxy6RppCG6kmOJkNOXzRpEoTdsPygc2aQhsUsZk=
github.com/prysmaticlabs/ethereumapis v0.0.0-20201020182719-7f66dae2bbba h1:ItW6tq3B45Gws8dO0cIuU1Srlgf4qomZnWkc0sDCln0=
github.com/prysmaticlabs/ethereumapis v0.0.0-20201020182719-7f66dae2bbba/go.mod h1:k7b2dxy6RppCG6kmOJkNOXzRpEoTdsPygc2aQhsUsZk=
github.com/prysmaticlabs/go-bitfield v0.0.0-20191017011753-53b773adde52/go.mod h1:hCwmef+4qXWjv0jLDbQdWnL0Ol7cS7/lCSS26WR+u6s=
github.com/prysmaticlabs/go-bitfield v0.0.0-20200322041314-62c2aee71669 h1:cX6YRZnZ9sgMqM5U14llxUiXVNJ3u07Res1IIjTOgtI=
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 h1:hJfAWrlxx7SKpn4S/h2JGl2HHwA1a2wSS3HAzzZ0F+U=
github.com/prysmaticlabs/go-bitfield v0.0.0-20200618145306-2ae0807bef65/go.mod h1:hCwmef+4qXWjv0jLDbQdWnL0Ol7cS7/lCSS26WR+u6s=
github.com/prysmaticlabs/go-ssz v0.0.0-20200101200214-e24db4d9e963/go.mod h1:VecIJZrewdAuhVckySLFt2wAAHRME934bSDurP8ftkc=
github.com/prysmaticlabs/go-ssz v0.0.0-20200612203617-6d5c9aa213ae h1:7qd0Af1ozWKBU3c93YW2RH+/09hJns9+ftqWUZyts9c=
github.com/prysmaticlabs/go-ssz v0.0.0-20200612203617-6d5c9aa213ae/go.mod h1:VecIJZrewdAuhVckySLFt2wAAHRME934bSDurP8ftkc=
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/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.19.0 h1:hYz4ZVdUgjXTBUmrkrw55j1nHx68LfOKIQk5IYtyScg=
github.com/rs/zerolog v1.19.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo=
github.com/rs/zerolog v1.20.0 h1:38k9hgtUBdxFwE34yS8rTHmHBa4eN16E4DJlv177LNs=
github.com/rs/zerolog v1.20.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo=
@ -535,38 +507,30 @@ 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/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.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
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/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
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/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=
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/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.3.4 h1:8q6vk3hthlpb2SouZcnBVKboxWQWMDNF38bwholZrJc=
github.com/spf13/afero v1.3.4/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/afero v1.4.0 h1:jsLTaI1zwYO3vjrzHalkVcIHXTNmdQFepW4OI8H3+x8=
github.com/spf13/afero v1.4.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/afero v1.4.1 h1:asw9sl74539yqavKaglDM5hFpdJVK0Y5Dr/JOgQ89nQ=
github.com/spf13/afero v1.4.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
@ -582,28 +546,20 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
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.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tj/assert v0.0.3/go.mod h1:Ne6X72Q+TB1AteidzQncjw9PabbMp4PBMZ1k+vd1Pvk=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/uber/jaeger-client-go v2.25.0+incompatible h1:IxcNZ7WRY1Y3G4poYlx24szfsn/3LvK9QHCq9oQw8+U=
github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/uber/jaeger-lib v2.2.0+incompatible h1:MxZXOiR2JuoANZ3J6DE/U0kSFv/eJ/GfSYVCjK7dyaw=
github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
github.com/uber/jaeger-lib v2.3.0+incompatible h1:B/kUIXcj6kIU3WSXgeJ7/uYj94I/r0LDa//JKgN/Sf0=
github.com/uber/jaeger-lib v2.3.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
github.com/uber/jaeger-lib v2.4.0+incompatible h1:fY7QsGQWiCt8pajv4r7JEvmATdCVaWxXbjwyYwsNaLQ=
github.com/uber/jaeger-lib v2.4.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/wealdtech/eth2-signer-api v1.5.2 h1:3jw8MW0r7KlX9bme0q6j+QMa8osRhEnKLkgkECH6xcU=
github.com/wealdtech/eth2-signer-api v1.5.2/go.mod h1:5wlLQ7NO7nbXo3znJOwIWHN8S4C3xHcZ0uOg9Ue4mvg=
github.com/wealdtech/eth2-signer-api v1.6.0 h1:YgQ35qS6sm1N4SGp3gcP6SHSDx7OvghstzpDQ9zvLZY=
github.com/wealdtech/eth2-signer-api v1.6.0/go.mod h1:5wlLQ7NO7nbXo3znJOwIWHN8S4C3xHcZ0uOg9Ue4mvg=
github.com/wealdtech/go-bytesutil v1.0.1/go.mod h1:jENeMqeTEU8FNZyDFRVc7KqBdRKSnJ9CCh26TcuNb9s=
@ -611,54 +567,71 @@ github.com/wealdtech/go-bytesutil v1.1.1 h1:ocEg3Ke2GkZ4vQw5lp46rmO+pfqCCTgq35gq
github.com/wealdtech/go-bytesutil v1.1.1/go.mod h1:jENeMqeTEU8FNZyDFRVc7KqBdRKSnJ9CCh26TcuNb9s=
github.com/wealdtech/go-ecodec v1.1.0 h1:yggrTSckcPJRaxxOxQF7FPm21kgE8WA6+f5jdq5Kr8o=
github.com/wealdtech/go-ecodec v1.1.0/go.mod h1:PSdBFEB6cltdT7V4E1jbboufMZTZXcQOKG/2PeEjKK4=
github.com/wealdtech/go-ecodec v1.1.1 h1:Lti3l4r/tHxviU4GzYMkkLWPuY/pJeG+QURE8KJObYk=
github.com/wealdtech/go-ecodec v1.1.1/go.mod h1:PSdBFEB6cltdT7V4E1jbboufMZTZXcQOKG/2PeEjKK4=
github.com/wealdtech/go-eth2-types/v2 v2.5.0 h1:L8sl3yoICAbn3134CBLNUt0o5h2voe0Es2KD5O9r8YQ=
github.com/wealdtech/go-eth2-types/v2 v2.5.0/go.mod h1:321w9X26lAnNa/lQJi2A6Lap5IsNORoLwFPoJ1i8QvY=
github.com/wealdtech/go-eth2-util v1.5.0/go.mod h1:0PGWeWWc6qjky/aNjdPdguJdZ2HSEHHCA+3cTjvT+Hk=
github.com/wealdtech/go-eth2-types/v2 v2.5.1 h1:59VZuwgqRaTjBu3b3CCaxG05XTmANtuTKA8hy3C6IFQ=
github.com/wealdtech/go-eth2-types/v2 v2.5.1/go.mod h1:UUtEgRum8HkPvImpu5+hFYRanMUjP0k6KWqHlYkOGbk=
github.com/wealdtech/go-eth2-util v1.6.0 h1:l2OR0SqfYdEnb1I1Ggnk0w+B9/LA5aHdQ2KK2FPnGkY=
github.com/wealdtech/go-eth2-util v1.6.0/go.mod h1:0PGWeWWc6qjky/aNjdPdguJdZ2HSEHHCA+3cTjvT+Hk=
github.com/wealdtech/go-eth2-wallet v1.12.0/go.mod h1:ouV+YSMbzk2dyecmofm8jhaMKdSigdIPMSnSqmWEfW8=
github.com/wealdtech/go-eth2-wallet v1.14.0 h1:eZjopWDMlCHCE9SLydAXBr0Cqtm2HWL3O56ELfeGK9c=
github.com/wealdtech/go-eth2-wallet v1.14.0/go.mod h1:HrJ4hLcTPZPjhdkZKZd07OFxA+r7d3i+7XKjYJbxdxk=
github.com/wealdtech/go-eth2-util v1.6.1 h1:gYW2s6iea/6NoSuSbisMqETpcnQYfqQnpmGLPYc0XHY=
github.com/wealdtech/go-eth2-util v1.6.1/go.mod h1:0hCjncDU0yi6dzGgrCgWAj6grdvJ6loEKCGpCMfxo9c=
github.com/wealdtech/go-eth2-util v1.6.2 h1:Gk7xVTG/bY1IUw/8wxOf97DuPbLTGGoZ0k5dNayudhk=
github.com/wealdtech/go-eth2-util v1.6.2/go.mod h1:0hCjncDU0yi6dzGgrCgWAj6grdvJ6loEKCGpCMfxo9c=
github.com/wealdtech/go-eth2-wallet v1.14.1 h1:0XQ6Bc2vZQCvDMg4qD6usObsXEVUPaNdv31qpwHpm0g=
github.com/wealdtech/go-eth2-wallet v1.14.1/go.mod h1:MfQZSlMPfUlvh8EAnlHan/ZQSr+lSWA1zD4QTl4116w=
github.com/wealdtech/go-eth2-wallet-dirk v1.0.2 h1:ZxAdF6iTOzYHtQlWd1nzVevZ+HtXS/LLn580t+NXT3A=
github.com/wealdtech/go-eth2-wallet-dirk v1.0.2/go.mod h1:5jK/aEAjYAVRBKKjYAvJWSmOWxiECs4asYXHwloNI+w=
github.com/wealdtech/go-eth2-wallet-dirk v1.0.3 h1:NWwxzYjFG3k7S9mzVOvj02A5S9QOak4uh+MJF2Ae37w=
github.com/wealdtech/go-eth2-wallet-dirk v1.0.3/go.mod h1:WIy6Xx0FgTNG5bP7IytxsEt8y1Yl46HbsWVFbE4Yc94=
github.com/wealdtech/go-eth2-wallet-dirk v1.0.4 h1:BOESKDQ2n8EsaeyD+wsTk71zx6VY1mpPe8ADjRqGMoE=
github.com/wealdtech/go-eth2-wallet-dirk v1.0.4/go.mod h1:ezepVp6m3sNGsZwFzcA6kjgljGek9ZGYh5AdC5PndPo=
github.com/wealdtech/go-eth2-wallet-distributed v1.1.0 h1:OZjjuxcIYo+EhAfph7lYP1z+VeNs9ruOI32kqtYe1Jg=
github.com/wealdtech/go-eth2-wallet-distributed v1.1.0/go.mod h1:8r06Vpg/315/7Hl9CXq0ShQP8/cgUrBGzKKo6ywA4yQ=
github.com/wealdtech/go-eth2-wallet v1.14.2 h1:pk6JGQdeEafVmZw5JYg2gk/8IeZjf0mY8gjufdTfYo8=
github.com/wealdtech/go-eth2-wallet v1.14.2/go.mod h1:irzlGFMyRCWlvGgdI7IjS+/Oyr3Y+Dkkh5kxo0VCRDg=
github.com/wealdtech/go-eth2-wallet v1.14.3 h1:VskYm62CSMPm9pc/93E2mO3p1GcYUg8HHUSW/rgXPks=
github.com/wealdtech/go-eth2-wallet v1.14.3/go.mod h1:cGFCLvyUua84+WQ9e9ETnXjx9hnlZgjRRYYltn+RfOE=
github.com/wealdtech/go-eth2-wallet-dirk v1.1.1 h1:lACHi/+nCQlxDEgMAwl4HE05+RN79NndqDNKTP7iAsk=
github.com/wealdtech/go-eth2-wallet-dirk v1.1.1/go.mod h1:qG4tbznw2pO80tMm3x42uPqOAO+LUhQosWApbL0enqY=
github.com/wealdtech/go-eth2-wallet-dirk v1.1.2 h1:HSF3j/RY5bl46cPgskNNz9k7NEeVRrZq+qKWDKRWqP8=
github.com/wealdtech/go-eth2-wallet-dirk v1.1.2/go.mod h1:WQ0YW8E+A8r+SjMYX8ZwouZNAHEQPvoxy4Q3OtC0KqU=
github.com/wealdtech/go-eth2-wallet-dirk v1.1.4 h1:huJwlmQDNGjjBi6B/yEDLYFUcx+xbldhoJfkVGLBJYY=
github.com/wealdtech/go-eth2-wallet-dirk v1.1.4/go.mod h1:CEQyNdk+egD2UbvnVn4qGeSBkvR09dmknCA293WiCVk=
github.com/wealdtech/go-eth2-wallet-distributed v1.1.1 h1:KSaNQbtj5XXjttTVHe1oy+LgvHmi4NHNfLl+jaTM8fU=
github.com/wealdtech/go-eth2-wallet-distributed v1.1.1/go.mod h1:Ik8JPsQQiMengG+dVUaLbFmGug1z9UOWqBDHkF1tGro=
github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.0 h1:CWb82xeNaZQt1Z829RyDALUy7UZbc6VOfTS+82jRdEQ=
github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.0/go.mod h1:JelKMM10UzDJNXdIcojMj6SCIsHC8NYn4c1S2FFk7OQ=
github.com/wealdtech/go-eth2-wallet-distributed v1.1.2 h1:ABE1tyxGfXAPPphQ32dval7+9aP61BsIdtvuOJr3azY=
github.com/wealdtech/go-eth2-wallet-distributed v1.1.2/go.mod h1:BRl33Vt9urhVuNHGiBfrf0gRs+U+gKSWCV2kmzD5xTw=
github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.1 h1:PYwMOCt92iWEHXdnsBaAk1/xygPfuBMkrXEgO8WtFdw=
github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.1/go.mod h1:JelKMM10UzDJNXdIcojMj6SCIsHC8NYn4c1S2FFk7OQ=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.3.0/go.mod h1:Kc/8WcqMTczfH2xy5mDfCRd0NI/ca/j2jXmqJ7gz8yk=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.5.0 h1:OhJm7hn6vlO+dazs5S1EBrZu/ZVQUQcaNw1ncfy0/xI=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.5.0/go.mod h1:LfgcOnQeBcqBEoHd4VNqwZhwqzz0Xh1DqnDmjHWONGs=
github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.2 h1:JRZGHJWTX9iEYNg1jKSuO5WBrLVwMLExkJg04esRgss=
github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.2/go.mod h1:q+Ng4rNBsD7nMk6s07BpAa2V6Se1aH1dua2jk5orjc0=
github.com/wealdtech/go-eth2-wallet-encryptor-unencrypted v1.0.0/go.mod h1:49K88T/4LNQpB8ghVcjTKeRRi/bZHeYjN8Ef5S23yps=
github.com/wealdtech/go-eth2-wallet-encryptor-unencrypted v1.0.1 h1:x6bq8cVgRgfhwtSQSYo/9AqJ8qEeaS6af28cW0cVj5U=
github.com/wealdtech/go-eth2-wallet-encryptor-unencrypted v1.0.1/go.mod h1:49K88T/4LNQpB8ghVcjTKeRRi/bZHeYjN8Ef5S23yps=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.5.1 h1:QoIyyVQ/vaztkeG88L1vOZKkKMM43Wo8hutH+qn8jA4=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.5.1/go.mod h1:smW8Ca0x7JO41urG0sgrlJALb1mGTSagnqaapMWiHfk=
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.3.0 h1:L1aPK9nc+8Ctcw+8I05vM6408weFc4a5RtLQDUeS0eE=
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.3.0/go.mod h1:e2q2uuEdq5+B3GE7jk+Mi9oz9V5nPPKXcXRg1XYavsU=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.5.2 h1:3EYbuUrs4cCId+WxFAtx+H/uQXRRlBLzosMRSijpwps=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.5.2/go.mod h1:hmDme779S5sqxN+W+zmHpS0K8n13fGekHM3gUUB1Ip0=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.5.3 h1:9Gt/UGrg3wWkZEFuXOdmm5Ih/wOJPP/p8l9v3MIPPzc=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.5.3/go.mod h1:UzS7JsWmOGjaSky+NTSjriTpdv+Vww1pWemb+3+GRk8=
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.3.1 h1:inSu0xN3LQN9/nEXTri5IbGLfhsvHwyrXiCI3rAHTzc=
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.3.1/go.mod h1:72HjvN+bANNgv/YCZ4Rjwgn6wesg24aHSQlHzrbPFWo=
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.3.2 h1:NwJV/Ll90WhqxhCcYCdHYWIURGXDt/GRPNFOvu4kzbg=
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.3.2/go.mod h1:WyFAmQHBIUN4hd9hAZQ9Py+N7c+mmlpDSTgiNxvICCM=
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.16.1 h1:l9YV6OBqcxp5fjscK63lzuCUIye8ANACjJdpm5ULGS8=
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.16.1/go.mod h1:Zxhj/4i8nRpk4LTTqFKbfI2KyvO3uqLMerNXqKZKDK0=
github.com/wealdtech/go-eth2-wallet-store-s3 v1.8.0/go.mod h1:OxYD+d79StAOHigNaI5bWuvjhanEyrD4MqTj8hIvt2Y=
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.16.13 h1:zVV0kL6TZ1fW/Od9BW9e7W5UJB78gNbcbRQK+HeJOL8=
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.16.13/go.mod h1:x6sKafiDSvsUeiYZq7TE/ZWIWeAToXLIqgb7KCehgjU=
github.com/wealdtech/go-eth2-wallet-store-s3 v1.9.0 h1:O5211UskLbK1WDecTXwugUlINDBQ26MqtiFn6u66fmA=
github.com/wealdtech/go-eth2-wallet-store-s3 v1.9.0/go.mod h1:dcQPLsRRYDiMV0DFYzTX6HRpP9WP+gWreAX5SLBOJ0I=
github.com/wealdtech/go-eth2-wallet-store-s3 v1.9.1 h1:YGw5YanOepPGalSyvDKwCEdwvAmG9E3pwo7v6jR/7IM=
github.com/wealdtech/go-eth2-wallet-store-s3 v1.9.1/go.mod h1:FR+mhCaoZN4d+EEBSV2QT2cO4szdKvDLTHRygMrH6fk=
github.com/wealdtech/go-eth2-wallet-store-s3 v1.9.2 h1:HFT1w+8icvHj5Yb1qDZUjzIQYnFbau1ahYwB08kwwJM=
github.com/wealdtech/go-eth2-wallet-store-s3 v1.9.2/go.mod h1:oKDDrc/BMDotY8/zT9TfmnELt+QMaPCiWwTiBmjlwTw=
github.com/wealdtech/go-eth2-wallet-store-scratch v1.6.0 h1:41H6hnVsI/csBx20UHpI2pY922N7Vhcro35DFS+slj0=
github.com/wealdtech/go-eth2-wallet-store-scratch v1.6.0/go.mod h1:XtXHbl4OV/XenQsvGmXbh+bVXaGS788oa30DB7kDInA=
github.com/wealdtech/go-eth2-wallet-types/v2 v2.5.0 h1:J29mbkSCUMl2xdu8Lg6U+JptFGfmli6xl04DAHtq9aM=
github.com/wealdtech/go-eth2-wallet-store-scratch v1.6.1 h1:vv9lR8K76FUSNbzUU25MN4HNhZIBBI1kJBNfHq2WjRY=
github.com/wealdtech/go-eth2-wallet-store-scratch v1.6.1/go.mod h1:qnI6/VRpFyKGV+DhzdC1zmx2sA7mRRanCFlk4RYzoYs=
github.com/wealdtech/go-eth2-wallet-types/v2 v2.5.0/go.mod h1:X9kYUH/E5YMqFMZ4xL6MJanABUkJGaH/yPZRT2o+yYA=
github.com/wealdtech/go-eth2-wallet-types/v2 v2.6.0 h1:vBrH5icPPSeb14cdShA7/P2PBZOgZscJ2IhBlTIaFrA=
github.com/wealdtech/go-eth2-wallet-types/v2 v2.6.0/go.mod h1:X9kYUH/E5YMqFMZ4xL6MJanABUkJGaH/yPZRT2o+yYA=
github.com/wealdtech/go-eth2-wallet-types/v2 v2.7.0 h1:pquFQdIWEiSYrpIpFuvsRuialI8t9KhFsPvbIBPnzic=
github.com/wealdtech/go-eth2-wallet-types/v2 v2.7.0/go.mod h1:X9kYUH/E5YMqFMZ4xL6MJanABUkJGaH/yPZRT2o+yYA=
github.com/wealdtech/go-eth2-wallet-types/v2 v2.8.0 h1:30sYrHQBchcOv+N2yIB2APnqf1RjwAbgXK+IzmXS6cw=
github.com/wealdtech/go-eth2-wallet-types/v2 v2.8.0/go.mod h1:X9kYUH/E5YMqFMZ4xL6MJanABUkJGaH/yPZRT2o+yYA=
github.com/wealdtech/go-eth2-wallet-types/v2 v2.8.1 h1:pcvljXdc/CqXl/JAXXtd6Ey5SqfOq9MvQutvM+5wvHQ=
github.com/wealdtech/go-eth2-wallet-types/v2 v2.8.1/go.mod h1:PWvCKqRknUmOdkXmMLpyW7wBVaAEP5BWSWRph4iWy98=
github.com/wealdtech/go-indexer v1.0.0 h1:/S4rfWQbSOnnYmwnvuTVatDibZ8o1s9bmTCHO16XINg=
github.com/wealdtech/go-indexer v1.0.0/go.mod h1:u1cjsbsOXsm5jzJDyLmZY7GsrdX8KYXKBXkZcAmk3Zg=
github.com/wealdtech/go-majordomo v1.0.1 h1:wo4e0hZmCquhz/l8T/PHLr6hF9+hPY65BM1uRdFXtc8=
@ -678,16 +651,12 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
@ -705,15 +674,14 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191105034135-c7e5f84aec59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 h1:vEg9joUBmeBcK9iSJftGNf3coIG4HqZElCPehJsfAYM=
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg=
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee h1:4yd7jl+vXjalO5ztz6Vc1VADv+S/80LGJmyl1ROJ2AI=
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9 h1:umElSU9WZirRdgu2yFHY0ayQkEnKiOC1TtM3fWXFnoU=
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -736,7 +704,6 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
@ -745,7 +712,6 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -767,8 +733,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191002035440-2ec189313ef0 h1:2mqDk8w/o6UmeUCu5Qiq2y7iMf6anbx+YA8d1JFoFrs=
golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191116160921-f9c825593386/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@ -781,42 +747,38 @@ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200528225125-3c3fba18258b h1:IYiJPiJfzktmDAO1HQiwjMjwjlYKHAL7KzeD544RJPs=
golang.org/x/net v0.0.0-20200528225125-3c3fba18258b/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc h1:zK/HqS5bZxDptfPJNq8v7vJfXtkU7r9TLIoSr1bXaP4=
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200925080053-05aa5d4ee321 h1:lleNcKRbcaC8MqgLwghIkzZ2JBQAb7QQ9MiwRt1BisA=
golang.org/x/net v0.0.0-20200925080053-05aa5d4ee321/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200927032502-5d4f70055728/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb h1:mUVeFHoDKis5nxCAzoAi7E8Ghb86EXh/RK6wtvJIqRY=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0 h1:5kGOVHlq0euqwzgTC9Vu15p6fV1Wi0ArVi8da2urnVg=
golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201024042810-be3efd7ff127/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201026091529-146b70c837a4 h1:awiuzyrRjJDb+OXi9ceHO3SDxVoN3JER57mhtqkdQBs=
golang.org/x/net v0.0.0-20201026091529-146b70c837a4/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 h1:ld7aEMNHoBnnDAX15v1T6z31v8HwR2A9FYOuAhWqkwc=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58 h1:Mj83v+wSRNEar42a/MQgxk9X42TdEmrOl9i+y8WbxLo=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201008141435-b3e1573b7520 h1:Bx6FllMpG4NWDOfhMBz1VR2QYNp/SAOHPIAsaVmxfPo=
golang.org/x/sync v0.0.0-20201008141435-b3e1573b7520/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -828,24 +790,27 @@ golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/xC2Run6RzeW1SyHxpc=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -859,31 +824,29 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200722175500-76b94024e4b6 h1:X9xIZ1YU8bLZA3l6gqDUHSFiD0GFI9S548h6C8nDtOY=
golang.org/x/sys v0.0.0-20200722175500-76b94024e4b6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200819171115-d785dc25833f h1:KJuwZVtZBVzDmEDtB2zro9CXkD9O0dpCv4o2LHbQIAw=
golang.org/x/sys v0.0.0-20200819171115-d785dc25833f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d h1:L/IKR6COd7ubZrs2oTnTi73IhgqJ71c9s80WsQnh0Es=
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201013132646-2da7054afaeb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201014080544-cc95f250f6bc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 h1:9UQO31fZ+0aKQOFldThf7BKPMJTiBfWycGh/u3UoO88=
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201017003518-b09fb700fbb7 h1:XtNJkfEjb4zR3q20BBBcYUykVOEMgZeIUOpBPfNYgxg=
golang.org/x/sys v0.0.0-20201017003518-b09fb700fbb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5 h1:iCaAy5bMeEvwANu3YnJfWwI0kWAGkEa2RXPdweI/ysk=
golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 h1:a/mKvvZr9Jcc8oKfcmgzyp7OwF73JPWsQLvH1z2Kxck=
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY=
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201113233024-12cec1faf1ba h1:xmhUJGQGbxlod18iJGqVEp9cHIPLl7QiX2aA3to708s=
golang.org/x/sys v0.0.0-20201113233024-12cec1faf1ba/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -910,7 +873,6 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc h1:NCy3Ohtk6Iny5V/reW2Ktypo4zIpWBdRJ1uFMjBxdg8=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@ -935,26 +897,23 @@ golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7 h1:LHW24ah7B+uV/OePwNP0p/t889F3QSyLvY8Sg/bK0SY=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200828161849-5deb26317202/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20200915173823-2db8f0ff891c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.0.0-20201013201025-64a9e34f3752/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.0.0-20201017001424-6003fad69a88/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0 h1:Q3Ui3V3/CVinFWFiW39Iw0kMuVrRzYX0wN6OPFp0lTA=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
@ -965,21 +924,19 @@ google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0 h1:BaiDisFir8O4IJxvAabCGGkQ6yCJegNQqSVoYUNAnbk=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.31.0/go.mod h1:CL+9IBCa2WWU6gRuBWaKqGWLFFwbEUXkfeMkHLQWYWo=
google.golang.org/api v0.32.0 h1:Le77IccnTqEa8ryp9wIpX5W3zYm7Gf9LhOp9PHcwFts=
google.golang.org/api v0.32.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.33.0 h1:+gL0XvACeMIvpwLZ5rQZzLn5cwOsgg8dIcfJ2SYfBVw=
google.golang.org/api v0.33.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.35.0 h1:TBCmTTxUrRDA1iTctnK/fIeitxIZ+TQuaf0j29fmCGo=
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
@ -1012,27 +969,23 @@ google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfG
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200528191852-705c0b31589b h1:nl5tymnV+50ACFZUDAP+xFCe3Zh3SWdMDx+ernZSKNA=
google.golang.org/genproto v0.0.0-20200528191852-705c0b31589b/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200722002428-88e341933a54 h1:ASrBgpl9XvkNTP0m39/j18mid7aoF21npu2ioIBxYnY=
google.golang.org/genproto v0.0.0-20200722002428-88e341933a54/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200731012542-8145dea6a485/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70 h1:wboULUXGF3c5qdUnKp+6gLAccE6PRpa/czkYvQ4UXv8=
google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200831141814-d751682dd103/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200914193844-75d14daec038/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200925023002-c2d885f95484 h1:Rr9EZdYRq2WLckzJQVtN3ISKoP7dvgwi7jbglILNZ34=
google.golang.org/genproto v0.0.0-20200925023002-c2d885f95484/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201002142447-3860012362da/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201013134114-7f9ee70cb474/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201014134559-03b6142f0dc9/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201015140912-32ed001d685c h1:FM0/YezufKHjM3Y9gndHmhytJuCHW0bExs92Pu3LTQ0=
google.golang.org/genproto v0.0.0-20201015140912-32ed001d685c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201022181438-0ff5f38871d5 h1:YejJbGvoWsTXHab4OKNrzk27Dr7s4lPLnewbHue1+gM=
google.golang.org/genproto v0.0.0-20201022181438-0ff5f38871d5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201111145450-ac7456db90a6 h1:iRN4+t0lvZX/l9gH14ARF9i58tsVa5a97k6aH95rC3Y=
google.golang.org/genproto v0.0.0-20201111145450-ac7456db90a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201113130914-ce600e9a6f9e h1:jRAe+6EDD0LNrVzmjx7FxBivivOZTKnXMbH5lvmxLP8=
google.golang.org/genproto v0.0.0-20201113130914-ce600e9a6f9e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
@ -1048,17 +1001,17 @@ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0 h1:T7P4R73V3SSDPhH7WW7ATbfViLtmamH0DKrP3f9AuDI=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.32.0 h1:zWTV+LMdc3kaiJMSTOFz2UgSBgx8RNQoTGiZu3fR9S0=
google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.0 h1:IBKSUNL2uBS2DkJBncPP+TwT0sp9tgA8A75NjHt6umg=
google.golang.org/grpc v1.33.0/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.1 h1:DGeFlSan2f+WEtCERJ4J9GJWk15TxUi8QGagfI87Xyc=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@ -1067,11 +1020,12 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y=
gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UDAkHu8BrjI=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
@ -1080,12 +1034,9 @@ gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.60.0 h1:P5ZzC7RJO04094NJYlEnBdFK2wwmnCAy/+7sAzvWs60=
gopkg.in/ini.v1 v1.60.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.61.0 h1:LBCdW4FmFYL4s/vDZD1RQYX7oAR6IjujCYgMdbHBR10=
gopkg.in/ini.v1 v1.61.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/jcmturner/gokrb5.v7 v7.5.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
@ -1096,7 +1047,6 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

26
main.go
View File

@ -265,13 +265,13 @@ func startServices(ctx context.Context, majordomo majordomo.Service) error {
}
log.Trace().Msg("Selecting submitter strategy")
submitterStrategy, err := selectSubmitterStrategy(ctx, eth2Client)
submitterStrategy, err := selectSubmitterStrategy(ctx, monitor, eth2Client)
if err != nil {
return errors.Wrap(err, "failed to select submitter")
}
log.Trace().Msg("Starting graffiti provider")
graffitiProvider, err := startGraffitiProvider(ctx, monitor, majordomo)
graffitiProvider, err := startGraffitiProvider(ctx, majordomo)
if err != nil {
return errors.Wrap(err, "failed to start graffiti provider")
}
@ -310,11 +310,17 @@ func startServices(ctx context.Context, majordomo majordomo.Service) error {
}
log.Trace().Msg("Starting beacon attestation aggregator")
var aggregationAttester standardattestationaggregator.Parameter
if provider, isProvider := eth2Client.(eth2client.AggregateAttestationProvider); isProvider {
aggregationAttester = standardattestationaggregator.WithAggregateAttestationDataProvider(provider)
} else {
aggregationAttester = standardattestationaggregator.WithPrysmAggregateAttestationDataProvider(eth2Client.(eth2client.PrysmAggregateAttestationProvider))
}
attestationAggregator, err := standardattestationaggregator.New(ctx,
standardattestationaggregator.WithLogLevel(logLevel(viper.GetString("attestationaggregator.log-level"))),
standardattestationaggregator.WithTargetAggregatorsPerCommitteeProvider(eth2Client.(eth2client.TargetAggregatorsPerCommitteeProvider)),
standardattestationaggregator.WithAggregateAttestationDataProvider(eth2Client.(eth2client.NonSpecAggregateAttestationProvider)),
standardattestationaggregator.WithAggregateAttestationsSubmitter(submitterStrategy.(submitter.AggregateAttestationsSubmitter)),
aggregationAttester,
standardattestationaggregator.WithAggregateAttestationsSubmitter(eth2Client.(eth2client.AggregateAttestationsSubmitter)),
standardattestationaggregator.WithMonitor(monitor.(metrics.AttestationAggregationMonitor)),
standardattestationaggregator.WithValidatingAccountsProvider(accountManager.(accountmanager.ValidatingAccountsProvider)),
)
@ -344,7 +350,7 @@ func startServices(ctx context.Context, majordomo majordomo.Service) error {
standardcontroller.WithChainTimeService(chainTime),
standardcontroller.WithProposerDutiesProvider(eth2Client.(eth2client.ProposerDutiesProvider)),
standardcontroller.WithAttesterDutiesProvider(eth2Client.(eth2client.AttesterDutiesProvider)),
standardcontroller.WithBeaconChainHeadUpdatedSource(eth2Client.(eth2client.BeaconChainHeadUpdatedSource)),
standardcontroller.WithEventsProvider(eth2Client.(eth2client.EventsProvider)),
standardcontroller.WithScheduler(scheduler),
standardcontroller.WithValidatingAccountsProvider(accountManager.(accountmanager.ValidatingAccountsProvider)),
standardcontroller.WithAttester(attester),
@ -474,7 +480,7 @@ func startMonitor(ctx context.Context) (metrics.Service, error) {
return monitor, nil
}
func startGraffitiProvider(ctx context.Context, monitor metrics.Service, majordomo majordomo.Service) (graffitiprovider.Service, error) {
func startGraffitiProvider(ctx context.Context, majordomo majordomo.Service) (graffitiprovider.Service, error) {
switch {
case viper.Get("graffiti.dynamic") != nil:
log.Info().Msg("Starting dynamic graffiti provider")
@ -524,7 +530,7 @@ func startAccountManager(ctx context.Context, monitor metrics.Service, eth2Clien
dirkaccountmanager.WithRANDAODomainProvider(eth2Client.(eth2client.RANDAODomainProvider)),
dirkaccountmanager.WithSelectionProofDomainProvider(eth2Client.(eth2client.SelectionProofDomainProvider)),
dirkaccountmanager.WithAggregateAndProofDomainProvider(eth2Client.(eth2client.AggregateAndProofDomainProvider)),
dirkaccountmanager.WithSignatureDomainProvider(eth2Client.(eth2client.SignatureDomainProvider)),
dirkaccountmanager.WithDomainProvider(eth2Client.(eth2client.DomainProvider)),
dirkaccountmanager.WithClientCert(certPEMBlock),
dirkaccountmanager.WithClientKey(keyPEMBlock),
dirkaccountmanager.WithCACert(caPEMBlock),
@ -563,7 +569,7 @@ func startAccountManager(ctx context.Context, monitor metrics.Service, eth2Clien
walletaccountmanager.WithRANDAODomainProvider(eth2Client.(eth2client.RANDAODomainProvider)),
walletaccountmanager.WithSelectionProofDomainProvider(eth2Client.(eth2client.SelectionProofDomainProvider)),
walletaccountmanager.WithAggregateAndProofDomainProvider(eth2Client.(eth2client.AggregateAndProofDomainProvider)),
walletaccountmanager.WithSignatureDomainProvider(eth2Client.(eth2client.SignatureDomainProvider)),
walletaccountmanager.WithDomainProvider(eth2Client.(eth2client.DomainProvider)),
)
if err != nil {
return nil, errors.Wrap(err, "failed to start wallet account manager service")
@ -626,7 +632,7 @@ func selectBeaconBlockProposalProvider(ctx context.Context,
return beaconBlockProposalProvider, nil
}
func selectSubmitterStrategy(ctx context.Context, 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 err error
switch viper.GetString("submitter.style") {
@ -647,6 +653,7 @@ func selectSubmitterStrategy(ctx context.Context, eth2Client eth2client.Service)
beaconCommitteeSubscriptionsSubmitters[address] = client.(eth2client.BeaconCommitteeSubscriptionsSubmitter)
}
submitter, err = multinodesubmitter.New(ctx,
multinodesubmitter.WithClientMonitor(monitor.(metrics.ClientMonitor)),
multinodesubmitter.WithProcessConcurrency(viper.GetInt64("process-concurrency")),
multinodesubmitter.WithLogLevel(logLevel(viper.GetString("submitter.log-level"))),
multinodesubmitter.WithBeaconBlockSubmitters(beaconBlockSubmitters),
@ -658,6 +665,7 @@ func selectSubmitterStrategy(ctx context.Context, eth2Client eth2client.Service)
log.Info().Msg("Starting standard submitter strategy")
submitter, err = immediatesubmitter.New(ctx,
immediatesubmitter.WithLogLevel(logLevel(viper.GetString("submitter.log-level"))),
immediatesubmitter.WithClientMonitor(monitor.(metrics.ClientMonitor)),
immediatesubmitter.WithBeaconBlockSubmitter(eth2Client.(eth2client.BeaconBlockSubmitter)),
immediatesubmitter.WithAttestationSubmitter(eth2Client.(eth2client.AttestationSubmitter)),
immediatesubmitter.WithBeaconCommitteeSubscriptionsSubmitter(eth2Client.(eth2client.BeaconCommitteeSubscriptionsSubmitter)),

View File

@ -22,6 +22,7 @@ import (
"strings"
api "github.com/attestantio/go-eth2-client/api/v1"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/attestantio/vouch/services/accountmanager"
"github.com/herumi/bls-eth-go-binary/bls"
"github.com/pkg/errors"
@ -32,12 +33,14 @@ type validatingAccount struct {
key *bls.SecretKey
}
func (a *validatingAccount) PubKey(ctx context.Context) ([]byte, error) {
return a.key.GetPublicKey().Serialize(), nil
func (a *validatingAccount) PubKey(ctx context.Context) (spec.BLSPubKey, error) {
var res spec.BLSPubKey
copy(res[:], a.key.GetPublicKey().Serialize())
return res, nil
}
func (a *validatingAccount) Index(ctx context.Context) (uint64, error) {
return a.index, nil
func (a *validatingAccount) Index(ctx context.Context) (spec.ValidatorIndex, error) {
return spec.ValidatorIndex(a.index), nil
}
func (a *validatingAccount) State() api.ValidatorState {
@ -175,8 +178,8 @@ func (m *ValidatingAccountsProvider) Accounts(ctx context.Context) ([]accountman
}
// AccountsByIndex returns accounts.
func (m *ValidatingAccountsProvider) AccountsByIndex(ctx context.Context, indices []uint64) ([]accountmanager.ValidatingAccount, error) {
indexMap := make(map[uint64]bool)
func (m *ValidatingAccountsProvider) AccountsByIndex(ctx context.Context, indices []spec.ValidatorIndex) ([]accountmanager.ValidatingAccount, error) {
indexMap := make(map[spec.ValidatorIndex]bool)
for _, index := range indices {
indexMap[index] = true
}
@ -195,7 +198,7 @@ func (m *ValidatingAccountsProvider) AccountsByIndex(ctx context.Context, indice
}
// AccountsByPubKey returns accounts.
func (m *ValidatingAccountsProvider) AccountsByPubKey(ctx context.Context, pubKeys [][]byte) ([]accountmanager.ValidatingAccount, error) {
func (m *ValidatingAccountsProvider) AccountsByPubKey(ctx context.Context, pubKeys []spec.BLSPubKey) ([]accountmanager.ValidatingAccount, error) {
keyMap := make(map[string]bool)
for _, pubKey := range pubKeys {
keyMap[fmt.Sprintf("%x", pubKey)] = true

View File

@ -177,7 +177,7 @@ func NewBeaconCommitteeSubscriptionsSubmitter() eth2client.BeaconCommitteeSubscr
}
// SubmitBeaconCommitteeSubscriptions is a mock.
func (m *BeaconCommitteeSubscriptionsSubmitter) SubmitBeaconCommitteeSubscriptions(ctx context.Context, subscriptions []*eth2client.BeaconCommitteeSubscription) error {
func (m *BeaconCommitteeSubscriptionsSubmitter) SubmitBeaconCommitteeSubscriptions(ctx context.Context, subscriptions []*api.BeaconCommitteeSubscription) error {
return nil
}
@ -190,7 +190,7 @@ func NewErroringBeaconCommitteeSubscriptionsSubmitter() eth2client.BeaconCommitt
}
// SubmitBeaconCommitteeSubscriptions is a mock.
func (m *ErroringBeaconCommitteeSubscriptionsSubmitter) SubmitBeaconCommitteeSubscriptions(ctx context.Context, subscriptions []*eth2client.BeaconCommitteeSubscription) error {
func (m *ErroringBeaconCommitteeSubscriptionsSubmitter) SubmitBeaconCommitteeSubscriptions(ctx context.Context, subscriptions []*api.BeaconCommitteeSubscription) error {
return errors.New("error")
}
@ -203,7 +203,7 @@ func NewBeaconBlockProposalProvider() eth2client.BeaconBlockProposalProvider {
}
// BeaconBlockProposal is a mock.
func (m *BeaconBlockProposalProvider) BeaconBlockProposal(ctx context.Context, slot uint64, randaoReveal []byte, graffiti []byte) (*spec.BeaconBlock, error) {
func (m *BeaconBlockProposalProvider) BeaconBlockProposal(ctx context.Context, slot spec.Slot, randaoReveal spec.BLSSignature, graffiti []byte) (*spec.BeaconBlock, error) {
// Graffiti should be 32 bytes.
fixedGraffiti := make([]byte, 32)
copy(fixedGraffiti, graffiti)
@ -219,55 +219,55 @@ func (m *BeaconBlockProposalProvider) BeaconBlockProposal(ctx context.Context, s
AggregationBits: aggregationBits,
Data: &spec.AttestationData{
Slot: slot - 1,
Index: i,
BeaconBlockRoot: []byte{
Index: spec.CommitteeIndex(i),
BeaconBlockRoot: spec.Root([32]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,
},
}),
Source: &spec.Checkpoint{
Epoch: 0,
Root: []byte{
Root: spec.Root([32]byte{
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,
},
}),
},
Target: &spec.Checkpoint{
Epoch: 1,
Root: []byte{
Root: spec.Root([32]byte{
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,
},
}),
},
},
Signature: []byte{
Signature: spec.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,
},
}),
}
}
block := &spec.BeaconBlock{
Slot: slot,
ProposerIndex: 1,
ParentRoot: []byte{
ParentRoot: spec.Root([32]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,
},
StateRoot: []byte{
}),
StateRoot: spec.Root([32]byte{
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,
},
}),
Body: &spec.BeaconBlockBody{
RANDAOReveal: randaoReveal,
ETH1Data: &spec.ETH1Data{
DepositRoot: []byte{
DepositRoot: spec.Root([32]byte{
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,
},
}),
DepositCount: 16384,
BlockHash: []byte{
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
@ -295,8 +295,8 @@ func NewBeaconProposerDomainProvider() eth2client.BeaconProposerDomainProvider {
}
// BeaconProposerDomain is a mock.
func (m *BeaconProposerDomainProvider) BeaconProposerDomain(ctx context.Context) ([]byte, error) {
return []byte{0x00, 0x00, 0x00, 0x00}, nil
func (m *BeaconProposerDomainProvider) BeaconProposerDomain(ctx context.Context) (spec.DomainType, error) {
return spec.DomainType{0x00, 0x00, 0x00, 0x00}, nil
}
// ErroringBeaconProposerDomainProvider is a mock for eth2client.BeaconProposerDomainProvider.
@ -308,8 +308,8 @@ func NewErroringBeaconProposerDomainProvider() eth2client.BeaconProposerDomainPr
}
// BeaconProposerDomain is a mock.
func (m *ErroringBeaconProposerDomainProvider) BeaconProposerDomain(ctx context.Context) ([]byte, error) {
return nil, errors.New("error")
func (m *ErroringBeaconProposerDomainProvider) BeaconProposerDomain(ctx context.Context) (spec.DomainType, error) {
return spec.DomainType{}, errors.New("error")
}
// BeaconAttesterDomainProvider is a mock for eth2client.BeaconAttesterDomainProvider.
@ -321,8 +321,8 @@ func NewBeaconAttesterDomainProvider() eth2client.BeaconAttesterDomainProvider {
}
// BeaconAttesterDomain is a mock.
func (m *BeaconAttesterDomainProvider) BeaconAttesterDomain(ctx context.Context) ([]byte, error) {
return []byte{0x01, 0x00, 0x00, 0x00}, nil
func (m *BeaconAttesterDomainProvider) BeaconAttesterDomain(ctx context.Context) (spec.DomainType, error) {
return spec.DomainType{0x01, 0x00, 0x00, 0x00}, nil
}
// ErroringBeaconAttesterDomainProvider is a mock for eth2client.BeaconAttesterDomainProvider.
@ -334,8 +334,8 @@ func NewErroringBeaconAttesterDomainProvider() eth2client.BeaconAttesterDomainPr
}
// BeaconAttesterDomain is a mock.
func (m *ErroringBeaconAttesterDomainProvider) BeaconAttesterDomain(ctx context.Context) ([]byte, error) {
return nil, errors.New("error")
func (m *ErroringBeaconAttesterDomainProvider) BeaconAttesterDomain(ctx context.Context) (spec.DomainType, error) {
return spec.DomainType{}, errors.New("error")
}
// RANDAODomainProvider is a mock for eth2client.RANDAODomainProvider.
@ -347,8 +347,8 @@ func NewRANDAODomainProvider() eth2client.RANDAODomainProvider {
}
// RANDAODomain is a mock.
func (m *RANDAODomainProvider) RANDAODomain(ctx context.Context) ([]byte, error) {
return []byte{0x02, 0x00, 0x00, 0x00}, nil
func (m *RANDAODomainProvider) RANDAODomain(ctx context.Context) (spec.DomainType, error) {
return spec.DomainType{0x02, 0x00, 0x00, 0x00}, nil
}
// ErroringRANDAODomainProvider is a mock for eth2client.RANDAODomainProvider.
@ -360,8 +360,8 @@ func NewErroringRANDAODomainProvider() eth2client.RANDAODomainProvider {
}
// RANDAODomain is a mock.
func (m *ErroringRANDAODomainProvider) RANDAODomain(ctx context.Context) ([]byte, error) {
return nil, errors.New("error")
func (m *ErroringRANDAODomainProvider) RANDAODomain(ctx context.Context) (spec.DomainType, error) {
return spec.DomainType{}, errors.New("error")
}
// DepositDomainProvider is a mock for eth2client.DepositDomainProvider.
@ -373,8 +373,8 @@ func NewDepositDomainProvider() eth2client.DepositDomainProvider {
}
// DepositDomain is a mock.
func (m *DepositDomainProvider) DepositDomain(ctx context.Context) ([]byte, error) {
return []byte{0x03, 0x00, 0x00, 0x00}, nil
func (m *DepositDomainProvider) DepositDomain(ctx context.Context) (spec.DomainType, error) {
return spec.DomainType{0x03, 0x00, 0x00, 0x00}, nil
}
// ErroringDepositDomainProvider is a mock for eth2client.DepositDomainProvider.
@ -386,8 +386,8 @@ func NewErroringDepositDomainProvider() eth2client.DepositDomainProvider {
}
// DepositDomain is a mock.
func (m *ErroringDepositDomainProvider) DepositDomain(ctx context.Context) ([]byte, error) {
return nil, errors.New("error")
func (m *ErroringDepositDomainProvider) DepositDomain(ctx context.Context) (spec.DomainType, error) {
return spec.DomainType{}, errors.New("error")
}
// VoluntaryExitDomainProvider is a mock for eth2client.VoluntaryExitDomainProvider.
@ -399,8 +399,8 @@ func NewVoluntaryExitDomainProvider() eth2client.VoluntaryExitDomainProvider {
}
// VoluntaryExitDomain is a mock.
func (m *VoluntaryExitDomainProvider) VoluntaryExitDomain(ctx context.Context) ([]byte, error) {
return []byte{0x04, 0x00, 0x00, 0x00}, nil
func (m *VoluntaryExitDomainProvider) VoluntaryExitDomain(ctx context.Context) (spec.DomainType, error) {
return spec.DomainType{0x04, 0x00, 0x00, 0x00}, nil
}
// ErroringVoluntaryExitDomainProvider is a mock for eth2client.VoluntaryExitDomainProvider.
@ -412,8 +412,8 @@ func NewErroringVoluntaryExitDomainProvider() eth2client.VoluntaryExitDomainProv
}
// VoluntaryExitDomain is a mock.
func (m *ErroringVoluntaryExitDomainProvider) VoluntaryExitDomain(ctx context.Context) ([]byte, error) {
return nil, errors.New("error")
func (m *ErroringVoluntaryExitDomainProvider) VoluntaryExitDomain(ctx context.Context) (spec.DomainType, error) {
return spec.DomainType{}, errors.New("error")
}
// SelectionProofDomainProvider is a mock for eth2client.SelectionProofDomainProvider.
@ -425,8 +425,8 @@ func NewSelectionProofDomainProvider() eth2client.SelectionProofDomainProvider {
}
// SelectionProofDomain is a mock.
func (m *SelectionProofDomainProvider) SelectionProofDomain(ctx context.Context) ([]byte, error) {
return []byte{0x05, 0x00, 0x00, 0x00}, nil
func (m *SelectionProofDomainProvider) SelectionProofDomain(ctx context.Context) (spec.DomainType, error) {
return spec.DomainType{0x05, 0x00, 0x00, 0x00}, nil
}
// ErroringSelectionProofDomainProvider is a mock for eth2client.SelectionProofDomainProvider.
@ -438,8 +438,8 @@ func NewErroringSelectionProofDomainProvider() eth2client.SelectionProofDomainPr
}
// SelectionProofDomain is a mock.
func (m *ErroringSelectionProofDomainProvider) SelectionProofDomain(ctx context.Context) ([]byte, error) {
return nil, errors.New("error")
func (m *ErroringSelectionProofDomainProvider) SelectionProofDomain(ctx context.Context) (spec.DomainType, error) {
return spec.DomainType{}, errors.New("error")
}
// AggregateAndProofDomainProvider is a mock for eth2client.AggregateAndProofDomainProvider.
@ -451,8 +451,8 @@ func NewAggregateAndProofDomainProvider() eth2client.AggregateAndProofDomainProv
}
// AggregateAndProofDomain is a mock.
func (m *AggregateAndProofDomainProvider) AggregateAndProofDomain(ctx context.Context) ([]byte, error) {
return []byte{0x06, 0x00, 0x00, 0x00}, nil
func (m *AggregateAndProofDomainProvider) AggregateAndProofDomain(ctx context.Context) (spec.DomainType, error) {
return spec.DomainType{0x06, 0x00, 0x00, 0x00}, nil
}
// ErroringAggregateAndProofDomainProvider is a mock for eth2client.AggregateAndProofDomainProvider.
@ -464,38 +464,38 @@ func NewErroringAggregateAndProofDomainProvider() eth2client.AggregateAndProofDo
}
// AggregateAndProofDomain is a mock.
func (m *ErroringAggregateAndProofDomainProvider) AggregateAndProofDomain(ctx context.Context) ([]byte, error) {
return nil, errors.New("error")
func (m *ErroringAggregateAndProofDomainProvider) AggregateAndProofDomain(ctx context.Context) (spec.DomainType, error) {
return spec.DomainType{}, errors.New("error")
}
// SignatureDomainProvider is a mock for eth2client.SignatureDomainProvider.
type SignatureDomainProvider struct{}
// DomainProvider is a mock for eth2client.DomainProvider.
type DomainProvider struct{}
// NewSignatureDomainProvider returns a mock signature domain provider.
func NewSignatureDomainProvider() eth2client.SignatureDomainProvider {
return &SignatureDomainProvider{}
// NewDomainProvider returns a mock domain provider.
func NewDomainProvider() eth2client.DomainProvider {
return &DomainProvider{}
}
// SignatureDomain is a mock.
func (m *SignatureDomainProvider) SignatureDomain(ctx context.Context, domain []byte, epoch uint64) ([]byte, error) {
var signatureDomain [32]byte
// Put the domain in the first four bytes, to differentiate signatures.
copy(signatureDomain[:], domain)
// Domain is a mock.
func (m *DomainProvider) Domain(ctx context.Context, domainType spec.DomainType, epoch spec.Epoch) (spec.Domain, error) {
var domain spec.Domain
// Put the domain type in the first four bytes, to differentiate signatures.
copy(domain[:], domainType[:])
return signatureDomain[:], nil
return domain, nil
}
// ErroringSignatureDomainProvider is a mock for eth2client.SignatureDomainProvider.
type ErroringSignatureDomainProvider struct{}
// ErroringDomainProvider is a mock for eth2client.DomainProvider.
type ErroringDomainProvider struct{}
// NewErroringSignatureDomainProvider returns a mock signature domain provider that errors.
func NewErroringSignatureDomainProvider() eth2client.SignatureDomainProvider {
return &SignatureDomainProvider{}
// NewErroringDomainProvider returns a mock signature domain provider that errors.
func NewErroringDomainProvider() eth2client.DomainProvider {
return &ErroringDomainProvider{}
}
// SignatureDomain is a mock.
func (m *ErroringSignatureDomainProvider) SignatureDomain(ctx context.Context, domain []byte, epoch uint64) ([]byte, error) {
return nil, errors.New("error")
// Domain is a mock.
func (m *ErroringDomainProvider) Domain(ctx context.Context, domainType spec.DomainType, epoch spec.Epoch) (spec.Domain, error) {
return spec.Domain{}, errors.New("error")
}
// ValidatorsProvider is a mock for eth2client.ValidatorsProvider.
@ -511,13 +511,20 @@ func _byte(input string) []byte {
return res
}
func _epochValidator(index uint64, pubKey string, withdrwalCredentials string) *api.Validator {
func _blsPubKey(input string) spec.BLSPubKey {
tmp, _ := hex.DecodeString(strings.TrimPrefix(input, "0x"))
var res spec.BLSPubKey
copy(res[:], tmp)
return res
}
func _epochValidator(index spec.ValidatorIndex, pubKey string, withdrwalCredentials string) *api.Validator {
return &api.Validator{
Index: index,
Balance: 32000000000,
State: api.ValidatorStateActiveOngoing,
Status: api.ValidatorStateActiveOngoing,
Validator: &spec.Validator{
PublicKey: _byte(pubKey),
PublicKey: _blsPubKey(pubKey),
WithdrawalCredentials: _byte(withdrwalCredentials),
EffectiveBalance: 32000000,
Slashed: false,
@ -530,8 +537,110 @@ func _epochValidator(index uint64, pubKey string, withdrwalCredentials string) *
}
// Validators is a mock.
func (m *ValidatorsProvider) Validators(ctx context.Context, stateID string, validators []eth2client.ValidatorIDProvider) (map[uint64]*api.Validator, error) {
return map[uint64]*api.Validator{
func (m *ValidatorsProvider) Validators(ctx context.Context, stateID string, validators []spec.ValidatorIndex) (map[spec.ValidatorIndex]*api.Validator, error) {
return map[spec.ValidatorIndex]*api.Validator{
0: _epochValidator(0,
"0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c",
"0x00fad2a6bfb0e7f1f0f45460944fbd8dfa7f37da06a4d13b3983cc90bb46963b"),
1: _epochValidator(1,
"0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b",
"0x00ec7ef7780c9d151597924036262dd28dc60e1228f4da6fecf9d402cb3f3594"),
2: _epochValidator(2,
"0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b",
"0x0036085c6c608e6d048505b04402568c36cce1e025722de44f9c3685a5c80fa6"),
3: _epochValidator(3,
"0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e",
"0x005a7de495bcec04d3b5e74ae09ffe493a9dd06d7dcbf18c78455571e87d901a"),
4: _epochValidator(4,
"0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e",
"0x004a28c193c65c91b7ebb5b5d14ffa7f75dc48ad4bc66de82f70fc55a2df1215"),
5: _epochValidator(5,
"0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34",
"0x005856ab195b61df2ff5d6ab2fa36f30dab45e42cfa1aaef3ffd899f29bd8641"),
6: _epochValidator(6,
"0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373",
"0x001c5d9bedbad1b7aff3b80e887e65b3357a695b70b6ee0625c2b2f6f86449f8"),
7: _epochValidator(7,
"0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac",
"0x001414bfc6dacca55f974ec910893c8617f9c99da897534c637b50e9fc695323"),
8: _epochValidator(8,
"0xa6d310dbbfab9a22450f59993f87a4ce5db6223f3b5f1f30d2c4ec718922d400e0b3c7741de8e59960f72411a0ee10a7",
"0x00ed09b6181e6f97365e221e70aeebcb2604011d8c4326f3b98ce8d79b031ae8"),
9: _epochValidator(9,
"0x9893413c00283a3f9ed9fd9845dda1cea38228d22567f9541dccc357e54a2d6a6e204103c92564cbc05f4905ac7c493a",
"0x001fe05baa70dd29ce85f694898bb6de3bcde158a825db56906b54141b2a728d"),
10: _epochValidator(10,
"0x876dd4705157eb66dc71bc2e07fb151ea53e1a62a0bb980a7ce72d15f58944a8a3752d754f52f4a60dbfc7b18169f268",
"0x00aa2cfedd0160868d0901664e9d2eac1275dd658e109fabe11c7ad87a07fc0c"),
11: _epochValidator(11,
"0xaec922bd7a9b7b1dc21993133b586b0c3041c1e2e04b513e862227b9d7aecaf9444222f7e78282a449622ffc6278915d",
"0x0076f08e6f40cf14992b7e4f524ea0cf7e1c6fd7dd5200b564c96fc099d601aa"),
12: _epochValidator(12,
"0x9314c6de0386635e2799af798884c2ea09c63b9f079e572acc00b06a7faccce501ea4dfc0b1a23b8603680a5e3481327",
"0x004a581b2ef2b79652a19d3332f6574b0213ddbd179480edbf7ff490823fd5c7"),
13: _epochValidator(13,
"0x903e2989e7442ee0a8958d020507a8bd985d3974f5e8273093be00db3935f0500e141b252bd09e3728892c7a8443863c",
"0x0040c37a4dafa560a7665394aa7502e113ecfbdb72c1ef92826db24601889b87"),
14: _epochValidator(14,
"0x84398f539a64cbe01cfcd8c485ea51cd6657b94df93ee9b5dc61e1f18f69da6ca9d4dba63c956a81c68d5d4d4277a60f",
"0x0047381e2716b14a79e1f102669c615eb3542e9230ed7712b21f305ecc1a43d5"),
15: _epochValidator(15,
"0x872c61b4a7f8510ec809e5b023f5fdda2105d024c470ddbbeca4bc74e8280af0d178d749853e8f6a841083ac1b4db98f",
"0x0020dd5f2223831fce8d1c8fd4148943c9917e1d3a92191651892dc56448451c"),
16: _epochValidator(16,
"0x8f467e5723deac7659e1ca273e28410cbaa6d495ab66ae77014f4cd21c64b6b5ab9987c9b5537fe0279bd063fe609be7",
"0x00b24fc624e56a5ed42a9639691e27e34b783c7237030367bd17cbef65fa6ccf"),
17: _epochValidator(17,
"0x8dde8306920812b32def3b663f7c540b49180345d3bcb8d3770790b7dc80030ebc06497feebd1bcf017d918f00bfa88f",
"0x0018e4071970526ed149970747c6b858307be8b60aa7440ad93c1f351af62923"),
18: _epochValidator(18,
"0xab8d3a9bcc160e518fac0756d3e192c74789588ed4a2b1debf0c78f78479ca8edb05b12ce21103076df6af4eb8756ff9",
"0x00bb019106332edfed624b40e410561513e9fb9e285cbc56a450d499a2b13769"),
19: _epochValidator(19,
"0x8d5d3672a233db513df7ad1e8beafeae99a9f0199ed4d949bbedbb6f394030c0416bd99b910e14f73c65b6a11fe6b62e",
"0x004218c29533321c9aae659d8b2148b87693d6b1eee8e119805e5298f8bf0a33"),
20: _epochValidator(20,
"0xa1c76af1545d7901214bb6be06be5d9e458f8e989c19373a920f0018327c83982f6a2ac138260b8def732cb366411ddc",
"0x0004e3d99964ee8b0b6ed11833ba55fbf7bf80fe8f4e45c4d00a3d4ff6d73c0c"),
21: _epochValidator(21,
"0x8dd74e1bb5228fc1fca274fda02b971c1003a4f409bbdfbcfec6426bf2f52addcbbebccdbf45eee6ae11eb5b5ee7244d",
"0x00037233059d7c629c79ddb7d94b0ef1275ebe55ed20fb80a414548be9ec890a"),
22: _epochValidator(22,
"0x954eb88ed1207f891dc3c28fa6cfdf8f53bf0ed3d838f3476c0900a61314d22d4f0a300da3cd010444dd5183e35a593c",
"0x0056a7b95fd200d2997155b525eacda73baae3f3196a48fb9a513ddd1e7247c3"),
23: _epochValidator(23,
"0xaf344fce60dbd5fb850070e6e76a065e1a32485245ef4f413135a86ae703da88407c5d01c71f6bb06a151ff96cca7191",
"0x005bdba6a856b0df016f8cbad0f9c02a517e2ff2f5db19187e6d1ba155d4b2e5"),
24: _epochValidator(24,
"0xae241af60691fda1cf8ca44d49573c55818c53b6141800cca2d488b9a3fba71c0f869179fff50c084657831fbeb42bf4",
"0x000cc62d0bf911cfba5320da6e1d7407ff744427f74e855fc2444357788d6830"),
25: _epochValidator(25,
"0x96746aaba64dc87835ba709332f4d5d7837ada092b439c49d251aecf92aab5dc132e917bf6f59799bc093f976a7bc021",
"0x006badd5d911c8565362da6e00dde8d2dda73fb9127d5ba26849ae0a0636172b"),
26: _epochValidator(26,
"0xb9d1d914df3d4565465c3fd52b5b96e637f9980570cabf5b5d4aadf5a329ac36ad672819d997e735f5052e28b1f0c104",
"0x00f53dc973d5288e8070cf79ac0168443f3a2703e83f600e6197067aa02ca662"),
27: _epochValidator(27,
"0x963528adb5322c2e2c54dc296ffddd2861bb103cbf64646781dfa8a3c2d8a8eda7079d2b3e95600028c44365afbf8879",
"0x00fa4e26953e907b1ed8032bdd02c9869dbbf521f3cb7bac1c8112ccf45c1d3a"),
28: _epochValidator(28,
"0xb245d63d3f9d8ea1807a629fcb1b328cb4d542f35a3d5bc478be0df389dddd712fc4c816ba3fede9a96320ae6b24a7d8",
"0x00a68cdbfc1e865255d8e436d7bc7fc63c87b5c9c247c9e5de34d4fc26a1adc9"),
29: _epochValidator(29,
"0xa98ed496c2f464226500a6ce04602ff9ef133ed6316f372f6c744aee165149f7e578b12780e0eacec307ae6907351d99",
"0x002f6d1f79f89a308365af4dbb8a850918db7844165b36e43c64e1a35b4af0b2"),
30: _epochValidator(30,
"0xae00fc3de831b09661a0ac02873c45c84cb2b58cffb6430a3f607e4c3fa1e0932397f11307cd169cdc6f79c463527260",
"0x00e6ef2894304bc790c9e6b3a75815f10ceea391d8ebb9a27e07bf54360e9b3d"),
31: _epochValidator(31,
"0xa4855c83d868f772a579133d9f23818008417b743e8447e235d8eb78b1d8f8a9f63f98c551beb7de254400f89592314d",
"0x0077c6a139204cbdaae840e0beb43b384c35182aabbc1104207b6a5a626fe75b"),
}, nil
}
// ValidatorsByPubKey is a mock.
func (m *ValidatorsProvider) ValidatorsByPubKey(ctx context.Context, stateID string, validators []spec.BLSPubKey) (map[spec.ValidatorIndex]*api.Validator, error) {
return map[spec.ValidatorIndex]*api.Validator{
0: _epochValidator(0,
"0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c",
"0x00fad2a6bfb0e7f1f0f45460944fbd8dfa7f37da06a4d13b3983cc90bb46963b"),
@ -640,8 +749,110 @@ func NewValidatorsWithoutBalanceProvider() eth2client.ValidatorsProvider {
}
// Validators is a mock.
func (m *ValidatorsWithoutBalanceProvider) Validators(ctx context.Context, stateID string, validators []eth2client.ValidatorIDProvider) (map[uint64]*api.Validator, error) {
return map[uint64]*api.Validator{
func (m *ValidatorsWithoutBalanceProvider) Validators(ctx context.Context, stateID string, validators []spec.ValidatorIndex) (map[spec.ValidatorIndex]*api.Validator, error) {
return map[spec.ValidatorIndex]*api.Validator{
0: _epochValidator(0,
"0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c",
"0x00fad2a6bfb0e7f1f0f45460944fbd8dfa7f37da06a4d13b3983cc90bb46963b"),
1: _epochValidator(1,
"0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b",
"0x00ec7ef7780c9d151597924036262dd28dc60e1228f4da6fecf9d402cb3f3594"),
2: _epochValidator(2,
"0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b",
"0x0036085c6c608e6d048505b04402568c36cce1e025722de44f9c3685a5c80fa6"),
3: _epochValidator(3,
"0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e",
"0x005a7de495bcec04d3b5e74ae09ffe493a9dd06d7dcbf18c78455571e87d901a"),
4: _epochValidator(4,
"0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e",
"0x004a28c193c65c91b7ebb5b5d14ffa7f75dc48ad4bc66de82f70fc55a2df1215"),
5: _epochValidator(5,
"0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34",
"0x005856ab195b61df2ff5d6ab2fa36f30dab45e42cfa1aaef3ffd899f29bd8641"),
6: _epochValidator(6,
"0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373",
"0x001c5d9bedbad1b7aff3b80e887e65b3357a695b70b6ee0625c2b2f6f86449f8"),
7: _epochValidator(7,
"0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac",
"0x001414bfc6dacca55f974ec910893c8617f9c99da897534c637b50e9fc695323"),
8: _epochValidator(8,
"0xa6d310dbbfab9a22450f59993f87a4ce5db6223f3b5f1f30d2c4ec718922d400e0b3c7741de8e59960f72411a0ee10a7",
"0x00ed09b6181e6f97365e221e70aeebcb2604011d8c4326f3b98ce8d79b031ae8"),
9: _epochValidator(9,
"0x9893413c00283a3f9ed9fd9845dda1cea38228d22567f9541dccc357e54a2d6a6e204103c92564cbc05f4905ac7c493a",
"0x001fe05baa70dd29ce85f694898bb6de3bcde158a825db56906b54141b2a728d"),
10: _epochValidator(10,
"0x876dd4705157eb66dc71bc2e07fb151ea53e1a62a0bb980a7ce72d15f58944a8a3752d754f52f4a60dbfc7b18169f268",
"0x00aa2cfedd0160868d0901664e9d2eac1275dd658e109fabe11c7ad87a07fc0c"),
11: _epochValidator(11,
"0xaec922bd7a9b7b1dc21993133b586b0c3041c1e2e04b513e862227b9d7aecaf9444222f7e78282a449622ffc6278915d",
"0x0076f08e6f40cf14992b7e4f524ea0cf7e1c6fd7dd5200b564c96fc099d601aa"),
12: _epochValidator(12,
"0x9314c6de0386635e2799af798884c2ea09c63b9f079e572acc00b06a7faccce501ea4dfc0b1a23b8603680a5e3481327",
"0x004a581b2ef2b79652a19d3332f6574b0213ddbd179480edbf7ff490823fd5c7"),
13: _epochValidator(13,
"0x903e2989e7442ee0a8958d020507a8bd985d3974f5e8273093be00db3935f0500e141b252bd09e3728892c7a8443863c",
"0x0040c37a4dafa560a7665394aa7502e113ecfbdb72c1ef92826db24601889b87"),
14: _epochValidator(14,
"0x84398f539a64cbe01cfcd8c485ea51cd6657b94df93ee9b5dc61e1f18f69da6ca9d4dba63c956a81c68d5d4d4277a60f",
"0x0047381e2716b14a79e1f102669c615eb3542e9230ed7712b21f305ecc1a43d5"),
15: _epochValidator(15,
"0x872c61b4a7f8510ec809e5b023f5fdda2105d024c470ddbbeca4bc74e8280af0d178d749853e8f6a841083ac1b4db98f",
"0x0020dd5f2223831fce8d1c8fd4148943c9917e1d3a92191651892dc56448451c"),
16: _epochValidator(16,
"0x8f467e5723deac7659e1ca273e28410cbaa6d495ab66ae77014f4cd21c64b6b5ab9987c9b5537fe0279bd063fe609be7",
"0x00b24fc624e56a5ed42a9639691e27e34b783c7237030367bd17cbef65fa6ccf"),
17: _epochValidator(17,
"0x8dde8306920812b32def3b663f7c540b49180345d3bcb8d3770790b7dc80030ebc06497feebd1bcf017d918f00bfa88f",
"0x0018e4071970526ed149970747c6b858307be8b60aa7440ad93c1f351af62923"),
18: _epochValidator(18,
"0xab8d3a9bcc160e518fac0756d3e192c74789588ed4a2b1debf0c78f78479ca8edb05b12ce21103076df6af4eb8756ff9",
"0x00bb019106332edfed624b40e410561513e9fb9e285cbc56a450d499a2b13769"),
19: _epochValidator(19,
"0x8d5d3672a233db513df7ad1e8beafeae99a9f0199ed4d949bbedbb6f394030c0416bd99b910e14f73c65b6a11fe6b62e",
"0x004218c29533321c9aae659d8b2148b87693d6b1eee8e119805e5298f8bf0a33"),
20: _epochValidator(20,
"0xa1c76af1545d7901214bb6be06be5d9e458f8e989c19373a920f0018327c83982f6a2ac138260b8def732cb366411ddc",
"0x0004e3d99964ee8b0b6ed11833ba55fbf7bf80fe8f4e45c4d00a3d4ff6d73c0c"),
21: _epochValidator(21,
"0x8dd74e1bb5228fc1fca274fda02b971c1003a4f409bbdfbcfec6426bf2f52addcbbebccdbf45eee6ae11eb5b5ee7244d",
"0x00037233059d7c629c79ddb7d94b0ef1275ebe55ed20fb80a414548be9ec890a"),
22: _epochValidator(22,
"0x954eb88ed1207f891dc3c28fa6cfdf8f53bf0ed3d838f3476c0900a61314d22d4f0a300da3cd010444dd5183e35a593c",
"0x0056a7b95fd200d2997155b525eacda73baae3f3196a48fb9a513ddd1e7247c3"),
23: _epochValidator(23,
"0xaf344fce60dbd5fb850070e6e76a065e1a32485245ef4f413135a86ae703da88407c5d01c71f6bb06a151ff96cca7191",
"0x005bdba6a856b0df016f8cbad0f9c02a517e2ff2f5db19187e6d1ba155d4b2e5"),
24: _epochValidator(24,
"0xae241af60691fda1cf8ca44d49573c55818c53b6141800cca2d488b9a3fba71c0f869179fff50c084657831fbeb42bf4",
"0x000cc62d0bf911cfba5320da6e1d7407ff744427f74e855fc2444357788d6830"),
25: _epochValidator(25,
"0x96746aaba64dc87835ba709332f4d5d7837ada092b439c49d251aecf92aab5dc132e917bf6f59799bc093f976a7bc021",
"0x006badd5d911c8565362da6e00dde8d2dda73fb9127d5ba26849ae0a0636172b"),
26: _epochValidator(26,
"0xb9d1d914df3d4565465c3fd52b5b96e637f9980570cabf5b5d4aadf5a329ac36ad672819d997e735f5052e28b1f0c104",
"0x00f53dc973d5288e8070cf79ac0168443f3a2703e83f600e6197067aa02ca662"),
27: _epochValidator(27,
"0x963528adb5322c2e2c54dc296ffddd2861bb103cbf64646781dfa8a3c2d8a8eda7079d2b3e95600028c44365afbf8879",
"0x00fa4e26953e907b1ed8032bdd02c9869dbbf521f3cb7bac1c8112ccf45c1d3a"),
28: _epochValidator(28,
"0xb245d63d3f9d8ea1807a629fcb1b328cb4d542f35a3d5bc478be0df389dddd712fc4c816ba3fede9a96320ae6b24a7d8",
"0x00a68cdbfc1e865255d8e436d7bc7fc63c87b5c9c247c9e5de34d4fc26a1adc9"),
29: _epochValidator(29,
"0xa98ed496c2f464226500a6ce04602ff9ef133ed6316f372f6c744aee165149f7e578b12780e0eacec307ae6907351d99",
"0x002f6d1f79f89a308365af4dbb8a850918db7844165b36e43c64e1a35b4af0b2"),
30: _epochValidator(30,
"0xae00fc3de831b09661a0ac02873c45c84cb2b58cffb6430a3f607e4c3fa1e0932397f11307cd169cdc6f79c463527260",
"0x00e6ef2894304bc790c9e6b3a75815f10ceea391d8ebb9a27e07bf54360e9b3d"),
31: _epochValidator(31,
"0xa4855c83d868f772a579133d9f23818008417b743e8447e235d8eb78b1d8f8a9f63f98c551beb7de254400f89592314d",
"0x0077c6a139204cbdaae840e0beb43b384c35182aabbc1104207b6a5a626fe75b"),
}, nil
}
// ValidatorsByPubKey is a mock.
func (m *ValidatorsWithoutBalanceProvider) ValidatorsByPubKey(ctx context.Context, stateID string, validators []spec.BLSPubKey) (map[spec.ValidatorIndex]*api.Validator, error) {
return map[spec.ValidatorIndex]*api.Validator{
0: _epochValidator(0,
"0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c",
"0x00fad2a6bfb0e7f1f0f45460944fbd8dfa7f37da06a4d13b3983cc90bb46963b"),
@ -742,14 +953,109 @@ func (m *ValidatorsWithoutBalanceProvider) Validators(ctx context.Context, state
}
// ValidatorsWithoutBalance is a mock.
func (m *ValidatorsWithoutBalanceProvider) ValidatorsWithoutBalance(ctx context.Context, stateID string, validators []eth2client.ValidatorIDProvider) (map[uint64]*api.Validator, error) {
res, err := m.Validators(ctx, stateID, validators)
if err != nil {
return nil, err
func (m *ValidatorsWithoutBalanceProvider) ValidatorsWithoutBalance(ctx context.Context, stateID string, validators []spec.ValidatorIndex) (map[spec.ValidatorIndex]*api.Validator, error) {
res := map[spec.ValidatorIndex]*api.Validator{
0: _epochValidator(0,
"0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c",
"0x00fad2a6bfb0e7f1f0f45460944fbd8dfa7f37da06a4d13b3983cc90bb46963b"),
1: _epochValidator(1,
"0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b",
"0x00ec7ef7780c9d151597924036262dd28dc60e1228f4da6fecf9d402cb3f3594"),
2: _epochValidator(2,
"0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b",
"0x0036085c6c608e6d048505b04402568c36cce1e025722de44f9c3685a5c80fa6"),
3: _epochValidator(3,
"0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e",
"0x005a7de495bcec04d3b5e74ae09ffe493a9dd06d7dcbf18c78455571e87d901a"),
4: _epochValidator(4,
"0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e",
"0x004a28c193c65c91b7ebb5b5d14ffa7f75dc48ad4bc66de82f70fc55a2df1215"),
5: _epochValidator(5,
"0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34",
"0x005856ab195b61df2ff5d6ab2fa36f30dab45e42cfa1aaef3ffd899f29bd8641"),
6: _epochValidator(6,
"0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373",
"0x001c5d9bedbad1b7aff3b80e887e65b3357a695b70b6ee0625c2b2f6f86449f8"),
7: _epochValidator(7,
"0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac",
"0x001414bfc6dacca55f974ec910893c8617f9c99da897534c637b50e9fc695323"),
8: _epochValidator(8,
"0xa6d310dbbfab9a22450f59993f87a4ce5db6223f3b5f1f30d2c4ec718922d400e0b3c7741de8e59960f72411a0ee10a7",
"0x00ed09b6181e6f97365e221e70aeebcb2604011d8c4326f3b98ce8d79b031ae8"),
9: _epochValidator(9,
"0x9893413c00283a3f9ed9fd9845dda1cea38228d22567f9541dccc357e54a2d6a6e204103c92564cbc05f4905ac7c493a",
"0x001fe05baa70dd29ce85f694898bb6de3bcde158a825db56906b54141b2a728d"),
10: _epochValidator(10,
"0x876dd4705157eb66dc71bc2e07fb151ea53e1a62a0bb980a7ce72d15f58944a8a3752d754f52f4a60dbfc7b18169f268",
"0x00aa2cfedd0160868d0901664e9d2eac1275dd658e109fabe11c7ad87a07fc0c"),
11: _epochValidator(11,
"0xaec922bd7a9b7b1dc21993133b586b0c3041c1e2e04b513e862227b9d7aecaf9444222f7e78282a449622ffc6278915d",
"0x0076f08e6f40cf14992b7e4f524ea0cf7e1c6fd7dd5200b564c96fc099d601aa"),
12: _epochValidator(12,
"0x9314c6de0386635e2799af798884c2ea09c63b9f079e572acc00b06a7faccce501ea4dfc0b1a23b8603680a5e3481327",
"0x004a581b2ef2b79652a19d3332f6574b0213ddbd179480edbf7ff490823fd5c7"),
13: _epochValidator(13,
"0x903e2989e7442ee0a8958d020507a8bd985d3974f5e8273093be00db3935f0500e141b252bd09e3728892c7a8443863c",
"0x0040c37a4dafa560a7665394aa7502e113ecfbdb72c1ef92826db24601889b87"),
14: _epochValidator(14,
"0x84398f539a64cbe01cfcd8c485ea51cd6657b94df93ee9b5dc61e1f18f69da6ca9d4dba63c956a81c68d5d4d4277a60f",
"0x0047381e2716b14a79e1f102669c615eb3542e9230ed7712b21f305ecc1a43d5"),
15: _epochValidator(15,
"0x872c61b4a7f8510ec809e5b023f5fdda2105d024c470ddbbeca4bc74e8280af0d178d749853e8f6a841083ac1b4db98f",
"0x0020dd5f2223831fce8d1c8fd4148943c9917e1d3a92191651892dc56448451c"),
16: _epochValidator(16,
"0x8f467e5723deac7659e1ca273e28410cbaa6d495ab66ae77014f4cd21c64b6b5ab9987c9b5537fe0279bd063fe609be7",
"0x00b24fc624e56a5ed42a9639691e27e34b783c7237030367bd17cbef65fa6ccf"),
17: _epochValidator(17,
"0x8dde8306920812b32def3b663f7c540b49180345d3bcb8d3770790b7dc80030ebc06497feebd1bcf017d918f00bfa88f",
"0x0018e4071970526ed149970747c6b858307be8b60aa7440ad93c1f351af62923"),
18: _epochValidator(18,
"0xab8d3a9bcc160e518fac0756d3e192c74789588ed4a2b1debf0c78f78479ca8edb05b12ce21103076df6af4eb8756ff9",
"0x00bb019106332edfed624b40e410561513e9fb9e285cbc56a450d499a2b13769"),
19: _epochValidator(19,
"0x8d5d3672a233db513df7ad1e8beafeae99a9f0199ed4d949bbedbb6f394030c0416bd99b910e14f73c65b6a11fe6b62e",
"0x004218c29533321c9aae659d8b2148b87693d6b1eee8e119805e5298f8bf0a33"),
20: _epochValidator(20,
"0xa1c76af1545d7901214bb6be06be5d9e458f8e989c19373a920f0018327c83982f6a2ac138260b8def732cb366411ddc",
"0x0004e3d99964ee8b0b6ed11833ba55fbf7bf80fe8f4e45c4d00a3d4ff6d73c0c"),
21: _epochValidator(21,
"0x8dd74e1bb5228fc1fca274fda02b971c1003a4f409bbdfbcfec6426bf2f52addcbbebccdbf45eee6ae11eb5b5ee7244d",
"0x00037233059d7c629c79ddb7d94b0ef1275ebe55ed20fb80a414548be9ec890a"),
22: _epochValidator(22,
"0x954eb88ed1207f891dc3c28fa6cfdf8f53bf0ed3d838f3476c0900a61314d22d4f0a300da3cd010444dd5183e35a593c",
"0x0056a7b95fd200d2997155b525eacda73baae3f3196a48fb9a513ddd1e7247c3"),
23: _epochValidator(23,
"0xaf344fce60dbd5fb850070e6e76a065e1a32485245ef4f413135a86ae703da88407c5d01c71f6bb06a151ff96cca7191",
"0x005bdba6a856b0df016f8cbad0f9c02a517e2ff2f5db19187e6d1ba155d4b2e5"),
24: _epochValidator(24,
"0xae241af60691fda1cf8ca44d49573c55818c53b6141800cca2d488b9a3fba71c0f869179fff50c084657831fbeb42bf4",
"0x000cc62d0bf911cfba5320da6e1d7407ff744427f74e855fc2444357788d6830"),
25: _epochValidator(25,
"0x96746aaba64dc87835ba709332f4d5d7837ada092b439c49d251aecf92aab5dc132e917bf6f59799bc093f976a7bc021",
"0x006badd5d911c8565362da6e00dde8d2dda73fb9127d5ba26849ae0a0636172b"),
26: _epochValidator(26,
"0xb9d1d914df3d4565465c3fd52b5b96e637f9980570cabf5b5d4aadf5a329ac36ad672819d997e735f5052e28b1f0c104",
"0x00f53dc973d5288e8070cf79ac0168443f3a2703e83f600e6197067aa02ca662"),
27: _epochValidator(27,
"0x963528adb5322c2e2c54dc296ffddd2861bb103cbf64646781dfa8a3c2d8a8eda7079d2b3e95600028c44365afbf8879",
"0x00fa4e26953e907b1ed8032bdd02c9869dbbf521f3cb7bac1c8112ccf45c1d3a"),
28: _epochValidator(28,
"0xb245d63d3f9d8ea1807a629fcb1b328cb4d542f35a3d5bc478be0df389dddd712fc4c816ba3fede9a96320ae6b24a7d8",
"0x00a68cdbfc1e865255d8e436d7bc7fc63c87b5c9c247c9e5de34d4fc26a1adc9"),
29: _epochValidator(29,
"0xa98ed496c2f464226500a6ce04602ff9ef133ed6316f372f6c744aee165149f7e578b12780e0eacec307ae6907351d99",
"0x002f6d1f79f89a308365af4dbb8a850918db7844165b36e43c64e1a35b4af0b2"),
30: _epochValidator(30,
"0xae00fc3de831b09661a0ac02873c45c84cb2b58cffb6430a3f607e4c3fa1e0932397f11307cd169cdc6f79c463527260",
"0x00e6ef2894304bc790c9e6b3a75815f10ceea391d8ebb9a27e07bf54360e9b3d"),
31: _epochValidator(31,
"0xa4855c83d868f772a579133d9f23818008417b743e8447e235d8eb78b1d8f8a9f63f98c551beb7de254400f89592314d",
"0x0077c6a139204cbdaae840e0beb43b384c35182aabbc1104207b6a5a626fe75b"),
}
for _, validator := range res {
validator.Balance = 0
}
return res, nil
}

View File

@ -38,7 +38,7 @@ type parameters struct {
randaoDomainProvider eth2client.RANDAODomainProvider
selectionProofDomainProvider eth2client.SelectionProofDomainProvider
aggregateAndProofDomainProvider eth2client.AggregateAndProofDomainProvider
signatureDomainProvider eth2client.SignatureDomainProvider
domainProvider eth2client.DomainProvider
validatorsProvider eth2client.ValidatorsProvider
}
@ -158,10 +158,10 @@ func WithAggregateAndProofDomainProvider(provider eth2client.AggregateAndProofDo
})
}
// WithSignatureDomainProvider sets the signature domain provider.
func WithSignatureDomainProvider(provider eth2client.SignatureDomainProvider) Parameter {
// WithDomainProvider sets the signature domain provider.
func WithDomainProvider(provider eth2client.DomainProvider) Parameter {
return parameterFunc(func(p *parameters) {
p.signatureDomainProvider = provider
p.domainProvider = provider
})
}
@ -217,8 +217,8 @@ func parseAndCheckParameters(params ...Parameter) (*parameters, error) {
if parameters.aggregateAndProofDomainProvider == nil {
return nil, errors.New("no aggregate and proof domain provider specified")
}
if parameters.signatureDomainProvider == nil {
return nil, errors.New("no signature domain provider specified")
if parameters.domainProvider == nil {
return nil, errors.New("no domain provider specified")
}
return &parameters, nil

View File

@ -26,6 +26,7 @@ import (
eth2client "github.com/attestantio/go-eth2-client"
api "github.com/attestantio/go-eth2-client/api/v1"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/attestantio/vouch/services/accountmanager"
"github.com/attestantio/vouch/services/metrics"
"github.com/pkg/errors"
@ -39,21 +40,21 @@ import (
// Service is the manager for dirk accounts.
type Service struct {
mutex sync.RWMutex
monitor metrics.AccountManagerMonitor
clientMonitor metrics.ClientMonitor
endpoints []*dirk.Endpoint
accountPaths []string
credentials credentials.TransportCredentials
accounts map[[48]byte]*ValidatingAccount
validatorsProvider eth2client.ValidatorsProvider
slotsPerEpoch uint64
beaconProposerDomain []byte
beaconAttesterDomain []byte
randaoDomain []byte
selectionProofDomain []byte
aggregateAndProofDomain []byte
signatureDomainProvider eth2client.SignatureDomainProvider
mutex sync.RWMutex
monitor metrics.AccountManagerMonitor
clientMonitor metrics.ClientMonitor
endpoints []*dirk.Endpoint
accountPaths []string
credentials credentials.TransportCredentials
accounts map[spec.BLSPubKey]*ValidatingAccount
validatorsProvider eth2client.ValidatorsProvider
slotsPerEpoch spec.Slot
beaconProposerDomainType spec.DomainType
beaconAttesterDomainType spec.DomainType
randaoDomainType spec.DomainType
selectionProofDomainType spec.DomainType
aggregateAndProofDomainType spec.DomainType
domainProvider eth2client.DomainProvider
}
// module-wide log.
@ -103,41 +104,41 @@ func New(ctx context.Context, params ...Parameter) (*Service, error) {
if err != nil {
return nil, errors.Wrap(err, "failed to obtain slots per epoch")
}
beaconAttesterDomain, err := parameters.beaconAttesterDomainProvider.BeaconAttesterDomain(ctx)
beaconAttesterDomainType, err := parameters.beaconAttesterDomainProvider.BeaconAttesterDomain(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to obtain beacon attester domain")
}
beaconProposerDomain, err := parameters.beaconProposerDomainProvider.BeaconProposerDomain(ctx)
beaconProposerDomainType, err := parameters.beaconProposerDomainProvider.BeaconProposerDomain(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to obtain beacon proposer domain")
}
randaoDomain, err := parameters.randaoDomainProvider.RANDAODomain(ctx)
randaoDomainType, err := parameters.randaoDomainProvider.RANDAODomain(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to obtain RANDAO domain")
}
selectionProofDomain, err := parameters.selectionProofDomainProvider.SelectionProofDomain(ctx)
selectionProofDomainType, err := parameters.selectionProofDomainProvider.SelectionProofDomain(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to obtain selection proof domain")
}
aggregateAndProofDomain, err := parameters.aggregateAndProofDomainProvider.AggregateAndProofDomain(ctx)
aggregateAndProofDomainType, err := parameters.aggregateAndProofDomainProvider.AggregateAndProofDomain(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to obtain aggregate and proof domain")
}
s := &Service{
monitor: parameters.monitor,
clientMonitor: parameters.clientMonitor,
endpoints: endpoints,
accountPaths: parameters.accountPaths,
credentials: credentials,
slotsPerEpoch: slotsPerEpoch,
beaconAttesterDomain: beaconAttesterDomain,
beaconProposerDomain: beaconProposerDomain,
randaoDomain: randaoDomain,
selectionProofDomain: selectionProofDomain,
aggregateAndProofDomain: aggregateAndProofDomain,
signatureDomainProvider: parameters.signatureDomainProvider,
validatorsProvider: parameters.validatorsProvider,
monitor: parameters.monitor,
clientMonitor: parameters.clientMonitor,
endpoints: endpoints,
accountPaths: parameters.accountPaths,
credentials: credentials,
slotsPerEpoch: spec.Slot(slotsPerEpoch),
beaconAttesterDomainType: beaconAttesterDomainType,
beaconProposerDomainType: beaconProposerDomainType,
randaoDomainType: randaoDomainType,
selectionProofDomainType: selectionProofDomainType,
aggregateAndProofDomainType: aggregateAndProofDomainType,
domainProvider: parameters.domainProvider,
validatorsProvider: parameters.validatorsProvider,
}
if err := s.RefreshAccounts(ctx); err != nil {
@ -150,23 +151,24 @@ func New(ctx context.Context, params ...Parameter) (*Service, error) {
// UpdateAccountsState updates account state with the latest information from the beacon chain.
// This should be run at the beginning of each epoch to ensure that any newly-activated accounts are registered.
func (s *Service) UpdateAccountsState(ctx context.Context) error {
validatorIDs := make([]eth2client.ValidatorIDProvider, 0, len(s.accounts))
validatorIDProviders := make([]eth2client.ValidatorIDProvider, 0, len(s.accounts))
for _, account := range s.accounts {
if !account.state.HasActivated() {
validatorIDs = append(validatorIDs, account)
validatorIDProviders = append(validatorIDProviders, account)
}
}
if len(validatorIDs) == 0 {
if len(validatorIDProviders) == 0 {
// Nothing to do.
log.Trace().Msg("No unactivated keys")
return nil
}
log.Trace().Int("total", len(s.accounts)).Int("unactivated", len(validatorIDs)).Msg("Updating state of unactivated keys")
var validators map[uint64]*api.Validator
// TODO unactivated validators can have an index of 0, so cannot send via an API call that is by index. Need to use bypubkeys.
log.Trace().Int("total", len(s.accounts)).Int("unactivated", len(validatorIDProviders)).Msg("Updating state of unactivated keys")
var validators map[spec.ValidatorIndex]*api.Validator
var err error
if validatorsWithoutBalanceProvider, isProvider := s.validatorsProvider.(eth2client.ValidatorsWithoutBalanceProvider); isProvider {
started := time.Now()
validators, err = validatorsWithoutBalanceProvider.ValidatorsWithoutBalance(ctx, "head", validatorIDs)
validators, err = validatorsWithoutBalanceProvider.ValidatorsWithoutBalance(ctx, "head", validatorIDProviders)
if service, isService := s.validatorsProvider.(eth2client.Service); isService {
s.clientMonitor.ClientOperation(service.Address(), "validators without balance", err == nil, time.Since(started))
} else {
@ -177,6 +179,16 @@ func (s *Service) UpdateAccountsState(ctx context.Context) error {
}
} else {
started := time.Now()
validatorIDs := make([]spec.ValidatorIndex, 0, len(s.accounts))
for _, account := range s.accounts {
if !account.state.HasActivated() {
index, err := account.Index(ctx)
if err != nil {
return errors.Wrap(err, "failed to obtain account index")
}
validatorIDs = append(validatorIDs, index)
}
}
validators, err = s.validatorsProvider.Validators(ctx, "head", validatorIDs)
if service, isService := s.validatorsProvider.(eth2client.Service); isService {
s.clientMonitor.ClientOperation(service.Address(), "validators", err == nil, time.Since(started))
@ -220,7 +232,7 @@ func (s *Service) RefreshAccounts(ctx context.Context) error {
verificationRegexes := accountPathsToVerificationRegexes(s.accountPaths)
// Fetch accounts for each wallet.
accounts := make(map[[48]byte]*ValidatingAccount)
accounts := make(map[spec.BLSPubKey]*ValidatingAccount)
for _, wallet := range wallets {
// if _, isProvider := wallet.(e2wtypes.WalletAccountsByPathProvider); isProvider {
// fmt.Printf("TODO: fetch accounts by path")
@ -229,32 +241,44 @@ func (s *Service) RefreshAccounts(ctx context.Context) error {
//}
}
validatorIDs := make([]eth2client.ValidatorIDProvider, 0, len(accounts))
// Update indices for accounts.
pubKeys := make([]spec.BLSPubKey, 0, len(accounts))
for _, account := range accounts {
if !account.state.IsAttesting() {
validatorIDs = append(validatorIDs, account)
pubKey, err := account.PubKey(ctx)
if err != nil {
return errors.Wrap(err, "failed to obtain public key")
}
pubKeys = append(pubKeys, pubKey)
}
log.Trace().Int("keys", len(accounts)).Msg("Keys obtained")
if len(validatorIDs) == 0 {
log.Warn().Msg("No accounts obtained")
return nil
validators, err := s.validatorsProvider.ValidatorsByPubKey(ctx, "head", pubKeys)
if err != nil {
return errors.Wrap(err, "failed to obtain validators")
}
log.Trace().Int("accounts", len(validatorIDs)).Msg("Obtaining validator state of accounts")
var validators map[uint64]*api.Validator
var err error
if validatorsWithoutBalanceProvider, isProvider := s.validatorsProvider.(eth2client.ValidatorsWithoutBalanceProvider); isProvider {
validators, err = validatorsWithoutBalanceProvider.ValidatorsWithoutBalance(ctx, "head", validatorIDs)
if err != nil {
return errors.Wrap(err, "failed to obtain validators without balances")
}
} else {
validators, err = s.validatorsProvider.Validators(ctx, "head", validatorIDs)
if err != nil {
return errors.Wrap(err, "failed to obtain validators")
}
}
// log.Trace().Int("accounts", len(validatorIDProviders)).Msg("Obtaining validator state of accounts")
// var validators map[uint64]*api.Validator
// var err error
// if validatorsWithoutBalanceProvider, isProvider := s.validatorsProvider.(eth2client.ValidatorsWithoutBalanceProvider); isProvider {
// validators, err = validatorsWithoutBalanceProvider.ValidatorsWithoutBalance(ctx, "head", validatorIDProviders)
// if err != nil {
// return errors.Wrap(err, "failed to obtain validators without balances")
// }
// } else {
// validatorIDs := make([]uint64, 0, len(s.accounts))
// for _, account := range s.accounts {
// if !account.state.IsAttesting() {
// index, err := account.Index(ctx)
// if err != nil {
// return errors.Wrap(err, "failed to obtain account index")
// }
// validatorIDs = append(validatorIDs, index)
// }
// }
// validators, err = s.validatorsProvider.Validators(ctx, "head", validatorIDs)
// if err != nil {
// return errors.Wrap(err, "failed to obtain validators")
// }
// }
log.Trace().Int("received", len(validators)).Msg("Received state of accounts")
s.updateAccountStates(ctx, accounts, validators)
@ -304,8 +328,8 @@ func (s *Service) Accounts(ctx context.Context) ([]accountmanager.ValidatingAcco
}
// AccountsByIndex returns attesting accounts.
func (s *Service) AccountsByIndex(ctx context.Context, indices []uint64) ([]accountmanager.ValidatingAccount, error) {
indexMap := make(map[uint64]bool)
func (s *Service) AccountsByIndex(ctx context.Context, indices []spec.ValidatorIndex) ([]accountmanager.ValidatingAccount, error) {
indexMap := make(map[spec.ValidatorIndex]bool)
for _, index := range indices {
indexMap[index] = true
}
@ -333,12 +357,10 @@ func (s *Service) AccountsByIndex(ctx context.Context, indices []uint64) ([]acco
}
// AccountsByPubKey returns validating accounts.
func (s *Service) AccountsByPubKey(ctx context.Context, pubKeys [][]byte) ([]accountmanager.ValidatingAccount, error) {
pubKeyMap := make(map[[48]byte]bool)
func (s *Service) AccountsByPubKey(ctx context.Context, pubKeys []spec.BLSPubKey) ([]accountmanager.ValidatingAccount, error) {
pubKeyMap := make(map[spec.BLSPubKey]bool)
for _, pubKey := range pubKeys {
var mapKey [48]byte
copy(mapKey[:], pubKey)
pubKeyMap[mapKey] = true
pubKeyMap[pubKey] = true
}
s.mutex.RLock()
@ -388,19 +410,17 @@ func accountPathsToVerificationRegexes(paths []string) []*regexp.Regexp {
return regexes
}
func (s *Service) updateAccountStates(ctx context.Context, accounts map[[48]byte]*ValidatingAccount, validators map[uint64]*api.Validator) {
func (s *Service) updateAccountStates(ctx context.Context, accounts map[spec.BLSPubKey]*ValidatingAccount, validators map[spec.ValidatorIndex]*api.Validator) {
validatorsByPubKey := make(map[[48]byte]*api.Validator, len(validators))
for _, validator := range validators {
var pubKey [48]byte
copy(pubKey[:], validator.Validator.PublicKey)
validatorsByPubKey[pubKey] = validator
validatorsByPubKey[validator.Validator.PublicKey] = validator
}
validatorStateCounts := make(map[string]uint64)
for pubKey, account := range accounts {
if validator, exists := validatorsByPubKey[pubKey]; exists {
account.index = validator.Index
account.state = validator.State
account.state = validator.Status
}
validatorStateCounts[strings.ToLower(account.state.String())]++
}
@ -419,7 +439,7 @@ func (s *Service) updateAccountStates(ctx context.Context, accounts map[[48]byte
}
}
func (s *Service) fetchAccountsForWallet(ctx context.Context, wallet e2wtypes.Wallet, accounts map[[48]byte]*ValidatingAccount, verificationRegexes []*regexp.Regexp) {
func (s *Service) fetchAccountsForWallet(ctx context.Context, wallet e2wtypes.Wallet, accounts map[spec.BLSPubKey]*ValidatingAccount, verificationRegexes []*regexp.Regexp) {
for account := range wallet.Accounts(ctx) {
// Ensure the name matches one of our account paths.
name := fmt.Sprintf("%s/%s", wallet.Name(), account.Name())
@ -444,9 +464,9 @@ func (s *Service) fetchAccountsForWallet(ctx context.Context, wallet e2wtypes.Wa
// Set up account as unknown to beacon chain.
accounts[bytesutil.ToBytes48(pubKey)] = &ValidatingAccount{
account: account,
accountManager: s,
signatureDomainProvider: s.signatureDomainProvider,
account: account,
accountManager: s,
domainProvider: s.domainProvider,
}
}
}

View File

@ -23,6 +23,7 @@ import (
"github.com/attestantio/dirk/testing/daemon"
api "github.com/attestantio/go-eth2-client/api/v1"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/attestantio/vouch/mock"
nullmetrics "github.com/attestantio/vouch/services/metrics/null"
"github.com/attestantio/vouch/testing/logger"
@ -57,9 +58,9 @@ func TestFetchAccountsForWallet(t *testing.T) {
// Test with wallet regex.
s, err := setupService(ctx, t, []string{"localhost:12345"}, []string{"wallet1", "wallet2"})
require.NoError(t, err)
validatingAccounts := make(map[[48]byte]*ValidatingAccount)
validatingAccounts := make(map[spec.BLSPubKey]*ValidatingAccount)
for account := range wallets[0].Accounts(ctx) {
var key [48]byte
var key spec.BLSPubKey
copy(key[:], account.PublicKey().Marshal())
validatingAccounts[key] = &ValidatingAccount{
account: account,
@ -76,9 +77,9 @@ func TestFetchAccountsForWallet(t *testing.T) {
capture := logger.NewLogCapture()
s, err = setupService(ctx, t, []string{"localhost:12345"}, []string{"wallet1", "wallet2"})
require.NoError(t, err)
validatingAccounts = make(map[[48]byte]*ValidatingAccount)
validatingAccounts = make(map[spec.BLSPubKey]*ValidatingAccount)
for account := range wallets[0].Accounts(ctx) {
var key [48]byte
var key spec.BLSPubKey
copy(key[:], account.PublicKey().Marshal())
validatingAccounts[key] = &ValidatingAccount{
account: account,
@ -180,7 +181,7 @@ func TestAccountPathsToVerificationRegexes(t *testing.T) {
func TestAccounts(t *testing.T) {
tests := []struct {
name string
accounts map[[48]byte]*ValidatingAccount
accounts map[spec.BLSPubKey]*ValidatingAccount
expected int
}{
{
@ -260,7 +261,7 @@ func TestUpdateAccountsStateWithoutBalances(t *testing.T) {
WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
WithDomainProvider(mock.NewDomainProvider()),
)
require.NoError(t, err)
accounts, err := s.Accounts(ctx)
@ -301,7 +302,7 @@ func setupService(ctx context.Context, t *testing.T, endpoints []string, account
WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
WithDomainProvider(mock.NewDomainProvider()),
)
}

View File

@ -23,11 +23,13 @@ import (
"time"
"github.com/attestantio/dirk/testing/daemon"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/attestantio/vouch/mock"
"github.com/attestantio/vouch/services/accountmanager/dirk"
nullmetrics "github.com/attestantio/vouch/services/metrics/null"
"github.com/attestantio/vouch/testing/logger"
"github.com/attestantio/vouch/testing/resources"
"github.com/attestantio/vouch/testutil"
"github.com/rs/zerolog"
"github.com/stretchr/testify/require"
)
@ -37,6 +39,36 @@ func _byte(input string) []byte {
return res
}
func _root(input string) spec.Root {
res, err := hex.DecodeString(strings.TrimPrefix(input, "0x"))
if err != nil {
panic(err)
}
var root spec.Root
copy(root[:], res)
return root
}
func _sig(input string) spec.BLSSignature {
res, err := hex.DecodeString(strings.TrimPrefix(input, "0x"))
if err != nil {
panic(err)
}
var sig spec.BLSSignature
copy(sig[:], res)
return sig
}
func _pubKey(input string) spec.BLSPubKey {
res, err := hex.DecodeString(strings.TrimPrefix(input, "0x"))
if err != nil {
panic(err)
}
var pubKey spec.BLSPubKey
copy(pubKey[:], res)
return pubKey
}
func TestService(t *testing.T) {
slotsPerEpochProvider := mock.NewSlotsPerEpochProvider(32)
beaconProposerDomainProvider := mock.NewBeaconProposerDomainProvider()
@ -44,7 +76,7 @@ func TestService(t *testing.T) {
randaoDomainProvider := mock.NewRANDAODomainProvider()
selectionProofDomainProvider := mock.NewSelectionProofDomainProvider()
aggregateAndProofDomainProvider := mock.NewAggregateAndProofDomainProvider()
signatureDomainProvider := mock.NewSignatureDomainProvider()
domainProvider := mock.NewDomainProvider()
validatorsProvider := mock.NewValidatorsProvider()
tests := []struct {
@ -71,7 +103,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "problem with parameters: no monitor specified",
},
@ -93,7 +125,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "problem with parameters: no client monitor specified",
},
@ -114,7 +146,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "problem with parameters: no endpoints specified",
},
@ -136,7 +168,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "problem with parameters: no endpoints specified",
},
@ -158,7 +190,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "no valid endpoints specified",
logEntry: "Malformed endpoint",
@ -181,7 +213,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "no valid endpoints specified",
logEntry: "Malformed port",
@ -204,7 +236,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "no valid endpoints specified",
logEntry: "Invalid port",
@ -226,7 +258,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "problem with parameters: no account paths specified",
},
@ -248,7 +280,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "problem with parameters: no account paths specified",
},
@ -269,7 +301,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "problem with parameters: no client certificate specified",
},
@ -290,7 +322,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "problem with parameters: no client key specified",
},
@ -312,7 +344,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "failed to build credentials: failed to load client keypair: tls: private key does not match public key",
},
@ -333,7 +365,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "problem with parameters: no validators provider specified",
},
@ -354,7 +386,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "problem with parameters: no slots per epoch provider specified",
},
@ -376,7 +408,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "failed to obtain slots per epoch: error",
},
@ -397,7 +429,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "problem with parameters: no beacon proposer domain provider specified",
},
@ -419,7 +451,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "failed to obtain beacon proposer domain: error",
},
@ -440,7 +472,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "problem with parameters: no beacon attester domain provider specified",
},
@ -462,7 +494,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "failed to obtain beacon attester domain: error",
},
@ -483,7 +515,7 @@ func TestService(t *testing.T) {
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "problem with parameters: no RANDAO domain provider specified",
},
@ -505,7 +537,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(mock.NewErroringRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "failed to obtain RANDAO domain: error",
},
@ -526,7 +558,7 @@ func TestService(t *testing.T) {
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "problem with parameters: no selection proof domain provider specified",
},
@ -548,7 +580,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(mock.NewErroringSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "failed to obtain selection proof domain: error",
},
@ -569,7 +601,7 @@ func TestService(t *testing.T) {
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "problem with parameters: no aggregate and proof domain provider specified",
},
@ -591,12 +623,12 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(mock.NewErroringAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
err: "failed to obtain aggregate and proof domain: error",
},
{
name: "SignatureDomainProviderMissing",
name: "DomainProviderMissing",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
@ -614,7 +646,7 @@ func TestService(t *testing.T) {
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
},
err: "problem with parameters: no signature domain provider specified",
err: "problem with parameters: no domain provider specified",
},
{
name: "Good",
@ -634,7 +666,7 @@ func TestService(t *testing.T) {
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
dirk.WithDomainProvider(domainProvider),
},
},
}
@ -705,7 +737,7 @@ func TestAccounts(t *testing.T) {
dirk.WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
dirk.WithDomainProvider(mock.NewDomainProvider()),
)
require.Nil(t, err)
@ -728,7 +760,7 @@ func TestAccountsByIndex(t *testing.T) {
tests := []struct {
name string
indices []uint64
indices []spec.ValidatorIndex
accounts int
}{
{
@ -737,17 +769,17 @@ func TestAccountsByIndex(t *testing.T) {
},
{
name: "Empty",
indices: []uint64{},
indices: []spec.ValidatorIndex{},
accounts: 0,
},
{
name: "All",
indices: []uint64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
indices: []spec.ValidatorIndex{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
accounts: 16,
},
{
name: "Missing",
indices: []uint64{15, 16},
indices: []spec.ValidatorIndex{15, 16},
accounts: 1,
},
}
@ -770,7 +802,7 @@ func TestAccountsByIndex(t *testing.T) {
dirk.WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
dirk.WithDomainProvider(mock.NewDomainProvider()),
)
require.Nil(t, err)
@ -793,7 +825,7 @@ func TestAccountsByPubKey(t *testing.T) {
tests := []struct {
name string
pubKeys [][]byte
pubKeys []spec.BLSPubKey
accounts int
}{
{
@ -802,38 +834,38 @@ func TestAccountsByPubKey(t *testing.T) {
},
{
name: "Empty",
pubKeys: [][]byte{
_byte(""),
pubKeys: []spec.BLSPubKey{
{},
},
accounts: 0,
},
{
name: "All",
pubKeys: [][]byte{
_byte("0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c"),
_byte("0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b"),
_byte("0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b"),
_byte("0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e"),
_byte("0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e"),
_byte("0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34"),
_byte("0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373"),
_byte("0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac"),
_byte("0xa6d310dbbfab9a22450f59993f87a4ce5db6223f3b5f1f30d2c4ec718922d400e0b3c7741de8e59960f72411a0ee10a7"),
_byte("0x9893413c00283a3f9ed9fd9845dda1cea38228d22567f9541dccc357e54a2d6a6e204103c92564cbc05f4905ac7c493a"),
_byte("0x876dd4705157eb66dc71bc2e07fb151ea53e1a62a0bb980a7ce72d15f58944a8a3752d754f52f4a60dbfc7b18169f268"),
_byte("0xaec922bd7a9b7b1dc21993133b586b0c3041c1e2e04b513e862227b9d7aecaf9444222f7e78282a449622ffc6278915d"),
_byte("0x9314c6de0386635e2799af798884c2ea09c63b9f079e572acc00b06a7faccce501ea4dfc0b1a23b8603680a5e3481327"),
_byte("0x903e2989e7442ee0a8958d020507a8bd985d3974f5e8273093be00db3935f0500e141b252bd09e3728892c7a8443863c"),
_byte("0x84398f539a64cbe01cfcd8c485ea51cd6657b94df93ee9b5dc61e1f18f69da6ca9d4dba63c956a81c68d5d4d4277a60f"),
_byte("0x872c61b4a7f8510ec809e5b023f5fdda2105d024c470ddbbeca4bc74e8280af0d178d749853e8f6a841083ac1b4db98f"),
pubKeys: []spec.BLSPubKey{
testutil.HexToPubKey("0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c"),
testutil.HexToPubKey("0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b"),
testutil.HexToPubKey("0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b"),
testutil.HexToPubKey("0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e"),
testutil.HexToPubKey("0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e"),
testutil.HexToPubKey("0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34"),
testutil.HexToPubKey("0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373"),
testutil.HexToPubKey("0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac"),
testutil.HexToPubKey("0xa6d310dbbfab9a22450f59993f87a4ce5db6223f3b5f1f30d2c4ec718922d400e0b3c7741de8e59960f72411a0ee10a7"),
testutil.HexToPubKey("0x9893413c00283a3f9ed9fd9845dda1cea38228d22567f9541dccc357e54a2d6a6e204103c92564cbc05f4905ac7c493a"),
testutil.HexToPubKey("0x876dd4705157eb66dc71bc2e07fb151ea53e1a62a0bb980a7ce72d15f58944a8a3752d754f52f4a60dbfc7b18169f268"),
testutil.HexToPubKey("0xaec922bd7a9b7b1dc21993133b586b0c3041c1e2e04b513e862227b9d7aecaf9444222f7e78282a449622ffc6278915d"),
testutil.HexToPubKey("0x9314c6de0386635e2799af798884c2ea09c63b9f079e572acc00b06a7faccce501ea4dfc0b1a23b8603680a5e3481327"),
testutil.HexToPubKey("0x903e2989e7442ee0a8958d020507a8bd985d3974f5e8273093be00db3935f0500e141b252bd09e3728892c7a8443863c"),
testutil.HexToPubKey("0x84398f539a64cbe01cfcd8c485ea51cd6657b94df93ee9b5dc61e1f18f69da6ca9d4dba63c956a81c68d5d4d4277a60f"),
testutil.HexToPubKey("0x872c61b4a7f8510ec809e5b023f5fdda2105d024c470ddbbeca4bc74e8280af0d178d749853e8f6a841083ac1b4db98f"),
},
accounts: 16,
},
{
name: "Missing",
pubKeys: [][]byte{
_byte("0x872c61b4a7f8510ec809e5b023f5fdda2105d024c470ddbbeca4bc74e8280af0d178d749853e8f6a841083ac1b4db98f"),
_byte("0x8f467e5723deac7659e1ca273e28410cbaa6d495ab66ae77014f4cd21c64b6b5ab9987c9b5537fe0279bd063fe609be7"),
pubKeys: []spec.BLSPubKey{
testutil.HexToPubKey("0x872c61b4a7f8510ec809e5b023f5fdda2105d024c470ddbbeca4bc74e8280af0d178d749853e8f6a841083ac1b4db98f"),
testutil.HexToPubKey("0x8f467e5723deac7659e1ca273e28410cbaa6d495ab66ae77014f4cd21c64b6b5ab9987c9b5537fe0279bd063fe609be7"),
},
accounts: 1,
},
@ -857,7 +889,7 @@ func TestAccountsByPubKey(t *testing.T) {
dirk.WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
dirk.WithDomainProvider(mock.NewDomainProvider()),
)
require.Nil(t, err)

View File

@ -19,30 +19,33 @@ import (
eth2client "github.com/attestantio/go-eth2-client"
api "github.com/attestantio/go-eth2-client/api/v1"
"github.com/opentracing/opentracing-go"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/pkg/errors"
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
)
// ValidatingAccount is a wrapper around the dirk account that implements ValidatingAccount.
type ValidatingAccount struct {
account e2wtypes.Account
index uint64
state api.ValidatorState
accountManager *Service
signatureDomainProvider eth2client.SignatureDomainProvider
account e2wtypes.Account
index spec.ValidatorIndex
state api.ValidatorState
accountManager *Service
domainProvider eth2client.DomainProvider
}
// PubKey returns the public key of the validating account.
func (d *ValidatingAccount) PubKey(ctx context.Context) ([]byte, error) {
func (d *ValidatingAccount) PubKey(ctx context.Context) (spec.BLSPubKey, error) {
var pubKey spec.BLSPubKey
if provider, isProvider := d.account.(e2wtypes.AccountCompositePublicKeyProvider); isProvider {
return provider.CompositePublicKey().Marshal(), nil
copy(pubKey[:], provider.CompositePublicKey().Marshal())
} else {
copy(pubKey[:], d.account.PublicKey().Marshal())
}
return d.account.PublicKey().Marshal(), nil
return pubKey, nil
}
// Index returns the index of the validating account.
func (d *ValidatingAccount) Index(ctx context.Context) (uint64, error) {
func (d *ValidatingAccount) Index(ctx context.Context) (spec.ValidatorIndex, error) {
return d.index, nil
}
@ -53,133 +56,142 @@ func (d *ValidatingAccount) State() api.ValidatorState {
// SignSlotSelection returns a slot selection signature.
// This signs a slot with the "selection proof" domain.
func (d *ValidatingAccount) SignSlotSelection(ctx context.Context, slot uint64) ([]byte, error) {
span, ctx := opentracing.StartSpanFromContext(ctx, "dirk.SignSlotSelection")
defer span.Finish()
func (d *ValidatingAccount) SignSlotSelection(ctx context.Context, slot spec.Slot) (spec.BLSSignature, error) {
var messageRoot spec.Root
binary.LittleEndian.PutUint64(messageRoot[:], uint64(slot))
// Calculate the signature domain.
signatureDomain, err := d.signatureDomainProvider.SignatureDomain(ctx,
d.accountManager.selectionProofDomain,
slot/d.accountManager.slotsPerEpoch)
// Calculate the domain.
domain, err := d.domainProvider.Domain(ctx,
d.accountManager.selectionProofDomainType,
spec.Epoch(slot/d.accountManager.slotsPerEpoch))
if err != nil {
return nil, errors.Wrap(err, "failed to obtain signature domain for selection proof")
return spec.BLSSignature{}, errors.Wrap(err, "failed to obtain signature domain for selection proof")
}
slotBytes := make([]byte, 32)
binary.LittleEndian.PutUint64(slotBytes, slot)
binary.LittleEndian.PutUint64(slotBytes, uint64(slot))
sig, err := d.account.(e2wtypes.AccountProtectingSigner).SignGeneric(ctx, slotBytes, signatureDomain)
sig, err := d.account.(e2wtypes.AccountProtectingSigner).SignGeneric(ctx, slotBytes, domain[:])
if err != nil {
return nil, errors.Wrap(err, "failed to sign slot")
return spec.BLSSignature{}, errors.Wrap(err, "failed to sign slot")
}
return sig.Marshal(), nil
var signature spec.BLSSignature
copy(signature[:], sig.Marshal())
return signature, nil
}
// SignRANDAOReveal returns a RANDAO reveal signature.
// This signs an epoch with the "RANDAO reveal" domain.
// N.B. This passes in a slot, not an epoch.
func (d *ValidatingAccount) SignRANDAOReveal(ctx context.Context, slot uint64) ([]byte, error) {
span, ctx := opentracing.StartSpanFromContext(ctx, "dirk.SignRANDAOReveal")
defer span.Finish()
func (d *ValidatingAccount) SignRANDAOReveal(ctx context.Context, slot spec.Slot) (spec.BLSSignature, error) {
var messageRoot spec.Root
epoch := spec.Epoch(slot / d.accountManager.slotsPerEpoch)
binary.LittleEndian.PutUint64(messageRoot[:], uint64(epoch))
epoch := slot / d.accountManager.slotsPerEpoch
// Obtain the RANDAO reveal signature domain.
signatureDomain, err := d.signatureDomainProvider.SignatureDomain(ctx,
d.accountManager.randaoDomain,
domain, err := d.domainProvider.Domain(ctx,
d.accountManager.randaoDomainType,
epoch)
if err != nil {
return nil, errors.Wrap(err, "failed to obtain signature domain for RANDAO reveal")
return spec.BLSSignature{}, errors.Wrap(err, "failed to obtain signature domain for RANDAO reveal")
}
epochBytes := make([]byte, 32)
binary.LittleEndian.PutUint64(epochBytes, epoch)
binary.LittleEndian.PutUint64(epochBytes, uint64(epoch))
sig, err := d.account.(e2wtypes.AccountProtectingSigner).SignGeneric(ctx, epochBytes, signatureDomain)
sig, err := d.account.(e2wtypes.AccountProtectingSigner).SignGeneric(ctx, epochBytes, domain[:])
if err != nil {
return nil, errors.Wrap(err, "failed to sign RANDO reveal")
return spec.BLSSignature{}, errors.Wrap(err, "failed to sign RANDO reveal")
}
return sig.Marshal(), nil
var signature spec.BLSSignature
copy(signature[:], sig.Marshal())
return signature, nil
}
// SignBeaconBlockProposal signs a beacon block proposal item.
func (d *ValidatingAccount) SignBeaconBlockProposal(ctx context.Context,
slot uint64,
proposerIndex uint64,
parentRoot []byte,
stateRoot []byte,
bodyRoot []byte) ([]byte, error) {
slot spec.Slot,
proposerIndex spec.ValidatorIndex,
parentRoot spec.Root,
stateRoot spec.Root,
bodyRoot spec.Root) (spec.BLSSignature, error) {
// Fetch the signature domain.
signatureDomain, err := d.signatureDomainProvider.SignatureDomain(ctx,
d.accountManager.beaconProposerDomain,
slot/d.accountManager.slotsPerEpoch)
// Fetch the domain.
domain, err := d.domainProvider.Domain(ctx,
d.accountManager.beaconProposerDomainType,
spec.Epoch(slot/d.accountManager.slotsPerEpoch))
if err != nil {
return nil, errors.Wrap(err, "failed to obtain signature domain for beacon proposal")
return spec.BLSSignature{}, errors.Wrap(err, "failed to obtain signature domain for beacon proposal")
}
sig, err := d.account.(e2wtypes.AccountProtectingSigner).SignBeaconProposal(ctx,
slot,
proposerIndex,
parentRoot,
stateRoot,
bodyRoot,
signatureDomain)
uint64(slot),
uint64(proposerIndex),
parentRoot[:],
stateRoot[:],
bodyRoot[:],
domain[:])
if err != nil {
return nil, errors.Wrap(err, "failed to sign beacon block proposal")
return spec.BLSSignature{}, errors.Wrap(err, "failed to sign beacon block proposal")
}
return sig.Marshal(), nil
var signature spec.BLSSignature
copy(signature[:], sig.Marshal())
return signature, nil
}
// SignBeaconAttestation signs a beacon attestation item.
func (d *ValidatingAccount) SignBeaconAttestation(ctx context.Context,
slot uint64,
committeeIndex uint64,
blockRoot []byte,
sourceEpoch uint64,
sourceRoot []byte,
targetEpoch uint64,
targetRoot []byte) ([]byte, error) {
span, ctx := opentracing.StartSpanFromContext(ctx, "dirk.SignBeaconAttestation")
defer span.Finish()
slot spec.Slot,
committeeIndex spec.CommitteeIndex,
blockRoot spec.Root,
sourceEpoch spec.Epoch,
sourceRoot spec.Root,
targetEpoch spec.Epoch,
targetRoot spec.Root) (spec.BLSSignature, error) {
signatureDomain, err := d.signatureDomainProvider.SignatureDomain(ctx,
d.accountManager.beaconAttesterDomain,
slot/d.accountManager.slotsPerEpoch)
domain, err := d.domainProvider.Domain(ctx,
d.accountManager.beaconAttesterDomainType,
spec.Epoch(slot/d.accountManager.slotsPerEpoch))
if err != nil {
return nil, errors.Wrap(err, "failed to obtain signature domain for beacon attestation")
return spec.BLSSignature{}, errors.Wrap(err, "failed to obtain signature domain for beacon attestation")
}
sig, err := d.account.(e2wtypes.AccountProtectingSigner).SignBeaconAttestation(ctx,
slot,
committeeIndex,
blockRoot,
sourceEpoch,
sourceRoot,
targetEpoch,
targetRoot,
signatureDomain)
uint64(slot),
uint64(committeeIndex),
blockRoot[:],
uint64(sourceEpoch),
sourceRoot[:],
uint64(targetEpoch),
targetRoot[:],
domain[:])
if err != nil {
return nil, errors.Wrap(err, "failed to sign beacon attestation")
return spec.BLSSignature{}, errors.Wrap(err, "failed to sign beacon attestation")
}
return sig.Marshal(), nil
var signature spec.BLSSignature
copy(signature[:], sig.Marshal())
return signature, nil
}
// SignAggregateAndProof signs an aggregate and proof item.
func (d *ValidatingAccount) SignAggregateAndProof(ctx context.Context, slot uint64, aggregateAndProofRoot []byte) ([]byte, error) {
span, ctx := opentracing.StartSpanFromContext(ctx, "dirk.SignAggregateAndProof")
defer span.Finish()
// Fetch the signature domain.
signatureDomain, err := d.signatureDomainProvider.SignatureDomain(ctx,
d.accountManager.aggregateAndProofDomain,
slot)
func (d *ValidatingAccount) SignAggregateAndProof(ctx context.Context, slot spec.Slot, aggregateAndProofRoot spec.Root) (spec.BLSSignature, error) {
// Fetch the domain.
domain, err := d.domainProvider.Domain(ctx,
d.accountManager.aggregateAndProofDomainType,
spec.Epoch(slot/d.accountManager.slotsPerEpoch))
if err != nil {
return nil, errors.Wrap(err, "failed to obtain signature domain for beacon aggregate and proof")
return spec.BLSSignature{}, errors.Wrap(err, "failed to obtain signature domain for beacon aggregate and proof")
}
sig, err := d.account.(e2wtypes.AccountProtectingSigner).SignGeneric(ctx, aggregateAndProofRoot, signatureDomain)
sig, err := d.account.(e2wtypes.AccountProtectingSigner).SignGeneric(ctx, aggregateAndProofRoot[:], domain[:])
if err != nil {
return nil, errors.Wrap(err, "failed to aggregate and proof")
return spec.BLSSignature{}, errors.Wrap(err, "failed to aggregate and proof")
}
return sig.Marshal(), nil
var signature spec.BLSSignature
copy(signature[:], sig.Marshal())
return signature, nil
}

View File

@ -22,6 +22,7 @@ import (
"github.com/attestantio/dirk/testing/daemon"
api "github.com/attestantio/go-eth2-client/api/v1"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/attestantio/vouch/mock"
"github.com/attestantio/vouch/services/accountmanager"
"github.com/attestantio/vouch/services/accountmanager/dirk"
@ -57,30 +58,30 @@ func TestPubKey(t *testing.T) {
dirk.WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
dirk.WithDomainProvider(mock.NewDomainProvider()),
)
require.Nil(t, err)
tests := []struct {
name string
index uint64
expected []byte
index spec.ValidatorIndex
expected spec.BLSPubKey
}{
{
name: "0",
index: 0,
expected: _byte("0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c"),
expected: _pubKey("0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c"),
},
{
name: "1",
index: 1,
expected: _byte("0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b"),
expected: _pubKey("0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b"),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
accounts, err := s.AccountsByIndex(ctx, []uint64{test.index})
accounts, err := s.AccountsByIndex(ctx, []spec.ValidatorIndex{test.index})
require.NoError(t, err)
require.Equal(t, 1, len(accounts))
account := accounts[0]
@ -120,13 +121,13 @@ func TestState(t *testing.T) {
dirk.WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
dirk.WithDomainProvider(mock.NewDomainProvider()),
)
require.Nil(t, err)
tests := []struct {
name string
index uint64
index spec.ValidatorIndex
expected api.ValidatorState
}{
{
@ -143,7 +144,7 @@ func TestState(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
accounts, err := s.AccountsByIndex(ctx, []uint64{test.index})
accounts, err := s.AccountsByIndex(ctx, []spec.ValidatorIndex{test.index})
require.NoError(t, err)
require.Equal(t, 1, len(accounts))
account := accounts[0]
@ -182,30 +183,30 @@ func TestSignSlotSelection(t *testing.T) {
dirk.WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
dirk.WithDomainProvider(mock.NewDomainProvider()),
)
require.Nil(t, err)
tests := []struct {
name string
index uint64
expected []byte
index spec.ValidatorIndex
expected spec.BLSSignature
}{
{
name: "0",
index: 0,
expected: _byte("0xa207bbed7d1e43585e5d42e3f09a5179f21a12a33b66ac9af47132c20f9b7b7caaa162420e095664ca3318fe365776e80bd0f9ef1e3b07a2e5340d0c07152234bf18f7596c8d94d72e11961ad8455f08c4417b0019246e24f570a166f86de2c5"),
expected: _sig("0xa207bbed7d1e43585e5d42e3f09a5179f21a12a33b66ac9af47132c20f9b7b7caaa162420e095664ca3318fe365776e80bd0f9ef1e3b07a2e5340d0c07152234bf18f7596c8d94d72e11961ad8455f08c4417b0019246e24f570a166f86de2c5"),
},
{
name: "1",
index: 1,
expected: _byte("0xa17b1a6decb1503b5b8eacb4ca48e2f1665e43c587088995bb7e2da0738268ad0e1f28519ed79fbb318b9b98c6e8b65805a005bca4c98656fefb9ec6753df29ad6ef92da5e3074c027caaaf738d37fd09e08d8d8f86531bd80cf4152709240f9"),
expected: _sig("0xa17b1a6decb1503b5b8eacb4ca48e2f1665e43c587088995bb7e2da0738268ad0e1f28519ed79fbb318b9b98c6e8b65805a005bca4c98656fefb9ec6753df29ad6ef92da5e3074c027caaaf738d37fd09e08d8d8f86531bd80cf4152709240f9"),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
accounts, err := s.AccountsByIndex(ctx, []uint64{test.index})
accounts, err := s.AccountsByIndex(ctx, []spec.ValidatorIndex{test.index})
require.NoError(t, err)
require.Equal(t, 1, len(accounts))
account := accounts[0]
@ -245,30 +246,30 @@ func TestSignRANDAOReveal(t *testing.T) {
dirk.WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
dirk.WithDomainProvider(mock.NewDomainProvider()),
)
require.Nil(t, err)
tests := []struct {
name string
index uint64
expected []byte
index spec.ValidatorIndex
expected spec.BLSSignature
}{
{
name: "0",
index: 0,
expected: _byte("0xb990eeca35dadda689f5561ac39bba9a27a0c41c40bd1ce584595ba2a44782a89e2630ced7b1fc348b2408d15fa6746c177c5227625e39031e6be1536387ae33e21ec3de6d1d0b46bada1b99b621f8d40eab81882400c028716b22d31999b177"),
expected: _sig("0xb990eeca35dadda689f5561ac39bba9a27a0c41c40bd1ce584595ba2a44782a89e2630ced7b1fc348b2408d15fa6746c177c5227625e39031e6be1536387ae33e21ec3de6d1d0b46bada1b99b621f8d40eab81882400c028716b22d31999b177"),
},
{
name: "1",
index: 1,
expected: _byte("0x840c144974632f09084b91ec7be5044c3fe9dd0dc7ce1031c0c78911807e264f36cb4fee0ddccf0ca93bada5d102cfb7118e6b75b5ecc5e18648a29f21f70727f3587b8d34bc7474d926fab4fb30eae4436153c336e6eb290d3d1cdd88ee9a58"),
expected: _sig("0x840c144974632f09084b91ec7be5044c3fe9dd0dc7ce1031c0c78911807e264f36cb4fee0ddccf0ca93bada5d102cfb7118e6b75b5ecc5e18648a29f21f70727f3587b8d34bc7474d926fab4fb30eae4436153c336e6eb290d3d1cdd88ee9a58"),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
accounts, err := s.AccountsByIndex(ctx, []uint64{test.index})
accounts, err := s.AccountsByIndex(ctx, []spec.ValidatorIndex{test.index})
require.NoError(t, err)
require.Equal(t, 1, len(accounts))
account := accounts[0]
@ -308,30 +309,30 @@ func TestSignBeaconBlockProposal(t *testing.T) {
dirk.WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
dirk.WithDomainProvider(mock.NewDomainProvider()),
)
require.Nil(t, err)
tests := []struct {
name string
index uint64
expected []byte
index spec.ValidatorIndex
expected spec.BLSSignature
}{
{
name: "0",
index: 0,
expected: _byte("0x83d91f4fe6dd962493f212a94dc62c81358ffbdb6c3f8567d96fbe31c5ab505db1a3d37b8c3d653225621bb34918d30b069bbc02daeea9e1b2e62166014563f271fdfbe9aad37f0d155754f63eb368dd853c0bf723ad64af371a04b7778e891a"),
expected: _sig("0x83d91f4fe6dd962493f212a94dc62c81358ffbdb6c3f8567d96fbe31c5ab505db1a3d37b8c3d653225621bb34918d30b069bbc02daeea9e1b2e62166014563f271fdfbe9aad37f0d155754f63eb368dd853c0bf723ad64af371a04b7778e891a"),
},
{
name: "1",
index: 1,
expected: _byte("0x9176ac06d426beb74bfb3969a619d364a5e214f0da511433b56f8dca47b93725c4ddd225c1cb81dd5a26fc321801a1d70b1c28c6cf705c010fadf9c4f139c044224680d8c60e425c9d6e6b8e8af21f12cffab38b393a9b7529527b92cf20e80a"),
expected: _sig("0x9176ac06d426beb74bfb3969a619d364a5e214f0da511433b56f8dca47b93725c4ddd225c1cb81dd5a26fc321801a1d70b1c28c6cf705c010fadf9c4f139c044224680d8c60e425c9d6e6b8e8af21f12cffab38b393a9b7529527b92cf20e80a"),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
accounts, err := s.AccountsByIndex(ctx, []uint64{test.index})
accounts, err := s.AccountsByIndex(ctx, []spec.ValidatorIndex{test.index})
require.NoError(t, err)
require.Equal(t, 1, len(accounts))
account := accounts[0]
@ -341,9 +342,9 @@ func TestSignBeaconBlockProposal(t *testing.T) {
res, err := signer.SignBeaconBlockProposal(ctx,
1,
1,
_byte("0x0000000000000000000000000000000000000000000000000000000000000000"),
_byte("0x0000000000000000000000000000000000000000000000000000000000000000"),
_byte("0x0000000000000000000000000000000000000000000000000000000000000000"),
_root("0x0000000000000000000000000000000000000000000000000000000000000000"),
_root("0x0000000000000000000000000000000000000000000000000000000000000000"),
_root("0x0000000000000000000000000000000000000000000000000000000000000000"),
)
require.NoError(t, err)
require.Equal(t, test.expected, res)
@ -377,30 +378,30 @@ func TestBeaconAttestationsSigner(t *testing.T) {
dirk.WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
dirk.WithDomainProvider(mock.NewDomainProvider()),
)
require.Nil(t, err)
tests := []struct {
name string
index uint64
expected []byte
index spec.ValidatorIndex
expected spec.BLSSignature
}{
{
name: "0",
index: 0,
expected: _byte("0x974fb6782c196c8e523b74ea3dbdfe7b122c6a18590992f2cb789358dcea6c28498ffa6cac68629bf83175cb55bb0d3910919eab48d2934c3a81655dcc27c91a996ca4a9880ffde7864f6aba3cd7c40111e3317c817032776d077d8d6a348bb2"),
expected: _sig("0x974fb6782c196c8e523b74ea3dbdfe7b122c6a18590992f2cb789358dcea6c28498ffa6cac68629bf83175cb55bb0d3910919eab48d2934c3a81655dcc27c91a996ca4a9880ffde7864f6aba3cd7c40111e3317c817032776d077d8d6a348bb2"),
},
{
name: "1",
index: 1,
expected: _byte("0x84a1c3c50d093901ea1b027b18598e4b9cf0f848f6bd49f2807a3f6ea37c0cbf3794556705863de0ae8ea7dd2da4d4d91436e2ca96fa1eb045a22fb7704cedf8a842fa881a416eaa02444454d9f7f8040b84fc3cd3d42817f6992c3c29e16007"),
expected: _sig("0x84a1c3c50d093901ea1b027b18598e4b9cf0f848f6bd49f2807a3f6ea37c0cbf3794556705863de0ae8ea7dd2da4d4d91436e2ca96fa1eb045a22fb7704cedf8a842fa881a416eaa02444454d9f7f8040b84fc3cd3d42817f6992c3c29e16007"),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
accounts, err := s.AccountsByIndex(ctx, []uint64{test.index})
accounts, err := s.AccountsByIndex(ctx, []spec.ValidatorIndex{test.index})
require.NoError(t, err)
require.Equal(t, 1, len(accounts))
account := accounts[0]
@ -410,11 +411,11 @@ func TestBeaconAttestationsSigner(t *testing.T) {
res, err := signer.SignBeaconAttestation(ctx,
1,
1,
_byte("0x0000000000000000000000000000000000000000000000000000000000000000"),
_root("0x0000000000000000000000000000000000000000000000000000000000000000"),
0,
_byte("0x0000000000000000000000000000000000000000000000000000000000000000"),
_root("0x0000000000000000000000000000000000000000000000000000000000000000"),
1,
_byte("0x0000000000000000000000000000000000000000000000000000000000000000"),
_root("0x0000000000000000000000000000000000000000000000000000000000000000"),
)
require.NoError(t, err)
require.Equal(t, test.expected, res)
@ -448,30 +449,30 @@ func TestAggregateAndProofsigner(t *testing.T) {
dirk.WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
dirk.WithDomainProvider(mock.NewDomainProvider()),
)
require.Nil(t, err)
tests := []struct {
name string
index uint64
expected []byte
index spec.ValidatorIndex
expected spec.BLSSignature
}{
{
name: "0",
index: 0,
expected: _byte("0xafd6b2ed80506b63e964820aba6523735d6156d4f2e3d53c88075f22b2a48447d6f083952e7d6c315a96dfde35b6959616591ac9d8b2d7f1c423b7f257e6f5eb4406b97b55270a9101cca809e76c7759aaf1235b028aa23da118697dfb9c34c5"),
expected: _sig("0xafd6b2ed80506b63e964820aba6523735d6156d4f2e3d53c88075f22b2a48447d6f083952e7d6c315a96dfde35b6959616591ac9d8b2d7f1c423b7f257e6f5eb4406b97b55270a9101cca809e76c7759aaf1235b028aa23da118697dfb9c34c5"),
},
{
name: "1",
index: 1,
expected: _byte("0xa006085be92bb0ee2cf2bba3da0d5e21630efb7e32a5e4fa7ca742ea0bd273f76a6336ef3a9817200bddbc0b4a6dbecf1303d9804806fa38ee05b7d5cfbba6e851c37ca587d66df935c296e6210db69f8b4c96f5e590cb83c7f82c06aee1d4c3"),
expected: _sig("0xa006085be92bb0ee2cf2bba3da0d5e21630efb7e32a5e4fa7ca742ea0bd273f76a6336ef3a9817200bddbc0b4a6dbecf1303d9804806fa38ee05b7d5cfbba6e851c37ca587d66df935c296e6210db69f8b4c96f5e590cb83c7f82c06aee1d4c3"),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
accounts, err := s.AccountsByIndex(ctx, []uint64{test.index})
accounts, err := s.AccountsByIndex(ctx, []spec.ValidatorIndex{test.index})
require.NoError(t, err)
require.Equal(t, 1, len(accounts))
account := accounts[0]
@ -480,7 +481,7 @@ func TestAggregateAndProofsigner(t *testing.T) {
require.True(t, isSigner)
res, err := signer.SignAggregateAndProof(ctx,
1,
_byte("0x0000000000000000000000000000000000000000000000000000000000000000"),
_root("0x0000000000000000000000000000000000000000000000000000000000000000"),
)
require.NoError(t, err)
require.Equal(t, test.expected, res)

View File

@ -18,6 +18,7 @@ import (
"context"
api "github.com/attestantio/go-eth2-client/api/v1"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
)
// Service is the generic accountmanager service.
@ -29,23 +30,23 @@ type ValidatingAccountsProvider interface {
Accounts(ctx context.Context) ([]ValidatingAccount, error)
// AccountsByIndex provides information about the specific accounts that are configured to validate through this instance.
AccountsByIndex(ctx context.Context, indices []uint64) ([]ValidatingAccount, error)
AccountsByIndex(ctx context.Context, indices []spec.ValidatorIndex) ([]ValidatingAccount, error)
// AccountsByPubKey provides information about the specific accounts that are configured to validate through this instance.
AccountsByPubKey(ctx context.Context, pubKeys [][]byte) ([]ValidatingAccount, error)
AccountsByPubKey(ctx context.Context, pubKeys []spec.BLSPubKey) ([]ValidatingAccount, error)
}
// ValidatingAccountPubKeyProvider provides methods for obtaining public keys from accounts.
type ValidatingAccountPubKeyProvider interface {
// PubKey() provides the public key for this account.
PubKey(ctx context.Context) ([]byte, error)
PubKey(ctx context.Context) (spec.BLSPubKey, error)
}
// ValidatingAccountIndexProvider provides methods for obtaining indices from accounts.
type ValidatingAccountIndexProvider interface {
// Index() provides the validator index for this account.
// Returns an error if there is no index for this validator.
Index(ctx context.Context) (uint64, error)
Index(ctx context.Context) (spec.ValidatorIndex, error)
}
// ValidatingAccountStateProvider provides methods for obtaining state from accounts.
@ -81,45 +82,44 @@ type IsAggregatorProvider interface {
type RANDAORevealSigner interface {
// SignRANDAOReveal returns a RANDAO signature.
// This signs an epoch with the "RANDAO" domain.
// N.B. This passes in a slot, not an epoch.
SignRANDAOReveal(ctx context.Context, slot uint64) ([]byte, error)
SignRANDAOReveal(ctx context.Context, slot spec.Slot) (spec.BLSSignature, error)
}
// SlotSelectionSigner provides methods to sign slot selections.
type SlotSelectionSigner interface {
// SignSlotSelection returns a slot selection signature.
// This signs a slot with the "selection proof" domain.
SignSlotSelection(ctx context.Context, slot uint64) ([]byte, error)
SignSlotSelection(ctx context.Context, slot spec.Slot) (spec.BLSSignature, error)
}
// BeaconBlockSigner provides methods to sign beacon blocks.
type BeaconBlockSigner interface {
// SignBeaconBlockProposal signs a beacon block proposal.
SignBeaconBlockProposal(ctx context.Context,
slot uint64,
proposerIndex uint64,
parentRoot []byte,
stateRoot []byte,
bodyRoot []byte) ([]byte, error)
slot spec.Slot,
proposerIndex spec.ValidatorIndex,
parentRoot spec.Root,
stateRoot spec.Root,
bodyRoot spec.Root) (spec.BLSSignature, error)
}
// BeaconAttestationSigner provides methods to sign beacon attestations.
type BeaconAttestationSigner interface {
// SignBeaconAttestation signs a beacon attestation.
SignBeaconAttestation(ctx context.Context,
slot uint64,
committeeIndex uint64,
blockRoot []byte,
sourceEpoch uint64,
sourceRoot []byte,
targetEpoch uint64,
targetRoot []byte) ([]byte, error)
slot spec.Slot,
committeeIndex spec.CommitteeIndex,
blockRoot spec.Root,
sourceEpoch spec.Epoch,
sourceRoot spec.Root,
targetEpoch spec.Epoch,
targetRoot spec.Root) (spec.BLSSignature, error)
}
// AggregateAndProofSigner provides methods to sign aggregate and proofs.
type AggregateAndProofSigner interface {
// SignAggregateAndProof signs an aggregate attestation for given slot and root.
SignAggregateAndProof(ctx context.Context, slot uint64, root []byte) ([]byte, error)
SignAggregateAndProof(ctx context.Context, slot spec.Slot, root spec.Root) (spec.BLSSignature, error)
}
// Signer is a composite interface for all signer operations.

View File

@ -1,17 +0,0 @@
// Copyright © 2020 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 wallet
// Need to `go get github.com/ferranbt/fastssz/sszgen` for this to work.
//go:generate sszgen --path . --objs SigningContainer

View File

@ -33,7 +33,7 @@ type parameters struct {
randaoDomainProvider eth2client.RANDAODomainProvider
selectionProofDomainProvider eth2client.SelectionProofDomainProvider
aggregateAndProofDomainProvider eth2client.AggregateAndProofDomainProvider
signatureDomainProvider eth2client.SignatureDomainProvider
domainProvider eth2client.DomainProvider
}
// Parameter is the interface for service parameters.
@ -131,10 +131,10 @@ func WithAggregateAndProofDomainProvider(provider eth2client.AggregateAndProofDo
})
}
// WithSignatureDomainProvider sets the signature domain provider.
func WithSignatureDomainProvider(provider eth2client.SignatureDomainProvider) Parameter {
// WithDomainProvider sets the domain provider.
func WithDomainProvider(provider eth2client.DomainProvider) Parameter {
return parameterFunc(func(p *parameters) {
p.signatureDomainProvider = provider
p.domainProvider = provider
})
}
@ -179,8 +179,8 @@ func parseAndCheckParameters(params ...Parameter) (*parameters, error) {
if parameters.aggregateAndProofDomainProvider == nil {
return nil, errors.New("no aggregate and proof domain provider specified")
}
if parameters.signatureDomainProvider == nil {
return nil, errors.New("no signature domain provider specified")
if parameters.domainProvider == nil {
return nil, errors.New("no domain provider specified")
}
return &parameters, nil

View File

@ -22,6 +22,7 @@ import (
eth2client "github.com/attestantio/go-eth2-client"
api "github.com/attestantio/go-eth2-client/api/v1"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/attestantio/vouch/services/accountmanager"
"github.com/attestantio/vouch/services/metrics"
"github.com/pkg/errors"
@ -40,15 +41,15 @@ type Service struct {
stores []e2wtypes.Store
accountPaths []string
passphrases [][]byte
accounts map[[48]byte]*ValidatingAccount
accounts map[spec.BLSPubKey]*ValidatingAccount
validatorsProvider eth2client.ValidatorsProvider
slotsPerEpoch uint64
beaconProposerDomain []byte
beaconAttesterDomain []byte
randaoDomain []byte
selectionProofDomain []byte
aggregateAndProofDomain []byte
signatureDomainProvider eth2client.SignatureDomainProvider
slotsPerEpoch spec.Slot
beaconProposerDomain spec.DomainType
beaconAttesterDomain spec.DomainType
randaoDomain spec.DomainType
selectionProofDomain spec.DomainType
aggregateAndProofDomain spec.DomainType
domainProvider eth2client.DomainProvider
}
// module-wide log.
@ -81,23 +82,23 @@ func New(ctx context.Context, params ...Parameter) (*Service, error) {
if err != nil {
return nil, errors.Wrap(err, "failed to obtain slots per epoch")
}
beaconAttesterDomain, err := parameters.beaconAttesterDomainProvider.BeaconAttesterDomain(ctx)
beaconAttesterDomainType, err := parameters.beaconAttesterDomainProvider.BeaconAttesterDomain(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to obtain beacon attester domain")
}
beaconProposerDomain, err := parameters.beaconProposerDomainProvider.BeaconProposerDomain(ctx)
beaconProposerDomainType, err := parameters.beaconProposerDomainProvider.BeaconProposerDomain(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to obtain beacon proposer domain")
}
randaoDomain, err := parameters.randaoDomainProvider.RANDAODomain(ctx)
randaoDomainType, err := parameters.randaoDomainProvider.RANDAODomain(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to obtain RANDAO domain")
}
selectionProofDomain, err := parameters.selectionProofDomainProvider.SelectionProofDomain(ctx)
selectionProofDomainType, err := parameters.selectionProofDomainProvider.SelectionProofDomain(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to obtain selection proof domain")
}
aggregateAndProofDomain, err := parameters.aggregateAndProofDomainProvider.AggregateAndProofDomain(ctx)
aggregateAndProofDomainType, err := parameters.aggregateAndProofDomainProvider.AggregateAndProofDomain(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to obtain aggregate and proof domain")
}
@ -107,13 +108,13 @@ func New(ctx context.Context, params ...Parameter) (*Service, error) {
accountPaths: parameters.accountPaths,
passphrases: parameters.passphrases,
validatorsProvider: parameters.validatorsProvider,
slotsPerEpoch: slotsPerEpoch,
beaconAttesterDomain: beaconAttesterDomain,
beaconProposerDomain: beaconProposerDomain,
randaoDomain: randaoDomain,
selectionProofDomain: selectionProofDomain,
aggregateAndProofDomain: aggregateAndProofDomain,
signatureDomainProvider: parameters.signatureDomainProvider,
slotsPerEpoch: spec.Slot(slotsPerEpoch),
beaconAttesterDomain: beaconAttesterDomainType,
beaconProposerDomain: beaconProposerDomainType,
randaoDomain: randaoDomainType,
selectionProofDomain: selectionProofDomainType,
aggregateAndProofDomain: aggregateAndProofDomainType,
domainProvider: parameters.domainProvider,
}
if err := s.RefreshAccounts(ctx); err != nil {
@ -126,18 +127,22 @@ func New(ctx context.Context, params ...Parameter) (*Service, error) {
// UpdateAccountsState updates account state with the latest information from the beacon chain.
// This should be run at the beginning of each epoch to ensure that any newly-activated accounts are registered.
func (s *Service) UpdateAccountsState(ctx context.Context) error {
validatorIDs := make([]eth2client.ValidatorIDProvider, 0, len(s.accounts))
validatorIndices := make([]spec.ValidatorIndex, 0, len(s.accounts))
for _, account := range s.accounts {
if !account.state.IsAttesting() {
validatorIDs = append(validatorIDs, account)
index, err := account.Index(ctx)
if err != nil {
return errors.Wrap(err, "failed to obtain account index")
}
validatorIndices = append(validatorIndices, index)
}
}
if len(validatorIDs) == 0 {
if len(validatorIndices) == 0 {
// Nothing to do.
log.Trace().Msg("No unactivated keys")
return nil
}
validators, err := s.validatorsProvider.Validators(ctx, "head", validatorIDs)
validators, err := s.validatorsProvider.Validators(ctx, "head", validatorIndices)
if err != nil {
return errors.Wrap(err, "failed to obtain validators")
}
@ -180,7 +185,7 @@ func (s *Service) RefreshAccounts(ctx context.Context) error {
verificationRegexes := accountPathsToVerificationRegexes(s.accountPaths)
// Fetch accounts for each wallet.
accounts := make(map[[48]byte]*ValidatingAccount)
accounts := make(map[spec.BLSPubKey]*ValidatingAccount)
for _, wallet := range wallets {
// if _, isProvider := wallet.(e2wtypes.WalletAccountsByPathProvider); isProvider {
// fmt.Printf("TODO: fetch accounts by path")
@ -189,22 +194,26 @@ func (s *Service) RefreshAccounts(ctx context.Context) error {
//}
}
validatorIDs := make([]eth2client.ValidatorIDProvider, 0, len(accounts))
// Update indices for accounts.
pubKeys := make([]spec.BLSPubKey, 0, len(accounts))
for _, account := range accounts {
if !account.state.IsAttesting() {
validatorIDs = append(validatorIDs, account)
pubKey, err := account.PubKey(ctx)
if err != nil {
return errors.Wrap(err, "failed to obtain public key")
}
pubKeys = append(pubKeys, pubKey)
}
validators, err := s.validatorsProvider.ValidatorsByPubKey(ctx, "head", pubKeys)
if err != nil {
return errors.Wrap(err, "failed to obtain validators")
}
log.Trace().Int("keys", len(accounts)).Msg("Keys obtained")
if len(validatorIDs) == 0 {
if len(pubKeys) == 0 {
log.Warn().Msg("No accounts obtained")
return nil
}
validators, err := s.validatorsProvider.Validators(ctx, "head", validatorIDs)
if err != nil {
return errors.Wrap(err, "failed to obtain validators")
}
s.updateAccountStates(ctx, accounts, validators)
s.mutex.Lock()
@ -230,9 +239,9 @@ func (s *Service) Accounts(ctx context.Context) ([]accountmanager.ValidatingAcco
}
// AccountsByIndex returns attesting accounts.
func (s *Service) AccountsByIndex(ctx context.Context, indices []uint64) ([]accountmanager.ValidatingAccount, error) {
indexMap := make(map[uint64]bool)
for _, index := range indices {
func (s *Service) AccountsByIndex(ctx context.Context, validatorIndices []spec.ValidatorIndex) ([]accountmanager.ValidatingAccount, error) {
indexMap := make(map[spec.ValidatorIndex]bool)
for _, index := range validatorIndices {
indexMap[index] = true
}
@ -246,7 +255,7 @@ func (s *Service) AccountsByIndex(ctx context.Context, indices []uint64) ([]acco
}
index, err := account.Index(ctx)
if err != nil {
log.Error().Err(err).Msg("No index for account")
log.Error().Err(err).Msg("Failed to obtain account index")
continue
}
if _, exists := indexMap[index]; exists {
@ -259,12 +268,10 @@ func (s *Service) AccountsByIndex(ctx context.Context, indices []uint64) ([]acco
}
// AccountsByPubKey returns validating accounts.
func (s *Service) AccountsByPubKey(ctx context.Context, pubKeys [][]byte) ([]accountmanager.ValidatingAccount, error) {
pubKeyMap := make(map[[48]byte]bool)
func (s *Service) AccountsByPubKey(ctx context.Context, pubKeys []spec.BLSPubKey) ([]accountmanager.ValidatingAccount, error) {
pubKeyMap := make(map[spec.BLSPubKey]bool)
for _, pubKey := range pubKeys {
var mapKey [48]byte
copy(mapKey[:], pubKey)
pubKeyMap[mapKey] = true
pubKeyMap[pubKey] = true
}
s.mutex.RLock()
@ -313,12 +320,10 @@ func accountPathsToVerificationRegexes(paths []string) []*regexp.Regexp {
return regexes
}
func (s *Service) updateAccountStates(ctx context.Context, accounts map[[48]byte]*ValidatingAccount, validators map[uint64]*api.Validator) {
validatorsByPubKey := make(map[[48]byte]*api.Validator, len(validators))
func (s *Service) updateAccountStates(ctx context.Context, accounts map[spec.BLSPubKey]*ValidatingAccount, validators map[spec.ValidatorIndex]*api.Validator) {
validatorsByPubKey := make(map[spec.BLSPubKey]*api.Validator, len(validators))
for _, validator := range validators {
var pubKey [48]byte
copy(pubKey[:], validator.Validator.PublicKey)
validatorsByPubKey[pubKey] = validator
validatorsByPubKey[validator.Validator.PublicKey] = validator
}
validatorStateCounts := make(map[string]uint64)
@ -326,7 +331,7 @@ func (s *Service) updateAccountStates(ctx context.Context, accounts map[[48]byte
validator, exists := validatorsByPubKey[pubKey]
if exists {
account.index = validator.Index
account.state = validator.State
account.state = validator.Status
}
validatorStateCounts[strings.ToLower(account.state.String())]++
}
@ -345,7 +350,7 @@ func (s *Service) updateAccountStates(ctx context.Context, accounts map[[48]byte
}
}
func (s *Service) fetchAccountsForWallet(ctx context.Context, wallet e2wtypes.Wallet, accounts map[[48]byte]*ValidatingAccount, verificationRegexes []*regexp.Regexp) {
func (s *Service) fetchAccountsForWallet(ctx context.Context, wallet e2wtypes.Wallet, accounts map[spec.BLSPubKey]*ValidatingAccount, verificationRegexes []*regexp.Regexp) {
for account := range wallet.Accounts(ctx) {
// Ensure the name matches one of our account paths.
name := fmt.Sprintf("%s/%s", wallet.Name(), account.Name())
@ -385,9 +390,9 @@ func (s *Service) fetchAccountsForWallet(ctx context.Context, wallet e2wtypes.Wa
// Set up account as unknown to beacon chain.
accounts[bytesutil.ToBytes48(pubKey)] = &ValidatingAccount{
account: account,
accountManager: s,
signatureDomainProvider: s.signatureDomainProvider,
account: account,
accountManager: s,
domainProvider: s.domainProvider,
}
}
}

View File

@ -1,20 +0,0 @@
// Copyright © 2020 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 wallet
// SigningContainer is the container for signing roots with a domain.
type SigningContainer struct {
Root []byte `ssz-size:"32"`
Domain []byte `ssz-size:"32"`
}

View File

@ -1,88 +0,0 @@
// Code generated by fastssz. DO NOT EDIT.
package wallet
import (
ssz "github.com/ferranbt/fastssz"
)
// MarshalSSZ ssz marshals the SigningContainer object
func (s *SigningContainer) MarshalSSZ() ([]byte, error) {
return ssz.MarshalSSZ(s)
}
// MarshalSSZTo ssz marshals the SigningContainer object to a target array
func (s *SigningContainer) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = buf
// Field (0) 'Root'
if len(s.Root) != 32 {
err = ssz.ErrBytesLength
return
}
dst = append(dst, s.Root...)
// Field (1) 'Domain'
if len(s.Domain) != 32 {
err = ssz.ErrBytesLength
return
}
dst = append(dst, s.Domain...)
return
}
// UnmarshalSSZ ssz unmarshals the SigningContainer object
func (s *SigningContainer) UnmarshalSSZ(buf []byte) error {
var err error
size := uint64(len(buf))
if size != 64 {
return ssz.ErrSize
}
// Field (0) 'Root'
if cap(s.Root) == 0 {
s.Root = make([]byte, 0, len(buf[0:32]))
}
s.Root = append(s.Root, buf[0:32]...)
// Field (1) 'Domain'
if cap(s.Domain) == 0 {
s.Domain = make([]byte, 0, len(buf[32:64]))
}
s.Domain = append(s.Domain, buf[32:64]...)
return err
}
// SizeSSZ returns the ssz encoded size in bytes for the SigningContainer object
func (s *SigningContainer) SizeSSZ() (size int) {
size = 64
return
}
// HashTreeRoot ssz hashes the SigningContainer object
func (s *SigningContainer) HashTreeRoot() ([32]byte, error) {
return ssz.HashWithDefaultHasher(s)
}
// HashTreeRootWith ssz hashes the SigningContainer object with a hasher
func (s *SigningContainer) HashTreeRootWith(hh *ssz.Hasher) (err error) {
indx := hh.Index()
// Field (0) 'Root'
if len(s.Root) != 32 {
err = ssz.ErrBytesLength
return
}
hh.PutBytes(s.Root)
// Field (1) 'Domain'
if len(s.Domain) != 32 {
err = ssz.ErrBytesLength
return
}
hh.PutBytes(s.Domain)
hh.Merkleize(indx)
return
}

View File

@ -21,28 +21,32 @@ import (
api "github.com/attestantio/go-eth2-client/api/v1"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/pkg/errors"
e2types "github.com/wealdtech/go-eth2-types/v2"
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
)
// ValidatingAccount is a wrapper around the wallet account that implements ValidatingAccount.
type ValidatingAccount struct {
account e2wtypes.Account
index uint64
state api.ValidatorState
accountManager *Service
signatureDomainProvider eth2client.SignatureDomainProvider
account e2wtypes.Account
index spec.ValidatorIndex
state api.ValidatorState
accountManager *Service
domainProvider eth2client.DomainProvider
}
// PubKey returns the public key of the validating account.
func (d *ValidatingAccount) PubKey(ctx context.Context) ([]byte, error) {
func (d *ValidatingAccount) PubKey(ctx context.Context) (spec.BLSPubKey, error) {
var pubKey spec.BLSPubKey
if provider, isProvider := d.account.(e2wtypes.AccountCompositePublicKeyProvider); isProvider {
return provider.CompositePublicKey().Marshal(), nil
copy(pubKey[:], provider.CompositePublicKey().Marshal())
} else {
copy(pubKey[:], d.account.PublicKey().Marshal())
}
return d.account.PublicKey().Marshal(), nil
return pubKey, nil
}
// Index returns the index of the validating account.
func (d *ValidatingAccount) Index(ctx context.Context) (uint64, error) {
func (d *ValidatingAccount) Index(ctx context.Context) (spec.ValidatorIndex, error) {
return d.index, nil
}
@ -53,16 +57,16 @@ func (d *ValidatingAccount) State() api.ValidatorState {
// SignSlotSelection returns a slot selection signature.
// This signs a slot with the "selection proof" domain.
func (d *ValidatingAccount) SignSlotSelection(ctx context.Context, slot uint64) ([]byte, error) {
messageRoot := make([]byte, 32)
binary.LittleEndian.PutUint64(messageRoot, slot)
func (d *ValidatingAccount) SignSlotSelection(ctx context.Context, slot spec.Slot) (spec.BLSSignature, error) {
var messageRoot spec.Root
binary.LittleEndian.PutUint64(messageRoot[:], uint64(slot))
// Calculate the signature domain.
domain, err := d.signatureDomainProvider.SignatureDomain(ctx,
// Calculate the domain.
domain, err := d.domainProvider.Domain(ctx,
d.accountManager.selectionProofDomain,
slot/d.accountManager.slotsPerEpoch)
spec.Epoch(slot/d.accountManager.slotsPerEpoch))
if err != nil {
return nil, errors.Wrap(err, "failed to obtain signature domain for selection proof")
return spec.BLSSignature{}, errors.Wrap(err, "failed to obtain domain for selection proof")
}
return d.sign(ctx, messageRoot, domain)
@ -70,30 +74,32 @@ func (d *ValidatingAccount) SignSlotSelection(ctx context.Context, slot uint64)
// SignRANDAOReveal returns a RANDAO reveal signature.
// This signs an epoch with the "RANDAO reveal" domain.
// N.B. This passes in a slot, not an epoch.
func (d *ValidatingAccount) SignRANDAOReveal(ctx context.Context, slot uint64) ([]byte, error) {
messageRoot := make([]byte, 32)
epoch := slot / d.accountManager.slotsPerEpoch
binary.LittleEndian.PutUint64(messageRoot, epoch)
func (d *ValidatingAccount) SignRANDAOReveal(ctx context.Context, slot spec.Slot) (spec.BLSSignature, error) {
var messageRoot spec.Root
epoch := spec.Epoch(slot / d.accountManager.slotsPerEpoch)
binary.LittleEndian.PutUint64(messageRoot[:], uint64(epoch))
// Obtain the RANDAO reveal signature domain.
domain, err := d.signatureDomainProvider.SignatureDomain(ctx,
domain, err := d.domainProvider.Domain(ctx,
d.accountManager.randaoDomain,
epoch)
if err != nil {
return nil, errors.Wrap(err, "failed to obtain signature domain for RANDAO reveal")
return spec.BLSSignature{}, errors.Wrap(err, "failed to obtain signature domain for RANDAO reveal")
}
return d.sign(ctx, messageRoot, domain)
var epochBytes spec.Root
binary.LittleEndian.PutUint64(epochBytes[:], uint64(epoch))
return d.sign(ctx, epochBytes, domain)
}
// SignBeaconBlockProposal signs a beacon block proposal item.
func (d *ValidatingAccount) SignBeaconBlockProposal(ctx context.Context,
slot uint64,
proposerIndex uint64,
parentRoot []byte,
stateRoot []byte,
bodyRoot []byte) ([]byte, error) {
slot spec.Slot,
proposerIndex spec.ValidatorIndex,
parentRoot spec.Root,
stateRoot spec.Root,
bodyRoot spec.Root) (spec.BLSSignature, error) {
message := &spec.BeaconBlockHeader{
Slot: slot,
@ -104,29 +110,29 @@ func (d *ValidatingAccount) SignBeaconBlockProposal(ctx context.Context,
}
messageRoot, err := message.HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "failed to obtain hash tree root of block")
return spec.BLSSignature{}, errors.Wrap(err, "failed to obtain hash tree root of block")
}
// Obtain the signature domain.
domain, err := d.signatureDomainProvider.SignatureDomain(ctx,
// Fetch the domain.
domain, err := d.domainProvider.Domain(ctx,
d.accountManager.beaconProposerDomain,
slot/d.accountManager.slotsPerEpoch)
spec.Epoch(slot/d.accountManager.slotsPerEpoch))
if err != nil {
return nil, errors.Wrap(err, "failed to obtain signature domain for beacon proposal")
return spec.BLSSignature{}, errors.Wrap(err, "failed to obtain signature domain for beacon proposal")
}
return d.sign(ctx, messageRoot[:], domain)
return d.sign(ctx, messageRoot, domain)
}
// SignBeaconAttestation signs a beacon attestation item.
func (d *ValidatingAccount) SignBeaconAttestation(ctx context.Context,
slot uint64,
committeeIndex uint64,
blockRoot []byte,
sourceEpoch uint64,
sourceRoot []byte,
targetEpoch uint64,
targetRoot []byte) ([]byte, error) {
slot spec.Slot,
committeeIndex spec.CommitteeIndex,
blockRoot spec.Root,
sourceEpoch spec.Epoch,
sourceRoot spec.Root,
targetEpoch spec.Epoch,
targetRoot spec.Root) (spec.BLSSignature, error) {
message := &spec.AttestationData{
Slot: slot,
@ -143,46 +149,56 @@ func (d *ValidatingAccount) SignBeaconAttestation(ctx context.Context,
}
messageRoot, err := message.HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "failed to obtain hash tree root of attestation data")
return spec.BLSSignature{}, errors.Wrap(err, "failed to obtain hash tree root of attestation data")
}
domain, err := d.signatureDomainProvider.SignatureDomain(ctx,
domain, err := d.domainProvider.Domain(ctx,
d.accountManager.beaconAttesterDomain,
slot/d.accountManager.slotsPerEpoch)
spec.Epoch(slot/d.accountManager.slotsPerEpoch))
if err != nil {
return nil, errors.Wrap(err, "failed to obtain signature domain for beacon attestation")
return spec.BLSSignature{}, errors.Wrap(err, "failed to obtain signature domain for beacon attestation")
}
return d.sign(ctx, messageRoot[:], domain)
return d.sign(ctx, messageRoot, domain)
}
// SignAggregateAndProof signs an aggregate and proof item.
func (d *ValidatingAccount) SignAggregateAndProof(ctx context.Context, slot uint64, aggregateAndProofRoot []byte) ([]byte, error) {
func (d *ValidatingAccount) SignAggregateAndProof(ctx context.Context, slot spec.Slot, aggregateAndProofRoot spec.Root) (spec.BLSSignature, error) {
// Fetch the signature domain.
domain, err := d.signatureDomainProvider.SignatureDomain(ctx,
domain, err := d.domainProvider.Domain(ctx,
d.accountManager.aggregateAndProofDomain,
slot)
spec.Epoch(slot/d.accountManager.slotsPerEpoch))
if err != nil {
return nil, errors.Wrap(err, "failed to obtain signature domain for beacon aggregate and proof")
return spec.BLSSignature{}, errors.Wrap(err, "failed to obtain signature domain for beacon aggregate and proof")
}
return d.sign(ctx, aggregateAndProofRoot, domain)
}
func (d *ValidatingAccount) sign(ctx context.Context, messageRoot []byte, domain []byte) ([]byte, error) {
container := &SigningContainer{
Root: messageRoot,
Domain: domain,
func (d *ValidatingAccount) sign(ctx context.Context, message spec.Root, domain spec.Domain) (spec.BLSSignature, error) {
var sig e2types.Signature
var err error
if protectingSigner, isProtectingSigner := d.account.(e2wtypes.AccountProtectingSigner); isProtectingSigner {
sig, err = protectingSigner.SignGeneric(ctx, message[:], domain[:])
} else {
// Create the root manually.
container := &spec.SigningData{
ObjectRoot: message,
Domain: domain,
}
var signingRoot spec.Root
signingRoot, err = container.HashTreeRoot()
if err != nil {
return spec.BLSSignature{}, errors.Wrap(err, "failed to generate hash tree root for signing container")
}
sig, err = d.account.(e2wtypes.AccountSigner).Sign(ctx, signingRoot[:])
}
signingRoot, err := container.HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "failed to generate hash tree root for signing container")
return spec.BLSSignature{}, errors.Wrap(err, "failed to sign")
}
sig, err := d.account.(e2wtypes.AccountSigner).Sign(ctx, signingRoot[:])
if err != nil {
return nil, errors.Wrap(err, "failed to sign beacon block proposal")
}
return sig.Marshal(), nil
var signature spec.BLSSignature
copy(signature[:], sig.Marshal())
return signature, nil
}

View File

@ -21,56 +21,20 @@ import (
// Duty contains information about an attestation aggregation duty.
type Duty struct {
validatorIndex uint64
validatorPubKey []byte
slotSignature []byte
attestation *spec.Attestation
}
// NewDuty creates a new attestation aggregation duty.
func NewDuty(ctx context.Context, validatorIndex uint64, validatorPubKey []byte, attestation *spec.Attestation, slotSignature []byte) (*Duty, error) {
return &Duty{
validatorIndex: validatorIndex,
validatorPubKey: validatorPubKey,
slotSignature: slotSignature,
attestation: attestation,
}, nil
}
// Slot provides the slot for the attestaton aggregation.
func (d *Duty) Slot() uint64 {
return d.attestation.Data.Slot
}
// CommitteeIndex provides the committee index for the attestaton aggregation.
func (d *Duty) CommitteeIndex() uint64 {
return d.attestation.Data.Index
}
// ValidatorIndex provides the index of the validator carrying out the attestation aggregation.
func (d *Duty) ValidatorIndex() uint64 {
return d.validatorIndex
}
// ValidatorPubKey provides the public key of the validator carrying out the attestation aggregation.
func (d *Duty) ValidatorPubKey() []byte {
return d.validatorPubKey
}
// Attestation provides the attestation of the validator carrying out the attestation aggregation.
func (d *Duty) Attestation() *spec.Attestation {
return d.attestation
}
// SlotSignature provides the slot signature of the validator carrying out the attestation aggregation.
func (d *Duty) SlotSignature() []byte {
return d.slotSignature
// Slot is the slot of the attestation aggregation; required for obtaining the aggregate.
Slot spec.Slot
// Attestation data root is the root of the attestation to be aggregated; required for obtaining the aggregate.
AttestationDataRoot spec.Root
// ValidatorIndex is the index of the validator carrying out the aggregation; reuqired for submitting the aggregate.
ValidatorIndex spec.ValidatorIndex
// SlotSignature is the signature of the slot by the validator carrying out the aggregation; reuqired for submitting the aggregate.
SlotSignature spec.BLSSignature
}
// IsAggregatorProvider provides information about if a validator is an aggregator.
type IsAggregatorProvider interface {
// IsAggregator returns true if the given validator is an aggregator for the given committee at the given slot.
IsAggregator(ctx context.Context, validatorIndex uint64, committeeIndex uint64, slot uint64, committeeSize uint64) (bool, []byte, error)
IsAggregator(ctx context.Context, validatorIndex spec.ValidatorIndex, committeeIndex spec.CommitteeIndex, slot spec.Slot, committeeSize uint64) (bool, spec.BLSSignature, error)
}
// Service is the attestation aggregation service.

View File

@ -27,7 +27,8 @@ type parameters struct {
monitor metrics.AttestationAggregationMonitor
targetAggregatorsPerCommitteeProvider eth2client.TargetAggregatorsPerCommitteeProvider
validatingAccountsProvider accountmanager.ValidatingAccountsProvider
aggregateAttestationProvider eth2client.NonSpecAggregateAttestationProvider
aggregateAttestationProvider eth2client.AggregateAttestationProvider
prysmAggregateAttestationProvider eth2client.PrysmAggregateAttestationProvider
aggregateAttestationsSubmitter submitter.AggregateAttestationsSubmitter
}
@ -71,12 +72,19 @@ func WithValidatingAccountsProvider(provider accountmanager.ValidatingAccountsPr
}
// WithAggregateAttestationDataProvider sets the aggregate attestation provider.
func WithAggregateAttestationDataProvider(provider eth2client.NonSpecAggregateAttestationProvider) Parameter {
func WithAggregateAttestationDataProvider(provider eth2client.AggregateAttestationProvider) Parameter {
return parameterFunc(func(p *parameters) {
p.aggregateAttestationProvider = provider
})
}
// WithPrysmAggregateAttestationDataProvider sets the non-spec aggregate attestation provider.
func WithPrysmAggregateAttestationDataProvider(provider eth2client.PrysmAggregateAttestationProvider) Parameter {
return parameterFunc(func(p *parameters) {
p.prysmAggregateAttestationProvider = provider
})
}
// WithAggregateAttestationsSubmitter sets the aggregate attestation submitter.
func WithAggregateAttestationsSubmitter(submitter submitter.AggregateAttestationsSubmitter) Parameter {
return parameterFunc(func(p *parameters) {
@ -104,7 +112,7 @@ func parseAndCheckParameters(params ...Parameter) (*parameters, error) {
if parameters.validatingAccountsProvider == nil {
return nil, errors.New("no validating accounts provider specified")
}
if parameters.aggregateAttestationProvider == nil {
if parameters.aggregateAttestationProvider == nil && parameters.prysmAggregateAttestationProvider == nil {
return nil, errors.New("no aggregate attestation provider specified")
}
if parameters.aggregateAttestationsSubmitter == nil {

View File

@ -17,6 +17,7 @@ import (
"context"
"crypto/sha256"
"encoding/binary"
"fmt"
"time"
eth2client "github.com/attestantio/go-eth2-client"
@ -32,11 +33,12 @@ import (
// Service is an attestation aggregator.
type Service struct {
monitor metrics.AttestationAggregationMonitor
targetAggregatorsPerCommittee uint64
validatingAccountsProvider accountmanager.ValidatingAccountsProvider
aggregateAttestationProvider eth2client.NonSpecAggregateAttestationProvider
aggregateAttestationsSubmitter submitter.AggregateAttestationsSubmitter
monitor metrics.AttestationAggregationMonitor
targetAggregatorsPerCommittee uint64
validatingAccountsProvider accountmanager.ValidatingAccountsProvider
aggregateAttestationProvider eth2client.AggregateAttestationProvider
prysmAggregateAttestationProvider eth2client.PrysmAggregateAttestationProvider
aggregateAttestationsSubmitter submitter.AggregateAttestationsSubmitter
}
// module-wide log.
@ -61,11 +63,12 @@ func New(ctx context.Context, params ...Parameter) (*Service, error) {
}
s := &Service{
monitor: parameters.monitor,
targetAggregatorsPerCommittee: targetAggregatorsPerCommittee,
validatingAccountsProvider: parameters.validatingAccountsProvider,
aggregateAttestationProvider: parameters.aggregateAttestationProvider,
aggregateAttestationsSubmitter: parameters.aggregateAttestationsSubmitter,
monitor: parameters.monitor,
targetAggregatorsPerCommittee: targetAggregatorsPerCommittee,
validatingAccountsProvider: parameters.validatingAccountsProvider,
aggregateAttestationProvider: parameters.aggregateAttestationProvider,
prysmAggregateAttestationProvider: parameters.prysmAggregateAttestationProvider,
aggregateAttestationsSubmitter: parameters.aggregateAttestationsSubmitter,
}
return s, nil
@ -81,23 +84,32 @@ func (s *Service) Aggregate(ctx context.Context, data interface{}) {
s.monitor.AttestationAggregationCompleted(started, "failed")
return
}
log := log.With().Uint64("slot", duty.Slot()).Uint64("committee_index", duty.CommitteeIndex()).Logger()
log := log.With().Uint64("slot", uint64(duty.Slot)).Str("attestation_data_root", fmt.Sprintf("%#x", duty.AttestationDataRoot)).Logger()
log.Trace().Msg("Aggregating")
// Obtain the aggregate attestation.
aggregateAttestation, err := s.aggregateAttestationProvider.NonSpecAggregateAttestation(ctx,
duty.Attestation(),
duty.ValidatorPubKey(),
duty.SlotSignature())
var aggregateAttestation *spec.Attestation
var err error
if s.aggregateAttestationProvider != nil {
aggregateAttestation, err = s.aggregateAttestationProvider.AggregateAttestation(ctx, duty.Slot, duty.AttestationDataRoot)
} else {
// TODO
log.Debug().Msg("Not aggregating for non-spec beacon node")
return
}
if err != nil {
log.Error().Err(err).Msg("Failed to obtain aggregate attestation")
s.monitor.AttestationAggregationCompleted(started, "failed")
return
}
log.Trace().Dur("elapsed", time.Since(started)).Msg("Obtained aggregate attestation")
if aggregateAttestation == nil {
log.Debug().Msg("Obtained nil aggregate attestation")
return
}
// Fetch the validating account.
accounts, err := s.validatingAccountsProvider.AccountsByPubKey(ctx, [][]byte{duty.ValidatorPubKey()})
accounts, err := s.validatingAccountsProvider.AccountsByIndex(ctx, []spec.ValidatorIndex{duty.ValidatorIndex})
if err != nil {
log.Error().Err(err).Msg("Failed to obtain proposing validator account")
s.monitor.AttestationAggregationCompleted(started, "failed")
@ -119,16 +131,16 @@ func (s *Service) Aggregate(ctx context.Context, data interface{}) {
return
}
aggregateAndProof := &spec.AggregateAndProof{
AggregatorIndex: duty.ValidatorIndex(),
AggregatorIndex: duty.ValidatorIndex,
Aggregate: aggregateAttestation,
SelectionProof: duty.SlotSignature(),
SelectionProof: duty.SlotSignature,
}
aggregateAndProofRoot, err := aggregateAndProof.HashTreeRoot()
if err != nil {
log.Error().Err(err).Msg("Failed to generate hash tree root of aggregate and proof")
}
sig, err := signer.SignAggregateAndProof(ctx, duty.Slot(), aggregateAndProofRoot[:])
sig, err := signer.SignAggregateAndProof(ctx, duty.Slot, spec.Root(aggregateAndProofRoot))
if err != nil {
log.Error().Err(err).Msg("Failed to sign aggregate and proof")
s.monitor.AttestationAggregationCompleted(started, "failed")
@ -157,7 +169,12 @@ func (s *Service) Aggregate(ctx context.Context, data interface{}) {
}
// IsAggregator reports if we are an attestation aggregator for a given validator/committee/slot combination.
func (s *Service) IsAggregator(ctx context.Context, validatorIndex uint64, committeeIndex uint64, slot uint64, committeeSize uint64) (bool, []byte, error) {
func (s *Service) IsAggregator(ctx context.Context,
validatorIndex spec.ValidatorIndex,
committeeIndex spec.CommitteeIndex,
slot spec.Slot,
committeeSize uint64,
) (bool, spec.BLSSignature, error) {
modulo := committeeSize / s.targetAggregatorsPerCommittee
if modulo == 0 {
// Modulo must be at least 1.
@ -165,34 +182,34 @@ func (s *Service) IsAggregator(ctx context.Context, validatorIndex uint64, commi
}
// Fetch the validator from the account manager.
accounts, err := s.validatingAccountsProvider.AccountsByIndex(ctx, []uint64{validatorIndex})
accounts, err := s.validatingAccountsProvider.AccountsByIndex(ctx, []spec.ValidatorIndex{validatorIndex})
if err != nil {
return false, nil, errors.Wrap(err, "failed to obtain validator")
return false, spec.BLSSignature{}, errors.Wrap(err, "failed to obtain validator")
}
if len(accounts) == 0 {
return false, nil, errors.New("validator unknown")
return false, spec.BLSSignature{}, errors.New("validator unknown")
}
account := accounts[0]
slotSelectionSigner, isSlotSelectionSigner := account.(accountmanager.SlotSelectionSigner)
if !isSlotSelectionSigner {
return false, nil, errors.New("validating account is not a slot selection signer")
return false, spec.BLSSignature{}, errors.New("validating account is not a slot selection signer")
}
// Sign the slot.
signature, err := slotSelectionSigner.SignSlotSelection(ctx, slot)
if err != nil {
return false, nil, errors.Wrap(err, "failed to sign the slot")
return false, spec.BLSSignature{}, errors.Wrap(err, "failed to sign the slot")
}
// Hash the signature.
sigHash := sha256.New()
n, err := sigHash.Write(signature)
n, err := sigHash.Write(signature[:])
if err != nil {
return false, nil, errors.Wrap(err, "failed to hash the slot signature")
return false, spec.BLSSignature{}, errors.Wrap(err, "failed to hash the slot signature")
}
if n != len(signature) {
return false, nil, errors.New("failed to write all bytes of the slot signature to the hash")
return false, spec.BLSSignature{}, errors.New("failed to write all bytes of the slot signature to the hash")
}
hash := sigHash.Sum(nil)

View File

@ -18,14 +18,21 @@ import (
"sort"
api "github.com/attestantio/go-eth2-client/api/v1"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
)
// MergeDuties merges attester duties given by an Ethereum 2 client into vouch's per-slot structure.
func MergeDuties(ctx context.Context, attesterDuties []*api.AttesterDuty) ([]*Duty, error) {
validatorIndices := make(map[uint64][]uint64)
committeeIndices := make(map[uint64][]uint64)
validatorCommitteeIndices := make(map[uint64][]uint64)
committeeLengths := make(map[uint64]map[uint64]uint64)
duties := make([]*Duty, 0, len(attesterDuties))
if len(attesterDuties) == 0 {
return duties, nil
}
validatorIndices := make(map[spec.Slot][]spec.ValidatorIndex)
committeeIndices := make(map[spec.Slot][]spec.CommitteeIndex)
validatorCommitteeIndices := make(map[spec.Slot][]uint64)
committeeLengths := make(map[spec.Slot]map[spec.CommitteeIndex]uint64)
committeesAtSlots := make(map[spec.Slot]uint64)
// Set the base capacity for our arrays based on the number of attester duties.
// This is much higher than we need, but is overall minimal and avoids reallocations.
@ -56,9 +63,10 @@ func MergeDuties(ctx context.Context, attesterDuties []*api.AttesterDuty) ([]*Du
_, exists := validatorIndices[duty.Slot]
if !exists {
validatorIndices[duty.Slot] = make([]uint64, 0, arrayCap)
committeeIndices[duty.Slot] = make([]uint64, 0, arrayCap)
committeeLengths[duty.Slot] = make(map[uint64]uint64)
validatorIndices[duty.Slot] = make([]spec.ValidatorIndex, 0, arrayCap)
committeeIndices[duty.Slot] = make([]spec.CommitteeIndex, 0, arrayCap)
committeeLengths[duty.Slot] = make(map[spec.CommitteeIndex]uint64)
committeesAtSlots[duty.Slot] = duty.CommitteesAtSlot
}
validatorIndices[duty.Slot] = append(validatorIndices[duty.Slot], duty.ValidatorIndex)
committeeIndices[duty.Slot] = append(committeeIndices[duty.Slot], duty.CommitteeIndex)
@ -66,11 +74,11 @@ func MergeDuties(ctx context.Context, attesterDuties []*api.AttesterDuty) ([]*Du
validatorCommitteeIndices[duty.Slot] = append(validatorCommitteeIndices[duty.Slot], duty.ValidatorCommitteeIndex)
}
duties := make([]*Duty, 0, len(validatorIndices))
for slot := range validatorIndices {
if duty, err := NewDuty(
ctx,
slot,
committeesAtSlots[slot],
validatorIndices[slot],
committeeIndices[slot],
validatorCommitteeIndices[slot],

View File

@ -22,15 +22,23 @@ import (
// Duty contains information about a beacon block attester duty.
type Duty struct {
slot uint64
validatorIndices []uint64
committeeIndices []uint64
slot spec.Slot
committeesAtSlot uint64
validatorIndices []spec.ValidatorIndex
committeeIndices []spec.CommitteeIndex
validatorCommitteeIndices []uint64
committeeLengths map[uint64]uint64
committeeLengths map[spec.CommitteeIndex]uint64
}
// NewDuty creates a new beacon block attester duty.
func NewDuty(ctx context.Context, slot uint64, validatorIndices []uint64, committeeIndices []uint64, validatorCommitteeIndices []uint64, committeeLengths map[uint64]uint64) (*Duty, error) {
func NewDuty(ctx context.Context,
slot spec.Slot,
committeesAtSlot uint64,
validatorIndices []spec.ValidatorIndex,
committeeIndices []spec.CommitteeIndex,
validatorCommitteeIndices []uint64,
committeeLengths map[spec.CommitteeIndex]uint64,
) (*Duty, error) {
// Ensure there is a matching committee size for each committee index.
for i := range committeeIndices {
if _, exists := committeeLengths[committeeIndices[i]]; !exists {
@ -40,6 +48,7 @@ func NewDuty(ctx context.Context, slot uint64, validatorIndices []uint64, commit
return &Duty{
slot: slot,
committeesAtSlot: committeesAtSlot,
validatorIndices: validatorIndices,
committeeIndices: committeeIndices,
validatorCommitteeIndices: validatorCommitteeIndices,
@ -48,17 +57,22 @@ func NewDuty(ctx context.Context, slot uint64, validatorIndices []uint64, commit
}
// Slot provides the slot for the beacon block attester.
func (d *Duty) Slot() uint64 {
func (d *Duty) Slot() spec.Slot {
return d.slot
}
// CommitteesAtSlot provides the number of committees at the duty's slot.
func (d *Duty) CommitteesAtSlot() uint64 {
return d.committeesAtSlot
}
// ValidatorIndices provides the validator indices for the beacon block attester.
func (d *Duty) ValidatorIndices() []uint64 {
func (d *Duty) ValidatorIndices() []spec.ValidatorIndex {
return d.validatorIndices
}
// CommitteeIndices provides the committee indices for the beacon block attester.
func (d *Duty) CommitteeIndices() []uint64 {
func (d *Duty) CommitteeIndices() []spec.CommitteeIndex {
return d.committeeIndices
}
@ -68,7 +82,7 @@ func (d *Duty) ValidatorCommitteeIndices() []uint64 {
}
// CommitteeSize provides the committee size for a given index.
func (d *Duty) CommitteeSize(committeeIndex uint64) uint64 {
func (d *Duty) CommitteeSize(committeeIndex spec.CommitteeIndex) uint64 {
return d.committeeLengths[committeeIndex]
}
@ -77,6 +91,20 @@ func (d *Duty) String() string {
return fmt.Sprintf("beacon block attester for slot %d with validators %v committee indices %v", d.slot, d.validatorIndices, d.committeeIndices)
}
// Tuples returns a slice of (validator index, committee index, validator position in committee) strings.
// Useful for logging the
func (d *Duty) Tuples() []string {
tuples := make([]string, len(d.committeeIndices))
for i := range d.committeeIndices {
tuples[i] = fmt.Sprintf("(%d,%d,%d)",
d.validatorIndices[i],
d.committeeIndices[i],
d.validatorCommitteeIndices[i],
)
}
return tuples
}
// Service is the beacon block attester service.
type Service interface {
// Attest carries out attestations for a slot.

View File

@ -85,8 +85,8 @@ func (s *Service) Attest(ctx context.Context, data interface{}) ([]*spec.Attesta
s.monitor.AttestationCompleted(started, "failed")
return nil, errors.New("passed invalid data structure")
}
log := log.With().Uint64("slot", duty.Slot()).Logger()
log.Trace().Uints64("validator_indices", duty.ValidatorIndices()).Msg("Attesting")
log := log.With().Uint64("slot", uint64(duty.Slot())).Logger()
log.Trace().Strs("duties", duty.Tuples()).Msg("Attesting")
attestations := make([]*spec.Attestation, 0, len(duty.ValidatorIndices()))
var attestationsMutex sync.Mutex
@ -110,10 +110,10 @@ func (s *Service) Attest(ctx context.Context, data interface{}) ([]*spec.Attesta
s.monitor.AttestationCompleted(started, "failed")
return nil, errors.New("failed to obtain attesting validator accounts")
}
log.Trace().Dur("elapsed", time.Since(started)).Uints64("validator_indices", duty.ValidatorIndices()).Msg("Obtained validating accounts")
log.Trace().Dur("elapsed", time.Since(started)).Strs("tuples", duty.Tuples()).Msg("Obtained validating accounts")
// Run the attestations in parallel, up to a concurrency limit.
validatorIndexToArrayIndexMap := make(map[uint64]int)
validatorIndexToArrayIndexMap := make(map[spec.ValidatorIndex]int)
for i := range duty.ValidatorIndices() {
validatorIndexToArrayIndexMap[duty.ValidatorIndices()[i]] = i
}
@ -134,7 +134,7 @@ func (s *Service) Attest(ctx context.Context, data interface{}) ([]*spec.Attesta
log.Warn().Err(err).Msg("Failed to obtain validator index")
return
}
log := log.With().Uint64("validator_index", validatorIndex).Logger()
log := log.With().Uint64("validator_index", uint64(validatorIndex)).Logger()
attestation, err := s.attest(ctx,
duty.Slot(),
duty.CommitteeIndices()[validatorIndexToArrayIndexMap[validatorIndex]],
@ -163,8 +163,8 @@ func (s *Service) Attest(ctx context.Context, data interface{}) ([]*spec.Attesta
func (s *Service) attest(
ctx context.Context,
slot uint64,
committeeIndex uint64,
slot spec.Slot,
committeeIndex spec.CommitteeIndex,
validatorCommitteeIndex uint64,
committeeSize uint64,
account accountmanager.ValidatingAccount,

View File

@ -16,20 +16,26 @@ package beaconblockproposer
import (
"context"
"fmt"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/attestantio/vouch/services/accountmanager"
)
// Duty contains information about a beacon block proposal duty.
type Duty struct {
// Details for the duty.
slot uint64
validatorIndex uint64
slot spec.Slot
validatorIndex spec.ValidatorIndex
// randaoReveal is required to be passed to the beacon node when proposing the block; can be pre-calculated.
randaoReveal []byte
randaoReveal spec.BLSSignature
// account is used to sign the proposal; can be pre-fetched.
account accountmanager.ValidatingAccount
}
// NewDuty creates a new beacon block proposer duty.
func NewDuty(ctx context.Context, slot uint64, validatorIndex uint64) (*Duty, error) {
func NewDuty(ctx context.Context, slot spec.Slot, validatorIndex spec.ValidatorIndex) (*Duty, error) {
return &Duty{
slot: slot,
validatorIndex: validatorIndex,
@ -37,12 +43,12 @@ func NewDuty(ctx context.Context, slot uint64, validatorIndex uint64) (*Duty, er
}
// Slot provides the slot for the beacon block proposer.
func (d *Duty) Slot() uint64 {
func (d *Duty) Slot() spec.Slot {
return d.slot
}
// ValidatorIndex provides the validator index for the beacon block proposer.
func (d *Duty) ValidatorIndex() uint64 {
func (d *Duty) ValidatorIndex() spec.ValidatorIndex {
return d.validatorIndex
}
@ -52,15 +58,25 @@ func (d *Duty) String() string {
}
// SetRandaoReveal sets the RANDAO reveal.
func (d *Duty) SetRandaoReveal(randaoReveal []byte) {
func (d *Duty) SetRandaoReveal(randaoReveal spec.BLSSignature) {
d.randaoReveal = randaoReveal
}
// RANDAOReveal provides the RANDAO reveal.
func (d *Duty) RANDAOReveal() []byte {
func (d *Duty) RANDAOReveal() spec.BLSSignature {
return d.randaoReveal
}
// SetAccount sets the account.
func (d *Duty) SetAccount(account accountmanager.ValidatingAccount) {
d.account = account
}
// Account provides the account.
func (d *Duty) Account() accountmanager.ValidatingAccount {
return d.account
}
// Service is the beacon block proposer service.
type Service interface {
// Prepare prepares the proposal for a slot.

View File

@ -26,7 +26,6 @@ import (
"github.com/attestantio/vouch/services/metrics"
"github.com/attestantio/vouch/services/submitter"
"github.com/pkg/errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/rs/zerolog"
zerologger "github.com/rs/zerolog/log"
)
@ -76,11 +75,11 @@ func (s *Service) Prepare(ctx context.Context, data interface{}) error {
if !ok {
return errors.New("passed invalid data structure")
}
log := log.With().Uint64("slot", duty.Slot()).Uint64("validator_index", duty.ValidatorIndex()).Logger()
log := log.With().Uint64("slot", uint64(duty.Slot())).Uint64("validator_index", uint64(duty.ValidatorIndex())).Logger()
log.Trace().Msg("Preparing")
// Fetch the validating account.
accounts, err := s.validatingAccountsProvider.AccountsByIndex(ctx, []uint64{duty.ValidatorIndex()})
accounts, err := s.validatingAccountsProvider.AccountsByIndex(ctx, []spec.ValidatorIndex{duty.ValidatorIndex()})
if err != nil {
return errors.Wrap(err, "failed to obtain proposing validator account")
}
@ -89,6 +88,7 @@ func (s *Service) Prepare(ctx context.Context, data interface{}) error {
}
account := accounts[0]
log.Trace().Dur("elapsed", time.Since(started)).Msg("Obtained proposing account")
duty.SetAccount(account)
revealSigner, isRevealSigner := account.(accountmanager.RANDAORevealSigner)
if !isRevealSigner {
@ -114,25 +114,11 @@ func (s *Service) Propose(ctx context.Context, data interface{}) {
s.monitor.BeaconBlockProposalCompleted(started, "failed")
return
}
log := log.With().Uint64("slot", duty.Slot()).Uint64("validator_index", duty.ValidatorIndex()).Logger()
log := log.With().Uint64("slot", uint64(duty.Slot())).Uint64("validator_index", uint64(duty.ValidatorIndex())).Logger()
log.Trace().Msg("Proposing")
// Fetch the validating account.
accounts, err := s.validatingAccountsProvider.AccountsByIndex(ctx, []uint64{duty.ValidatorIndex()})
if err != nil {
log.Error().Err(err).Msg("Failed to obtain proposing validator account")
s.monitor.BeaconBlockProposalCompleted(started, "failed")
return
}
if len(accounts) != 1 {
log.Error().Err(err).Msg("Unknown proposing validator account")
s.monitor.BeaconBlockProposalCompleted(started, "failed")
return
}
account := accounts[0]
log.Trace().Dur("elapsed", time.Since(started)).Msg("Obtained account")
var graffiti []byte
var err error
if s.graffitiProvider != nil {
graffiti, err = s.graffitiProvider.Graffiti(ctx, duty.Slot(), duty.ValidatorIndex())
if err != nil {
@ -156,7 +142,7 @@ func (s *Service) Propose(ctx context.Context, data interface{}) {
log.Trace().Dur("elapsed", time.Since(started)).Msg("Obtained proposal")
if proposal.Slot != duty.Slot() {
log.Error().Uint64("proposal_slot", proposal.Slot).Msg("Proposal data for incorrect slot; not proceeding")
log.Error().Uint64("proposal_slot", uint64(proposal.Slot)).Msg("Proposal data for incorrect slot; not proceeding")
s.monitor.BeaconBlockProposalCompleted(started, "failed")
return
}
@ -167,27 +153,20 @@ func (s *Service) Propose(ctx context.Context, data interface{}) {
s.monitor.BeaconBlockProposalCompleted(started, "failed")
return
}
proposalData := &ethpb.BeaconBlockHeader{
Slot: proposal.Slot,
ProposerIndex: duty.ValidatorIndex(),
ParentRoot: proposal.ParentRoot,
StateRoot: proposal.StateRoot,
BodyRoot: bodyRoot[:],
}
// Sign the block.
signer, isSigner := account.(accountmanager.BeaconBlockSigner)
signer, isSigner := duty.Account().(accountmanager.BeaconBlockSigner)
if !isSigner {
log.Error().Msg("Account is not a beacon block signer")
s.monitor.BeaconBlockProposalCompleted(started, "failed")
return
}
sig, err := signer.SignBeaconBlockProposal(ctx,
proposalData.Slot,
proposalData.ProposerIndex,
proposalData.ParentRoot,
proposalData.StateRoot,
proposalData.BodyRoot)
proposal.Slot,
duty.ValidatorIndex(),
proposal.ParentRoot,
proposal.StateRoot,
bodyRoot)
if err != nil {
log.Error().Err(err).Msg("Failed to sign beacon block proposal")
s.monitor.BeaconBlockProposalCompleted(started, "failed")

View File

@ -17,21 +17,21 @@ package beaconcommitteesubscriber
import (
"context"
api "github.com/attestantio/go-eth2-client/api/v1"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/attestantio/vouch/services/accountmanager"
)
// Subscription holds details of the committees to which we are subscribing.
type Subscription struct {
ValidatorIndex uint64
ValidatorPubKey []byte
CommitteeSize uint64
Signature []byte
Aggregate bool
Duty *api.AttesterDuty
IsAggregator bool
// TODO is this in the correct place?
Signature spec.BLSSignature
}
// Service is the beacon committee subscriber service.
type Service interface {
// Subscribe subscribes to beacon committees for a given epoch.
// It returns a map of slot => committee => subscription info.
Subscribe(ctx context.Context, epoch uint64, accounts []accountmanager.ValidatingAccount) (map[uint64]map[uint64]*Subscription, error)
Subscribe(ctx context.Context, epoch spec.Epoch, accounts []accountmanager.ValidatingAccount) (map[spec.Slot]map[spec.CommitteeIndex]*Subscription, error)
}

View File

@ -19,6 +19,8 @@ import (
"time"
eth2client "github.com/attestantio/go-eth2-client"
api "github.com/attestantio/go-eth2-client/api/v1"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/attestantio/vouch/services/accountmanager"
"github.com/attestantio/vouch/services/attestationaggregator"
"github.com/attestantio/vouch/services/attester"
@ -70,22 +72,29 @@ func New(ctx context.Context, params ...Parameter) (*Service, error) {
// Subscribe subscribes to beacon committees for a given epoch.
// This returns data about the subnets to which we are subscribing.
func (s *Service) Subscribe(ctx context.Context, epoch uint64, accounts []accountmanager.ValidatingAccount) (map[uint64]map[uint64]*beaconcommitteesubscriber.Subscription, error) {
func (s *Service) Subscribe(ctx context.Context,
epoch spec.Epoch,
accounts []accountmanager.ValidatingAccount,
) (map[spec.Slot]map[spec.CommitteeIndex]*beaconcommitteesubscriber.Subscription, error) {
started := time.Now()
log := log.With().Uint64("epoch", epoch).Logger()
log := log.With().Uint64("epoch", uint64(epoch)).Logger()
log.Trace().Msg("Subscribing")
idProviders := make([]eth2client.ValidatorIDProvider, len(accounts))
validatorIDs := make([]spec.ValidatorIndex, len(accounts))
var err error
for i, account := range accounts {
idProviders[i] = account.(eth2client.ValidatorIDProvider)
validatorIDs[i], err = account.Index(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to obtain account index")
}
}
attesterDuties, err := s.attesterDutiesProvider.AttesterDuties(ctx, epoch, idProviders)
attesterDuties, err := s.attesterDutiesProvider.AttesterDuties(ctx, epoch, validatorIDs)
if err != nil {
s.monitor.BeaconCommitteeSubscriptionCompleted(started, "failed")
return nil, errors.Wrap(err, "failed to obtain attester duties")
}
log.Trace().Dur("elapsed", time.Since(started)).Int("accounts", len(idProviders)).Msg("Fetched attester duties")
log.Trace().Dur("elapsed", time.Since(started)).Int("accounts", len(validatorIDs)).Msg("Fetched attester duties")
duties, err := attester.MergeDuties(ctx, attesterDuties)
if err != nil {
s.monitor.BeaconCommitteeSubscriptionCompleted(started, "failed")
@ -105,7 +114,7 @@ func (s *Service) Subscribe(ctx context.Context, epoch uint64, accounts []accoun
for _, v := range subscriptionInfo {
for _, v2 := range v {
subscriptions++
if v2.Aggregate {
if v2.IsAggregator {
aggregators++
}
}
@ -116,17 +125,15 @@ func (s *Service) Subscribe(ctx context.Context, epoch uint64, accounts []accoun
// Submit the subscription information.
go func() {
log.Trace().Msg("Submitting subscription")
subscriptions := make([]*submitter.BeaconCommitteeSubscription, 0, len(duties))
subscriptions := make([]*api.BeaconCommitteeSubscription, 0, len(duties))
for slot, slotInfo := range subscriptionInfo {
for committeeIndex, info := range slotInfo {
subscriptions = append(subscriptions, &submitter.BeaconCommitteeSubscription{
Slot: slot,
CommitteeIndex: committeeIndex,
CommitteeSize: info.CommitteeSize,
ValidatorIndex: info.ValidatorIndex,
ValidatorPubKey: info.ValidatorPubKey,
Aggregate: info.Aggregate,
Signature: info.Signature,
subscriptions = append(subscriptions, &api.BeaconCommitteeSubscription{
ValidatorIndex: info.Duty.ValidatorIndex,
Slot: slot,
CommitteeIndex: committeeIndex,
CommitteesAtSlot: info.Duty.CommitteesAtSlot,
IsAggregator: info.IsAggregator,
})
}
}
@ -146,17 +153,17 @@ func (s *Service) Subscribe(ctx context.Context, epoch uint64, accounts []accoun
// calculateSubscriptionInfo calculates our beacon block attesation subnet requirements given a set of duties.
// It returns a map of slot => committee => subscription information.
func (s *Service) calculateSubscriptionInfo(ctx context.Context,
epoch uint64,
epoch spec.Epoch,
accounts []accountmanager.ValidatingAccount,
duties []*attester.Duty,
) (map[uint64]map[uint64]*beaconcommitteesubscriber.Subscription, error) {
) (map[spec.Slot]map[spec.CommitteeIndex]*beaconcommitteesubscriber.Subscription, error) {
// Map is slot => committee => info.
subscriptionInfo := make(map[uint64]map[uint64]*beaconcommitteesubscriber.Subscription)
subscriptionInfo := make(map[spec.Slot]map[spec.CommitteeIndex]*beaconcommitteesubscriber.Subscription)
subscriptionInfoMutex := deadlock.RWMutex{}
// Map is validator ID => account.
accountMap := make(map[uint64]accountmanager.ValidatingAccount, len(accounts))
accountMap := make(map[spec.ValidatorIndex]accountmanager.ValidatingAccount, len(accounts))
for _, account := range accounts {
index, err := account.Index(ctx)
if err != nil {
@ -187,7 +194,7 @@ func (s *Service) calculateSubscriptionInfo(ctx context.Context,
subscriptionInfoMutex.RLock()
info, exists := subscriptionInfo[duty.Slot()][duty.CommitteeIndices()[i]]
subscriptionInfoMutex.RUnlock()
if exists && info.Aggregate {
if exists && info.IsAggregator {
// Already an aggregator for this slot/committee; don't need to go further.
return
}
@ -201,26 +208,27 @@ func (s *Service) calculateSubscriptionInfo(ctx context.Context,
log.Error().Err(err).Msg("Failed to calculate if validator is an aggregator")
return
}
account, exists := accountMap[duty.ValidatorIndices()[i]]
if !exists {
log.Error().Uint64("validator_index", duty.ValidatorIndices()[i]).Msg("Failed to obtain validator account")
pubKey, err := accountMap[duty.ValidatorIndices()[i]].PubKey(ctx)
if err != nil {
log.Error().Err(err).Msg("Failed to obtain validator's public key")
return
}
subscriptionInfoMutex.Lock()
if _, exists := subscriptionInfo[duty.Slot()]; !exists {
subscriptionInfo[duty.Slot()] = make(map[uint64]*beaconcommitteesubscriber.Subscription)
}
pubKey, err := account.PubKey(ctx)
if err != nil {
log.Error().Uint64("validator_index", duty.ValidatorIndices()[i]).Err(err).Msg("Failed to obtain validator public key")
return
subscriptionInfo[duty.Slot()] = make(map[spec.CommitteeIndex]*beaconcommitteesubscriber.Subscription)
}
subscriptionInfo[duty.Slot()][duty.CommitteeIndices()[i]] = &beaconcommitteesubscriber.Subscription{
ValidatorIndex: duty.ValidatorIndices()[i],
ValidatorPubKey: pubKey,
CommitteeSize: duty.CommitteeSize(duty.CommitteeIndices()[i]),
Signature: signature,
Aggregate: isAggregator,
Duty: &api.AttesterDuty{
PubKey: pubKey,
Slot: duty.Slot(),
ValidatorIndex: duty.ValidatorIndices()[i],
CommitteeIndex: duty.CommitteeIndices()[i],
CommitteeLength: duty.CommitteeSize(duty.CommitteeIndices()[i]),
CommitteesAtSlot: duty.CommitteesAtSlot(),
ValidatorCommitteeIndex: duty.ValidatorCommitteeIndices()[i],
},
IsAggregator: isAggregator,
Signature: signature,
}
subscriptionInfoMutex.Unlock()
}(ctx, sem, wg, duty, i)

View File

@ -13,22 +13,26 @@
package chaintime
import "time"
import (
"time"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
)
// Service provides a number of functions for calculating chain-related times.
type Service interface {
// GenesisTime provides the time of the chain's genesis.
GenesisTime() time.Time
// StartOfSlot provides the time at which a given slot starts.
StartOfSlot(slot uint64) time.Time
StartOfSlot(slot spec.Slot) time.Time
// StartOfEpoch provides the time at which a given epoch starts.
StartOfEpoch(epoch uint64) time.Time
StartOfEpoch(epoch spec.Epoch) time.Time
// CurrentSlot provides the current slot.
CurrentSlot() uint64
CurrentSlot() spec.Slot
// CurrentEpoch provides the current epoch.
CurrentEpoch() uint64
CurrentEpoch() spec.Epoch
// SlotToEpoch provides the epoch of the given slot.
SlotToEpoch(slot uint64) uint64
SlotToEpoch(slot spec.Slot) spec.Epoch
// FirstSlotOfEpoch provides the first slot of the given epoch.
FirstSlotOfEpoch(epoch uint64) uint64
FirstSlotOfEpoch(epoch spec.Epoch) spec.Slot
}

View File

@ -17,6 +17,7 @@ import (
"context"
"time"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/pkg/errors"
"github.com/rs/zerolog"
zerologger "github.com/rs/zerolog/log"
@ -78,37 +79,37 @@ func (s *Service) GenesisTime() time.Time {
}
// StartOfSlot provides the time at which a given slot starts.
func (s *Service) StartOfSlot(slot uint64) time.Time {
func (s *Service) StartOfSlot(slot spec.Slot) time.Time {
return s.genesisTime.Add(time.Duration(slot) * s.slotDuration)
}
// StartOfEpoch provides the time at which a given epoch starts.
func (s *Service) StartOfEpoch(epoch uint64) time.Time {
return s.genesisTime.Add(time.Duration(epoch*s.slotsPerEpoch) * s.slotDuration)
func (s *Service) StartOfEpoch(epoch spec.Epoch) time.Time {
return s.genesisTime.Add(time.Duration(uint64(epoch)*s.slotsPerEpoch) * s.slotDuration)
}
// CurrentSlot provides the current slot.
func (s *Service) CurrentSlot() uint64 {
func (s *Service) CurrentSlot() spec.Slot {
if s.genesisTime.After(time.Now()) {
return 0
return spec.Slot(0)
}
return uint64(time.Since(s.genesisTime).Seconds()) / uint64(s.slotDuration.Seconds())
return spec.Slot(uint64(time.Since(s.genesisTime).Seconds()) / uint64(s.slotDuration.Seconds()))
}
// CurrentEpoch provides the current epoch.
func (s *Service) CurrentEpoch() uint64 {
func (s *Service) CurrentEpoch() spec.Epoch {
if s.genesisTime.After(time.Now()) {
return 0
return spec.Epoch(0)
}
return uint64(time.Since(s.genesisTime).Seconds()) / (uint64(s.slotDuration.Seconds()) * s.slotsPerEpoch)
return spec.Epoch(uint64(time.Since(s.genesisTime).Seconds()) / (uint64(s.slotDuration.Seconds()) * s.slotsPerEpoch))
}
// SlotToEpoch provides the epoch of a given slot.
func (s *Service) SlotToEpoch(slot uint64) uint64 {
return slot / s.slotsPerEpoch
func (s *Service) SlotToEpoch(slot spec.Slot) spec.Epoch {
return spec.Epoch(uint64(slot) / s.slotsPerEpoch)
}
// FirstSlotOfEpoch provides the first slot of the given epoch.
func (s *Service) FirstSlotOfEpoch(epoch uint64) uint64 {
return epoch * s.slotsPerEpoch
func (s *Service) FirstSlotOfEpoch(epoch spec.Epoch) spec.Slot {
return spec.Slot(uint64(epoch) * s.slotsPerEpoch)
}

View File

@ -18,6 +18,7 @@ import (
"testing"
"time"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/attestantio/vouch/mock"
"github.com/attestantio/vouch/services/chaintime"
"github.com/attestantio/vouch/services/chaintime/standard"
@ -143,7 +144,7 @@ func TestCurrentSlot(t *testing.T) {
s, err := createMockService(slotDuration, slotsPerEpoch, genesisTime)
require.NoError(t, err)
require.Equal(t, uint64(5), s.CurrentSlot())
require.Equal(t, spec.Slot(5), s.CurrentSlot())
}
func TestCurrentSlotPreGenesis(t *testing.T) {
@ -154,7 +155,7 @@ func TestCurrentSlotPreGenesis(t *testing.T) {
s, err := createMockService(slotDuration, slotsPerEpoch, genesisTime)
require.NoError(t, err)
require.Equal(t, uint64(0), s.CurrentSlot())
require.Equal(t, spec.Slot(0), s.CurrentSlot())
}
func TestCurrentEpoch(t *testing.T) {
@ -165,7 +166,7 @@ func TestCurrentEpoch(t *testing.T) {
s, err := createMockService(slotDuration, slotsPerEpoch, genesisTime)
require.NoError(t, err)
require.Equal(t, uint64(2), s.CurrentEpoch())
require.Equal(t, spec.Epoch(2), s.CurrentEpoch())
}
func TestCurrentEpochPreGenesis(t *testing.T) {
@ -176,14 +177,14 @@ func TestCurrentEpochPreGenesis(t *testing.T) {
s, err := createMockService(slotDuration, slotsPerEpoch, genesisTime)
require.NoError(t, err)
require.Equal(t, uint64(0), s.CurrentEpoch())
require.Equal(t, spec.Epoch(0), s.CurrentEpoch())
}
func TestSlotToEpoch(t *testing.T) {
tests := []struct {
name string
slot uint64
epoch uint64
slot spec.Slot
epoch spec.Epoch
}{
{
name: "ZeroFirstSlot",
@ -220,8 +221,8 @@ func TestSlotToEpoch(t *testing.T) {
func TestFirstSlotOfEpoch(t *testing.T) {
tests := []struct {
name string
epoch uint64
slot uint64
epoch spec.Epoch
slot spec.Slot
}{
{
name: "Zero",

View File

@ -17,8 +17,8 @@ import (
"context"
"fmt"
eth2client "github.com/attestantio/go-eth2-client"
api "github.com/attestantio/go-eth2-client/api/v1"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/attestantio/vouch/services/accountmanager"
"github.com/attestantio/vouch/services/attestationaggregator"
"github.com/attestantio/vouch/services/attester"
@ -26,16 +26,21 @@ import (
// createAttesterJobs creates attestation jobs for the given epoch provided accounts.
func (s *Service) createAttesterJobs(ctx context.Context,
epoch uint64,
epoch spec.Epoch,
accounts []accountmanager.ValidatingAccount,
firstRun bool) {
log.Trace().Msg("Creating attester jobs")
idProviders := make([]eth2client.ValidatorIDProvider, len(accounts))
validatorIDs := make([]spec.ValidatorIndex, len(accounts))
var err error
for i, account := range accounts {
idProviders[i] = account.(eth2client.ValidatorIDProvider)
validatorIDs[i], err = account.Index(ctx)
if err != nil {
log.Error().Err(err).Msg("Failed to obtain account index")
return
}
}
resp, err := s.attesterDutiesProvider.AttesterDuties(ctx, epoch, idProviders)
resp, err := s.attesterDutiesProvider.AttesterDuties(ctx, epoch, validatorIDs)
if err != nil {
log.Error().Err(err).Msg("Failed to obtain attester duties")
return
@ -43,11 +48,11 @@ func (s *Service) createAttesterJobs(ctx context.Context,
// Filter bad responses.
filteredDuties := make([]*api.AttesterDuty, 0, len(resp))
firstSlot := epoch * s.slotsPerEpoch
lastSlot := (epoch+1)*s.slotsPerEpoch - 1
firstSlot := spec.Slot(uint64(epoch) * s.slotsPerEpoch)
lastSlot := spec.Slot((uint64(epoch)+1)*s.slotsPerEpoch - 1)
for _, duty := range resp {
if duty.Slot < firstSlot || duty.Slot > lastSlot {
log.Warn().Uint64("epoch", epoch).Uint64("duty_slot", duty.Slot).Msg("Attester duty has invalid slot for requested epoch; ignoring")
log.Warn().Uint64("epoch", uint64(epoch)).Uint64("duty_slot", uint64(duty.Slot)).Msg("Attester duty has invalid slot for requested epoch; ignoring")
continue
}
filteredDuties = append(filteredDuties, duty)
@ -59,24 +64,24 @@ func (s *Service) createAttesterJobs(ctx context.Context,
return
}
for _, duty := range duties {
log.
Trace().
Uint64("slot", duty.Slot()).
Uints64("committee_indices", duty.CommitteeIndices()).
Uints64("validator_indices", duty.ValidatorCommitteeIndices()).
Msg("Received attester duty")
if e := log.Trace(); e.Enabled() {
for _, duty := range duties {
log.Trace().
Uint64("slot", uint64(duty.Slot())).
Strs("duties", duty.Tuples()).
Msg("Received attester duties")
}
}
currentSlot := s.chainTimeService.CurrentSlot()
for _, duty := range duties {
// Do not schedule attestations for past slots (or the current slot if we've just started).
if duty.Slot() < currentSlot {
log.Debug().Uint64("attestation_slot", duty.Slot()).Uint64("current_slot", currentSlot).Msg("Attestation in the past; not scheduling")
log.Debug().Uint64("attestation_slot", uint64(duty.Slot())).Uint64("current_slot", uint64(currentSlot)).Msg("Attestation for a past slot; not scheduling")
continue
}
if firstRun && duty.Slot() == currentSlot {
log.Debug().Uint64("attestation_slot", duty.Slot()).Uint64("current_slot", currentSlot).Msg("Attestation in the current slot and this is our first run; not scheduling")
log.Debug().Uint64("attestation_slot", uint64(duty.Slot())).Uint64("current_slot", uint64(currentSlot)).Msg("Attestation for the current slot and this is our first run; not scheduling")
continue
}
if err := s.scheduler.ScheduleJob(ctx,
@ -110,38 +115,45 @@ func (s *Service) AttestAndScheduleAggregate(ctx context.Context, data interface
return
}
epoch := attestations[0].Data.Slot / s.slotsPerEpoch
epoch := s.chainTimeService.SlotToEpoch(attestations[0].Data.Slot)
s.subscriptionInfosMutex.Lock()
subscriptionInfoMap, exists := s.subscriptionInfos[epoch]
s.subscriptionInfosMutex.Unlock()
if !exists {
log.Warn().Msg("No subscription info for this epoch; cannot aggregate")
log.Debug().Uint64("epoch", uint64(epoch)).Msg("No subscription info for this epoch; not aggregating")
return
}
for _, attestation := range attestations {
log := log.With().Uint64("attestation_slot", uint64(attestation.Data.Slot)).Logger()
slotInfoMap, exists := subscriptionInfoMap[attestation.Data.Slot]
if !exists {
log.Debug().Uint64("attestation_slot", attestation.Data.Slot).Msg("No slot info; cannot aggregate")
log.Debug().Msg("No slot info; not aggregating")
continue
}
// Do not schedule aggregations for past slots.
if attestation.Data.Slot < s.chainTimeService.CurrentSlot() {
log.Debug().Uint64("aggregation_slot", attestation.Data.Slot).Uint64("current_slot", s.chainTimeService.CurrentSlot()).Msg("Aggregation in the past; not scheduling")
log.Debug().Uint64("current_slot", uint64(s.chainTimeService.CurrentSlot())).Msg("Aggregation in the past; not scheduling")
continue
}
info, exists := slotInfoMap[attestation.Data.Index]
if !exists {
log.Debug().Uint64("attestation_slot", attestation.Data.Slot).Uint64("committee_index", attestation.Data.Index).Msg("No committee info; cannot aggregate")
log.Debug().Uint64("committee_index", uint64(attestation.Data.Index)).Msg("No committee info; not aggregating")
continue
}
if info.Aggregate {
aggregatorDuty, err := attestationaggregator.NewDuty(ctx, info.ValidatorIndex, info.ValidatorPubKey, attestation, info.Signature)
if info.IsAggregator {
attestationDataRoot, err := attestation.Data.HashTreeRoot()
if err != nil {
// Don't return here; we want to try to set up as many aggregator jobs as possible.
log.Error().Err(err).Msg("Failed to create beacon block attestation aggregation duty")
log.Error().Err(err).Msg("Failed to obtain hash tree root of attestation")
continue
}
aggregatorDuty := &attestationaggregator.Duty{
Slot: info.Duty.Slot,
AttestationDataRoot: attestationDataRoot,
ValidatorIndex: info.Duty.ValidatorIndex,
SlotSignature: info.Signature,
}
if err := s.scheduler.ScheduleJob(ctx,
fmt.Sprintf("Beacon block attestation aggregation for slot %d committee %d", attestation.Data.Slot, attestation.Data.Index),
s.chainTimeService.StartOfSlot(attestation.Data.Slot).Add(s.slotDuration*2/3),

View File

@ -0,0 +1,49 @@
// Copyright © 2020 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 standard
import (
"context"
"fmt"
"time"
api "github.com/attestantio/go-eth2-client/api/v1"
)
// HandleHeadEvent handles the "head" events from the beacon node.
func (s *Service) HandleHeadEvent(event *api.Event) {
ctx := context.Background()
data := event.Data.(*api.HeadEvent)
log.Trace().Uint64("slot", uint64(data.Slot)).Msg("Received head event")
if data.Slot != s.chainTimeService.CurrentSlot() {
return
}
s.monitor.BlockDelay(time.Since(s.chainTimeService.StartOfSlot(data.Slot)))
// Kick off attestations for the block's slot immediately.
jobName := fmt.Sprintf("Beacon block attestations for slot %d", data.Slot)
if s.scheduler.JobExists(ctx, jobName) {
log.Trace().Uint64("slot", uint64(data.Slot)).Msg("Kicking off attestations for slot early due to receiving relevant block")
if err := s.scheduler.RunJobIfExists(ctx, jobName); err != nil {
log.Error().Str("job", jobName).Err(err).Msg("Failed to run attester job")
}
}
// If the head is in a new fork it may result in different attester duties.
// TODO
// Remove old subscriptions if present.
delete(s.subscriptionInfos, s.chainTimeService.SlotToEpoch(data.Slot)-2)
}

View File

@ -28,20 +28,20 @@ import (
)
type parameters struct {
logLevel zerolog.Level
monitor metrics.ControllerMonitor
slotDurationProvider eth2client.SlotDurationProvider
slotsPerEpochProvider eth2client.SlotsPerEpochProvider
chainTimeService chaintime.Service
proposerDutiesProvider eth2client.ProposerDutiesProvider
attesterDutiesProvider eth2client.AttesterDutiesProvider
validatingAccountsProvider accountmanager.ValidatingAccountsProvider
scheduler scheduler.Service
beaconChainHeadUpdatedSource eth2client.BeaconChainHeadUpdatedSource
attester attester.Service
beaconBlockProposer beaconblockproposer.Service
attestationAggregator attestationaggregator.Service
beaconCommitteeSubscriber beaconcommitteesubscriber.Service
logLevel zerolog.Level
monitor metrics.ControllerMonitor
slotDurationProvider eth2client.SlotDurationProvider
slotsPerEpochProvider eth2client.SlotsPerEpochProvider
chainTimeService chaintime.Service
proposerDutiesProvider eth2client.ProposerDutiesProvider
attesterDutiesProvider eth2client.AttesterDutiesProvider
validatingAccountsProvider accountmanager.ValidatingAccountsProvider
scheduler scheduler.Service
eventsProvider eth2client.EventsProvider
attester attester.Service
beaconBlockProposer beaconblockproposer.Service
attestationAggregator attestationaggregator.Service
beaconCommitteeSubscriber beaconcommitteesubscriber.Service
}
// Parameter is the interface for service parameters.
@ -104,10 +104,10 @@ func WithAttesterDutiesProvider(provider eth2client.AttesterDutiesProvider) Para
})
}
// WithBeaconChainHeadUpdatedSource sets the source for an OnBeaconChainHeadUpdated request
func WithBeaconChainHeadUpdatedSource(source eth2client.BeaconChainHeadUpdatedSource) Parameter {
// WithEventsProvider sets the events provider.
func WithEventsProvider(provider eth2client.EventsProvider) Parameter {
return parameterFunc(func(p *parameters) {
p.beaconChainHeadUpdatedSource = source
p.eventsProvider = provider
})
}
@ -182,8 +182,8 @@ func parseAndCheckParameters(params ...Parameter) (*parameters, error) {
if parameters.attesterDutiesProvider == nil {
return nil, errors.New("no attester duties provider specified")
}
if parameters.beaconChainHeadUpdatedSource == nil {
return nil, errors.New("no beacon chain head updated source specified")
if parameters.eventsProvider == nil {
return nil, errors.New("no events provider specified")
}
if parameters.scheduler == nil {
return nil, errors.New("no scheduler service specified")

View File

@ -17,22 +17,29 @@ import (
"context"
"fmt"
eth2client "github.com/attestantio/go-eth2-client"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/attestantio/vouch/services/accountmanager"
"github.com/attestantio/vouch/services/beaconblockproposer"
)
// createProposerJobs creates proposal jobs for the given epoch.
func (s *Service) createProposerJobs(ctx context.Context,
epoch uint64,
epoch spec.Epoch,
accounts []accountmanager.ValidatingAccount,
firstRun bool) {
validatorIDProviders := make([]eth2client.ValidatorIDProvider, len(accounts))
log.Trace().Msg("Creating proposer jobs")
validatorIDs := make([]spec.ValidatorIndex, len(accounts))
var err error
for i, account := range accounts {
validatorIDProviders[i] = account
validatorIDs[i], err = account.Index(ctx)
if err != nil {
log.Error().Err(err).Msg("Failed to obtain account index")
return
}
}
resp, err := s.proposerDutiesProvider.ProposerDuties(ctx, epoch, validatorIDProviders)
resp, err := s.proposerDutiesProvider.ProposerDuties(ctx, epoch, validatorIDs)
if err != nil {
log.Error().Err(err).Msg("Failed to obtain proposer duties")
return
@ -40,11 +47,11 @@ func (s *Service) createProposerJobs(ctx context.Context,
// Filter bad responses.
duties := make([]*beaconblockproposer.Duty, 0, len(resp))
firstSlot := epoch * s.slotsPerEpoch
lastSlot := (epoch+1)*s.slotsPerEpoch - 1
firstSlot := s.chainTimeService.FirstSlotOfEpoch(epoch)
lastSlot := s.chainTimeService.FirstSlotOfEpoch(epoch+1) - 1
for _, respDuty := range resp {
if respDuty.Slot < firstSlot || respDuty.Slot > lastSlot {
log.Warn().Uint64("epoch", epoch).Uint64("duty_slot", respDuty.Slot).Msg("Proposer duty has invalid slot for requested epoch; ignoring")
log.Warn().Uint64("epoch", uint64(epoch)).Uint64("duty_slot", uint64(respDuty.Slot)).Msg("Proposer duty has invalid slot for requested epoch; ignoring")
continue
}
duty, err := beaconblockproposer.NewDuty(ctx, respDuty.Slot, respDuty.ValidatorIndex)
@ -59,12 +66,12 @@ func (s *Service) createProposerJobs(ctx context.Context,
for _, duty := range duties {
// Do not schedule proposals for past slots (or the current slot if we've just started).
if duty.Slot() < currentSlot || firstRun && duty.Slot() == currentSlot {
log.Debug().Uint64("proposal_slot", duty.Slot()).Uint64("current_slot", currentSlot).Msg("Proposal in the past; not scheduling")
log.Debug().Uint64("proposal_slot", uint64(duty.Slot())).Uint64("current_slot", uint64(currentSlot)).Msg("Proposal in the past; not scheduling")
continue
}
go func(duty *beaconblockproposer.Duty) {
if err := s.beaconBlockProposer.Prepare(ctx, duty); err != nil {
log.Error().Uint64("proposal_slot", duty.Slot()).Err(err).Msg("Failed to prepare proposal")
log.Error().Uint64("proposal_slot", uint64(duty.Slot())).Err(err).Msg("Failed to prepare proposal")
return
}
if err := s.scheduler.ScheduleJob(ctx,

View File

@ -20,6 +20,7 @@ import (
"time"
eth2client "github.com/attestantio/go-eth2-client"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/attestantio/vouch/services/accountmanager"
"github.com/attestantio/vouch/services/attestationaggregator"
"github.com/attestantio/vouch/services/attester"
@ -50,9 +51,8 @@ type Service struct {
attestationAggregator attestationaggregator.Service
beaconCommitteeSubscriber beaconcommitteesubscriber.Service
activeAccounts int
// Epoch => slot => committee => subscription info cache.
subscriptionInfos map[uint64]map[uint64]map[uint64]*beaconcommitteesubscriber.Subscription
subscriptionInfosMutex sync.Mutex
subscriptionInfos map[spec.Epoch]map[spec.Slot]map[spec.CommitteeIndex]*beaconcommitteesubscriber.Subscription
subscriptionInfosMutex sync.Mutex
}
// module-wide log.
@ -94,12 +94,13 @@ func New(ctx context.Context, params ...Parameter) (*Service, error) {
beaconBlockProposer: parameters.beaconBlockProposer,
attestationAggregator: parameters.attestationAggregator,
beaconCommitteeSubscriber: parameters.beaconCommitteeSubscriber,
subscriptionInfos: make(map[uint64]map[uint64]map[uint64]*beaconcommitteesubscriber.Subscription),
subscriptionInfos: make(map[spec.Epoch]map[spec.Slot]map[spec.CommitteeIndex]*beaconcommitteesubscriber.Subscription),
}
log.Trace().Msg("Adding beacon chain head updated handler")
if err := parameters.beaconChainHeadUpdatedSource.AddOnBeaconChainHeadUpdatedHandler(ctx, s); err != nil {
return nil, errors.Wrap(err, "failed to add beacon chain head updated handler")
// Subscribe to head events. This allows us to go early for attestations if a block arrives, as well as
// re-request duties if there is a change in beacon block.
if err := parameters.eventsProvider.Events(ctx, []string{"head"}, s.HandleHeadEvent); err != nil {
return nil, errors.Wrap(err, "failed to add head event handler")
}
// Subscriptions are usually updated one epoch in advance, but as we're
@ -206,10 +207,10 @@ func (s *Service) epochTicker(ctx context.Context, data interface{}) {
epochTickerData := data.(*epochTickerData)
currentEpoch := s.chainTimeService.CurrentEpoch()
firstRun := epochTickerData.latestEpochRan == -1
log.Trace().Uint64("epoch", currentEpoch).Bool("first_run", firstRun).Msg("Starting per-epoch duties")
log.Trace().Uint64("epoch", uint64(currentEpoch)).Bool("first_run", firstRun).Msg("Starting per-epoch duties")
epochTickerData.mutex.Lock()
if epochTickerData.latestEpochRan >= int64(currentEpoch) {
log.Trace().Uint64("epoch", currentEpoch).Msg("Already ran for this epoch; skipping")
log.Trace().Uint64("epoch", uint64(currentEpoch)).Msg("Already ran for this epoch; skipping")
epochTickerData.mutex.Unlock()
return
}
@ -263,21 +264,21 @@ func (s *Service) epochTicker(ctx context.Context, data interface{}) {
epochTickerData.atGenesis = false
}
// OnBeaconChainHeadUpdated runs attestations for a slot immediately, if the update is for the current slot.
func (s *Service) OnBeaconChainHeadUpdated(ctx context.Context, slot uint64, stateRoot []byte, bodyRoot []byte, epochTransitioni bool) {
if slot != s.chainTimeService.CurrentSlot() {
return
}
s.monitor.BlockDelay(time.Since(s.chainTimeService.StartOfSlot(slot)))
jobName := fmt.Sprintf("Beacon block attestations for slot %d", slot)
if s.scheduler.JobExists(ctx, jobName) {
log.Trace().Uint64("slot", slot).Msg("Kicking off attestations for slot early due to receiving relevant block")
if err := s.scheduler.RunJobIfExists(ctx, jobName); err != nil {
log.Error().Str("job", jobName).Err(err).Msg("Failed to run attester job")
}
}
// Remove old subscriptions if present.
delete(s.subscriptionInfos, s.chainTimeService.SlotToEpoch(slot)-2)
}
// // OnBeaconChainHeadUpdated runs attestations for a slot immediately, if the update is for the current slot.
// func (s *Service) OnBeaconChainHeadUpdated(ctx context.Context, slot uint64, stateRoot []byte, bodyRoot []byte, epochTransitioni bool) {
// if slot != s.chainTimeService.CurrentSlot() {
// return
// }
// s.monitor.BlockDelay(time.Since(s.chainTimeService.StartOfSlot(slot)))
//
// jobName := fmt.Sprintf("Beacon block attestations for slot %d", slot)
// if s.scheduler.JobExists(ctx, jobName) {
// log.Trace().Uint64("slot", slot).Msg("Kicking off attestations for slot early due to receiving relevant block")
// if err := s.scheduler.RunJobIfExists(ctx, jobName); err != nil {
// log.Error().Str("job", jobName).Err(err).Msg("Failed to run attester job")
// }
// }
//
// // Remove old subscriptions if present.
// delete(s.subscriptionInfos, s.chainTimeService.SlotToEpoch(slot)-2)
// }

View File

@ -20,6 +20,7 @@ import (
"strings"
"time"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/pkg/errors"
"github.com/rs/zerolog"
zerologger "github.com/rs/zerolog/log"
@ -60,7 +61,7 @@ func New(ctx context.Context, params ...Parameter) (*Service, error) {
}
// Graffiti provides graffiti.
func (s *Service) Graffiti(ctx context.Context, slot uint64, validatorIndex uint64) ([]byte, error) {
func (s *Service) Graffiti(ctx context.Context, slot spec.Slot, validatorIndex spec.ValidatorIndex) ([]byte, error) {
// Replace location parameters with values.
location := strings.ReplaceAll(s.location, "{{SLOT}}", fmt.Sprintf("%d", slot))
location = strings.ReplaceAll(location, "{{VALIDATORINDEX}}", fmt.Sprintf("%d", validatorIndex))

View File

@ -21,6 +21,7 @@ import (
"path/filepath"
"testing"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/attestantio/vouch/services/graffitiprovider/dynamic"
"github.com/rs/zerolog"
"github.com/stretchr/testify/require"
@ -182,7 +183,7 @@ func TestReplacement(t *testing.T) {
require.NoError(t, err)
for validatorIndex := uint64(0); validatorIndex < 16; validatorIndex++ {
for slot := uint64(0); slot < 16; slot++ {
graffiti, err := svc.Graffiti(ctx, slot, validatorIndex)
graffiti, err := svc.Graffiti(ctx, spec.Slot(slot), spec.ValidatorIndex(validatorIndex))
require.NoError(t, err)
delete(expectedGraffitis, string(graffiti))
}
@ -298,7 +299,7 @@ func TestMultiline(t *testing.T) {
require.NoError(t, err)
for validatorIndex := uint64(0); validatorIndex < 16; validatorIndex++ {
for slot := uint64(0); slot < 16; slot++ {
graffiti, err := svc.Graffiti(ctx, slot, validatorIndex)
graffiti, err := svc.Graffiti(ctx, spec.Slot(slot), spec.ValidatorIndex(validatorIndex))
require.NoError(t, err)
require.Contains(t, test.expectedGraffitis, string(graffiti))
delete(obtainedGraffitis, string(graffiti))

View File

@ -16,10 +16,12 @@ package graffitiprovider
import (
"context"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
)
// Service is the graffiti provider service.
type Service interface {
// Graffiti returns the graffiti for a given slot and validator.
Graffiti(ctx context.Context, slot uint64, validatorIndex uint64) ([]byte, error)
Graffiti(ctx context.Context, slot spec.Slot, validatorIndex spec.ValidatorIndex) ([]byte, error)
}

View File

@ -16,6 +16,7 @@ package static
import (
"context"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/pkg/errors"
"github.com/rs/zerolog"
zerologger "github.com/rs/zerolog/log"
@ -50,6 +51,6 @@ func New(ctx context.Context, params ...Parameter) (*Service, error) {
}
// Graffiti provides graffiti.
func (s *Service) Graffiti(ctx context.Context, slot uint64, validatorIndex uint64) ([]byte, error) {
func (s *Service) Graffiti(ctx context.Context, slot spec.Slot, validatorIndex spec.ValidatorIndex) ([]byte, error) {
return s.graffiti, nil
}

View File

@ -15,13 +15,18 @@
package immediate
import (
"context"
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
beaconBlockSubmitter eth2client.BeaconBlockSubmitter
attestationSubmitter eth2client.AttestationSubmitter
beaconCommitteeSubscriptionsSubmitter eth2client.BeaconCommitteeSubscriptionsSubmitter
@ -46,14 +51,21 @@ func WithLogLevel(logLevel zerolog.Level) Parameter {
})
}
// WithBeaconBlockSubmitter sets the beacon block submitter
// WithClientMonitor sets the client monitor.
func WithClientMonitor(clientMonitor metrics.ClientMonitor) Parameter {
return parameterFunc(func(p *parameters) {
p.clientMonitor = clientMonitor
})
}
// WithBeaconBlockSubmitter sets the beacon block submitter.
func WithBeaconBlockSubmitter(submitter eth2client.BeaconBlockSubmitter) Parameter {
return parameterFunc(func(p *parameters) {
p.beaconBlockSubmitter = submitter
})
}
// WithAttestationSubmitter sets the attestation submitter
// WithAttestationSubmitter sets the attestation submitter.
func WithAttestationSubmitter(submitter eth2client.AttestationSubmitter) Parameter {
return parameterFunc(func(p *parameters) {
p.attestationSubmitter = submitter
@ -77,7 +89,8 @@ func WithAggregateAttestationsSubmitter(submitter eth2client.AggregateAttestatio
// 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(),
logLevel: zerolog.GlobalLevel(),
clientMonitor: nullmetrics.New(context.Background()),
}
for _, p := range params {
if params != nil {
@ -85,6 +98,9 @@ func parseAndCheckParameters(params ...Parameter) (*parameters, error) {
}
}
if parameters.clientMonitor == nil {
return nil, errors.New("no client monitor specified")
}
if parameters.beaconBlockSubmitter == nil {
return nil, errors.New("no beacon block submitter specified")
}

View File

@ -16,10 +16,12 @@ package immediate
import (
"context"
"encoding/json"
"time"
eth2client "github.com/attestantio/go-eth2-client"
api "github.com/attestantio/go-eth2-client/api/v1"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/attestantio/vouch/services/submitter"
"github.com/attestantio/vouch/services/metrics"
"github.com/pkg/errors"
"github.com/rs/zerolog"
zerologger "github.com/rs/zerolog/log"
@ -27,6 +29,7 @@ import (
// Service is the submitter for signed items.
type Service struct {
clientMonitor metrics.ClientMonitor
attestationSubmitter eth2client.AttestationSubmitter
beaconBlockSubmitter eth2client.BeaconBlockSubmitter
beaconCommitteeSubscriptionsSubmitter eth2client.BeaconCommitteeSubscriptionsSubmitter
@ -50,6 +53,7 @@ func New(ctx context.Context, params ...Parameter) (*Service, error) {
}
s := &Service{
clientMonitor: parameters.clientMonitor,
attestationSubmitter: parameters.attestationSubmitter,
beaconBlockSubmitter: parameters.beaconBlockSubmitter,
beaconCommitteeSubscriptionsSubmitter: parameters.beaconCommitteeSubscriptionsSubmitter,
@ -65,7 +69,14 @@ func (s *Service) SubmitBeaconBlock(ctx context.Context, block *spec.SignedBeaco
return errors.New("no beacon block supplied")
}
if err := s.beaconBlockSubmitter.SubmitBeaconBlock(ctx, block); err != nil {
started := time.Now()
err := s.beaconBlockSubmitter.SubmitBeaconBlock(ctx, block)
if service, isService := s.beaconBlockSubmitter.(eth2client.Service); isService {
s.clientMonitor.ClientOperation(service.Address(), "submit beacon block", err == nil, time.Since(started))
} else {
s.clientMonitor.ClientOperation("<unknown>", "submit beacon block", err == nil, time.Since(started))
}
if err != nil {
return errors.Wrap(err, "failed to submit beacon block")
}
@ -85,7 +96,14 @@ func (s *Service) SubmitAttestation(ctx context.Context, attestation *spec.Attes
return errors.New("no attestation supplied")
}
if err := s.attestationSubmitter.SubmitAttestation(ctx, attestation); err != nil {
started := time.Now()
err := s.attestationSubmitter.SubmitAttestation(ctx, attestation)
if service, isService := s.attestationSubmitter.(eth2client.Service); isService {
s.clientMonitor.ClientOperation(service.Address(), "submit attestation", err == nil, time.Since(started))
} else {
s.clientMonitor.ClientOperation("<unknown>", "submit attestation", err == nil, time.Since(started))
}
if err != nil {
return errors.Wrap(err, "failed to submit attestation")
}
@ -100,24 +118,28 @@ func (s *Service) SubmitAttestation(ctx context.Context, attestation *spec.Attes
}
// SubmitBeaconCommitteeSubscriptions submits a batch of beacon committee subscriptions.
func (s *Service) SubmitBeaconCommitteeSubscriptions(ctx context.Context, subscriptions []*submitter.BeaconCommitteeSubscription) error {
func (s *Service) SubmitBeaconCommitteeSubscriptions(ctx context.Context, subscriptions []*api.BeaconCommitteeSubscription) error {
if len(subscriptions) == 0 {
return errors.New("no beacon committee subscriptions supplied")
}
subs := make([]*eth2client.BeaconCommitteeSubscription, len(subscriptions))
subs := make([]*api.BeaconCommitteeSubscription, len(subscriptions))
for i, subscription := range subscriptions {
subs[i] = &eth2client.BeaconCommitteeSubscription{
Slot: subscription.Slot,
CommitteeIndex: subscription.CommitteeIndex,
CommitteeSize: subscription.CommitteeSize,
ValidatorIndex: subscription.ValidatorIndex,
ValidatorPubKey: subscription.ValidatorPubKey,
Aggregate: subscription.Aggregate,
SlotSelectionSignature: subscription.Signature,
subs[i] = &api.BeaconCommitteeSubscription{
Slot: subscription.Slot,
CommitteeIndex: subscription.CommitteeIndex,
CommitteesAtSlot: subscription.CommitteesAtSlot,
IsAggregator: subscription.IsAggregator,
}
}
if err := s.beaconCommitteeSubscriptionsSubmitter.SubmitBeaconCommitteeSubscriptions(ctx, subs); err != nil {
started := time.Now()
err := s.beaconCommitteeSubscriptionsSubmitter.SubmitBeaconCommitteeSubscriptions(ctx, subs)
if service, isService := s.beaconCommitteeSubscriptionsSubmitter.(eth2client.Service); isService {
s.clientMonitor.ClientOperation(service.Address(), "submit beacon committee subscription", err == nil, time.Since(started))
} else {
s.clientMonitor.ClientOperation("<unknown>", "submit beacon committee subscription", err == nil, time.Since(started))
}
if err != nil {
return errors.Wrap(err, "failed to submit beacon committee subscriptions")
}
@ -125,7 +147,7 @@ func (s *Service) SubmitBeaconCommitteeSubscriptions(ctx context.Context, subscr
// Summary counts.
aggregating := 0
for i := range subscriptions {
if subscriptions[i].Aggregate {
if subscriptions[i].IsAggregator {
aggregating++
}
}
@ -145,7 +167,14 @@ func (s *Service) SubmitAggregateAttestations(ctx context.Context, aggregates []
return errors.New("no aggregate attestations supplied")
}
if err := s.aggregateAttestationsSubmitter.SubmitAggregateAttestations(ctx, aggregates); err != nil {
started := time.Now()
err := s.aggregateAttestationsSubmitter.SubmitAggregateAttestations(ctx, aggregates)
if service, isService := s.aggregateAttestationsSubmitter.(eth2client.Service); isService {
s.clientMonitor.ClientOperation(service.Address(), "submit aggregate attestation", err == nil, time.Since(started))
} else {
s.clientMonitor.ClientOperation("<unknown>", "submit aggregate attestation", err == nil, time.Since(started))
}
if err != nil {
return errors.Wrap(err, "failed to submit aggregate attestation")
}

View File

@ -17,6 +17,7 @@ import (
"context"
"testing"
api "github.com/attestantio/go-eth2-client/api/v1"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/attestantio/vouch/mock"
"github.com/attestantio/vouch/services/submitter"
@ -330,7 +331,7 @@ func TestSubmitBeaconCommitteeSubscriptions(t *testing.T) {
tests := []struct {
name string
params []immediate.Parameter
subscriptions []*submitter.BeaconCommitteeSubscription
subscriptions []*api.BeaconCommitteeSubscription
err string
}{
{
@ -353,7 +354,7 @@ func TestSubmitBeaconCommitteeSubscriptions(t *testing.T) {
immediate.WithBeaconCommitteeSubscriptionsSubmitter(mock.NewBeaconCommitteeSubscriptionsSubmitter()),
immediate.WithAggregateAttestationsSubmitter(mock.NewAggregateAttestationsSubmitter()),
},
subscriptions: []*submitter.BeaconCommitteeSubscription{},
subscriptions: []*api.BeaconCommitteeSubscription{},
err: "no beacon committee subscriptions supplied",
},
{
@ -365,7 +366,7 @@ func TestSubmitBeaconCommitteeSubscriptions(t *testing.T) {
immediate.WithBeaconCommitteeSubscriptionsSubmitter(mock.NewErroringBeaconCommitteeSubscriptionsSubmitter()),
immediate.WithAggregateAttestationsSubmitter(mock.NewAggregateAttestationsSubmitter()),
},
subscriptions: []*submitter.BeaconCommitteeSubscription{
subscriptions: []*api.BeaconCommitteeSubscription{
{},
},
err: "failed to submit beacon committee subscriptions: error",
@ -379,7 +380,7 @@ func TestSubmitBeaconCommitteeSubscriptions(t *testing.T) {
immediate.WithBeaconCommitteeSubscriptionsSubmitter(mock.NewBeaconCommitteeSubscriptionsSubmitter()),
immediate.WithAggregateAttestationsSubmitter(mock.NewAggregateAttestationsSubmitter()),
},
subscriptions: []*submitter.BeaconCommitteeSubscription{
subscriptions: []*api.BeaconCommitteeSubscription{
{},
},
},

View File

@ -16,13 +16,18 @@
package multinode
import (
"context"
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
beaconBlockSubmitters map[string]eth2client.BeaconBlockSubmitter
attestationSubmitters map[string]eth2client.AttestationSubmitter
@ -48,6 +53,13 @@ func WithLogLevel(logLevel zerolog.Level) Parameter {
})
}
// WithClientMonitor sets the client monitor.
func WithClientMonitor(clientMonitor metrics.ClientMonitor) Parameter {
return parameterFunc(func(p *parameters) {
p.clientMonitor = clientMonitor
})
}
// WithProcessConcurrency sets the concurrency for the service.
func WithProcessConcurrency(concurrency int64) Parameter {
return parameterFunc(func(p *parameters) {
@ -86,7 +98,8 @@ func WithBeaconCommitteeSubscriptionsSubmitters(submitters map[string]eth2client
// 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(),
logLevel: zerolog.GlobalLevel(),
clientMonitor: nullmetrics.New(context.Background()),
}
for _, p := range params {
if params != nil {
@ -94,6 +107,9 @@ func parseAndCheckParameters(params ...Parameter) (*parameters, error) {
}
}
if parameters.clientMonitor == nil {
return nil, errors.New("no client monitor specified")
}
if parameters.processConcurrency == 0 {
return nil, errors.New("no process concurrency specified")
}

View File

@ -17,6 +17,7 @@ import (
"context"
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"
@ -24,6 +25,7 @@ import (
// Service is the provider for beacon block proposals.
type Service struct {
clientMonitor metrics.ClientMonitor
processConcurrency int64
beaconBlockSubmitters map[string]eth2client.BeaconBlockSubmitter
attestationSubmitters map[string]eth2client.AttestationSubmitter
@ -48,6 +50,7 @@ func New(ctx context.Context, params ...Parameter) (*Service, error) {
}
s := &Service{
clientMonitor: parameters.clientMonitor,
processConcurrency: parameters.processConcurrency,
beaconBlockSubmitters: parameters.beaconBlockSubmitters,
attestationSubmitters: parameters.attestationSubmitters,

View File

@ -17,6 +17,7 @@ import (
"context"
"encoding/json"
"sync"
"time"
eth2client "github.com/attestantio/go-eth2-client"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
@ -41,14 +42,21 @@ func (s *Service) SubmitAggregateAttestations(ctx context.Context, aggregates []
submitter eth2client.AggregateAttestationsSubmitter,
) {
defer wg.Done()
log := log.With().Str("beacon_node_address", name).Uint64("slot", aggregates[0].Message.Aggregate.Data.Slot).Logger()
log := log.With().Str("beacon_node_address", name).Uint64("slot", uint64(aggregates[0].Message.Aggregate.Data.Slot)).Logger()
if err := sem.Acquire(ctx, 1); err != nil {
log.Error().Err(err).Msg("Failed to acquire semaphore")
return
}
defer sem.Release(1)
if err := submitter.SubmitAggregateAttestations(ctx, aggregates); err != nil {
started := time.Now()
err := submitter.SubmitAggregateAttestations(ctx, aggregates)
if service, isService := submitter.(eth2client.Service); isService {
s.clientMonitor.ClientOperation(service.Address(), "submit aggregate attestation", err == nil, time.Since(started))
} else {
s.clientMonitor.ClientOperation("<unknown>", "submit aggregate attestation", err == nil, time.Since(started))
}
if err != nil {
log.Warn().Err(err).Msg("Failed to submit aggregate attestations")
return
}

View File

@ -18,6 +18,7 @@ import (
"encoding/json"
"strings"
"sync"
"time"
eth2client "github.com/attestantio/go-eth2-client"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
@ -42,14 +43,21 @@ func (s *Service) SubmitAttestation(ctx context.Context, attestation *spec.Attes
submitter eth2client.AttestationSubmitter,
) {
defer wg.Done()
log := log.With().Str("beacon_node_address", name).Uint64("slot", attestation.Data.Slot).Logger()
log := log.With().Str("beacon_node_address", name).Uint64("slot", uint64(attestation.Data.Slot)).Logger()
if err := sem.Acquire(ctx, 1); err != nil {
log.Error().Err(err).Msg("Failed to acquire semaphore")
return
}
defer sem.Release(1)
if err := submitter.SubmitAttestation(ctx, attestation); err != nil {
started := time.Now()
err := submitter.SubmitAttestation(ctx, attestation)
if service, isService := submitter.(eth2client.Service); isService {
s.clientMonitor.ClientOperation(service.Address(), "submit attestation", err == nil, time.Since(started))
} else {
s.clientMonitor.ClientOperation("<unknown>", "submit attestation", err == nil, time.Since(started))
}
if err != nil {
if strings.Contains(err.Error(), "PriorAttestationKnown") {
// Lighthouse rejects duplicate attestations. It is possible that an attestation we sent
// to another node already propagated to this node, so ignore the error.

View File

@ -17,6 +17,7 @@ import (
"context"
"encoding/json"
"sync"
"time"
eth2client "github.com/attestantio/go-eth2-client"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
@ -41,14 +42,21 @@ func (s *Service) SubmitBeaconBlock(ctx context.Context, block *spec.SignedBeaco
submitter eth2client.BeaconBlockSubmitter,
) {
defer wg.Done()
log := log.With().Str("beacon_node_address", name).Uint64("slot", block.Message.Slot).Logger()
log := log.With().Str("beacon_node_address", name).Uint64("slot", uint64(block.Message.Slot)).Logger()
if err := sem.Acquire(ctx, 1); err != nil {
log.Error().Err(err).Msg("Failed to acquire semaphore")
return
}
defer sem.Release(1)
if err := submitter.SubmitBeaconBlock(ctx, block); err != nil {
started := time.Now()
err := submitter.SubmitBeaconBlock(ctx, block)
if service, isService := submitter.(eth2client.Service); isService {
s.clientMonitor.ClientOperation(service.Address(), "submit beacon block", err == nil, time.Since(started))
} else {
s.clientMonitor.ClientOperation("<unknown>", "submit beacon block", err == nil, time.Since(started))
}
if err != nil {
log.Warn().Err(err).Msg("Failed to submit beacon block")
return
}

View File

@ -17,32 +17,20 @@ import (
"context"
"encoding/json"
"sync"
"time"
eth2client "github.com/attestantio/go-eth2-client"
"github.com/attestantio/vouch/services/submitter"
api "github.com/attestantio/go-eth2-client/api/v1"
"github.com/pkg/errors"
"golang.org/x/sync/semaphore"
)
// SubmitBeaconCommitteeSubscriptions submits a batch of beacon committee subscriptions.
func (s *Service) SubmitBeaconCommitteeSubscriptions(ctx context.Context, subscriptions []*submitter.BeaconCommitteeSubscription) error {
func (s *Service) SubmitBeaconCommitteeSubscriptions(ctx context.Context, subscriptions []*api.BeaconCommitteeSubscription) error {
if subscriptions == nil {
return errors.New("no subscriptions supplied")
}
subs := make([]*eth2client.BeaconCommitteeSubscription, len(subscriptions))
for i, subscription := range subscriptions {
subs[i] = &eth2client.BeaconCommitteeSubscription{
Slot: subscription.Slot,
CommitteeIndex: subscription.CommitteeIndex,
CommitteeSize: subscription.CommitteeSize,
ValidatorIndex: subscription.ValidatorIndex,
ValidatorPubKey: subscription.ValidatorPubKey,
Aggregate: subscription.Aggregate,
SlotSelectionSignature: subscription.Signature,
}
}
sem := semaphore.NewWeighted(s.processConcurrency)
var wg sync.WaitGroup
for name, submitter := range s.beaconCommitteeSubscriptionSubmitters {
@ -54,14 +42,21 @@ func (s *Service) SubmitBeaconCommitteeSubscriptions(ctx context.Context, subscr
submitter eth2client.BeaconCommitteeSubscriptionsSubmitter,
) {
defer wg.Done()
log := log.With().Str("beacon_node_address", name).Int("subscriptions", len(subs)).Logger()
log := log.With().Str("beacon_node_address", name).Int("subscriptions", len(subscriptions)).Logger()
if err := sem.Acquire(ctx, 1); err != nil {
log.Error().Err(err).Msg("Failed to acquire semaphore")
return
}
defer sem.Release(1)
if err := submitter.SubmitBeaconCommitteeSubscriptions(ctx, subs); err != nil {
started := time.Now()
err := submitter.SubmitBeaconCommitteeSubscriptions(ctx, subscriptions)
if service, isService := submitter.(eth2client.Service); isService {
s.clientMonitor.ClientOperation(service.Address(), "submit beacon committee subscription", err == nil, time.Since(started))
} else {
s.clientMonitor.ClientOperation("<unknown>", "submit beacon committee subscription", err == nil, time.Since(started))
}
if err != nil {
log.Warn().Err(err).Msg("Failed to submit beacon committee subscription")
return
}
@ -74,7 +69,7 @@ func (s *Service) SubmitBeaconCommitteeSubscriptions(ctx context.Context, subscr
// Summary counts.
aggregating := 0
for i := range subscriptions {
if subscriptions[i].Aggregate {
if subscriptions[i].IsAggregator {
aggregating++
}
}

View File

@ -17,8 +17,8 @@ import (
"context"
"encoding/json"
api "github.com/attestantio/go-eth2-client/api/v1"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/attestantio/vouch/services/submitter"
"github.com/pkg/errors"
"github.com/rs/zerolog"
zerologger "github.com/rs/zerolog/log"
@ -81,7 +81,7 @@ func (s *Service) SubmitAttestation(ctx context.Context, attestation *spec.Attes
}
// SubmitBeaconCommitteeSubscriptions submits a batch of beacon committee subscriptions.
func (s *Service) SubmitBeaconCommitteeSubscriptions(ctx context.Context, subscriptions []*submitter.BeaconCommitteeSubscription) error {
func (s *Service) SubmitBeaconCommitteeSubscriptions(ctx context.Context, subscriptions []*api.BeaconCommitteeSubscription) error {
if subscriptions == nil {
return errors.New("no subscriptions supplied")
}
@ -90,7 +90,7 @@ func (s *Service) SubmitBeaconCommitteeSubscriptions(ctx context.Context, subscr
// Summary counts.
aggregating := 0
for i := range subscriptions {
if subscriptions[i].Aggregate {
if subscriptions[i].IsAggregator {
aggregating++
}
}

View File

@ -16,6 +16,7 @@ package submitter
import (
"context"
api "github.com/attestantio/go-eth2-client/api/v1"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
)
@ -34,21 +35,10 @@ type BeaconBlockSubmitter interface {
SubmitBeaconBlock(ctx context.Context, block *spec.SignedBeaconBlock) error
}
// BeaconCommitteeSubscription is a subscription for a particular beacon committee at a given time.
type BeaconCommitteeSubscription struct {
Slot uint64
CommitteeIndex uint64
CommitteeSize uint64
ValidatorIndex uint64
ValidatorPubKey []byte
Aggregate bool
Signature []byte
}
// BeaconCommitteeSubscriptionsSubmitter is the interface for a submitter of beacon committee subscriptions.
type BeaconCommitteeSubscriptionsSubmitter interface {
// SubmitBeaconCommitteeSubscription submits a batch of beacon committee subscriptions.
SubmitBeaconCommitteeSubscriptions(ctx context.Context, subscriptions []*BeaconCommitteeSubscription) error
SubmitBeaconCommitteeSubscriptions(ctx context.Context, subscriptions []*api.BeaconCommitteeSubscription) error
}
// AggregateAttestationsSubmitter is the interface for a submitter of aggregate attestations.

View File

@ -23,12 +23,13 @@ import (
"golang.org/x/sync/semaphore"
)
// BeaconBlockProposal provies the best beacon block proposal from a number of beacon nodes.
func (s *Service) BeaconBlockProposal(ctx context.Context, slot uint64, randaoReveal []byte, graffiti []byte) (*spec.BeaconBlock, error) {
// BeaconBlockProposal provides the best beacon block proposal from a number of beacon nodes.
func (s *Service) BeaconBlockProposal(ctx context.Context, slot spec.Slot, randaoReveal spec.BLSSignature, graffiti []byte) (*spec.BeaconBlock, error) {
var mu sync.Mutex
bestScore := float64(0)
var bestProposal *spec.BeaconBlock
started := time.Now()
sem := semaphore.NewWeighted(s.processConcurrency)
var wg sync.WaitGroup
for name, provider := range s.beaconBlockProposalProviders {
@ -41,10 +42,10 @@ func (s *Service) BeaconBlockProposal(ctx context.Context, slot uint64, randaoRe
return
}
defer sem.Release(1)
log := log.With().Str("provider", name).Uint64("slot", slot).Logger()
log := log.With().Str("provider", name).Uint64("slot", uint64(slot)).Logger()
log.Trace().Dur("elapsed", time.Since(started)).Msg("Obtained semaphore")
opCtx, cancel := context.WithTimeout(ctx, s.timeout)
started := time.Now()
proposal, err := provider.BeaconBlockProposal(opCtx, slot, randaoReveal, graffiti)
s.clientMonitor.ClientOperation(name, "beacon block proposal", err == nil, time.Since(started))
if err != nil {

View File

@ -18,6 +18,7 @@ import (
"testing"
eth2client "github.com/attestantio/go-eth2-client"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/attestantio/vouch/mock"
"github.com/attestantio/vouch/services/metrics/null"
"github.com/attestantio/vouch/strategies/beaconblockproposal/best"
@ -42,10 +43,14 @@ func TestBeaconBlockProposal(t *testing.T) {
block, err := service.BeaconBlockProposal(ctx,
12345,
[]byte{
spec.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,
)
require.NoError(t, err)

View File

@ -35,11 +35,11 @@ func scoreBeaconBlockProposal(ctx context.Context, name string, blockProposal *s
// We need to avoid duplicates in attestations.
// Map is slot -> committee index -> validator committee index -> attested.
attested := make(map[uint64]map[uint64]map[uint64]bool)
attested := make(map[spec.Slot]map[spec.CommitteeIndex]map[uint64]bool)
for _, attestation := range blockProposal.Body.Attestations {
slotAttested, exists := attested[attestation.Data.Slot]
if !exists {
slotAttested = make(map[uint64]map[uint64]bool)
slotAttested = make(map[spec.CommitteeIndex]map[uint64]bool)
attested[attestation.Data.Slot] = slotAttested
}
committeeAttested, exists := slotAttested[attestation.Data.Index]
@ -84,7 +84,7 @@ func scoreBeaconBlockProposal(ctx context.Context, name string, blockProposal *s
attesterSlashingScore := slashingWeight * float64(indicesSlashed)
log.Trace().
Uint64("slot", blockProposal.Slot).
Uint64("slot", uint64(blockProposal.Slot)).
Str("provider", name).
Float64("immediate_attestations", immediateAttestationScore).
Float64("attestations", attestationScore).

View File

@ -1,5 +1,5 @@
// Copyright © 2020 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// Licensed )junder 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
//
@ -57,8 +57,8 @@ func New(ctx context.Context, params ...Parameter) (*Service, error) {
return s, nil
}
// BeaconBlockProposal provies the first beacon block proposal from a number of beacon nodes.
func (s *Service) BeaconBlockProposal(ctx context.Context, slot uint64, randaoReveal []byte, graffiti []byte) (*spec.BeaconBlock, error) {
// BeaconBlockProposal provides the first beacon block proposal from a number of beacon nodes.
func (s *Service) BeaconBlockProposal(ctx context.Context, slot spec.Slot, randaoReveal spec.BLSSignature, graffiti []byte) (*spec.BeaconBlock, error) {
// We create a cancelable context with a timeout. As soon as the first provider has responded we
// cancel the context to cancel the other requests.
ctx, cancel := context.WithTimeout(ctx, s.timeout)
@ -66,7 +66,7 @@ func (s *Service) BeaconBlockProposal(ctx context.Context, slot uint64, randaoRe
proposalCh := make(chan *spec.BeaconBlock, 1)
for name, provider := range s.beaconBlockProposalProviders {
go func(ctx context.Context, name string, provider eth2client.BeaconBlockProposalProvider, ch chan *spec.BeaconBlock) {
log := log.With().Str("provider", name).Uint64("slot", slot).Logger()
log := log.With().Str("provider", name).Uint64("slot", uint64(slot)).Logger()
started := time.Now()
proposal, err := provider.BeaconBlockProposal(ctx, slot, randaoReveal, graffiti)

View File

@ -506,6 +506,24 @@ XDCQeaEUOuLjokRojHrN27ghz3wJoUJzTdjtHZ+yE9s2cW9VXRUxkun0aLcQd/iY
xvXEII1qCvhI4mmWvbcepvtswQmTEeOroM/27/IIEAOvTyqd6rDi2A==
-----END RSA PRIVATE KEY-----`
// SignerCerts gives access to signer certificates by ID.
var SignerCerts = map[uint64][]byte{
1: []byte(SignerTest01Crt),
2: []byte(SignerTest02Crt),
3: []byte(SignerTest03Crt),
4: []byte(SignerTest04Crt),
5: []byte(SignerTest05Crt),
}
// SignerKeys gives access to signer keys by ID.
var SignerKeys = map[uint64][]byte{
1: []byte(SignerTest01Key),
2: []byte(SignerTest02Key),
3: []byte(SignerTest03Key),
4: []byte(SignerTest04Key),
5: []byte(SignerTest05Key),
}
// SetupCerts sets up a number of certificates on-disk in the provided location.
func SetupCerts(base string) error {
if err := ioutil.WriteFile(filepath.Join(base, "ca.crt"), []byte(CACrt), 0600); err != nil {

85
testutil/bytes.go Normal file
View File

@ -0,0 +1,85 @@
// Copyright © 2020 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 testutil
import (
"encoding/hex"
"strings"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
)
// HexToBytes converts a hex string to a byte array.
// This should only be used for pre-defined test strings; it will panic if the input is invalid.
func HexToBytes(input string) []byte {
res, err := hex.DecodeString(strings.TrimPrefix(input, "0x"))
if err != nil {
panic(err)
}
return res
}
// HexToPubKey converts a hex string to a spec public key.
// This should only be used for pre-defined test strings; it will panic if the input is invalid.
func HexToPubKey(input string) spec.BLSPubKey {
data := HexToBytes(input)
var res spec.BLSPubKey
copy(res[:], data)
return res
}
// HexToSignature converts a hex string to a spec signature.
// This should only be used for pre-defined test strings; it will panic if the input is invalid.
func HexToSignature(input string) spec.BLSSignature {
data := HexToBytes(input)
var res spec.BLSSignature
copy(res[:], data)
return res
}
// HexToDomainType converts a hex string to a spec domain type.
// This should only be used for pre-defined test strings; it will panic if the input is invalid.
func HexToDomainType(input string) spec.DomainType {
data := HexToBytes(input)
var res spec.DomainType
copy(res[:], data)
return res
}
// HexToDomain converts a hex string to a spec domain.
// This should only be used for pre-defined test strings; it will panic if the input is invalid.
func HexToDomain(input string) spec.Domain {
data := HexToBytes(input)
var res spec.Domain
copy(res[:], data)
return res
}
// HexToVersion converts a hex string to a spec version.
// This should only be used for pre-defined test strings; it will panic if the input is invalid.
func HexToVersion(input string) spec.Version {
data := HexToBytes(input)
var res spec.Version
copy(res[:], data)
return res
}
// HexToRoot converts a hex string to a spec root.
// This should only be used for pre-defined test strings; it will panic if the input is invalid.
func HexToRoot(input string) spec.Root {
data := HexToBytes(input)
var res spec.Root
copy(res[:], data)
return res
}