Skip to content
Merged
Show file tree
Hide file tree
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
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,11 @@ Flags:
--password-file string Path to key password file
--rpc-url string Node HTTP RPC_URL, normally starts with https://****
--secret-key 0x****** Private key in format 0x****** or `*******`. If provided, no need to use --keystore
--subscription-url string [Optional] Used if you want to subscribe to events rather than poll, typically starts with wss://****
--tx-type legacy Transaction type definition, possible values are: legacy, `eip1559` or `none` (default "none")

```

Note that in *all* cases you must provide `--rpc-url`, but if you want to use event driven listening instead of polling you also need to provide `--subscription-url`.
Note that in *all* cases you must provide `--rpc-url`.

## Example

Expand Down
4 changes: 1 addition & 3 deletions cmd/challenger/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ type options struct {
PasswordFile string
RpcURL string
FlashbotRPCURL string
SubscriptionURL string
Address []string
FromBlock int64
ChainID uint64
Expand Down Expand Up @@ -247,7 +246,7 @@ func main() {
wg.Add(1)

p := challenger.NewScribeOptimisticRPCProvider(client, flashbotClient)
c := challenger.NewChallenger(ctx, address, p, opts.FromBlock, opts.SubscriptionURL, &wg)
c := challenger.NewChallenger(ctx, address, p, opts.FromBlock, &wg)

go func(addr types.Address) {
err := c.Run()
Expand Down Expand Up @@ -288,7 +287,6 @@ func main() {
cmd.PersistentFlags().StringVar(&opts.PasswordFile, "password-file", "", "Path to key password file")
cmd.PersistentFlags().StringVar(&opts.RpcURL, "rpc-url", "", "Node HTTP RPC_URL, normally starts with https://****")
cmd.PersistentFlags().StringVar(&opts.FlashbotRPCURL, "flashbot-rpc-url", "", "Flashbot Node HTTP RPC_URL, normally starts with https://****")
cmd.PersistentFlags().StringVar(&opts.SubscriptionURL, "subscription-url", "", "[Optional] Used if you want to subscribe to events rather than poll, typically starts with wss://****")
cmd.PersistentFlags().StringArrayVarP(&opts.Address, "addresses", "a", []string{}, "ScribeOptimistic contract address. Example: `0x891E368fE81cBa2aC6F6cc4b98e684c106e2EF4f`")
cmd.PersistentFlags().
Int64Var(&opts.FromBlock, "from-block", 0, "Block number to start from. If not provided, binary will try to get it from given RPC")
Expand Down
1 change: 0 additions & 1 deletion contract/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ function start_challenger {
--keystore "$ETH_KEYSTORE_FILE" \
--password "$ETH_PASS" \
--chain-id "$chainid" \
--subscription-url "$ETH_WSS_URL" | tee /tmp/challenger-test.log)&

sleep 5
cecho "Challenger running"
Expand Down
119 changes: 11 additions & 108 deletions core/challenger.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,6 @@ import (
logger "github.com/sirupsen/logrus"

"github.com/defiweb/go-eth/types"

"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
gethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
)

const slotPeriodInSec = 12
Expand All @@ -40,7 +35,6 @@ const OpPokedEventSig = "0xb9dc937c5e394d0c8f76e0e324500b88251b4c909ddc56232df10
type Challenger struct {
ctx context.Context
address types.Address
subscriptionURL string
provider IScribeOptimisticProvider
lastProcessedBlock *big.Int
wg *sync.WaitGroup
Expand All @@ -52,7 +46,6 @@ func NewChallenger(
address types.Address,
provider IScribeOptimisticProvider,
fromBlock int64,
subscriptionURL string,
wg *sync.WaitGroup,
) *Challenger {
var latestBlock *big.Int
Expand All @@ -65,7 +58,6 @@ func NewChallenger(
provider: provider,
lastProcessedBlock: latestBlock,
wg: wg,
subscriptionURL: subscriptionURL,
}
}

Expand Down Expand Up @@ -244,63 +236,7 @@ func (c *Challenger) Run() error {
WithField("address", c.address).
Infof("Started contract monitoring")

if c.subscriptionURL == "" { // We poll
ticker := time.NewTicker(30 * time.Second)

for {
select {
case <-c.ctx.Done():
logger.
WithField("address", c.address).
Infof("Terminate challenger")
return nil

case t := <-ticker.C:
logger.
WithField("address", c.address).
Debugf("Tick at: %v", t)

err := c.executeTick()
if err != nil {
logger.
WithField("address", c.address).
Errorf("Failed to execute tick with error: %v", err)
// Add error to metrics
ErrorsCounter.WithLabelValues(
c.address.String(),
c.provider.GetFrom(c.ctx).String(),
err.Error(),
).Inc()
}
}
}
} else { // Event based
return c.Listen()
}
}

// Listen listens for `OpPoked` events from WS connection and challenges them if they are challengeable.
// It requires you to provide WS connection to challenger.
func (c *Challenger) Listen() error {
logger.
WithField("address", c.address).
Infof("Listening for events from %v", c.address)
ethcli, err := ethclient.Dial(c.subscriptionURL)
if err != nil {
return err
}

//nolint:typecheck
query := ethereum.FilterQuery{
Addresses: []common.Address{common.HexToAddress(c.address.String())},
}

logs := make(chan gethtypes.Log)

sub, err := ethcli.SubscribeFilterLogs(c.ctx, query, logs)
if err != nil {
return err
}
ticker := time.NewTicker(30 * time.Second)

for {
select {
Expand All @@ -309,56 +245,23 @@ func (c *Challenger) Listen() error {
WithField("address", c.address).
Infof("Terminate challenger")
return nil
case err := <-sub.Err():
return err
case evlog := <-logs:
if evlog.Topics[0].Hex() != OpPokedEventSig {
logger.
WithField("address", c.address).
Infof("Event occurred, but is not 'opPoked': %s", evlog.Topics[0].Hex())
continue
}

// Marshal go-ethereum data to defiweb types
addr, err := types.AddressFromBytes(evlog.Address.Bytes())
if err != nil {
return err
}
case t := <-ticker.C:
logger.
WithField("address", c.address).
Infof("opPoked event for %v", addr)

topics := make([]types.Hash, 0)
for _, topic := range evlog.Topics {
t, err := types.HashFromBytes(topic.Bytes(), types.PadLeft)
if err != nil {
return err
}
topics = append(topics, t)
}
log := types.Log{
Address: addr,
Topics: topics,
Data: evlog.Data,
BlockNumber: new(big.Int).SetUint64(evlog.BlockNumber),
}

poke, err := DecodeOpPokeEvent(log)
if err != nil {
return err
}
Debugf("Tick at: %v", t)

period, err := c.provider.GetChallengePeriod(c.ctx, c.address)
err := c.executeTick()
if err != nil {
return fmt.Errorf("failed to get challenge period with error: %v", err)
}

if c.isPokeChallengeable(poke, period) {
c.SpawnChallenge(poke)
} else {
logger.
WithField("address", c.address).
Debugf("Event from block %v is not challengeable", poke.BlockNumber)
Errorf("Failed to execute tick with error: %v", err)
// Add error to metrics
ErrorsCounter.WithLabelValues(
c.address.String(),
c.provider.GetFrom(c.ctx).String(),
err.Error(),
).Inc()
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions core/challenger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func TestGetFromBlockNumber(t *testing.T) {
address := types.MustAddressFromHex("0x1F7acDa376eF37EC371235a094113dF9Cb4EfEe1")
mockedProvider := new(mockScribeOptimisticProvider)

c := NewChallenger(context.TODO(), address, mockedProvider, 0, "", nil)
c := NewChallenger(context.TODO(), address, mockedProvider, 0, nil)
require.NotNil(t, c)

// Error on nil as latest block number
Expand All @@ -104,7 +104,7 @@ func TestIsPokeChallengeable(t *testing.T) {
challengePeriod := uint16(600)
poke := OpPokedEvent{BlockNumber: big.NewInt(1000)}

c := NewChallenger(context.TODO(), address, mockedProvider, 0, "", nil)
c := NewChallenger(context.TODO(), address, mockedProvider, 0, nil)
require.NotNil(t, c)

assert.False(t, c.isPokeChallengeable(nil, 600))
Expand Down
24 changes: 1 addition & 23 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,58 +4,36 @@ go 1.22

require (
github.com/defiweb/go-eth v0.7.0
github.com/ethereum/go-ethereum v1.14.13
github.com/prometheus/client_golang v1.19.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.7.0
github.com/stretchr/testify v1.9.0
)

require (
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.13.0 // indirect
github.com/btcsuite/btcd v0.24.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
github.com/btcsuite/btcd/btcutil v1.1.5 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/consensys/bavard v0.1.13 // indirect
github.com/consensys/gnark-crypto v0.12.1 // indirect
github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c // indirect
github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deckarep/golang-set/v2 v2.6.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/defiweb/go-anymapper v0.3.0 // indirect
github.com/defiweb/go-rlp v0.3.0 // indirect
github.com/defiweb/go-sigparser v0.6.0 // indirect
github.com/ethereum/c-kzg-4844 v1.0.0 // indirect
github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/holiman/uint256 v1.3.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.48.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/supranational/blst v0.3.13 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
golang.org/x/crypto v0.31.0 // indirect
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.28.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
nhooyr.io/websocket v1.8.10 // indirect
rsc.io/tmplfunc v0.0.3 // indirect
)
Loading