Skip to content

Commit

Permalink
Finish voting logic
Browse files Browse the repository at this point in the history
  • Loading branch information
violog committed Dec 8, 2023
1 parent 6f145a3 commit 8d6ca8a
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 27 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
github.com/alecthomas/kingpin v2.2.6+incompatible
github.com/ethereum/go-ethereum v1.10.26
github.com/gogo/protobuf v1.3.3
github.com/rarimo/rarimo-core v1.0.7-0.20231206161857-c1f9b5f9a6f5
github.com/rarimo/rarimo-core v1.0.7-0.20231208125434-eaf4ddf6c070
github.com/rarimo/saver-grpc-lib v1.0.0
github.com/spf13/cast v1.5.1
github.com/tendermint/tendermint v0.34.27
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1206,6 +1206,8 @@ github.com/rarimo/cosmos-sdk v0.46.7 h1:jU2PiWzc+19SF02cXM0O0puKPeH1C6Q6t2lzJ9s1
github.com/rarimo/cosmos-sdk v0.46.7/go.mod h1:fqKqz39U5IlEFb4nbQ72951myztsDzFKKDtffYJ63nk=
github.com/rarimo/rarimo-core v1.0.7-0.20231206161857-c1f9b5f9a6f5 h1:/waQ2jEJ/ZUQVhpGTOBBvzxPqB5+yQlfjxOsIlVCEvw=
github.com/rarimo/rarimo-core v1.0.7-0.20231206161857-c1f9b5f9a6f5/go.mod h1:S8d3kZWPFuNsy7llrzUd8Rj92WSCrjSH2YEUD+2A+Ww=
github.com/rarimo/rarimo-core v1.0.7-0.20231208125434-eaf4ddf6c070 h1:gug/AW6noXk5m1yff/1u2CBz8UDSWRonZPhfPAdm04k=
github.com/rarimo/rarimo-core v1.0.7-0.20231208125434-eaf4ddf6c070/go.mod h1:auP3KgxaSwkOUrLWBifjnMbbSQTSBA9Y/gVgq1WU/B4=
github.com/rarimo/saver-grpc-lib v1.0.0 h1:MGUVjYg7unmodYczVsLqlqZNkT4CIgKqdo6aQtL1qdE=
github.com/rarimo/saver-grpc-lib v1.0.0/go.mod h1:DpugWK5B7Hi0bdC3MPe/9FD2zCxaRwsyykdwxtF1Zgg=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
Expand Down
113 changes: 87 additions & 26 deletions internal/services/voting/vote.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,72 @@ package voting

import (
"context"
"fmt"
"math/big"
"strconv"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common/hexutil"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/gogo/protobuf/proto"
"github.com/rarimo/evm-worldcoin-saver-svc/internal/config"
oracletypes "github.com/rarimo/rarimo-core/x/oraclemanager/types"
"github.com/rarimo/evm-worldcoin-saver-svc/pkg/worldid"
rarimocore "github.com/rarimo/rarimo-core/x/rarimocore/types"
"github.com/rarimo/saver-grpc-lib/voter"
"github.com/rarimo/saver-grpc-lib/voter/verifiers"
"gitlab.com/distributed_lab/logan/v3"
"gitlab.com/distributed_lab/logan/v3/errors"
)

type WorldCoinVerifier struct {
log *logan.Entry
oracleQueryClient oracletypes.QueryClient
type verifier struct {
log *logan.Entry
filter filterer
header headerGetter
chain string
}

var _ voter.Verifier = &WorldCoinVerifier{}
type filterer interface {
FilterTreeChanged(*bind.FilterOpts, []*big.Int, []uint8, []*big.Int) (*worldid.WorldIdTreeChangedIterator, error)
}

type headerGetter interface {
HeaderByNumber(context.Context, *big.Int) (*ethtypes.Header, error)
}

var _ voter.Verifier = &verifier{}

func NewWorldCoinVerifier(cfg config.Config) voter.Verifier {
filter, err := worldid.NewWorldIdFilterer(cfg.Ethereum().ContractAddr, cfg.Ethereum().RPCClient)
if err != nil {
panic(fmt.Errorf("failed to init TreeChanged event filterer for verifier: %w", err))
}

func NewWorldCoinVerifier(cfg config.Config) *WorldCoinVerifier {
return &WorldCoinVerifier{
log: cfg.Log(),
oracleQueryClient: oracletypes.NewQueryClient(cfg.Cosmos()),
return &verifier{
log: cfg.Log(),
filter: filter,
header: cfg.Ethereum().RPCClient,
chain: cfg.Ethereum().NetworkName,
}
}

func (s *WorldCoinVerifier) Verify(ctx context.Context, operation rarimocore.Operation) (rarimocore.VoteType, error) {
func (v *verifier) Verify(ctx context.Context, operation rarimocore.Operation) (rarimocore.VoteType, error) {
if operation.OperationType != rarimocore.OpType_WORLDCOIN_IDENTITY_TRANSFER {
s.log.Debugf("Voted NO: invalid operation type")
v.log.Debugf("Voted NO: invalid operation type")
return rarimocore.VoteType_NO, verifiers.ErrInvalidOperationType
}

var op rarimocore.WorldCoinIdentityTransfer
if err := proto.Unmarshal(operation.Details.Value, &op); err != nil {
s.log.Debugf("Voted NO: failed to unmarshal")
v.log.Debugf("Voted NO: failed to unmarshal")
return rarimocore.VoteType_NO, err
}

err := s.verify(ctx, op)
err := v.verify(ctx, op)
if err == nil {
return rarimocore.VoteType_YES, nil
}

s.log.WithError(err).Debugf("Voted NO: received an error from verifier")
v.log.WithError(err).Debugf("Voted NO: received an error from verifier")
switch errors.Cause(err) {
case verifiers.ErrUnsupportedNetwork:
return rarimocore.VoteType_NO, verifiers.ErrUnsupportedNetwork
Expand All @@ -55,24 +78,62 @@ func (s *WorldCoinVerifier) Verify(ctx context.Context, operation rarimocore.Ope
}
}

func (s *WorldCoinVerifier) verify(ctx context.Context, op rarimocore.WorldCoinIdentityTransfer) error {
// TODO. Get data from Ethereum, then compare with Rarimo op (current logic is wrong)
msg := oracletypes.MsgCreateWorldCoinIdentityTransferOp{
Contract: op.Contract,
Chain: op.Chain,
PrevState: op.PrevState,
State: op.State,
Timestamp: op.Timestamp,
func (v *verifier) verify(ctx context.Context, op rarimocore.WorldCoinIdentityTransfer) error {
evt, err := v.getEvent(ctx, op)
if err != nil {
return fmt.Errorf("failed to get event: %w", err)
}
// we can avoid the transfer and just use the op
resp, err := s.oracleQueryClient.WorldCoinIdentityTransfer(ctx, &oracletypes.QueryGetWorldCoinIdentityTransferRequest{Msg: msg})

num := new(big.Int).SetUint64(evt.Raw.BlockNumber)
header, err := v.header.HeaderByNumber(ctx, num)
if err != nil {
return errors.Wrap(err, "failed to fetch operation details from core")
return fmt.Errorf("failed to get block header by number from event: %w", err)
}

if !proto.Equal(&resp.Transfer, &op) {
if !proto.Equal(&op, opFromExternalData(evt, v.chain, header.Time)) {
return verifiers.ErrWrongOperationContent
}

return nil
}

func (v *verifier) getEvent(ctx context.Context, op rarimocore.WorldCoinIdentityTransfer) (*worldid.WorldIdTreeChanged, error) {
iter, err := v.filter.FilterTreeChanged(&bind.FilterOpts{
Context: ctx,
Start: op.BlockNumber,
End: &op.BlockNumber, // end block is inclusive
}, toBigIntFilter(op.PrevState), nil, toBigIntFilter(op.State))

if err != nil {
return nil, fmt.Errorf("failed to filter WorldID changed events: %w", err)
}
if !iter.Next() || iter.Event == nil {
return nil, errors.New("event not found")
}

res := *iter.Event
if iter.Next() {
return nil, errors.New("multiple events found for given block, preRoot and postRoot")
}

return &res, nil
}

func opFromExternalData(evt *worldid.WorldIdTreeChanged, chain string, timestamp uint64) *rarimocore.WorldCoinIdentityTransfer {
return &rarimocore.WorldCoinIdentityTransfer{
Contract: evt.Raw.Address.Hex(),
Chain: chain,
PrevState: hexutil.EncodeBig(evt.PreRoot),
State: hexutil.EncodeBig(evt.PostRoot),
Timestamp: strconv.FormatUint(timestamp, 10),
BlockNumber: evt.Raw.BlockNumber,
}
}

func toBigIntFilter(s string) []*big.Int {
b, ok := new(big.Int).SetString(s, 16)
if !ok {
return nil
}
return []*big.Int{b}
}

0 comments on commit 8d6ca8a

Please sign in to comment.