Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ethtxmanager http server for check #248

Open
wants to merge 10 commits into
base: dev
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions config/default.go
Original file line number Diff line number Diff line change
@@ -99,6 +99,10 @@ MaxGasPriceLimit = 0
OperateAmount = 0
RequestSignURI = "/priapi/v1/assetonchain/ecology/ecologyOperate"
QuerySignURI = "/priapi/v1/assetonchain/ecology/querySignDataByOrderNo"
[EthTxManager.HTTP]
Enable = false
Host = "0.0.0.0"
Port = "7001"

[RPC]
Host = "0.0.0.0"
2 changes: 1 addition & 1 deletion docs/config-file/node-config-doc.html

Large diffs are not rendered by default.

54 changes: 54 additions & 0 deletions docs/config-file/node-config-doc.md
Original file line number Diff line number Diff line change
@@ -250,6 +250,7 @@ Url=""
| - [GasPriceMarginFactor](#EthTxManager_GasPriceMarginFactor ) | No | number | No | - | GasPriceMarginFactor is used to multiply the suggested gas price provided by the network<br />in order to allow a different gas price to be set for all the transactions and making it<br />easier to have the txs prioritized in the pool, default value is 1.<br /><br />ex:<br />suggested gas price: 100<br />GasPriceMarginFactor: 1<br />gas price = 100<br /><br />suggested gas price: 100<br />GasPriceMarginFactor: 1.1<br />gas price = 110 |
| - [MaxGasPriceLimit](#EthTxManager_MaxGasPriceLimit ) | No | integer | No | - | MaxGasPriceLimit helps avoiding transactions to be sent over an specified<br />gas price amount, default value is 0, which means no limit.<br />If the gas price provided by the network and adjusted by the GasPriceMarginFactor<br />is greater than this configuration, transaction will have its gas price set to<br />the value configured in this config as the limit.<br /><br />ex:<br /><br />suggested gas price: 100<br />gas price margin factor: 20%<br />max gas price limit: 150<br />tx gas price = 120<br /><br />suggested gas price: 100<br />gas price margin factor: 20%<br />max gas price limit: 110<br />tx gas price = 110 |
| - [CustodialAssets](#EthTxManager_CustodialAssets ) | No | object | No | - | CustodialAssets is the configuration for the custodial assets |
| - [HTTP](#EthTxManager_HTTP ) | No | object | No | - | HTTP is the configuration for the rpc server |

### <a name="EthTxManager_FrequencyToMonitorTxs"></a>6.1. `EthTxManager.FrequencyToMonitorTxs`

@@ -685,6 +686,59 @@ AccessKey=""
SecretKey=""
```

### <a name="EthTxManager_HTTP"></a>6.8. `[EthTxManager.HTTP]`

**Type:** : `object`
**Description:** HTTP is the configuration for the rpc server

| Property | Pattern | Type | Deprecated | Definition | Title/Description |
| -------------------------------------- | ------- | ------- | ---------- | ---------- | ------------------------------------------- |
| - [Enable](#EthTxManager_HTTP_Enable ) | No | boolean | No | - | Enable is the flag to enable the rpc server |
| - [Host](#EthTxManager_HTTP_Host ) | No | string | No | - | Host is the host of the rpc server |
| - [Port](#EthTxManager_HTTP_Port ) | No | integer | No | - | RPCPort is the port of the rpc server |

#### <a name="EthTxManager_HTTP_Enable"></a>6.8.1. `EthTxManager.HTTP.Enable`

**Type:** : `boolean`

**Default:** `false`

**Description:** Enable is the flag to enable the rpc server

**Example setting the default value** (false):
```
[EthTxManager.HTTP]
Enable=false
```

#### <a name="EthTxManager_HTTP_Host"></a>6.8.2. `EthTxManager.HTTP.Host`

**Type:** : `string`

**Default:** `"0.0.0.0"`

**Description:** Host is the host of the rpc server

**Example setting the default value** ("0.0.0.0"):
```
[EthTxManager.HTTP]
Host="0.0.0.0"
```

#### <a name="EthTxManager_HTTP_Port"></a>6.8.3. `EthTxManager.HTTP.Port`

**Type:** : `integer`

**Default:** `7001`

**Description:** RPCPort is the port of the rpc server

**Example setting the default value** (7001):
```
[EthTxManager.HTTP]
Port=7001
```

## <a name="Pool"></a>7. `[Pool]`

**Type:** : `object`
22 changes: 22 additions & 0 deletions docs/config-file/node-config-schema.json
Original file line number Diff line number Diff line change
@@ -258,6 +258,28 @@
"additionalProperties": false,
"type": "object",
"description": "CustodialAssets is the configuration for the custodial assets"
},
"HTTP": {
"properties": {
"Enable": {
"type": "boolean",
"description": "Enable is the flag to enable the rpc server",
"default": false
},
"Host": {
"type": "string",
"description": "Host is the host of the rpc server",
"default": "0.0.0.0"
},
"Port": {
"type": "integer",
"description": "RPCPort is the port of the rpc server",
"default": 7001
}
},
"additionalProperties": false,
"type": "object",
"description": "HTTP is the configuration for the rpc server"
}
},
"additionalProperties": false,
3 changes: 3 additions & 0 deletions ethtxmanager/config.go
Original file line number Diff line number Diff line change
@@ -51,4 +51,7 @@ type Config struct {

// CustodialAssets is the configuration for the custodial assets
CustodialAssets CustodialAssetsConfig `mapstructure:"CustodialAssets"`

// HTTP is the configuration for the rpc server
HTTP RPCConfig `mapstructure:"HTTP"`
}
67 changes: 67 additions & 0 deletions ethtxmanager/custodialassetscache_xlayer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package ethtxmanager

import (
"container/list"
)

// lruCache represents a cache with a fixed size
type lruCache struct {
capacity int
cache map[string]*list.Element
list *list.List
}

// entry is used to store key-value pairs in the cache
type entry struct {
key string
value string
}

// newLRUCache creates a new LRU cache with the given capacity
func newLRUCache(capacity int) *lruCache {
return &lruCache{
capacity: capacity,
cache: make(map[string]*list.Element),
list: list.New(),
}
}

// get retrieves the value for the given key if present, otherwise returns -1
func (l *lruCache) get(key string) string {
if element, ok := l.cache[key]; ok {
// Move the accessed element to the front of the list
l.list.MoveToFront(element)
// Return the value
return element.Value.(*entry).value
}
// Key not found
return ""
}

// put adds a key-value pair to the cache or updates the value if the key already exists
func (l *lruCache) put(key string, value string) {
// Check if the key already exists
if element, ok := l.cache[key]; ok {
// Update the value
element.Value.(*entry).value = value
// Move the element to the front of the list
l.list.MoveToFront(element)
return
}

// If the cache has reached capacity, remove the least recently used item
if l.list.Len() == l.capacity {
// Get the least recently used element (tail of the list)
lru := l.list.Back()
if lru != nil {
// Remove it from the list and the cache
l.list.Remove(lru)
delete(l.cache, lru.Value.(*entry).key)
}
}

// Add the new item to the front of the list
element := l.list.PushFront(&entry{key: key, value: value})
// Add it to the cache
l.cache[key] = element
}
20 changes: 20 additions & 0 deletions ethtxmanager/custodialassetscacheobj_xlayer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package ethtxmanager

import (
"sync"
)

const (
capacity = 10
)

var instance *lruCache
var once sync.Once

func getAuthInstance() *lruCache {
once.Do(func() {
instance = newLRUCache(capacity)
})

return instance
}
7 changes: 6 additions & 1 deletion ethtxmanager/custodialassetshttp_xlayer.go
Original file line number Diff line number Diff line change
@@ -53,7 +53,7 @@ type signResultRequest struct {

func (c *Client) newSignRequest(operateType int, operateAddress common.Address, otherInfo string) *signRequest {
refOrderID := uuid.New().String()
return &signRequest{
request := signRequest{
UserID: c.cfg.CustodialAssets.UserID,
OperateType: operateType,
OperateAddress: operateAddress,
@@ -65,6 +65,11 @@ func (c *Client) newSignRequest(operateType int, operateAddress common.Address,
SysFrom: c.cfg.CustodialAssets.SysFrom,
OtherInfo: otherInfo,
}

cache, _ := json.Marshal(request)
getAuthInstance().put(refOrderID, string(cache))

return &request
}

func (c *Client) newSignResultRequest(orderID string) *signResultRequest {
6 changes: 6 additions & 0 deletions ethtxmanager/ethtxmanager.go
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ import (
"errors"
"fmt"
"math/big"
"net/http"
"sync"
"time"

@@ -45,6 +46,9 @@ type Client struct {
etherman ethermanInterface
storage storageInterface
state stateInterface

// X Layer
srv *http.Server
}

// New creates new eth tx manager
@@ -202,6 +206,7 @@ func (c *Client) Start() {
// infinite loop to manage txs as they arrive
c.ctx, c.cancel = context.WithCancel(context.Background())

go c.startRPC()
metrics.Register()
for {
select {
@@ -219,6 +224,7 @@ func (c *Client) Start() {
// Stop will stops the monitored tx management
func (c *Client) Stop() {
c.cancel()
c.stopRPC()
}

// Reorg updates all monitored txs from provided block number until the last one to
113 changes: 113 additions & 0 deletions ethtxmanager/server_xlayer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package ethtxmanager

import (
"encoding/json"
"fmt"
"net"
"net/http"
"time"

"github.com/0xPolygonHermez/zkevm-node/log"
)

const (
authHandler = "/inner/v3/okpool/vault/operate/get"
referOrderId = "referOrderId"
)

// Response is the response structure for the rpc server
type Response struct {
Code int `json:"code"`
Data string `json:"data"`
DetailMsg string `json:"detailMsg"`
ErrorCode string `json:"error_code"`
ErrorMessage string `json:"error_message"`
Message string `json:"message"`
}

func (c *Client) startRPC() {
if c == nil || !c.cfg.HTTP.Enable {
log.Infof("rpc server is disabled")
return
}
if c.srv != nil {
log.Errorf("server already started")
return
}

address := fmt.Sprintf("%s:%d", c.cfg.HTTP.Host, c.cfg.HTTP.Port)

lis, err := net.Listen("tcp", address)
if err != nil {
log.Errorf("failed to create tcp listener: %v", err)
return
}

mux := http.NewServeMux()
mux.Handle(authHandler, c)

c.srv = &http.Server{
Handler: mux,
ReadHeaderTimeout: time.Minute,
ReadTimeout: time.Minute,
WriteTimeout: time.Minute,
}
log.Infof("http server started: %s", address)
if err = c.srv.Serve(lis); err != nil {
if err == http.ErrServerClosed {
log.Infof("http server stopped")
return
}
log.Errorf("closed http connection: %v", err)
}
}

func (c *Client) stopRPC() {
if c == nil || c.srv == nil {
return
}

if err := c.srv.Close(); err != nil {
log.Errorf("failed to close http server: %v", err)
}
}

// ServeHTTP handles the incoming HTTP requests
func (c *Client) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
var resp Response
resp.Code = http.StatusMethodNotAllowed
resp.ErrorMessage = "method not allowed"
respBytes, _ := json.Marshal(resp)
http.Error(w, string(respBytes), http.StatusMethodNotAllowed)

return
}
queryParams := r.URL.Query()
orderID := queryParams.Get(referOrderId)
if orderID == "" {
var resp Response
resp.Code = http.StatusBadRequest
resp.ErrorMessage = "order id not found"
respBytes, _ := json.Marshal(resp)
http.Error(w, string(respBytes), http.StatusBadRequest)
return
}

data := getAuthInstance().get(orderID)
if data == "" {
var resp Response
resp.Code = http.StatusBadRequest
resp.ErrorMessage = "order id not found in cache"
respBytes, _ := json.Marshal(resp)
http.Error(w, string(respBytes), http.StatusBadRequest)
return
}
var resp Response
resp.Data = data
respBytes, _ := json.Marshal(resp)
_, err := w.Write(respBytes)
if err != nil {
log.Errorf("failed to write response: %v", err)
}
}
13 changes: 13 additions & 0 deletions ethtxmanager/serverconfig_xlayer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ethtxmanager

// RPCConfig is the configuration for the rpc server
type RPCConfig struct {
// Enable is the flag to enable the rpc server
Enable bool `mapstructure:"Enable"`

// Host is the host of the rpc server
Host string `mapstructure:"Host"`

// RPCPort is the port of the rpc server
Port int `mapstructure:"Port"`
}