package services import ( "encoding/binary" "math/rand" "time" "ripple/commands" "ripple/config" "ripple/types" ) const feeInterval = 10 * config.FeeRate const failsafeInterval = 10 * time.Minute func (m *PaymentManager) RunPaymentFeeFailsafe() { for { time.Sleep(failsafeInterval) m.FeeFailsafeCh <- struct{}{} } } func (m *PaymentManager) RunCollectFees() { for { time.Sleep(feeInterval) m.ScheduleFeeCh <- struct{}{} } } func (m *PaymentManager) PaymentFeeFailsafe() { for paymentID, payment := range m.st.Storage.Payments { maxFee := payment.CalculateFee() if maxFee == 0 || payment.Incoming == (types.UserIdentifier{}) || payment.Outgoing == (types.UserIdentifier{}) { continue } userIDs := []types.UserIdentifier{payment.Incoming, payment.Outgoing} previewState := m.lockstep.PreviewAccounts(userIDs) previewPayment, ok := previewState.Storage.Payments[paymentID] if !ok || previewPayment.Cancelled() || previewPayment.Incoming == (types.UserIdentifier{}) || previewPayment.Outgoing == (types.UserIdentifier{}) || previewPayment.FeeIn == previewPayment.FeeOut { continue } var smallerFee, biggerFee uint64 var userID types.UserIdentifier if previewPayment.FeeIn < previewPayment.FeeOut { smallerFee, biggerFee = previewPayment.FeeIn, previewPayment.FeeOut userID = previewPayment.Incoming } else { smallerFee, biggerFee = previewPayment.FeeOut, previewPayment.FeeIn userID = previewPayment.Outgoing } if smallerFee >= maxFee { continue } var diff uint64 if biggerFee > maxFee { diff = maxFee - smallerFee } else { diff = biggerFee - smallerFee } buf := make([]byte, 40) copy(buf[:32], paymentID[:]) binary.BigEndian.PutUint64(buf[32:], diff) m.lockstep.Enqueue(userID, types.Instruction{ Command: commands.LOCKSTEP_PAYMENT_FEE, Arguments: buf, }) } } func (m *PaymentManager) CollectFees() { for pid, payment := range m.st.Storage.Payments { calculateFee := payment.CalculateFee() if calculateFee == 0 || payment.Cancelled() { continue } userIDs := []types.UserIdentifier{payment.Incoming} if payment.Outgoing != (types.UserIdentifier{}) { userIDs = append(userIDs, payment.Outgoing) } previewState := m.lockstep.PreviewAccounts(userIDs) previewPayment, ok := previewState.Storage.Payments[pid] if !ok || previewPayment.Cancelled() { continue } var feePaid uint64 if previewPayment.FeeOut >= previewPayment.FeeIn { feePaid = previewPayment.FeeOut } else { feePaid = previewPayment.FeeIn } if feePaid >= previewPayment.Amount { continue } maxFee := int64(calculateFee)-int64(feePaid) if maxFee <= 0 { continue } fee := 1 + (rand.Uint64() % uint64(maxFee)) argsBuf := make([]byte, 40) copy(argsBuf[:32], pid[:]) binary.BigEndian.PutUint64(argsBuf[32:], fee) if previewPayment.Incoming != (types.UserIdentifier{}) { m.lockstep.Enqueue(previewPayment.Incoming, types.Instruction{ Command: commands.LOCKSTEP_PAYMENT_FEE, Arguments: argsBuf, }) } if previewPayment.Outgoing != (types.UserIdentifier{}) { m.lockstep.Enqueue(previewPayment.Outgoing, types.Instruction{ Command: commands.LOCKSTEP_PAYMENT_FEE, Arguments: argsBuf, }) } } }