Integrate go-nitro node for payments #256
@ -17,6 +17,7 @@
|
|||||||
package payments
|
package payments
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -41,6 +42,14 @@ const (
|
|||||||
DEFAULT_LRU_CACHE_VOUCHER_TTL = 5 * 60 // 5mins
|
DEFAULT_LRU_CACHE_VOUCHER_TTL = 5 * 60 // 5mins
|
||||||
DEFAULT_LRU_CACHE_MAX_PAYMENT_CHANNELS = 10000
|
DEFAULT_LRU_CACHE_MAX_PAYMENT_CHANNELS = 10000
|
||||||
DEFAULT_LRU_CACHE_PAYMENT_CHANNEL_TTL = DEFAULT_LRU_CACHE_ACCOUNT_TTL
|
DEFAULT_LRU_CACHE_PAYMENT_CHANNEL_TTL = DEFAULT_LRU_CACHE_ACCOUNT_TTL
|
||||||
|
|
||||||
|
DEFAULT_VOUCHER_CHECK_INTERVAL = 2
|
||||||
|
DEFAULT_VOUCHER_CHECK_ATTEMPTS = 5
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ERR_PAYMENT_NOT_RECEIVED = errors.New("Payment not received")
|
||||||
|
ERR_AMOUNT_INSUFFICIENT = errors.New("Payment amount insufficient")
|
||||||
)
|
)
|
||||||
|
|
||||||
type Payment struct {
|
type Payment struct {
|
||||||
@ -48,11 +57,6 @@ type Payment struct {
|
|||||||
amount *big.Int
|
amount *big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
type paymentVoucher struct {
|
|
||||||
payer common.Address
|
|
||||||
voucherHash common.Hash
|
|
||||||
}
|
|
||||||
|
|
||||||
// Struct representing payments manager
|
// Struct representing payments manager
|
||||||
// Maintains either an in-process Nitro node or communication with an out-of-process Nitro node
|
// Maintains either an in-process Nitro node or communication with an out-of-process Nitro node
|
||||||
type PaymentsManager struct {
|
type PaymentsManager struct {
|
||||||
@ -66,14 +70,11 @@ type PaymentsManager struct {
|
|||||||
|
|
||||||
paidSoFarOnChannel *expirable.LRU[nitroTypes.Destination, *big.Int]
|
paidSoFarOnChannel *expirable.LRU[nitroTypes.Destination, *big.Int]
|
||||||
|
|
||||||
paymentListeners []chan paymentVoucher
|
|
||||||
|
|
||||||
// Used to signal shutdown of the service
|
// Used to signal shutdown of the service
|
||||||
quitChan chan bool
|
quitChan chan bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPaymentsManager(runInProcessNitroNode bool) (PaymentsManager, error) {
|
func NewPaymentsManager(runInProcessNitroNode bool) (PaymentsManager, error) {
|
||||||
// TODO: Implement
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
pm := PaymentsManager{runInProcessNitroNode: runInProcessNitroNode}
|
pm := PaymentsManager{runInProcessNitroNode: runInProcessNitroNode}
|
||||||
@ -130,6 +131,50 @@ func (pm *PaymentsManager) Stop() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pm *PaymentsManager) AuthenticatePayment(voucherHash common.Hash, signerAddress common.Address, value *big.Int) error {
|
||||||
|
// Check the payments map for required voucher
|
||||||
|
var isPaymentReceived, isOfSufficientValue bool
|
||||||
|
for i := 0; i < DEFAULT_VOUCHER_CHECK_ATTEMPTS; i++ {
|
||||||
|
isPaymentReceived, isOfSufficientValue = pm.acceptReceivedPayment(voucherHash, signerAddress, value)
|
||||||
|
|
||||||
|
if isPaymentReceived {
|
||||||
|
if !isOfSufficientValue {
|
||||||
|
return ERR_AMOUNT_INSUFFICIENT
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retry after an interval if voucher not found
|
||||||
|
log.Debugf("Payment from %s not found, retrying after %d sec...", signerAddress, DEFAULT_VOUCHER_CHECK_INTERVAL)
|
||||||
|
time.Sleep(DEFAULT_VOUCHER_CHECK_INTERVAL * time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_PAYMENT_NOT_RECEIVED
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for a given payment voucher in LRU cache map
|
||||||
|
// Returns whether the voucher was found, whether it was of sufficient value
|
||||||
|
func (pm *PaymentsManager) acceptReceivedPayment(voucherHash common.Hash, signerAddress common.Address, minRequiredValue *big.Int) (bool, bool) {
|
||||||
|
paymentsMap, ok := pm.receivedPayments.Get(signerAddress)
|
||||||
|
if !ok {
|
||||||
|
return false, false
|
||||||
|
}
|
||||||
|
|
||||||
|
receivedPayment, ok := paymentsMap.Get(voucherHash)
|
||||||
|
if !ok {
|
||||||
|
return false, false
|
||||||
|
}
|
||||||
|
|
||||||
|
if receivedPayment.amount.Cmp(minRequiredValue) < 0 {
|
||||||
|
return true, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the voucher from map after consuming it
|
||||||
|
paymentsMap.Remove(voucherHash)
|
||||||
|
return true, true
|
||||||
|
}
|
||||||
|
|
||||||
func (pm *PaymentsManager) run(receivedVouchers <-chan payments.Voucher) {
|
func (pm *PaymentsManager) run(receivedVouchers <-chan payments.Voucher) {
|
||||||
log.Info("starting voucher subscription...")
|
log.Info("starting voucher subscription...")
|
||||||
for {
|
for {
|
||||||
@ -168,10 +213,6 @@ func (pm *PaymentsManager) run(receivedVouchers <-chan payments.Voucher) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
paymentsMap.Add(voucherHash, Payment{voucher: voucher, amount: paymentAmount})
|
paymentsMap.Add(voucherHash, Payment{voucher: voucher, amount: paymentAmount})
|
||||||
|
|
||||||
for _, listener := range pm.paymentListeners {
|
|
||||||
listener <- paymentVoucher{payer: payer, voucherHash: voucherHash}
|
|
||||||
}
|
|
||||||
case <-pm.quitChan:
|
case <-pm.quitChan:
|
||||||
log.Info("stopping voucher subscription loop")
|
log.Info("stopping voucher subscription loop")
|
||||||
// TODO: stop the nitro node if that means anything
|
// TODO: stop the nitro node if that means anything
|
||||||
|
Loading…
Reference in New Issue
Block a user