Skip to content

Commit

Permalink
added proof of work code, and stub pairing function
Browse files Browse the repository at this point in the history
  • Loading branch information
omerlavanet committed Mar 16, 2022
1 parent 75d674e commit 61f5be6
Show file tree
Hide file tree
Showing 12 changed files with 182 additions and 44 deletions.
32 changes: 16 additions & 16 deletions vue/src/store/generated/lavanet/lava/lavanet.lava.servicer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -317,37 +317,37 @@ export default {
throw new SpVuexError('QueryClient:QueryUnstakingServicersAllSpecsAll', 'API Node Unavailable. Could not perform query: ' + e.message);
}
},
async sendMsgStakeServicer({ rootGetters }, { value, fee = [], memo = '' }) {
async sendMsgUnstakeServicer({ rootGetters }, { value, fee = [], memo = '' }) {
try {
const txClient = await initTxClient(rootGetters);
const msg = await txClient.msgStakeServicer(value);
const msg = await txClient.msgUnstakeServicer(value);
const result = await txClient.signAndBroadcast([msg], { fee: { amount: fee,
gas: "200000" }, memo });
return result;
}
catch (e) {
if (e == MissingWalletError) {
throw new SpVuexError('TxClient:MsgStakeServicer:Init', 'Could not initialize signing client. Wallet is required.');
throw new SpVuexError('TxClient:MsgUnstakeServicer:Init', 'Could not initialize signing client. Wallet is required.');
}
else {
throw new SpVuexError('TxClient:MsgStakeServicer:Send', 'Could not broadcast Tx: ' + e.message);
throw new SpVuexError('TxClient:MsgUnstakeServicer:Send', 'Could not broadcast Tx: ' + e.message);
}
}
},
async sendMsgUnstakeServicer({ rootGetters }, { value, fee = [], memo = '' }) {
async sendMsgStakeServicer({ rootGetters }, { value, fee = [], memo = '' }) {
try {
const txClient = await initTxClient(rootGetters);
const msg = await txClient.msgUnstakeServicer(value);
const msg = await txClient.msgStakeServicer(value);
const result = await txClient.signAndBroadcast([msg], { fee: { amount: fee,
gas: "200000" }, memo });
return result;
}
catch (e) {
if (e == MissingWalletError) {
throw new SpVuexError('TxClient:MsgUnstakeServicer:Init', 'Could not initialize signing client. Wallet is required.');
throw new SpVuexError('TxClient:MsgStakeServicer:Init', 'Could not initialize signing client. Wallet is required.');
}
else {
throw new SpVuexError('TxClient:MsgUnstakeServicer:Send', 'Could not broadcast Tx: ' + e.message);
throw new SpVuexError('TxClient:MsgStakeServicer:Send', 'Could not broadcast Tx: ' + e.message);
}
}
},
Expand All @@ -368,33 +368,33 @@ export default {
}
}
},
async MsgStakeServicer({ rootGetters }, { value }) {
async MsgUnstakeServicer({ rootGetters }, { value }) {
try {
const txClient = await initTxClient(rootGetters);
const msg = await txClient.msgStakeServicer(value);
const msg = await txClient.msgUnstakeServicer(value);
return msg;
}
catch (e) {
if (e == MissingWalletError) {
throw new SpVuexError('TxClient:MsgStakeServicer:Init', 'Could not initialize signing client. Wallet is required.');
throw new SpVuexError('TxClient:MsgUnstakeServicer:Init', 'Could not initialize signing client. Wallet is required.');
}
else {
throw new SpVuexError('TxClient:MsgStakeServicer:Create', 'Could not create message: ' + e.message);
throw new SpVuexError('TxClient:MsgUnstakeServicer:Create', 'Could not create message: ' + e.message);
}
}
},
async MsgUnstakeServicer({ rootGetters }, { value }) {
async MsgStakeServicer({ rootGetters }, { value }) {
try {
const txClient = await initTxClient(rootGetters);
const msg = await txClient.msgUnstakeServicer(value);
const msg = await txClient.msgStakeServicer(value);
return msg;
}
catch (e) {
if (e == MissingWalletError) {
throw new SpVuexError('TxClient:MsgUnstakeServicer:Init', 'Could not initialize signing client. Wallet is required.');
throw new SpVuexError('TxClient:MsgStakeServicer:Init', 'Could not initialize signing client. Wallet is required.');
}
else {
throw new SpVuexError('TxClient:MsgUnstakeServicer:Create', 'Could not create message: ' + e.message);
throw new SpVuexError('TxClient:MsgStakeServicer:Create', 'Could not create message: ' + e.message);
}
}
},
Expand Down
32 changes: 16 additions & 16 deletions vue/src/store/generated/lavanet/lava/lavanet.lava.servicer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,33 +401,33 @@ export default {
},


async sendMsgStakeServicer({ rootGetters }, { value, fee = [], memo = '' }) {
async sendMsgUnstakeServicer({ rootGetters }, { value, fee = [], memo = '' }) {
try {
const txClient=await initTxClient(rootGetters)
const msg = await txClient.msgStakeServicer(value)
const msg = await txClient.msgUnstakeServicer(value)
const result = await txClient.signAndBroadcast([msg], {fee: { amount: fee,
gas: "200000" }, memo})
return result
} catch (e) {
if (e == MissingWalletError) {
throw new SpVuexError('TxClient:MsgStakeServicer:Init', 'Could not initialize signing client. Wallet is required.')
throw new SpVuexError('TxClient:MsgUnstakeServicer:Init', 'Could not initialize signing client. Wallet is required.')
}else{
throw new SpVuexError('TxClient:MsgStakeServicer:Send', 'Could not broadcast Tx: '+ e.message)
throw new SpVuexError('TxClient:MsgUnstakeServicer:Send', 'Could not broadcast Tx: '+ e.message)
}
}
},
async sendMsgUnstakeServicer({ rootGetters }, { value, fee = [], memo = '' }) {
async sendMsgStakeServicer({ rootGetters }, { value, fee = [], memo = '' }) {
try {
const txClient=await initTxClient(rootGetters)
const msg = await txClient.msgUnstakeServicer(value)
const msg = await txClient.msgStakeServicer(value)
const result = await txClient.signAndBroadcast([msg], {fee: { amount: fee,
gas: "200000" }, memo})
return result
} catch (e) {
if (e == MissingWalletError) {
throw new SpVuexError('TxClient:MsgUnstakeServicer:Init', 'Could not initialize signing client. Wallet is required.')
throw new SpVuexError('TxClient:MsgStakeServicer:Init', 'Could not initialize signing client. Wallet is required.')
}else{
throw new SpVuexError('TxClient:MsgUnstakeServicer:Send', 'Could not broadcast Tx: '+ e.message)
throw new SpVuexError('TxClient:MsgStakeServicer:Send', 'Could not broadcast Tx: '+ e.message)
}
}
},
Expand All @@ -447,30 +447,30 @@ export default {
}
},

async MsgStakeServicer({ rootGetters }, { value }) {
async MsgUnstakeServicer({ rootGetters }, { value }) {
try {
const txClient=await initTxClient(rootGetters)
const msg = await txClient.msgStakeServicer(value)
const msg = await txClient.msgUnstakeServicer(value)
return msg
} catch (e) {
if (e == MissingWalletError) {
throw new SpVuexError('TxClient:MsgStakeServicer:Init', 'Could not initialize signing client. Wallet is required.')
throw new SpVuexError('TxClient:MsgUnstakeServicer:Init', 'Could not initialize signing client. Wallet is required.')
}else{
throw new SpVuexError('TxClient:MsgStakeServicer:Create', 'Could not create message: ' + e.message)
throw new SpVuexError('TxClient:MsgUnstakeServicer:Create', 'Could not create message: ' + e.message)

}
}
},
async MsgUnstakeServicer({ rootGetters }, { value }) {
async MsgStakeServicer({ rootGetters }, { value }) {
try {
const txClient=await initTxClient(rootGetters)
const msg = await txClient.msgUnstakeServicer(value)
const msg = await txClient.msgStakeServicer(value)
return msg
} catch (e) {
if (e == MissingWalletError) {
throw new SpVuexError('TxClient:MsgUnstakeServicer:Init', 'Could not initialize signing client. Wallet is required.')
throw new SpVuexError('TxClient:MsgStakeServicer:Init', 'Could not initialize signing client. Wallet is required.')
}else{
throw new SpVuexError('TxClient:MsgUnstakeServicer:Create', 'Could not create message: ' + e.message)
throw new SpVuexError('TxClient:MsgStakeServicer:Create', 'Could not create message: ' + e.message)

}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { StdFee } from "@cosmjs/launchpad";
import { Registry, OfflineSigner, EncodeObject } from "@cosmjs/proto-signing";
import { Api } from "./rest";
import { MsgStakeServicer } from "./types/servicer/tx";
import { MsgUnstakeServicer } from "./types/servicer/tx";
import { MsgStakeServicer } from "./types/servicer/tx";
import { MsgProofOfWork } from "./types/servicer/tx";
export declare const MissingWalletError: Error;
export declare const registry: Registry;
Expand All @@ -15,8 +15,8 @@ interface SignAndBroadcastOptions {
}
declare const txClient: (wallet: OfflineSigner, { addr: addr }?: TxClientOptions) => Promise<{
signAndBroadcast: (msgs: EncodeObject[], { fee, memo }?: SignAndBroadcastOptions) => any;
msgStakeServicer: (data: MsgStakeServicer) => EncodeObject;
msgUnstakeServicer: (data: MsgUnstakeServicer) => EncodeObject;
msgStakeServicer: (data: MsgStakeServicer) => EncodeObject;
msgProofOfWork: (data: MsgProofOfWork) => EncodeObject;
}>;
interface QueryClientOptions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
import { SigningStargateClient } from "@cosmjs/stargate";
import { Registry } from "@cosmjs/proto-signing";
import { Api } from "./rest";
import { MsgStakeServicer } from "./types/servicer/tx";
import { MsgUnstakeServicer } from "./types/servicer/tx";
import { MsgStakeServicer } from "./types/servicer/tx";
import { MsgProofOfWork } from "./types/servicer/tx";
const types = [
["/lavanet.lava.servicer.MsgStakeServicer", MsgStakeServicer],
["/lavanet.lava.servicer.MsgUnstakeServicer", MsgUnstakeServicer],
["/lavanet.lava.servicer.MsgStakeServicer", MsgStakeServicer],
["/lavanet.lava.servicer.MsgProofOfWork", MsgProofOfWork],
];
export const MissingWalletError = new Error("wallet is required");
Expand All @@ -29,8 +29,8 @@ const txClient = async (wallet, { addr: addr } = { addr: "http://localhost:26657
const { address } = (await wallet.getAccounts())[0];
return {
signAndBroadcast: (msgs, { fee, memo } = { fee: defaultFee, memo: "" }) => client.signAndBroadcast(address, msgs, fee, memo),
msgStakeServicer: (data) => ({ typeUrl: "/lavanet.lava.servicer.MsgStakeServicer", value: MsgStakeServicer.fromPartial(data) }),
msgUnstakeServicer: (data) => ({ typeUrl: "/lavanet.lava.servicer.MsgUnstakeServicer", value: MsgUnstakeServicer.fromPartial(data) }),
msgStakeServicer: (data) => ({ typeUrl: "/lavanet.lava.servicer.MsgStakeServicer", value: MsgStakeServicer.fromPartial(data) }),
msgProofOfWork: (data) => ({ typeUrl: "/lavanet.lava.servicer.MsgProofOfWork", value: MsgProofOfWork.fromPartial(data) }),
};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import { StdFee } from "@cosmjs/launchpad";
import { SigningStargateClient } from "@cosmjs/stargate";
import { Registry, OfflineSigner, EncodeObject, DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";
import { Api } from "./rest";
import { MsgStakeServicer } from "./types/servicer/tx";
import { MsgUnstakeServicer } from "./types/servicer/tx";
import { MsgStakeServicer } from "./types/servicer/tx";
import { MsgProofOfWork } from "./types/servicer/tx";


const types = [
["/lavanet.lava.servicer.MsgStakeServicer", MsgStakeServicer],
["/lavanet.lava.servicer.MsgUnstakeServicer", MsgUnstakeServicer],
["/lavanet.lava.servicer.MsgStakeServicer", MsgStakeServicer],
["/lavanet.lava.servicer.MsgProofOfWork", MsgProofOfWork],

];
Expand Down Expand Up @@ -45,8 +45,8 @@ const txClient = async (wallet: OfflineSigner, { addr: addr }: TxClientOptions =

return {
signAndBroadcast: (msgs: EncodeObject[], { fee, memo }: SignAndBroadcastOptions = {fee: defaultFee, memo: ""}) => client.signAndBroadcast(address, msgs, fee,memo),
msgStakeServicer: (data: MsgStakeServicer): EncodeObject => ({ typeUrl: "/lavanet.lava.servicer.MsgStakeServicer", value: MsgStakeServicer.fromPartial( data ) }),
msgUnstakeServicer: (data: MsgUnstakeServicer): EncodeObject => ({ typeUrl: "/lavanet.lava.servicer.MsgUnstakeServicer", value: MsgUnstakeServicer.fromPartial( data ) }),
msgStakeServicer: (data: MsgStakeServicer): EncodeObject => ({ typeUrl: "/lavanet.lava.servicer.MsgStakeServicer", value: MsgStakeServicer.fromPartial( data ) }),
msgProofOfWork: (data: MsgProofOfWork): EncodeObject => ({ typeUrl: "/lavanet.lava.servicer.MsgProofOfWork", value: MsgProofOfWork.fromPartial( data ) }),

};
Expand Down
48 changes: 45 additions & 3 deletions x/servicer/keeper/msg_server_proof_of_work.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package keeper

import (
"context"
"errors"
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/lavanet/lava/x/servicer/types"
Expand All @@ -10,8 +12,48 @@ import (
func (k msgServer) ProofOfWork(goCtx context.Context, msg *types.MsgProofOfWork) (*types.MsgProofOfWorkResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

// TODO: Handling the message
_ = ctx

clientRequestRaw := msg.ClientRequest
clientRequest, err := clientRequestRaw.ParseData(ctx)
if err != nil {
return nil, errors.New(fmt.Sprintf("error on proof of work, can't verify client message: %s", err))
}
foundAndActive, _ := k.Keeper.specKeeper.IsSpecIDFoundAndActive(ctx, uint64(clientRequest.Spec_id))
if !foundAndActive {
return nil, errors.New(fmt.Sprintf("error on proof of work, spec specified: %s is inactive", clientRequest.Spec_id))
}
clientAddr, err := sdk.AccAddressFromBech32(clientRequest.ClientSig)
if err != nil {
return nil, errors.New(fmt.Sprintf("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
possibleServicerAddresses, err := k.Keeper.GetPairingForClient(ctx, *msg.BlockOfWork, uint64(clientRequest.Spec_id), clientAddr)
if err != nil {
return nil, errors.New(fmt.Sprintf("error on pairing for addresses : %s and %s, err: %s", clientAddr, msg.Creator, err))
}
for _, possibleAddr := range possibleServicerAddresses {
servicerAddr, err := sdk.AccAddressFromBech32(msg.Creator)
if err != nil {
return nil, errors.New(fmt.Sprintf("error on proof of work, invalid servicer address: %s", err))
}
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))
}
// 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
}
36 changes: 36 additions & 0 deletions x/servicer/keeper/pairing.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package keeper

import (
"errors"
"fmt"

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

func (k Keeper) GetPairingForClient(ctx sdk.Context, block types.BlockNum, specID uint64, clientAddress sdk.AccAddress) ([]sdk.AccAddress, error) {
//TODO: client stake needs to be verified
spec, found := k.specKeeper.GetSpec(ctx, specID)
if !found {
return nil, errors.New(fmt.Sprintf("spec not found for id given: %s", specID))
}
specStakeStorage, found := k.GetSpecStakeStorage(ctx, spec.Name)
if !found {
return nil, errors.New(fmt.Sprintf("no specStakeStorage for spec name: %s", spec.Name))
}
stakedServicers := specStakeStorage.StakeStorage.Staked
return k.calculatePairingForClient(ctx, stakedServicers, block, clientAddress)
}

func (k Keeper) calculatePairingForClient(ctx sdk.Context, stakedServicers []types.StakeMap, block types.BlockNum, clientAddress sdk.AccAddress) (addrList []sdk.AccAddress, err error) {
//TODO: need to do the pairing function, right now i just return the staked servicers addresses
for _, stakeMap := range stakedServicers {
servicerAddress := stakeMap.Index
servicerAccAddr, err := sdk.AccAddressFromBech32(servicerAddress)
if err != nil {
panic(fmt.Sprintf("invalid servicer address saved in keeper %s", servicerAddress))
}
addrList = append(addrList, servicerAccAddr)
}
return addrList, nil
}
6 changes: 6 additions & 0 deletions x/servicer/keeper/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ func (k Keeper) CoinsPerCU(ctx sdk.Context) (res uint64) {
k.paramstore.Get(ctx, types.KeyCoinsPerCU, &res)
return
}
func (k Keeper) GetCoinsPerCU(ctx sdk.Context) (res float64) {
var val uint64
k.paramstore.Get(ctx, types.KeyCoinsPerCU, &val)
res = float64(val) / float64(types.PrecisionForCoinsPerCU)
return
}

// UnstakeHoldBlocks returns the UnstakeHoldBlocks param
func (k Keeper) UnstakeHoldBlocks(ctx sdk.Context) (res uint64) {
Expand Down
4 changes: 4 additions & 0 deletions x/servicer/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/types"
spectypes "github.com/lavanet/lava/x/spec/types"
)

type EvidenceKeeper interface {
Expand All @@ -22,9 +23,12 @@ type BankKeeper interface {
GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
MintCoins(ctx sdk.Context, moduleName string, amounts sdk.Coins) error
// Methods imported from bank should be defined here
}

type SpecKeeper interface {
IsSpecFoundAndActive(ctx sdk.Context, specName string) (bool, bool)
IsSpecIDFoundAndActive(ctx sdk.Context, id uint64) (bool, bool)
GetSpec(ctx sdk.Context, id uint64) (val spectypes.Spec, found bool)
}
2 changes: 2 additions & 0 deletions x/servicer/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (

var _ paramtypes.ParamSet = (*Params)(nil)

const PrecisionForCoinsPerCU uint64 = 1000000

var (
KeyMinStake = []byte("MinStake")
DefaultMinStake uint64 = 1000
Expand Down
Loading

0 comments on commit 61f5be6

Please sign in to comment.