Commit b22fda83 authored by acud's avatar acud Committed by GitHub

swap,sctx,debugapi: add optional gas limit and gas price to cashout (#1455)

parent b35ee5db
...@@ -19,7 +19,7 @@ var ( ...@@ -19,7 +19,7 @@ var (
errCantBalances = "Cannot get balances" errCantBalances = "Cannot get balances"
errCantBalance = "Cannot get balance" errCantBalance = "Cannot get balance"
errNoBalance = "No balance for peer" errNoBalance = "No balance for peer"
errInvaliAddress = "Invalid address" errInvalidAddress = "Invalid address"
) )
type balanceResponse struct { type balanceResponse struct {
...@@ -59,7 +59,7 @@ func (s *Service) peerBalanceHandler(w http.ResponseWriter, r *http.Request) { ...@@ -59,7 +59,7 @@ func (s *Service) peerBalanceHandler(w http.ResponseWriter, r *http.Request) {
if err != nil { if err != nil {
s.logger.Debugf("debug api: balances peer: invalid peer address %s: %v", addr, err) s.logger.Debugf("debug api: balances peer: invalid peer address %s: %v", addr, err)
s.logger.Errorf("debug api: balances peer: invalid peer address %s", addr) s.logger.Errorf("debug api: balances peer: invalid peer address %s", addr)
jsonhttp.NotFound(w, errInvaliAddress) jsonhttp.NotFound(w, errInvalidAddress)
return return
} }
...@@ -109,7 +109,7 @@ func (s *Service) compensatedPeerBalanceHandler(w http.ResponseWriter, r *http.R ...@@ -109,7 +109,7 @@ func (s *Service) compensatedPeerBalanceHandler(w http.ResponseWriter, r *http.R
if err != nil { if err != nil {
s.logger.Debugf("debug api: compensated balances peer: invalid peer address %s: %v", addr, err) s.logger.Debugf("debug api: compensated balances peer: invalid peer address %s: %v", addr, err)
s.logger.Errorf("debug api: compensated balances peer: invalid peer address %s", addr) s.logger.Errorf("debug api: compensated balances peer: invalid peer address %s", addr)
jsonhttp.NotFound(w, errInvaliAddress) jsonhttp.NotFound(w, errInvalidAddress)
return return
} }
......
...@@ -136,7 +136,7 @@ func TestBalancesInvalidAddress(t *testing.T) { ...@@ -136,7 +136,7 @@ func TestBalancesInvalidAddress(t *testing.T) {
jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/balances/"+peer, http.StatusNotFound, jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/balances/"+peer, http.StatusNotFound,
jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{ jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{
Message: debugapi.ErrInvaliAddress, Message: debugapi.ErrInvalidAddress,
Code: http.StatusNotFound, Code: http.StatusNotFound,
}), }),
) )
...@@ -289,7 +289,7 @@ func TestConsumedInvalidAddress(t *testing.T) { ...@@ -289,7 +289,7 @@ func TestConsumedInvalidAddress(t *testing.T) {
jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/consumed/"+peer, http.StatusNotFound, jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/consumed/"+peer, http.StatusNotFound,
jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{ jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{
Message: debugapi.ErrInvaliAddress, Message: debugapi.ErrInvalidAddress,
Code: http.StatusNotFound, Code: http.StatusNotFound,
}), }),
) )
......
...@@ -8,9 +8,11 @@ import ( ...@@ -8,9 +8,11 @@ import (
"errors" "errors"
"math/big" "math/big"
"net/http" "net/http"
"strconv"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethersphere/bee/pkg/jsonhttp" "github.com/ethersphere/bee/pkg/jsonhttp"
"github.com/ethersphere/bee/pkg/sctx"
"github.com/ethersphere/bee/pkg/settlement/swap/chequebook" "github.com/ethersphere/bee/pkg/settlement/swap/chequebook"
"github.com/ethersphere/bee/pkg/swarm" "github.com/ethersphere/bee/pkg/swarm"
...@@ -29,6 +31,11 @@ var ( ...@@ -29,6 +31,11 @@ var (
errCannotCashStatus = "cannot get cashout status" errCannotCashStatus = "cannot get cashout status"
errNoCashout = "no prior cashout" errNoCashout = "no prior cashout"
errNoCheque = "no prior cheque" errNoCheque = "no prior cheque"
errBadGasPrice = "bad gas price"
errBadGasLimit = "bad gas limit"
gasPriceHeader = "Gas-Price"
gasLimitHeader = "Gas-Limit"
) )
type chequebookBalanceResponse struct { type chequebookBalanceResponse struct {
...@@ -87,7 +94,7 @@ func (s *Service) chequebookLastPeerHandler(w http.ResponseWriter, r *http.Reque ...@@ -87,7 +94,7 @@ func (s *Service) chequebookLastPeerHandler(w http.ResponseWriter, r *http.Reque
if err != nil { if err != nil {
s.logger.Debugf("debug api: chequebook cheque peer: invalid peer address %s: %v", addr, err) s.logger.Debugf("debug api: chequebook cheque peer: invalid peer address %s: %v", addr, err)
s.logger.Errorf("debug api: chequebook cheque peer: invalid peer address %s", addr) s.logger.Errorf("debug api: chequebook cheque peer: invalid peer address %s", addr)
jsonhttp.NotFound(w, errInvaliAddress) jsonhttp.NotFound(w, errInvalidAddress)
return return
} }
...@@ -200,11 +207,33 @@ func (s *Service) swapCashoutHandler(w http.ResponseWriter, r *http.Request) { ...@@ -200,11 +207,33 @@ func (s *Service) swapCashoutHandler(w http.ResponseWriter, r *http.Request) {
if err != nil { if err != nil {
s.logger.Debugf("debug api: cashout peer: invalid peer address %s: %v", addr, err) s.logger.Debugf("debug api: cashout peer: invalid peer address %s: %v", addr, err)
s.logger.Errorf("debug api: cashout peer: invalid peer address %s", addr) s.logger.Errorf("debug api: cashout peer: invalid peer address %s", addr)
jsonhttp.NotFound(w, errInvaliAddress) jsonhttp.NotFound(w, errInvalidAddress)
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("debug api: cashout peer: bad gas price")
jsonhttp.BadRequest(w, errBadGasPrice)
return return
} }
ctx = sctx.SetGasPrice(ctx, p)
}
if limit, ok := r.Header[gasLimitHeader]; ok {
l, err := strconv.ParseUint(limit[0], 10, 64)
if err != nil {
s.logger.Debugf("debug api: cashout peer: bad gas limit: %v", err)
s.logger.Error("debug api: cashout peer: bad gas limit")
jsonhttp.BadRequest(w, errBadGasLimit)
return
}
ctx = sctx.SetGasLimit(ctx, l)
}
txHash, err := s.swap.CashCheque(r.Context(), peer) txHash, err := s.swap.CashCheque(ctx, peer)
if err != nil { if err != nil {
s.logger.Debugf("debug api: cashout peer: cannot cash %s: %v", addr, err) s.logger.Debugf("debug api: cashout peer: cannot cash %s: %v", addr, err)
s.logger.Errorf("debug api: cashout peer: cannot cash %s", addr) s.logger.Errorf("debug api: cashout peer: cannot cash %s", addr)
...@@ -236,7 +265,7 @@ func (s *Service) swapCashoutStatusHandler(w http.ResponseWriter, r *http.Reques ...@@ -236,7 +265,7 @@ func (s *Service) swapCashoutStatusHandler(w http.ResponseWriter, r *http.Reques
if err != nil { if err != nil {
s.logger.Debugf("debug api: cashout status peer: invalid peer address %s: %v", addr, err) s.logger.Debugf("debug api: cashout status peer: invalid peer address %s: %v", addr, err)
s.logger.Errorf("debug api: cashout status peer: invalid peer address %s", addr) s.logger.Errorf("debug api: cashout status peer: invalid peer address %s", addr)
jsonhttp.NotFound(w, errInvaliAddress) jsonhttp.NotFound(w, errInvalidAddress)
return return
} }
......
...@@ -16,6 +16,7 @@ import ( ...@@ -16,6 +16,7 @@ import (
"github.com/ethersphere/bee/pkg/debugapi" "github.com/ethersphere/bee/pkg/debugapi"
"github.com/ethersphere/bee/pkg/jsonhttp" "github.com/ethersphere/bee/pkg/jsonhttp"
"github.com/ethersphere/bee/pkg/jsonhttp/jsonhttptest" "github.com/ethersphere/bee/pkg/jsonhttp/jsonhttptest"
"github.com/ethersphere/bee/pkg/sctx"
"github.com/ethersphere/bee/pkg/settlement/swap/chequebook" "github.com/ethersphere/bee/pkg/settlement/swap/chequebook"
"github.com/ethersphere/bee/pkg/settlement/swap/chequebook/mock" "github.com/ethersphere/bee/pkg/settlement/swap/chequebook/mock"
swapmock "github.com/ethersphere/bee/pkg/settlement/swap/mock" swapmock "github.com/ethersphere/bee/pkg/settlement/swap/mock"
...@@ -433,6 +434,45 @@ func TestChequebookCashout(t *testing.T) { ...@@ -433,6 +434,45 @@ func TestChequebookCashout(t *testing.T) {
} }
} }
func TestChequebookCashout_CustomGas(t *testing.T) {
addr := swarm.MustParseHexAddress("1000000000000000000000000000000000000000000000000000000000000000")
deployCashingHash := common.HexToHash("0xffff")
var price *big.Int
var limit uint64
cashChequeFunc := func(ctx context.Context, peer swarm.Address) (common.Hash, error) {
price = sctx.GetGasPrice(ctx)
limit = sctx.GetGasLimit(ctx)
return deployCashingHash, nil
}
testServer := newTestServer(t, testServerOptions{
SwapOpts: []swapmock.Option{swapmock.WithCashChequeFunc(cashChequeFunc)},
})
expected := &debugapi.SwapCashoutResponse{TransactionHash: deployCashingHash.String()}
var got *debugapi.SwapCashoutResponse
jsonhttptest.Request(t, testServer.Client, http.MethodPost, "/chequebook/cashout/"+addr.String(), http.StatusOK,
jsonhttptest.WithRequestHeader("Gas-Price", "10000"),
jsonhttptest.WithRequestHeader("Gas-Limit", "12221"),
jsonhttptest.WithUnmarshalJSONResponse(&got),
)
if !reflect.DeepEqual(got, expected) {
t.Fatalf("Got: \n %+v \n\n Expected: \n %+v \n\n", got, expected)
}
if price.Cmp(big.NewInt(10000)) != 0 {
t.Fatalf("expected gas price 10000 got %s", price)
}
if limit != 12221 {
t.Fatalf("expected gas limit 12221 got %d", limit)
}
}
func TestChequebookCashoutStatus(t *testing.T) { func TestChequebookCashoutStatus(t *testing.T) {
actionTxHash := common.HexToHash("0xacfe") actionTxHash := common.HexToHash("0xacfe")
......
...@@ -35,5 +35,5 @@ var ( ...@@ -35,5 +35,5 @@ var (
ErrCantSettlementsPeer = errCantSettlementsPeer ErrCantSettlementsPeer = errCantSettlementsPeer
ErrCantSettlements = errCantSettlements ErrCantSettlements = errCantSettlements
ErrChequebookBalance = errChequebookBalance ErrChequebookBalance = errChequebookBalance
ErrInvaliAddress = errInvaliAddress ErrInvalidAddress = errInvalidAddress
) )
...@@ -94,7 +94,7 @@ func (s *Service) peerSettlementsHandler(w http.ResponseWriter, r *http.Request) ...@@ -94,7 +94,7 @@ func (s *Service) peerSettlementsHandler(w http.ResponseWriter, r *http.Request)
if err != nil { if err != nil {
s.logger.Debugf("debug api: settlements peer: invalid peer address %s: %v", addr, err) s.logger.Debugf("debug api: settlements peer: invalid peer address %s: %v", addr, err)
s.logger.Errorf("debug api: settlements peer: invalid peer address %s", addr) s.logger.Errorf("debug api: settlements peer: invalid peer address %s", addr)
jsonhttp.NotFound(w, errInvaliAddress) jsonhttp.NotFound(w, errInvalidAddress)
return return
} }
......
...@@ -182,7 +182,7 @@ func TestSettlementsInvalidAddress(t *testing.T) { ...@@ -182,7 +182,7 @@ func TestSettlementsInvalidAddress(t *testing.T) {
jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/settlements/"+peer, http.StatusNotFound, jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/settlements/"+peer, http.StatusNotFound,
jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{ jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{
Message: debugapi.ErrInvaliAddress, Message: debugapi.ErrInvalidAddress,
Code: http.StatusNotFound, Code: http.StatusNotFound,
}), }),
) )
......
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
"context" "context"
"encoding/hex" "encoding/hex"
"errors" "errors"
"math/big"
"strings" "strings"
"github.com/ethersphere/bee/pkg/pss" "github.com/ethersphere/bee/pkg/pss"
...@@ -26,6 +27,8 @@ type ( ...@@ -26,6 +27,8 @@ type (
requestHostKey struct{} requestHostKey struct{}
tagKey struct{} tagKey struct{}
targetsContextKey struct{} targetsContextKey struct{}
gasPriceKey struct{}
gasLimitKey struct{}
) )
// SetHost sets the http request host in the context // SetHost sets the http request host in the context
...@@ -84,3 +87,28 @@ func GetTargets(ctx context.Context) pss.Targets { ...@@ -84,3 +87,28 @@ func GetTargets(ctx context.Context) pss.Targets {
} }
return targets return targets
} }
func SetGasLimit(ctx context.Context, limit uint64) context.Context {
return context.WithValue(ctx, gasLimitKey{}, limit)
}
func GetGasLimit(ctx context.Context) uint64 {
v, ok := ctx.Value(gasLimitKey{}).(uint64)
if ok {
return v
}
return 0
}
func SetGasPrice(ctx context.Context, price *big.Int) context.Context {
return context.WithValue(ctx, gasPriceKey{}, price)
}
func GetGasPrice(ctx context.Context) *big.Int {
v, ok := ctx.Value(gasPriceKey{}).(*big.Int)
if ok {
return v
}
return nil
}
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethersphere/bee/pkg/sctx"
"github.com/ethersphere/bee/pkg/settlement/swap/transaction" "github.com/ethersphere/bee/pkg/settlement/swap/transaction"
"github.com/ethersphere/bee/pkg/storage" "github.com/ethersphere/bee/pkg/storage"
) )
...@@ -100,12 +101,16 @@ func (s *cashoutService) CashCheque(ctx context.Context, chequebook, recipient c ...@@ -100,12 +101,16 @@ func (s *cashoutService) CashCheque(ctx context.Context, chequebook, recipient c
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
lim := sctx.GetGasLimit(ctx)
if lim == 0 {
// fix for out of gas errors
lim = 300000
}
request := &transaction.TxRequest{ request := &transaction.TxRequest{
To: &chequebook, To: &chequebook,
Data: callData, Data: callData,
GasPrice: nil, GasPrice: sctx.GetGasPrice(ctx),
GasLimit: 0, GasLimit: lim,
Value: big.NewInt(0), Value: big.NewInt(0),
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment