Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RelayMiner] Supplier rate limiting #895

Merged
merged 80 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from 63 commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
6738d21
WIP
Olshansk Aug 16, 2024
3e6a146
Merge branch 'main' into inflation
Olshansk Aug 20, 2024
c3a235a
Checkpoint
Olshansk Aug 21, 2024
846bc1d
Finished first version of the documentation
Olshansk Aug 21, 2024
40c56a5
Merge branch 'main' into inflation
Olshansk Aug 21, 2024
98736f3
Revert tokenomic docs
Olshansk Aug 21, 2024
eeabb30
Performed self review
Olshansk Aug 21, 2024
10ef513
Merge with main
Olshansk Aug 22, 2024
0e725a4
Remove everything related to TLMGlobalMintReimbursementRequest
Olshansk Aug 22, 2024
bbe2366
WIP
Olshansk Aug 23, 2024
ad70e70
Fixed the TestProcessTokenLogicModules_TLMBurnEqualsMintValid test
Olshansk Aug 23, 2024
b02ef24
WIP
Olshansk Aug 24, 2024
8663fac
Finished implementing TestProcessTokenLogicModules_TLMBurnEqualsMint_…
Olshansk Aug 25, 2024
085d134
Implemented TestProcessTokenLogicModules_TLMGlobalMint_Valid_MintDist…
Olshansk Aug 25, 2024
1de13ba
Updated comments in e2e/tests/0_settlement.feature
Olshansk Aug 25, 2024
b8dff51
Fixed failing unit test
Olshansk Aug 25, 2024
9231d6f
Merge branch 'main' into issues/732_max_claimable_pokt
Olshansk Aug 25, 2024
f79989a
Merge branch 'main' into issues/732_max_claimable_pokt
Olshansk Aug 26, 2024
4c335e7
update compile proto
Olshansk Aug 26, 2024
0020303
Merge remote-tracking branch 'origin/main' into issues/732_tokenomics…
red-0ne Sep 19, 2024
f7a0da7
fix: Remove merge added lines
red-0ne Sep 19, 2024
79ac3e6
feat: Add GMRR
red-0ne Sep 20, 2024
1befc5e
fix: Skip GMRR if GMI is disabled
red-0ne Sep 20, 2024
e5a732b
Merge remote-tracking branch 'origin/main' into issues/732_tokenomics…
red-0ne Oct 13, 2024
197c5a0
fix: Activate GMRR TLM
red-0ne Oct 14, 2024
61a62fa
chore: Add TODO for the relay miner to account for GMRR
red-0ne Oct 14, 2024
942c525
Merge remote-tracking branch 'origin/main' into feat/gmrr
red-0ne Oct 14, 2024
5db96bc
Merge remote-tracking branch 'origin/main' into feat/gmrr
red-0ne Oct 14, 2024
13784b8
fix: Min stake tests
red-0ne Oct 14, 2024
2be5464
Merge remote-tracking branch 'origin/main' into feat/gmrr
red-0ne Oct 14, 2024
3baec62
Merge remote-tracking branch 'origin/main' into feat/gmrr
red-0ne Oct 17, 2024
e91a20e
feat: Add WithProofRequirement option
red-0ne Oct 18, 2024
568ecb9
fix: ensure app stake is always enough
red-0ne Oct 24, 2024
6c836e7
fix: Ensure no over-servicing
red-0ne Oct 24, 2024
fafd2f3
chore: Address reveiw change requests
red-0ne Oct 24, 2024
ba13177
Merge remote-tracking branch 'origin/main' into feat/gmrr
red-0ne Oct 25, 2024
3185741
fix: Add globalmint to tests
red-0ne Oct 25, 2024
1593bfb
fix: Linting errors
red-0ne Oct 25, 2024
b2a14b2
fix: Check cached stake before query
red-0ne Oct 25, 2024
5e6e514
fix: Remove redundant check
red-0ne Oct 25, 2024
2b14bab
feat: Supplier rate limiting
red-0ne Oct 28, 2024
f050d8c
fix: Cmd dependencies
red-0ne Oct 28, 2024
196c2fa
fix: Hidden error
red-0ne Oct 28, 2024
6fea32f
fix: Ineffectual assignement
red-0ne Oct 28, 2024
b175916
Merge remote-tracking branch 'origin/main' into feat/gmrr
red-0ne Oct 28, 2024
7bd6058
chore: Address review change requests
red-0ne Oct 29, 2024
3f1a2b8
Merge remote-tracking branch 'origin/main' into feat/no-overservicing
red-0ne Oct 29, 2024
f304c87
feat: Add overservicing allowance
red-0ne Oct 29, 2024
aaec275
Merge remote-tracking branch 'origin/feat/gmrr' into feat/no-overserv…
red-0ne Oct 29, 2024
2ee8448
fix: Merge error
red-0ne Oct 29, 2024
6170a45
improve: Add per relayer app meter
red-0ne Oct 30, 2024
2784cfb
Merge remote-tracking branch 'origin/main' into feat/gmrr
red-0ne Oct 30, 2024
2bd7240
chore: Address review change requests
red-0ne Oct 30, 2024
4c65e84
Merge remote-tracking branch 'origin/feat/gmrr' into feat/no-overserv…
red-0ne Oct 30, 2024
ee93efa
fix: Rename supplier app stake retrieval fn
red-0ne Oct 30, 2024
1550475
fix: Update godoc comment
red-0ne Oct 30, 2024
cbe98ac
Merge remote-tracking branch 'origin/main' into feat/no-overservicing
red-0ne Oct 30, 2024
cd45da6
chore: Address reivew change requests
red-0ne Oct 30, 2024
5ad3b28
Merge remote-tracking branch 'origin/main' into feat/no-overservicing
red-0ne Oct 31, 2024
e7c288b
fix: Total supply
red-0ne Oct 31, 2024
44a5b19
fix: Add all apps suply
red-0ne Oct 31, 2024
d38c51c
Merge remote-tracking branch 'origin/main' into feat/no-overservicing
red-0ne Nov 5, 2024
c5a3c20
Empty commit
red-0ne Nov 5, 2024
1146aba
chore: Address review change requests
red-0ne Nov 6, 2024
7b8998e
fix: Do not process 0 claim amounts
red-0ne Nov 6, 2024
88a3d45
Empty commit
red-0ne Nov 6, 2024
4b04353
fix: Prevent 0 settlement due to int div
red-0ne Nov 7, 2024
331654f
fix: consumed coin calculation
red-0ne Nov 7, 2024
1cb995c
chore: Address review change requests
red-0ne Nov 11, 2024
a39d5b2
fix: Remove wrong param comment
red-0ne Nov 11, 2024
a2dd722
chore: Remove already tackled TODOs
red-0ne Nov 11, 2024
2b64d0b
Merge remote-tracking branch 'origin/main' into feat/no-overservicing
red-0ne Nov 11, 2024
586b20e
Merge remote-tracking branch 'origin/main' into feat/no-overservicing
red-0ne Nov 12, 2024
75fc9b6
Merge remote-tracking branch 'origin/main' into feat/no-overservicing
red-0ne Nov 13, 2024
b46cb72
fix: Merge with main
red-0ne Nov 13, 2024
e7d14ba
Merge remote-tracking branch 'origin/main' into feat/no-overservicing
red-0ne Nov 13, 2024
02e40fb
Merge remote-tracking branch 'origin/main' into feat/no-overservicing
red-0ne Nov 13, 2024
990ef42
Merge remote-tracking branch 'origin/main' into feat/no-overservicing
red-0ne Nov 13, 2024
8d491ce
fix: Missing session querier
red-0ne Nov 13, 2024
a800fbd
Merge remote-tracking branch 'origin/main' into feat/no-overservicing
red-0ne Nov 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,13 @@ genesis:
denom: upokt
bank:
supply:
- amount: "1102000204"
- amount: "1202000272"
denom: upokt
balances:
# Application module
- address: pokt1rl3gjgzexmplmds3tq3r3yk84zlwdl6djzgsvm
coins:
- amount: "100000068" # MUST BE equal to the total of all app stakes below
- amount: "200000136" # MUST BE equal to the total of all app stakes below
red-0ne marked this conversation as resolved.
Show resolved Hide resolved
denom: upokt
# Supplier module
- address: pokt1j40dzzmn6cn9kxku7a5tjnud6hv37vesr5ccaa
Expand Down
18 changes: 17 additions & 1 deletion pkg/relayer/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,11 @@ func setupRelayerDependencies(
config.NewSupplyDelegationClientFn(), // leaf
config.NewSupplySharedQueryClientFn(), // leaf
config.NewSupplyServiceQueryClientFn(),
config.NewSupplyApplicationQuerierFn(),
supplyRelayMeter,
supplyMiner,
config.NewSupplyAccountQuerierFn(),
config.NewSupplyBankQuerierFn(),
config.NewSupplyApplicationQuerierFn(),
config.NewSupplySupplierQuerierFn(),
config.NewSupplySessionQuerierFn(),
config.NewSupplyProofQueryClientFn(),
Expand Down Expand Up @@ -231,6 +232,21 @@ func supplyMiner(
return depinject.Configs(deps, depinject.Supply(mnr)), nil
}

// supplyRelayMeter constructs a RelayMeter instance and returns a new
// depinject.Config which is supplied with the given deps and the new RelayMeter.
func supplyRelayMeter(
_ context.Context,
deps depinject.Config,
_ *cobra.Command,
) (depinject.Config, error) {
rm, err := proxy.NewRelayMeter(deps)
if err != nil {
return nil, err
}

return depinject.Configs(deps, depinject.Supply(rm)), nil
}

// supplyTxFactory constructs a cosmostx.Factory instance and returns a new
// depinject.Config which is supplied with the given deps and the new
// cosmostx.Factory.
Expand Down
24 changes: 24 additions & 0 deletions pkg/relayer/interface.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//go:generate mockgen -destination=../../testutil/mockrelayer/relayer_proxy_mock.go -package=mockrelayer . RelayerProxy
//go:generate mockgen -destination=../../testutil/mockrelayer/miner_mock.go -package=mockrelayer . Miner
//go:generate mockgen -destination=../../testutil/mockrelayer/relayer_sessions_manager_mock.go -package=mockrelayer . RelayerSessionsManager
//go:generate mockgen -destination=../../testutil/mockrelayer/relay_meter_mock.go -package=mockrelayer . RelayMeter

package relayer

Expand Down Expand Up @@ -162,3 +163,26 @@ type SessionTree interface {
// GetTrieSpec returns the trie spec of the SMST.
GetTrieSpec() smt.TrieSpec
}

// RelayMeter is an interface that keeps track of the amount of stake consumed between
// a single onchain Application and a single onchain Supplier over the course of a single session.
// It enables the RelayMiner t orate limit the number of requests handled offchain as a function
red-0ne marked this conversation as resolved.
Show resolved Hide resolved
// of the optimistic onchain rate limits.
type RelayMeter interface {
// Start starts the relay meter.
Start(ctx context.Context) error

// AccumulateRelayReward adds the relay reward from the incoming request to session's accumulator.
// The relay cost is added optimistically, assuming that the relay WILL be volume / reward applicable.
// The reason why optimistic AccumulateRelayReward + SetNonApplicableRelayReward is used instead of
// a simpler AccumulateVolumeApplicableRelayReward is that when the relay is first seen
// we don't know if it will be volume / reward applicable until it is served.
// Since the check of whether we allow the relay to be served or not is done before.
// To rate limit or not the current relay, we need to optimistically account
// for it as volume / reward applicable.
red-0ne marked this conversation as resolved.
Show resolved Hide resolved
AccumulateRelayReward(ctx context.Context, relayRequestMeta servicetypes.RelayRequestMetadata) error
red-0ne marked this conversation as resolved.
Show resolved Hide resolved

// SetNonApplicableRelayReward updates the relay meter for the given relay request as
// non-applicable between a single Application and a single Supplier for a single session.
red-0ne marked this conversation as resolved.
Show resolved Hide resolved
SetNonApplicableRelayReward(ctx context.Context, relayRequestMeta servicetypes.RelayRequestMetadata) error
}
15 changes: 14 additions & 1 deletion pkg/relayer/miner/miner.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type miner struct {
// serviceQueryClient is used to query for the relay difficulty target hash of a service.
// relay_difficulty is the target hash which a relay hash must be less than to be volume/reward applicable.
serviceQueryClient client.ServiceQueryClient
relayMeter relayer.RelayMeter
}

// NewMiner creates a new miner from the given dependencies and options. It
Expand All @@ -43,7 +44,7 @@ func NewMiner(
) (*miner, error) {
mnr := &miner{}

if err := depinject.Inject(deps, &mnr.serviceQueryClient); err != nil {
if err := depinject.Inject(deps, &mnr.serviceQueryClient, &mnr.relayMeter); err != nil {
return nil, err
}

Expand Down Expand Up @@ -88,18 +89,30 @@ func (mnr *miner) mapMineRelay(
) (_ either.Either[*relayer.MinedRelay], skip bool) {
relayBz, err := relay.Marshal()
if err != nil {
meteringError := mnr.relayMeter.SetNonApplicableRelayReward(ctx, relay.GetReq().GetMeta())
if meteringError != nil {
return either.Error[*relayer.MinedRelay](fmt.Errorf("failed to unclaim relay price: %w", meteringError)), false
}
return either.Error[*relayer.MinedRelay](err), false
}
relayHashArr := protocol.GetRelayHashFromBytes(relayBz)
relayHash := relayHashArr[:]

relayDifficultyTargetHash, err := mnr.getServiceRelayDifficultyTargetHash(ctx, relay.Req)
if err != nil {
meteringError := mnr.relayMeter.SetNonApplicableRelayReward(ctx, relay.GetReq().GetMeta())
if meteringError != nil {
return either.Error[*relayer.MinedRelay](fmt.Errorf("failed to unclaim relay price: %w", meteringError)), false
}
return either.Error[*relayer.MinedRelay](err), false
}

// The relay IS NOT volume / reward applicable
if !protocol.IsRelayVolumeApplicable(relayHash, relayDifficultyTargetHash) {
meteringError := mnr.relayMeter.SetNonApplicableRelayReward(ctx, relay.GetReq().GetMeta())
if meteringError != nil {
return either.Error[*relayer.MinedRelay](fmt.Errorf("failed to unclaim relay price: %w", meteringError)), false
}
red-0ne marked this conversation as resolved.
Show resolved Hide resolved
return either.Success[*relayer.MinedRelay](nil), true
}

Expand Down
19 changes: 18 additions & 1 deletion pkg/relayer/miner/miner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ import (
"time"

"cosmossdk.io/depinject"
gomock "github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"

"github.com/pokt-network/poktroll/pkg/crypto/protocol"
"github.com/pokt-network/poktroll/pkg/observable/channel"
"github.com/pokt-network/poktroll/pkg/relayer"
"github.com/pokt-network/poktroll/pkg/relayer/miner"
"github.com/pokt-network/poktroll/testutil/mockrelayer"
"github.com/pokt-network/poktroll/testutil/testclient/testqueryclients"
servicetypes "github.com/pokt-network/poktroll/x/service/types"
)
Expand Down Expand Up @@ -48,8 +50,9 @@ func TestMiner_MinedRelays(t *testing.T) {

testqueryclients.SetServiceRelayDifficultyTargetHash(t, testSvcId, testRelayMiningTargetHash)
serviceQueryClientMock := testqueryclients.NewTestServiceQueryClient(t)
testRelayMeter := mockRelayMeter(t)
red-0ne marked this conversation as resolved.
Show resolved Hide resolved

deps := depinject.Supply(serviceQueryClientMock)
deps := depinject.Supply(serviceQueryClientMock, testRelayMeter)
red-0ne marked this conversation as resolved.
Show resolved Hide resolved
mnr, err := miner.NewMiner(deps)
require.NoError(t, err)

Expand Down Expand Up @@ -154,3 +157,17 @@ func unmarshalHexMinedRelay(
Hash: relayHash,
}
}

// mockRelayMeter returns a mock RelayMeter that is used by the relay miner to claim and unclaim relays.
func mockRelayMeter(t *testing.T) relayer.RelayMeter {
red-0ne marked this conversation as resolved.
Show resolved Hide resolved
t.Helper()

ctrl := gomock.NewController(t)
relayMeter := mockrelayer.NewMockRelayMeter(ctrl)

relayMeter.EXPECT().Start(gomock.Any()).Return(nil).AnyTimes()
relayMeter.EXPECT().AccumulateRelayReward(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
relayMeter.EXPECT().SetNonApplicableRelayReward(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()

return relayMeter
}
2 changes: 2 additions & 0 deletions pkg/relayer/proxy/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@ var (
ErrRelayerProxyUnsupportedTransportType = sdkerrors.Register(codespace, 9, "unsupported proxy transport type")
ErrRelayerProxyInternalError = sdkerrors.Register(codespace, 10, "internal error")
ErrRelayerProxyMissingSupplierOperatorAddress = sdkerrors.Register(codespace, 11, "supplier operator address is missing")
ErrRelayerProxyUnknownApplication = sdkerrors.Register(codespace, 12, "relayer proxy encountered unknown application")
ErrRelayerProxyRateLimited = sdkerrors.Register(codespace, 13, "offchain rate limit hit by relayer proxy")
)
red-0ne marked this conversation as resolved.
Show resolved Hide resolved
21 changes: 20 additions & 1 deletion pkg/relayer/proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ type relayerProxy struct {
// 1. Relay verification to check if the incoming relay matches the supplier hosted by the relay miner;
// 2. Relay signing to resolve which keyring key name to use for signing;
OperatorAddressToSigningKeyNameMap map[string]string

// relayMeter keeps track of the total amount of stake an onchhain Application
// will owe an onchain Supplier (backed by this RelayMiner) once the session settles.
// It also configures over servicing allowance.
red-0ne marked this conversation as resolved.
Show resolved Hide resolved
relayMeter relayer.RelayMeter
}

// NewRelayerProxy creates a new relayer proxy with the given dependencies or returns
Expand All @@ -86,9 +91,15 @@ type relayerProxy struct {
// Required dependencies:
// - cosmosclient.Context
// - client.BlockClient
// - crypto.RingCache
// - client.SupplierQueryClient
// - client.SessionQueryClient
// - client.SharedQueryClient
// - client.SupplierQueryClient
// - keyring.Keyring
// - client.SharedQueryClient
// - client.ApplicationQueryClient
// - client.ServiceQueryClient
// - client.EventsQueryClient
//
// Available options:
// - WithSigningKeyNames
Expand All @@ -108,6 +119,7 @@ func NewRelayerProxy(
&rp.sessionQuerier,
&rp.sharedQuerier,
&rp.keyring,
&rp.relayMeter,
); err != nil {
return nil, err
}
Expand Down Expand Up @@ -143,6 +155,13 @@ func (rp *relayerProxy) Start(ctx context.Context) error {
// Start the ring cache.
rp.ringCache.Start(ctx)

// Start the relay meter by subscribing to the on-chain events.
// This function is non-blocking and the subscription cancellation is handled
// by the context passed to the Start method.
if err := rp.relayMeter.Start(ctx); err != nil {
red-0ne marked this conversation as resolved.
Show resolved Hide resolved
return err
}

startGroup, ctx := errgroup.WithContext(ctx)

for _, relayServer := range rp.servers {
Expand Down
Loading
Loading