Validator RPC Accounts Voluntary Exit (#8776)

* begin voluntary exits RPC

* added in exit logic

* complete exit func

* revert

* capitalize

* revert

* import

* rpc voluntary exit test

* fmt
This commit is contained in:
Raul Jordan
2021-04-16 02:46:38 -05:00
committed by GitHub
parent a4ff97d24b
commit 02a8ae7f36
14 changed files with 1430 additions and 627 deletions

View File

@@ -6,10 +6,6 @@ package ethereum_validator_accounts_v2
import ( import (
context "context" context "context"
fmt "fmt" fmt "fmt"
io "io"
math "math"
math_bits "math/bits"
_ "github.com/gogo/protobuf/gogoproto" _ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto" proto "github.com/gogo/protobuf/proto"
empty "github.com/golang/protobuf/ptypes/empty" empty "github.com/golang/protobuf/ptypes/empty"
@@ -19,6 +15,9 @@ import (
grpc "google.golang.org/grpc" grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes" codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status" status "google.golang.org/grpc/status"
io "io"
math "math"
math_bits "math/bits"
) )
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.

View File

@@ -6,10 +6,6 @@ package ethereum_validator_accounts_v2
import ( import (
context "context" context "context"
fmt "fmt" fmt "fmt"
io "io"
math "math"
math_bits "math/bits"
proto "github.com/gogo/protobuf/proto" proto "github.com/gogo/protobuf/proto"
empty "github.com/golang/protobuf/ptypes/empty" empty "github.com/golang/protobuf/ptypes/empty"
v1alpha1 "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" v1alpha1 "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
@@ -18,6 +14,9 @@ import (
grpc "google.golang.org/grpc" grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes" codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status" status "google.golang.org/grpc/status"
io "io"
math "math"
math_bits "math/bits"
) )
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
@@ -1421,6 +1420,100 @@ func (m *BeaconStatusResponse) GetChainHead() *v1alpha1.ChainHead {
return nil return nil
} }
type VoluntaryExitRequest struct {
PublicKeys [][]byte `protobuf:"bytes,1,rep,name=public_keys,json=publicKeys,proto3" json:"public_keys,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *VoluntaryExitRequest) Reset() { *m = VoluntaryExitRequest{} }
func (m *VoluntaryExitRequest) String() string { return proto.CompactTextString(m) }
func (*VoluntaryExitRequest) ProtoMessage() {}
func (*VoluntaryExitRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_8a5153635bfe042e, []int{22}
}
func (m *VoluntaryExitRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *VoluntaryExitRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_VoluntaryExitRequest.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *VoluntaryExitRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_VoluntaryExitRequest.Merge(m, src)
}
func (m *VoluntaryExitRequest) XXX_Size() int {
return m.Size()
}
func (m *VoluntaryExitRequest) XXX_DiscardUnknown() {
xxx_messageInfo_VoluntaryExitRequest.DiscardUnknown(m)
}
var xxx_messageInfo_VoluntaryExitRequest proto.InternalMessageInfo
func (m *VoluntaryExitRequest) GetPublicKeys() [][]byte {
if m != nil {
return m.PublicKeys
}
return nil
}
type VoluntaryExitResponse struct {
ExitedKeys [][]byte `protobuf:"bytes,1,rep,name=exited_keys,json=exitedKeys,proto3" json:"exited_keys,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *VoluntaryExitResponse) Reset() { *m = VoluntaryExitResponse{} }
func (m *VoluntaryExitResponse) String() string { return proto.CompactTextString(m) }
func (*VoluntaryExitResponse) ProtoMessage() {}
func (*VoluntaryExitResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_8a5153635bfe042e, []int{23}
}
func (m *VoluntaryExitResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *VoluntaryExitResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_VoluntaryExitResponse.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *VoluntaryExitResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_VoluntaryExitResponse.Merge(m, src)
}
func (m *VoluntaryExitResponse) XXX_Size() int {
return m.Size()
}
func (m *VoluntaryExitResponse) XXX_DiscardUnknown() {
xxx_messageInfo_VoluntaryExitResponse.DiscardUnknown(m)
}
var xxx_messageInfo_VoluntaryExitResponse proto.InternalMessageInfo
func (m *VoluntaryExitResponse) GetExitedKeys() [][]byte {
if m != nil {
return m.ExitedKeys
}
return nil
}
type BackupAccountsRequest struct { type BackupAccountsRequest struct {
PublicKeys [][]byte `protobuf:"bytes,1,rep,name=public_keys,json=publicKeys,proto3" json:"public_keys,omitempty"` PublicKeys [][]byte `protobuf:"bytes,1,rep,name=public_keys,json=publicKeys,proto3" json:"public_keys,omitempty"`
BackupPassword string `protobuf:"bytes,2,opt,name=backup_password,json=backupPassword,proto3" json:"backup_password,omitempty"` BackupPassword string `protobuf:"bytes,2,opt,name=backup_password,json=backupPassword,proto3" json:"backup_password,omitempty"`
@@ -1433,7 +1526,7 @@ func (m *BackupAccountsRequest) Reset() { *m = BackupAccountsRequest{} }
func (m *BackupAccountsRequest) String() string { return proto.CompactTextString(m) } func (m *BackupAccountsRequest) String() string { return proto.CompactTextString(m) }
func (*BackupAccountsRequest) ProtoMessage() {} func (*BackupAccountsRequest) ProtoMessage() {}
func (*BackupAccountsRequest) Descriptor() ([]byte, []int) { func (*BackupAccountsRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_8a5153635bfe042e, []int{22} return fileDescriptor_8a5153635bfe042e, []int{24}
} }
func (m *BackupAccountsRequest) XXX_Unmarshal(b []byte) error { func (m *BackupAccountsRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@@ -1487,7 +1580,7 @@ func (m *BackupAccountsResponse) Reset() { *m = BackupAccountsResponse{}
func (m *BackupAccountsResponse) String() string { return proto.CompactTextString(m) } func (m *BackupAccountsResponse) String() string { return proto.CompactTextString(m) }
func (*BackupAccountsResponse) ProtoMessage() {} func (*BackupAccountsResponse) ProtoMessage() {}
func (*BackupAccountsResponse) Descriptor() ([]byte, []int) { func (*BackupAccountsResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_8a5153635bfe042e, []int{23} return fileDescriptor_8a5153635bfe042e, []int{25}
} }
func (m *BackupAccountsResponse) XXX_Unmarshal(b []byte) error { func (m *BackupAccountsResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@@ -1534,7 +1627,7 @@ func (m *DeleteAccountsRequest) Reset() { *m = DeleteAccountsRequest{} }
func (m *DeleteAccountsRequest) String() string { return proto.CompactTextString(m) } func (m *DeleteAccountsRequest) String() string { return proto.CompactTextString(m) }
func (*DeleteAccountsRequest) ProtoMessage() {} func (*DeleteAccountsRequest) ProtoMessage() {}
func (*DeleteAccountsRequest) Descriptor() ([]byte, []int) { func (*DeleteAccountsRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_8a5153635bfe042e, []int{24} return fileDescriptor_8a5153635bfe042e, []int{26}
} }
func (m *DeleteAccountsRequest) XXX_Unmarshal(b []byte) error { func (m *DeleteAccountsRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@@ -1581,7 +1674,7 @@ func (m *DeleteAccountsResponse) Reset() { *m = DeleteAccountsResponse{}
func (m *DeleteAccountsResponse) String() string { return proto.CompactTextString(m) } func (m *DeleteAccountsResponse) String() string { return proto.CompactTextString(m) }
func (*DeleteAccountsResponse) ProtoMessage() {} func (*DeleteAccountsResponse) ProtoMessage() {}
func (*DeleteAccountsResponse) Descriptor() ([]byte, []int) { func (*DeleteAccountsResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_8a5153635bfe042e, []int{25} return fileDescriptor_8a5153635bfe042e, []int{27}
} }
func (m *DeleteAccountsResponse) XXX_Unmarshal(b []byte) error { func (m *DeleteAccountsResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@@ -1628,7 +1721,7 @@ func (m *ExportSlashingProtectionResponse) Reset() { *m = ExportSlashing
func (m *ExportSlashingProtectionResponse) String() string { return proto.CompactTextString(m) } func (m *ExportSlashingProtectionResponse) String() string { return proto.CompactTextString(m) }
func (*ExportSlashingProtectionResponse) ProtoMessage() {} func (*ExportSlashingProtectionResponse) ProtoMessage() {}
func (*ExportSlashingProtectionResponse) Descriptor() ([]byte, []int) { func (*ExportSlashingProtectionResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_8a5153635bfe042e, []int{26} return fileDescriptor_8a5153635bfe042e, []int{28}
} }
func (m *ExportSlashingProtectionResponse) XXX_Unmarshal(b []byte) error { func (m *ExportSlashingProtectionResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@@ -1675,7 +1768,7 @@ func (m *ImportSlashingProtectionRequest) Reset() { *m = ImportSlashingP
func (m *ImportSlashingProtectionRequest) String() string { return proto.CompactTextString(m) } func (m *ImportSlashingProtectionRequest) String() string { return proto.CompactTextString(m) }
func (*ImportSlashingProtectionRequest) ProtoMessage() {} func (*ImportSlashingProtectionRequest) ProtoMessage() {}
func (*ImportSlashingProtectionRequest) Descriptor() ([]byte, []int) { func (*ImportSlashingProtectionRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_8a5153635bfe042e, []int{27} return fileDescriptor_8a5153635bfe042e, []int{29}
} }
func (m *ImportSlashingProtectionRequest) XXX_Unmarshal(b []byte) error { func (m *ImportSlashingProtectionRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@@ -1735,6 +1828,8 @@ func init() {
proto.RegisterType((*HasUsedWebResponse)(nil), "ethereum.validator.accounts.v2.HasUsedWebResponse") proto.RegisterType((*HasUsedWebResponse)(nil), "ethereum.validator.accounts.v2.HasUsedWebResponse")
proto.RegisterType((*LogsResponse)(nil), "ethereum.validator.accounts.v2.LogsResponse") proto.RegisterType((*LogsResponse)(nil), "ethereum.validator.accounts.v2.LogsResponse")
proto.RegisterType((*BeaconStatusResponse)(nil), "ethereum.validator.accounts.v2.BeaconStatusResponse") proto.RegisterType((*BeaconStatusResponse)(nil), "ethereum.validator.accounts.v2.BeaconStatusResponse")
proto.RegisterType((*VoluntaryExitRequest)(nil), "ethereum.validator.accounts.v2.VoluntaryExitRequest")
proto.RegisterType((*VoluntaryExitResponse)(nil), "ethereum.validator.accounts.v2.VoluntaryExitResponse")
proto.RegisterType((*BackupAccountsRequest)(nil), "ethereum.validator.accounts.v2.BackupAccountsRequest") proto.RegisterType((*BackupAccountsRequest)(nil), "ethereum.validator.accounts.v2.BackupAccountsRequest")
proto.RegisterType((*BackupAccountsResponse)(nil), "ethereum.validator.accounts.v2.BackupAccountsResponse") proto.RegisterType((*BackupAccountsResponse)(nil), "ethereum.validator.accounts.v2.BackupAccountsResponse")
proto.RegisterType((*DeleteAccountsRequest)(nil), "ethereum.validator.accounts.v2.DeleteAccountsRequest") proto.RegisterType((*DeleteAccountsRequest)(nil), "ethereum.validator.accounts.v2.DeleteAccountsRequest")
@@ -1748,157 +1843,161 @@ func init() {
} }
var fileDescriptor_8a5153635bfe042e = []byte{ var fileDescriptor_8a5153635bfe042e = []byte{
// 2396 bytes of a gzipped FileDescriptorProto // 2460 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x59, 0x59, 0x6f, 0x1c, 0x59, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x59, 0xcd, 0x6f, 0x1c, 0x49,
0xf5, 0xff, 0x97, 0xb7, 0xb4, 0x8f, 0xdb, 0x4b, 0xae, 0x97, 0x74, 0x1c, 0xc7, 0x76, 0x6e, 0x16, 0x15, 0xa7, 0x6d, 0x67, 0x32, 0x7e, 0x1e, 0x7f, 0xa4, 0xfc, 0x91, 0x89, 0xe3, 0xd8, 0x4e, 0x6d,
0x3b, 0x4e, 0xd2, 0x9d, 0xb4, 0xff, 0x59, 0x14, 0x1e, 0x86, 0x78, 0x99, 0x24, 0xe3, 0x2c, 0xa6, 0xb2, 0x76, 0x9c, 0x64, 0x66, 0x33, 0x66, 0x93, 0x68, 0x39, 0x2c, 0xb1, 0x3d, 0x9b, 0x64, 0xbd,
0xec, 0x49, 0x84, 0x90, 0xa6, 0x74, 0x5d, 0x75, 0xd3, 0x5d, 0xb8, 0xbb, 0xaa, 0xa6, 0xea, 0x76, 0x9b, 0x98, 0xb6, 0x37, 0x11, 0x42, 0xda, 0x56, 0xb9, 0xbb, 0x32, 0xd3, 0x78, 0xa6, 0xbb, 0xb7,
0xc7, 0x0e, 0x2f, 0x30, 0x8c, 0x84, 0x40, 0x42, 0x2c, 0xf3, 0x80, 0x90, 0x10, 0x12, 0x88, 0x07, 0xbb, 0x66, 0x62, 0x87, 0x0b, 0x2c, 0x2b, 0x21, 0x90, 0x90, 0x80, 0x3d, 0x20, 0x24, 0x84, 0x04,
0x90, 0x78, 0x00, 0x09, 0x69, 0x3e, 0x02, 0xf0, 0x86, 0xc4, 0x07, 0x00, 0x45, 0x3c, 0x31, 0x5f, 0xe2, 0x00, 0x12, 0x42, 0x20, 0x21, 0xed, 0x95, 0x1b, 0x70, 0x43, 0xe2, 0x0f, 0x00, 0x45, 0x9c,
0x02, 0xdd, 0xa5, 0xb6, 0x76, 0x55, 0xca, 0x06, 0xf1, 0xc2, 0x5b, 0xd7, 0x59, 0x7f, 0xf7, 0xdc, 0xd8, 0x7f, 0x02, 0xd5, 0x47, 0x7f, 0x8d, 0xbb, 0xd3, 0x36, 0x88, 0x0b, 0xb7, 0xe9, 0x57, 0xef,
0x73, 0xce, 0x3d, 0xf7, 0x36, 0x5c, 0xf5, 0x7c, 0x97, 0xb9, 0xb5, 0x2e, 0x69, 0xd9, 0x16, 0x61, 0xe3, 0x57, 0xaf, 0xde, 0x7b, 0xf5, 0x5e, 0x0d, 0x5c, 0xf3, 0x7c, 0x97, 0xb9, 0xf5, 0x3e, 0xe9,
0xae, 0x5f, 0x23, 0xa6, 0xe9, 0x76, 0x1c, 0x16, 0xd4, 0xba, 0xf5, 0xda, 0x6b, 0xba, 0x67, 0x10, 0xd8, 0x16, 0x61, 0xae, 0x5f, 0x27, 0xa6, 0xe9, 0xf6, 0x1c, 0x16, 0xd4, 0xfb, 0x8d, 0xfa, 0x73,
0xcf, 0xae, 0x0a, 0x19, 0x34, 0x4f, 0x59, 0x93, 0xfa, 0xb4, 0xd3, 0xae, 0x46, 0xd2, 0xd5, 0x50, 0xba, 0x6f, 0x10, 0xcf, 0xae, 0x09, 0x1e, 0xb4, 0x48, 0x59, 0x9b, 0xfa, 0xb4, 0xd7, 0xad, 0x45,
0xba, 0xda, 0xad, 0xcf, 0x2e, 0x4a, 0x53, 0x7b, 0x94, 0x98, 0xae, 0x53, 0xf3, 0x3d, 0xb3, 0xd6, 0xdc, 0xb5, 0x90, 0xbb, 0xd6, 0x6f, 0xcc, 0x2f, 0x4b, 0x55, 0xfb, 0x94, 0x98, 0xae, 0x53, 0xf7,
0xbd, 0x55, 0x6b, 0x52, 0xd2, 0x62, 0x4d, 0x69, 0x61, 0x76, 0x81, 0xb2, 0x66, 0xad, 0x7b, 0x8b, 0x3d, 0xb3, 0xde, 0xbf, 0x55, 0x6f, 0x53, 0xd2, 0x61, 0x6d, 0xa9, 0x61, 0x7e, 0x89, 0xb2, 0x76,
0xb4, 0xbc, 0x26, 0xb9, 0xa5, 0x04, 0x0d, 0xb3, 0x49, 0x6c, 0x47, 0x09, 0x9c, 0x49, 0x09, 0x38, 0xbd, 0x7f, 0x8b, 0x74, 0xbc, 0x36, 0xb9, 0xa5, 0x18, 0x0d, 0xb3, 0x4d, 0x6c, 0x47, 0x31, 0x9c,
0xae, 0x45, 0x15, 0x63, 0xae, 0xe1, 0xba, 0x8d, 0x16, 0xad, 0x11, 0xcf, 0xae, 0x11, 0xc7, 0x71, 0x4f, 0x31, 0x38, 0xae, 0x45, 0xd5, 0xc2, 0x42, 0xcb, 0x75, 0x5b, 0x1d, 0x5a, 0x27, 0x9e, 0x5d,
0x19, 0x61, 0xb6, 0xeb, 0x04, 0x8a, 0x7b, 0x4e, 0x71, 0xc5, 0xd7, 0x5e, 0xe7, 0x55, 0x8d, 0xb6, 0x27, 0x8e, 0xe3, 0x32, 0xc2, 0x6c, 0xd7, 0x09, 0xd4, 0xea, 0x45, 0xb5, 0x2a, 0xbe, 0xf6, 0x7b,
0x3d, 0x76, 0x28, 0x99, 0xf8, 0x8b, 0x3e, 0x98, 0x5c, 0xf7, 0x29, 0x61, 0xf4, 0x25, 0x69, 0xb5, 0xcf, 0xea, 0xb4, 0xeb, 0xb1, 0x23, 0xb9, 0x88, 0x3f, 0x1f, 0x82, 0xe9, 0x4d, 0x9f, 0x12, 0x46,
0x28, 0xd3, 0xe9, 0xc7, 0x1d, 0x1a, 0x30, 0xf4, 0x0c, 0x60, 0x9f, 0x1e, 0xb6, 0x89, 0x43, 0x1a, 0x9f, 0x92, 0x4e, 0x87, 0x32, 0x9d, 0x7e, 0xd4, 0xa3, 0x01, 0x43, 0x8f, 0x00, 0x0e, 0xe8, 0x51,
0xd4, 0xaf, 0x68, 0x8b, 0xda, 0xf2, 0x58, 0xbd, 0x5a, 0x7d, 0xf7, 0x1a, 0xab, 0x5b, 0x91, 0xc6, 0x97, 0x38, 0xa4, 0x45, 0xfd, 0xaa, 0xb6, 0xac, 0xad, 0x4e, 0x34, 0x6a, 0xb5, 0x57, 0xef, 0xb1,
0x96, 0xed, 0x58, 0x7a, 0xc2, 0x02, 0x5a, 0x82, 0xf1, 0xd7, 0xc2, 0x81, 0xe1, 0x91, 0x20, 0x78, 0xb6, 0x1d, 0x49, 0x6c, 0xdb, 0x8e, 0xa5, 0x27, 0x34, 0xa0, 0x15, 0x98, 0x7c, 0x2e, 0x0c, 0x18,
0xed, 0xfa, 0x56, 0xa5, 0x6f, 0x51, 0x5b, 0x1e, 0xd6, 0xc7, 0x24, 0x79, 0x5b, 0x51, 0xd1, 0x2c, 0x1e, 0x09, 0x82, 0xe7, 0xae, 0x6f, 0x55, 0x87, 0x96, 0xb5, 0xd5, 0x51, 0x7d, 0x42, 0x92, 0x77,
0x94, 0xda, 0x0e, 0x6d, 0xbb, 0x8e, 0x6d, 0x56, 0xfa, 0x85, 0x44, 0xf4, 0x8d, 0x2e, 0x40, 0xd9, 0x14, 0x15, 0xcd, 0x43, 0xb9, 0xeb, 0xd0, 0xae, 0xeb, 0xd8, 0x66, 0x75, 0x58, 0x70, 0x44, 0xdf,
0xe9, 0xb4, 0x8d, 0xd0, 0x65, 0x65, 0x60, 0x51, 0x5b, 0x1e, 0xd0, 0x47, 0x9c, 0x4e, 0xfb, 0x81, 0xe8, 0x32, 0x54, 0x9c, 0x5e, 0xd7, 0x08, 0x4d, 0x56, 0x47, 0x96, 0xb5, 0xd5, 0x11, 0x7d, 0xcc,
0x22, 0xa1, 0x05, 0x18, 0xf1, 0x69, 0xdb, 0x65, 0xd4, 0x20, 0x96, 0xe5, 0x57, 0x06, 0x85, 0x05, 0xe9, 0x75, 0xef, 0x29, 0x12, 0x5a, 0x82, 0x31, 0x9f, 0x76, 0x5d, 0x46, 0x0d, 0x62, 0x59, 0x7e,
0x90, 0xa4, 0x07, 0x96, 0xe5, 0xa3, 0x2b, 0x30, 0xae, 0x04, 0x4c, 0x9f, 0x83, 0x61, 0xcd, 0xca, 0xf5, 0x8c, 0xd0, 0x00, 0x92, 0x74, 0xcf, 0xb2, 0x7c, 0xf4, 0x3a, 0x4c, 0x2a, 0x06, 0xd3, 0xe7,
0x90, 0x10, 0x1a, 0x95, 0xe4, 0x75, 0x9f, 0x6d, 0x13, 0xd6, 0x4c, 0xc8, 0xed, 0xd3, 0x43, 0x29, 0x60, 0x58, 0xbb, 0x5a, 0x12, 0x4c, 0xe3, 0x92, 0xbc, 0xe9, 0xb3, 0x1d, 0xc2, 0xda, 0x09, 0xbe,
0x77, 0x2a, 0x29, 0xb7, 0x45, 0x0f, 0x85, 0xdc, 0x35, 0x40, 0xa1, 0x3d, 0x12, 0x9b, 0x2c, 0x09, 0x03, 0x7a, 0x24, 0xf9, 0xce, 0x26, 0xf9, 0xb6, 0xe9, 0x91, 0xe0, 0xbb, 0x0e, 0x28, 0xd4, 0x47,
0x51, 0x65, 0x61, 0x9d, 0x28, 0xa3, 0xf8, 0x23, 0x98, 0x4a, 0x07, 0x3b, 0xf0, 0x5c, 0x27, 0xa0, 0x62, 0x95, 0x65, 0xc1, 0xaa, 0x34, 0x6c, 0x12, 0xa5, 0x14, 0x7f, 0x08, 0x33, 0x69, 0x67, 0x07,
0xe8, 0x7d, 0x18, 0x92, 0x61, 0x10, 0x91, 0x1e, 0x29, 0x8e, 0x74, 0x5a, 0x5f, 0x57, 0xda, 0xf8, 0x9e, 0xeb, 0x04, 0x14, 0xbd, 0x03, 0x25, 0xe9, 0x06, 0xe1, 0xe9, 0xb1, 0x62, 0x4f, 0xa7, 0xe5,
0x73, 0x0d, 0xce, 0x6c, 0x5a, 0x36, 0x93, 0xec, 0x75, 0xd7, 0x79, 0x65, 0x37, 0xc2, 0x1d, 0xed, 0x75, 0x25, 0x8d, 0x3f, 0xd3, 0xe0, 0x7c, 0xd3, 0xb2, 0x99, 0x5c, 0xde, 0x74, 0x9d, 0x67, 0x76,
0x89, 0x8c, 0x76, 0x9c, 0xc8, 0xf4, 0x1d, 0x33, 0x32, 0xfd, 0xc7, 0x8f, 0xcc, 0x40, 0x76, 0x64, 0x2b, 0x3c, 0xd1, 0x01, 0xcf, 0x68, 0x27, 0xf1, 0xcc, 0xd0, 0x09, 0x3d, 0x33, 0x7c, 0x72, 0xcf,
0xee, 0x40, 0xe5, 0x21, 0x75, 0xa8, 0x4f, 0x18, 0x7d, 0xaa, 0xb6, 0x3b, 0x8a, 0x4e, 0x32, 0x25, 0x8c, 0x64, 0x7b, 0xe6, 0x36, 0x54, 0xef, 0x53, 0x87, 0xfa, 0x84, 0xd1, 0xf7, 0xd5, 0x71, 0x47,
0xb4, 0x74, 0x4a, 0xe0, 0xef, 0x69, 0x30, 0xd6, 0x13, 0xcc, 0x05, 0x18, 0x89, 0x52, 0x8d, 0x35, 0xde, 0x49, 0x86, 0x84, 0x96, 0x0e, 0x09, 0xfc, 0x3d, 0x0d, 0x26, 0x06, 0x9c, 0xb9, 0x04, 0x63,
0xc3, 0x85, 0x86, 0x69, 0xc6, 0x9a, 0xe8, 0x25, 0x8c, 0xc7, 0x99, 0x69, 0xec, 0xdb, 0x8e, 0xcc, 0x51, 0xa8, 0xb1, 0x76, 0xb8, 0xd1, 0x30, 0xcc, 0x58, 0x1b, 0x3d, 0x85, 0xc9, 0x38, 0x32, 0x8d,
0xc5, 0x93, 0x27, 0xf8, 0xd8, 0x7e, 0xea, 0x1b, 0xff, 0x51, 0x83, 0x29, 0x9d, 0x9a, 0x6e, 0x97, 0x03, 0xdb, 0x91, 0xb1, 0x78, 0xfa, 0x00, 0x9f, 0x38, 0x48, 0x7d, 0xe3, 0x3f, 0x69, 0x30, 0xa3,
0xfa, 0xe9, 0x6a, 0x7a, 0xc7, 0x0a, 0x8e, 0x24, 0x75, 0xdf, 0xd1, 0xa4, 0xce, 0x28, 0x9e, 0xfe, 0x53, 0xd3, 0xed, 0x53, 0x3f, 0x9d, 0x4d, 0xaf, 0xd8, 0xc1, 0xb1, 0xa0, 0x1e, 0x3a, 0x1e, 0xd4,
0xbc, 0xe2, 0x69, 0x11, 0xa7, 0xd1, 0x21, 0x0d, 0xaa, 0x02, 0x1d, 0x7d, 0xa3, 0x6b, 0x70, 0x3a, 0x19, 0xc9, 0x33, 0x9c, 0x97, 0x3c, 0x1d, 0xe2, 0xb4, 0x7a, 0xa4, 0x45, 0x95, 0xa3, 0xa3, 0x6f,
0xf4, 0x59, 0xbf, 0xcd, 0x9a, 0x86, 0x30, 0x23, 0xeb, 0x63, 0x22, 0xc9, 0x78, 0xe9, 0xfa, 0x16, 0x74, 0x1d, 0xce, 0x85, 0x36, 0x1b, 0x6f, 0xb2, 0xb6, 0x21, 0xd4, 0xc8, 0xfc, 0x98, 0x4a, 0x2e,
0xfe, 0xb1, 0x06, 0x93, 0x4f, 0xec, 0x80, 0x85, 0x10, 0xc2, 0x85, 0xdc, 0x80, 0xc9, 0x06, 0x65, 0x3c, 0x75, 0x7d, 0x0b, 0xff, 0x48, 0x83, 0xe9, 0xf7, 0xec, 0x80, 0x85, 0x10, 0xc2, 0x8d, 0xdc,
0x86, 0x45, 0x3d, 0x37, 0xb0, 0x99, 0xc1, 0x0e, 0x0c, 0x8b, 0x30, 0x22, 0xd6, 0x54, 0xd2, 0x27, 0x84, 0xe9, 0x16, 0x65, 0x86, 0x45, 0x3d, 0x37, 0xb0, 0x99, 0xc1, 0x0e, 0x0d, 0x8b, 0x30, 0x22,
0x1a, 0x94, 0x6d, 0x48, 0xce, 0xee, 0xc1, 0x06, 0x61, 0x04, 0x9d, 0x83, 0x61, 0x8f, 0x34, 0xa8, 0xf6, 0x54, 0xd6, 0xa7, 0x5a, 0x94, 0x6d, 0xc9, 0x95, 0xbd, 0xc3, 0x2d, 0xc2, 0x08, 0xba, 0x08,
0x11, 0xd8, 0x6f, 0xa8, 0x58, 0xd8, 0xa0, 0x5e, 0xe2, 0x84, 0x1d, 0xfb, 0x0d, 0x45, 0xe7, 0x01, 0xa3, 0x1e, 0x69, 0x51, 0x23, 0xb0, 0x5f, 0x50, 0xb1, 0xb1, 0x33, 0x7a, 0x99, 0x13, 0x76, 0xed,
0x04, 0x93, 0xb9, 0xfb, 0xd4, 0x51, 0x0b, 0x12, 0xe2, 0xbb, 0x9c, 0x80, 0x26, 0xa0, 0x9f, 0xb4, 0x17, 0x14, 0x5d, 0x02, 0x10, 0x8b, 0xcc, 0x3d, 0xa0, 0x8e, 0xda, 0x90, 0x60, 0xdf, 0xe3, 0x04,
0x5a, 0x62, 0x19, 0x25, 0x9d, 0xff, 0xc4, 0xbf, 0xd4, 0x60, 0x2a, 0x0d, 0x4a, 0xed, 0xf8, 0x3a, 0x34, 0x05, 0xc3, 0xa4, 0xd3, 0x11, 0xdb, 0x28, 0xeb, 0xfc, 0x27, 0xfe, 0x85, 0x06, 0x33, 0x69,
0x94, 0xa2, 0xf0, 0x69, 0x8b, 0xfd, 0xcb, 0x23, 0xf5, 0xa5, 0xa2, 0x9d, 0x54, 0x36, 0xf4, 0x48, 0x50, 0xea, 0xc4, 0x37, 0xa1, 0x1c, 0xb9, 0x4f, 0x5b, 0x1e, 0x5e, 0x1d, 0x6b, 0xac, 0x14, 0x9d,
0x91, 0xa7, 0xb5, 0x43, 0x0f, 0x78, 0x88, 0x23, 0x4c, 0x2a, 0xfd, 0x39, 0x79, 0x3b, 0xc2, 0x75, 0xa4, 0xd2, 0xa1, 0x47, 0x82, 0x3c, 0xac, 0x1d, 0x7a, 0xc8, 0x5d, 0x1c, 0x61, 0x52, 0xe1, 0xcf,
0x1e, 0x80, 0xb9, 0x8c, 0xb4, 0xe4, 0xa2, 0xfa, 0xc5, 0xa2, 0x86, 0x05, 0x85, 0xaf, 0x0a, 0xff, 0xc9, 0x3b, 0x11, 0xae, 0x4b, 0x00, 0xcc, 0x65, 0xa4, 0x23, 0x37, 0x35, 0x2c, 0x36, 0x35, 0x2a,
0x5e, 0x83, 0x53, 0xca, 0x38, 0xaa, 0xc3, 0xb4, 0xf2, 0x6e, 0x3b, 0x0d, 0xc3, 0xeb, 0xec, 0xb5, 0x28, 0x7c, 0x57, 0xf8, 0xf7, 0x1a, 0x9c, 0x55, 0xca, 0x51, 0x03, 0x66, 0x95, 0x75, 0xdb, 0x69,
0x6c, 0x93, 0x17, 0x8d, 0x88, 0x57, 0x59, 0x9f, 0x8c, 0x99, 0xdb, 0x82, 0xb7, 0x45, 0x0f, 0x79, 0x19, 0x5e, 0x6f, 0xbf, 0x63, 0x9b, 0x3c, 0x69, 0x84, 0xbf, 0x2a, 0xfa, 0x74, 0xbc, 0xb8, 0x23,
0x3a, 0x28, 0x48, 0x86, 0x43, 0xda, 0x54, 0x61, 0x18, 0x51, 0xb4, 0x67, 0xa4, 0x4d, 0x39, 0xd2, 0xd6, 0xb6, 0xe9, 0x11, 0x0f, 0x07, 0x05, 0xc9, 0x70, 0x48, 0x97, 0x2a, 0x0c, 0x63, 0x8a, 0xf6,
0xde, 0x0d, 0xe8, 0x17, 0x06, 0x47, 0xad, 0x54, 0xf4, 0x97, 0xb8, 0x9c, 0x6f, 0x77, 0xc5, 0x69, 0x88, 0x74, 0x29, 0x47, 0x3a, 0x78, 0x00, 0xc3, 0x42, 0xe1, 0xb8, 0x95, 0xf2, 0xfe, 0x0a, 0xe7,
0x90, 0xac, 0xbe, 0xb1, 0x98, 0x2c, 0x8a, 0x6f, 0x0b, 0xc6, 0xc2, 0x78, 0xc4, 0xcd, 0x22, 0x86, 0xf3, 0xed, 0xbe, 0xb8, 0x0d, 0x92, 0xd9, 0x37, 0x11, 0x93, 0x45, 0xf2, 0x6d, 0xc3, 0x44, 0xe8,
0x2b, 0x83, 0x5a, 0xd6, 0xc1, 0x0b, 0x51, 0x06, 0xa8, 0x02, 0xa7, 0x6c, 0xc7, 0xb2, 0x4d, 0xca, 0x8f, 0xb8, 0x58, 0xc4, 0x70, 0xa5, 0x53, 0x2b, 0x3a, 0x78, 0x21, 0xca, 0x00, 0x55, 0xe1, 0xac,
0x13, 0xb6, 0x7f, 0x79, 0x40, 0x0f, 0x3f, 0xf1, 0x47, 0x30, 0xf2, 0xa0, 0xc3, 0x9a, 0x89, 0xd4, 0xed, 0x58, 0xb6, 0x49, 0x79, 0xc0, 0x0e, 0xaf, 0x8e, 0xe8, 0xe1, 0x27, 0xfe, 0x10, 0xc6, 0xee,
0x8f, 0x92, 0x56, 0xa5, 0x7e, 0xf8, 0x8d, 0x56, 0x61, 0x3a, 0xfc, 0x6d, 0x98, 0xbc, 0x59, 0xf9, 0xf5, 0x58, 0x3b, 0x11, 0xfa, 0x51, 0xd0, 0xaa, 0xd0, 0x0f, 0xbf, 0xd1, 0x3a, 0xcc, 0x86, 0xbf,
0x6d, 0x01, 0x4a, 0x2d, 0x7a, 0x2a, 0x64, 0xae, 0x27, 0x78, 0xf8, 0x39, 0x94, 0xa5, 0x7d, 0xb5, 0x0d, 0x93, 0x17, 0x2b, 0xbf, 0x2b, 0x40, 0xa9, 0x4d, 0xcf, 0x84, 0x8b, 0x9b, 0x89, 0x35, 0xfc,
0xf9, 0x53, 0x30, 0x28, 0x77, 0x4b, 0x5a, 0x97, 0x1f, 0xe8, 0x2a, 0x4c, 0x88, 0x1f, 0x06, 0x3d, 0x18, 0x2a, 0x52, 0xbf, 0x3a, 0xfc, 0x19, 0x38, 0x23, 0x4f, 0x4b, 0x6a, 0x97, 0x1f, 0xe8, 0x1a,
0xf0, 0x6c, 0x3f, 0xb6, 0x3a, 0xa0, 0x8f, 0x0b, 0xfa, 0x66, 0x44, 0xc6, 0x7f, 0xd3, 0x60, 0xe6, 0x4c, 0x89, 0x1f, 0x06, 0x3d, 0xf4, 0x6c, 0x3f, 0xd6, 0x3a, 0xa2, 0x4f, 0x0a, 0x7a, 0x33, 0x22,
0x99, 0x6b, 0xd1, 0x75, 0xd7, 0x71, 0xa8, 0xc9, 0x49, 0x91, 0xed, 0x9b, 0x30, 0xa5, 0xce, 0x61, 0xe3, 0xbf, 0x6b, 0x30, 0xf7, 0xc8, 0xb5, 0xe8, 0xa6, 0xeb, 0x38, 0xd4, 0xe4, 0xa4, 0x48, 0xf7,
0x7e, 0xda, 0x1a, 0xd4, 0xb1, 0x3c, 0xd7, 0x76, 0x98, 0x72, 0x85, 0x24, 0x8f, 0xeb, 0x6e, 0x2a, 0x1b, 0x30, 0xa3, 0xee, 0x61, 0x7e, 0xdb, 0x1a, 0xd4, 0xb1, 0x3c, 0xd7, 0x76, 0x98, 0x32, 0x85,
0x0e, 0x9a, 0x83, 0x61, 0x53, 0xda, 0xa1, 0xb2, 0xab, 0x94, 0xf4, 0x98, 0xc0, 0xa3, 0x16, 0x1c, 0xe4, 0x1a, 0x97, 0x6d, 0xaa, 0x15, 0xb4, 0x00, 0xa3, 0xa6, 0xd4, 0x43, 0x65, 0x55, 0x29, 0xeb,
0x3a, 0xa6, 0xed, 0x34, 0xc4, 0x8e, 0x95, 0xf4, 0xf0, 0x93, 0x6f, 0x7b, 0x83, 0x3a, 0x34, 0xb0, 0x31, 0x81, 0x7b, 0x2d, 0x38, 0x72, 0x4c, 0xdb, 0x69, 0x89, 0x13, 0x2b, 0xeb, 0xe1, 0x27, 0x3f,
0x03, 0x83, 0xd9, 0x6d, 0x1a, 0x1e, 0x6d, 0x8a, 0xb6, 0x6b, 0xb7, 0x29, 0xba, 0x07, 0x95, 0x70, 0xf6, 0x16, 0x75, 0x68, 0x60, 0x07, 0x06, 0xb3, 0xbb, 0x34, 0xbc, 0xda, 0x14, 0x6d, 0xcf, 0xee,
0xdb, 0x4d, 0xd7, 0x61, 0x3e, 0x31, 0x99, 0x68, 0xe5, 0x34, 0x08, 0x44, 0x1d, 0x97, 0xf5, 0x19, 0x52, 0x74, 0x17, 0xaa, 0xe1, 0xb1, 0x9b, 0xae, 0xc3, 0x7c, 0x62, 0x32, 0x51, 0xca, 0x69, 0x10,
0xc5, 0x5f, 0x57, 0xec, 0x07, 0x92, 0x8b, 0xbf, 0xc9, 0x0b, 0xc7, 0x6d, 0x04, 0x21, 0xca, 0x68, 0x88, 0x3c, 0xae, 0xe8, 0x73, 0x6a, 0x7d, 0x53, 0x2d, 0xdf, 0x93, 0xab, 0xf8, 0x9b, 0x3c, 0x71,
0x7d, 0x77, 0xe0, 0x4c, 0x54, 0x1e, 0x46, 0xcb, 0x6d, 0x04, 0xbd, 0x4b, 0x9c, 0x8e, 0xd8, 0x49, 0xdc, 0x56, 0x10, 0xa2, 0x8c, 0xf6, 0x77, 0x1b, 0xce, 0x47, 0xe9, 0x61, 0x74, 0xdc, 0x56, 0x30,
0xfd, 0x44, 0x5c, 0xd2, 0x4a, 0x7d, 0xc9, 0xb8, 0x24, 0x35, 0xf0, 0x43, 0x18, 0x7f, 0x41, 0xfd, 0xb8, 0xc5, 0xd9, 0x68, 0x39, 0x29, 0x9f, 0xf0, 0x4b, 0x5a, 0x68, 0x28, 0xe9, 0x97, 0xa4, 0x04,
0x20, 0x19, 0xdc, 0x19, 0x18, 0x92, 0x82, 0xca, 0x97, 0xfa, 0xe2, 0x21, 0x8c, 0xbc, 0x2a, 0x8b, 0xbe, 0x0f, 0x93, 0x4f, 0xa8, 0x1f, 0x24, 0x9d, 0x3b, 0x07, 0x25, 0xc9, 0xa8, 0x6c, 0xa9, 0x2f,
0x31, 0x01, 0x7f, 0xa6, 0xc1, 0xf4, 0x7a, 0x93, 0x38, 0x0d, 0x1a, 0x76, 0xbd, 0x30, 0xd3, 0xae, 0xee, 0xc2, 0xc8, 0xaa, 0xd2, 0x18, 0x13, 0xf0, 0xa7, 0x1a, 0xcc, 0x6e, 0xb6, 0x89, 0xd3, 0xa2,
0xc2, 0x84, 0xd9, 0xf1, 0x7d, 0xea, 0x24, 0xda, 0xa4, 0xb4, 0x3c, 0xae, 0xe8, 0xc9, 0x3e, 0xd9, 0x61, 0xd5, 0x0b, 0x23, 0xed, 0x1a, 0x4c, 0x99, 0x3d, 0xdf, 0xa7, 0x4e, 0xa2, 0x4c, 0x4a, 0xcd,
0x33, 0x86, 0x1c, 0x23, 0x29, 0xfb, 0xdf, 0x91, 0x94, 0xf7, 0xe0, 0xf4, 0x23, 0x12, 0xf4, 0x1c, 0x93, 0x8a, 0x9e, 0xac, 0x93, 0x03, 0x6d, 0xc8, 0x09, 0x82, 0x72, 0xf8, 0x15, 0x41, 0x79, 0x17,
0x44, 0x17, 0x61, 0x54, 0xb5, 0x6d, 0x7a, 0x60, 0x07, 0xa2, 0x37, 0xf1, 0x3d, 0x2f, 0x4b, 0xe2, 0xce, 0x3d, 0x20, 0xc1, 0xc0, 0x45, 0xf4, 0x1a, 0x8c, 0xab, 0xb2, 0x4d, 0x0f, 0xed, 0x40, 0xd4,
0xa6, 0xa0, 0xe1, 0x2e, 0xcc, 0x3c, 0x6e, 0x7b, 0xae, 0xcf, 0x78, 0x59, 0x31, 0xd7, 0xa7, 0x89, 0x26, 0x7e, 0xe6, 0x15, 0x49, 0x6c, 0x0a, 0x1a, 0xee, 0xc3, 0xdc, 0xc3, 0xae, 0xe7, 0xfa, 0x8c,
0x5e, 0x8b, 0xf6, 0x43, 0x9a, 0x61, 0x0b, 0x19, 0x6a, 0x89, 0x52, 0x1c, 0xd6, 0x4f, 0x47, 0x9c, 0xa7, 0x15, 0x73, 0x7d, 0x9a, 0xa8, 0xb5, 0xe8, 0x20, 0xa4, 0x19, 0xb6, 0xe0, 0xa1, 0x96, 0x48,
0xc7, 0x8a, 0x91, 0x16, 0xef, 0x59, 0x5d, 0x2c, 0x1e, 0x86, 0x00, 0x6f, 0xc1, 0x99, 0x23, 0x7e, 0xc5, 0x51, 0xfd, 0x5c, 0xb4, 0xf2, 0x50, 0x2d, 0xa4, 0xd9, 0x07, 0x76, 0x17, 0xb3, 0x87, 0x2e,
0xe3, 0xac, 0x0f, 0xdd, 0x19, 0x47, 0xbb, 0x00, 0x0a, 0x79, 0x51, 0xcf, 0x0a, 0xf0, 0x4b, 0x40, 0xc0, 0xdb, 0x70, 0xfe, 0x98, 0xdd, 0x38, 0xea, 0x43, 0x73, 0xc6, 0xf1, 0x2a, 0x80, 0xc2, 0xb5,
0x8f, 0x48, 0xf0, 0x61, 0x40, 0xad, 0x97, 0x74, 0x2f, 0xb2, 0x83, 0x61, 0xb4, 0x49, 0x02, 0x23, 0xa8, 0x66, 0x05, 0xf8, 0x29, 0xa0, 0x07, 0x24, 0xf8, 0x20, 0xa0, 0xd6, 0x53, 0xba, 0x1f, 0xe9,
0xb0, 0x1b, 0x0e, 0xb5, 0x8c, 0x8e, 0xa7, 0xd6, 0x3f, 0xd2, 0x24, 0xc1, 0x8e, 0xa0, 0x7d, 0xe8, 0xc1, 0x30, 0xde, 0x26, 0x81, 0x11, 0xd8, 0x2d, 0x87, 0x5a, 0x46, 0xcf, 0x53, 0xfb, 0x1f, 0x6b,
0xf1, 0x6e, 0xca, 0x65, 0xd4, 0xf4, 0xa3, 0x0a, 0xa6, 0x19, 0x86, 0x12, 0x63, 0x28, 0xf3, 0x34, 0x93, 0x60, 0x57, 0xd0, 0x3e, 0xf0, 0x78, 0x35, 0xe5, 0x3c, 0xaa, 0xfb, 0x51, 0x09, 0xd3, 0x0e,
0x8a, 0x4c, 0x22, 0x18, 0xe0, 0x19, 0xa7, 0xa2, 0x20, 0x7e, 0xe3, 0x9f, 0xf7, 0xc1, 0xd4, 0x9a, 0x5d, 0x89, 0x31, 0x54, 0x78, 0x18, 0x45, 0x2a, 0x11, 0x8c, 0xf0, 0x88, 0x53, 0x5e, 0x10, 0xbf,
0x48, 0x9d, 0x1d, 0x46, 0x58, 0x27, 0xf8, 0x1f, 0xab, 0x5e, 0xf4, 0x1e, 0x80, 0xb8, 0x05, 0x18, 0xf1, 0xcf, 0x86, 0x60, 0x66, 0x43, 0x84, 0xce, 0x2e, 0x23, 0xac, 0x17, 0xfc, 0x9f, 0x65, 0x2f,
0x4d, 0x4a, 0x2c, 0x31, 0xac, 0x8e, 0xd4, 0x17, 0xe3, 0xf3, 0x8d, 0xb2, 0x66, 0x35, 0xbc, 0x14, 0x7a, 0x1b, 0x40, 0x4c, 0x01, 0x46, 0x9b, 0x12, 0x4b, 0x34, 0xab, 0x63, 0x8d, 0xe5, 0xf8, 0x7e,
0x54, 0xd7, 0xb9, 0xe0, 0x23, 0x4a, 0x2c, 0x7d, 0xd8, 0x0c, 0x7f, 0x62, 0x02, 0xd3, 0x6b, 0xc4, 0xa3, 0xac, 0x5d, 0x0b, 0x87, 0x82, 0xda, 0x26, 0x67, 0x7c, 0x40, 0x89, 0xa5, 0x8f, 0x9a, 0xe1,
0xdc, 0xef, 0x78, 0xbd, 0xa7, 0x79, 0x61, 0x97, 0x5f, 0x82, 0xf1, 0x3d, 0xa1, 0x79, 0x64, 0x6a, 0x4f, 0x7c, 0x07, 0x66, 0x9e, 0xb8, 0x9d, 0x9e, 0xc3, 0x88, 0x7f, 0xd4, 0x3c, 0xb4, 0x4f, 0x5c,
0x97, 0xe4, 0x28, 0x9b, 0x56, 0x61, 0xa6, 0xd7, 0x85, 0xda, 0x84, 0xb3, 0x50, 0x7a, 0x63, 0x7b, 0xe4, 0xf1, 0x5d, 0x98, 0x1d, 0x10, 0x8c, 0x5b, 0x2c, 0x7a, 0x68, 0xf3, 0xf8, 0x48, 0x4a, 0x4a,
0xc6, 0x2b, 0xbb, 0x45, 0xd5, 0xb1, 0x77, 0xea, 0x8d, 0xed, 0xbd, 0x6f, 0xb7, 0x28, 0xfe, 0x00, 0x92, 0x90, 0x24, 0x30, 0xbb, 0x41, 0xcc, 0x83, 0x9e, 0x37, 0xd8, 0x40, 0x14, 0x5e, 0x2c, 0x2b,
0xa6, 0x37, 0x68, 0x8b, 0x32, 0xda, 0x8b, 0xeb, 0x16, 0x4c, 0x27, 0x70, 0x19, 0xcc, 0x35, 0x2c, 0x30, 0xb9, 0x2f, 0x24, 0x8f, 0x0d, 0x0a, 0x92, 0x1c, 0x05, 0xf0, 0x3a, 0xcc, 0x0d, 0x9a, 0x50,
0x21, 0x17, 0x66, 0x60, 0x8c, 0x70, 0xd7, 0x95, 0x16, 0xf0, 0x97, 0x60, 0xa6, 0xd7, 0x96, 0x02, 0xe8, 0x2e, 0x40, 0xf9, 0x85, 0xed, 0x19, 0xcf, 0xec, 0x0e, 0x55, 0x37, 0xed, 0xd9, 0x17, 0xb6,
0x70, 0x01, 0xca, 0x52, 0xdb, 0x4a, 0xae, 0x72, 0x44, 0xd1, 0x44, 0xfa, 0xde, 0x81, 0xc5, 0xcd, 0xf7, 0x8e, 0xdd, 0xa1, 0xf8, 0x5d, 0x98, 0xdd, 0xa2, 0x1d, 0xca, 0xe8, 0x20, 0xae, 0x5b, 0x30,
0x03, 0x9e, 0xd4, 0x3b, 0x2d, 0x12, 0x34, 0xf9, 0x71, 0xec, 0xbb, 0xac, 0xe7, 0x28, 0x40, 0x30, 0x9b, 0xc0, 0x65, 0x30, 0xd7, 0xb0, 0x04, 0x5f, 0x18, 0xf4, 0x31, 0xc2, 0x3d, 0x57, 0x6a, 0xc0,
0x10, 0xad, 0x61, 0x58, 0x17, 0xbf, 0xf1, 0xd7, 0x60, 0x41, 0xd6, 0x50, 0x96, 0x9e, 0x5c, 0xca, 0x5f, 0x82, 0xb9, 0x41, 0x5d, 0x0a, 0xc0, 0x65, 0xa8, 0x48, 0xe9, 0x94, 0x7f, 0xc6, 0x14, 0x4d,
0x3d, 0xa8, 0x04, 0x8a, 0x69, 0x78, 0x11, 0xd7, 0xf8, 0x7a, 0x10, 0xb5, 0xbd, 0x99, 0xe0, 0x88, 0x38, 0xe8, 0x36, 0x2c, 0x37, 0x0f, 0x79, 0x1e, 0xed, 0x76, 0x48, 0xd0, 0xe6, 0x1d, 0x80, 0xef,
0xf2, 0x07, 0x81, 0xeb, 0xac, 0xdc, 0x85, 0xb1, 0xf4, 0xb8, 0x89, 0x46, 0xe0, 0xd4, 0xc6, 0xa6, 0xb2, 0x81, 0xdb, 0x07, 0xc1, 0x48, 0xb4, 0x87, 0x51, 0x5d, 0xfc, 0xc6, 0x5f, 0x83, 0x25, 0x99,
0xfe, 0xf8, 0xc5, 0xe6, 0xc6, 0xc4, 0xff, 0xa1, 0x32, 0x94, 0x1e, 0x3f, 0xdd, 0x7e, 0xae, 0xef, 0xb6, 0x59, 0x72, 0x72, 0x2b, 0x77, 0xa1, 0x1a, 0xa8, 0x45, 0xc3, 0x8b, 0x56, 0x8d, 0xaf, 0x07,
0x6e, 0x6e, 0x4c, 0x68, 0x08, 0x60, 0x48, 0xdf, 0x7c, 0xfa, 0x7c, 0x77, 0x73, 0xa2, 0xaf, 0xfe, 0x51, 0xa5, 0x9d, 0x0b, 0x8e, 0x09, 0xbf, 0x1b, 0xb8, 0xce, 0xda, 0x1d, 0x98, 0x48, 0x77, 0xb8,
0xc3, 0x21, 0x18, 0x92, 0xe5, 0x83, 0x7e, 0xa1, 0x41, 0x39, 0x79, 0xe1, 0x40, 0xab, 0x45, 0x73, 0x68, 0x0c, 0xce, 0x6e, 0x35, 0xf5, 0x87, 0x4f, 0x9a, 0x5b, 0x53, 0x5f, 0x40, 0x15, 0x28, 0x3f,
0x51, 0xc6, 0x5d, 0x70, 0xf6, 0xff, 0x4f, 0xa6, 0x24, 0x03, 0x86, 0xaf, 0x7c, 0xf2, 0xd7, 0x7f, 0x7c, 0x7f, 0xe7, 0xb1, 0xbe, 0xd7, 0xdc, 0x9a, 0xd2, 0x10, 0x40, 0x49, 0x6f, 0xbe, 0xff, 0x78,
0x7c, 0xd6, 0xb7, 0x88, 0xcf, 0xf1, 0xbb, 0x72, 0x7c, 0x83, 0x96, 0x95, 0x5e, 0x33, 0x85, 0xca, 0xaf, 0x39, 0x35, 0xd4, 0xf8, 0x41, 0x09, 0x4a, 0x32, 0x63, 0xd1, 0xcf, 0x35, 0xa8, 0x24, 0x67,
0x7d, 0x6d, 0x05, 0x31, 0x28, 0x27, 0xaf, 0x2b, 0x68, 0xa6, 0x2a, 0xef, 0xab, 0xd5, 0xf0, 0xbe, 0x1c, 0xb4, 0x5e, 0xd4, 0x8a, 0x65, 0x8c, 0x9f, 0xf3, 0x5f, 0x3c, 0x9d, 0x90, 0x74, 0x18, 0x7e,
0x5a, 0xdd, 0xe4, 0xf7, 0xd5, 0xd9, 0x13, 0xde, 0x89, 0xf0, 0x9c, 0xf0, 0x3f, 0x83, 0xa6, 0xb2, 0xfd, 0xe3, 0xbf, 0xfd, 0xf3, 0xd3, 0xa1, 0x65, 0x7c, 0x91, 0x8f, 0xe7, 0xf1, 0xd0, 0x2e, 0x8b,
0xfc, 0xa3, 0xef, 0x6b, 0x30, 0xd1, 0x7b, 0xe1, 0xc8, 0x75, 0x7d, 0xaf, 0xc8, 0x75, 0xde, 0xd5, 0x4b, 0xdd, 0x14, 0x22, 0x6f, 0x69, 0x6b, 0x88, 0x41, 0x25, 0x39, 0x21, 0xa1, 0xb9, 0x9a, 0x1c,
0x05, 0x2f, 0x09, 0x10, 0x17, 0xd0, 0x42, 0x1a, 0x44, 0x38, 0x6f, 0xd7, 0x1a, 0x4a, 0x11, 0xfd, 0x91, 0x6b, 0xe1, 0x88, 0x5c, 0x6b, 0xf2, 0x11, 0x79, 0xfe, 0x94, 0x63, 0x18, 0x5e, 0x10, 0xf6,
0x41, 0x83, 0xf1, 0x9e, 0x7e, 0x8c, 0xee, 0x14, 0xb9, 0xcd, 0x3e, 0x38, 0x66, 0xef, 0x9e, 0x58, 0xe7, 0xd0, 0x4c, 0x96, 0x7d, 0xf4, 0x7d, 0x0d, 0xa6, 0x06, 0x67, 0x9c, 0x5c, 0xd3, 0x77, 0x8b,
0x4f, 0xa1, 0xbd, 0x29, 0xd0, 0xae, 0xe0, 0xcb, 0x99, 0x5b, 0x16, 0x9d, 0x21, 0x35, 0x79, 0x02, 0x4c, 0xe7, 0x4d, 0x4b, 0x78, 0x45, 0x80, 0xb8, 0x8c, 0x96, 0xd2, 0x20, 0xc2, 0x16, 0xbf, 0xde,
0xf0, 0xcd, 0xfb, 0x95, 0x06, 0xa3, 0xa9, 0x1b, 0x0f, 0x2a, 0x4c, 0x96, 0xac, 0x0b, 0xd2, 0xbf, 0x52, 0x82, 0xe8, 0x0f, 0x1a, 0x4c, 0x0e, 0x5c, 0x01, 0xe8, 0x76, 0x91, 0xd9, 0xec, 0xbb, 0x6a,
0x99, 0x62, 0x2a, 0xba, 0x78, 0x2e, 0x13, 0xaf, 0x2f, 0x1d, 0xdd, 0xd7, 0x56, 0xea, 0x3f, 0x18, 0xfe, 0xce, 0xa9, 0xe5, 0x14, 0xda, 0x37, 0x04, 0xda, 0x35, 0x7c, 0x35, 0xf3, 0xc8, 0xa2, 0x6b,
0x84, 0x52, 0x74, 0x9b, 0xfa, 0xa9, 0x06, 0xe5, 0xe4, 0x35, 0xa2, 0xb8, 0x28, 0x32, 0x6e, 0x42, 0xab, 0x2e, 0x2f, 0x1d, 0x7e, 0x78, 0xbf, 0xd4, 0x60, 0x3c, 0x35, 0x64, 0xa1, 0xc2, 0x60, 0xc9,
0xc5, 0x88, 0xb3, 0x6e, 0x2a, 0x78, 0x5e, 0x20, 0xae, 0xa0, 0x99, 0x34, 0xe2, 0xe8, 0x12, 0xf2, 0x9a, 0xc9, 0xfe, 0xc3, 0x10, 0x53, 0xde, 0xc5, 0x0b, 0x99, 0x78, 0x7d, 0x69, 0xe8, 0x2d, 0x6d,
0x1b, 0x0d, 0xc6, 0xd2, 0x8d, 0x14, 0xdd, 0x2e, 0x72, 0x94, 0xd9, 0xdb, 0x67, 0xef, 0x9c, 0x54, 0xad, 0xf1, 0xc7, 0x12, 0x94, 0xa3, 0x01, 0xee, 0x27, 0x1a, 0x54, 0x92, 0x93, 0x4b, 0x71, 0x52,
0x4d, 0x21, 0x5c, 0x16, 0x08, 0x31, 0x3e, 0x9f, 0x8d, 0xb0, 0x26, 0x1b, 0x3f, 0xdf, 0xfb, 0xdf, 0x64, 0x0c, 0x5f, 0xc5, 0x88, 0xb3, 0x86, 0x23, 0xbc, 0x28, 0x10, 0x57, 0xd1, 0x5c, 0x1a, 0x71,
0x69, 0x30, 0x96, 0xee, 0xb9, 0xc5, 0x58, 0x33, 0xfb, 0x7d, 0x31, 0xd6, 0xec, 0xd6, 0x8e, 0x6b, 0x34, 0xf7, 0xfc, 0x5a, 0x83, 0x89, 0x74, 0x21, 0x45, 0x6f, 0x16, 0x19, 0xca, 0xac, 0xed, 0xf3,
0x02, 0xeb, 0x55, 0x7c, 0x29, 0x73, 0xff, 0x23, 0xc8, 0xb2, 0xd5, 0x73, 0xc8, 0xdf, 0xd1, 0x60, 0xb7, 0x4f, 0x2b, 0xa6, 0x10, 0xae, 0x0a, 0x84, 0x18, 0x5f, 0xca, 0x46, 0x58, 0x97, 0x85, 0x9f,
0x2c, 0x3d, 0x3c, 0x16, 0x43, 0xce, 0x1c, 0x36, 0x67, 0x73, 0x5a, 0x45, 0x5e, 0xd7, 0x0b, 0x8f, 0x9f, 0xfd, 0xef, 0x34, 0x98, 0x48, 0xd7, 0xdc, 0x62, 0xac, 0x99, 0xf5, 0xbe, 0x18, 0x6b, 0x76,
0xcf, 0x1a, 0xb5, 0x6c, 0x5e, 0x38, 0xf5, 0x6f, 0x95, 0x60, 0x48, 0x0e, 0x2d, 0xe8, 0x53, 0x0d, 0x69, 0xc7, 0x75, 0x81, 0xf5, 0x1a, 0xbe, 0x92, 0x79, 0xfe, 0x11, 0x64, 0x59, 0xea, 0x39, 0xe4,
0xc6, 0x1f, 0x52, 0x96, 0x1c, 0x61, 0x72, 0x3b, 0x51, 0x61, 0xd6, 0x65, 0x0d, 0x42, 0xf8, 0xa2, 0xef, 0x68, 0x30, 0x91, 0xee, 0x57, 0x8b, 0x21, 0x67, 0xf6, 0xb7, 0xf3, 0x39, 0xa5, 0x22, 0xaf,
0x00, 0x75, 0x1e, 0xf5, 0x80, 0x52, 0x6f, 0x91, 0x81, 0x74, 0xf9, 0xb9, 0x06, 0x67, 0x1f, 0x52, 0xea, 0x85, 0xd7, 0x67, 0x9d, 0x5a, 0xb6, 0x48, 0x9c, 0xdf, 0x6a, 0x30, 0x9e, 0xba, 0xce, 0x8b,
0xf6, 0x22, 0x64, 0x6f, 0x13, 0x9f, 0xd9, 0xa6, 0xed, 0x89, 0x01, 0x17, 0xdd, 0xcd, 0x19, 0x38, 0x13, 0x27, 0xab, 0x6d, 0x98, 0x7f, 0xf3, 0x94, 0x52, 0xaf, 0xce, 0xf4, 0xf8, 0x45, 0x35, 0x94,
0x72, 0x35, 0xc2, 0x40, 0xdd, 0xce, 0x51, 0xcc, 0xd3, 0x52, 0x90, 0x57, 0x04, 0xe4, 0x4b, 0x08, 0xba, 0xc9, 0xfb, 0x08, 0x9e, 0x42, 0xdf, 0x2a, 0x43, 0x49, 0x36, 0x76, 0xe8, 0x13, 0x0d, 0x26,
0x67, 0x42, 0xf6, 0x52, 0xd8, 0x7e, 0xab, 0xc1, 0x99, 0x14, 0x0e, 0xea, 0xbf, 0x72, 0xfd, 0x36, 0xef, 0x53, 0x96, 0x6c, 0xf3, 0x72, 0x4b, 0x67, 0xe1, 0xae, 0xb2, 0x9a, 0x45, 0xfc, 0x9a, 0x80,
0x71, 0x4c, 0x8a, 0xea, 0x85, 0xee, 0x63, 0xe1, 0x10, 0xf2, 0xea, 0x89, 0x74, 0xd2, 0x75, 0x83, 0x77, 0x09, 0x0d, 0x78, 0x51, 0xbd, 0xd7, 0x06, 0xd2, 0xe4, 0x67, 0x1a, 0x5c, 0xb8, 0x4f, 0xd9,
0x16, 0xb3, 0x01, 0x27, 0x20, 0x7d, 0x57, 0x83, 0xd1, 0x24, 0xdc, 0x00, 0x5d, 0xcf, 0x71, 0xc8, 0x93, 0x70, 0x79, 0x87, 0xf8, 0xcc, 0x36, 0x6d, 0x4f, 0x0c, 0x01, 0xe8, 0x4e, 0x4e, 0x53, 0x96,
0x5b, 0x48, 0x2c, 0x16, 0xc2, 0xbb, 0x50, 0x04, 0x2f, 0xc8, 0x3b, 0x76, 0x14, 0x98, 0x6e, 0xec, 0x2b, 0x91, 0xe1, 0xd1, 0x94, 0x60, 0x9e, 0x94, 0x82, 0xbc, 0x26, 0x20, 0x5f, 0x41, 0x38, 0x13,
0xf9, 0x67, 0x1a, 0x4c, 0x25, 0xb1, 0xac, 0x91, 0x16, 0xc7, 0x98, 0xea, 0x89, 0xf9, 0x90, 0x42, 0xb2, 0x97, 0xc2, 0xf6, 0x1b, 0x0d, 0xce, 0xa7, 0x70, 0x50, 0xff, 0x99, 0xeb, 0x77, 0x89, 0x63,
0xe9, 0x10, 0xd9, 0x72, 0x11, 0xb2, 0x50, 0x01, 0x5f, 0x16, 0x00, 0x17, 0xd0, 0xf9, 0x4c, 0x80, 0x52, 0xd4, 0x28, 0x34, 0x1f, 0x33, 0x87, 0x90, 0xd7, 0x4f, 0x25, 0x93, 0x4e, 0x74, 0xb4, 0x9c,
0x7b, 0x21, 0x8a, 0x2e, 0x9c, 0x4e, 0xa2, 0xfb, 0x4a, 0x87, 0x76, 0x68, 0x6e, 0x6d, 0x5c, 0x2e, 0x0d, 0x38, 0x01, 0xe9, 0xbb, 0x1a, 0x8c, 0x27, 0xe1, 0x06, 0xe8, 0x46, 0x8e, 0x41, 0x5e, 0xf3,
0xf2, 0x2e, 0xd4, 0x31, 0x16, 0xae, 0xe7, 0xd0, 0x6c, 0xa6, 0xeb, 0x8f, 0x85, 0x0b, 0x0b, 0x4a, 0x62, 0xb6, 0x10, 0xde, 0xe5, 0x22, 0x78, 0x41, 0xde, 0x3d, 0xa9, 0xc0, 0xf4, 0x63, 0xcb, 0x3f,
0x0f, 0x29, 0xdb, 0xa6, 0xd4, 0xcf, 0x2f, 0xc5, 0xb9, 0x1c, 0x77, 0x42, 0xab, 0xc0, 0x8b, 0xc7, 0xd5, 0x60, 0x26, 0x89, 0x65, 0x83, 0x74, 0x38, 0xc6, 0x54, 0x11, 0xcf, 0x87, 0x14, 0x72, 0x87,
0x65, 0xea, 0x5f, 0xf4, 0x01, 0x3a, 0x3a, 0x39, 0xf2, 0x33, 0xa0, 0x92, 0x37, 0x8e, 0xe6, 0xa2, 0xc8, 0x56, 0x8b, 0x90, 0x85, 0x02, 0xf8, 0xaa, 0x00, 0xb8, 0x84, 0x2e, 0x65, 0x02, 0xdc, 0x0f,
0xf9, 0x72, 0x51, 0x63, 0x28, 0x1a, 0x70, 0xf1, 0xaa, 0x40, 0x7c, 0x03, 0x2f, 0xa7, 0x11, 0x87, 0x51, 0xf4, 0xe1, 0x5c, 0x12, 0xdd, 0x57, 0x7a, 0xb4, 0x47, 0x73, 0x73, 0xe3, 0x6a, 0x91, 0x75,
0xd3, 0xe9, 0x8d, 0x78, 0x7a, 0xad, 0xd1, 0x83, 0xf0, 0xfc, 0xff, 0xb5, 0x06, 0x95, 0xbc, 0x11, 0x21, 0x8e, 0xb1, 0x30, 0xbd, 0x80, 0xe6, 0x33, 0x4d, 0x7f, 0x24, 0x4c, 0x58, 0x50, 0xbe, 0x4f,
0x18, 0xbd, 0x77, 0xbc, 0x39, 0x24, 0x77, 0x78, 0xce, 0x6d, 0xb2, 0x27, 0x80, 0x1a, 0x8d, 0x2a, 0xd9, 0x0e, 0xa5, 0x7e, 0x7e, 0x2a, 0x2e, 0xe4, 0x98, 0x13, 0x52, 0x05, 0x56, 0x3c, 0xce, 0xd3,
0xf5, 0x3f, 0x0f, 0xc2, 0xd0, 0x23, 0xf1, 0x7f, 0x0b, 0xfa, 0x89, 0x6c, 0x18, 0x6b, 0xd1, 0x05, 0xf8, 0x7c, 0x08, 0xd0, 0xf1, 0x56, 0x97, 0x5f, 0x5a, 0xd5, 0xbc, 0xfe, 0x39, 0x17, 0xcd, 0x97,
0x30, 0x7e, 0xfa, 0xc9, 0x0d, 0x70, 0xe1, 0x19, 0x95, 0xfd, 0x84, 0x84, 0xaf, 0x0b, 0xac, 0x57, 0x8b, 0x0a, 0x43, 0x51, 0x47, 0x8e, 0xd7, 0x05, 0xe2, 0x9b, 0x78, 0x35, 0x8d, 0x38, 0x6c, 0xa7,
0x50, 0xcf, 0x19, 0x25, 0xff, 0xf9, 0x11, 0x7f, 0xe2, 0x18, 0x66, 0xec, 0x5d, 0x8e, 0xa5, 0x2c, 0x6f, 0xc6, 0xed, 0x76, 0x9d, 0x1e, 0x86, 0x0d, 0xcb, 0xaf, 0x34, 0xa8, 0xe6, 0xf5, 0xec, 0xe8,
0xf9, 0x74, 0xf2, 0x1f, 0x1c, 0x06, 0x59, 0x6f, 0x3e, 0xf8, 0x9a, 0x00, 0x74, 0x19, 0x5d, 0xcc, 0xed, 0x93, 0x35, 0x4e, 0xb9, 0xdd, 0x7e, 0xee, 0xad, 0x70, 0x0a, 0xa8, 0x51, 0x6f, 0xd5, 0xf8,
0x04, 0xc4, 0x6f, 0xd4, 0x35, 0x1a, 0xb9, 0xfe, 0x06, 0x00, 0x2f, 0x40, 0xf9, 0x72, 0x93, 0x0b, 0xcb, 0x19, 0x28, 0x3d, 0x10, 0xff, 0x49, 0xa1, 0x1f, 0xcb, 0x82, 0xb1, 0x11, 0x0d, 0xc9, 0xf1,
0xa4, 0x56, 0x04, 0xa4, 0xe7, 0xe9, 0x07, 0x5f, 0x12, 0x18, 0xe6, 0xd1, 0x5c, 0x26, 0x86, 0xae, 0xf3, 0x58, 0xae, 0x83, 0x0b, 0x2f, 0xd5, 0xec, 0x67, 0x36, 0x7c, 0x43, 0x60, 0x7d, 0x1d, 0x0d,
0x72, 0xf7, 0x6d, 0x0d, 0x26, 0x76, 0x98, 0x4f, 0x49, 0x7b, 0x2d, 0x7a, 0x50, 0xca, 0xc5, 0x70, 0x5c, 0xaa, 0xf2, 0xdf, 0x31, 0xf1, 0x47, 0x97, 0x61, 0xc6, 0xd6, 0x65, 0x1f, 0xcd, 0x92, 0xcf,
0x29, 0xc6, 0x20, 0x8b, 0xac, 0xea, 0x7b, 0x66, 0xb5, 0x7b, 0xab, 0x9a, 0x7c, 0x3f, 0x08, 0x27, 0x4b, 0xff, 0xc5, 0x65, 0x90, 0xf5, 0x2e, 0x86, 0xaf, 0x0b, 0x40, 0x57, 0xd1, 0x6b, 0x99, 0x80,
0x06, 0xb4, 0x94, 0xbf, 0xf8, 0xe8, 0x54, 0xe4, 0x8e, 0x6f, 0x6a, 0xe8, 0x47, 0x1a, 0x4c, 0x4a, 0x3a, 0x6e, 0x2b, 0xa8, 0xd3, 0xc8, 0xf4, 0x37, 0x00, 0x78, 0x02, 0xca, 0xd7, 0xad, 0x5c, 0x20,
0x14, 0x2f, 0x92, 0x6f, 0x61, 0xb9, 0x40, 0xae, 0x1f, 0x67, 0x57, 0x22, 0x40, 0x75, 0x01, 0xe8, 0xf5, 0xc2, 0x5b, 0x33, 0xfd, 0x3c, 0x86, 0xaf, 0x08, 0x0c, 0x8b, 0x68, 0x21, 0x13, 0x43, 0x5f,
0x3a, 0x5a, 0xc9, 0x07, 0x94, 0x48, 0x70, 0x85, 0xa9, 0xfe, 0xcf, 0x7e, 0x18, 0x78, 0xd0, 0x61, 0x99, 0xfb, 0xb6, 0x06, 0x53, 0xbb, 0xcc, 0xa7, 0xa4, 0xbb, 0x11, 0x3d, 0xba, 0xe5, 0x62, 0xb8,
0x4d, 0xbe, 0x3f, 0xf1, 0xc3, 0x4b, 0x2e, 0xa4, 0x7a, 0x11, 0xa4, 0xa3, 0x8f, 0x37, 0xf8, 0x82, 0x12, 0x63, 0x90, 0x49, 0x56, 0xf3, 0x3d, 0xb3, 0xd6, 0xbf, 0x55, 0x4b, 0xbe, 0xb1, 0x84, 0x2d,
0x00, 0x76, 0x0e, 0x9d, 0x4d, 0x03, 0xb3, 0x1d, 0x9b, 0xd9, 0xa4, 0x65, 0xbf, 0xa1, 0x16, 0xfa, 0x0e, 0x5a, 0xc9, 0xdf, 0x7c, 0x74, 0x2b, 0x72, 0xc3, 0x6f, 0x68, 0xe8, 0x87, 0x1a, 0x4c, 0x4b,
0x44, 0x83, 0xc1, 0x27, 0x6e, 0xc3, 0x76, 0xd0, 0xb5, 0xc2, 0xe7, 0xf6, 0xf8, 0x45, 0xb8, 0x38, 0x14, 0x4f, 0x92, 0xef, 0x85, 0xb9, 0x40, 0x6e, 0x9c, 0xe4, 0x54, 0x22, 0x40, 0x0d, 0x01, 0xe8,
0x40, 0xc9, 0xe7, 0xdd, 0x70, 0x62, 0xc6, 0x93, 0x69, 0x1c, 0x2d, 0xee, 0x97, 0x77, 0xa0, 0x4f, 0x06, 0x5a, 0xcb, 0x07, 0x94, 0x08, 0x70, 0x85, 0xa9, 0xf1, 0xaf, 0x61, 0x18, 0xb9, 0xd7, 0x63,
0x35, 0x18, 0xda, 0xb1, 0x1b, 0x4e, 0xc7, 0xfb, 0x6f, 0xa2, 0x58, 0x10, 0x28, 0xce, 0xe2, 0x9e, 0x6d, 0x7e, 0x3e, 0xf1, 0xe3, 0x54, 0x2e, 0xa4, 0x46, 0x11, 0xa4, 0xe3, 0x0f, 0x5c, 0xf8, 0xb2,
0xcb, 0x64, 0x20, 0x1c, 0x73, 0x18, 0x5f, 0x85, 0xa1, 0x27, 0x6e, 0xc3, 0xed, 0xb0, 0xdc, 0x4d, 0x00, 0x76, 0x11, 0x5d, 0x48, 0x03, 0xb3, 0x1d, 0x9b, 0xd9, 0xa4, 0x63, 0xbf, 0xa0, 0x16, 0xfa,
0xc8, 0x6b, 0x66, 0x39, 0xa6, 0x5b, 0xc2, 0xda, 0x7d, 0x6d, 0x65, 0xad, 0xfc, 0xa7, 0xb7, 0xf3, 0x58, 0x83, 0x33, 0xef, 0xb9, 0x2d, 0xdb, 0x41, 0xd7, 0x0b, 0xff, 0x92, 0x88, 0x5f, 0xcd, 0x8b,
0xda, 0x5f, 0xde, 0xce, 0x6b, 0x7f, 0x7f, 0x3b, 0xaf, 0xed, 0x0d, 0x09, 0xf5, 0xd5, 0x7f, 0x05, 0x1d, 0x94, 0x7c, 0x02, 0x0f, 0x5b, 0x7c, 0x3c, 0x9d, 0xc6, 0xd1, 0xe1, 0x76, 0x79, 0x05, 0xfa,
0x00, 0x00, 0xff, 0xff, 0x1f, 0xcc, 0x40, 0xa1, 0x9b, 0x1e, 0x00, 0x00, 0x44, 0x83, 0xd2, 0xae, 0xdd, 0x72, 0x7a, 0xde, 0xff, 0x12, 0xc5, 0x92, 0x40, 0x71, 0x01, 0x0f,
0x4c, 0xbf, 0x81, 0x30, 0xcc, 0x61, 0x7c, 0x15, 0x4a, 0xef, 0xb9, 0x2d, 0xb7, 0xc7, 0x72, 0x0f,
0x21, 0xaf, 0x98, 0xe5, 0xa8, 0xee, 0x08, 0x6d, 0x6f, 0x69, 0x6b, 0x1b, 0x95, 0x3f, 0xbf, 0x5c,
0xd4, 0xfe, 0xfa, 0x72, 0x51, 0xfb, 0xc7, 0xcb, 0x45, 0x6d, 0xbf, 0x24, 0xc4, 0xd7, 0xff, 0x1d,
0x00, 0x00, 0xff, 0xff, 0x17, 0xe3, 0x4f, 0x1d, 0xbf, 0x1f, 0x00, 0x00,
} }
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
@@ -2133,6 +2232,7 @@ type AccountsClient interface {
BackupAccounts(ctx context.Context, in *BackupAccountsRequest, opts ...grpc.CallOption) (*BackupAccountsResponse, error) BackupAccounts(ctx context.Context, in *BackupAccountsRequest, opts ...grpc.CallOption) (*BackupAccountsResponse, error)
DeleteAccounts(ctx context.Context, in *DeleteAccountsRequest, opts ...grpc.CallOption) (*DeleteAccountsResponse, error) DeleteAccounts(ctx context.Context, in *DeleteAccountsRequest, opts ...grpc.CallOption) (*DeleteAccountsResponse, error)
ChangePassword(ctx context.Context, in *ChangePasswordRequest, opts ...grpc.CallOption) (*empty.Empty, error) ChangePassword(ctx context.Context, in *ChangePasswordRequest, opts ...grpc.CallOption) (*empty.Empty, error)
VoluntaryExit(ctx context.Context, in *VoluntaryExitRequest, opts ...grpc.CallOption) (*VoluntaryExitResponse, error)
} }
type accountsClient struct { type accountsClient struct {
@@ -2179,12 +2279,22 @@ func (c *accountsClient) ChangePassword(ctx context.Context, in *ChangePasswordR
return out, nil return out, nil
} }
func (c *accountsClient) VoluntaryExit(ctx context.Context, in *VoluntaryExitRequest, opts ...grpc.CallOption) (*VoluntaryExitResponse, error) {
out := new(VoluntaryExitResponse)
err := c.cc.Invoke(ctx, "/ethereum.validator.accounts.v2.Accounts/VoluntaryExit", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// AccountsServer is the server API for Accounts service. // AccountsServer is the server API for Accounts service.
type AccountsServer interface { type AccountsServer interface {
ListAccounts(context.Context, *ListAccountsRequest) (*ListAccountsResponse, error) ListAccounts(context.Context, *ListAccountsRequest) (*ListAccountsResponse, error)
BackupAccounts(context.Context, *BackupAccountsRequest) (*BackupAccountsResponse, error) BackupAccounts(context.Context, *BackupAccountsRequest) (*BackupAccountsResponse, error)
DeleteAccounts(context.Context, *DeleteAccountsRequest) (*DeleteAccountsResponse, error) DeleteAccounts(context.Context, *DeleteAccountsRequest) (*DeleteAccountsResponse, error)
ChangePassword(context.Context, *ChangePasswordRequest) (*empty.Empty, error) ChangePassword(context.Context, *ChangePasswordRequest) (*empty.Empty, error)
VoluntaryExit(context.Context, *VoluntaryExitRequest) (*VoluntaryExitResponse, error)
} }
// UnimplementedAccountsServer can be embedded to have forward compatible implementations. // UnimplementedAccountsServer can be embedded to have forward compatible implementations.
@@ -2203,6 +2313,9 @@ func (*UnimplementedAccountsServer) DeleteAccounts(ctx context.Context, req *Del
func (*UnimplementedAccountsServer) ChangePassword(ctx context.Context, req *ChangePasswordRequest) (*empty.Empty, error) { func (*UnimplementedAccountsServer) ChangePassword(ctx context.Context, req *ChangePasswordRequest) (*empty.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method ChangePassword not implemented") return nil, status.Errorf(codes.Unimplemented, "method ChangePassword not implemented")
} }
func (*UnimplementedAccountsServer) VoluntaryExit(ctx context.Context, req *VoluntaryExitRequest) (*VoluntaryExitResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method VoluntaryExit not implemented")
}
func RegisterAccountsServer(s *grpc.Server, srv AccountsServer) { func RegisterAccountsServer(s *grpc.Server, srv AccountsServer) {
s.RegisterService(&_Accounts_serviceDesc, srv) s.RegisterService(&_Accounts_serviceDesc, srv)
@@ -2280,6 +2393,24 @@ func _Accounts_ChangePassword_Handler(srv interface{}, ctx context.Context, dec
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _Accounts_VoluntaryExit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(VoluntaryExitRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AccountsServer).VoluntaryExit(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/ethereum.validator.accounts.v2.Accounts/VoluntaryExit",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AccountsServer).VoluntaryExit(ctx, req.(*VoluntaryExitRequest))
}
return interceptor(ctx, in, info, handler)
}
var _Accounts_serviceDesc = grpc.ServiceDesc{ var _Accounts_serviceDesc = grpc.ServiceDesc{
ServiceName: "ethereum.validator.accounts.v2.Accounts", ServiceName: "ethereum.validator.accounts.v2.Accounts",
HandlerType: (*AccountsServer)(nil), HandlerType: (*AccountsServer)(nil),
@@ -2300,6 +2431,10 @@ var _Accounts_serviceDesc = grpc.ServiceDesc{
MethodName: "ChangePassword", MethodName: "ChangePassword",
Handler: _Accounts_ChangePassword_Handler, Handler: _Accounts_ChangePassword_Handler,
}, },
{
MethodName: "VoluntaryExit",
Handler: _Accounts_VoluntaryExit_Handler,
},
}, },
Streams: []grpc.StreamDesc{}, Streams: []grpc.StreamDesc{},
Metadata: "proto/validator/accounts/v2/web_api.proto", Metadata: "proto/validator/accounts/v2/web_api.proto",
@@ -4232,6 +4367,78 @@ func (m *BeaconStatusResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil return len(dAtA) - i, nil
} }
func (m *VoluntaryExitRequest) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *VoluntaryExitRequest) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *VoluntaryExitRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.XXX_unrecognized != nil {
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if len(m.PublicKeys) > 0 {
for iNdEx := len(m.PublicKeys) - 1; iNdEx >= 0; iNdEx-- {
i -= len(m.PublicKeys[iNdEx])
copy(dAtA[i:], m.PublicKeys[iNdEx])
i = encodeVarintWebApi(dAtA, i, uint64(len(m.PublicKeys[iNdEx])))
i--
dAtA[i] = 0xa
}
}
return len(dAtA) - i, nil
}
func (m *VoluntaryExitResponse) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *VoluntaryExitResponse) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *VoluntaryExitResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.XXX_unrecognized != nil {
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if len(m.ExitedKeys) > 0 {
for iNdEx := len(m.ExitedKeys) - 1; iNdEx >= 0; iNdEx-- {
i -= len(m.ExitedKeys[iNdEx])
copy(dAtA[i:], m.ExitedKeys[iNdEx])
i = encodeVarintWebApi(dAtA, i, uint64(len(m.ExitedKeys[iNdEx])))
i--
dAtA[i] = 0xa
}
}
return len(dAtA) - i, nil
}
func (m *BackupAccountsRequest) Marshal() (dAtA []byte, err error) { func (m *BackupAccountsRequest) Marshal() (dAtA []byte, err error) {
size := m.Size() size := m.Size()
dAtA = make([]byte, size) dAtA = make([]byte, size)
@@ -4971,6 +5178,42 @@ func (m *BeaconStatusResponse) Size() (n int) {
return n return n
} }
func (m *VoluntaryExitRequest) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if len(m.PublicKeys) > 0 {
for _, b := range m.PublicKeys {
l = len(b)
n += 1 + l + sovWebApi(uint64(l))
}
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func (m *VoluntaryExitResponse) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if len(m.ExitedKeys) > 0 {
for _, b := range m.ExitedKeys {
l = len(b)
n += 1 + l + sovWebApi(uint64(l))
}
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func (m *BackupAccountsRequest) Size() (n int) { func (m *BackupAccountsRequest) Size() (n int) {
if m == nil { if m == nil {
return 0 return 0
@@ -5114,7 +5357,7 @@ func (m *CreateWalletRequest) Unmarshal(dAtA []byte) error {
switch fieldNum { switch fieldNum {
case 1: case 1:
if wireType != 0 { if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Keymanager", wireType) return fmt.Errorf("proto: wrong wireType = %d for field keymanager", wireType)
} }
m.Keymanager = 0 m.Keymanager = 0
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
@@ -8058,6 +8301,172 @@ func (m *BeaconStatusResponse) Unmarshal(dAtA []byte) error {
} }
return nil return nil
} }
func (m *VoluntaryExitRequest) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowWebApi
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: VoluntaryExitRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: VoluntaryExitRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field PublicKeys", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowWebApi
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthWebApi
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthWebApi
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.PublicKeys = append(m.PublicKeys, make([]byte, postIndex-iNdEx))
copy(m.PublicKeys[len(m.PublicKeys)-1], dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipWebApi(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthWebApi
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *VoluntaryExitResponse) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowWebApi
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: VoluntaryExitResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: VoluntaryExitResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ExitedKeys", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowWebApi
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthWebApi
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthWebApi
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.ExitedKeys = append(m.ExitedKeys, make([]byte, postIndex-iNdEx))
copy(m.ExitedKeys[len(m.ExitedKeys)-1], dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipWebApi(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthWebApi
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *BackupAccountsRequest) Unmarshal(dAtA []byte) error { func (m *BackupAccountsRequest) Unmarshal(dAtA []byte) error {
l := len(dAtA) l := len(dAtA)
iNdEx := 0 iNdEx := 0

View File

@@ -62,6 +62,12 @@ service Accounts {
body: "*" body: "*"
}; };
} }
rpc VoluntaryExit(VoluntaryExitRequest) returns (VoluntaryExitResponse) {
option (google.api.http) = {
post: "/v2/validator/accounts/voluntary-exit",
body: "*"
};
}
} }
service Beacon { service Beacon {
@@ -365,6 +371,16 @@ message BeaconStatusResponse {
ethereum.eth.v1alpha1.ChainHead chain_head = 6; ethereum.eth.v1alpha1.ChainHead chain_head = 6;
} }
message VoluntaryExitRequest {
// List of public keys to voluntarily exit.
repeated bytes public_keys = 1;
}
message VoluntaryExitResponse {
// List of keys that successfully exited.
repeated bytes exited_keys = 1;
}
message BackupAccountsRequest { message BackupAccountsRequest {
// List of public keys to backup. // List of public keys to backup.
repeated bytes public_keys = 1; repeated bytes public_keys = 1;
@@ -386,6 +402,7 @@ message DeleteAccountsResponse {
// List of public keys successfully deleted. // List of public keys successfully deleted.
repeated bytes deleted_keys = 1; repeated bytes deleted_keys = 1;
} }
message ExportSlashingProtectionResponse { message ExportSlashingProtectionResponse {
// JSON representation of the slash protection // JSON representation of the slash protection
string file = 1; string file = 1;

View File

@@ -8,9 +8,6 @@ package ethereum_validator_accounts_v2
import ( import (
context "context" context "context"
reflect "reflect"
sync "sync"
_ "github.com/gogo/protobuf/gogoproto" _ "github.com/gogo/protobuf/gogoproto"
proto "github.com/golang/protobuf/proto" proto "github.com/golang/protobuf/proto"
empty "github.com/golang/protobuf/ptypes/empty" empty "github.com/golang/protobuf/ptypes/empty"
@@ -21,6 +18,8 @@ import (
status "google.golang.org/grpc/status" status "google.golang.org/grpc/status"
protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl" protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
) )
const ( const (

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,7 @@ import (
"github.com/golang/protobuf/ptypes/empty" "github.com/golang/protobuf/ptypes/empty"
"github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/grpc-ecosystem/grpc-gateway/utilities" "github.com/grpc-ecosystem/grpc-gateway/utilities"
eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/grpclog" "google.golang.org/grpc/grpclog"
@@ -311,6 +311,40 @@ func local_request_Accounts_ChangePassword_0(ctx context.Context, marshaler runt
} }
func request_Accounts_VoluntaryExit_0(ctx context.Context, marshaler runtime.Marshaler, client AccountsClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq VoluntaryExitRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.VoluntaryExit(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Accounts_VoluntaryExit_0(ctx context.Context, marshaler runtime.Marshaler, server AccountsServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq VoluntaryExitRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.VoluntaryExit(ctx, &protoReq)
return msg, metadata, err
}
func request_Beacon_GetBeaconStatus_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { func request_Beacon_GetBeaconStatus_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq empty.Empty var protoReq empty.Empty
var metadata runtime.ServerMetadata var metadata runtime.ServerMetadata
@@ -1007,6 +1041,29 @@ func RegisterAccountsHandlerServer(ctx context.Context, mux *runtime.ServeMux, s
}) })
mux.Handle("POST", pattern_Accounts_VoluntaryExit_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Accounts_VoluntaryExit_0(rctx, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Accounts_VoluntaryExit_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil return nil
} }
@@ -1711,6 +1768,26 @@ func RegisterAccountsHandlerClient(ctx context.Context, mux *runtime.ServeMux, c
}) })
mux.Handle("POST", pattern_Accounts_VoluntaryExit_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Accounts_VoluntaryExit_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Accounts_VoluntaryExit_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil return nil
} }
@@ -1722,6 +1799,8 @@ var (
pattern_Accounts_DeleteAccounts_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"v2", "validator", "wallet", "accounts", "delete"}, "", runtime.AssumeColonVerbOpt(true))) pattern_Accounts_DeleteAccounts_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"v2", "validator", "wallet", "accounts", "delete"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Accounts_ChangePassword_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v2", "validator", "password", "edit"}, "", runtime.AssumeColonVerbOpt(true))) pattern_Accounts_ChangePassword_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v2", "validator", "password", "edit"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Accounts_VoluntaryExit_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v2", "validator", "accounts", "voluntary-exit"}, "", runtime.AssumeColonVerbOpt(true)))
) )
var ( var (
@@ -1732,6 +1811,8 @@ var (
forward_Accounts_DeleteAccounts_0 = runtime.ForwardResponseMessage forward_Accounts_DeleteAccounts_0 = runtime.ForwardResponseMessage
forward_Accounts_ChangePassword_0 = runtime.ForwardResponseMessage forward_Accounts_ChangePassword_0 = runtime.ForwardResponseMessage
forward_Accounts_VoluntaryExit_0 = runtime.ForwardResponseMessage
) )
// RegisterBeaconHandlerFromEndpoint is same as RegisterBeaconHandler but // RegisterBeaconHandlerFromEndpoint is same as RegisterBeaconHandler but

View File

@@ -2,6 +2,7 @@ package accounts
import ( import (
"bytes" "bytes"
"context"
"fmt" "fmt"
"io" "io"
"strings" "strings"
@@ -25,12 +26,13 @@ import (
"google.golang.org/grpc" "google.golang.org/grpc"
) )
type performExitCfg struct { // PerformExitCfg for account voluntary exits.
validatorClient ethpb.BeaconNodeValidatorClient type PerformExitCfg struct {
nodeClient ethpb.NodeClient ValidatorClient ethpb.BeaconNodeValidatorClient
keymanager keymanager.IKeymanager NodeClient ethpb.NodeClient
rawPubKeys [][]byte Keymanager keymanager.IKeymanager
formattedPubKeys []string RawPubKeys [][]byte
FormattedPubKeys []string
} }
const exitPassphrase = "Exit my validator" const exitPassphrase = "Exit my validator"
@@ -56,14 +58,14 @@ func ExitAccountsCli(cliCtx *cli.Context, r io.Reader) error {
return err return err
} }
cfg := performExitCfg{ cfg := PerformExitCfg{
*validatorClient, *validatorClient,
*nodeClient, *nodeClient,
kManager, kManager,
rawPubKeys, rawPubKeys,
trimmedPubKeys, trimmedPubKeys,
} }
rawExitedKeys, trimmedExitedKeys, err := performExit(cliCtx, cfg) rawExitedKeys, trimmedExitedKeys, err := PerformVoluntaryExit(cliCtx.Context, cfg)
if err != nil { if err != nil {
return err return err
} }
@@ -72,6 +74,44 @@ func ExitAccountsCli(cliCtx *cli.Context, r io.Reader) error {
return nil return nil
} }
// PerformVoluntaryExit uses gRPC clients to submit a voluntary exit message to a beacon node.
func PerformVoluntaryExit(
ctx context.Context, cfg PerformExitCfg,
) (rawExitedKeys [][]byte, formattedExitedKeys []string, err error) {
var rawNotExitedKeys [][]byte
for i, key := range cfg.RawPubKeys {
if err := client.ProposeExit(ctx, cfg.ValidatorClient, cfg.NodeClient, cfg.Keymanager.Sign, key); err != nil {
rawNotExitedKeys = append(rawNotExitedKeys, key)
msg := err.Error()
if strings.Contains(msg, blocks.ValidatorAlreadyExitedMsg) ||
strings.Contains(msg, blocks.ValidatorCannotExitYetMsg) {
log.Warningf("Could not perform voluntary exit for account %s: %s", cfg.FormattedPubKeys[i], msg)
} else {
log.WithError(err).Errorf("voluntary exit failed for account %s", cfg.FormattedPubKeys[i])
}
}
}
rawExitedKeys = make([][]byte, 0)
formattedExitedKeys = make([]string, 0)
for i, key := range cfg.RawPubKeys {
found := false
for _, notExited := range rawNotExitedKeys {
if bytes.Equal(notExited, key) {
found = true
break
}
}
if !found {
rawExitedKeys = append(rawExitedKeys, key)
formattedExitedKeys = append(formattedExitedKeys, cfg.FormattedPubKeys[i])
}
}
return rawExitedKeys, formattedExitedKeys, nil
}
func prepareWallet(cliCtx *cli.Context) (validatingPublicKeys [][48]byte, km keymanager.IKeymanager, err error) { func prepareWallet(cliCtx *cli.Context) (validatingPublicKeys [][48]byte, km keymanager.IKeymanager, err error) {
w, err := wallet.OpenWalletOrElseCli(cliCtx, func(cliCtx *cli.Context) (*wallet.Wallet, error) { w, err := wallet.OpenWalletOrElseCli(cliCtx, func(cliCtx *cli.Context) (*wallet.Wallet, error) {
return nil, wallet.ErrNoWalletFound return nil, wallet.ErrNoWalletFound
@@ -204,41 +244,6 @@ func prepareClients(cliCtx *cli.Context) (*ethpb.BeaconNodeValidatorClient, *eth
return &validatorClient, &nodeClient, nil return &validatorClient, &nodeClient, nil
} }
func performExit(cliCtx *cli.Context, cfg performExitCfg) (rawExitedKeys [][]byte, formattedExitedKeys []string, err error) {
var rawNotExitedKeys [][]byte
for i, key := range cfg.rawPubKeys {
if err := client.ProposeExit(cliCtx.Context, cfg.validatorClient, cfg.nodeClient, cfg.keymanager.Sign, key); err != nil {
rawNotExitedKeys = append(rawNotExitedKeys, key)
msg := err.Error()
if strings.Contains(msg, blocks.ValidatorAlreadyExitedMsg) ||
strings.Contains(msg, blocks.ValidatorCannotExitYetMsg) {
log.Warningf("Could not perform voluntary exit for account %s: %s", cfg.formattedPubKeys[i], msg)
} else {
log.WithError(err).Errorf("voluntary exit failed for account %s", cfg.formattedPubKeys[i])
}
}
}
rawExitedKeys = make([][]byte, 0)
formattedExitedKeys = make([]string, 0)
for i, key := range cfg.rawPubKeys {
found := false
for _, notExited := range rawNotExitedKeys {
if bytes.Equal(notExited, key) {
found = true
break
}
}
if !found {
rawExitedKeys = append(rawExitedKeys, key)
formattedExitedKeys = append(formattedExitedKeys, cfg.formattedPubKeys[i])
}
}
return rawExitedKeys, formattedExitedKeys, nil
}
func displayExitInfo(rawExitedKeys [][]byte, trimmedExitedKeys []string) { func displayExitInfo(rawExitedKeys [][]byte, trimmedExitedKeys []string) {
if len(rawExitedKeys) > 0 { if len(rawExitedKeys) > 0 {
urlFormattedPubKeys := make([]string, len(rawExitedKeys)) urlFormattedPubKeys := make([]string, len(rawExitedKeys))

View File

@@ -92,14 +92,14 @@ func TestExitAccountsCli_OK(t *testing.T) {
require.NotNil(t, rawPubKeys) require.NotNil(t, rawPubKeys)
require.NotNil(t, formattedPubKeys) require.NotNil(t, formattedPubKeys)
cfg := performExitCfg{ cfg := PerformExitCfg{
mockValidatorClient, mockValidatorClient,
mockNodeClient, mockNodeClient,
keymanager, keymanager,
rawPubKeys, rawPubKeys,
formattedPubKeys, formattedPubKeys,
} }
rawExitedKeys, formattedExitedKeys, err := performExit(cliCtx, cfg) rawExitedKeys, formattedExitedKeys, err := PerformVoluntaryExit(cliCtx.Context, cfg)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(rawExitedKeys)) require.Equal(t, 1, len(rawExitedKeys))
assert.DeepEqual(t, rawPubKeys[0], rawExitedKeys[0]) assert.DeepEqual(t, rawPubKeys[0], rawExitedKeys[0])
@@ -187,14 +187,14 @@ func TestExitAccountsCli_OK_AllPublicKeys(t *testing.T) {
require.NotNil(t, rawPubKeys) require.NotNil(t, rawPubKeys)
require.NotNil(t, formattedPubKeys) require.NotNil(t, formattedPubKeys)
cfg := performExitCfg{ cfg := PerformExitCfg{
mockValidatorClient, mockValidatorClient,
mockNodeClient, mockNodeClient,
keymanager, keymanager,
rawPubKeys, rawPubKeys,
formattedPubKeys, formattedPubKeys,
} }
rawExitedKeys, formattedExitedKeys, err := performExit(cliCtx, cfg) rawExitedKeys, formattedExitedKeys, err := PerformVoluntaryExit(cliCtx.Context, cfg)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(rawExitedKeys)) require.Equal(t, 2, len(rawExitedKeys))
assert.DeepEqual(t, rawPubKeys, rawExitedKeys) assert.DeepEqual(t, rawPubKeys, rawExitedKeys)

View File

@@ -174,3 +174,38 @@ func (s *Server) DeleteAccounts(
DeletedKeys: req.PublicKeysToDelete, DeletedKeys: req.PublicKeysToDelete,
}, nil }, nil
} }
// VoluntaryExit performs a voluntary exit for the validator keys specified in a request.
func (s *Server) VoluntaryExit(
ctx context.Context, req *pb.VoluntaryExitRequest,
) (*pb.VoluntaryExitResponse, error) {
if len(req.PublicKeys) == 0 {
return nil, status.Error(codes.InvalidArgument, "No public keys specified to delete")
}
if s.wallet == nil || s.keymanager == nil {
return nil, status.Error(codes.FailedPrecondition, "No wallet found")
}
if s.wallet.KeymanagerKind() != keymanager.Imported && s.wallet.KeymanagerKind() != keymanager.Derived {
return nil, status.Error(
codes.FailedPrecondition, "Only Imported or Derived wallets can submit voluntary exits",
)
}
formattedKeys := make([]string, len(req.PublicKeys))
for i, key := range req.PublicKeys {
formattedKeys[i] = fmt.Sprintf("%#x", key)
}
cfg := accounts.PerformExitCfg{
ValidatorClient: s.beaconNodeValidatorClient,
NodeClient: s.beaconNodeClient,
Keymanager: s.keymanager,
RawPubKeys: req.PublicKeys,
FormattedPubKeys: formattedKeys,
}
rawExitedKeys, _, err := accounts.PerformVoluntaryExit(ctx, cfg)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not perform voluntary exit: %v", err)
}
return &pb.VoluntaryExitResponse{
ExitedKeys: rawExitedKeys,
}, nil
}

View File

@@ -9,10 +9,15 @@ import (
"io/ioutil" "io/ioutil"
"path/filepath" "path/filepath"
"testing" "testing"
"time"
"github.com/gogo/protobuf/types"
"github.com/golang/mock/gomock"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/cmd/validator/flags" "github.com/prysmaticlabs/prysm/cmd/validator/flags"
pb "github.com/prysmaticlabs/prysm/proto/validator/accounts/v2" pb "github.com/prysmaticlabs/prysm/proto/validator/accounts/v2"
"github.com/prysmaticlabs/prysm/shared/bytesutil" "github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/mock"
"github.com/prysmaticlabs/prysm/shared/testutil/assert" "github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require" "github.com/prysmaticlabs/prysm/shared/testutil/require"
"github.com/prysmaticlabs/prysm/validator/accounts" "github.com/prysmaticlabs/prysm/validator/accounts"
@@ -233,3 +238,78 @@ func TestServer_DeleteAccounts_OK_ImportedWallet(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, len(pubKeys)-1, len(keys)) assert.Equal(t, len(pubKeys)-1, len(keys))
} }
func TestServer_VoluntaryExit(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
ctx := context.Background()
mockValidatorClient := mock.NewMockBeaconNodeValidatorClient(ctrl)
mockNodeClient := mock.NewMockNodeClient(ctrl)
mockValidatorClient.EXPECT().
ValidatorIndex(gomock.Any(), gomock.Any()).
Return(&ethpb.ValidatorIndexResponse{Index: 0}, nil)
mockValidatorClient.EXPECT().
ValidatorIndex(gomock.Any(), gomock.Any()).
Return(&ethpb.ValidatorIndexResponse{Index: 1}, nil)
// Any time in the past will suffice
genesisTime := &types.Timestamp{
Seconds: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC).Unix(),
}
mockNodeClient.EXPECT().
GetGenesis(gomock.Any(), gomock.Any()).
Times(2).
Return(&ethpb.Genesis{GenesisTime: genesisTime}, nil)
mockValidatorClient.EXPECT().
DomainData(gomock.Any(), gomock.Any()).
Times(2).
Return(&ethpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil)
mockValidatorClient.EXPECT().
ProposeExit(gomock.Any(), gomock.AssignableToTypeOf(&ethpb.SignedVoluntaryExit{})).
Times(2).
Return(&ethpb.ProposeExitResponse{}, nil)
localWalletDir := setupWalletDir(t)
defaultWalletPath = localWalletDir
// We attempt to create the wallet.
w, err := accounts.CreateWalletWithKeymanager(ctx, &accounts.CreateWalletConfig{
WalletCfg: &wallet.Config{
WalletDir: defaultWalletPath,
KeymanagerKind: keymanager.Derived,
WalletPassword: strongPass,
},
SkipMnemonicConfirm: true,
})
require.NoError(t, err)
km, err := w.InitializeKeymanager(ctx, iface.InitKeymanagerConfig{ListenForChanges: false})
require.NoError(t, err)
s := &Server{
keymanager: km,
walletInitialized: true,
wallet: w,
beaconNodeClient: mockNodeClient,
beaconNodeValidatorClient: mockValidatorClient,
}
numAccounts := 2
dr, ok := km.(*derived.Keymanager)
require.Equal(t, true, ok)
err = dr.RecoverAccountsFromMnemonic(ctx, constant.TestMnemonic, "", numAccounts)
require.NoError(t, err)
pubKeys, err := dr.FetchValidatingPublicKeys(ctx)
require.NoError(t, err)
rawPubKeys := make([][]byte, len(pubKeys))
for i, key := range pubKeys {
rawPubKeys[i] = key[:]
}
res, err := s.VoluntaryExit(ctx, &pb.VoluntaryExitRequest{
PublicKeys: rawPubKeys,
})
require.NoError(t, err)
require.DeepEqual(t, rawPubKeys, res.ExitedKeys)
}

View File

@@ -49,6 +49,7 @@ func (s *Server) registerBeaconClient() error {
s.beaconChainClient = ethpb.NewBeaconChainClient(conn) s.beaconChainClient = ethpb.NewBeaconChainClient(conn)
s.beaconNodeClient = ethpb.NewNodeClient(conn) s.beaconNodeClient = ethpb.NewNodeClient(conn)
s.beaconNodeHealthClient = healthpb.NewHealthClient(conn) s.beaconNodeHealthClient = healthpb.NewHealthClient(conn)
s.beaconNodeValidatorClient = ethpb.NewBeaconNodeValidatorClient(conn)
return nil return nil
} }

View File

@@ -58,41 +58,42 @@ type Config struct {
// Server defining a gRPC server for the remote signer API. // Server defining a gRPC server for the remote signer API.
type Server struct { type Server struct {
logsStreamer logutil.Streamer logsStreamer logutil.Streamer
streamLogsBufferSize int streamLogsBufferSize int
beaconChainClient ethpb.BeaconChainClient beaconChainClient ethpb.BeaconChainClient
beaconNodeClient ethpb.NodeClient beaconNodeClient ethpb.NodeClient
beaconNodeHealthClient healthpb.HealthClient beaconNodeValidatorClient ethpb.BeaconNodeValidatorClient
valDB db.Database beaconNodeHealthClient healthpb.HealthClient
ctx context.Context valDB db.Database
cancel context.CancelFunc ctx context.Context
beaconClientEndpoint string cancel context.CancelFunc
clientMaxCallRecvMsgSize int beaconClientEndpoint string
clientGrpcRetries uint clientMaxCallRecvMsgSize int
clientGrpcRetryDelay time.Duration clientGrpcRetries uint
clientGrpcHeaders []string clientGrpcRetryDelay time.Duration
clientWithCert string clientGrpcHeaders []string
host string clientWithCert string
port string host string
listener net.Listener port string
keymanager keymanager.IKeymanager listener net.Listener
withCert string keymanager keymanager.IKeymanager
withKey string withCert string
credentialError error withKey string
grpcServer *grpc.Server credentialError error
jwtKey []byte grpcServer *grpc.Server
validatorService *client.ValidatorService jwtKey []byte
syncChecker client.SyncChecker validatorService *client.ValidatorService
genesisFetcher client.GenesisFetcher syncChecker client.SyncChecker
walletDir string genesisFetcher client.GenesisFetcher
wallet *wallet.Wallet walletDir string
walletInitializedFeed *event.Feed wallet *wallet.Wallet
walletInitialized bool walletInitializedFeed *event.Feed
nodeGatewayEndpoint string walletInitialized bool
validatorMonitoringHost string nodeGatewayEndpoint string
validatorMonitoringPort int validatorMonitoringHost string
validatorGatewayHost string validatorMonitoringPort int
validatorGatewayPort int validatorGatewayHost string
validatorGatewayPort int
} }
// NewServer instantiates a new gRPC server. // NewServer instantiates a new gRPC server.

View File

@@ -4,14 +4,14 @@ import (
"bytes" "bytes"
"context" "context"
"encoding/json" "encoding/json"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
"github.com/golang/protobuf/ptypes/empty" "github.com/golang/protobuf/ptypes/empty"
"github.com/pkg/errors" "github.com/pkg/errors"
pb "github.com/prysmaticlabs/prysm/proto/validator/accounts/v2" pb "github.com/prysmaticlabs/prysm/proto/validator/accounts/v2"
slashing "github.com/prysmaticlabs/prysm/validator/slashing-protection/local/standard-protection-format" slashing "github.com/prysmaticlabs/prysm/validator/slashing-protection/local/standard-protection-format"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
) )
// ExportSlashingProtection handles the rpc call returning the json slashing history. // ExportSlashingProtection handles the rpc call returning the json slashing history.

View File

@@ -3,9 +3,9 @@ package rpc
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"github.com/golang/protobuf/ptypes/empty"
"testing" "testing"
"github.com/golang/protobuf/ptypes/empty"
pb "github.com/prysmaticlabs/prysm/proto/validator/accounts/v2" pb "github.com/prysmaticlabs/prysm/proto/validator/accounts/v2"
"github.com/prysmaticlabs/prysm/shared/testutil/require" "github.com/prysmaticlabs/prysm/shared/testutil/require"
"github.com/prysmaticlabs/prysm/validator/accounts" "github.com/prysmaticlabs/prysm/validator/accounts"