Skip to content

Commit

Permalink
feat(debugapi, postage): dilute batch handling (#2410)
Browse files Browse the repository at this point in the history
  • Loading branch information
aloknerurkar authored Aug 23, 2021
1 parent da0cb07 commit 9ee3107
Show file tree
Hide file tree
Showing 16 changed files with 682 additions and 46 deletions.
35 changes: 35 additions & 0 deletions openapi/SwarmDebug.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -908,3 +908,38 @@ paths:
$ref: "SwarmCommon.yaml#/components/responses/500"
default:
description: Default response

"/stamps/dilute/{id}/{depth}":
patch:
summary: Dilute an existing postage batch.
description: Be aware, this endpoint creates on-chain transactions and transfers BZZ from the node's Ethereum account and hence directly manipulates the wallet balance!
tags:
- Postage Stamps
parameters:
- in: path
name: id
schema:
$ref: "SwarmCommon.yaml#/components/schemas/BatchID"
required: true
description: Batch ID to dilute
- in: path
name: depth
schema:
type: integer
required: true
description: New batch depth. Must be higher than the previous depth.
responses:
"202":
description: Returns the postage batch ID that was diluted.
content:
application/json:
schema:
$ref: "SwarmCommon.yaml#/components/schemas/BatchIDResponse"
"400":
$ref: "SwarmCommon.yaml#/components/responses/400"
"429":
$ref: "SwarmCommon.yaml#/components/responses/429"
"500":
$ref: "SwarmCommon.yaml#/components/responses/500"
default:
description: Default response
4 changes: 2 additions & 2 deletions pkg/debugapi/debugapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ type Service struct {

// The following are semaphores which exists to limit concurrent access
// to some parts of the resources in order to avoid undefined behaviour.
postageCreateSem *semaphore.Weighted
postageSem *semaphore.Weighted
cashOutChequeSem *semaphore.Weighted
}

Expand All @@ -88,7 +88,7 @@ func New(publicKey, pssPublicKey ecdsa.PublicKey, ethereumAddress common.Address
s.blockTime = blockTime
s.metricsRegistry = newMetricsRegistry()
s.transaction = transaction
s.postageCreateSem = semaphore.NewWeighted(1)
s.postageSem = semaphore.NewWeighted(1)
s.cashOutChequeSem = semaphore.NewWeighted(1)

s.setRouter(s.newBasicRouter())
Expand Down
86 changes: 69 additions & 17 deletions pkg/debugapi/postage.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,20 @@ import (
"github.com/gorilla/mux"
)

func (s *Service) postageAccessHandler(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !s.postageSem.TryAcquire(1) {
s.logger.Debug("postage access: simultaneous on-chain operations not supported")
s.logger.Error("postage access: simultaneous on-chain operations not supported")
jsonhttp.TooManyRequests(w, "simultaneous on-chain operations not supported")
return
}
defer s.postageSem.Release(1)

h.ServeHTTP(w, r)
})
}

type batchID []byte

func (b batchID) MarshalJSON() ([]byte, error) {
Expand Down Expand Up @@ -68,14 +82,6 @@ func (s *Service) postageCreateHandler(w http.ResponseWriter, r *http.Request) {
immutable, _ = strconv.ParseBool(val[0])
}

if !s.postageCreateSem.TryAcquire(1) {
s.logger.Debug("create batch: simultaneous on-chain operations not supported")
s.logger.Error("create batch: simultaneous on-chain operations not supported")
jsonhttp.TooManyRequests(w, "simultaneous on-chain operations not supported")
return
}
defer s.postageCreateSem.Release(1)

batchID, err := s.postageContract.CreateBatch(ctx, amount, uint8(depth), immutable, label)
if err != nil {
if errors.Is(err, postagecontract.ErrInsufficientFunds) {
Expand Down Expand Up @@ -324,7 +330,7 @@ func (s *Service) estimateBatchTTL(id []byte) (int64, error) {

func (s *Service) postageTopUpHandler(w http.ResponseWriter, r *http.Request) {
idStr := mux.Vars(r)["id"]
if idStr == "" || len(idStr) != 64 {
if len(idStr) != 64 {
s.logger.Error("topup batch: invalid batchID")
jsonhttp.BadRequest(w, "invalid batchID")
return
Expand Down Expand Up @@ -355,14 +361,6 @@ func (s *Service) postageTopUpHandler(w http.ResponseWriter, r *http.Request) {
ctx = sctx.SetGasPrice(ctx, p)
}

if !s.postageCreateSem.TryAcquire(1) {
s.logger.Debug("topup batch: simultaneous on-chain operations not supported")
s.logger.Error("topup batch: simultaneous on-chain operations not supported")
jsonhttp.TooManyRequests(w, "simultaneous on-chain operations not supported")
return
}
defer s.postageCreateSem.Release(1)

err = s.postageContract.TopUpBatch(ctx, id, amount)
if err != nil {
if errors.Is(err, postagecontract.ErrInsufficientFunds) {
Expand All @@ -381,3 +379,57 @@ func (s *Service) postageTopUpHandler(w http.ResponseWriter, r *http.Request) {
BatchID: id,
})
}

func (s *Service) postageDiluteHandler(w http.ResponseWriter, r *http.Request) {
idStr := mux.Vars(r)["id"]
if len(idStr) != 64 {
s.logger.Error("dilute batch: invalid batchID")
jsonhttp.BadRequest(w, "invalid batchID")
return
}
id, err := hex.DecodeString(idStr)
if err != nil {
s.logger.Debugf("dilute batch: invalid batchID: %v", err)
s.logger.Error("dilute batch: invalid batchID")
jsonhttp.BadRequest(w, "invalid batchID")
return
}

depthStr := mux.Vars(r)["depth"]
depth, err := strconv.ParseUint(depthStr, 10, 8)
if err != nil {
s.logger.Debugf("dilute batch: invalid depth: %v", err)
s.logger.Error("dilute batch: invalid depth")
jsonhttp.BadRequest(w, "invalid depth")
return
}

ctx := r.Context()
if price, ok := r.Header[gasPriceHeader]; ok {
p, ok := big.NewInt(0).SetString(price[0], 10)
if !ok {
s.logger.Error("dilute batch: bad gas price")
jsonhttp.BadRequest(w, errBadGasPrice)
return
}
ctx = sctx.SetGasPrice(ctx, p)
}

err = s.postageContract.DiluteBatch(ctx, id, uint8(depth))
if err != nil {
if errors.Is(err, postagecontract.ErrInvalidDepth) {
s.logger.Debugf("dilute batch: invalid depth: %v", err)
s.logger.Error("dilte batch: invalid depth")
jsonhttp.BadRequest(w, "invalid depth")
return
}
s.logger.Debugf("dilute batch: failed to dilute: %v", err)
s.logger.Error("dilute batch: failed to dilute")
jsonhttp.InternalServerError(w, "cannot dilute batch")
return
}

jsonhttp.Accepted(w, &postageCreateResponse{
BatchID: id,
})
}
Loading

0 comments on commit 9ee3107

Please sign in to comment.