Skip to content

Commit

Permalink
Custom Gas Limit (#46)
Browse files Browse the repository at this point in the history
* first pass

* setup preprocess

* fix tests

* fix linting

* nits

* update version
  • Loading branch information
patrick-ogrady authored Oct 21, 2021
1 parent ad8e37a commit d538302
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 17 deletions.
2 changes: 1 addition & 1 deletion service/rosetta.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ package service

const (
NodeVersion = "1.6.3"
MiddlewareVersion = "0.0.15"
MiddlewareVersion = "0.0.16"
BlockchainName = "Avalanche"
)
27 changes: 24 additions & 3 deletions service/service_construction.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,26 @@ func (s ConstructionService) ConstructionMetadata(
gasPrice = input.GasPrice
}

var gasLimit uint64
if input.GasLimit == nil {
// TODO: use dynamic gas limit suggestion
gasLimit = transferGasLimit
} else {
gasLimit = input.GasLimit.Uint64()
}

metadata := &metadata{
Nonce: nonce,
GasPrice: gasPrice,
GasLimit: gasLimit,
}

metadataMap, err := marshalJSONMap(metadata)
if err != nil {
return nil, wrapError(errInternalError, err)
}

suggestedFee := gasPrice.Int64() * int64(transferGasLimit)
suggestedFee := gasPrice.Int64() * int64(gasLimit)
return &types.ConstructionMetadataResponse{
Metadata: metadataMap,
SuggestedFee: []*types.Amount{
Expand Down Expand Up @@ -286,6 +295,7 @@ func (s ConstructionService) ConstructionParse(
metadata := &parseMetadata{
Nonce: tx.Nonce,
GasPrice: tx.GasPrice,
GasLimit: tx.GasLimit,
ChainID: tx.ChainID,
}
metaMap, err := marshalJSONMap(metadata)
Expand Down Expand Up @@ -370,8 +380,8 @@ func (s ConstructionService) ConstructionPayloads(
toAddress := toOp.Account.Address
nonce := metadata.Nonce
gasPrice := metadata.GasPrice
gasLimit := metadata.GasLimit
chainID := s.config.ChainID
transferGasLimit := transferGasLimit
transferData := []byte{}

fromOp, _ := matches[0].First()
Expand All @@ -391,7 +401,7 @@ func (s ConstructionService) ConstructionPayloads(
nonce,
ethcommon.HexToAddress(checkTo),
amount,
transferGasLimit,
gasLimit,
gasPrice,
transferData,
)
Expand Down Expand Up @@ -497,6 +507,17 @@ func (s ConstructionService) ConstructionPreprocess(
}
preprocessOptions.GasPrice = bigObj
}
if v, ok := req.Metadata["gas_limit"]; ok {
stringObj, ok := v.(string)
if !ok {
return nil, wrapError(errInvalidInput, fmt.Errorf("%s is not a valid gas limit string", v))
}
bigObj, ok := new(big.Int).SetString(stringObj, 10) //nolint:gomnd
if !ok {
return nil, wrapError(errInvalidInput, fmt.Errorf("%s is not a valid gas limit", v))
}
preprocessOptions.GasLimit = bigObj
}
if v, ok := req.Metadata["nonce"]; ok {
stringObj, ok := v.(string)
if !ok {
Expand Down
66 changes: 66 additions & 0 deletions service/service_construction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ func TestPreprocessMetadata(t *testing.T) {

metadata := &metadata{
GasPrice: big.NewInt(1000000000),
GasLimit: 21_000,
Nonce: 0,
}

Expand Down Expand Up @@ -232,6 +233,7 @@ func TestPreprocessMetadata(t *testing.T) {

metadata := &metadata{
GasPrice: big.NewInt(1100000000),
GasLimit: 21_000,
Nonce: 0,
}

Expand Down Expand Up @@ -285,6 +287,7 @@ func TestPreprocessMetadata(t *testing.T) {

metadata := &metadata{
GasPrice: big.NewInt(1100000000),
GasLimit: 21_000,
Nonce: 0,
}

Expand Down Expand Up @@ -335,6 +338,7 @@ func TestPreprocessMetadata(t *testing.T) {

metadata := &metadata{
GasPrice: big.NewInt(1100000000),
GasLimit: 21_000,
Nonce: 0,
}

Expand Down Expand Up @@ -395,6 +399,7 @@ func TestPreprocessMetadata(t *testing.T) {

metadata := &metadata{
GasPrice: big.NewInt(1100000000),
GasLimit: 21_000,
Nonce: 1,
}

Expand All @@ -420,4 +425,65 @@ func TestPreprocessMetadata(t *testing.T) {
},
}, metadataResponse)
})

t.Run("custom gas limit", func(t *testing.T) {
var ops []*types.Operation
assert.NoError(t, json.Unmarshal([]byte(intent), &ops))
multiplier := float64(1.1)
preprocessResponse, err := service.ConstructionPreprocess(
ctx,
&types.ConstructionPreprocessRequest{
NetworkIdentifier: networkIdentifier,
Operations: ops,
SuggestedFeeMultiplier: &multiplier,
Metadata: map[string]interface{}{
"gas_limit": "40000",
},
},
)
assert.Nil(t, err)
optionsRaw := `{"from":"0xe3a5B4d7f79d64088C8d4ef153A7DDe2B2d47309","suggested_fee_multiplier":1.1,"gas_limit":"0x9c40"}` //nolint:lll
var opt options
assert.NoError(t, json.Unmarshal([]byte(optionsRaw), &opt))
assert.Equal(t, &types.ConstructionPreprocessResponse{
Options: forceMarshalMap(t, &opt),
}, preprocessResponse)

metadata := &metadata{
GasPrice: big.NewInt(1100000000),
GasLimit: 40_000,
Nonce: 0,
}

client.On(
"SuggestGasPrice",
ctx,
).Return(
big.NewInt(1000000000),
nil,
).Once()
client.On(
"NonceAt",
ctx,
common.HexToAddress("0xe3a5B4d7f79d64088C8d4ef153A7DDe2B2d47309"),
(*big.Int)(nil),
).Return(
uint64(0),
nil,
).Once()
metadataResponse, err := service.ConstructionMetadata(ctx, &types.ConstructionMetadataRequest{
NetworkIdentifier: networkIdentifier,
Options: forceMarshalMap(t, &opt),
})
assert.Nil(t, err)
assert.Equal(t, &types.ConstructionMetadataResponse{
Metadata: forceMarshalMap(t, metadata),
SuggestedFee: []*types.Amount{
{
Value: "44000000000000",
Currency: mapper.AvaxCurrency,
},
},
}, metadataResponse)
})
}
50 changes: 37 additions & 13 deletions service/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ type options struct {
From string `json:"from"`
SuggestedFeeMultiplier *float64 `json:"suggested_fee_multiplier,omitempty"`
GasPrice *big.Int `json:"gas_price,omitempty"`
GasLimit *big.Int `json:"gas_limit,omitempty"`
Nonce *big.Int `json:"nonce,omitempty"`
}

type optionsWire struct {
From string `json:"from"`
SuggestedFeeMultiplier *float64 `json:"suggested_fee_multiplier,omitempty"`
GasPrice string `json:"gas_price,omitempty"`
GasLimit string `json:"gas_limit,omitempty"`
Nonce string `json:"nonce,omitempty"`
}

Expand All @@ -31,13 +33,15 @@ func (o *options) MarshalJSON() ([]byte, error) {
From: o.From,
SuggestedFeeMultiplier: o.SuggestedFeeMultiplier,
}
if o.Nonce != nil {
ow.Nonce = hexutil.EncodeBig(o.Nonce)
}
if o.GasPrice != nil {
ow.GasPrice = hexutil.EncodeBig(o.GasPrice)
}

if o.GasLimit != nil {
ow.GasLimit = hexutil.EncodeBig(o.GasLimit)
}
if o.Nonce != nil {
ow.Nonce = hexutil.EncodeBig(o.Nonce)
}
return json.Marshal(ow)
}

Expand All @@ -49,20 +53,28 @@ func (o *options) UnmarshalJSON(data []byte) error {
o.From = ow.From
o.SuggestedFeeMultiplier = ow.SuggestedFeeMultiplier

if len(ow.Nonce) > 0 {
nonce, err := hexutil.DecodeBig(ow.Nonce)
if len(ow.GasPrice) > 0 {
gasPrice, err := hexutil.DecodeBig(ow.GasPrice)
if err != nil {
return err
}
o.Nonce = nonce
o.GasPrice = gasPrice
}

if len(ow.GasPrice) > 0 {
gasPrice, err := hexutil.DecodeBig(ow.GasPrice)
if len(ow.GasLimit) > 0 {
gasLimit, err := hexutil.DecodeBig(ow.GasLimit)
if err != nil {
return err
}
o.GasPrice = gasPrice
o.GasLimit = gasLimit
}

if len(ow.Nonce) > 0 {
nonce, err := hexutil.DecodeBig(ow.Nonce)
if err != nil {
return err
}
o.Nonce = nonce
}

return nil
Expand All @@ -71,17 +83,20 @@ func (o *options) UnmarshalJSON(data []byte) error {
type metadata struct {
Nonce uint64 `json:"nonce"`
GasPrice *big.Int `json:"gas_price"`
GasLimit uint64 `json:"gas_limit"`
}

type metadataWire struct {
Nonce string `json:"nonce"`
GasPrice string `json:"gas_price"`
GasLimit string `json:"gas_limit"`
}

func (m *metadata) MarshalJSON() ([]byte, error) {
mw := &metadataWire{
Nonce: hexutil.Uint64(m.Nonce).String(),
GasPrice: hexutil.EncodeBig(m.GasPrice),
GasLimit: hexutil.Uint64(m.GasLimit).String(),
}

return json.Marshal(mw)
Expand All @@ -93,37 +108,46 @@ func (m *metadata) UnmarshalJSON(data []byte) error {
return err
}

nonce, err := hexutil.DecodeUint64(mw.Nonce)
gasPrice, err := hexutil.DecodeBig(mw.GasPrice)
if err != nil {
return err
}
m.GasPrice = gasPrice

gasPrice, err := hexutil.DecodeBig(mw.GasPrice)
gasLimit, err := hexutil.DecodeUint64(mw.GasLimit)
if err != nil {
return err
}
m.GasLimit = gasLimit

m.GasPrice = gasPrice
nonce, err := hexutil.DecodeUint64(mw.Nonce)
if err != nil {
return err
}
m.Nonce = nonce

return nil
}

type parseMetadata struct {
Nonce uint64 `json:"nonce"`
GasPrice *big.Int `json:"gas_price"`
GasLimit uint64 `json:"gas_limit"`
ChainID *big.Int `json:"chain_id"`
}

type parseMetadataWire struct {
Nonce string `json:"nonce"`
GasPrice string `json:"gas_price"`
GasLimit string `json:"gas_limit"`
ChainID string `json:"chain_id"`
}

func (p *parseMetadata) MarshalJSON() ([]byte, error) {
pmw := &parseMetadataWire{
Nonce: hexutil.Uint64(p.Nonce).String(),
GasPrice: hexutil.EncodeBig(p.GasPrice),
GasLimit: hexutil.Uint64(p.GasLimit).String(),
ChainID: hexutil.EncodeBig(p.ChainID),
}

Expand Down

0 comments on commit d538302

Please sign in to comment.