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 }