github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/session/pingpong/hermes_promise_settler.go (about)

     1  /*
     2   * Copyright (C) 2019 The "MysteriumNetwork/node" Authors.
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU General Public License as published by
     6   * the Free Software Foundation, either version 3 of the License, or
     7   * (at your option) any later version.
     8   *
     9   * This program is distributed in the hope that it will be useful,
    10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12   * GNU General Public License for more details.
    13   *
    14   * You should have received a copy of the GNU General Public License
    15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16   */
    17  
    18  package pingpong
    19  
    20  import (
    21  	"bytes"
    22  	"crypto/rand"
    23  	"encoding/hex"
    24  	"errors"
    25  	"fmt"
    26  	"math/big"
    27  	"strings"
    28  	"sync"
    29  	"time"
    30  
    31  	"github.com/ethereum/go-ethereum/accounts"
    32  	"github.com/ethereum/go-ethereum/common"
    33  	"github.com/ethereum/go-ethereum/core/types"
    34  	"github.com/mysteriumnetwork/go-rest/apierror"
    35  	"github.com/mysteriumnetwork/node/config"
    36  	"github.com/mysteriumnetwork/node/core/beneficiary"
    37  	nodevent "github.com/mysteriumnetwork/node/core/node/event"
    38  	"github.com/mysteriumnetwork/node/core/service/servicestate"
    39  	"github.com/mysteriumnetwork/node/eventbus"
    40  	"github.com/mysteriumnetwork/node/identity"
    41  	"github.com/mysteriumnetwork/node/identity/registry"
    42  	"github.com/mysteriumnetwork/node/session/pingpong/event"
    43  	"github.com/mysteriumnetwork/payments/bindings"
    44  	"github.com/mysteriumnetwork/payments/client"
    45  	"github.com/mysteriumnetwork/payments/crypto"
    46  	"github.com/mysteriumnetwork/payments/observer"
    47  	"github.com/mysteriumnetwork/payments/units"
    48  	"github.com/rs/zerolog/log"
    49  )
    50  
    51  type settlementHistoryStorage interface {
    52  	Store(she SettlementHistoryEntry) error
    53  }
    54  
    55  type providerChannelStatusProvider interface {
    56  	GetHermesFee(chainID int64, hermesAddress common.Address) (uint16, error)
    57  	CalculateHermesFee(chainID int64, hermesAddress common.Address, value *big.Int) (*big.Int, error)
    58  	GetMystBalance(chainID int64, mystAddress, identity common.Address) (*big.Int, error)
    59  	GetProvidersWithdrawalChannel(chainID int64, hermesAddress common.Address, addressToCheck common.Address, pending bool) (client.ProviderChannel, error)
    60  	FilterPromiseSettledEventByChannelID(chainID int64, from uint64, to *uint64, hermesID common.Address, providerAddresses [][32]byte) ([]bindings.HermesImplementationPromiseSettled, error)
    61  	HeaderByNumber(chainID int64, number *big.Int) (*types.Header, error)
    62  	TransactionReceipt(chainID int64, hash common.Hash) (*types.Receipt, error)
    63  }
    64  
    65  type paySettler interface {
    66  	PayAndSettle(r []byte, em crypto.ExchangeMessage, providerID identity.Identity, sessionID string) <-chan error
    67  }
    68  
    69  type ks interface {
    70  	Accounts() []accounts.Account
    71  	SignHash(a accounts.Account, hash []byte) ([]byte, error)
    72  }
    73  
    74  type registrationStatusProvider interface {
    75  	GetRegistrationStatus(chainID int64, id identity.Identity) (registry.RegistrationStatus, error)
    76  }
    77  
    78  type promiseStorage interface {
    79  	Get(chainID int64, channelID string) (HermesPromise, error)
    80  	Delete(promise HermesPromise) error
    81  }
    82  
    83  type transactor interface {
    84  	SettleAndRebalance(hermesID, providerID string, promise crypto.Promise) (string, error)
    85  	SettleWithBeneficiary(id, beneficiary, hermesID string, promise crypto.Promise) (string, error)
    86  	PayAndSettle(hermesID, providerID string, promise crypto.Promise, beneficiary string, beneficiarySignature string) (string, error)
    87  	SettleIntoStake(hermesID, providerID string, promise crypto.Promise) (string, error)
    88  	FetchSettleFees(chainID int64) (registry.FeesResponse, error)
    89  	GetQueueStatus(ID string) (registry.QueueResponse, error)
    90  }
    91  
    92  type hermesChannelProvider interface {
    93  	Get(chainID int64, id identity.Identity, hermesID common.Address) (HermesChannel, bool)
    94  	Fetch(chainID int64, id identity.Identity, hermesID common.Address) (HermesChannel, error)
    95  }
    96  
    97  type receivedPromise struct {
    98  	provider    identity.Identity
    99  	hermesID    common.Address
   100  	promise     crypto.Promise
   101  	beneficiary common.Address
   102  	maxFee      *big.Int
   103  }
   104  
   105  // HermesPromiseSettler is responsible for settling the hermes promises.
   106  type HermesPromiseSettler interface {
   107  	ForceSettle(chainID int64, providerID identity.Identity, hermesID ...common.Address) error
   108  	ForceSettleAsync(chainID int64, providerID identity.Identity, hermesID ...common.Address) error
   109  	SettleWithBeneficiary(chainID int64, providerID identity.Identity, beneficiary common.Address, hermeses []common.Address) error
   110  	SettleIntoStake(chainID int64, providerID identity.Identity, hermesID ...common.Address) error
   111  	GetHermesFee(chainID int64, hermesID common.Address) (uint16, error)
   112  	Withdraw(fromChainID int64, toChainID int64, providerID identity.Identity, hermesID, beneficiary common.Address, amount *big.Int) error
   113  	CheckLatestWithdrawal(chainID int64, providerID identity.Identity, hermesID common.Address) (*big.Int, string, error)
   114  	RetryWithdrawLatest(chainID int64, amountToWithdraw *big.Int, chid string, beneficiary common.Address, providerID identity.Identity) error
   115  }
   116  
   117  // hermesPromiseSettler is responsible for settling the hermes promises.
   118  type hermesPromiseSettler struct {
   119  	bc                         providerChannelStatusProvider
   120  	config                     HermesPromiseSettlerConfig
   121  	lock                       sync.RWMutex
   122  	registrationStatusProvider registrationStatusProvider
   123  	ks                         ks
   124  	transactor                 transactor
   125  	channelProvider            hermesChannelProvider
   126  	settlementHistoryStorage   settlementHistoryStorage
   127  	hermesURLGetter            hermesURLGetter
   128  	hermesCallerFactory        HermesCallerFactory
   129  	addressProvider            addressProvider
   130  	paySettler                 paySettler
   131  	promiseStorage             promiseStorage
   132  	publisher                  eventbus.Publisher
   133  	hf                         hermesFees
   134  	observerApi                observerApi
   135  	beneficiaryLocalStorage    beneficiary.BeneficiaryStorage
   136  	currentState               map[identity.Identity]settlementState
   137  	settleQueue                chan receivedPromise
   138  	stop                       chan struct{}
   139  	once                       sync.Once
   140  }
   141  
   142  type hermesFees struct {
   143  	fees map[string]uint16
   144  	m    sync.RWMutex
   145  }
   146  
   147  func (h *hermesFees) key(chainID int64, hermesID common.Address) string {
   148  	return fmt.Sprint(chainID, hermesID.Hex())
   149  }
   150  
   151  func (h *hermesFees) set(chainID int64, hermesID common.Address, fee uint16) {
   152  	h.m.Lock()
   153  	defer h.m.Unlock()
   154  	h.fees[h.key(chainID, hermesID)] = fee
   155  }
   156  
   157  func (h *hermesFees) get(chainID int64, hermesID common.Address) (uint16, bool) {
   158  	h.m.RLock()
   159  	defer h.m.RUnlock()
   160  	got, ok := h.fees[h.key(chainID, hermesID)]
   161  	return got, ok
   162  }
   163  
   164  // HermesPromiseSettlerConfig configures the hermes promise settler accordingly.
   165  type HermesPromiseSettlerConfig struct {
   166  	MaxFeeThreshold         float64
   167  	MinAutoSettleAmount     float64
   168  	MaxUnSettledAmount      float64
   169  	L1ChainID               int64
   170  	L2ChainID               int64
   171  	SettlementCheckInterval time.Duration
   172  	SettlementCheckTimeout  time.Duration
   173  	BalanceThreshold        float64
   174  }
   175  
   176  var errFeeNotCovered = errors.New("fee not covered, cannot continue")
   177  
   178  // NewHermesPromiseSettler creates a new instance of hermes promise settler.
   179  func NewHermesPromiseSettler(transactor transactor, promiseStorage promiseStorage, paySettler paySettler, addressProvider addressProvider, hermesCallerFactory HermesCallerFactory, hermesURLGetter hermesURLGetter, channelProvider hermesChannelProvider, providerChannelStatusProvider providerChannelStatusProvider, registrationStatusProvider registrationStatusProvider, ks ks, settlementHistoryStorage settlementHistoryStorage, publisher eventbus.Publisher, observerApi observerApi, beneficiaryLocalStorage beneficiary.BeneficiaryStorage, config HermesPromiseSettlerConfig) *hermesPromiseSettler {
   180  	return &hermesPromiseSettler{
   181  		bc:                         providerChannelStatusProvider,
   182  		ks:                         ks,
   183  		registrationStatusProvider: registrationStatusProvider,
   184  		config:                     config,
   185  		currentState:               make(map[identity.Identity]settlementState),
   186  		channelProvider:            channelProvider,
   187  		settlementHistoryStorage:   settlementHistoryStorage,
   188  		hermesCallerFactory:        hermesCallerFactory,
   189  		hermesURLGetter:            hermesURLGetter,
   190  		addressProvider:            addressProvider,
   191  		promiseStorage:             promiseStorage,
   192  		paySettler:                 paySettler,
   193  		publisher:                  publisher,
   194  		beneficiaryLocalStorage:    beneficiaryLocalStorage,
   195  		hf: hermesFees{
   196  			fees: make(map[string]uint16),
   197  		},
   198  		observerApi: observerApi,
   199  		// defaulting to a queue of 5, in case we have a few active identities.
   200  		settleQueue: make(chan receivedPromise, 5),
   201  		stop:        make(chan struct{}),
   202  		transactor:  transactor,
   203  	}
   204  }
   205  
   206  // GetHermesFee fetches the hermes fee.
   207  func (aps *hermesPromiseSettler) GetHermesFee(chainID int64, hermesID common.Address) (uint16, error) {
   208  	got, ok := aps.hf.get(chainID, hermesID)
   209  	if !ok {
   210  		fees, err := aps.bc.GetHermesFee(chainID, hermesID)
   211  		if err != nil {
   212  			return 0, err
   213  		}
   214  
   215  		aps.hf.set(chainID, hermesID, fees)
   216  		return fees, nil
   217  	}
   218  
   219  	return got, nil
   220  }
   221  
   222  // loadInitialState loads the initial state for the given identity. Inteded to be called on service start.
   223  func (aps *hermesPromiseSettler) loadInitialState(chainID int64, id identity.Identity) error {
   224  	aps.lock.Lock()
   225  	defer aps.lock.Unlock()
   226  
   227  	if _, ok := aps.currentState[id]; ok {
   228  		log.Info().Msgf("State for %v already loaded, skipping", id)
   229  		return nil
   230  	}
   231  
   232  	status, err := aps.registrationStatusProvider.GetRegistrationStatus(chainID, id)
   233  	if err != nil {
   234  		return fmt.Errorf("could not check registration status for %v: %w", id, err)
   235  	}
   236  
   237  	if status != registry.Registered {
   238  		log.Info().Msgf("Provider %v not registered, skipping", id)
   239  		return nil
   240  	}
   241  
   242  	aps.currentState[id] = settlementState{
   243  		registered:       true,
   244  		settleInProgress: make(map[common.Address]struct{}),
   245  	}
   246  	return nil
   247  }
   248  
   249  // Subscribe subscribes the hermes promise settler to the appropriate events
   250  func (aps *hermesPromiseSettler) Subscribe(bus eventbus.Subscriber) error {
   251  	err := bus.SubscribeAsync(nodevent.AppTopicNode, aps.handleNodeEvent)
   252  	if err != nil {
   253  		return fmt.Errorf("could not subscribe to node status event: %w", err)
   254  	}
   255  
   256  	err = bus.SubscribeAsync(registry.AppTopicIdentityRegistration, aps.handleRegistrationEvent)
   257  	if err != nil {
   258  		return fmt.Errorf("could not subscribe to registration event: %w", err)
   259  	}
   260  
   261  	err = bus.SubscribeAsync(servicestate.AppTopicServiceStatus, aps.handleServiceEvent)
   262  	if err != nil {
   263  		return fmt.Errorf("could not subscribe to service status event: %w", err)
   264  	}
   265  
   266  	err = bus.SubscribeAsync(event.AppTopicSettlementRequest, aps.handleSettlementEvent)
   267  	if err != nil {
   268  		return fmt.Errorf("could not subscribe to settlement event: %w", err)
   269  	}
   270  
   271  	err = bus.SubscribeAsync(event.AppTopicHermesPromise, aps.handleHermesPromiseReceived)
   272  	if err != nil {
   273  		return fmt.Errorf("could not subscribe to hermes promise event: %w", err)
   274  	}
   275  	return nil
   276  }
   277  
   278  func (aps *hermesPromiseSettler) handleSettlementEvent(event event.AppEventSettlementRequest) {
   279  	err := aps.ForceSettle(event.ChainID, event.ProviderID, event.HermesID)
   280  	if err != nil {
   281  		log.Error().Err(err).Msg("could not settle promise")
   282  	}
   283  }
   284  
   285  func (aps *hermesPromiseSettler) chainID() int64 {
   286  	return config.GetInt64(config.FlagChainID)
   287  }
   288  
   289  func (aps *hermesPromiseSettler) handleServiceEvent(event servicestate.AppEventServiceStatus) {
   290  	switch event.Status {
   291  	case string(servicestate.Running):
   292  		err := aps.loadInitialState(aps.chainID(), identity.FromAddress(event.ProviderID))
   293  		if err != nil {
   294  			log.Error().Err(err).Msgf("could not load initial state for provider %v", event.ProviderID)
   295  		}
   296  	default:
   297  		log.Debug().Msgf("Ignoring service event with status %v", event.Status)
   298  	}
   299  }
   300  
   301  func (aps *hermesPromiseSettler) handleNodeEvent(payload nodevent.Payload) {
   302  	if payload.Status == nodevent.StatusStarted {
   303  		aps.handleNodeStart()
   304  		return
   305  	}
   306  
   307  	if payload.Status == nodevent.StatusStopped {
   308  		aps.handleNodeStop()
   309  		return
   310  	}
   311  }
   312  
   313  func (aps *hermesPromiseSettler) handleRegistrationEvent(payload registry.AppEventIdentityRegistration) {
   314  	aps.lock.Lock()
   315  	defer aps.lock.Unlock()
   316  
   317  	if payload.Status != registry.Registered {
   318  		log.Debug().Msgf("Ignoring event %v for provider %q", payload.Status.String(), payload.ID)
   319  		return
   320  	}
   321  	log.Info().Msgf("Identity registration event received for provider %q", payload.ID)
   322  
   323  	s := aps.currentState[payload.ID]
   324  	s.registered = true
   325  	aps.currentState[payload.ID] = s
   326  	log.Info().Msgf("Identity registration event handled for provider %q", payload.ID)
   327  }
   328  
   329  func (aps *hermesPromiseSettler) handleHermesPromiseReceived(apep event.AppEventHermesPromise) {
   330  	id := apep.ProviderID
   331  	log.Info().Msgf("Received hermes promise for %q", id)
   332  	aps.lock.Lock()
   333  	defer aps.lock.Unlock()
   334  
   335  	s, ok := aps.currentState[apep.ProviderID]
   336  	if !ok {
   337  		log.Error().Msgf("Have no info on provider %q, skipping", id)
   338  		return
   339  	}
   340  	if !s.registered {
   341  		log.Error().Msgf("provider %q not registered, skipping", id)
   342  		return
   343  	}
   344  
   345  	var channel HermesChannel
   346  	hc, ok := aps.channelProvider.Get(apep.Promise.ChainID, id, apep.HermesID)
   347  	if ok {
   348  		channel = hc
   349  	} else {
   350  		hc, err := aps.channelProvider.Fetch(apep.Promise.ChainID, id, apep.HermesID)
   351  		if err != nil && !errors.Is(err, ErrNotFound) {
   352  			log.Error().Err(err).Msgf("could not sync state for provider %v, hermesID %v", apep.ProviderID, apep.HermesID.Hex())
   353  			return
   354  		}
   355  		channel = hc
   356  	}
   357  
   358  	log.Info().Msgf("Hermes %q promise state updated for provider %q", apep.HermesID.Hex(), id)
   359  
   360  	needs, maxFee := aps.needsSettling(s, aps.config.BalanceThreshold, aps.config.MaxFeeThreshold, aps.config.MinAutoSettleAmount, aps.config.MaxUnSettledAmount, channel, apep.Promise.ChainID)
   361  	if needs {
   362  		log.Info().Msgf("Starting auto settle for provider %v", id)
   363  		aps.initiateSettling(channel, maxFee)
   364  	}
   365  }
   366  
   367  func (aps *hermesPromiseSettler) initiateSettling(channel HermesChannel, maxFee *big.Int) {
   368  	hexR, err := hex.DecodeString(channel.lastPromise.R)
   369  	if err != nil {
   370  		log.Error().Err(fmt.Errorf("could encode R: %w", err))
   371  		return
   372  	}
   373  	channel.lastPromise.Promise.R = hexR
   374  	aps.settleQueue <- receivedPromise{
   375  		hermesID:    channel.HermesID,
   376  		provider:    channel.Identity,
   377  		promise:     channel.lastPromise.Promise,
   378  		beneficiary: channel.Beneficiary,
   379  		maxFee:      maxFee,
   380  	}
   381  }
   382  
   383  func (aps *hermesPromiseSettler) listenForSettlementRequests() {
   384  	log.Info().Msg("Listening for settlement events")
   385  	defer log.Info().Msg("Stopped listening for settlement events")
   386  
   387  	for {
   388  		select {
   389  		case <-aps.stop:
   390  			return
   391  		case p := <-aps.settleQueue:
   392  			channel, found := aps.channelProvider.Get(p.promise.ChainID, p.provider, p.hermesID)
   393  			if !found {
   394  				continue
   395  			}
   396  
   397  			beneficiary, changed, err := aps.validateBeneficiary(p.promise.ChainID, p.provider.ToCommonAddress(), p.beneficiary)
   398  			if err != nil {
   399  				log.Error().Err(err).Msg("could not validate beneficiary")
   400  				continue
   401  			}
   402  			settleFunc := func(promise crypto.Promise) (string, error) {
   403  				return aps.transactor.SettleAndRebalance(p.hermesID.Hex(), p.provider.Address, promise)
   404  			}
   405  			if changed {
   406  				settleFunc = func(promise crypto.Promise) (string, error) {
   407  					return aps.transactor.SettleWithBeneficiary(p.provider.Address, channel.Beneficiary.Hex(), p.hermesID.Hex(), promise)
   408  				}
   409  			}
   410  			channel.Beneficiary = beneficiary
   411  
   412  			go aps.settle(
   413  				settleFunc,
   414  				p.provider,
   415  				p.hermesID,
   416  				p.promise,
   417  				channel.Beneficiary,
   418  				channel.Channel.Settled,
   419  				p.maxFee,
   420  			)
   421  		}
   422  	}
   423  }
   424  
   425  // SettleIntoStake settles the promise but transfers the money to stake increase, not to beneficiary.
   426  func (aps *hermesPromiseSettler) SettleIntoStake(chainID int64, providerID identity.Identity, hermesIDs ...common.Address) error {
   427  	for _, hermesID := range hermesIDs {
   428  		channel, err := aps.channelProvider.Fetch(chainID, providerID, hermesID)
   429  		if err != nil {
   430  			log.Err(err).Fields(map[string]interface{}{
   431  				"chain_id":  chainID,
   432  				"provider":  providerID.Address,
   433  				"hermes_id": hermesID,
   434  			}).Msg("Failed to fetch a channel")
   435  			return ErrNothingToSettle
   436  		}
   437  
   438  		hexR, err := hex.DecodeString(channel.lastPromise.R)
   439  		if err != nil {
   440  			return fmt.Errorf("could not decode R: %w", err)
   441  		}
   442  		channel.lastPromise.Promise.R = hexR
   443  		err = aps.settle(
   444  			func(promise crypto.Promise) (string, error) {
   445  				return aps.transactor.SettleIntoStake(hermesID.Hex(), providerID.Address, promise)
   446  			},
   447  			providerID,
   448  			hermesID,
   449  			channel.lastPromise.Promise,
   450  			channel.Beneficiary,
   451  			channel.Channel.Settled,
   452  			nil,
   453  		)
   454  		if err != nil {
   455  			return err
   456  		}
   457  	}
   458  
   459  	return nil
   460  }
   461  
   462  // ErrNothingToSettle indicates that there is nothing to settle.
   463  var ErrNothingToSettle = errors.New("nothing to settle for the given provider")
   464  
   465  // ForceSettle forces the settlement for a provider
   466  func (aps *hermesPromiseSettler) ForceSettle(chainID int64, providerID identity.Identity, hermesIDs ...common.Address) error {
   467  	return aps.forceSettle(false, chainID, providerID, hermesIDs...)
   468  }
   469  
   470  // ForceSettleAsync forces the settlement for a provider asynchronously
   471  func (aps *hermesPromiseSettler) ForceSettleAsync(chainID int64, providerID identity.Identity, hermesIDs ...common.Address) error {
   472  	return aps.forceSettle(true, chainID, providerID, hermesIDs...)
   473  }
   474  
   475  func (aps *hermesPromiseSettler) forceSettle(async bool, chainID int64, providerID identity.Identity, hermesIDs ...common.Address) error {
   476  	feeNotCoveredCount := 0
   477  	for _, hermesID := range hermesIDs {
   478  		channel, err := aps.channelProvider.Fetch(chainID, providerID, hermesID)
   479  		if err != nil {
   480  			log.Err(err).Fields(map[string]interface{}{
   481  				"chain_id":  chainID,
   482  				"provider":  providerID.Address,
   483  				"hermes_id": hermesID,
   484  			}).Msg("Failed to fetch a channel")
   485  			return ErrNothingToSettle
   486  		}
   487  
   488  		beneficiary, changed, err := aps.validateBeneficiary(aps.chainID(), common.HexToAddress(providerID.Address), channel.Beneficiary)
   489  		if err != nil {
   490  			return fmt.Errorf("beneficiary validation failed: %w", err)
   491  		}
   492  		settleFunc := func(promise crypto.Promise) (string, error) {
   493  			return aps.transactor.SettleAndRebalance(hermesID.Hex(), providerID.Address, promise)
   494  		}
   495  		if changed {
   496  			settleFunc = func(promise crypto.Promise) (string, error) {
   497  				return aps.transactor.SettleWithBeneficiary(providerID.Address, channel.Beneficiary.Hex(), hermesID.Hex(), promise)
   498  			}
   499  			channel.Beneficiary = beneficiary
   500  		}
   501  
   502  		hexR, err := hex.DecodeString(channel.lastPromise.R)
   503  		if err != nil {
   504  			return fmt.Errorf("could not decode R: %w", err)
   505  		}
   506  		channel.lastPromise.Promise.R = hexR
   507  
   508  		if !async {
   509  			err = aps.settle(
   510  				settleFunc,
   511  				providerID,
   512  				hermesID,
   513  				channel.lastPromise.Promise,
   514  				channel.Beneficiary,
   515  				channel.Channel.Settled,
   516  				nil,
   517  			)
   518  			if err != nil {
   519  				if errors.Is(err, errFeeNotCovered) {
   520  					log.Warn().Err(err).Str("hermes_id", hermesID.Hex()).Msg("fee not covered, skipping")
   521  					feeNotCoveredCount++
   522  					continue
   523  				}
   524  
   525  				return fmt.Errorf("settlements with hermes %q interrupted with an error: %w", hermesID.Hex(), err)
   526  			}
   527  		} else {
   528  			go func(hermesAddress common.Address) {
   529  				err = aps.settle(
   530  					settleFunc,
   531  					providerID,
   532  					hermesAddress,
   533  					channel.lastPromise.Promise,
   534  					channel.Beneficiary,
   535  					channel.Channel.Settled,
   536  					nil,
   537  				)
   538  				if err != nil {
   539  					if errors.Is(err, errFeeNotCovered) {
   540  						log.Warn().Err(err).Str("hermes_id", hermesAddress.Hex()).Msg("fee not covered, skipping")
   541  						return
   542  					}
   543  					log.Error().Err(err).Str("hermes_id", hermesAddress.Hex()).Msg("settlements with hermes interrupted with an error")
   544  				}
   545  			}(hermesID)
   546  		}
   547  	}
   548  
   549  	if feeNotCoveredCount == len(hermesIDs) {
   550  		return errors.New("fee not covered for all given hermeses, settled with none")
   551  	}
   552  
   553  	return nil
   554  }
   555  
   556  // ForceSettleInactiveHermeses forces the settlement for the inactive hermeses
   557  func (aps *hermesPromiseSettler) ForceSettleInactiveHermeses(chainID int64, providerID identity.Identity) error {
   558  	active := false
   559  	approved := true
   560  	inactiveHermeses, err := aps.observerApi.GetHermeses(&observer.HermesFilter{
   561  		Active:   &active,
   562  		Approved: &approved,
   563  	})
   564  	if err != nil {
   565  		return fmt.Errorf("failed to get inactive hermeses: %w", err)
   566  	}
   567  	chainInactiveHermesesResponses, ok := inactiveHermeses[chainID]
   568  	if !ok {
   569  		log.Info().Msgf("no inactive hermeses found for chain: %d", chainID)
   570  		return nil
   571  	}
   572  
   573  	chainInactiveHermeses := make([]common.Address, len(chainInactiveHermesesResponses))
   574  	for i, h := range chainInactiveHermesesResponses {
   575  		chainInactiveHermeses[i] = h.HermesAddress
   576  	}
   577  
   578  	return aps.ForceSettle(chainID, providerID, chainInactiveHermeses...)
   579  }
   580  
   581  // SettleWithBeneficiary settles the promise with beneficiary.
   582  func (aps *hermesPromiseSettler) SettleWithBeneficiary(chainID int64, providerID identity.Identity, beneficiary common.Address, hermeses []common.Address) error {
   583  	err := aps.beneficiaryLocalStorage.Save(providerID.Address, beneficiary.Hex())
   584  	if err != nil {
   585  		return fmt.Errorf("could not save beneficiary before settling with beneficiary: %w", err)
   586  	}
   587  
   588  	return aps.forceSettle(false, chainID, providerID, hermeses...)
   589  }
   590  
   591  // ErrSettleTimeout indicates that the settlement has timed out
   592  var ErrSettleTimeout = errors.New("settle timeout")
   593  
   594  func (aps *hermesPromiseSettler) updatePromiseWithLatestFee(hermesID common.Address, promise crypto.Promise, maxFee *big.Int) (crypto.Promise, error) {
   595  	log.Debug().Msgf("Updating promise with latest fee. HermesID %v", hermesID.Hex())
   596  	fees, err := aps.transactor.FetchSettleFees(promise.ChainID)
   597  	if err != nil {
   598  		return crypto.Promise{}, fmt.Errorf("could not fetch settle fees: %w", err)
   599  	}
   600  
   601  	if maxFee != nil && fees.Fee.Cmp(maxFee) == 1 {
   602  		return crypto.Promise{}, fmt.Errorf("current fee is more than the max")
   603  	}
   604  
   605  	hermesCaller, err := aps.getHermesCaller(promise.ChainID, hermesID)
   606  	if err != nil {
   607  		return crypto.Promise{}, fmt.Errorf("could not fetch settle fees: %w", err)
   608  	}
   609  
   610  	updatedPromise, err := hermesCaller.UpdatePromiseFee(promise, fees.Fee)
   611  	if err != nil {
   612  		var hermesErr *HermesErrorResponse
   613  		if errors.As(err, &hermesErr) {
   614  			return crypto.Promise{}, fmt.Errorf("could not update promise fee: %w", err)
   615  		}
   616  		log.Err(err).Msg("could not update promise fee with unknown error, will try settling with outdated promise")
   617  		return promise, nil
   618  	}
   619  	updatedPromise.R = promise.R
   620  	log.Debug().Msg("promise updated with latest fee")
   621  	return updatedPromise, nil
   622  }
   623  
   624  func (aps *hermesPromiseSettler) Withdraw(
   625  	fromChainID int64,
   626  	toChainID int64,
   627  	providerID identity.Identity,
   628  	hermesID,
   629  	beneficiary common.Address,
   630  	amountToWithdraw *big.Int,
   631  ) error {
   632  	if aps.isSettling(providerID, hermesID) {
   633  		return errors.New("provider already has settlement in progress")
   634  	}
   635  
   636  	aps.setSettling(providerID, hermesID, true)
   637  	log.Info().Msgf("Marked provider %v as requesting settlement", providerID)
   638  	defer aps.setSettling(providerID, hermesID, false)
   639  
   640  	if toChainID == 0 {
   641  		toChainID = aps.config.L1ChainID
   642  	}
   643  
   644  	if fromChainID != aps.config.L2ChainID {
   645  		return fmt.Errorf("can only withdraw from chain with ID %v, requested with %v", aps.config.L2ChainID, fromChainID)
   646  	}
   647  
   648  	registry, err := aps.addressProvider.GetRegistryAddress(fromChainID)
   649  	if err != nil {
   650  		return err
   651  	}
   652  	channel, err := aps.addressProvider.GetChannelImplementationForHermes(fromChainID, hermesID)
   653  	if err != nil {
   654  		return err
   655  	}
   656  
   657  	consumerChannelAddress, err := aps.addressProvider.GetArbitraryChannelAddress(hermesID, registry, channel, providerID.ToCommonAddress())
   658  	if err != nil {
   659  		return fmt.Errorf("could not generate channel address: %w", err)
   660  	}
   661  
   662  	chid, err := crypto.GenerateProviderChannelIDForPayAndSettle(providerID.Address, hermesID.Hex())
   663  	if err != nil {
   664  		return fmt.Errorf("could not get channel id for pay and settle: %w", err)
   665  	}
   666  
   667  	// 1. calculate amount to withdraw - check balance on consumer channel
   668  	data, err := aps.getHermesData(fromChainID, hermesID, providerID.ToCommonAddress())
   669  	if err != nil {
   670  		return err
   671  	}
   672  
   673  	if amountToWithdraw == nil {
   674  		amountToWithdraw = data.Balance
   675  
   676  		// TODO: Pull this from hermes contract in the future.
   677  		maxWithdraw := units.FloatEthToBigIntWei(500)
   678  		if amountToWithdraw.Cmp(maxWithdraw) > 0 {
   679  			amountToWithdraw = maxWithdraw
   680  		}
   681  	}
   682  
   683  	err = aps.validateWithdrawalAmount(amountToWithdraw, toChainID)
   684  	if err != nil {
   685  		return err
   686  	}
   687  
   688  	currentPromise, err := aps.promiseStorage.Get(toChainID, chid)
   689  	if err != nil {
   690  		if !errors.Is(err, ErrNotFound) {
   691  			return err
   692  		}
   693  	}
   694  
   695  	// 2. issue a self promise
   696  	promisedAmount := data.LatestPromise.Amount
   697  	if promisedAmount.Cmp(data.Settled) < 0 {
   698  		// If consumer has an incorrect promise. Issue a correct one
   699  		// together with a withdrawal request.
   700  		promisedAmount = data.Settled
   701  	}
   702  	msg, err := aps.issueSelfPromise(fromChainID, toChainID, amountToWithdraw, promisedAmount, providerID, consumerChannelAddress, hermesID)
   703  	if err != nil {
   704  		return err
   705  	}
   706  
   707  	// 3. call hermes with the promise via the payandsettle endpoint
   708  	ch := aps.paySettler.PayAndSettle(msg.Promise.R, *msg, providerID, "")
   709  	err = <-ch
   710  	if err != nil {
   711  		log.Debug().Msgf("ERROR HERMES. provider:%s, hermes:%s, channel: %s", providerID, hermesID, channel)
   712  		return fmt.Errorf("could not call hermes pay and settle:%w", err)
   713  	}
   714  
   715  	// 4. fetch the promise from storage
   716  	latestPromise, err := aps.promiseStorage.Get(toChainID, chid)
   717  	if err != nil {
   718  		return err
   719  	}
   720  
   721  	if latestPromise.Promise.GetSignatureHexString() == currentPromise.Promise.GetSignatureHexString() {
   722  		log.Warn().Msg("hermes promise was not updated, was not able to complete the withdrawal")
   723  		return errors.New("promise was not updated, please request again")
   724  	}
   725  
   726  	decodedR, err := hex.DecodeString(latestPromise.R)
   727  	if err != nil {
   728  		return fmt.Errorf("could not decode R %w", err)
   729  	}
   730  	latestPromise.Promise.R = decodedR
   731  
   732  	return aps.payAndSettleTransactor(toChainID, amountToWithdraw, beneficiary, providerID, chid, latestPromise, fromChainID)
   733  }
   734  
   735  func (aps *hermesPromiseSettler) CheckLatestWithdrawal(
   736  	chainID int64,
   737  	providerID identity.Identity,
   738  	hermesID common.Address,
   739  ) (*big.Int, string, error) {
   740  	chid, err := crypto.GenerateProviderChannelIDForPayAndSettle(providerID.Address, hermesID.Hex())
   741  	if err != nil {
   742  		return nil, "", fmt.Errorf("could not get channel id for pay and settle: %w", err)
   743  	}
   744  
   745  	latestPromise, err := aps.promiseStorage.Get(chainID, chid)
   746  	if err != nil {
   747  		return nil, chid, err
   748  	}
   749  
   750  	withdrawalChannel, err := aps.bc.GetProvidersWithdrawalChannel(chainID, hermesID, providerID.ToCommonAddress(), true)
   751  	if err != nil {
   752  		return nil, chid, err
   753  	}
   754  
   755  	return new(big.Int).Sub(latestPromise.Promise.Amount, withdrawalChannel.Settled), chid, nil
   756  }
   757  
   758  func (aps *hermesPromiseSettler) RetryWithdrawLatest(
   759  	chainID int64,
   760  	amountToWithdraw *big.Int,
   761  	chid string,
   762  	beneficiary common.Address,
   763  	providerID identity.Identity,
   764  ) error {
   765  	latestPromise, err := aps.promiseStorage.Get(chainID, chid)
   766  	if err != nil {
   767  		return err
   768  	}
   769  
   770  	decodedR, err := hex.DecodeString(latestPromise.R)
   771  	if err != nil {
   772  		return fmt.Errorf("could not decode R %w", err)
   773  	}
   774  	latestPromise.Promise.R = decodedR
   775  
   776  	return aps.payAndSettleTransactor(chainID, amountToWithdraw, beneficiary, providerID, chid, latestPromise, chainID)
   777  
   778  }
   779  
   780  func (aps *hermesPromiseSettler) payAndSettleTransactor(toChainID int64, amountToWithdraw *big.Int, beneficiary common.Address, providerID identity.Identity, chid string, promiseFromStorage HermesPromise, fromChain int64) error {
   781  	decodedR, err := hex.DecodeString(promiseFromStorage.R)
   782  	if err != nil {
   783  		return fmt.Errorf("could not decode R %w", err)
   784  	}
   785  	promiseFromStorage.Promise.R = decodedR
   786  
   787  	// 5. add the missing beneficiary signature
   788  	payload := crypto.NewPayAndSettleBeneficiaryPayload(beneficiary, toChainID, chid, promiseFromStorage.Promise.Amount, client.ToBytes32(promiseFromStorage.Promise.R))
   789  	err = payload.Sign(aps.ks, providerID.ToCommonAddress())
   790  	if err != nil {
   791  		return fmt.Errorf("could not sign pay and settle payload: %w", err)
   792  	}
   793  
   794  	settleFunc := func(promise crypto.Promise) (string, error) {
   795  		id, err := aps.transactor.PayAndSettle(promiseFromStorage.HermesID.Hex(), providerID.Address, promise, payload.Beneficiary.Hex(), hex.EncodeToString(payload.Signature))
   796  		if err != nil {
   797  			return "", err
   798  		}
   799  
   800  		aps.publisher.Publish(event.AppTopicWithdrawalRequested, event.AppEventWithdrawalRequested{
   801  			ProviderID: providerID,
   802  			HermesID:   promiseFromStorage.HermesID,
   803  			FromChain:  fromChain,
   804  			ToChain:    promiseFromStorage.Promise.ChainID,
   805  		})
   806  
   807  		return id, nil
   808  	}
   809  
   810  	go func() {
   811  		log.Info().Msg("calling transactor")
   812  		err := aps.payAndSettle(
   813  			settleFunc,
   814  			providerID,
   815  			promiseFromStorage.HermesID,
   816  			promiseFromStorage.Promise,
   817  			beneficiary,
   818  			amountToWithdraw,
   819  			promiseFromStorage,
   820  		)
   821  		if err != nil {
   822  			log.Err(err).Msg("could not withdraw, failed to call transactor")
   823  			return
   824  		}
   825  		log.Info().Msg("withdrawal complete")
   826  	}()
   827  	return nil
   828  }
   829  
   830  func (aps *hermesPromiseSettler) validateWithdrawalAmount(amount *big.Int, toChain int64) error {
   831  	fees, err := aps.transactor.FetchSettleFees(toChain)
   832  	if err != nil {
   833  		return err
   834  	}
   835  
   836  	if fees.Fee.Cmp(amount) > 0 {
   837  		return fmt.Errorf("transactors fee exceeds amount to withdraw. Fee %v, amount to withdraw %v", fees.Fee.String(), amount.String())
   838  	}
   839  	return nil
   840  }
   841  
   842  func (aps *hermesPromiseSettler) payAndSettle(
   843  	settleFunc func(promise crypto.Promise) (string, error),
   844  	provider identity.Identity,
   845  	hermesID common.Address,
   846  	promise crypto.Promise,
   847  	beneficiary common.Address,
   848  	withdrawalAmount *big.Int,
   849  	promiseFromStorage HermesPromise,
   850  ) error {
   851  
   852  	id, err := aps.settlePayAndSettleWithRetry(settleFunc, withdrawalAmount, promiseFromStorage)
   853  	if err != nil {
   854  		return err
   855  	}
   856  
   857  	channelID, err := crypto.GenerateProviderChannelIDForPayAndSettle(provider.Address, hermesID.Hex())
   858  	if err != nil {
   859  		return fmt.Errorf("could not generate provider channel address: %w", err)
   860  	}
   861  
   862  	errCh := aps.listenForSettlement(hermesID, beneficiary, promise, provider, aps.toBytes32(channelID), id, true)
   863  	return <-errCh
   864  }
   865  
   866  func payAndSettleErrorShouldRetry(err error) bool {
   867  	var apiErr *apierror.APIError
   868  	if errors.As(err, &apiErr) {
   869  		return apiErr.Status == 409 || apiErr.Status >= 500
   870  	}
   871  
   872  	return false
   873  }
   874  
   875  func (aps *hermesPromiseSettler) settlePayAndSettleWithRetry(
   876  	settleFunc func(promise crypto.Promise) (string, error),
   877  	withdrawalAmount *big.Int,
   878  	promiseFromStorage HermesPromise,
   879  ) (string, error) {
   880  	promise, err := aps.updatePromiseWithLatestFee(promiseFromStorage.HermesID, promiseFromStorage.Promise, nil)
   881  	if err != nil {
   882  		log.Error().Err(err).Msg("Could not update promise fee")
   883  		return "", err
   884  	}
   885  
   886  	if promise.Fee.Cmp(withdrawalAmount) > 0 {
   887  		log.Error().Fields(map[string]interface{}{
   888  			"promiseAmount": promise.Amount.String(),
   889  			"transactorFee": promise.Fee.String(),
   890  		}).Err(err).Msg("Earned amount too small for withdrawal")
   891  		return "", fmt.Errorf("amount too small for settlement. Need at least %v, have %v", promise.Fee.String(), withdrawalAmount.String())
   892  	}
   893  
   894  	id, err := settleFunc(promise)
   895  	if err == nil {
   896  		return id, nil
   897  	}
   898  
   899  	if err != nil && !payAndSettleErrorShouldRetry(err) {
   900  		log.Err(err).Msg("tried to settle withdrawal but failed")
   901  		return "", err
   902  	}
   903  
   904  	log.Warn().Err(err).Msg("got an error for which we can retry a withdrawal, will do that")
   905  	// Retry 10 times incase transactor failed to accept our settlement request.
   906  	// There is no point in going for longer than 5 minutes, after that fees
   907  	// will expire and there will be a different amount of fees to pay meaning
   908  	// user would get a different amount of money after the withdrawal.
   909  	// It would be rather strange from users perspective if he ends up paying
   910  	// way more than he agreed when creating the request.
   911  	for i := 0; i < 10; i++ {
   912  		select {
   913  		case <-time.After(time.Second * 30):
   914  			log.Info().Int("count", i+1).Msg("retrying a call to settle withdrawal")
   915  
   916  			id, err := settleFunc(promise)
   917  			if err != nil {
   918  				if payAndSettleErrorShouldRetry(err) {
   919  					log.Warn().Err(err).Msg("failed when retrying withdrawal")
   920  					continue
   921  				}
   922  				return "", err
   923  			}
   924  
   925  			return id, nil
   926  		case <-aps.stop:
   927  			return "", errors.New("stopped trying to withdraw, will not finish")
   928  		}
   929  	}
   930  
   931  	return "", errors.New("out of retries, transactor never accepted our request to pay and settle")
   932  }
   933  
   934  func (aps *hermesPromiseSettler) issueSelfPromise(fromChain, toChain int64, amount, previousPromiseAmount *big.Int, providerID identity.Identity, consumerChannelAddress, hermesAddress common.Address) (*crypto.ExchangeMessage, error) {
   935  	r, err := crypto.GenerateR()
   936  	if err != nil {
   937  		return nil, fmt.Errorf("failed to generate R: %w", err)
   938  	}
   939  	agreementID := aps.generateAgreementID()
   940  	invoice, err := crypto.CreateInvoice(agreementID, amount, big.NewInt(0), r, toChain)
   941  	if err != nil {
   942  		return nil, fmt.Errorf("failed to create invoice: %w", err)
   943  	}
   944  	invoice.Provider = providerID.ToCommonAddress().Hex()
   945  
   946  	promise, err := crypto.CreatePromise(consumerChannelAddress.Hex(), fromChain, big.NewInt(0).Add(amount, previousPromiseAmount), big.NewInt(0), invoice.Hashlock, aps.ks, providerID.ToCommonAddress())
   947  	if err != nil {
   948  		return nil, fmt.Errorf("could not create promise: %w", err)
   949  	}
   950  
   951  	promise.R = r
   952  
   953  	msg, err := crypto.CreateExchangeMessageWithPromise(toChain, invoice, promise, hermesAddress.Hex(), aps.ks, providerID.ToCommonAddress())
   954  	if err != nil {
   955  		return nil, fmt.Errorf("could not get create exchange message: %w", err)
   956  	}
   957  
   958  	return msg, nil
   959  }
   960  
   961  func (aps *hermesPromiseSettler) generateAgreementID() *big.Int {
   962  	agreementID := make([]byte, 32)
   963  	_, err := rand.Read(agreementID)
   964  	if err != nil {
   965  		panic(err)
   966  	}
   967  	return new(big.Int).SetBytes(agreementID)
   968  }
   969  
   970  func (aps *hermesPromiseSettler) getHermesData(chainID int64, hermesID, id common.Address) (*HermesUserInfo, error) {
   971  	caller, err := aps.getHermesCaller(chainID, hermesID)
   972  	if err != nil {
   973  		return nil, err
   974  	}
   975  
   976  	data, err := caller.GetConsumerData(chainID, id.Hex(), time.Second)
   977  	if err != nil {
   978  		return nil, err
   979  	}
   980  
   981  	if data.Balance.Cmp(big.NewInt(0)) > 0 {
   982  		return data.fillZerosIfBigIntNull(), nil
   983  	}
   984  
   985  	// if hermes returned zero, re-check with BC
   986  	myst, err := aps.addressProvider.GetMystAddress(chainID)
   987  	if err != nil {
   988  		return nil, err
   989  	}
   990  
   991  	channelAddress, err := aps.addressProvider.GetActiveChannelAddress(chainID, id)
   992  	if err != nil {
   993  		return nil, err
   994  	}
   995  
   996  	balance, err := aps.bc.GetMystBalance(chainID, myst, channelAddress)
   997  	if err != nil {
   998  		return nil, err
   999  	}
  1000  
  1001  	if balance.Cmp(big.NewInt(0)) <= 0 {
  1002  		return nil, fmt.Errorf("nothing to withdraw. Balance in channel %v is %v", data.ChannelID, data.Balance)
  1003  	}
  1004  
  1005  	data.Balance = balance
  1006  
  1007  	return data.fillZerosIfBigIntNull(), nil
  1008  }
  1009  
  1010  func (aps *hermesPromiseSettler) settle(
  1011  	settleFunc func(promise crypto.Promise) (string, error),
  1012  	provider identity.Identity,
  1013  	hermesID common.Address,
  1014  	promise crypto.Promise,
  1015  	beneficiary common.Address,
  1016  	settled *big.Int,
  1017  	maxFee *big.Int,
  1018  ) error {
  1019  	if aps.isSettling(provider, hermesID) {
  1020  		return errors.New("provider already has settlement in progress")
  1021  	}
  1022  	aps.setSettling(provider, hermesID, true)
  1023  	defer aps.setSettling(provider, hermesID, false)
  1024  
  1025  	log.Info().Msgf("Marked provider %v as requesting settlement", provider)
  1026  
  1027  	updatedPromise, err := aps.updatePromiseWithLatestFee(hermesID, promise, maxFee)
  1028  	if err != nil {
  1029  		log.Error().Err(err).Msg("Could not update promise fee")
  1030  		return err
  1031  	}
  1032  
  1033  	if settled == nil {
  1034  		settled = new(big.Int)
  1035  	}
  1036  
  1037  	amountToSettle := new(big.Int).Sub(updatedPromise.Amount, settled)
  1038  	if amountToSettle.Cmp(big.NewInt(0)) <= 0 {
  1039  		log.Warn().Msgf("Tried to settle for %s MYST", amountToSettle.String())
  1040  		return nil
  1041  	}
  1042  
  1043  	fee, err := aps.bc.CalculateHermesFee(promise.ChainID, hermesID, amountToSettle)
  1044  	if err != nil {
  1045  		log.Error().Err(err).Msg("Could not calculate hermes fee")
  1046  		return err
  1047  	}
  1048  
  1049  	totalFees := new(big.Int).Add(fee, updatedPromise.Fee)
  1050  	if totalFees.Cmp(amountToSettle) > 0 {
  1051  		log.Error().Fields(map[string]interface{}{
  1052  			"amountToSettle": amountToSettle.String(),
  1053  			"promiseAmount":  updatedPromise.Amount.String(),
  1054  			"settled":        settled.String(),
  1055  			"transactorFee":  updatedPromise.Fee.String(),
  1056  			"hermesFee":      fee.String(),
  1057  			"totalFees":      totalFees.String(),
  1058  		}).Err(err).Msg("Earned amount too small for settling")
  1059  		return fmt.Errorf("settlement fees exceed earning amount. Please provide more service and try again. Current earnings: %v, current fees: %v: %w", amountToSettle, totalFees, errFeeNotCovered)
  1060  	}
  1061  
  1062  	id, err := settleFunc(updatedPromise)
  1063  	if err != nil {
  1064  		log.Error().Err(err).Msgf("Could not settle promise for %v", provider)
  1065  		return err
  1066  	}
  1067  
  1068  	channelID, err := crypto.GenerateProviderChannelID(provider.Address, hermesID.Hex())
  1069  	if err != nil {
  1070  		return fmt.Errorf("could not generate provider channel address: %w", err)
  1071  	}
  1072  
  1073  	errCh := aps.listenForSettlement(hermesID, beneficiary, updatedPromise, provider, aps.toBytes32(channelID), id, false)
  1074  	return <-errCh
  1075  }
  1076  
  1077  func (aps *hermesPromiseSettler) listenForSettlement(hermesID, beneficiary common.Address, promise crypto.Promise, provider identity.Identity, providerChannelID [32]byte, queueID string, isWithdrawal bool) <-chan error {
  1078  	errCh := make(chan error)
  1079  	go func() {
  1080  		defer close(errCh)
  1081  		t := time.After(aps.config.SettlementCheckTimeout)
  1082  		for {
  1083  			select {
  1084  			case <-aps.stop:
  1085  				return
  1086  			case <-t:
  1087  				return
  1088  			case <-time.After(aps.config.SettlementCheckInterval):
  1089  				res, err := aps.transactor.GetQueueStatus(queueID)
  1090  				if err != nil {
  1091  					log.Err(err).Str("queueID", queueID).Msg("could not get queue status")
  1092  					break
  1093  				}
  1094  				state := strings.ToLower(res.State)
  1095  
  1096  				// if queued, continue
  1097  				if state == "queue" {
  1098  					break
  1099  				}
  1100  
  1101  				// if error, don't wait as it will never complete
  1102  				if state == "error" {
  1103  					she := SettlementHistoryEntry{
  1104  						TxHash:           common.HexToHash(""),
  1105  						BlockExplorerURL: "",
  1106  						ProviderID:       provider,
  1107  						HermesID:         hermesID,
  1108  						// TODO: this should probably be either provider channel address or the consumer address from the promise, not truncated provider channel address.
  1109  						ChannelAddress: common.BytesToAddress(providerChannelID[:]),
  1110  						Time:           time.Now().UTC(),
  1111  						Promise:        promise,
  1112  						Beneficiary:    beneficiary,
  1113  						Error:          res.Error,
  1114  						IsWithdrawal:   isWithdrawal,
  1115  					}
  1116  					err = aps.settlementHistoryStorage.Store(she)
  1117  					if err != nil {
  1118  						log.Error().Err(err).Msg("Could not store settlement history")
  1119  					}
  1120  					errCh <- fmt.Errorf("transactor reported queue error for id %v: %v", queueID, res.Error)
  1121  					return
  1122  				}
  1123  
  1124  				// at this point, state should be done. If it is something else, abort.
  1125  				if state != "done" {
  1126  					errCh <- fmt.Errorf("transactor reported unknown settlement state for id %v, state %v", queueID, state)
  1127  					return
  1128  				}
  1129  
  1130  				filtered, err := aps.findSettlementInBCLogs(promise.ChainID, hermesID, providerChannelID, aps.toBytes32(common.Bytes2Hex(promise.R)))
  1131  				if err != nil {
  1132  					errCh <- fmt.Errorf("could not get settlement event from bc: %w", err)
  1133  					return
  1134  				}
  1135  
  1136  				if len(filtered) == 0 {
  1137  					log.Warn().Fields(map[string]interface{}{
  1138  						"hermesID": hermesID.Hex(),
  1139  						"provider": provider.Address,
  1140  						"queueID":  queueID,
  1141  					}).Err(err).Msg("no settlement found, will try again later")
  1142  					break
  1143  				}
  1144  
  1145  				ch, err := aps.channelProvider.Fetch(promise.ChainID, provider, hermesID)
  1146  				if err != nil {
  1147  					log.Error().Err(err).Msgf("Resync failed for provider %v", provider)
  1148  				} else {
  1149  					log.Info().Msgf("Resync success for provider %v", provider)
  1150  				}
  1151  
  1152  				for _, info := range filtered {
  1153  					uri, err := formTXUrl(info.Raw.TxHash.Hex(), promise.ChainID)
  1154  					if err != nil {
  1155  						log.Err(err).Msg("could not generate tx uri")
  1156  					}
  1157  
  1158  					she := SettlementHistoryEntry{
  1159  						TxHash:           info.Raw.TxHash,
  1160  						BlockExplorerURL: uri,
  1161  						ProviderID:       provider,
  1162  						HermesID:         hermesID,
  1163  						// TODO: this should probably be either provider channel address or the consumer address from the promise, not truncated provider channel address.
  1164  						ChannelAddress: common.BytesToAddress(providerChannelID[:]),
  1165  						Time:           time.Now().UTC(),
  1166  						Promise:        promise,
  1167  						Beneficiary:    beneficiary,
  1168  						Amount:         info.AmountSentToBeneficiary,
  1169  						Fees:           info.Fees,
  1170  						TotalSettled:   ch.Channel.Settled,
  1171  						Error:          aps.generateSettlementErrorMsg(promise.ChainID, info.Raw.TxHash),
  1172  						IsWithdrawal:   isWithdrawal,
  1173  					}
  1174  
  1175  					err = aps.settlementHistoryStorage.Store(she)
  1176  					if err != nil {
  1177  						log.Error().Err(err).Msg("Could not store settlement history")
  1178  					}
  1179  
  1180  					log.Debug().Str("tx_hash", info.Raw.TxHash.Hex()).Msg("saved a settlement")
  1181  				}
  1182  
  1183  				aps.publisher.Publish(event.AppTopicSettlementComplete, event.AppEventSettlementComplete{
  1184  					ProviderID: provider,
  1185  					HermesID:   hermesID,
  1186  					ChainID:    promise.ChainID,
  1187  				})
  1188  				log.Info().Msgf("Settling complete for provider %v", provider)
  1189  				return
  1190  			}
  1191  		}
  1192  	}()
  1193  	return errCh
  1194  }
  1195  
  1196  func (aps *hermesPromiseSettler) generateSettlementErrorMsg(chainID int64, hash common.Hash) string {
  1197  	receipt, err := aps.bc.TransactionReceipt(chainID, hash)
  1198  	if err != nil {
  1199  		log.Err(err).Msg("failed to get receipt for settlemnt")
  1200  		return "Could not get receipt"
  1201  	}
  1202  
  1203  	if receipt.Status == types.ReceiptStatusFailed {
  1204  		return "Transaction was reverted"
  1205  	}
  1206  
  1207  	return ""
  1208  }
  1209  
  1210  func (aps *hermesPromiseSettler) toBytes32(hexValue string) [32]byte {
  1211  	var arr [32]byte
  1212  	copy(arr[:], common.Hex2Bytes(strings.TrimPrefix(hexValue, "0x"))[:32])
  1213  	return arr
  1214  }
  1215  
  1216  func (aps *hermesPromiseSettler) findSettlementInBCLogs(chainID int64, hermesID common.Address, providerAddress, r [32]byte) ([]bindings.HermesImplementationPromiseSettled, error) {
  1217  	latest, err := aps.bc.HeaderByNumber(chainID, nil)
  1218  	if err != nil {
  1219  		return nil, err
  1220  	}
  1221  	blockNo := latest.Number.Uint64()
  1222  	from := aps.safeSub(blockNo, 800)
  1223  
  1224  	filtered, err := aps.bc.FilterPromiseSettledEventByChannelID(chainID, from, nil, hermesID, [][32]byte{providerAddress})
  1225  	if err != nil {
  1226  		return nil, err
  1227  	}
  1228  
  1229  	match := func(v bindings.HermesImplementationPromiseSettled) bool {
  1230  		if !bytes.EqualFold(v.ChannelId[:], providerAddress[:]) {
  1231  			return false
  1232  		}
  1233  		if !bytes.EqualFold(v.Lock[:], r[:]) {
  1234  			return false
  1235  		}
  1236  
  1237  		return true
  1238  	}
  1239  
  1240  	matched := make([]bindings.HermesImplementationPromiseSettled, 0)
  1241  	for _, v := range filtered {
  1242  		log.Info().Str("expected", hex.EncodeToString(providerAddress[:])).Str("got", hex.EncodeToString(v.ChannelId[:])).Msg("filtering")
  1243  
  1244  		if match(v) {
  1245  			matched = append(matched, v)
  1246  			log.Debug().Str("tx_hash", v.Raw.TxHash.Hex()).Msg("matched a settlement")
  1247  		}
  1248  	}
  1249  
  1250  	return matched, nil
  1251  }
  1252  
  1253  func (aps *hermesPromiseSettler) safeSub(a uint64, b uint64) uint64 {
  1254  	if b > a {
  1255  		return 0
  1256  	}
  1257  	return a - b
  1258  }
  1259  
  1260  func (aps *hermesPromiseSettler) isSettling(id identity.Identity, hermesID common.Address) bool {
  1261  	aps.lock.RLock()
  1262  	defer aps.lock.RUnlock()
  1263  	v, ok := aps.currentState[id]
  1264  	if !ok {
  1265  		return false
  1266  	}
  1267  
  1268  	if v.settleInProgress == nil {
  1269  		v.settleInProgress = make(map[common.Address]struct{})
  1270  		aps.currentState[id] = v
  1271  	}
  1272  
  1273  	_, ok = v.settleInProgress[hermesID]
  1274  
  1275  	return ok
  1276  }
  1277  
  1278  func (aps *hermesPromiseSettler) setSettling(id identity.Identity, hermesID common.Address, settling bool) {
  1279  	aps.lock.Lock()
  1280  	defer aps.lock.Unlock()
  1281  	v := aps.currentState[id]
  1282  
  1283  	if v.settleInProgress == nil {
  1284  		v.settleInProgress = make(map[common.Address]struct{})
  1285  	}
  1286  
  1287  	if settling {
  1288  		v.settleInProgress[hermesID] = struct{}{}
  1289  	} else {
  1290  		delete(v.settleInProgress, hermesID)
  1291  	}
  1292  
  1293  	aps.currentState[id] = v
  1294  }
  1295  
  1296  func (aps *hermesPromiseSettler) handleNodeStart() {
  1297  	go aps.listenForSettlementRequests()
  1298  
  1299  	for _, v := range aps.ks.Accounts() {
  1300  		addr := identity.FromAddress(v.Address.Hex())
  1301  		go func(address identity.Identity) {
  1302  			err := aps.loadInitialState(aps.chainID(), address)
  1303  			if err != nil {
  1304  				log.Error().Err(err).Msgf("could not load initial state for %v", addr)
  1305  			}
  1306  			err = aps.ForceSettleInactiveHermeses(aps.chainID(), addr)
  1307  			if err != nil {
  1308  				log.Error().Err(err).Msgf("could not settle inactive hermeses %v", addr)
  1309  			}
  1310  		}(addr)
  1311  	}
  1312  }
  1313  
  1314  func (aps *hermesPromiseSettler) getHermesCaller(chainID int64, hermesID common.Address) (HermesHTTPRequester, error) {
  1315  	addr, err := aps.hermesURLGetter.GetHermesURL(chainID, hermesID)
  1316  	if err != nil {
  1317  		return nil, fmt.Errorf("could not get hermes URL: %w", err)
  1318  	}
  1319  	return aps.hermesCallerFactory(addr), nil
  1320  }
  1321  
  1322  func (aps *hermesPromiseSettler) handleNodeStop() {
  1323  	aps.once.Do(func() {
  1324  		close(aps.stop)
  1325  	})
  1326  }
  1327  
  1328  // settlementState earning calculations model
  1329  type settlementState struct {
  1330  	registered bool
  1331  
  1332  	settleInProgress map[common.Address]struct{}
  1333  }
  1334  
  1335  func (aps *hermesPromiseSettler) needsSettling(ss settlementState, balanceThreshold float64, feeThreshold float64, minSettleAmount, maxUnSettledAmount float64, channel HermesChannel, chainID int64) (bool, *big.Int) {
  1336  	if !ss.registered {
  1337  		return false, nil
  1338  	}
  1339  
  1340  	if _, ok := ss.settleInProgress[channel.HermesID]; ok {
  1341  		return false, nil
  1342  	}
  1343  
  1344  	if channel.Channel.Stake.Cmp(big.NewInt(0)) == 0 {
  1345  		// no stake mode
  1346  		unsettledAmount := channel.UnsettledBalance()
  1347  		if unsettledAmount.Cmp(units.FloatEthToBigIntWei(maxUnSettledAmount)) > 0 {
  1348  			return true, nil
  1349  		}
  1350  		if unsettledAmount.Cmp(units.FloatEthToBigIntWei(minSettleAmount)) >= 0 {
  1351  			settleFees, err := aps.transactor.FetchSettleFees(chainID)
  1352  			if err != nil {
  1353  				log.Err(err).Msgf("will not use settlement fees to check if settling is needed")
  1354  				return false, nil
  1355  			}
  1356  			//set max fee to 10% more than current
  1357  			maxFee, _ := new(big.Float).Mul(new(big.Float).SetInt(settleFees.Fee), big.NewFloat(1.1)).Int(nil)
  1358  			unsettledBalance := new(big.Float).SetInt(channel.UnsettledBalance())
  1359  			calculatedFeesThreshold := new(big.Float).Mul(big.NewFloat(feeThreshold), unsettledBalance)
  1360  			calculatedFeesThresholdInt, _ := calculatedFeesThreshold.Int(nil)
  1361  			return settleFees.Fee.Cmp(calculatedFeesThresholdInt) < 0, maxFee
  1362  		}
  1363  		return false, nil
  1364  	}
  1365  
  1366  	floated := new(big.Float).SetInt(channel.availableBalance())
  1367  	calculatedThreshold := new(big.Float).Mul(big.NewFloat(balanceThreshold), floated)
  1368  	possibleEarnings := channel.UnsettledBalance()
  1369  	i, _ := calculatedThreshold.Int(nil)
  1370  	if possibleEarnings.Cmp(i) == -1 {
  1371  		return false, nil
  1372  	}
  1373  
  1374  	if channel.balance().Cmp(i) <= 0 {
  1375  		return true, nil
  1376  	}
  1377  
  1378  	return false, nil
  1379  }
  1380  
  1381  func (aps *hermesPromiseSettler) isBenenficiarySetToChannel(chainID int64, identity, beneficiary common.Address) (bool, error) {
  1382  	hermeses, err := aps.addressProvider.GetKnownHermeses(chainID)
  1383  	if err != nil {
  1384  		return false, fmt.Errorf("failed to get list of known hermeses: %w", err)
  1385  	}
  1386  	for _, h := range hermeses {
  1387  		channelAddr, err := aps.addressProvider.GetHermesChannelAddress(chainID, identity, h)
  1388  		if err != nil {
  1389  			return false, fmt.Errorf("failed to generate channel address: %w", err)
  1390  		}
  1391  		if channelAddr == beneficiary {
  1392  			return true, nil
  1393  		}
  1394  	}
  1395  	return false, nil
  1396  }
  1397  
  1398  func formTXUrl(txHash string, chainID int64) (string, error) {
  1399  	if len(txHash) == 0 {
  1400  		return "", nil
  1401  	}
  1402  
  1403  	if txHash == common.HexToHash("").Hex() {
  1404  		return "", nil
  1405  	}
  1406  
  1407  	switch chainID {
  1408  	case 1:
  1409  		return fmt.Sprintf("https://etherscan.io/tx/%v", txHash), nil
  1410  	case 5:
  1411  		return fmt.Sprintf("https://goerli.etherscan.io/tx/%v", txHash), nil
  1412  	case 80001:
  1413  		return fmt.Sprintf("https://mumbai.polygonscan.com/tx/%v", txHash), nil
  1414  	case 80002:
  1415  		return fmt.Sprintf("https://amoy.polygonscan.com/tx/%v", txHash), nil
  1416  	case 137:
  1417  		return fmt.Sprintf("https://polygonscan.com/tx/%v", txHash), nil
  1418  	default:
  1419  		return "", fmt.Errorf("unsupported chainID(%v) for tx url", chainID)
  1420  	}
  1421  }
  1422  
  1423  func (aps *hermesPromiseSettler) validateBeneficiary(chainID int64, identity, currentBeneficiary common.Address) (common.Address, bool, error) {
  1424  	localBeneficiaryAddress, err := aps.beneficiaryLocalStorage.Address(identity.Hex())
  1425  	if err != nil {
  1426  		if !errors.Is(err, beneficiary.ErrNotFound) {
  1427  			return common.Address{}, false, fmt.Errorf("could not get local beneficiary address: %w", err)
  1428  		}
  1429  		localBeneficiaryAddress = ""
  1430  	}
  1431  	beneficiary := currentBeneficiary
  1432  	changed := false
  1433  	if localBeneficiaryAddress != "" && !strings.EqualFold(localBeneficiaryAddress, currentBeneficiary.Hex()) {
  1434  		beneficiary = common.HexToAddress(localBeneficiaryAddress)
  1435  		changed = true
  1436  	}
  1437  	beneficiaryEqualToAddress, err := aps.isBenenficiarySetToChannel(aps.chainID(), identity, beneficiary)
  1438  	if err != nil {
  1439  		return common.Address{}, false, fmt.Errorf("could not verify beneficiary and channel equality: %w", err)
  1440  	}
  1441  	if beneficiaryEqualToAddress {
  1442  		return common.Address{}, false, fmt.Errorf("payment channel for identity %s is set as beneficiary, skip settling", identity.Hex())
  1443  	}
  1444  	return beneficiary, changed, nil
  1445  }