Skip to content

Commit

Permalink
Merge pull request #11 from hyle-team/dev/subscriber
Browse files Browse the repository at this point in the history
Dev/subscriber-submodule
  • Loading branch information
slbmax authored Feb 12, 2025
2 parents 33224d5 + a8bc804 commit 772b40e
Show file tree
Hide file tree
Showing 10 changed files with 299 additions and 8 deletions.
3 changes: 1 addition & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package cmd

import (
"os"

"github.com/hyle-team/tss-svc/cmd/helpers"
"github.com/hyle-team/tss-svc/cmd/service"
"os"

"github.com/spf13/cobra"
)
Expand Down
12 changes: 12 additions & 0 deletions cmd/service/run/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/hyle-team/tss-svc/internal/bridge/withdrawal"
"github.com/hyle-team/tss-svc/internal/config"
core "github.com/hyle-team/tss-svc/internal/core/connector"
"github.com/hyle-team/tss-svc/internal/core/subscriber"
pg "github.com/hyle-team/tss-svc/internal/db/postgres"
"github.com/hyle-team/tss-svc/internal/p2p"
"github.com/hyle-team/tss-svc/internal/secrets/vault"
Expand Down Expand Up @@ -67,6 +68,7 @@ func runSigningService(ctx context.Context, cfg config.Config, wg *sync.WaitGrou

db := pg.NewDepositsQ(cfg.DB())
connector := core.NewConnector(*account, cfg.CoreConnectorConfig().Connection, cfg.CoreConnectorConfig().Settings)
sub := subscriber.NewSubmitSubscriber(db, cfg.TendermintHttpClient(), logger)
fetcher := bridge.NewDepositFetcher(clientsRepo, connector)
srv := api.NewServer(
cfg.ApiGrpcListener(),
Expand Down Expand Up @@ -174,6 +176,16 @@ func runSigningService(ctx context.Context, cfg config.Config, wg *sync.WaitGrou
depositAcceptorSession.Run(ctx)
}()

// Core deposit subscriber spin-up
wg.Add(1)
go func() {
defer wg.Done()

if err := sub.Run(ctx); err != nil {
logger.WithError(err).Error("failed to run Core event subscriber")
}
}()

// p2p server spin-up
wg.Add(1)
go func() {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ require (
github.com/pkg/errors v0.9.1
github.com/rubenv/sql-migrate v1.7.0
github.com/spf13/cobra v1.8.1
github.com/tendermint/tendermint v0.34.28
gitlab.com/distributed_lab/ape v1.7.2
gitlab.com/distributed_lab/figure/v3 v3.1.4
gitlab.com/distributed_lab/kit v1.11.3
Expand Down Expand Up @@ -159,7 +160,6 @@ require (
github.com/subosito/gotenv v1.6.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
github.com/tendermint/go-amino v0.16.0 // indirect
github.com/tendermint/tendermint v0.34.28 // indirect
github.com/tendermint/tm-db v0.6.7 // indirect
github.com/tidwall/btree v1.6.0 // indirect
github.com/tidwall/gjson v1.14.4 // indirect
Expand Down
2 changes: 1 addition & 1 deletion go.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg=
Expand Down
5 changes: 4 additions & 1 deletion internal/config/config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,7 @@ core_connector:
settings:
chain_id: "00000"
denom: "denom"
min_gas_price: 0
min_gas_price: 0

subscriber:
addr: "tcp"
4 changes: 4 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package config
import (
"github.com/hyle-team/tss-svc/internal/bridge/chains"
connector "github.com/hyle-team/tss-svc/internal/core/connector/config"
subscriber "github.com/hyle-team/tss-svc/internal/core/subscriber/config"
p2p "github.com/hyle-team/tss-svc/internal/p2p/config"
vaulter "github.com/hyle-team/tss-svc/internal/secrets/vault/config"
tss "github.com/hyle-team/tss-svc/internal/tss/config"
Expand All @@ -20,6 +21,7 @@ type Config interface {
tss.SessionParamsConfigurator
chains.Chainer
connector.ConnectorConfigurer
subscriber.SubscriberConfigurator
}

type config struct {
Expand All @@ -33,6 +35,7 @@ type config struct {
tss.SessionParamsConfigurator
chains.Chainer
connector.ConnectorConfigurer
subscriber.SubscriberConfigurator
}

func New(getter kv.Getter) Config {
Expand All @@ -46,5 +49,6 @@ func New(getter kv.Getter) Config {
SessionParamsConfigurator: tss.NewSessionParamsConfigurator(getter),
Chainer: chains.NewChainer(getter),
ConnectorConfigurer: connector.NewConnectorConfigurer(getter),
SubscriberConfigurator: subscriber.NewSubscriberConfigurator(getter),
}
}
48 changes: 48 additions & 0 deletions internal/core/subscriber/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package config

import (
"github.com/tendermint/tendermint/rpc/client/http"
"gitlab.com/distributed_lab/figure/v3"
"gitlab.com/distributed_lab/kit/comfig"
"gitlab.com/distributed_lab/kit/kv"
)

const subscriberConfigKey = "subscriber"

type SubscriberConfigurator interface {
TendermintHttpClient() *http.HTTP
}

type subscriber struct {
once comfig.Once
getter kv.Getter
}

func NewSubscriberConfigurator(getter kv.Getter) SubscriberConfigurator {
return &subscriber{
getter: getter,
}
}

func (sc *subscriber) TendermintHttpClient() *http.HTTP {
return sc.once.Do(func() interface{} {
var config struct {
Addr string `fig:"addr"`
}

if err := figure.Out(&config).From(kv.MustGetStringMap(sc.getter, subscriberConfigKey)).Please(); err != nil {
panic(err)
}

client, err := http.New(config.Addr, "/websocket")
if err != nil {
panic(err)
}

if err = client.Start(); err != nil {
panic(err)
}

return client
}).(*http.HTTP)
}
171 changes: 171 additions & 0 deletions internal/core/subscriber/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package subscriber

import (
"context"
"fmt"
"strconv"
"strings"

bridgeTypes "github.com/hyle-team/bridgeless-core/v12/x/bridge/types"
database "github.com/hyle-team/tss-svc/internal/db"
"github.com/hyle-team/tss-svc/internal/types"
"github.com/pkg/errors"
"github.com/tendermint/tendermint/rpc/client/http"
coretypes "github.com/tendermint/tendermint/rpc/core/types"
"gitlab.com/distributed_lab/logan/v3"
)

const (
OpServiceName = "op-subscriber"
OpPoolSize = 50

OpQuerySubmit = "tm.event='Tx' AND message.action='/core.bridge.MsgSubmitTransactions'"
)

type Subscriber struct {
db database.DepositsQ
client *http.HTTP
query string
log *logan.Entry
}

func NewSubmitSubscriber(db database.DepositsQ, client *http.HTTP, logger *logan.Entry) *Subscriber {
return &Subscriber{
db: db,
client: client,
query: OpQuerySubmit,
log: logger,
}
}

func (s *Subscriber) Run(ctx context.Context) error {
out, err := s.client.Subscribe(ctx, OpServiceName, s.query, OpPoolSize)
if err != nil {
return errors.Wrap(err, "subscriber init failed")
}

go s.run(ctx, out)

return nil
}

func (s *Subscriber) run(ctx context.Context, out <-chan coretypes.ResultEvent) {
for {
select {
case <-ctx.Done():
if err := s.client.Unsubscribe(ctx, OpServiceName, s.query); err != nil {
s.log.WithError(err).Error("failed to unsubscribe from new operations")
}

s.log.Info("context finished")
return
case c, ok := <-out:
if !ok {
s.log.Warn("chanel closed, stopping receiving messages")
return
}

deposit, err := parseSubmittedDeposit(c.Events)
if err != nil {
s.log.WithError(err).Error("failed to parse submitted deposit")
continue
}

tx, err := s.db.Get(deposit.DepositIdentifier)
if err != nil {
s.log.WithError(err).Error("failed to get deposit")
continue
}

// if deposit does not exist in db insert it
if tx == nil {
s.log.Info("found new submitted deposit")
if _, err = s.db.InsertProcessedDeposit(*deposit); err != nil {
s.log.WithError(err).Error("failed to insert new deposit")
}
continue
}

// if deposit exists and pending or processing update signature,withdrawal tx hash and status
switch tx.WithdrawalStatus {
case types.WithdrawalStatus_WITHDRAWAL_STATUS_PROCESSED:
s.log.Info("skipping processed deposit")
case types.WithdrawalStatus_WITHDRAWAL_STATUS_PROCESSING:
s.log.Info("found existing deposit submitted to core")
if err = s.db.UpdateWithdrawalDetails(tx.DepositIdentifier, deposit.WithdrawalTxHash, deposit.Signature); err != nil {
s.log.WithError(err).Error("failed to update deposit withdrawal details")
}
case types.WithdrawalStatus_WITHDRAWAL_STATUS_PENDING:
s.log.Info("found submitted pending deposit")
if err = s.db.UpdateWithdrawalDetails(tx.DepositIdentifier, deposit.WithdrawalTxHash, deposit.Signature); err != nil {
s.log.WithError(err).Error("failed to update deposit withdrawal details")
}
default:
s.log.Infof("nothing to do with deposit status %s", tx.WithdrawalStatus)
}
}
}
}

func parseSubmittedDeposit(attributes map[string][]string) (*database.Deposit, error) {
deposit := &database.Deposit{}
for keys, attribute := range attributes {

parts := strings.SplitN(keys, ".", 2)
if parts[0] != bridgeTypes.EventType_DEPOSIT_SUBMITTED.String() {
continue
}

switch parts[1] {
case bridgeTypes.AttributeKeyDepositTxHash:
deposit.TxHash = attribute[0]
case bridgeTypes.AttributeKeyDepositNonce:
n, err := strconv.Atoi(attribute[0])
if err != nil {
return nil, errors.Wrap(errors.New(fmt.Sprintf("got invalid nonce, got %s", attribute)), "invalid nonce")
}
deposit.TxNonce = n
case bridgeTypes.AttributeKeyDepositChainId:
deposit.ChainId = attribute[0]
case bridgeTypes.AttributeKeyDepositAmount:
deposit.DepositAmount = &attribute[0]
case bridgeTypes.AttributeKeyDepositToken:
deposit.DepositToken = &attribute[0]
case bridgeTypes.AttributeKeyDepositBlock:
b, err := strconv.ParseInt(attribute[0], 10, 64)
if err != nil {
return nil, errors.Wrap(err, "failed to parse deposit block")
}
deposit.DepositBlock = &b
case bridgeTypes.AttributeKeyWithdrawalAmount:
deposit.WithdrawalAmount = &attribute[0]
case bridgeTypes.AttributeKeyDepositor:
deposit.Depositor = &attribute[0]
case bridgeTypes.AttributeKeyReceiver:
deposit.Receiver = &attribute[0]
case bridgeTypes.AttributeKeyWithdrawalChainID:
deposit.WithdrawalChainId = &attribute[0]
case bridgeTypes.AttributeKeyWithdrawalTxHash:
if attribute[0] != "" {
deposit.WithdrawalTxHash = &attribute[0]
}
case bridgeTypes.AttributeKeyWithdrawalToken:
deposit.WithdrawalToken = &attribute[0]
case bridgeTypes.AttributeKeySignature:
if attribute[0] != "" {
deposit.Signature = &attribute[0]
}
case bridgeTypes.AttributeKeyIsWrapped:
isWrapped, err := strconv.ParseBool(attribute[0])
if err != nil {
return nil, errors.Wrap(err, "failed to parse isWrapped attribute")
}
deposit.IsWrappedToken = &isWrapped
default:

return nil, errors.Wrap(errors.New(fmt.Sprintf("unknown attribute key: %s", parts[1])), "failed to parse attribute")
}
}

return deposit, nil
}
3 changes: 2 additions & 1 deletion internal/db/deposits.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ type DepositsQ interface {
GetWithSelector(selector DepositsSelector) (*Deposit, error)

Exists(check DepositExistenceCheck) (bool, error)

UpdateWithdrawalDetails(identifier DepositIdentifier, hash *string, signature *string) error
UpdateWithdrawalTx(DepositIdentifier, string) error
UpdateSignature(DepositIdentifier, string) error
UpdateStatus(DepositIdentifier, types.WithdrawalStatus) error
InsertProcessedDeposit(deposit Deposit) (int64, error)

Transaction(f func() error) error
}
Expand Down
Loading

0 comments on commit 772b40e

Please sign in to comment.