Skip to content

Commit

Permalink
wip process proof of work
Browse files Browse the repository at this point in the history
sending request for reward at end of tx
Gil committed Mar 24, 2022
1 parent 2c8f2c8 commit c1dfa2d
Showing 8 changed files with 228 additions and 93 deletions.
3 changes: 2 additions & 1 deletion proto/servicer/tx.proto
Original file line number Diff line number Diff line change
@@ -43,7 +43,8 @@ message MsgUnstakeServicerResponse {
}

message MsgProofOfWork {
repeated RelayRequest relays = 1;
string creator = 1;
repeated RelayRequest relays = 2;
}

message MsgProofOfWorkResponse {
9 changes: 8 additions & 1 deletion relayer/cmd/relayer/main.go
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ import (

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"

"github.com/lavanet/lava/app"
@@ -40,6 +41,12 @@ func main() {
return err
}

//
// TODO: there has to be a better way to send txs
// (cosmosclient was a fail)
clientCtx.SkipConfirm = true
txFactory := tx.NewFactoryCLI(clientCtx, cmd.Flags()).WithChainID("lava")

port, err := strconv.Atoi(args[1])
if err != nil {
return err
@@ -52,7 +59,7 @@ func main() {

listenAddr := fmt.Sprintf("%s:%d", args[0], port)
ctx := context.Background()
relayer.Server(ctx, clientCtx, listenAddr, args[2], uint64(specId))
relayer.Server(ctx, clientCtx, txFactory, listenAddr, args[2], uint64(specId))

return nil
},
48 changes: 38 additions & 10 deletions relayer/server.go
Original file line number Diff line number Diff line change
@@ -7,6 +7,8 @@ import (
"fmt"
"log"
"net"
"os"
"os/signal"
"sync"
"time"

@@ -27,6 +29,7 @@ var (
g_sessions_mutex sync.Mutex
g_sentry *Sentry
g_serverSpecId uint64
g_txFactory tx.Factory
)

type RelaySession struct {
@@ -69,21 +72,29 @@ type jsonrpcMessage struct {
Result json.RawMessage `json:"result,omitempty"`
}

func askForRewards(sess *RelaySession, sessionId uint64) {
func askForRewards() {
log.Println("askForRewards")

//
// TODO: send reward properly (use sess.Proof)
//
msg := servicertypes.NewMsgProofOfWork()
err := tx.BroadcastTx(g_sentry.ClientCtx, tx.Factory{}, msg)
if err != nil {
log.Println(err)
g_sessions_mutex.Lock()
defer g_sessions_mutex.Unlock()

relays := []*servicertypes.RelayRequest{}
for _, userSessions := range g_sessions {
for _, sess := range userSessions {
relays = append(relays, sess.Proof)
}
}

msg := servicertypes.NewMsgProofOfWork(g_sentry.acc, relays)
log.Println("msg", msg)
err := tx.GenerateOrBroadcastTxWithFactory(g_sentry.ClientCtx, g_txFactory, msg)
if err != nil {
log.Println("GenerateOrBroadcastTxWithFactory", err)
}
}

func getRelayUser(in *servicertypes.RelayRequest) (bytes.HexBytes, error) {
pubKey, err := recoverPubKeyFromRelay(in)
pubKey, err := RecoverPubKeyFromRelay(in)
if err != nil {
return nil, err
}
@@ -237,10 +248,21 @@ func (s *relayServer) Relay(ctx context.Context, in *servicertypes.RelayRequest)
func Server(
ctx context.Context,
clientCtx client.Context,
txFactory tx.Factory,
listenAddr string,
nodeUrl string,
specId uint64,
) {
//
// ctrl+c
ctx, cancel := context.WithCancel(ctx)
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, os.Interrupt)
defer func() {
signal.Stop(signalChan)
cancel()
}()

//
// Start sentry
sentry := NewSentry(clientCtx, specId, false)
@@ -255,6 +277,7 @@ func Server(
g_sentry = sentry
g_sessions = map[string]map[uint64]*RelaySession{}
g_serverSpecId = specId
g_txFactory = txFactory

//
// Info
@@ -293,8 +316,12 @@ func Server(
select {
case <-ctx.Done():
log.Println("server ctx.Done")
s.Stop()
case <-signalChan:
log.Println("signalChan")
}

cancel()
s.Stop()
}()

Server := &relayServer{}
@@ -305,4 +332,5 @@ func Server(
log.Fatalf("failed to serve: %v", err)
}

askForRewards()
}
2 changes: 1 addition & 1 deletion relayer/sigs.go
Original file line number Diff line number Diff line change
@@ -69,7 +69,7 @@ func recoverPubKey(sig []byte, msgHash []byte) (secp256k1.PubKey, error) {
return (secp256k1.PubKey)(pk), nil
}

func recoverPubKeyFromRelay(in *servicertypes.RelayRequest) (secp256k1.PubKey, error) {
func RecoverPubKeyFromRelay(in *servicertypes.RelayRequest) (secp256k1.PubKey, error) {
tmp := in.Sig
in.Sig = []byte{}
hash := hashMsg([]byte(in.String()))
5 changes: 4 additions & 1 deletion x/servicer/client/cli/tx_proof_of_work.go
Original file line number Diff line number Diff line change
@@ -23,7 +23,10 @@ func CmdProofOfWork() *cobra.Command {
return err
}

msg := types.NewMsgProofOfWork()
msg := types.NewMsgProofOfWork(
clientCtx.GetFromAddress().String(),
[]*types.RelayRequest{},
)
if err := msg.ValidateBasic(); err != nil {
return err
}
112 changes: 72 additions & 40 deletions x/servicer/keeper/msg_server_proof_of_work.go
Original file line number Diff line number Diff line change
@@ -2,57 +2,89 @@ package keeper

import (
"context"
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/lavanet/lava/relayer"
"github.com/lavanet/lava/x/servicer/types"
)

func (k msgServer) ProofOfWork(goCtx context.Context, msg *types.MsgProofOfWork) (*types.MsgProofOfWorkResponse, error) {
/*ctx := sdk.UnwrapSDKContext(goCtx)
ctx := sdk.UnwrapSDKContext(goCtx)

clientRequestRaw := msg.ClientRequest
clientRequest, err := clientRequestRaw.ParseData(ctx)
creator, err := sdk.AccAddressFromBech32(msg.Creator)
if err != nil {
return nil, fmt.Errorf("error on proof of work, can't verify client message: %s", err)
return nil, err
}
foundAndActive, _ := k.Keeper.specKeeper.IsSpecIDFoundAndActive(ctx, uint64(clientRequest.Spec_id))
if !foundAndActive {
return nil, fmt.Errorf("error on proof of work, spec specified: %d is inactive", clientRequest.Spec_id)
}
clientAddr, err := sdk.AccAddressFromBech32(clientRequest.ClientSig)
if err != nil {
return nil, fmt.Errorf("error on proof of work, invalid client address: %s", err)
}
//TODO: validate CU requested is valid for the user and not too big, this requires the user module
//TODO: validate the user request only holds supported apis
//TODO: get the pairing for the block of work and not the current one
_, possibleServicerAddresses, err := k.Keeper.GetPairingForClient(ctx, uint64(clientRequest.Spec_id), clientAddr)
if err != nil {
return nil, fmt.Errorf("error on pairing for addresses : %s and %s, err: %s", clientAddr, msg.Creator, err)
}
for _, possibleAddr := range possibleServicerAddresses {
servicerAddr, err := sdk.AccAddressFromBech32(msg.Creator)

for _, relay := range msg.Relays {

pubKey, err := relayer.RecoverPubKeyFromRelay(relay)
if err != nil {
return nil, fmt.Errorf("error on proof of work, invalid servicer address: %s", err)
return nil, fmt.Errorf("error on proof of work, bad sig")
}
if possibleAddr.Equals(servicerAddr) {
//pairing is possible, we can pay servicer for work
amountToMintForServicerWork := sdk.NewIntFromUint64(uint64(float64(clientRequest.CU_sum) * k.Keeper.GetCoinsPerCU(ctx)))
amountToMintForServicerWorkCoins := sdk.Coin{Denom: "stake", Amount: amountToMintForServicerWork}
err := k.Keeper.bankKeeper.MintCoins(ctx, types.ModuleName, []sdk.Coin{amountToMintForServicerWorkCoins})
if err != nil {
panic(fmt.Sprintf("module failed to mint coins to give to servicer: %s", err))
}
err = k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, servicerAddr, []sdk.Coin{amountToMintForServicerWorkCoins})
if err != nil {
panic(fmt.Sprintf("failed to transfer minted new coins to servicer, %s account: %s", err, servicerAddr))
clientAddr, err := sdk.AccAddressFromHex(pubKey.Address().String())
if err != nil {
return nil, fmt.Errorf("error on proof of work, bad user address")
}
servicerAddr := (sdk.AccAddress)(relay.Servicer)
if !servicerAddr.Equals(creator) {
return nil, fmt.Errorf("error on proof of work, servicerAddr != creator")
}

//
// TODO: is this correct? spec could be disabled after the fact
ok, _ := k.Keeper.specKeeper.IsSpecIDFoundAndActive(ctx, uint64(relay.SpecId))
if !ok {
return nil, fmt.Errorf("error on proof of work, spec specified: %d is inactive", relay.SpecId)
}

//
//TODO: validate CU requested is valid for the user and not too big, this requires the user module
//

//
//TODO: validate the user request only holds supported apis
// impossible atm; we do not know what apis user used

//
//TODO: get the pairing for the block of work and not the current one
_, servicers, err := k.Keeper.GetPairingForClient(ctx, uint64(relay.SpecId), clientAddr)
if err != nil {
return nil, fmt.Errorf("error on pairing for addresses : %s and %s, err: %s", clientAddr, msg.Creator, err)
}

//
// Find pairing, reward servicer, burn user tokens
for _, servicer := range servicers {

if servicer.Equals(servicerAddr) {
reward := sdk.NewIntFromUint64(uint64(float64(relay.CuSum) * k.Keeper.GetCoinsPerCU(ctx)))
rewardCoins := sdk.Coins{sdk.Coin{Denom: "stake", Amount: reward}}

//
// Mint to module
err := k.Keeper.bankKeeper.MintCoins(ctx, types.ModuleName, rewardCoins)
if err != nil {
panic(fmt.Sprintf("module failed to mint coins to give to servicer: %s", err))
}
//
// Send to servicer
err = k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, servicerAddr, rewardCoins)
if err != nil {
panic(fmt.Sprintf("failed to transfer minted new coins to servicer, %s account: %s", err, servicerAddr))
}

// TODO: add param to burn client, and add code for that
//k.Keeper.GetBurnClientFactor(ctx)
amountToBurnClient := sdk.NewIntFromUint64(uint64(float64(relay.CuSum) * 0))
//need client Keeper and add a function BurnFromStake
_ = amountToBurnClient

break
}
// TODO: add param to burn client, and add code for that
//k.Keeper.GetBurnClientFactor(ctx)
amountToBurnClient := sdk.NewIntFromUint64(uint64(float64(clientRequest.CU_sum) * 0))
//need client Keeper and add a function BurnFromStake
_ = amountToBurnClient
break
}
}*/
}

return &types.MsgProofOfWorkResponse{}, nil
}
18 changes: 15 additions & 3 deletions x/servicer/types/message_proof_of_work.go
Original file line number Diff line number Diff line change
@@ -2,14 +2,18 @@ package types

import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)

const TypeMsgProofOfWork = "proof_of_work"

var _ sdk.Msg = &MsgProofOfWork{}

func NewMsgProofOfWork() *MsgProofOfWork {
return &MsgProofOfWork{}
func NewMsgProofOfWork(creator string, relays []*RelayRequest) *MsgProofOfWork {
return &MsgProofOfWork{
Creator: creator,
Relays: relays,
}
}

func (msg *MsgProofOfWork) Route() string {
@@ -21,7 +25,11 @@ func (msg *MsgProofOfWork) Type() string {
}

func (msg *MsgProofOfWork) GetSigners() []sdk.AccAddress {
return []sdk.AccAddress{}
creator, err := sdk.AccAddressFromBech32(msg.Creator)
if err != nil {
panic(err)
}
return []sdk.AccAddress{creator}
}

func (msg *MsgProofOfWork) GetSignBytes() []byte {
@@ -30,5 +38,9 @@ func (msg *MsgProofOfWork) GetSignBytes() []byte {
}

func (msg *MsgProofOfWork) ValidateBasic() error {
_, err := sdk.AccAddressFromBech32(msg.Creator)
if err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err)
}
return nil
}
124 changes: 88 additions & 36 deletions x/servicer/types/tx.pb.go

0 comments on commit c1dfa2d

Please sign in to comment.