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
......@@ -16,10 +16,10 @@ import (
)
var (
errCantBalances = "Cannot get balances"
errCantBalance = "Cannot get balance"
errNoBalance = "No balance for peer"
errInvaliAddress = "Invalid address"
errCantBalances = "Cannot get balances"
errCantBalance = "Cannot get balance"
errNoBalance = "No balance for peer"
errInvalidAddress = "Invalid address"
)
type balanceResponse struct {
......@@ -59,7 +59,7 @@ func (s *Service) peerBalanceHandler(w http.ResponseWriter, r *http.Request) {
if err != nil {
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)
jsonhttp.NotFound(w, errInvaliAddress)
jsonhttp.NotFound(w, errInvalidAddress)
return
}
......@@ -109,7 +109,7 @@ func (s *Service) compensatedPeerBalanceHandler(w http.ResponseWriter, r *http.R
if err != nil {
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)
jsonhttp.NotFound(w, errInvaliAddress)
jsonhttp.NotFound(w, errInvalidAddress)
return
}
......
......@@ -136,7 +136,7 @@ func TestBalancesInvalidAddress(t *testing.T) {
jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/balances/"+peer, http.StatusNotFound,
jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{
Message: debugapi.ErrInvaliAddress,
Message: debugapi.ErrInvalidAddress,
Code: http.StatusNotFound,
}),
)
......@@ -289,7 +289,7 @@ func TestConsumedInvalidAddress(t *testing.T) {
jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/consumed/"+peer, http.StatusNotFound,
jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{
Message: debugapi.ErrInvaliAddress,
Message: debugapi.ErrInvalidAddress,
Code: http.StatusNotFound,
}),
)
......
......@@ -8,9 +8,11 @@ import (
"errors"
"math/big"
"net/http"
"strconv"
"github.com/ethereum/go-ethereum/common"
"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/swarm"
......@@ -29,6 +31,11 @@ var (
errCannotCashStatus = "cannot get cashout status"
errNoCashout = "no prior cashout"
errNoCheque = "no prior cheque"
errBadGasPrice = "bad gas price"
errBadGasLimit = "bad gas limit"
gasPriceHeader = "Gas-Price"
gasLimitHeader = "Gas-Limit"
)
type chequebookBalanceResponse struct {
......@@ -87,7 +94,7 @@ func (s *Service) chequebookLastPeerHandler(w http.ResponseWriter, r *http.Reque
if err != nil {
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)
jsonhttp.NotFound(w, errInvaliAddress)
jsonhttp.NotFound(w, errInvalidAddress)
return
}
......@@ -200,11 +207,33 @@ func (s *Service) swapCashoutHandler(w http.ResponseWriter, r *http.Request) {
if err != nil {
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)
jsonhttp.NotFound(w, errInvaliAddress)
jsonhttp.NotFound(w, errInvalidAddress)
return
}
txHash, err := s.swap.CashCheque(r.Context(), peer)
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
}
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(ctx, peer)
if err != nil {
s.logger.Debugf("debug api: cashout peer: cannot cash %s: %v", addr, err)
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
if err != nil {
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)
jsonhttp.NotFound(w, errInvaliAddress)
jsonhttp.NotFound(w, errInvalidAddress)
return
}
......
......@@ -16,6 +16,7 @@ import (
"github.com/ethersphere/bee/pkg/debugapi"
"github.com/ethersphere/bee/pkg/jsonhttp"
"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/mock"
swapmock "github.com/ethersphere/bee/pkg/settlement/swap/mock"
......@@ -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) {
actionTxHash := common.HexToHash("0xacfe")
......
......@@ -35,5 +35,5 @@ var (
ErrCantSettlementsPeer = errCantSettlementsPeer
ErrCantSettlements = errCantSettlements
ErrChequebookBalance = errChequebookBalance
ErrInvaliAddress = errInvaliAddress
ErrInvalidAddress = errInvalidAddress
)
......@@ -94,7 +94,7 @@ func (s *Service) peerSettlementsHandler(w http.ResponseWriter, r *http.Request)
if err != nil {
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)
jsonhttp.NotFound(w, errInvaliAddress)
jsonhttp.NotFound(w, errInvalidAddress)
return
}
......
......@@ -182,7 +182,7 @@ func TestSettlementsInvalidAddress(t *testing.T) {
jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/settlements/"+peer, http.StatusNotFound,
jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{
Message: debugapi.ErrInvaliAddress,
Message: debugapi.ErrInvalidAddress,
Code: http.StatusNotFound,
}),
)
......
......@@ -10,6 +10,7 @@ import (
"context"
"encoding/hex"
"errors"
"math/big"
"strings"
"github.com/ethersphere/bee/pkg/pss"
......@@ -26,6 +27,8 @@ type (
requestHostKey struct{}
tagKey struct{}
targetsContextKey struct{}
gasPriceKey struct{}
gasLimitKey struct{}
)
// SetHost sets the http request host in the context
......@@ -84,3 +87,28 @@ func GetTargets(ctx context.Context) pss.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 (
"github.com/ethereum/go-ethereum/common"
"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/storage"
)
......@@ -100,12 +101,16 @@ func (s *cashoutService) CashCheque(ctx context.Context, chequebook, recipient c
if err != nil {
return common.Hash{}, err
}
lim := sctx.GetGasLimit(ctx)
if lim == 0 {
// fix for out of gas errors
lim = 300000
}
request := &transaction.TxRequest{
To: &chequebook,
Data: callData,
GasPrice: nil,
GasLimit: 0,
GasPrice: sctx.GetGasPrice(ctx),
GasLimit: lim,
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