Skip to content

Commit

Permalink
wip: solver arch
Browse files Browse the repository at this point in the history
  • Loading branch information
corverroos committed Nov 5, 2024
1 parent 9f62073 commit 443677d
Show file tree
Hide file tree
Showing 4 changed files with 325 additions and 0 deletions.
27 changes: 27 additions & 0 deletions solver/app/actions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package solver

import "context"

func (r *reactor) accept(ctx context.Context, chainID uint64, reqID reqID) error {

Check warning on line 5 in solver/app/actions.go

View workflow job for this annotation

GitHub Actions / go-lint / golangci

unused-receiver: method receiver 'r' is not referenced in method's body, consider removing or renaming it as _ (revive)
// TODO(corver): submit accept tx

return nil
}

func (r *reactor) reject(ctx context.Context, chainID uint64, reqID reqID, reason string) error {
// TODO(corver): submit reject tx

return nil
}

func (r *reactor) submit(ctx context.Context, chainID uint64, reqID reqID) error {
// TODO(corver): submit submit tx

return nil
}

func (r *reactor) claim(ctx context.Context, chainID uint64, reqID reqID) error {
// TODO(corver): submit claim tx

return nil
}
59 changes: 59 additions & 0 deletions solver/app/bindings.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package solver

import (
"github.com/ethereum/go-ethereum/common"
"math/big"
)

type BindingsCall struct {
DestChainId uint64

Check warning on line 9 in solver/app/bindings.go

View workflow job for this annotation

GitHub Actions / go-lint / golangci

var-naming: struct field DestChainId should be DestChainID (revive)
Value *big.Int
Address common.Address
Data []byte
}

type BindingsDeposit struct {
Amount *big.Int
Token common.Address
IsNative bool
}

type BindingsEventRequested struct {
ID reqID
From common.Address
Call BindingsCall
Deposits []BindingsDeposit

Height uint64
}

type BindingsEventAccepted struct {
ID reqID
By common.Address
}

type BindingsEventRejected struct {
ID reqID
By common.Address
}

type BindingsEventReverted struct {
ID reqID
}

type BindingsEventFulfilled struct {
ID reqID
}

type BindingsEventClaimed struct {
ID reqID
}

var (
BindingsEventRequestedTopic common.Hash
BindingsEventAcceptedTopic common.Hash
BindingsEventRejectedTopic common.Hash
BindingsEventRevertedTopic common.Hash
BindingsEventFulfilledTopic common.Hash
BindingsEventClaimedTopic common.Hash
)
88 changes: 88 additions & 0 deletions solver/app/parsers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package solver

import (
"context"
"github.com/ethereum/go-ethereum/core/types"
)

func parseRequestedEvent(log types.Log) (reqID, eventVisitor, error) {

Check warning on line 8 in solver/app/parsers.go

View workflow job for this annotation

GitHub Actions / go-lint / golangci

unused-parameter: parameter 'log' seems to be unused, consider removing or renaming it as _ (revive)
var e BindingsEventRequested
// TODO(corver): use bindings to parse log into bindings type.

// Requested triggers logic to either accepted or rejected
visistor := func(ctx context.Context, f *reactor, chainID uint64) (action, error) {
return f.ProcessRequested(ctx, chainID, e)
}

return e.ID, visistor, nil
}

func parseAcceptedEvent(log types.Log) (reqID, eventVisitor, error) {

Check warning on line 20 in solver/app/parsers.go

View workflow job for this annotation

GitHub Actions / go-lint / golangci

unused-parameter: parameter 'log' seems to be unused, consider removing or renaming it as _ (revive)
var e BindingsEventAccepted
// TODO(corver): use bindings to parse log into bindings type.

// Accepted directly maps to submit.
visistor := func(context.Context, *reactor, uint64) (action, error) {
return action{
Type: actionTypeSubmit,
}, nil
}

return e.ID, visistor, nil
}

func parseRejectedEvent(log types.Log) (reqID, eventVisitor, error) {

Check warning on line 34 in solver/app/parsers.go

View workflow job for this annotation

GitHub Actions / go-lint / golangci

unused-parameter: parameter 'log' seems to be unused, consider removing or renaming it as _ (revive)
var e BindingsEventRejected
// TODO(corver): use bindings to parse log into bindings type.

// Rejected triggers no transition.
visistor := func(context.Context, *reactor, uint64) (action, error) {
return action{
Type: actionTypeNone,
}, nil
}

return e.ID, visistor, nil
}

func parseRevertedEvent(log types.Log) (reqID, eventVisitor, error) {
var e BindingsEventReverted
// TODO(corver): use bindings to parse log into bindings type.

// Reverted triggers no transition.
visistor := func(context.Context, *reactor, uint64) (action, error) {
return action{
Type: actionTypeNone,
}, nil
}

return e.ID, visistor, nil
}

func parseFulfilledEvent(log types.Log) (reqID, eventVisitor, error) {
var e BindingsEventFulfilled
// TODO(corver): use bindings to parse log into bindings type.

// Fulfilled triggers claim action directly.
visistor := func(context.Context, *reactor, uint64) (action, error) {
return action{
Type: actionTypeClaim,
}, nil
}

return e.ID, visistor, nil
}

func parseClaimedEvent(log types.Log) (reqID, eventVisitor, error) {
var e BindingsEventClaimed
// TODO(corver): use bindings to parse log into bindings type.

// Claimed triggers no transition.
visistor := func(context.Context, *reactor, uint64) (action, error) {
return action{
Type: actionTypeNone,
}, nil
}

return e.ID, visistor, nil
}
151 changes: 151 additions & 0 deletions solver/app/reactor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package solver

import (
"context"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/omni-network/omni/lib/errors"
"github.com/omni-network/omni/lib/log"
"sync"
)

type reqID common.Hash

type eventVisitor func(ctx context.Context, r *reactor, chainID uint64) (action, error)

type action struct {
Type actionType
RejectReason string
}

type actionType int32
type eventType int32

const (
actionTypeNone actionType = 0
actionTypeAccept actionType = 1
actionTypeReject actionType = 2
actionTypeSubmit actionType = 3
actionTypeClaim actionType = 4

eventTypeRequested eventType = 1
eventTypeReverted eventType = 2
eventTypeAccepted eventType = 3
eventTypeRejected eventType = 4
eventTypeSubmitted eventType = 5
eventTypeFulfilled eventType = 6
eventTypeClaimed eventType = 7
)

type event struct {
Type eventType
Parse func(log types.Log) (reqID, eventVisitor, error)
}

var eventsByTopic = map[common.Hash]event{
BindingsEventRequestedTopic: {
Type: eventTypeRequested,
Parse: parseRequestedEvent,
},
BindingsEventAcceptedTopic: {
Type: eventTypeAccepted,
Parse: parseAcceptedEvent,
},
BindingsEventRejectedTopic: {
Type: eventTypeRejected,
Parse: parseRejectedEvent,
},
BindingsEventRevertedTopic: {
Type: eventTypeReverted,
Parse: parseRevertedEvent,
},
BindingsEventFulfilledTopic: {
Type: eventTypeFulfilled,
Parse: parseFulfilledEvent,
},
BindingsEventClaimedTopic: {
Type: eventTypeClaimed,
Parse: parseClaimedEvent,
},
}

type reactor struct {
mu sync.Mutex
}

// ProcessEvents is the callback provided to xchain.Provider::StreamEventLogs filtering all inbox contract events.
func (r *reactor) ProcessEvents(ctx context.Context, chainID uint64, _ uint64, elogs []types.Log) error {

Check warning on line 77 in solver/app/reactor.go

View workflow job for this annotation

GitHub Actions / go-lint / golangci

empty-lines: extra empty line at the end of a block (revive)
for _, elog := range elogs {
event, ok := eventsByTopic[elog.Topics[0]]
if !ok {
return errors.New("unknown event [BUG]")
}

reqID, visit, err := event.Parse(elog)
if err != nil {
return errors.Wrap(err, "parse event")
}

ctx := log.WithCtx(ctx, "req_id", reqID)

current, _, err := r.getCurrentStatus(ctx, chainID, reqID)
if err != nil {
return errors.Wrap(err, "current status")
} else if event.Type != current {
log.Warn(ctx, "Ignoring mismatching old event", nil, "actual", current, "event", event.Type)
continue
}

act, err := visit(ctx, r, chainID)
if err != nil {
return errors.Wrap(err, "visit")
}

switch act.Type {
case actionTypeAccept:
if err := r.accept(ctx, chainID, reqID); err != nil {
return errors.Wrap(err, "accept")
}
case actionTypeReject:
if err := r.reject(ctx, chainID, reqID, act.RejectReason); err != nil {
return errors.Wrap(err, "reject")
}
case actionTypeSubmit:
if err := r.submit(ctx, chainID, reqID); err != nil {
return errors.Wrap(err, "submit")
}
case actionTypeClaim:
if err := r.claim(ctx, chainID, reqID); err != nil {
return errors.Wrap(err, "claim")
}
}
}

return nil

}

// ProcessRequested return either a reject or accept action for the provided requested event.
func (r *reactor) ProcessRequested(ctx context.Context, chainID uint64, requestedEvent BindingsEventRequested) (action, error) {
if reason, reject, err := r.shouldReject(ctx, chainID, requestedEvent); err != nil {
return action{}, err
} else if reject {
return action{
Type: actionTypeReject,
RejectReason: reason,
}, nil
}

return action{
Type: actionTypeAccept,
}, nil
}

// shouldReject returns a reject reason or false or an error.
func (r *reactor) shouldReject(ctx context.Context, chainID uint64, requestedEvent BindingsEventRequested) (string, bool, error) {

Check warning on line 145 in solver/app/reactor.go

View workflow job for this annotation

GitHub Actions / go-lint / golangci

unused-receiver: method receiver 'r' is not referenced in method's body, consider removing or renaming it as _ (revive)
return "", false, nil
}

func (r *reactor) getCurrentStatus(ctx context.Context, chainID uint64, id reqID) (eventType, bool, error) {

Check warning on line 149 in solver/app/reactor.go

View workflow job for this annotation

GitHub Actions / go-lint / golangci

unused-receiver: method receiver 'r' is not referenced in method's body, consider removing or renaming it as _ (revive)
return 0, true, nil
}

0 comments on commit 443677d

Please sign in to comment.