mirror of https://github.com/certusone/vouch.git
Initial work on support of standard API
This commit is contained in:
parent
796cb6348f
commit
4e5fbf18ba
33
go.mod
33
go.mod
|
@ -3,19 +3,22 @@ module github.com/attestantio/vouch
|
|||
go 1.14
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.70.0 // indirect
|
||||
cloud.google.com/go v0.72.0 // indirect
|
||||
github.com/OneOfOne/xxhash v1.2.5 // indirect
|
||||
github.com/attestantio/dirk v0.9.1
|
||||
github.com/attestantio/go-eth2-client v0.6.8
|
||||
github.com/aws/aws-sdk-go v1.35.14
|
||||
github.com/ferranbt/fastssz v0.0.0-20201020132831-68dc48984fd3
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.15.2 // indirect
|
||||
github.com/herumi/bls-eth-go-binary v0.0.0-20201019012252-4b463a10c225
|
||||
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/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.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
|
||||
|
@ -27,19 +30,19 @@ require (
|
|||
github.com/uber/jaeger-client-go v2.25.0+incompatible
|
||||
github.com/wealdtech/go-bytesutil v1.1.1
|
||||
github.com/wealdtech/go-eth2-types/v2 v2.5.1
|
||||
github.com/wealdtech/go-eth2-wallet v1.14.2
|
||||
github.com/wealdtech/go-eth2-wallet-dirk v1.1.2
|
||||
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.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
|
||||
golang.org/x/net v0.0.0-20201026091529-146b70c837a4 // 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
|
||||
google.golang.org/genproto v0.0.0-20201022181438-0ff5f38871d5 // indirect
|
||||
google.golang.org/grpc v1.33.1
|
||||
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
|
||||
)
|
||||
|
||||
replace github.com/attestantio/go-eth2-client => ../go-eth2-client
|
||||
|
|
85
go.sum
85
go.sum
|
@ -16,6 +16,8 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb
|
|||
cloud.google.com/go v0.68.0/go.mod h1:91NO4SCDjUfe1zeC0f4/dpckkUNpuNEyqm4X2KLrzNQ=
|
||||
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=
|
||||
|
@ -66,6 +68,10 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj
|
|||
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
|
||||
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=
|
||||
|
@ -73,6 +79,10 @@ github.com/aws/aws-sdk-go v1.33.17/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZve
|
|||
github.com/aws/aws-sdk-go v1.35.7/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/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
|
@ -135,12 +145,17 @@ 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/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/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/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
|
@ -156,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=
|
||||
|
@ -209,10 +232,13 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
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/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=
|
||||
|
@ -222,6 +248,7 @@ 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/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
|
@ -247,6 +274,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t
|
|||
github.com/grpc-ecosystem/grpc-gateway v1.13.0/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c=
|
||||
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=
|
||||
|
@ -275,6 +304,8 @@ github.com/herumi/bls-eth-go-binary v0.0.0-20200706085701-832d8c2c0f7d/go.mod h1
|
|||
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-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=
|
||||
|
@ -315,6 +346,7 @@ github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn
|
|||
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=
|
||||
|
@ -323,8 +355,17 @@ github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP
|
|||
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=
|
||||
|
@ -420,6 +461,8 @@ github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt2
|
|||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
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/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
|
@ -534,14 +577,20 @@ github.com/wealdtech/go-eth2-util v1.6.0 h1:l2OR0SqfYdEnb1I1Ggnk0w+B9/LA5aHdQ2KK
|
|||
github.com/wealdtech/go-eth2-util v1.6.0/go.mod h1:0PGWeWWc6qjky/aNjdPdguJdZ2HSEHHCA+3cTjvT+Hk=
|
||||
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 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-distributed v1.1.2 h1:ABE1tyxGfXAPPphQ32dval7+9aP61BsIdtvuOJr3azY=
|
||||
|
@ -557,6 +606,8 @@ github.com/wealdtech/go-eth2-wallet-hd/v2 v2.5.1 h1:QoIyyVQ/vaztkeG88L1vOZKkKMM4
|
|||
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.5.1/go.mod h1:smW8Ca0x7JO41urG0sgrlJALb1mGTSagnqaapMWiHfk=
|
||||
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=
|
||||
|
@ -569,6 +620,8 @@ github.com/wealdtech/go-eth2-wallet-store-s3 v1.9.0 h1:O5211UskLbK1WDecTXwugUlIN
|
|||
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-store-scratch v1.6.1 h1:vv9lR8K76FUSNbzUU25MN4HNhZIBBI1kJBNfHq2WjRY=
|
||||
|
@ -627,6 +680,8 @@ golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPh
|
|||
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=
|
||||
|
@ -698,9 +753,13 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R
|
|||
golang.org/x/net v0.0.0-20200822124328-c89045814202/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/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=
|
||||
|
@ -708,6 +767,8 @@ golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4Iltr
|
|||
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=
|
||||
|
@ -729,6 +790,7 @@ 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=
|
||||
|
@ -741,11 +803,14 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
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=
|
||||
|
@ -768,12 +833,20 @@ golang.org/x/sys v0.0.0-20201014080544-cc95f250f6bc/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/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/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=
|
||||
|
@ -830,6 +903,7 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
|
|||
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||
golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -855,6 +929,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513
|
|||
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=
|
||||
|
@ -905,6 +981,11 @@ google.golang.org/genproto v0.0.0-20201013134114-7f9ee70cb474/go.mod h1:FWY/as6D
|
|||
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=
|
||||
|
@ -929,6 +1010,8 @@ 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=
|
||||
|
@ -951,6 +1034,8 @@ 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/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.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
|
|
14
main.go
14
main.go
|
@ -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.AggregateAttestationProvider)),
|
||||
standardattestationaggregator.WithAggregateAttestationsSubmitter(submitterStrategy.(submitter.AggregateAttestationsSubmitter)),
|
||||
aggregationAttester,
|
||||
standardattestationaggregator.WithAggregateAttestationsSubmitter(eth2Client.(eth2client.AggregateAttestationsSubmitter)),
|
||||
standardattestationaggregator.WithMonitor(monitor.(metrics.AttestationAggregationMonitor)),
|
||||
standardattestationaggregator.WithValidatingAccountsProvider(accountManager.(accountmanager.ValidatingAccountsProvider)),
|
||||
)
|
||||
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
Status: api.ValidatorStateActiveOngoing,
|
||||
Validator: &spec.Validator{
|
||||
PublicKey: _byte(pubKey),
|
||||
PublicKey: _blsPubKey(pubKey),
|
||||
WithdrawalCredentials: _byte(withdrwalCredentials),
|
||||
EffectiveBalance: 32000000,
|
||||
Slashed: false,
|
||||
|
@ -530,8 +537,8 @@ func _epochValidator(index uint64, pubKey string, withdrwalCredentials string) *
|
|||
}
|
||||
|
||||
// Validators is a mock.
|
||||
func (m *ValidatorsProvider) Validators(ctx context.Context, stateID string, validators []uint64) (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"),
|
||||
|
@ -632,8 +639,8 @@ func (m *ValidatorsProvider) Validators(ctx context.Context, stateID string, val
|
|||
}
|
||||
|
||||
// ValidatorsByPubKey is a mock.
|
||||
func (m *ValidatorsProvider) ValidatorsByPubKey(ctx context.Context, stateID string, validators [][]byte) (map[uint64]*api.Validator, error) {
|
||||
return map[uint64]*api.Validator{
|
||||
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"),
|
||||
|
@ -742,8 +749,8 @@ func NewValidatorsWithoutBalanceProvider() eth2client.ValidatorsProvider {
|
|||
}
|
||||
|
||||
// Validators is a mock.
|
||||
func (m *ValidatorsWithoutBalanceProvider) Validators(ctx context.Context, stateID string, validators []uint64) (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"),
|
||||
|
@ -844,8 +851,8 @@ func (m *ValidatorsWithoutBalanceProvider) Validators(ctx context.Context, state
|
|||
}
|
||||
|
||||
// ValidatorsByPubKey is a mock.
|
||||
func (m *ValidatorsWithoutBalanceProvider) ValidatorsByPubKey(ctx context.Context, stateID string, validators [][]byte) (map[uint64]*api.Validator, error) {
|
||||
return map[uint64]*api.Validator{
|
||||
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"),
|
||||
|
@ -946,8 +953,8 @@ func (m *ValidatorsWithoutBalanceProvider) ValidatorsByPubKey(ctx context.Contex
|
|||
}
|
||||
|
||||
// ValidatorsWithoutBalance is a mock.
|
||||
func (m *ValidatorsWithoutBalanceProvider) ValidatorsWithoutBalance(ctx context.Context, stateID string, validators []eth2client.ValidatorIDProvider) (map[uint64]*api.Validator, error) {
|
||||
res := map[uint64]*api.Validator{
|
||||
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"),
|
||||
|
|
|
@ -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 ¶meters, nil
|
||||
|
|
|
@ -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 {
|
||||
|
@ -161,8 +162,9 @@ func (s *Service) UpdateAccountsState(ctx context.Context) error {
|
|||
log.Trace().Msg("No unactivated keys")
|
||||
return nil
|
||||
}
|
||||
// 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[uint64]*api.Validator
|
||||
var validators map[spec.ValidatorIndex]*api.Validator
|
||||
var err error
|
||||
if validatorsWithoutBalanceProvider, isProvider := s.validatorsProvider.(eth2client.ValidatorsWithoutBalanceProvider); isProvider {
|
||||
started := time.Now()
|
||||
|
@ -177,7 +179,7 @@ func (s *Service) UpdateAccountsState(ctx context.Context) error {
|
|||
}
|
||||
} else {
|
||||
started := time.Now()
|
||||
validatorIDs := make([]uint64, 0, len(s.accounts))
|
||||
validatorIDs := make([]spec.ValidatorIndex, 0, len(s.accounts))
|
||||
for _, account := range s.accounts {
|
||||
if !account.state.HasActivated() {
|
||||
index, err := account.Index(ctx)
|
||||
|
@ -230,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")
|
||||
|
@ -240,7 +242,7 @@ func (s *Service) RefreshAccounts(ctx context.Context) error {
|
|||
}
|
||||
|
||||
// Update indices for accounts.
|
||||
pubKeys := make([][]byte, 0, len(accounts))
|
||||
pubKeys := make([]spec.BLSPubKey, 0, len(accounts))
|
||||
for _, account := range accounts {
|
||||
pubKey, err := account.PubKey(ctx)
|
||||
if err != nil {
|
||||
|
@ -326,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
|
||||
}
|
||||
|
@ -355,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()
|
||||
|
@ -410,12 +410,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) {
|
||||
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)
|
||||
|
@ -441,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())
|
||||
|
@ -466,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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
|
@ -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 ¶meters, nil
|
||||
|
|
|
@ -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,22 +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([]uint64, 0, len(s.accounts))
|
||||
validatorIndices := make([]spec.ValidatorIndex, 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)
|
||||
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")
|
||||
}
|
||||
|
@ -184,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")
|
||||
|
@ -194,7 +195,7 @@ func (s *Service) RefreshAccounts(ctx context.Context) error {
|
|||
}
|
||||
|
||||
// Update indices for accounts.
|
||||
pubKeys := make([][]byte, 0, len(accounts))
|
||||
pubKeys := make([]spec.BLSPubKey, 0, len(accounts))
|
||||
for _, account := range accounts {
|
||||
pubKey, err := account.PubKey(ctx)
|
||||
if err != nil {
|
||||
|
@ -238,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
|
||||
}
|
||||
|
||||
|
@ -267,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()
|
||||
|
@ -321,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)
|
||||
|
@ -353,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())
|
||||
|
@ -393,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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"`
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -15,24 +15,26 @@ package attestationaggregator
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
spec "github.com/attestantio/go-eth2-client/spec/phase0"
|
||||
)
|
||||
|
||||
// Duty contains information about an attestation aggregation duty.
|
||||
type Duty struct {
|
||||
// Slot is the slot of the attestation aggregation; required for obtaining the aggregate.
|
||||
Slot uint64
|
||||
Slot spec.Slot
|
||||
// Attestation data root is the root of the attestation to be aggregated; required for obtaining the aggregate.
|
||||
AttestationDataRoot []byte
|
||||
AttestationDataRoot spec.Root
|
||||
// ValidatorIndex is the index of the validator carrying out the aggregation; reuqired for submitting the aggregate.
|
||||
ValidatorIndex uint64
|
||||
ValidatorIndex spec.ValidatorIndex
|
||||
// SlotSignature is the signature of the slot by the validator carrying out the aggregation; reuqired for submitting the aggregate.
|
||||
SlotSignature []byte
|
||||
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.
|
||||
|
|
|
@ -28,6 +28,7 @@ type parameters struct {
|
|||
targetAggregatorsPerCommitteeProvider eth2client.TargetAggregatorsPerCommitteeProvider
|
||||
validatingAccountsProvider accountmanager.ValidatingAccountsProvider
|
||||
aggregateAttestationProvider eth2client.AggregateAttestationProvider
|
||||
prysmAggregateAttestationProvider eth2client.PrysmAggregateAttestationProvider
|
||||
aggregateAttestationsSubmitter submitter.AggregateAttestationsSubmitter
|
||||
}
|
||||
|
||||
|
@ -77,6 +78,13 @@ func WithAggregateAttestationDataProvider(provider eth2client.AggregateAttestati
|
|||
})
|
||||
}
|
||||
|
||||
// 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 {
|
||||
|
|
|
@ -33,11 +33,12 @@ import (
|
|||
|
||||
// Service is an attestation aggregator.
|
||||
type Service struct {
|
||||
monitor metrics.AttestationAggregationMonitor
|
||||
targetAggregatorsPerCommittee uint64
|
||||
validatingAccountsProvider accountmanager.ValidatingAccountsProvider
|
||||
aggregateAttestationProvider eth2client.AggregateAttestationProvider
|
||||
aggregateAttestationsSubmitter submitter.AggregateAttestationsSubmitter
|
||||
monitor metrics.AttestationAggregationMonitor
|
||||
targetAggregatorsPerCommittee uint64
|
||||
validatingAccountsProvider accountmanager.ValidatingAccountsProvider
|
||||
aggregateAttestationProvider eth2client.AggregateAttestationProvider
|
||||
prysmAggregateAttestationProvider eth2client.PrysmAggregateAttestationProvider
|
||||
aggregateAttestationsSubmitter submitter.AggregateAttestationsSubmitter
|
||||
}
|
||||
|
||||
// module-wide log.
|
||||
|
@ -62,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
|
||||
|
@ -82,20 +84,32 @@ func (s *Service) Aggregate(ctx context.Context, data interface{}) {
|
|||
s.monitor.AttestationAggregationCompleted(started, "failed")
|
||||
return
|
||||
}
|
||||
log := log.With().Uint64("slot", duty.Slot).Str("attestation_data_root", fmt.Sprintf("%#x", duty.AttestationDataRoot)).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.AggregateAttestation(ctx, duty.Slot, duty.AttestationDataRoot)
|
||||
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.AccountsByIndex(ctx, []uint64{duty.ValidatorIndex})
|
||||
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")
|
||||
|
@ -126,7 +140,7 @@ func (s *Service) Aggregate(ctx context.Context, data interface{}) {
|
|||
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")
|
||||
|
@ -155,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.
|
||||
|
@ -163,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)
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ 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.
|
||||
|
@ -27,11 +28,11 @@ func MergeDuties(ctx context.Context, attesterDuties []*api.AttesterDuty) ([]*Du
|
|||
return duties, nil
|
||||
}
|
||||
|
||||
validatorIndices := make(map[uint64][]uint64)
|
||||
committeeIndices := make(map[uint64][]uint64)
|
||||
validatorCommitteeIndices := make(map[uint64][]uint64)
|
||||
committeeLengths := make(map[uint64]map[uint64]uint64)
|
||||
committeesAtSlots := make(map[uint64]uint64)
|
||||
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.
|
||||
|
@ -62,9 +63,9 @@ 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)
|
||||
|
|
|
@ -22,16 +22,23 @@ import (
|
|||
|
||||
// Duty contains information about a beacon block attester duty.
|
||||
type Duty struct {
|
||||
slot uint64
|
||||
slot spec.Slot
|
||||
committeesAtSlot uint64
|
||||
validatorIndices []uint64
|
||||
committeeIndices []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, committeesAtSlot 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 {
|
||||
|
@ -50,7 +57,7 @@ func NewDuty(ctx context.Context, slot uint64, committeesAtSlot uint64, validato
|
|||
}
|
||||
|
||||
// Slot provides the slot for the beacon block attester.
|
||||
func (d *Duty) Slot() uint64 {
|
||||
func (d *Duty) Slot() spec.Slot {
|
||||
return d.slot
|
||||
}
|
||||
|
||||
|
@ -60,12 +67,12 @@ func (d *Duty) CommitteesAtSlot() uint64 {
|
|||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
|
@ -75,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]
|
||||
}
|
||||
|
||||
|
@ -84,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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 := ðpb.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")
|
||||
|
|
|
@ -18,6 +18,7 @@ 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"
|
||||
)
|
||||
|
||||
|
@ -26,12 +27,11 @@ type Subscription struct {
|
|||
Duty *api.AttesterDuty
|
||||
IsAggregator bool
|
||||
// TODO is this in the correct place?
|
||||
Signature []byte
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -20,6 +20,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/attestationaggregator"
|
||||
"github.com/attestantio/vouch/services/attester"
|
||||
|
@ -71,13 +72,16 @@ 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")
|
||||
|
||||
validatorIDs := make([]uint64, len(accounts))
|
||||
validatorIDs := make([]spec.ValidatorIndex, len(accounts))
|
||||
var err error
|
||||
for i, account := range accounts {
|
||||
validatorIDs[i], err = account.Index(ctx)
|
||||
|
@ -149,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 {
|
||||
|
@ -211,7 +215,7 @@ func (s *Service) calculateSubscriptionInfo(ctx context.Context,
|
|||
}
|
||||
subscriptionInfoMutex.Lock()
|
||||
if _, exists := subscriptionInfo[duty.Slot()]; !exists {
|
||||
subscriptionInfo[duty.Slot()] = make(map[uint64]*beaconcommitteesubscriber.Subscription)
|
||||
subscriptionInfo[duty.Slot()] = make(map[spec.CommitteeIndex]*beaconcommitteesubscriber.Subscription)
|
||||
}
|
||||
subscriptionInfo[duty.Slot()][duty.CommitteeIndices()[i]] = &beaconcommitteesubscriber.Subscription{
|
||||
Duty: &api.AttesterDuty{
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
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"
|
||||
|
@ -25,12 +26,12 @@ 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")
|
||||
|
||||
validatorIDs := make([]uint64, len(accounts))
|
||||
validatorIDs := make([]spec.ValidatorIndex, len(accounts))
|
||||
var err error
|
||||
for i, account := range accounts {
|
||||
validatorIDs[i], err = account.Index(ctx)
|
||||
|
@ -47,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)
|
||||
|
@ -63,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,
|
||||
|
@ -114,29 +115,30 @@ 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.IsAggregator {
|
||||
|
@ -148,7 +150,7 @@ func (s *Service) AttestAndScheduleAggregate(ctx context.Context, data interface
|
|||
}
|
||||
aggregatorDuty := &attestationaggregator.Duty{
|
||||
Slot: info.Duty.Slot,
|
||||
AttestationDataRoot: attestationDataRoot[:],
|
||||
AttestationDataRoot: attestationDataRoot,
|
||||
ValidatorIndex: info.Duty.ValidatorIndex,
|
||||
SlotSignature: info.Signature,
|
||||
}
|
||||
|
|
|
@ -25,20 +25,25 @@ import (
|
|||
func (s *Service) HandleHeadEvent(event *api.Event) {
|
||||
ctx := context.Background()
|
||||
data := event.Data.(*api.HeadEvent)
|
||||
log.Trace().Uint64("slot", data.Slot).Msg("Received head event")
|
||||
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", data.Slot).Msg("Kicking off attestations for slot early due to receiving relevant block")
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -17,18 +17,19 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
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) {
|
||||
log.Trace().Msg("Creating proposer jobs")
|
||||
|
||||
validatorIDs := make([]uint64, len(accounts))
|
||||
validatorIDs := make([]spec.ValidatorIndex, len(accounts))
|
||||
var err error
|
||||
for i, account := range accounts {
|
||||
validatorIDs[i], err = account.Index(ctx)
|
||||
|
@ -46,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)
|
||||
|
@ -65,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,
|
||||
|
|
|
@ -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,16 +94,15 @@ 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),
|
||||
}
|
||||
|
||||
// Subscribe to head events.
|
||||
// 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")
|
||||
}
|
||||
|
||||
// TODO subscribe to reorg events.
|
||||
|
||||
// Subscriptions are usually updated one epoch in advance, but as we're
|
||||
// just starting we don't have subscriptions (or subscription information)
|
||||
// for this or the next epoch; fetch them now.
|
||||
|
@ -208,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
|
||||
}
|
||||
|
@ -265,7 +264,6 @@ func (s *Service) epochTicker(ctx context.Context, data interface{}) {
|
|||
epochTickerData.atGenesis = false
|
||||
}
|
||||
|
||||
// TODO REMOVE
|
||||
// // 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() {
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ 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
|
||||
|
|
|
@ -43,7 +43,7 @@ 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
|
||||
|
|
|
@ -42,7 +42,7 @@ 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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
@ -58,7 +58,7 @@ func New(ctx context.Context, params ...Parameter) (*Service, error) {
|
|||
}
|
||||
|
||||
// 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) {
|
||||
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)
|
||||
|
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue