Skip to content

Commit

Permalink
update: refactor sending legacy transactions, combine gas costs in on…
Browse files Browse the repository at this point in the history
…e function
  • Loading branch information
mhrynenko committed May 9, 2024
1 parent 9c94f65 commit ed5da51
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 137 deletions.
74 changes: 2 additions & 72 deletions internal/service/api/handlers/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,10 @@ package handlers
import (
"encoding/json"
"net/http"
"strings"

"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/rarimo/proof-verification-relayer/internal/contracts"
"github.com/rarimo/proof-verification-relayer/internal/service/api/requests"
"gitlab.com/distributed_lab/ape"
Expand Down Expand Up @@ -77,82 +73,16 @@ func Register(w http.ResponseWriter, r *http.Request) {
return
}

gasPrice, err := EthClient(r).SuggestGasPrice(r.Context())
if err != nil {
Log(r).WithError(err).Error("failed to suggest gas price")
ape.RenderErr(w, problems.InternalError())
return
}

NetworkConfig(r).LockNonce()
defer NetworkConfig(r).UnlockNonce()

gas, err := EthClient(r).EstimateGas(r.Context(), ethereum.CallMsg{
From: crypto.PubkeyToAddress(NetworkConfig(r).PrivateKey.PublicKey),
To: &registration,
GasPrice: gasPrice,
Data: dataBytes,
})
if err != nil {
Log(r).WithError(err).Error("failed to estimate gas")
ape.RenderErr(w, problems.InternalError())
return
}

tx, err := types.SignNewTx(
NetworkConfig(r).PrivateKey,
types.NewCancunSigner(NetworkConfig(r).ChainID),
&types.LegacyTx{
Nonce: NetworkConfig(r).Nonce(),
Gas: uint64(float64(gas) * NetworkConfig(r).GasMultiplier),
GasPrice: multiplyGasPrice(gasPrice, NetworkConfig(r).GasMultiplier),
To: &registration,
Data: dataBytes,
},
)
tx, err := processLegacyTx(r, registration, dataBytes)
if err != nil {
Log(r).WithError(err).Error("failed to sign new tx")
Log(r).WithError(err).Error("failed to process legacy transaction")
ape.RenderErr(w, problems.InternalError())
return
}

if err := EthClient(r).SendTransaction(r.Context(), tx); err != nil {
if strings.Contains(err.Error(), "nonce") {
if err := NetworkConfig(r).ResetNonce(EthClient(r)); err != nil {
Log(r).WithError(err).Error("failed to reset nonce")
ape.RenderErr(w, problems.InternalError())
return
}

tx, err = types.SignNewTx(
NetworkConfig(r).PrivateKey,
types.NewCancunSigner(NetworkConfig(r).ChainID),
&types.LegacyTx{
Nonce: NetworkConfig(r).Nonce(),
Gas: gas,
GasPrice: gasPrice,
To: &registration,
Data: dataBytes,
},
)
if err != nil {
Log(r).WithError(err).Error("failed to sign new tx")
ape.RenderErr(w, problems.InternalError())
return
}

if err := EthClient(r).SendTransaction(r.Context(), tx); err != nil {
Log(r).WithError(err).Error("failed to send transaction")
ape.RenderErr(w, problems.InternalError())
return
}
} else {
Log(r).WithError(err).Error("failed to send transaction")
ape.RenderErr(w, problems.InternalError())
return
}
}

NetworkConfig(r).IncrementNonce()

ape.Render(w, newTxModel(tx))
Expand Down
20 changes: 4 additions & 16 deletions internal/service/api/handlers/transit_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@ import (
"math/big"
"net/http"

"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
validation "github.com/go-ozzo/ozzo-validation/v4"
"github.com/rarimo/proof-verification-relayer/internal/contracts"
"github.com/rarimo/proof-verification-relayer/internal/service/api/requests"
Expand Down Expand Up @@ -101,19 +99,9 @@ func getSignedTransitStateTxDataParams(r *http.Request, data []byte) ([32]byte,
}

func getTxOpts(r *http.Request, receiver common.Address, txData []byte) (*bind.TransactOpts, error) {
gasPrice, err := EthClient(r).SuggestGasPrice(r.Context())
gasPrice, gasLimit, err := getGasCosts(r, receiver, txData)
if err != nil {
return nil, errors.Wrap(err, "failed to suggest gas price")
}

gasLimit, err := EthClient(r).EstimateGas(r.Context(), ethereum.CallMsg{
From: crypto.PubkeyToAddress(NetworkConfig(r).PrivateKey.PublicKey),
To: &receiver,
GasPrice: gasPrice,
Data: txData,
})
if err != nil {
return nil, errors.Wrap(err, "failed to estimate gas limit")
return nil, errors.Wrap(err, "failed to get gas costs")
}

txOpts, err := bind.NewKeyedTransactorWithChainID(NetworkConfig(r).PrivateKey, NetworkConfig(r).ChainID)
Expand All @@ -122,8 +110,8 @@ func getTxOpts(r *http.Request, receiver common.Address, txData []byte) (*bind.T
}

txOpts.Nonce = new(big.Int).SetUint64(NetworkConfig(r).Nonce())
txOpts.GasPrice = multiplyGasPrice(gasPrice, NetworkConfig(r).GasMultiplier)
txOpts.GasLimit = uint64(float64(gasLimit) * NetworkConfig(r).GasMultiplier)
txOpts.GasPrice = gasPrice
txOpts.GasLimit = gasLimit

return txOpts, nil
}
Expand Down
118 changes: 69 additions & 49 deletions internal/service/api/handlers/vote.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,92 +48,112 @@ func Vote(w http.ResponseWriter, r *http.Request) {
return
}

gasPrice, err := EthClient(r).SuggestGasPrice(r.Context())
NetworkConfig(r).LockNonce()
defer NetworkConfig(r).UnlockNonce()

tx, err := processLegacyTx(r, voting, dataBytes)
if err != nil {
Log(r).WithError(err).Error("failed to suggest gas price")
Log(r).WithError(err).Error("failed to process legacy transaction")
ape.RenderErr(w, problems.InternalError())
return
}

NetworkConfig(r).LockNonce()
defer NetworkConfig(r).UnlockNonce()
NetworkConfig(r).IncrementNonce()

gas, err := EthClient(r).EstimateGas(r.Context(), ethereum.CallMsg{
From: crypto.PubkeyToAddress(NetworkConfig(r).PrivateKey.PublicKey),
To: &voting,
GasPrice: gasPrice,
Data: dataBytes,
})
ape.Render(w, newTxModel(tx))
}

// ONE - One GWEI
var ONE = 1000000000

func multiplyGasPrice(gasPrice *big.Int, multiplier float64) *big.Int {
mult := big.NewFloat(0).Mul(big.NewFloat(multiplier), big.NewFloat(float64(ONE)))
gas, _ := big.NewFloat(0).Mul(big.NewFloat(0).SetInt(gasPrice), mult).Int(nil)
return big.NewInt(0).Div(gas, big.NewInt(int64(ONE)))
}

func processLegacyTx(r *http.Request, receiver common.Address, txData []byte) (*types.Transaction, error) {
gasPrice, gasLimit, err := getGasCosts(r, receiver, txData)
if err != nil {
Log(r).WithError(err).Error("failed to estimate gas")
ape.RenderErr(w, problems.InternalError())
return
return nil, errors.Wrap(err, "failed to get gas costs")
}

tx, err := types.SignNewTx(
NetworkConfig(r).PrivateKey,
types.NewCancunSigner(NetworkConfig(r).ChainID),
&types.LegacyTx{
Nonce: NetworkConfig(r).Nonce(),
Gas: uint64(float64(gas) * NetworkConfig(r).GasMultiplier),
GasPrice: multiplyGasPrice(gasPrice, NetworkConfig(r).GasMultiplier),
To: &voting,
Data: dataBytes,
Gas: gasLimit,
GasPrice: gasPrice,
To: &receiver,
Data: txData,
},
)
if err != nil {
Log(r).WithError(err).Error("failed to sign new tx")
ape.RenderErr(w, problems.InternalError())
return
return nil, errors.Wrap(err, "failed to sign new tx")
}

if err = sendTransaction(r, tx); err != nil {
return nil, errors.Wrap(err, "failed to send transaction")
}

return tx, nil
}

func getGasCosts(
r *http.Request,
receiver common.Address,
txData []byte,
) (gasPrice *big.Int, gasLimit uint64, err error) {
gasPrice, err = EthClient(r).SuggestGasPrice(r.Context())
if err != nil {
return nil, 0, errors.Wrap(err, "failed to suggest gas price")
}
gasPrice = multiplyGasPrice(gasPrice, NetworkConfig(r).GasMultiplier)

gasLimit, err = EthClient(r).EstimateGas(r.Context(), ethereum.CallMsg{
From: crypto.PubkeyToAddress(NetworkConfig(r).PrivateKey.PublicKey),
To: &receiver,
GasPrice: gasPrice,
Data: txData,
})
if err != nil {
return nil, 0, errors.Wrap(err, "failed to estimate gas costs limit")
}
gasLimit = uint64(float64(gasLimit) * NetworkConfig(r).GasMultiplier)

return
}

func sendTransaction(r *http.Request, tx *types.Transaction) error {
if err := EthClient(r).SendTransaction(r.Context(), tx); err != nil {
if strings.Contains(err.Error(), "nonce") {
if err := NetworkConfig(r).ResetNonce(EthClient(r)); err != nil {
Log(r).WithError(err).Error("failed to reset nonce")
ape.RenderErr(w, problems.InternalError())
return
if err = NetworkConfig(r).ResetNonce(EthClient(r)); err != nil {
return errors.Wrap(err, "failed to reset nonce")
}

tx, err = types.SignNewTx(
NetworkConfig(r).PrivateKey,
types.NewCancunSigner(NetworkConfig(r).ChainID),
&types.LegacyTx{
Nonce: NetworkConfig(r).Nonce(),
Gas: gas,
GasPrice: gasPrice,
To: &voting,
Data: dataBytes,
Gas: tx.Gas(),
GasPrice: tx.GasPrice(),
To: tx.To(),
Data: tx.Data(),
},
)
if err != nil {
Log(r).WithError(err).Error("failed to sign new tx")
ape.RenderErr(w, problems.InternalError())
return
return errors.Wrap(err, "failed to sign new tx")
}

if err := EthClient(r).SendTransaction(r.Context(), tx); err != nil {
Log(r).WithError(err).Error("failed to send transaction")
ape.RenderErr(w, problems.InternalError())
return
return errors.Wrap(err, "failed to resend transaction")
}
} else {
Log(r).WithError(err).Error("failed to send transaction")
ape.RenderErr(w, problems.InternalError())
return
return errors.Wrap(err, "failed to send transaction")
}
}

NetworkConfig(r).IncrementNonce()

ape.Render(w, newTxModel(tx))
}

// ONE - One GWEI
var ONE = 1000000000

func multiplyGasPrice(gasPrice *big.Int, multiplier float64) *big.Int {
mult := big.NewFloat(0).Mul(big.NewFloat(multiplier), big.NewFloat(float64(ONE)))
gas, _ := big.NewFloat(0).Mul(big.NewFloat(0).SetInt(gasPrice), mult).Int(nil)
return big.NewInt(0).Div(gas, big.NewInt(int64(ONE)))
return nil
}

0 comments on commit ed5da51

Please sign in to comment.