Skip to content

Commit

Permalink
ethrpc: support nodes which return invalid vrs in no-strict mode (#148)
Browse files Browse the repository at this point in the history
  • Loading branch information
pkieltyka authored Nov 28, 2024
1 parent 5ef9f9a commit e20c4a4
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 2 deletions.
98 changes: 98 additions & 0 deletions cmd/chain-ethgas/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package main

import (
"context"
"fmt"
"log"
"time"

"github.com/0xsequence/ethkit/ethgas"
"github.com/0xsequence/ethkit/ethmonitor"
"github.com/0xsequence/ethkit/ethrpc"
"github.com/0xsequence/ethkit/util"
"github.com/goware/logger"
)

var ETH_NODE_URL = "http://localhost:8545"
var ETH_NODE_WSS_URL = ""

func init() {
testConfig, err := util.ReadTestConfig("../../ethkit-test.json")
if err != nil {
panic(err)
}

if testConfig["POLYGON_MAINNET_URL"] != "" {
ETH_NODE_URL = testConfig["POLYGON_MAINNET_URL"]
ETH_NODE_WSS_URL = testConfig["POLYGON_MAINNET_WSS_URL"]
}
// if testConfig["MAINNET_URL"] != "" {
// ETH_NODE_URL = testConfig["MAINNET_URL"]
// ETH_NODE_WSS_URL = testConfig["MAINNET_WSS_URL"]
// }

// ETH_NODE_URL = ""
// ETH_NODE_WSS_URL = ""
}

func main() {
fmt.Println("chain-ethgas start")

// Provider
provider, err := ethrpc.NewProvider(ETH_NODE_URL, ethrpc.WithStreaming(ETH_NODE_WSS_URL))
if err != nil {
log.Fatal(err)
}

// Monitor options
monitorOptions := ethmonitor.DefaultOptions
monitorOptions.PollingInterval = time.Duration(1000 * time.Millisecond)
// monitorOptions.DebugLogging = true
monitorOptions.WithLogs = true
monitorOptions.BlockRetentionLimit = 400
monitorOptions.StartBlockNumber = nil // track the head

// ...
monitor, err := ethmonitor.NewMonitor(provider, monitorOptions)
if err != nil {
log.Fatal(err)
}

ctx := context.Background()

go func() {
err = monitor.Run(ctx)
if err != nil {
panic(err)
}
}()
defer monitor.Stop()

logger := logger.NewLogger(logger.LogLevel_INFO)

gasGague, err := ethgas.NewGasGauge(logger, monitor, 1, false)
if err != nil {
log.Fatal(err)
}

go func() {
err := gasGague.Run(ctx)
if err != nil {
log.Fatal(err)
}
}()
defer gasGague.Stop()

sub := gasGague.Subscribe()
defer sub.Unsubscribe()

for {
select {
case <-sub.Blocks():
prices := gasGague.SuggestedGasPrice()
bids := gasGague.SuggestedGasPriceBid()
fmt.Println(prices.BlockNum, prices.BlockTime, prices.Instant, prices.Fast, prices.Standard, prices.Slow)
fmt.Println(bids.BlockNum, bids.BlockTime, bids.Instant, bids.Fast, bids.Standard, bids.Slow)
}
}
}
18 changes: 18 additions & 0 deletions ethrpc/ethrpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,3 +305,21 @@ func TestDebugTraceTransaction(t *testing.T) {
// require.NotNil(t, block)
// require.Equal(t, uint64(1_000_000), block.NumberU64())
// }

func TestFetchBlockWithInvalidVRS(t *testing.T) {
url := "https://rpc.telos.net"
// url := "https://node.mainnet.etherlink.com"

p, err := ethrpc.NewProvider(url)
require.NoError(t, err)

block, err := p.BlockByNumber(context.Background(), big.NewInt(373117692))
require.NoError(t, err)
require.NotNil(t, block)

for _, tx := range block.Transactions() {
require.Equal(t, uint8(0), tx.Type())
require.Equal(t, big.NewInt(0), tx.GasFeeCap())
require.Equal(t, big.NewInt(0), tx.GasPrice())
}
}
32 changes: 30 additions & 2 deletions ethrpc/unmarshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ func (tx *rpcTransaction) UnmarshalJSON(msg []byte) error {
// we set internal flag to check if txn has invalid VRS signature
if err == types.ErrInvalidSig {
tx.txVRSInvalid = true

// reset vrs to 0x0 and try again. we perform validation in the caller
msg, err = resetVRS(msg)
if err != nil {
return err
}

// in case of any other error, return the error
err = json.Unmarshal(msg, &tx.tx)
if err != nil {
return err
}
}
}

Expand Down Expand Up @@ -103,7 +115,7 @@ func IntoBlock(raw json.RawMessage, ret **types.Block, strictness StrictnessLeve
}

if strictness >= StrictnessLevel_Semi && tx.txVRSInvalid {
return fmt.Errorf("invalid transaction v, r, s")
return types.ErrInvalidSig
}

if tx.txExtraInfo.TxType != "" {
Expand Down Expand Up @@ -160,7 +172,7 @@ func IntoTransactionWithPending(raw json.RawMessage, tx **types.Transaction, pen

if strictness >= StrictnessLevel_Semi {
if body.txVRSInvalid {
return fmt.Errorf("invalid transaction v, r, s")
return types.ErrInvalidSig
}
if _, r, _ := body.tx.RawSignatureValues(); r == nil {
return fmt.Errorf("server returned transaction without signature")
Expand Down Expand Up @@ -217,3 +229,19 @@ func (s *senderFromServer) Hash(tx *types.Transaction) common.Hash {
func (s *senderFromServer) SignatureValues(tx *types.Transaction, sig []byte) (R, S, V *big.Int, err error) {
panic("can't sign with senderFromServer")
}

func resetVRS(msg []byte) ([]byte, error) {
var m map[string]interface{}
err := json.Unmarshal(msg, &m)
if err != nil {
return nil, err
}
m["v"] = "0x0"
m["r"] = "0x0"
m["s"] = "0x0"
out, err := json.Marshal(m)
if err != nil {
return nil, err
}
return out, nil
}

0 comments on commit e20c4a4

Please sign in to comment.