From 2cb0c36ca35c1f3524d0c5ad123fd9c3c7e588cd Mon Sep 17 00:00:00 2001 From: hacheigriega Date: Tue, 14 Jan 2025 05:33:57 -0500 Subject: [PATCH] WIP: data provider payout --- x/tally/keeper/endblock.go | 21 +++++++++--- x/tally/keeper/keeper.go | 4 ++- x/tally/keeper/payout.go | 53 +++++++++++++++++++++---------- x/tally/types/expected_keepers.go | 5 +++ 4 files changed, 60 insertions(+), 23 deletions(-) diff --git a/x/tally/keeper/endblock.go b/x/tally/keeper/endblock.go index 88a804fb..97c908ea 100644 --- a/x/tally/keeper/endblock.go +++ b/x/tally/keeper/endblock.go @@ -122,6 +122,7 @@ func (k Keeper) ProcessTallies(ctx sdk.Context, coreContract sdk.AccAddress) err if !ok { return fmt.Errorf("invalid gas price: %s", req.GasPrice) // TODO improve error handling } + // TODO also make sure gas price is not 0 _, tallyResults[i], distMsgs = k.FilterAndTally(ctx, req, params, gasPriceInt) dataResults[i].Result = tallyResults[i].Result @@ -240,14 +241,24 @@ func (k Keeper) FilterAndTally(ctx sdk.Context, req types.Request, params types. // Phase III: Calculate Payouts var distMsgs types.DistributionMessages if filterErr == nil || errors.Is(filterErr, types.ErrConsensusInError) { - var gasUsed uint64 - if req.ReplicationFactor == 1 || areGasReportsUniform(reveals) { - distMsgs.Messages, gasUsed = CalculateUniformPayouts(keys, reveals[0].GasUsed, req.ExecGasLimit, req.ReplicationFactor, gasPrice) + dataProviderDistMsgs, dataProviderGasUsed, err := k.CalculateDataProviderPayouts(ctx, result.ProxyPubKeys, gasPrice) + if err != nil { + // TODO error handling + } + + gasReports := make([]uint64, len(reveals)) + for i, reveal := range reveals { + gasReports[i] = reveal.GasUsed - dataProviderGasUsed + } + + var execGasUsed uint64 + if req.ReplicationFactor == 1 || areGasReportsUniform(gasReports) { + distMsgs.Messages, execGasUsed = CalculateUniformPayouts(keys, gasReports[0], req.ExecGasLimit, req.ReplicationFactor, gasPrice) } else { - distMsgs.Messages, gasUsed = CalculateDivergentPayouts(keys, reveals, req.ExecGasLimit, req.ReplicationFactor, gasPrice) + distMsgs.Messages, execGasUsed = CalculateDivergentPayouts(keys, gasReports, req.ExecGasLimit, req.ReplicationFactor, gasPrice) } distMsgs.RefundType = types.DistributionTypeExecutorReward // TODO double check - result.ExecGasUsed = gasUsed + result.ExecGasUsed = execGasUsed } // TODO: else pay committers? diff --git a/x/tally/keeper/keeper.go b/x/tally/keeper/keeper.go index d7cbb89a..9dcabd26 100644 --- a/x/tally/keeper/keeper.go +++ b/x/tally/keeper/keeper.go @@ -18,6 +18,7 @@ import ( type Keeper struct { wasmStorageKeeper types.WasmStorageKeeper batchingKeeper types.BatchingKeeper + dataProxyKeeper types.DataProxyKeeper wasmKeeper wasmtypes.ContractOpsKeeper wasmViewKeeper wasmtypes.ViewKeeper authority string @@ -26,12 +27,13 @@ type Keeper struct { params collections.Item[types.Params] } -func NewKeeper(cdc codec.BinaryCodec, storeService storetypes.KVStoreService, wsk types.WasmStorageKeeper, bk types.BatchingKeeper, wk wasmtypes.ContractOpsKeeper, wvk wasmtypes.ViewKeeper, authority string) Keeper { +func NewKeeper(cdc codec.BinaryCodec, storeService storetypes.KVStoreService, wsk types.WasmStorageKeeper, bk types.BatchingKeeper, dpk types.DataProxyKeeper, wk wasmtypes.ContractOpsKeeper, wvk wasmtypes.ViewKeeper, authority string) Keeper { sb := collections.NewSchemaBuilder(storeService) k := Keeper{ wasmStorageKeeper: wsk, batchingKeeper: bk, + dataProxyKeeper: dpk, wasmKeeper: wk, wasmViewKeeper: wvk, params: collections.NewItem(sb, types.ParamsPrefix, "params", codec.CollValue[types.Params](cdc)), diff --git a/x/tally/keeper/payout.go b/x/tally/keeper/payout.go index 7d0c7549..38b83973 100644 --- a/x/tally/keeper/payout.go +++ b/x/tally/keeper/payout.go @@ -1,6 +1,7 @@ package keeper import ( + "encoding/hex" "sort" "cosmossdk.io/math" @@ -10,8 +11,27 @@ import ( "github.com/sedaprotocol/seda-chain/x/tally/types" ) -// CalculateCommitterPayouts constructs distribution messages that -// pay the fixed gas cost for each commiter of a given data request. +// CalculateDataProviderPayouts returns payouts for the data providers and +// returns the the gas used by the data providers per executor. +func (k Keeper) CalculateDataProviderPayouts(ctx sdk.Context, proxyPubKeys []string, gasPrice math.Int) (types.DistributionMessages, uint64, error) { + gasUsed := math.NewInt(0) + for _, pubKey := range proxyPubKeys { + pubKeyBytes, err := hex.DecodeString(pubKey) + if err != nil { + return types.DistributionMessages{}, 0, err + } + proxyConfig, err := k.dataProxyKeeper.GetDataProxyConfig(ctx, pubKeyBytes) + if err != nil { + return types.DistributionMessages{}, 0, err + } + gasUsed = gasUsed.Add(proxyConfig.Fee.Amount.Quo(gasPrice)) + } + // TODO distMsgs? + return types.DistributionMessages{}, gasUsed.Uint64(), nil // TODO may panic +} + +// CalculateCommitterPayouts returns the fixed payouts for the committers of a +// given data request. func (k Keeper) CalculateCommitterPayouts(ctx sdk.Context, req types.Request) (types.DistributionMessages, error) { result := types.DistributionMessages{ Messages: []types.DistributionMessage{}, @@ -51,10 +71,10 @@ func (k Keeper) CalculateCommitterPayouts(ctx sdk.Context, req types.Request) (t } // CalculateUniformPayouts calculates payouts for the executors when their gas -// reports are uniformly at "gasUsed". It also returns the total execution gas +// reports are uniformly at "gasReport". It also returns the total execution gas // consumption. -func CalculateUniformPayouts(executors []string, gasUsed, execGasLimit uint64, replicationFactor uint16, gasPrice math.Int) ([]types.DistributionMessage, uint64) { - adjGasUsed := max(gasUsed, execGasLimit/uint64(replicationFactor)) +func CalculateUniformPayouts(executors []string, gasReport, execGasLimit uint64, replicationFactor uint16, gasPrice math.Int) ([]types.DistributionMessage, uint64) { + adjGasUsed := max(gasReport, execGasLimit/uint64(replicationFactor)) payout := gasPrice.Mul(math.NewIntFromUint64(adjGasUsed)) distMsgs := make([]types.DistributionMessage, len(executors)) @@ -72,16 +92,15 @@ func CalculateUniformPayouts(executors []string, gasUsed, execGasLimit uint64, r return distMsgs, adjGasUsed * uint64(replicationFactor) } -// CalculateDivergentPayouts calculates payouts for the executors of the given -// reveals when their gas reports are divergent. It also returns the total -// execution gas consumption. +// CalculateDivergentPayouts calculates payouts for the executors given their +// divergent gas reports. It also returns the total execution gas consumption. // It assumes that the i-th executor is the one who revealed the i-th reveal. -func CalculateDivergentPayouts(executors []string, reveals []types.RevealBody, execGasLimit uint64, replicationFactor uint16, gasPrice math.Int) ([]types.DistributionMessage, uint64) { - adjGasUsed := make([]uint64, len(reveals)) +func CalculateDivergentPayouts(executors []string, gasReports []uint64, execGasLimit uint64, replicationFactor uint16, gasPrice math.Int) ([]types.DistributionMessage, uint64) { + adjGasUsed := make([]uint64, len(gasReports)) var lowestGasUsed uint64 var lowestReporterIndex int - for i, reveal := range reveals { - adjGasUsed[i] = min(reveal.GasUsed, execGasLimit/uint64(replicationFactor)) + for i, gasReport := range gasReports { + adjGasUsed[i] = min(gasReport, execGasLimit/uint64(replicationFactor)) if i == 0 || adjGasUsed[i] < lowestGasUsed { lowestReporterIndex = i lowestGasUsed = adjGasUsed[i] @@ -121,13 +140,13 @@ func median(arr []uint64) uint64 { // areGasReportsUniform returns true if the gas reports of the given reveals are // uniform. -func areGasReportsUniform(reveals []types.RevealBody) bool { - if len(reveals) == 0 { +func areGasReportsUniform(reports []uint64) bool { + if len(reports) == 0 { return true } - firstGas := reveals[0].GasUsed - for i := 1; i < len(reveals); i++ { - if reveals[i].GasUsed != firstGas { + firstGas := reports[0] + for i := 1; i < len(reports); i++ { + if reports[i] != firstGas { return false } } diff --git a/x/tally/types/expected_keepers.go b/x/tally/types/expected_keepers.go index b279701e..e7838af9 100644 --- a/x/tally/types/expected_keepers.go +++ b/x/tally/types/expected_keepers.go @@ -4,8 +4,13 @@ import ( "context" batchingtypes "github.com/sedaprotocol/seda-chain/x/batching/types" + dataproxytypes "github.com/sedaprotocol/seda-chain/x/data-proxy/types" ) type BatchingKeeper interface { SetDataResultForBatching(ctx context.Context, result batchingtypes.DataResult) error } + +type DataProxyKeeper interface { + GetDataProxyConfig(ctx context.Context, pubKey []byte) (result dataproxytypes.ProxyConfig, err error) +}