Attributes
- Author(s): @toshi @conkleris @bulutcambazi in C0D3R
- Implementer(s): The proposal authors
- Category: Protocol Upgrade
GitHub: [v0.11 feature] Built-in Reward Share by msmania · Pull Request #1581 · pokt-network/pocket-core · GitHub 2
Please note that this feature was proposed before as bundled with another feature as part of PIP-31. It is now a proposal by itself, so if/when the time comes, DAO can vote on this independently.
Abstract
We suggest introducing a built-in reward sharing feature that enables a staked node to distribute block/relay rewards across multiple wallets with the percentages defined per wallet. Node operators can leverage this functionality to offer a reward sharing pricing model.
Motivation / Rationale
Below list is numbered to make references easier, but it is not necessarily in the order of importance.
- Built-in reward sharing will make the network more secure: The Non-Custodial Staking feature [1] reduced the security risks associated with staked funds being held in the custody of third-party node operators. From the standpoint of node operators, however, non-custodial staking and a reward share pricing model do not coexist naturally because the service rewards are now in the custody of customers. A bad-intentioned customer can abscond with rewards, and a node operator would have no recourse to recoup the losses (except for legal action, which is costly and in some cases impossible internationally). This can be a barrier for node operators to fully go into non-custodial staking. This feature will remove that barrier.
- This helps network be more efficient in terms of block use by reducing the number of transactions in the network because with this feature, commission transfers happen without issuing send transactions (which means spending tx fees and occupying block space). To facilitate zero-maintenance non-custodial staking, we also included fixes of minor issues —namely, negative rewards and operator topping-off— in this feature, as detailed below.
- This provides a better node running and investing experience by a) removing the burden for node runners of creating detailed bills b) customers watching for them and dealing with the mechanics of paying them c) back and forth for correcting wrong amounts, delayed payments, etc.
- This brings more transparency and trust to the system. Non-technical investors wouldn’t need to independently verify if the node runner calculations are correct, because now the proper distribution of rewards will be done by the network itself.
Specification
The built-in reward share is achieved by introducing a new field delegators in a staked node side by side with the existing output_address field as below, which defines reward share percentages for multiple addresses.
type Validator struct {
Address sdk.Address
PublicKey crypto.PublicKey
Jailed bool
Status sdk.StakeStatus
Chains []string
ServiceURL string
StakedTokens sdk.BigInt
UnstakingCompletionTime time.Time
OutputAddress sdk.Address
Delegators map[string]uint32 // <--- New
}
For a servicer to earn relay rewards from a single evidence submission, its operator address needs to submit two transactions, a claim and a proof. Since each of these transactions costs the hardcoded amount 0.01 POKT [2], the operator wallet incurs a fee of 0.02 POKT. If a servicer is staked in a non-custodial manner, relay rewards are distributed to three wallets, DAO, BlockProposer, and the servicer’s output address. Intriguingly, the operator address receives no rewards, even though a transaction fee of 0.02 POKT is debited from this wallet. As a result, node operators must regularly replenish the operator address of their non-custodial nodes.
We implemented a solution to this issue in this feature. With the introduction of delegators, the workflow is as follows: after the DAO and BlockProposer portions are deducted, the node first allocates the transaction fee cost to the operator address. It then distributes the delegators’ shares to their respective wallets and sends the remaining tokens to the output address. This means that relay rewards are now distributed across five types of wallets: the DAO, the BlockProposer, the servicer’s operator, the delegators, and the output address.
With the current RTTM, the relay rewards from a single evidence submission can be less than 0.02 POKT. Earning such a minuscule reward ultimately results in a net loss. To prevent it, we implemented a mechanism not to submit a claim transaction if the rewards from it are expected to be less than the reward cost. We say it’s “expected” because we cannot accurately calculate the amount when we claim it. The amount of the relay rewards is calculated when a node processes a proof transaction, hence it’s possible that RTTM or a servicer’s stake amount may have changed. For that reason, we put the option to potentially prevent a net-loss situation behind a new configuration so that a node operator can choose which logic is preferable.
This distribution to delegators is applied to block rewards too. Unlike relay rewards, there is no cost to earn block rewards.
Another topic we need to discuss is “editing”. The upgrade to RC-0.10.4 enabled the new feature Output Address Edit [3], which allows an MsgStake transaction signed by the current output address to change the output address to another. Now who should be able to change delegators? We propose that only the owner of the node operator should have the authority to make changes as follows:
- OutputAddress:
Only the current output address owner has the authority to modify. (since RC-0.10.4) - Delegators:
Only the node operator address owner should have the authority to modify. (Our proposal)
You may think that this reinstates the security risk that relay rewards are now in the custody of the node operator because they can change the commission percentages to 100 so that zero rewards go to the output address. You’re right. With this model, node operators can change the percentages to any value any time. Nevertheless, we think this is acceptable for the following reasons.
- Node operators may want to increase/decrease the commission percentage for a legitimate reason. If a node operator illegitimately appropriates rewards by tampering the percentages, customers still have the option to unstake nodes and reclaim their staked tokens immediately. And that would severely damage the reputation of the node operator, likely rendering them unable to continue in the business.
- Compared to the staked amount, which is still in the custody of the output address owner, the amount of relay rewards is much smaller (currently at 5% per year).
- Any such activity is recorded in the blockchain and can be audited backwards. Therefore, a customer doesn’t need to constantly check whether their node runner is doing anything fraudulent. A tool can check any time period in the past within seconds, warning the customer if their node runner was/has been acting without their knowledge.
[1] PIP-9 Consensus Rule Change – RC-0.8.0
[2] https://github.com/pokt-network/pocket-core/blob/353dd1047a5621a6dbc8351b28196cd39f5e7445/x/pocketcore/types/fee.go#L4-L5
[3] PIP-30: Consensus Rule Change – RC-0.10.0
Dissenting Opinions
As discussed above, the proposed features enhance the Non-Custodial staking feature. We believe there is no downside in the proposal. The only risk we see is the risk that applies to all code changes: the risk of regressions or upgrade operations. We expect to address this inherent risk in testing.
Viability
- New unit tests to verify the new features are included in the PRs we implemented.
- We perform end-to-end testing, where we submit relays and verify the rewards are distributed correctly, on Pocket Testnet before upgrading Mainnet.
- We prepare upgrade plan after this proposal is approved.
Implementation
This proposal includes a working implementation as GitHub PR above. It has been verified on our private devnet:
- submit gov transactions
- keep sending relays throughout a test (before/after gov transactions) and wait until relay rewards are minted
- verify the amount of rewards
Deployment:
- If this proposal is approved, and after testing has taken place for BETA-0.11.0 on Testnet, RC-0.11.0 will be published for node runner adoption. Anyone can monitor node runner adoption of RC-0.11.0 using the Servicers and Validators version pie charts displayed here or the equivalent “Staked Tokens by Node Version” chart displayed here .
- Once ≥67% of validator power has updated to this version, an upgrade height will be selected by the Foundation Directors based on the preferences expressed by node runners (e.g. through Discord polls) and they will pass this height to the chain through the
pocket gov upgrade
transaction. - The upgrade height chosen by the Foundation Directors will be communicated in advance to ensure node runners are prepared to react if necessary. A time will be targeted that maximizes the availability of node runners, accounting for all time zones and working hours.
- Once the network is upgraded, the new feature will be enabled by the Foundation submitting the
pocket gov enable
txs and working with the protocol developers to ensure there are no issues.
Example:
Here’s an example command to stake a node with two delegators. This patch introduces a new stake command nodes stakeNew
that takes a signer address and delegators.
export POKT=<path to pocket>
export NETWORK=mainnet
export URL=http://localhost:8082
export STAKE=8000000000000
export CHAINS=0001,0021,0040
export NODE=20c0be21bc69284d7d420ad7892a681400ef922e
export NODE_PUBKEY=59acadf42a784b4f66eade8c3207a416cea43434349fdb2cee040137b2ccb800
export OUTPUT=fe818527cd743866c1db6bdeb18731d04891df78
export SIGNER=fe818527cd743866c1db6bdeb18731d04891df78
export DELEGATOR1=1000000000000000000000000000000000000000
export DELEGATOR2=2000000000000000000000000000000000000000
$POKT nodes stakeNew \
$NODE_PUBKEY \
$OUTPUT \
$SIGNER \
$STAKE \
$CHAINS \
$URL \
'{"'$DELEGATOR1'":10,"'$DELEGATOR2'":20}' \
$NETWORK \
10000
Once it’s accepted by the network, the staked node looks like this.
$POKT query node $NODE
2023/10/12 12:39:44 Initializing Pocket Datadir
2023/10/12 12:39:44 datadir = /home/john/.pocket
http://localhost:8082/v1/query/node
{
"address": "20c0be21bc69284d7d420ad7892a681400ef922e",
"chains": [
"0001",
"0021",
"0040"
],
"delegators": {
"1000000000000000000000000000000000000000": 10,
"2000000000000000000000000000000000000000": 20
},
"jailed": false,
"output_address": "fe818527cd743866c1db6bdeb18731d04891df78",
"public_key": "59acadf42a784b4f66eade8c3207a416cea43434349fdb2cee040137b2ccb800",
"service_url": "http://localhost:8082",
"status": 2,
"tokens": "8000000000000",
"unstaking_time": "0001-01-01T00:00:00Z"
}
Audit
There will be no external audit, refer to Viability.
Copyright
Copyright and related rights waived via CC0.
#Edits
10/23: This proposal is now available for voting: Snapshot