Check token funds when handling community requests to join

This adds checks to `HandleCommunityRequestToJoin` and
`AcceptRequestToJoinCommunity` that ensure a given user's revealed
wallet addresses own the token funds required by a community.

When community has token permissions of type `BECOME_MEMBER`, the
following happens when the owner receives a request:

1. Upon verifying provided wallet addresses by the requester, the owner
   node accumulates all token funds related to the given wallets that
   match the token criteria in the configured permissions
2. If the requester does not meet the necessary requirements, the
   request to join will be declined. If the requester does have the
   funds, he'll either be automatically accepted to the community, or
   enters the next stage where an owner needs to manually accept the
   request.
3. The the community does not automatically accept users, then the funds
   check will happen again, when the owner tries to manually accept the
   request. If the necessary funds do not exist at this stage, the
   request will be declined
4. Upon accepting, whether automatically or manually, the owner adds the
   requester's wallet addresses to the `CommunityDescription`, such that
   they can be retrieved later when doing periodic checks or when
   permissions have changed.
This commit is contained in:
Pascal Precht 2023-03-16 15:35:33 +01:00 committed by Follow the white rabbit
parent 48eb705284
commit 2cbced95c5
11 changed files with 367 additions and 127 deletions

View File

@ -1606,7 +1606,7 @@ func (b *GethStatusBackend) injectAccountsIntoWakuService(w types.WakuKeyManager
}
if st != nil {
if err := st.InitProtocol(b.statusNode.GethNode().Config().Name, identity, b.appDB, b.statusNode.HTTPServer(), b.multiaccountsDB, acc, b.accountManager, logutils.ZapLogger()); err != nil {
if err := st.InitProtocol(b.statusNode.GethNode().Config().Name, identity, b.appDB, b.statusNode.HTTPServer(), b.multiaccountsDB, acc, b.accountManager, b.statusNode.RPCClient(), logutils.ZapLogger()); err != nil {
return err
}
// Set initial connection state

View File

@ -218,6 +218,7 @@ func main() {
protocol.WithPushNotificationServerConfig(&config.PushNotificationServerConfig),
protocol.WithDatabase(db),
protocol.WithTorrentConfig(&config.TorrentConfig),
protocol.WithRPCClient(backend.StatusNode().RPCClient()),
}
messenger, err := protocol.NewMessenger(

View File

@ -455,6 +455,9 @@ type CommunityChanges struct {
CategoriesAdded map[string]*protobuf.CommunityCategory `json:"categoriesAdded"`
CategoriesModified map[string]*protobuf.CommunityCategory `json:"categoriesModified"`
MemberWalletsRemoved []string `json:"memberWalletsRemoved"`
MemberWalletsAdded map[string][]string `json:"memberWalletsAdded"`
// ShouldMemberJoin indicates whether the user should join this community
// automatically
ShouldMemberJoin bool `json:"memberAdded"`
@ -1808,6 +1811,26 @@ func (o *Community) AllowsAllMembersToPinMessage() bool {
return o.config.CommunityDescription.AdminSettings != nil && o.config.CommunityDescription.AdminSettings.PinMessageAllMembersEnabled
}
func (o *Community) AddMemberWallet(memberID string, addresses []string) (*CommunityChanges, error) {
o.mutex.Lock()
defer o.mutex.Unlock()
if o.config.PrivateKey == nil {
return nil, ErrNotAdmin
}
if _, ok := o.config.CommunityDescription.Members[memberID]; !ok {
return nil, ErrMemberNotFound
}
o.config.CommunityDescription.Members[memberID].WalletAccounts = addresses
o.increaseClock()
changes := o.emptyCommunityChanges()
changes.MemberWalletsAdded[memberID] = o.config.CommunityDescription.Members[memberID].WalletAccounts
return changes, nil
}
func emptyCommunityChanges() *CommunityChanges {
return &CommunityChanges{
MembersAdded: make(map[string]*protobuf.CommunityMember),
@ -1820,6 +1843,9 @@ func emptyCommunityChanges() *CommunityChanges {
CategoriesRemoved: []string{},
CategoriesAdded: make(map[string]*protobuf.CommunityCategory),
CategoriesModified: make(map[string]*protobuf.CommunityCategory),
MemberWalletsRemoved: []string{},
MemberWalletsAdded: make(map[string][]string),
}
}

View File

@ -31,3 +31,6 @@ var ErrInvalidMessage = errors.New("invalid community description message")
var ErrMemberNotFound = errors.New("member not found")
var ErrTokenPermissionAlreadyExists = errors.New("token permission already exists")
var ErrTokenPermissionNotFound = errors.New("token permission not found")
var ErrNoPermissionToJoin = errors.New("member has no permission to join")
var ErrMemberWalletAlreadyExists = errors.New("member wallet already exists")
var ErrMemberWalletNotFound = errors.New("member wallet not found")

View File

@ -1,13 +1,17 @@
package communities
import (
"context"
"crypto/ecdsa"
"database/sql"
"fmt"
"io/ioutil"
"math"
"math/big"
"net"
"os"
"sort"
"strconv"
"strings"
"sync"
"time"
@ -21,6 +25,7 @@ import (
"github.com/pkg/errors"
"go.uber.org/zap"
gethcommon "github.com/ethereum/go-ethereum/common"
"github.com/status-im/status-go/account"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
@ -32,6 +37,7 @@ import (
"github.com/status-im/status-go/protocol/protobuf"
"github.com/status-im/status-go/protocol/requests"
"github.com/status-im/status-go/protocol/transport"
"github.com/status-im/status-go/services/wallet/token"
"github.com/status-im/status-go/signal"
)
@ -53,6 +59,7 @@ type Manager struct {
ensVerifier *ens.Verifier
identity *ecdsa.PrivateKey
accountsManager *account.GethManager
tokenManager *token.Manager
logger *zap.Logger
stdoutLogger *zap.Logger
transport *transport.Transport
@ -87,6 +94,7 @@ func (t *HistoryArchiveDownloadTask) Cancel() {
type managerOptions struct {
accountsManager *account.GethManager
tokenManager *token.Manager
}
type ManagerOption func(*managerOptions)
@ -97,6 +105,12 @@ func WithAccountManager(accountsManager *account.GethManager) ManagerOption {
}
}
func WithTokenManager(tokenManager *token.Manager) ManagerOption {
return func(opts *managerOptions) {
opts.tokenManager = tokenManager
}
}
func NewManager(identity *ecdsa.PrivateKey, db *sql.DB, encryptor *encryption.Protocol, logger *zap.Logger, verifier *ens.Verifier, transport *transport.Transport, torrentConfig *params.TorrentConfig, opts ...ManagerOption) (*Manager, error) {
if identity == nil {
return nil, errors.New("empty identity")
@ -140,6 +154,10 @@ func NewManager(identity *ecdsa.PrivateKey, db *sql.DB, encryptor *encryption.Pr
manager.accountsManager = managerConfig.accountsManager
}
if managerConfig.tokenManager != nil {
manager.tokenManager = managerConfig.tokenManager
}
if verifier != nil {
sub := verifier.Subscribe()
@ -1091,6 +1109,40 @@ func (m *Manager) AcceptRequestToJoin(request *requests.AcceptRequestToJoinCommu
return nil, err
}
becomeMemberPermissions := community.TokenPermissionsByType(protobuf.CommunityTokenPermission_BECOME_MEMBER)
addressesToAdd := make([]string, 0)
if len(becomeMemberPermissions) > 0 {
revealedAddresses, err := m.persistence.GetRequestToJoinRevealedAddresses(dbRequest.ID)
if err != nil {
return nil, err
}
walletAddresses := make([]gethcommon.Address, 0)
for _, walletAddress := range revealedAddresses {
walletAddresses = append(walletAddresses, gethcommon.HexToAddress(walletAddress))
}
hasPermission, err := m.checkPermissionToJoin(becomeMemberPermissions, walletAddresses)
if err != nil {
return nil, err
}
if !hasPermission {
pk, err := common.HexToPubkey(dbRequest.PublicKey)
if err != nil {
return nil, err
}
err = m.markRequestToJoinAsCanceled(pk, community)
if err != nil {
return nil, err
}
return community, ErrNoPermissionToJoin
}
addressesToAdd = append(addressesToAdd, revealedAddresses...)
}
pk, err := common.HexToPubkey(dbRequest.PublicKey)
if err != nil {
return nil, err
@ -1101,6 +1153,11 @@ func (m *Manager) AcceptRequestToJoin(request *requests.AcceptRequestToJoinCommu
return nil, err
}
_, err = community.AddMemberWallet(dbRequest.PublicKey, addressesToAdd)
if err != nil {
return nil, err
}
if err := m.markRequestToJoin(pk, community); err != nil {
return nil, err
}
@ -1228,6 +1285,27 @@ func (m *Manager) HandleCommunityRequestToJoin(signer *ecdsa.PublicKey, request
}
}
// provided wallet addresses seem to be legit, so let's check
// if the necessary token permission funds exist
verifiedAddresses := make([]gethcommon.Address, 0)
for walletAddress := range request.RevealedAddresses {
verifiedAddresses = append(verifiedAddresses, gethcommon.HexToAddress(walletAddress))
}
hasPermission, err := m.checkPermissionToJoin(becomeMemberPermissions, verifiedAddresses)
if err != nil {
return nil, err
}
if !hasPermission {
err = m.markRequestToJoinAsCanceled(signer, community)
if err != nil {
return nil, err
}
requestToJoin.State = RequestToJoinStateDeclined
return requestToJoin, nil
}
// Save revealed addresses + signatures so they can later be added
// to the community member list when the request is accepted
err = m.persistence.SaveRequestToJoinRevealedAddresses(requestToJoin)
@ -1235,7 +1313,7 @@ func (m *Manager) HandleCommunityRequestToJoin(signer *ecdsa.PublicKey, request
return nil, err
}
if acceptAutomatically {
if hasPermission && acceptAutomatically {
err = m.markRequestToJoin(signer, community)
if err != nil {
return nil, err
@ -1247,6 +1325,110 @@ func (m *Manager) HandleCommunityRequestToJoin(signer *ecdsa.PublicKey, request
return requestToJoin, nil
}
func (m *Manager) checkPermissionToJoin(permissions []*protobuf.CommunityTokenPermission, walletAddresses []gethcommon.Address) (bool, error) {
tokenAddresses, addressToSymbolMap := getTokenAddressesFromPermissions(permissions)
balances, err := m.getAccumulatedTokenBalances(walletAddresses, tokenAddresses, addressToSymbolMap)
if err != nil {
return false, err
}
hasPermission := false
for _, tokenPermission := range permissions {
if checkTokenCriteria(tokenPermission.TokenCriteria, balances) {
hasPermission = true
break
}
}
return hasPermission, nil
}
func checkTokenCriteria(tokenCriteria []*protobuf.TokenCriteria, balances map[string]*big.Float) bool {
result := true
hasERC20 := false
for _, tokenRequirement := range tokenCriteria {
// we gotta check for whether there are ERC20 token criteria
// in the first place, if we don't we'll return a false positive
if tokenRequirement.Type == protobuf.CommunityTokenType_ERC20 {
hasERC20 = true
amount, _ := strconv.ParseFloat(tokenRequirement.Amount, 32)
if balances[tokenRequirement.Symbol].Cmp(big.NewFloat(amount)) == -1 {
result = false
break
}
}
}
return hasERC20 && result
}
func (m *Manager) getAccumulatedTokenBalances(accounts []gethcommon.Address, tokenAddresses []gethcommon.Address, addressToToken map[gethcommon.Address]tokenData) (map[string]*big.Float, error) {
networks, err := m.tokenManager.RPCClient.NetworkManager.Get(false)
if err != nil {
return nil, err
}
chainIDs := make([]uint64, 0)
for _, network := range networks {
chainIDs = append(chainIDs, network.ChainID)
}
clients, err := m.tokenManager.RPCClient.EthClients(chainIDs)
if err != nil {
return nil, err
}
balancesByChain, err := m.tokenManager.GetBalancesByChain(context.Background(), clients, accounts, tokenAddresses)
if err != nil {
return nil, err
}
accumulatedBalances := make(map[string]*big.Float)
for _, accounts := range balancesByChain {
for _, contracts := range accounts {
for contract, value := range contracts {
if _, exists := accumulatedBalances[addressToToken[contract].Symbol]; !exists {
accumulatedBalances[addressToToken[contract].Symbol] = new(big.Float)
}
balance := new(big.Float).Quo(
new(big.Float).SetInt(value.ToInt()),
big.NewFloat(math.Pow(10, float64(addressToToken[contract].Decimals))),
)
prevBalance := accumulatedBalances[addressToToken[contract].Symbol]
accumulatedBalances[addressToToken[contract].Symbol].Add(prevBalance, balance)
}
}
}
return accumulatedBalances, nil
}
type tokenData struct {
Symbol string
Decimals int
}
func getTokenAddressesFromPermissions(tokenPermissions []*protobuf.CommunityTokenPermission) ([]gethcommon.Address, map[gethcommon.Address]tokenData) {
set := make(map[gethcommon.Address]bool)
addressToToken := make(map[gethcommon.Address]tokenData)
for _, tokenPermission := range tokenPermissions {
for _, token := range tokenPermission.TokenCriteria {
if token.Type == protobuf.CommunityTokenType_ERC20 {
for _, contractAddress := range token.ContractAddresses {
set[gethcommon.HexToAddress(contractAddress)] = true
addressToToken[gethcommon.HexToAddress(contractAddress)] = tokenData{
Symbol: token.Symbol,
Decimals: int(token.Decimals),
}
}
}
}
}
tokenAddresses := make([]gethcommon.Address, 0)
for tokenAddress := range set {
tokenAddresses = append(tokenAddresses, tokenAddress)
}
return tokenAddresses, addressToToken
}
func (m *Manager) HandleCommunityRequestToJoinResponse(signer *ecdsa.PublicKey, request *protobuf.CommunityRequestToJoinResponse) (*RequestToJoin, error) {
pkString := common.PubkeyToHex(&m.identity.PublicKey)

View File

@ -58,6 +58,7 @@ import (
"github.com/status-im/status-go/services/ext/mailservers"
mailserversDB "github.com/status-im/status-go/services/mailservers"
"github.com/status-im/status-go/services/wallet"
"github.com/status-im/status-go/services/wallet/token"
"github.com/status-im/status-go/telemetry"
)
@ -410,6 +411,10 @@ func NewMessenger(
managerOptions := []communities.ManagerOption{
communities.WithAccountManager(accountsManager),
}
if c.rpcClient != nil {
tokenManager := token.NewTokenManager(database, c.rpcClient, c.rpcClient.NetworkManager)
managerOptions = append(managerOptions, communities.WithTokenManager(tokenManager))
}
communitiesManager, err := communities.NewManager(identity, database, encryptionProtocol, logger, ensVerifier, transp, c.torrentConfig, managerOptions...)
if err != nil {

View File

@ -726,15 +726,27 @@ func (m *Messenger) AcceptRequestToJoinCommunity(request *requests.AcceptRequest
return nil, err
}
community, err := m.communitiesManager.AcceptRequestToJoin(request)
requestToJoin, err := m.communitiesManager.GetRequestToJoin(request.ID)
if err != nil {
return nil, err
}
requestToJoin, err := m.communitiesManager.GetRequestToJoin(request.ID)
community, err := m.communitiesManager.AcceptRequestToJoin(request)
if err != nil && err != communities.ErrNoPermissionToJoin {
return nil, err
}
if err == communities.ErrNoPermissionToJoin {
cancel := &requests.DeclineRequestToJoinCommunity{
ID: requestToJoin.ID,
}
response, err := m.DeclineRequestToJoinCommunity(cancel)
if err != nil {
return nil, err
}
response.AddCommunity(community)
return response, nil
}
pk, err := common.HexToPubkey(requestToJoin.PublicKey)
if err != nil {

View File

@ -175,6 +175,7 @@ func (m *Grant) GetClock() uint64 {
type CommunityMember struct {
Roles []CommunityMember_Roles `protobuf:"varint,1,rep,packed,name=roles,proto3,enum=protobuf.CommunityMember_Roles" json:"roles,omitempty"`
WalletAccounts []string `protobuf:"bytes,2,rep,name=wallet_accounts,json=walletAccounts,proto3" json:"wallet_accounts,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -212,6 +213,13 @@ func (m *CommunityMember) GetRoles() []CommunityMember_Roles {
return nil
}
func (m *CommunityMember) GetWalletAccounts() []string {
if m != nil {
return m.WalletAccounts
}
return nil
}
type CommunityTokenMetadata struct {
ContractAddresses map[uint64]string `protobuf:"bytes,1,rep,name=contract_addresses,json=contractAddresses,proto3" json:"contract_addresses,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"`
@ -1571,123 +1579,125 @@ func init() {
}
var fileDescriptor_f937943d74c1cd8b = []byte{
// 1880 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x58, 0x5f, 0x6f, 0x23, 0x49,
0x11, 0xdf, 0xf1, 0x9f, 0xc4, 0x2e, 0xdb, 0x59, 0xa7, 0x77, 0x93, 0x4c, 0xb2, 0xbb, 0x97, 0xec,
0x00, 0x22, 0x27, 0x84, 0x97, 0xcb, 0x81, 0x58, 0xdd, 0xc1, 0xdd, 0x79, 0x13, 0x6b, 0x31, 0x1b,
0xdb, 0xb9, 0x8e, 0xc3, 0x71, 0x27, 0x60, 0xd4, 0x99, 0xe9, 0x24, 0xad, 0x8c, 0x67, 0xcc, 0x74,
0x3b, 0xc2, 0x3c, 0xf0, 0xc4, 0x87, 0xe0, 0xfd, 0x5e, 0x11, 0x5f, 0x81, 0x07, 0x78, 0xe6, 0x11,
0x89, 0x37, 0x9e, 0x10, 0x1f, 0x03, 0xf5, 0x9f, 0x19, 0xcf, 0x38, 0x76, 0xb2, 0xe8, 0x40, 0xba,
0x27, 0x4f, 0x55, 0x57, 0x55, 0x57, 0x57, 0xfd, 0xba, 0xba, 0xca, 0xb0, 0xee, 0x45, 0xa3, 0xd1,
0x24, 0x64, 0x82, 0x51, 0xde, 0x1a, 0xc7, 0x91, 0x88, 0x50, 0x45, 0xfd, 0x9c, 0x4f, 0x2e, 0x76,
0x1e, 0x79, 0x57, 0x44, 0xb8, 0xcc, 0xa7, 0xa1, 0x60, 0x62, 0xaa, 0x97, 0x77, 0x6a, 0x34, 0x9c,
0x8c, 0x8c, 0xac, 0x73, 0x03, 0xe5, 0xd7, 0x31, 0x09, 0x05, 0x7a, 0x0e, 0xf5, 0xc4, 0xd2, 0xd4,
0x65, 0xbe, 0x6d, 0xed, 0x59, 0xfb, 0x75, 0x5c, 0x4b, 0x79, 0x5d, 0x1f, 0x3d, 0x81, 0xea, 0x88,
0x8e, 0xce, 0x69, 0x2c, 0xd7, 0x0b, 0x6a, 0xbd, 0xa2, 0x19, 0x5d, 0x1f, 0x6d, 0xc1, 0xaa, 0xd9,
0xcc, 0x2e, 0xee, 0x59, 0xfb, 0x55, 0xbc, 0x22, 0xc9, 0xae, 0x8f, 0x1e, 0x43, 0xd9, 0x0b, 0x22,
0xef, 0xda, 0x2e, 0xed, 0x59, 0xfb, 0x25, 0xac, 0x09, 0xe7, 0x4b, 0x0b, 0x1e, 0x1e, 0x26, 0xb6,
0x7b, 0xca, 0x08, 0xfa, 0x01, 0x94, 0xe3, 0x28, 0xa0, 0xdc, 0xb6, 0xf6, 0x8a, 0xfb, 0x6b, 0x07,
0xbb, 0xad, 0xe4, 0x1c, 0xad, 0x39, 0xc9, 0x16, 0x96, 0x62, 0x58, 0x4b, 0x3b, 0x9f, 0x43, 0x59,
0xd1, 0xa8, 0x09, 0xf5, 0xb3, 0xfe, 0x9b, 0xfe, 0xe0, 0xb3, 0xbe, 0x8b, 0x07, 0xc7, 0x9d, 0xe6,
0x03, 0x54, 0x87, 0x8a, 0xfc, 0x72, 0xdb, 0xc7, 0xc7, 0x4d, 0x0b, 0x6d, 0xc0, 0xba, 0xa2, 0x7a,
0xed, 0x7e, 0xfb, 0x75, 0xc7, 0x3d, 0x3b, 0xed, 0xe0, 0xd3, 0x66, 0x01, 0x6d, 0xc3, 0x86, 0x66,
0x0f, 0x8e, 0x3a, 0xb8, 0x3d, 0xec, 0xb8, 0x87, 0x83, 0xfe, 0xb0, 0xd3, 0x1f, 0x36, 0x8b, 0xce,
0xbf, 0x0a, 0xb0, 0x99, 0xee, 0x3d, 0x8c, 0xae, 0x69, 0xd8, 0xa3, 0x82, 0xf8, 0x44, 0x10, 0x74,
0x01, 0xc8, 0x8b, 0x42, 0x11, 0x13, 0x4f, 0xb8, 0xc4, 0xf7, 0x63, 0xca, 0xb9, 0xf1, 0xbc, 0x76,
0xf0, 0xc3, 0x05, 0x9e, 0xe7, 0xb4, 0x5b, 0x87, 0x46, 0xb5, 0x9d, 0x68, 0x76, 0x42, 0x11, 0x4f,
0xf1, 0xba, 0x37, 0xcf, 0x47, 0x7b, 0x50, 0xf3, 0x29, 0xf7, 0x62, 0x36, 0x16, 0x2c, 0x0a, 0x55,
0xd8, 0xab, 0x38, 0xcb, 0x92, 0x01, 0x66, 0x23, 0x72, 0x49, 0x4d, 0xdc, 0x35, 0x81, 0x3e, 0x80,
0xaa, 0x90, 0x5b, 0x0e, 0xa7, 0x63, 0xaa, 0x42, 0xbf, 0x76, 0xf0, 0x74, 0x99, 0x5b, 0x52, 0x06,
0xcf, 0xc4, 0xd1, 0x26, 0xac, 0xf0, 0xe9, 0xe8, 0x3c, 0x0a, 0xec, 0xb2, 0x4e, 0xa5, 0xa6, 0x10,
0x82, 0x52, 0x48, 0x46, 0xd4, 0x5e, 0x51, 0x5c, 0xf5, 0xbd, 0x73, 0x24, 0x23, 0xb4, 0xe8, 0x30,
0xa8, 0x09, 0xc5, 0x6b, 0x3a, 0x55, 0x40, 0x2a, 0x61, 0xf9, 0x29, 0x3d, 0xbd, 0x21, 0xc1, 0x84,
0x9a, 0x53, 0x68, 0xe2, 0x83, 0xc2, 0x4b, 0xcb, 0xf9, 0xa7, 0x05, 0x8f, 0x53, 0x9f, 0x4e, 0x68,
0x3c, 0x62, 0x9c, 0xb3, 0x28, 0xe4, 0x68, 0x1b, 0x2a, 0x34, 0xe4, 0x6e, 0x14, 0x06, 0xda, 0x52,
0x05, 0xaf, 0xd2, 0x90, 0x0f, 0xc2, 0x60, 0x8a, 0x6c, 0x58, 0x1d, 0xc7, 0xec, 0x86, 0x08, 0x6d,
0xaf, 0x82, 0x13, 0x12, 0xfd, 0x18, 0x56, 0x88, 0xe7, 0x51, 0xce, 0x55, 0x48, 0xd6, 0x0e, 0xbe,
0xb5, 0xe0, 0xe0, 0x99, 0x4d, 0x5a, 0x6d, 0x25, 0x8c, 0x8d, 0x92, 0x33, 0x84, 0x15, 0xcd, 0x41,
0x08, 0xd6, 0x12, 0x44, 0xb5, 0x0f, 0x0f, 0x3b, 0xa7, 0xa7, 0xcd, 0x07, 0x68, 0x1d, 0x1a, 0xfd,
0x81, 0xdb, 0xeb, 0xf4, 0x5e, 0x75, 0xf0, 0xe9, 0x4f, 0xba, 0x27, 0x4d, 0x0b, 0x3d, 0x82, 0x87,
0xdd, 0xfe, 0xcf, 0xba, 0xc3, 0xf6, 0xb0, 0x3b, 0xe8, 0xbb, 0x83, 0xfe, 0xf1, 0xe7, 0xcd, 0x02,
0x5a, 0x03, 0x18, 0xf4, 0x5d, 0xdc, 0xf9, 0xf4, 0xac, 0x73, 0x2a, 0xb1, 0xf4, 0xfb, 0x22, 0x34,
0x54, 0xb4, 0x0f, 0x63, 0x26, 0x68, 0xcc, 0x08, 0xfa, 0xe5, 0x1d, 0x10, 0x6a, 0xcd, 0x5c, 0xce,
0x29, 0xfd, 0x17, 0xc8, 0xf9, 0x1e, 0x94, 0x84, 0x4c, 0x7e, 0xe1, 0x2d, 0x92, 0xaf, 0x24, 0x33,
0x79, 0x2f, 0x2e, 0xcc, 0x7b, 0x69, 0x96, 0x77, 0x29, 0x4b, 0x46, 0xd1, 0x24, 0x14, 0x09, 0x46,
0x34, 0x25, 0x8b, 0x84, 0x02, 0x92, 0xcb, 0x7c, 0x6e, 0xaf, 0xec, 0x15, 0xf7, 0x4b, 0xb8, 0xa2,
0x18, 0x5d, 0x9f, 0xa3, 0x5d, 0xa8, 0xc9, 0x6c, 0x8e, 0x89, 0x10, 0x34, 0x0e, 0xed, 0x55, 0xa5,
0x09, 0x34, 0xe4, 0x27, 0x9a, 0x83, 0x76, 0xa0, 0xe2, 0x53, 0x8f, 0x8d, 0x48, 0xc0, 0xed, 0x8a,
0x02, 0x4e, 0x4a, 0xff, 0x8f, 0x90, 0xf6, 0xc7, 0x02, 0xd8, 0xf9, 0x00, 0xcc, 0x90, 0x80, 0xd6,
0xa0, 0x60, 0x4a, 0x5f, 0x15, 0x17, 0x98, 0x8f, 0x3e, 0xcc, 0x85, 0xf0, 0xdb, 0xcb, 0x42, 0x38,
0xb3, 0xd0, 0xca, 0x44, 0xf3, 0x23, 0x58, 0xd3, 0x91, 0xf0, 0x4c, 0xee, 0xec, 0xa2, 0x4a, 0xed,
0xd6, 0x92, 0xd4, 0xe2, 0x86, 0xc8, 0xc1, 0x63, 0x1b, 0x2a, 0xa6, 0xa2, 0x72, 0xbb, 0xb4, 0x57,
0xdc, 0xaf, 0xe2, 0x55, 0x5d, 0x52, 0x39, 0x7a, 0x06, 0xc0, 0xb8, 0x9b, 0xa0, 0xbf, 0xac, 0xd0,
0x5f, 0x65, 0xfc, 0x44, 0x33, 0x9c, 0x2e, 0x94, 0xd4, 0x3d, 0x7e, 0x0a, 0x76, 0x02, 0xdf, 0xe1,
0xe0, 0x4d, 0xa7, 0xef, 0x9e, 0x74, 0x70, 0xaf, 0x7b, 0x7a, 0xda, 0x1d, 0xf4, 0x9b, 0x0f, 0x64,
0xb9, 0x7c, 0xd5, 0x39, 0x1c, 0xf4, 0x3a, 0x6e, 0xfb, 0xa8, 0xd7, 0xed, 0x37, 0x2d, 0x09, 0x6d,
0xc3, 0xd1, 0xf0, 0x6e, 0x16, 0x9c, 0xbf, 0x56, 0x33, 0x17, 0xf3, 0x28, 0x5f, 0x75, 0x74, 0x59,
0xb7, 0x32, 0x65, 0x1d, 0x75, 0x60, 0x55, 0xbf, 0x08, 0xdc, 0x2e, 0xa8, 0xc3, 0x7e, 0x67, 0x41,
0xcc, 0x32, 0x66, 0x5a, 0xba, 0xa0, 0x1b, 0x10, 0x27, 0xba, 0xe8, 0x13, 0xa8, 0x8d, 0x67, 0xf7,
0x53, 0xa1, 0xb1, 0x76, 0xf0, 0xce, 0xdd, 0xb7, 0x18, 0x67, 0x55, 0xd0, 0x01, 0x54, 0x92, 0x67,
0x4f, 0xc5, 0xa7, 0x76, 0xb0, 0x99, 0x51, 0x57, 0x61, 0xd4, 0xab, 0x38, 0x95, 0x43, 0x1f, 0x43,
0x59, 0x06, 0x58, 0xc3, 0xb6, 0x76, 0xf0, 0xee, 0x3d, 0xae, 0x4b, 0x2b, 0xc6, 0x71, 0xad, 0x27,
0x33, 0x76, 0x4e, 0x42, 0x37, 0x60, 0x5c, 0xd8, 0xab, 0x3a, 0x63, 0xe7, 0x24, 0x3c, 0x66, 0x5c,
0xa0, 0x3e, 0x80, 0x47, 0x04, 0xbd, 0x8c, 0x62, 0x46, 0x25, 0xb4, 0xe7, 0xee, 0xf8, 0xe2, 0x0d,
0x52, 0x05, 0xbd, 0x4b, 0xc6, 0x02, 0x7a, 0x09, 0x36, 0x89, 0xbd, 0x2b, 0x76, 0x43, 0xdd, 0x11,
0xb9, 0x0c, 0xa9, 0x08, 0x58, 0x78, 0xed, 0xea, 0x8c, 0x54, 0x55, 0x46, 0x36, 0xcd, 0x7a, 0x2f,
0x5d, 0x3e, 0x54, 0x29, 0x7a, 0x0d, 0x6b, 0xc4, 0x1f, 0xb1, 0xd0, 0xe5, 0x54, 0x08, 0x16, 0x5e,
0x72, 0x1b, 0x54, 0x7c, 0xf6, 0x16, 0x78, 0xd3, 0x96, 0x82, 0xa7, 0x46, 0x0e, 0x37, 0x48, 0x96,
0x44, 0xdf, 0x80, 0x06, 0x0b, 0x45, 0x1c, 0xb9, 0x23, 0xca, 0xb9, 0x7c, 0x7f, 0x6a, 0xea, 0xde,
0xd4, 0x15, 0xb3, 0xa7, 0x79, 0x52, 0x28, 0x9a, 0x64, 0x85, 0xea, 0x5a, 0x48, 0x31, 0x13, 0xa1,
0xa7, 0x50, 0xa5, 0xa1, 0x17, 0x4f, 0xc7, 0x82, 0xfa, 0x76, 0x43, 0xa3, 0x39, 0x65, 0xc8, 0xea,
0x23, 0xc8, 0x25, 0xb7, 0xd7, 0x54, 0x44, 0xd5, 0x37, 0x22, 0xb0, 0xae, 0xef, 0x56, 0x16, 0x26,
0x0f, 0x55, 0x54, 0xbf, 0x7f, 0x4f, 0x54, 0xe7, 0x6e, 0xac, 0x89, 0x6d, 0x53, 0xcc, 0xb1, 0xd1,
0x2f, 0x60, 0x7b, 0xd6, 0x10, 0xa9, 0x55, 0xee, 0x8e, 0xcc, 0xfb, 0x6d, 0x37, 0xd5, 0x56, 0x7b,
0xf7, 0xbd, 0xf3, 0x78, 0xcb, 0xcb, 0xf1, 0x79, 0xb2, 0xb0, 0x73, 0x06, 0xf5, 0x2c, 0xf4, 0xb3,
0x25, 0xac, 0xaa, 0x4b, 0xd8, 0x8b, 0x6c, 0x09, 0xab, 0x1d, 0x6c, 0x2f, 0xed, 0x86, 0x32, 0xd5,
0x6d, 0xe7, 0x53, 0x80, 0x19, 0x2c, 0x17, 0x18, 0xfd, 0x6e, 0xde, 0xe8, 0xd6, 0x02, 0xa3, 0x52,
0x3f, 0x6b, 0xf2, 0x0b, 0x78, 0x38, 0x07, 0xc4, 0x05, 0x76, 0xdf, 0xcb, 0xdb, 0x7d, 0xb2, 0xc8,
0xae, 0x36, 0x32, 0xcd, 0xda, 0xbe, 0x84, 0x8d, 0x85, 0xe9, 0x58, 0xb0, 0xc3, 0xcb, 0xfc, 0x0e,
0xce, 0xfd, 0xb5, 0x38, 0x5b, 0xf5, 0x7f, 0x95, 0xe9, 0xe3, 0x72, 0xa0, 0x46, 0x47, 0xb0, 0x3b,
0x66, 0x61, 0x02, 0x4f, 0x97, 0x04, 0x81, 0x6b, 0xaa, 0x90, 0x4b, 0x43, 0x72, 0x1e, 0x50, 0xdf,
0xf4, 0x1d, 0x4f, 0xc6, 0x2c, 0x34, 0x80, 0x6d, 0x07, 0x41, 0x9a, 0x3c, 0x25, 0xe2, 0xfc, 0xa3,
0x00, 0x8d, 0x5c, 0x04, 0xd1, 0x47, 0xb3, 0x4a, 0xa8, 0x5f, 0xf4, 0x6f, 0x2e, 0x89, 0xf5, 0xdb,
0x95, 0xc0, 0xc2, 0x57, 0x2b, 0x81, 0xc5, 0xb7, 0x2c, 0x81, 0xbb, 0x50, 0x33, 0x45, 0x46, 0x0d,
0x01, 0xfa, 0xc1, 0x4f, 0xea, 0x8e, 0x9c, 0x01, 0x76, 0xa0, 0x32, 0x8e, 0x38, 0x53, 0xbd, 0xa8,
0xac, 0xab, 0x65, 0x9c, 0xd2, 0xff, 0x27, 0x4c, 0x3b, 0x3e, 0xac, 0xdf, 0x02, 0xd1, 0xbc, 0xa3,
0xd6, 0x2d, 0x47, 0x93, 0x9e, 0xa5, 0x90, 0xe9, 0x59, 0xb2, 0xce, 0x17, 0xf3, 0xce, 0x3b, 0x7f,
0xb0, 0xe0, 0x51, 0xba, 0x4d, 0x37, 0xbc, 0x61, 0x82, 0xa8, 0x77, 0xee, 0x7d, 0xd8, 0x98, 0x95,
0x81, 0x6c, 0x27, 0xae, 0x07, 0xa4, 0xc7, 0xde, 0x92, 0xc7, 0xf1, 0x52, 0x4e, 0x55, 0x66, 0x4a,
0xd2, 0xc4, 0xf2, 0x11, 0xe9, 0x19, 0xc0, 0x78, 0x72, 0x1e, 0x30, 0xcf, 0x95, 0xf1, 0x2a, 0x29,
0x9d, 0xaa, 0xe6, 0xbc, 0xa1, 0x53, 0xe7, 0xef, 0xd9, 0x29, 0x04, 0xd3, 0x5f, 0x4f, 0x28, 0x17,
0xc3, 0xe8, 0xa7, 0x11, 0x5b, 0xf6, 0x0a, 0x9b, 0xa6, 0x39, 0x73, 0x7e, 0xd9, 0x34, 0xf7, 0x65,
0x08, 0x96, 0xfa, 0x30, 0x3f, 0xff, 0x95, 0x6e, 0xcf, 0x7f, 0xcf, 0xa1, 0xee, 0x33, 0x3e, 0x0e,
0xc8, 0x54, 0x9b, 0x2e, 0x9b, 0x59, 0x44, 0xf3, 0x94, 0xf9, 0x0b, 0x40, 0x31, 0xbd, 0xa1, 0x24,
0xa0, 0x7e, 0xa6, 0xa5, 0x5d, 0x59, 0x3a, 0x15, 0xe5, 0x4e, 0xd3, 0xc2, 0x46, 0x75, 0xbe, 0xb7,
0x8d, 0xe7, 0xf9, 0xb2, 0x17, 0x5c, 0x2c, 0xbc, 0x00, 0x74, 0xb9, 0x5e, 0xb0, 0x9e, 0x45, 0xd6,
0x9f, 0x2c, 0x78, 0x9a, 0x81, 0x56, 0xe8, 0xd1, 0xe0, 0x6b, 0x1d, 0x5e, 0xe7, 0xdf, 0x16, 0xbc,
0xb3, 0x38, 0x76, 0x98, 0xf2, 0x71, 0x14, 0x72, 0xba, 0xc4, 0xe5, 0x1f, 0x41, 0x35, 0xdd, 0xea,
0x8e, 0x5a, 0x92, 0xc1, 0x30, 0x9e, 0x29, 0xc8, 0x7b, 0x23, 0x47, 0x23, 0xf5, 0x3c, 0x17, 0x55,
0x31, 0x4c, 0xe9, 0x19, 0xd4, 0x4b, 0x59, 0xa8, 0xcf, 0x1f, 0xb7, 0x7c, 0xfb, 0xb8, 0xcf, 0x00,
0x74, 0xe7, 0xe2, 0x4e, 0x62, 0x66, 0x46, 0xca, 0xaa, 0xe6, 0x9c, 0xc5, 0xcc, 0xc1, 0xb0, 0x75,
0xfb, 0xa4, 0xc7, 0x94, 0xdc, 0x2c, 0x3b, 0xe2, 0xfc, 0x96, 0x85, 0x5b, 0x5b, 0x3a, 0x3f, 0x87,
0xe7, 0x99, 0x3a, 0xa3, 0x4b, 0xf9, 0x7c, 0x93, 0xb4, 0xc4, 0x7a, 0xde, 0xdb, 0xc2, 0xbc, 0xb7,
0x7f, 0xb6, 0xa0, 0xf6, 0x19, 0xb9, 0x9e, 0x24, 0x1d, 0x4d, 0x13, 0x8a, 0x9c, 0x5d, 0x9a, 0x1a,
0x21, 0x3f, 0x65, 0x8f, 0x23, 0xd8, 0x88, 0x72, 0x41, 0x46, 0x63, 0xa5, 0x5f, 0xc2, 0x33, 0x86,
0xdc, 0x54, 0x44, 0x63, 0xe6, 0xa9, 0xf0, 0xd6, 0xb1, 0x26, 0xd4, 0x84, 0x4b, 0xa6, 0x41, 0x44,
0x12, 0xbc, 0x24, 0xa4, 0x5e, 0xf1, 0x7d, 0x16, 0x5e, 0x9a, 0xd0, 0x26, 0xa4, 0xac, 0x7b, 0x57,
0x84, 0x5f, 0xa9, 0x80, 0xd6, 0xb1, 0xfa, 0x46, 0x0e, 0xd4, 0xc5, 0x15, 0x8b, 0xfd, 0x13, 0x12,
0xcb, 0x38, 0x98, 0xb9, 0x2b, 0xc7, 0x73, 0x7e, 0x07, 0x3b, 0x99, 0x03, 0x24, 0x61, 0x49, 0xfe,
0xed, 0xb0, 0x61, 0xf5, 0x86, 0xc6, 0x3c, 0xa9, 0x7b, 0x0d, 0x9c, 0x90, 0x72, 0xbf, 0x8b, 0x38,
0x1a, 0x99, 0x23, 0xa9, 0x6f, 0x39, 0x46, 0x89, 0x48, 0x1d, 0xa5, 0x84, 0x0b, 0x22, 0x92, 0xfb,
0xcb, 0xf1, 0x94, 0x86, 0x62, 0xa8, 0x0e, 0x29, 0xa7, 0x99, 0x3a, 0xce, 0xf1, 0x9c, 0x2f, 0x2d,
0x40, 0xb7, 0x1d, 0xb8, 0x63, 0xe3, 0x4f, 0xa0, 0x92, 0xb6, 0x63, 0x1a, 0xd1, 0x99, 0x17, 0x76,
0xf9, 0x51, 0x70, 0xaa, 0x85, 0xde, 0x93, 0x16, 0x94, 0x0c, 0x37, 0xa3, 0xd9, 0xc6, 0x42, 0x0b,
0x38, 0x15, 0x73, 0xfe, 0x62, 0xc1, 0xee, 0x6d, 0xdb, 0xdd, 0xd0, 0xa7, 0xbf, 0x79, 0x8b, 0x58,
0x7d, 0x75, 0x97, 0x37, 0x61, 0x25, 0xba, 0xb8, 0xe0, 0x54, 0x98, 0xe8, 0x1a, 0x4a, 0x66, 0x81,
0xb3, 0xdf, 0x52, 0xf3, 0x1f, 0x9b, 0xfa, 0x9e, 0xc7, 0x48, 0x29, 0xc5, 0x88, 0xf3, 0x37, 0x0b,
0xb6, 0x96, 0x9c, 0x02, 0xbd, 0x81, 0x8a, 0x19, 0x1c, 0x92, 0xc6, 0xe5, 0xc5, 0x5d, 0x3e, 0x2a,
0xa5, 0x96, 0x21, 0x4c, 0xbd, 0x4e, 0x0d, 0xec, 0x5c, 0x40, 0x23, 0xb7, 0xb4, 0xa0, 0x3a, 0x7f,
0x9c, 0x6f, 0x09, 0xde, 0xbd, 0x77, 0xb3, 0x34, 0x2a, 0xb3, 0x42, 0xfe, 0xaa, 0xf1, 0x45, 0xad,
0xf5, 0xe2, 0xc3, 0x44, 0xf3, 0x7c, 0x45, 0x7d, 0xbd, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff,
0xda, 0xe1, 0xcd, 0x16, 0x1c, 0x15, 0x00, 0x00,
// 1905 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x58, 0xcd, 0x72, 0x23, 0x49,
0xf1, 0x9f, 0xd6, 0x87, 0x2d, 0xa5, 0x3e, 0x46, 0xae, 0x19, 0xdb, 0x6d, 0xcf, 0xcc, 0xda, 0xd3,
0xff, 0x3f, 0xb1, 0xde, 0x20, 0xd0, 0xb0, 0x5a, 0x08, 0x26, 0x76, 0x61, 0x77, 0x35, 0xb6, 0x62,
0x10, 0x63, 0x49, 0xde, 0xb2, 0xcc, 0xb2, 0x1b, 0x40, 0x47, 0xb9, 0xbb, 0x6c, 0x57, 0xb8, 0xd5,
0x2d, 0xba, 0x4a, 0x06, 0x71, 0xe0, 0xc4, 0x43, 0x70, 0xe7, 0x4a, 0xf0, 0x0a, 0x1c, 0xe0, 0x48,
0x70, 0x24, 0x82, 0x1b, 0x27, 0x82, 0xc7, 0x20, 0xea, 0xa3, 0xa5, 0x6e, 0x59, 0xb2, 0x87, 0x58,
0x88, 0xe0, 0xa4, 0xce, 0xac, 0xcc, 0xac, 0xac, 0xcc, 0x5f, 0x65, 0x65, 0x0a, 0x36, 0xbc, 0x68,
0x34, 0x9a, 0x84, 0x4c, 0x30, 0xca, 0x9b, 0xe3, 0x38, 0x12, 0x11, 0x2a, 0xa9, 0x9f, 0xf3, 0xc9,
0xc5, 0xee, 0x23, 0xef, 0x8a, 0x08, 0x97, 0xf9, 0x34, 0x14, 0x4c, 0x4c, 0xf5, 0xf2, 0x6e, 0x85,
0x86, 0x93, 0x91, 0x91, 0x75, 0x6e, 0xa0, 0xf8, 0x3a, 0x26, 0xa1, 0x40, 0xcf, 0xa1, 0x9a, 0x58,
0x9a, 0xba, 0xcc, 0xb7, 0xad, 0x7d, 0xeb, 0xa0, 0x8a, 0x2b, 0x33, 0x5e, 0xd7, 0x47, 0x4f, 0xa0,
0x3c, 0xa2, 0xa3, 0x73, 0x1a, 0xcb, 0xf5, 0x9c, 0x5a, 0x2f, 0x69, 0x46, 0xd7, 0x47, 0xdb, 0xb0,
0x6e, 0x36, 0xb3, 0xf3, 0xfb, 0xd6, 0x41, 0x19, 0xaf, 0x49, 0xb2, 0xeb, 0xa3, 0xc7, 0x50, 0xf4,
0x82, 0xc8, 0xbb, 0xb6, 0x0b, 0xfb, 0xd6, 0x41, 0x01, 0x6b, 0xc2, 0xf9, 0xb3, 0x05, 0x0f, 0x0f,
0x13, 0xdb, 0x3d, 0x65, 0x04, 0x7d, 0x1b, 0x8a, 0x71, 0x14, 0x50, 0x6e, 0x5b, 0xfb, 0xf9, 0x83,
0x7a, 0x6b, 0xaf, 0x99, 0x9c, 0xa3, 0xb9, 0x20, 0xd9, 0xc4, 0x52, 0x0c, 0x6b, 0x69, 0xf4, 0x2e,
0x3c, 0xfc, 0x39, 0x09, 0x02, 0x2a, 0x5c, 0xe2, 0x79, 0xd1, 0x24, 0x14, 0xdc, 0xce, 0xed, 0xe7,
0x0f, 0xca, 0xb8, 0xae, 0xd9, 0x6d, 0xc3, 0x75, 0xbe, 0x80, 0xa2, 0x52, 0x44, 0x0d, 0xa8, 0x9e,
0xf5, 0xdf, 0xf4, 0x07, 0x9f, 0xf7, 0x5d, 0x3c, 0x38, 0xee, 0x34, 0x1e, 0xa0, 0x2a, 0x94, 0xe4,
0x97, 0xdb, 0x3e, 0x3e, 0x6e, 0x58, 0x68, 0x13, 0x36, 0x14, 0xd5, 0x6b, 0xf7, 0xdb, 0xaf, 0x3b,
0xee, 0xd9, 0x69, 0x07, 0x9f, 0x36, 0x72, 0x68, 0x07, 0x36, 0x35, 0x7b, 0x70, 0xd4, 0xc1, 0xed,
0x61, 0xc7, 0x3d, 0x1c, 0xf4, 0x87, 0x9d, 0xfe, 0xb0, 0x91, 0x77, 0xfe, 0x91, 0x83, 0xad, 0x99,
0x93, 0xc3, 0xe8, 0x9a, 0x86, 0x3d, 0x2a, 0x88, 0x4f, 0x04, 0x41, 0x17, 0x80, 0xbc, 0x28, 0x14,
0x31, 0xf1, 0x84, 0x4b, 0x7c, 0x3f, 0xa6, 0x9c, 0x9b, 0x23, 0x56, 0x5a, 0xdf, 0x59, 0x72, 0xc4,
0x8c, 0x76, 0xf3, 0xd0, 0xa8, 0xb6, 0x13, 0xcd, 0x4e, 0x28, 0xe2, 0x29, 0xde, 0xf0, 0x16, 0xf9,
0x68, 0x1f, 0x2a, 0x3e, 0xe5, 0x5e, 0xcc, 0xc6, 0x82, 0x45, 0xa1, 0xca, 0x4f, 0x19, 0xa7, 0x59,
0x32, 0x13, 0x6c, 0x44, 0x2e, 0xa9, 0x49, 0x90, 0x26, 0xd0, 0x87, 0x50, 0x16, 0x72, 0xcb, 0xe1,
0x74, 0x4c, 0x55, 0x8e, 0xea, 0xad, 0xa7, 0xab, 0xdc, 0x92, 0x32, 0x78, 0x2e, 0x8e, 0xb6, 0x60,
0x8d, 0x4f, 0x47, 0xe7, 0x51, 0x60, 0x17, 0x75, 0xce, 0x35, 0x85, 0x10, 0x14, 0x42, 0x32, 0xa2,
0xf6, 0x9a, 0xe2, 0xaa, 0xef, 0xdd, 0x23, 0x19, 0xa1, 0x65, 0x87, 0x41, 0x0d, 0xc8, 0x5f, 0xd3,
0xa9, 0x42, 0x5c, 0x01, 0xcb, 0x4f, 0xe9, 0xe9, 0x0d, 0x09, 0x26, 0xd4, 0x9c, 0x42, 0x13, 0x1f,
0xe6, 0x5e, 0x5a, 0xce, 0xdf, 0x2d, 0x78, 0x3c, 0xf3, 0xe9, 0x84, 0xc6, 0x23, 0xc6, 0x39, 0x8b,
0x42, 0x8e, 0x76, 0xa0, 0x44, 0x43, 0xee, 0x46, 0x61, 0xa0, 0x2d, 0x95, 0xf0, 0x3a, 0x0d, 0xf9,
0x20, 0x0c, 0xa6, 0xc8, 0x86, 0xf5, 0x71, 0xcc, 0x6e, 0x88, 0xd0, 0xf6, 0x4a, 0x38, 0x21, 0xd1,
0xf7, 0x60, 0x8d, 0x78, 0x1e, 0xe5, 0x5c, 0x85, 0xa4, 0xde, 0xfa, 0xda, 0x92, 0x83, 0xa7, 0x36,
0x69, 0xb6, 0x95, 0x30, 0x36, 0x4a, 0xce, 0x10, 0xd6, 0x34, 0x07, 0x21, 0xa8, 0x27, 0x88, 0x6a,
0x1f, 0x1e, 0x76, 0x4e, 0x4f, 0x1b, 0x0f, 0xd0, 0x06, 0xd4, 0xfa, 0x03, 0xb7, 0xd7, 0xe9, 0xbd,
0xea, 0xe0, 0xd3, 0xef, 0x77, 0x4f, 0x1a, 0x16, 0x7a, 0x04, 0x0f, 0xbb, 0xfd, 0x1f, 0x76, 0x87,
0xed, 0x61, 0x77, 0xd0, 0x77, 0x07, 0xfd, 0xe3, 0x2f, 0x1a, 0x39, 0x54, 0x07, 0x18, 0xf4, 0x5d,
0xdc, 0xf9, 0xec, 0xac, 0x73, 0x2a, 0xb1, 0xf4, 0xeb, 0x3c, 0xd4, 0x54, 0xb4, 0x0f, 0x63, 0x26,
0x68, 0xcc, 0x08, 0xfa, 0xc9, 0x1d, 0x10, 0x6a, 0xce, 0x5d, 0xce, 0x28, 0xfd, 0x1b, 0xc8, 0xf9,
0x26, 0x14, 0x84, 0x4c, 0x7e, 0xee, 0x2d, 0x92, 0xaf, 0x24, 0x53, 0x79, 0xcf, 0x2f, 0xcd, 0x7b,
0x61, 0x9e, 0x77, 0x29, 0x4b, 0x46, 0xf2, 0x02, 0x26, 0x18, 0xd1, 0x94, 0xac, 0x26, 0x0a, 0x48,
0x2e, 0xf3, 0xb9, 0xbd, 0xb6, 0x9f, 0x3f, 0x28, 0xe0, 0x92, 0x62, 0x74, 0x7d, 0x8e, 0xf6, 0xa0,
0x22, 0xb3, 0x39, 0x26, 0x42, 0xd0, 0x38, 0xb4, 0xd7, 0x95, 0x26, 0xd0, 0x90, 0x9f, 0x68, 0x0e,
0xda, 0x85, 0x92, 0x4f, 0x3d, 0x36, 0x22, 0x01, 0xb7, 0x4b, 0x0a, 0x38, 0x33, 0xfa, 0x3f, 0x84,
0xb4, 0xdf, 0xe5, 0xc0, 0xce, 0x06, 0x60, 0x8e, 0x04, 0x54, 0x87, 0x9c, 0xa9, 0x91, 0x65, 0x9c,
0x63, 0x3e, 0xfa, 0x28, 0x13, 0xc2, 0x77, 0x57, 0x85, 0x70, 0x6e, 0xa1, 0x99, 0x8a, 0xe6, 0xc7,
0x50, 0xd7, 0x91, 0xf0, 0x4c, 0xee, 0xec, 0xbc, 0x4a, 0xed, 0xf6, 0x8a, 0xd4, 0xe2, 0x9a, 0xc8,
0xc0, 0x63, 0x07, 0x4a, 0xa6, 0xf4, 0x72, 0xbb, 0xa0, 0x2a, 0xdf, 0xba, 0xae, 0xbd, 0x1c, 0x3d,
0x03, 0x60, 0xdc, 0x4d, 0xd0, 0x5f, 0x54, 0xe8, 0x2f, 0x33, 0x7e, 0xa2, 0x19, 0x4e, 0x17, 0x0a,
0xea, 0x1e, 0x3f, 0x05, 0x3b, 0x81, 0xef, 0x70, 0xf0, 0xa6, 0xd3, 0x77, 0x4f, 0x3a, 0xb8, 0xd7,
0x3d, 0x3d, 0xed, 0x0e, 0xfa, 0x8d, 0x07, 0xb2, 0x5c, 0xbe, 0xea, 0x1c, 0x0e, 0x7a, 0x1d, 0xb7,
0x7d, 0xd4, 0xeb, 0xf6, 0x1b, 0x96, 0x84, 0xb6, 0xe1, 0x68, 0x78, 0x37, 0x72, 0xce, 0x9f, 0xca,
0xa9, 0x8b, 0x79, 0x94, 0xad, 0x3a, 0xba, 0xfe, 0x5b, 0xa9, 0xfa, 0x8f, 0x3a, 0xb0, 0xae, 0x9f,
0x0e, 0x5d, 0xac, 0x2b, 0xad, 0xaf, 0x2f, 0x89, 0x59, 0xca, 0x4c, 0x53, 0x57, 0x7e, 0x03, 0xe2,
0x44, 0x17, 0x7d, 0x0a, 0x95, 0xf1, 0xfc, 0x7e, 0x2a, 0x34, 0x56, 0x5a, 0xef, 0xdc, 0x7d, 0x8b,
0x71, 0x5a, 0x05, 0xb5, 0xa0, 0x94, 0xbc, 0x8f, 0x2a, 0x3e, 0x95, 0xd6, 0x56, 0x4a, 0x5d, 0x85,
0x51, 0xaf, 0xe2, 0x99, 0x1c, 0xfa, 0x04, 0x8a, 0x32, 0xc0, 0x1a, 0xb6, 0x95, 0xd6, 0x7b, 0xf7,
0xb8, 0x2e, 0xad, 0x18, 0xc7, 0xb5, 0x9e, 0xcc, 0xd8, 0x39, 0x09, 0xdd, 0x80, 0x71, 0x61, 0xaf,
0xeb, 0x8c, 0x9d, 0x93, 0xf0, 0x98, 0x71, 0x81, 0xfa, 0x00, 0x1e, 0x11, 0xf4, 0x32, 0x8a, 0x19,
0x95, 0xd0, 0x5e, 0xb8, 0xe3, 0xcb, 0x37, 0x98, 0x29, 0xe8, 0x5d, 0x52, 0x16, 0xd0, 0x4b, 0xb0,
0x49, 0xec, 0x5d, 0xb1, 0x1b, 0xea, 0x8e, 0xc8, 0x65, 0x48, 0x45, 0xc0, 0xc2, 0x6b, 0x57, 0x67,
0xa4, 0xac, 0x32, 0xb2, 0x65, 0xd6, 0x7b, 0xb3, 0xe5, 0x43, 0x95, 0xa2, 0xd7, 0x50, 0x27, 0xfe,
0x88, 0x85, 0x2e, 0xa7, 0x42, 0xb0, 0xf0, 0x92, 0xdb, 0xa0, 0xe2, 0xb3, 0xbf, 0xc4, 0x9b, 0xb6,
0x14, 0x3c, 0x35, 0x72, 0xb8, 0x46, 0xd2, 0x24, 0xfa, 0x3f, 0xa8, 0xb1, 0x50, 0xc4, 0x91, 0x3b,
0xa2, 0x9c, 0xcb, 0xf7, 0xa7, 0xa2, 0xee, 0x4d, 0x55, 0x31, 0x7b, 0x9a, 0x27, 0x85, 0xa2, 0x49,
0x5a, 0xa8, 0xaa, 0x85, 0x14, 0x33, 0x11, 0x7a, 0x0a, 0x65, 0x1a, 0x7a, 0xf1, 0x74, 0x2c, 0xa8,
0x6f, 0xd7, 0x34, 0x9a, 0x67, 0x0c, 0x59, 0x7d, 0x04, 0xb9, 0xe4, 0x76, 0x5d, 0x45, 0x54, 0x7d,
0x23, 0x02, 0x1b, 0xfa, 0x6e, 0xa5, 0x61, 0xf2, 0x50, 0x45, 0xf5, 0x5b, 0xf7, 0x44, 0x75, 0xe1,
0xc6, 0x9a, 0xd8, 0x36, 0xc4, 0x02, 0x1b, 0xfd, 0x18, 0x76, 0xe6, 0x9d, 0x93, 0x5a, 0xe5, 0xee,
0xc8, 0xbc, 0xdf, 0x76, 0x43, 0x6d, 0xb5, 0x7f, 0xdf, 0x3b, 0x8f, 0xb7, 0xbd, 0x0c, 0x9f, 0x27,
0x0b, 0xbb, 0x67, 0x50, 0x4d, 0x43, 0x3f, 0x5d, 0xc2, 0xca, 0xba, 0x84, 0xbd, 0x48, 0x97, 0xb0,
0x4a, 0x6b, 0x67, 0x65, 0xdb, 0x94, 0xaa, 0x6e, 0xbb, 0x9f, 0x01, 0xcc, 0x61, 0xb9, 0xc4, 0xe8,
0x37, 0xb2, 0x46, 0xb7, 0x97, 0x18, 0x95, 0xfa, 0x69, 0x93, 0x5f, 0xc2, 0xc3, 0x05, 0x20, 0x2e,
0xb1, 0xfb, 0x7e, 0xd6, 0xee, 0x93, 0x65, 0x76, 0xb5, 0x91, 0x69, 0xda, 0xf6, 0x25, 0x6c, 0x2e,
0x4d, 0xc7, 0x92, 0x1d, 0x5e, 0x66, 0x77, 0x70, 0xee, 0xaf, 0xc5, 0xe9, 0xaa, 0xff, 0xd3, 0x54,
0x1f, 0x97, 0x01, 0x35, 0x3a, 0x82, 0xbd, 0x31, 0x0b, 0x13, 0x78, 0xba, 0x24, 0x08, 0x5c, 0x53,
0x85, 0x5c, 0x1a, 0x92, 0xf3, 0x80, 0xfa, 0xa6, 0xef, 0x78, 0x32, 0x66, 0xa1, 0x01, 0x6c, 0x3b,
0x08, 0x66, 0xc9, 0x53, 0x22, 0xce, 0xdf, 0x72, 0x50, 0xcb, 0x44, 0x10, 0x7d, 0x3c, 0xaf, 0x84,
0xfa, 0x45, 0xff, 0xff, 0x15, 0xb1, 0x7e, 0xbb, 0x12, 0x98, 0xfb, 0x6a, 0x25, 0x30, 0xff, 0x96,
0x25, 0x70, 0x0f, 0x2a, 0xa6, 0xc8, 0xa8, 0x69, 0x41, 0x3f, 0xf8, 0x49, 0xdd, 0x91, 0xc3, 0xc2,
0x2e, 0x94, 0xc6, 0x11, 0x67, 0xaa, 0x17, 0x95, 0x75, 0xb5, 0x88, 0x67, 0xf4, 0x7f, 0x09, 0xd3,
0x8e, 0x0f, 0x1b, 0xb7, 0x40, 0xb4, 0xe8, 0xa8, 0x75, 0xcb, 0xd1, 0xa4, 0x67, 0xc9, 0xa5, 0x7a,
0x96, 0xb4, 0xf3, 0xf9, 0xac, 0xf3, 0xce, 0x6f, 0x2c, 0x78, 0x34, 0xdb, 0xa6, 0x1b, 0xde, 0x30,
0x41, 0xd4, 0x3b, 0xf7, 0x01, 0x6c, 0xce, 0xcb, 0x40, 0xba, 0x13, 0xd7, 0x93, 0xd4, 0x63, 0x6f,
0xc5, 0xe3, 0x78, 0x29, 0xc7, 0x2f, 0x33, 0x4e, 0x69, 0x62, 0xf5, 0x2c, 0xf5, 0x0c, 0x60, 0x3c,
0x39, 0x0f, 0x98, 0xe7, 0xca, 0x78, 0x15, 0x94, 0x4e, 0x59, 0x73, 0xde, 0xd0, 0xa9, 0xf3, 0xd7,
0xf4, 0x14, 0x82, 0xe9, 0xcf, 0x26, 0x94, 0x8b, 0x61, 0xf4, 0x83, 0x88, 0xad, 0x7a, 0x85, 0x4d,
0xd3, 0x9c, 0x3a, 0xbf, 0x6c, 0x9a, 0xfb, 0x32, 0x04, 0x2b, 0x7d, 0x58, 0x1c, 0x14, 0x0b, 0xb7,
0x07, 0xc5, 0xe7, 0x50, 0xf5, 0x19, 0x1f, 0x07, 0x64, 0xaa, 0x4d, 0x17, 0xcd, 0x2c, 0xa2, 0x79,
0xca, 0xfc, 0x05, 0xa0, 0x98, 0xde, 0x50, 0x12, 0x50, 0x3f, 0xd5, 0xd2, 0xae, 0xad, 0x9c, 0x8a,
0x32, 0xa7, 0x69, 0x62, 0xa3, 0xba, 0xd8, 0xdb, 0xc6, 0x8b, 0x7c, 0xd9, 0x0b, 0x2e, 0x17, 0x5e,
0x02, 0xba, 0x4c, 0x2f, 0x58, 0x4d, 0x23, 0xeb, 0xf7, 0x16, 0x3c, 0x4d, 0x41, 0x2b, 0xf4, 0x68,
0xf0, 0x3f, 0x1d, 0x5e, 0xe7, 0x9f, 0x16, 0xbc, 0xb3, 0x3c, 0x76, 0x98, 0xf2, 0x71, 0x14, 0x72,
0xba, 0xc2, 0xe5, 0xef, 0x42, 0x79, 0xb6, 0xd5, 0x1d, 0xb5, 0x24, 0x85, 0x61, 0x3c, 0x57, 0x90,
0xf7, 0x46, 0x8e, 0x46, 0xea, 0x79, 0xce, 0xab, 0x62, 0x38, 0xa3, 0xe7, 0x50, 0x2f, 0xa4, 0xa1,
0xbe, 0x78, 0xdc, 0xe2, 0xed, 0xe3, 0x3e, 0x03, 0xd0, 0x9d, 0x8b, 0x3b, 0x89, 0x99, 0x19, 0x29,
0xcb, 0x9a, 0x73, 0x16, 0x33, 0x07, 0xc3, 0xf6, 0xed, 0x93, 0x1e, 0x53, 0x72, 0xb3, 0xea, 0x88,
0x8b, 0x5b, 0xe6, 0x6e, 0x6d, 0xe9, 0xfc, 0x08, 0x9e, 0xa7, 0xea, 0x8c, 0x2e, 0xe5, 0x8b, 0x4d,
0xd2, 0x0a, 0xeb, 0x59, 0x6f, 0x73, 0x8b, 0xde, 0xfe, 0xc1, 0x82, 0xca, 0xe7, 0xe4, 0x7a, 0x92,
0x74, 0x34, 0x0d, 0xc8, 0x73, 0x76, 0x69, 0x6a, 0x84, 0xfc, 0x94, 0x3d, 0x8e, 0x60, 0x23, 0xca,
0x05, 0x19, 0x8d, 0x95, 0x7e, 0x01, 0xcf, 0x19, 0x72, 0x53, 0x11, 0x8d, 0x99, 0xa7, 0xc2, 0x5b,
0xc5, 0x9a, 0x50, 0x13, 0x2e, 0x99, 0x06, 0x11, 0x49, 0xf0, 0x92, 0x90, 0x7a, 0xc5, 0xf7, 0x59,
0x78, 0x69, 0x42, 0x9b, 0x90, 0xb2, 0xee, 0x5d, 0x11, 0x7e, 0xa5, 0x02, 0x5a, 0xc5, 0xea, 0x1b,
0x39, 0x50, 0x15, 0x57, 0x2c, 0xf6, 0x4f, 0x48, 0x2c, 0xe3, 0x60, 0xe6, 0xae, 0x0c, 0xcf, 0xf9,
0x15, 0xec, 0xa6, 0x0e, 0x90, 0x84, 0x25, 0xf9, 0xb7, 0xc3, 0x86, 0xf5, 0x1b, 0x1a, 0xf3, 0xa4,
0xee, 0xd5, 0x70, 0x42, 0xca, 0xfd, 0x2e, 0xe2, 0x68, 0x64, 0x8e, 0xa4, 0xbe, 0xe5, 0x18, 0x25,
0x22, 0x75, 0x94, 0x02, 0xce, 0x89, 0x48, 0xee, 0x2f, 0xc7, 0x53, 0x1a, 0x8a, 0xa1, 0x3a, 0xa4,
0x9c, 0x66, 0xaa, 0x38, 0xc3, 0x73, 0x7e, 0x6b, 0x01, 0xba, 0xed, 0xc0, 0x1d, 0x1b, 0x7f, 0x0a,
0xa5, 0x59, 0x3b, 0xa6, 0x11, 0x9d, 0x7a, 0x61, 0x57, 0x1f, 0x05, 0xcf, 0xb4, 0xd0, 0xfb, 0xd2,
0x82, 0x92, 0xe1, 0x66, 0x34, 0xdb, 0x5c, 0x6a, 0x01, 0xcf, 0xc4, 0x9c, 0x3f, 0x5a, 0xb0, 0x77,
0xdb, 0x76, 0x37, 0xf4, 0xe9, 0x2f, 0xde, 0x22, 0x56, 0x5f, 0xdd, 0xe5, 0x2d, 0x58, 0x8b, 0x2e,
0x2e, 0x38, 0x15, 0x26, 0xba, 0x86, 0x92, 0x59, 0xe0, 0xec, 0x97, 0xd4, 0xfc, 0x19, 0xa7, 0xbe,
0x17, 0x31, 0x52, 0x98, 0x61, 0xc4, 0xf9, 0x8b, 0x05, 0xdb, 0x2b, 0x4e, 0x81, 0xde, 0x40, 0xc9,
0x0c, 0x0e, 0x49, 0xe3, 0xf2, 0xe2, 0x2e, 0x1f, 0x95, 0x52, 0xd3, 0x10, 0xa6, 0x5e, 0xcf, 0x0c,
0xec, 0x5e, 0x40, 0x2d, 0xb3, 0xb4, 0xa4, 0x3a, 0x7f, 0x92, 0x6d, 0x09, 0xde, 0xbb, 0x77, 0xb3,
0x59, 0x54, 0xe6, 0x85, 0xfc, 0x55, 0xed, 0xcb, 0x4a, 0xf3, 0xc5, 0x47, 0x89, 0xe6, 0xf9, 0x9a,
0xfa, 0xfa, 0xe0, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x53, 0xf5, 0x9f, 0xe9, 0x45, 0x15, 0x00,
0x00,
}

View File

@ -21,6 +21,7 @@ message CommunityMember {
ROLE_MODERATE_CONTENT = 3;
}
repeated Roles roles = 1;
repeated string wallet_accounts = 2;
}
message CommunityTokenMetadata {

View File

@ -108,7 +108,7 @@ func (s *Service) GetPeer(rawURL string) (*enode.Node, error) {
return enode.ParseV4(rawURL)
}
func (s *Service) InitProtocol(nodeName string, identity *ecdsa.PrivateKey, db *sql.DB, httpServer *server.MediaServer, multiAccountDb *multiaccounts.Database, acc *multiaccounts.Account, accountManager *account.GethManager, logger *zap.Logger) error {
func (s *Service) InitProtocol(nodeName string, identity *ecdsa.PrivateKey, db *sql.DB, httpServer *server.MediaServer, multiAccountDb *multiaccounts.Database, acc *multiaccounts.Account, accountManager *account.GethManager, rpcClient *rpc.Client, logger *zap.Logger) error {
var err error
if !s.config.ShhextConfig.PFSEnabled {
return nil

View File

@ -137,7 +137,7 @@ func TestInitProtocol(t *testing.T) {
acc := &multiaccounts.Account{KeyUID: "0xdeadbeef"}
err = service.InitProtocol("Test", privateKey, sqlDB, nil, multiAccounts, acc, nil, zap.NewNop())
err = service.InitProtocol("Test", privateKey, sqlDB, nil, multiAccounts, acc, nil, nil, zap.NewNop())
require.NoError(t, err)
}
@ -202,7 +202,7 @@ func (s *ShhExtSuite) createAndAddNode() {
acc := &multiaccounts.Account{KeyUID: "0xdeadbeef"}
err = service.InitProtocol("Test", privateKey, sqlDB, nil, multiAccounts, acc, nil, zap.NewNop())
err = service.InitProtocol("Test", privateKey, sqlDB, nil, multiAccounts, acc, nil, nil, zap.NewNop())
s.NoError(err)
stack.RegisterLifecycle(service)