diff --git a/api/clients/v2/accountant.go b/api/clients/v2/accountant.go index 6b923d51b..f5e1c920f 100644 --- a/api/clients/v2/accountant.go +++ b/api/clients/v2/accountant.go @@ -154,56 +154,72 @@ func (a *Accountant) GetRelativeBinRecord(index uint32) *BinRecord { return &a.binRecords[relativeIndex] } +// SetPaymentState sets the accountant's state from the disperser's response +// We require disperser to return a valid set of global parameters, but optional +// account level on/off-chain state. If on-chain fields are not present, we use +// dummy values that disable accountant from using the corresponding payment method. +// If off-chain fields are not present, we assume the account has no payment history +// and set accoutant state to use initial values. func (a *Accountant) SetPaymentState(paymentState *disperser_rpc.GetPaymentStateReply) error { if paymentState == nil { return fmt.Errorf("payment state cannot be nil") } else if paymentState.GetPaymentGlobalParams() == nil { return fmt.Errorf("payment global params cannot be nil") - } else if paymentState.GetOnchainCumulativePayment() == nil { - return fmt.Errorf("onchain cumulative payment cannot be nil") - } else if paymentState.GetCumulativePayment() == nil { - return fmt.Errorf("cumulative payment cannot be nil") - } else if paymentState.GetReservation() == nil { - return fmt.Errorf("reservation cannot be nil") - } else if paymentState.GetReservation().GetQuorumNumbers() == nil { - return fmt.Errorf("reservation quorum numbers cannot be nil") - } else if paymentState.GetReservation().GetQuorumSplits() == nil { - return fmt.Errorf("reservation quorum split cannot be nil") - } else if paymentState.GetBinRecords() == nil { - return fmt.Errorf("bin records cannot be nil") - } - - a.minNumSymbols = uint32(paymentState.PaymentGlobalParams.MinNumSymbols) - a.onDemand.CumulativePayment = new(big.Int).SetBytes(paymentState.OnchainCumulativePayment) - a.cumulativePayment = new(big.Int).SetBytes(paymentState.CumulativePayment) - a.pricePerSymbol = uint32(paymentState.PaymentGlobalParams.PricePerSymbol) - - a.reservation.SymbolsPerSecond = uint64(paymentState.PaymentGlobalParams.GlobalSymbolsPerSecond) - a.reservation.StartTimestamp = uint64(paymentState.Reservation.StartTimestamp) - a.reservation.EndTimestamp = uint64(paymentState.Reservation.EndTimestamp) - a.reservationWindow = uint32(paymentState.PaymentGlobalParams.ReservationWindow) - - quorumNumbers := make([]uint8, len(paymentState.Reservation.QuorumNumbers)) - for i, quorum := range paymentState.Reservation.QuorumNumbers { - quorumNumbers[i] = uint8(quorum) - } - a.reservation.QuorumNumbers = quorumNumbers - - quorumSplits := make([]uint8, len(paymentState.Reservation.QuorumSplits)) - for i, quorum := range paymentState.Reservation.QuorumSplits { - quorumSplits[i] = uint8(quorum) - } - a.reservation.QuorumSplits = quorumSplits - - binRecords := make([]BinRecord, len(paymentState.BinRecords)) - for i, record := range paymentState.BinRecords { - binRecords[i] = BinRecord{ - Index: record.Index, - Usage: record.Usage, + } + + a.minNumSymbols = uint32(paymentState.GetPaymentGlobalParams().GetMinNumSymbols()) + a.pricePerSymbol = uint32(paymentState.GetPaymentGlobalParams().GetPricePerSymbol()) + a.reservationWindow = uint32(paymentState.GetPaymentGlobalParams().GetReservationWindow()) + + if paymentState.GetOnchainCumulativePayment() == nil { + a.onDemand.CumulativePayment = big.NewInt(0) + } else { + a.onDemand.CumulativePayment = new(big.Int).SetBytes(paymentState.GetOnchainCumulativePayment()) + } + + if paymentState.GetCumulativePayment() == nil { + a.cumulativePayment = big.NewInt(0) + } else { + a.cumulativePayment = new(big.Int).SetBytes(paymentState.GetCumulativePayment()) + } + + if paymentState.GetReservation() == nil { + a.reservation = &core.ReservedPayment{ + SymbolsPerSecond: 0, + StartTimestamp: 0, + EndTimestamp: 0, + QuorumNumbers: []uint8{}, + QuorumSplits: []byte{}, } + } else { + a.reservation.SymbolsPerSecond = uint64(paymentState.GetReservation().GetSymbolsPerSecond()) + a.reservation.StartTimestamp = uint64(paymentState.GetReservation().GetStartTimestamp()) + a.reservation.EndTimestamp = uint64(paymentState.GetReservation().GetEndTimestamp()) + quorumNumbers := make([]uint8, len(paymentState.GetReservation().GetQuorumNumbers())) + for i, quorum := range paymentState.GetReservation().GetQuorumNumbers() { + quorumNumbers[i] = uint8(quorum) + } + a.reservation.QuorumNumbers = quorumNumbers + + quorumSplits := make([]uint8, len(paymentState.GetReservation().GetQuorumSplits())) + for i, quorum := range paymentState.GetReservation().GetQuorumSplits() { + quorumSplits[i] = uint8(quorum) + } + a.reservation.QuorumSplits = quorumSplits } - a.binRecords = binRecords + binRecords := make([]BinRecord, len(paymentState.GetBinRecords())) + for i, record := range paymentState.GetBinRecords() { + if record == nil { + binRecords[i] = BinRecord{Index: 0, Usage: 0} + } else { + binRecords[i] = BinRecord{ + Index: record.Index, + Usage: record.Usage, + } + } + } + a.binRecords = binRecords return nil } diff --git a/core/meterer/offchain_store.go b/core/meterer/offchain_store.go index 6b213a495..5899ca75e 100644 --- a/core/meterer/offchain_store.go +++ b/core/meterer/offchain_store.go @@ -295,7 +295,7 @@ func (s *OffchainStore) GetLargestCumulativePayment(ctx context.Context, account } if len(payments) == 0 { - return nil, nil + return big.NewInt(0), nil } var payment *big.Int diff --git a/disperser/apiserver/server_v2.go b/disperser/apiserver/server_v2.go index bd45248f1..525954716 100644 --- a/disperser/apiserver/server_v2.go +++ b/disperser/apiserver/server_v2.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "math/big" "net" "sync/atomic" "time" @@ -254,20 +255,42 @@ func (s *DispersalServerV2) GetPaymentState(ctx context.Context, req *pb.GetPaym currentReservationPeriod := meterer.GetReservationPeriod(now, reservationWindow) binRecords, err := s.meterer.OffchainStore.GetBinRecords(ctx, req.AccountId, currentReservationPeriod) if err != nil { - return nil, api.NewErrorNotFound("failed to get active reservation") + s.logger.Debug("failed to get reservation records, use placeholders", "err", err, "accountID", accountID) } largestCumulativePayment, err := s.meterer.OffchainStore.GetLargestCumulativePayment(ctx, req.AccountId) if err != nil { - return nil, api.NewErrorNotFound("failed to get largest cumulative payment") + s.logger.Debug("failed to get largest cumulative payment, use zero value", "err", err, "accountID", accountID) } // on-Chain account state + var pbReservation *pb.Reservation reservation, err := s.meterer.ChainPaymentState.GetReservedPaymentByAccount(ctx, accountID) if err != nil { - return nil, api.NewErrorNotFound("failed to get active reservation") + s.logger.Debug("failed to get onchain reservation, use zero values", "err", err, "accountID", accountID) + } else { + quorumNumbers := make([]uint32, len(reservation.QuorumNumbers)) + for i, v := range reservation.QuorumNumbers { + quorumNumbers[i] = uint32(v) + } + quorumSplits := make([]uint32, len(reservation.QuorumSplits)) + for i, v := range reservation.QuorumSplits { + quorumSplits[i] = uint32(v) + } + + pbReservation = &pb.Reservation{ + SymbolsPerSecond: reservation.SymbolsPerSecond, + StartTimestamp: uint32(reservation.StartTimestamp), + EndTimestamp: uint32(reservation.EndTimestamp), + QuorumSplits: quorumSplits, + QuorumNumbers: quorumNumbers, + } } + + var onchainCumulativePayment *big.Int onDemandPayment, err := s.meterer.ChainPaymentState.GetOnDemandPaymentByAccount(ctx, accountID) if err != nil { - return nil, api.NewErrorNotFound("failed to get on-demand payment") + s.logger.Debug("failed to get ondemand payment, use zero value", "err", err, "accountID", accountID) + } else { + onchainCumulativePayment = onDemandPayment.CumulativePayment } paymentGlobalParams := pb.PaymentGlobalParams{ @@ -277,27 +300,13 @@ func (s *DispersalServerV2) GetPaymentState(ctx context.Context, req *pb.GetPaym ReservationWindow: reservationWindow, } - quorumNumbers := make([]uint32, len(reservation.QuorumNumbers)) - for i, v := range reservation.QuorumNumbers { - quorumNumbers[i] = uint32(v) - } - quorumSplits := make([]uint32, len(reservation.QuorumSplits)) - for i, v := range reservation.QuorumSplits { - quorumSplits[i] = uint32(v) - } // build reply reply := &pb.GetPaymentStateReply{ - PaymentGlobalParams: &paymentGlobalParams, - BinRecords: binRecords[:], - Reservation: &pb.Reservation{ - SymbolsPerSecond: reservation.SymbolsPerSecond, - StartTimestamp: uint32(reservation.StartTimestamp), - EndTimestamp: uint32(reservation.EndTimestamp), - QuorumSplits: quorumSplits, - QuorumNumbers: quorumNumbers, - }, + PaymentGlobalParams: &paymentGlobalParams, + BinRecords: binRecords[:], + Reservation: pbReservation, CumulativePayment: largestCumulativePayment.Bytes(), - OnchainCumulativePayment: onDemandPayment.CumulativePayment.Bytes(), + OnchainCumulativePayment: onchainCumulativePayment.Bytes(), } return reply, nil }