[WIP] PIP-24: TransferStake

Attributes

  • Author(s): @poktblade
  • Implementer(s): Me, myself, and I and literally anyone else who wants to join the fun.
  • Category: Protocol Upgrade

Summary

A new transaction within the network that allows a node to transfer a portion or their full stake to another account (or node) without the need to unstake. As well, this transaction will ensure that the transfered POKT is still staked into the network (no excess liquidity)

Community Calls

This topic was brought up two times in seperate V0 Developer Protocol Community calls. From an initial round of discussion, there isn’t necessarily anything engineering blocking about this feature. (@blockjoe , @luyzdeleon )

Motivation

Validator bidding war

The bidding war is defined as the top 1,000 validator nodes competing amongst each other to receive the block proposer reward currently set at 5%. The problem arises whenever one of these validators become “outbidded” and is no longer a validator (i.e: 1,001th validator). The outbided validator needs to decide whether they should increase their StakedAmount to reenter the top 1,000 validators or exit the bidding war by unstaking.

Whenever considering why someone would unstake after being outbidded, there is a high chance that they are unstaking to restake as horizontally scaled servicers or because it is no longer worth it from a macroeconomic perspective (or from a reward perspective). That being said, the main purpose is not to exit the network. We should not be penalizing participants by a hefty 21 days unstaking time before they can actually transition their stake into scaled servicers. Furthermore, the network is also penalized as we lose MAX(1, n) amount of potential servicers while the unstaking occurs since validators can be servicers too

Non Diverse/Small Validator Set
On top of this, leaving the responsibility for small to medium node runners to decide what will happen in the next 21 days is extremely harsh. The truth is only whales can afford to participate in such a bidding war, whereas most are incentivized to not validate and stay away from the high risk high reward scenarios. By offering a zero to low risk penalty, we should see more small to medium node runners participate in validation and as a result see a more diverse validator set. This is needed for a healthy decentralized protocol

Overall unhealthy staking economics
PIP-22 allows for either both horizontally scaled or vertical scaled nodes (up to a cap). We should allow for flexibility to chose for one or both and the ability to convert amongst the two. This would allow for efficient consolidation without the need to unstake and weaken the network.

PUP-19 also incentized more nodes to become validators. However, now if the DAO was to revert the block proposer to 1% (not saying it will, just an example), then it could result in a large reduction in validators and large amount of POKT being unstaked due to the bidding war. So, there is a side effect where the DAO is dissuaded to make this decision. With an transfer stake transaction, the DAO has more options on whether they should increase or decrease economic parameters.

Future PUPS and PIPS: Future proposals may result in some form of consolidation between servicers and validators (i.e GV). By offering a way to TransferStake’s, we are offering a healthy mechanism that participants of the network can use to bypass the so called “transition phase”

Initial Specification

These specifications are subject to change, it is not finalized. I am opening the floor for all to give their thoughts and shape TransferStake into something that is viable both from engineering perspective and what reflects the DAO’s will support. (And TBH, I wrote this in like 30 mins)

The final specifications will be announced after a round of discussion, let’s get it rollin’

Dependency

  • Non custodial staking activated

CLI Command

pocket accounts transfer-stake <sender_address> <receiver_operator_address> <receiver_output_address> <amount> <fee> <network_id> <service_url> <chain_ids>

TransferStake Transaction Rules

  • The sender address must be a staked node (not unstaking, not jailed) otherwise the transaction will fail (INVALID_VALIDATOR_ERR/NOT_FOUND)
  • If the sender address set an output address, it must be signed by the output address otherwise then transaction will fail
    (INVALID_SIGNER_ERR)
  • If the sender of the transaction does not have an output address, it must be signed by the sender address, otherwise the transaction will fail (INVALID_SIGNER_ERR)
  • If receiver node is already staked, and receiver output address is set (or empty), then the receiver_output_address in the TransferStake command must match (or be empty as well) otherwise the transaction will fail
  • The transfer stake amount must be within the bounds of MinStake and SenderStakedBalance, otherwise the transaction will fail. (INSUFFICIENT_TRANSFER_ERR)
    (We can also modify the transfer minimum amount so that senders can send smaller amounts lower than MinStake as long as the receiver is already a staked node. This modification should not use the Receiver’s Account balance due to unauthorized reasons (unless multi sig is supported)). This may include a little extra logic when it comes to engineering implementation but nothing major

Upon successful transactions, the state of the network will change as such:

  1. If the receiver account is unstaked, they will be staked into the network. Else If the receiver account is already staked, their staked balance will update
  2. SenderStakeBalance will decrement. If the SenderStakeBalance drops below MinStake, they will be effectively be unstaking (21 day waiting period) / unstaked (if net balance is 0)

Feature Flag

This new transaction will be protected by an block height activation feature flag

Implementation, Viability, Testing, Audits, etc

See: pocket-core/CONTRIBUTING.md at 629a38891850507c4374bdd8d75cbdfd343d469c · pokt-network/pocket-core · GitHub

Dissenting Opinions

This adds more block bloat

This is not too much of a concern. There are upcoming features i.e persistent replacement & LeanPOKT that will significantly reduce our storage requirements. Furthermore, the amount of TransferStake transaction should be on the lower end

Shuffling nodes will affect sessions and our QoS
This is nothing new to our protocol as is. If a node unstake, the dispatcher and full nodes should generate a new session. Additionally, TransferStake can minimize the amount of times a new session is generated by making TransferStake valid only at the end of a session block. With this modification, there is no need for apps, nodes, and dispatchers to generate new sessions since nodes shuffled via transferstake will only apply at the end of a session

Attack Vector(s)

Unauthorized Node transfers (Prevented momentary incentive not to do this + multisig if needed)

  1. Attacker transfer 15K stake to non staked random addresses with the attacker’s output address
  2. Random address doesn’t realize the output address is set to attackers output address, and stakes additional funds
  3. Atacker submits unstake and gets the net rewards

Block proposer gaming: Increasing your chances of being a block proposer by generating a keypair that is more likely to be chosen. I need to do more research, but given that there is a psuedo randominess and ticketed system for this - I think the risk is mitigated b itself

PIP-22 Gaming: Transfer stake to a node that is in session to earn more rewards. This is mitigated by only allowing transfer stake to occur at the end of session.

PIP-22 Gaming 2: If you are able to determine what the next block hash is, you can determine which nodes will be included in the next session and transfer stake to them. TBD - Needs more research on block hash determinstic behavior and if it’s gameable.

Oopsie: An application logic falls through the crack - allowing everyone and their grandma to do unauthorized stakes or duplicate stakes. - This is why we have a process for Q/A and a process!

Edits

  1. 8/13/2022: Added clarity on options for TransferStake minimum in TransferStake Transaction Rules
  2. 8/14/2022: Added a hypthoetical attack vector and added clarity on output address
  3. 9/1/2022: Added more attack vectors and migitations

Copyright

Copyright and related rights waived via CC0.

4 Likes

There was unofficial discussion in regards to this topic in the Discord Governance Channel:

3 Likes

I support this proposal. 21 day unstake is necesary for the health of the protocol. Transfer stake is completely different and will help foster competition between the legacy node runners and new entrants.

3 Likes

Thanks @poktblade. Interesting. Have you thought about, as an alternative, simply a PUP to lower unstake time for everyone? I’d be in favor of that.

Could you please explain how this works for us who are not node runners? If I want to spin up a node, what do I do? some form of registration where I am assigned a node address after which I fund and after which I stake? If so, who assigns the address and is the regristaration list kept on chain or is this a portal thing?. I didn’t see anything in the proposal about passing a check that the receiver address is registered as a node and not someone’s personal wallet. If there is no such registration process, isn’t it a bit intrusive to reach in and auto-stake on behalf of the wallet owner? would you autostake just the tx amount, or the entire contents of this wallet? Isn’t staking a client-side action? So the core is going to spoof the client’s issuing a stake command? Even if it does, won’t it have to wait until the transaction is confirmed? What prevents the owner of the address from running a bot to drain the wallet of funds the moment the tx is confirmed and before the process to stake the funds initiates? Sorry for the loads of ignorance baked into the questions, but if I have the questions I’m sure someone else will too.

Is the lower bound to prevent trivial transfers (eg tried for validator with 63k but missed out and want to go down 60k and put the extra 3k on my other node sitting at 28k), or do you think this kind of example could also benefit and should be allowed?

Note: I might suggest that upper bound should be SenderStakedBalance - MinStake. In this manner, " If the SenderStakeBalance drops below MinStake" is not even a possibility

I like this proposal. I was just thinking the other day how useful something like this would be if I wanted to create a higher stake using funds from other nodes without having to completely unstake or vice versa if I wanted to take a top tier node down to create more smaller stake nodes.

I believe the 21 day unstake period has a purpose that protects the network. To eliminate or reduce the time would open up serious issues down the road.

2 Likes

Yes, I’ve considered a proposal where unstaking time is decreased. In the last contributor hour, I asked what is the significance of the unstaking time of 21 days. You can view @luyzdeleon response Pocket v0 Core Contributors Hour | August 4, 2022 - YouTube. That being said, I believe that both TransferStake and decreasing unstaking time can work hand to hand, and doesn’t have to be mutually exclusive.

A key point that i want to highlight once again from the proposal is that every time we unstake, we weaken the network ever so slightly since that node is no longer servicing or validator once unstaking. If we go back to the users intentions on why they are unstaking, it’s not because they want to exit the network but rather convert it into another form (i.e a validator or servicer). Our network needs to streamline this. An unstaking period of even one hour still temporarily weakens the network.

Transactions are validated and confirmed block by block. Therefore, the unstaking from one node and staking to another will be considered one operation and atomic. within a single block. So this will not become a risk.

Given that this is a new transaction within the protocol - we can define whatever rules we want. Validators will run a pocket core client with code that reflect these rules, and a reminder to all - validators are the ones who decide whether a transaction is legitimate or not based off these rules.

The current specification states the transfer amount needs to be between MinStake and SenderStakedBalance So when the transfer occurs, the receiver wallet balance is untouched. This transfer amount is reflected into the receiver’s staked balance.

Furthermore, it is within the realm of possiblity that the transaction is multisig (more eng research needed on this), so that the sender and receiver of the transfer must sign the transaction. However, this may make it more difficult to streamline the process when someone wants to transfer a stake from one provider to another.

Reminder that most folks will not freely send POKT over to others as there’s a clear monentary reason not to do so.

I am in favor of the latter where users can transfer minimal amounts as well. Right now the current specification doesn’t support transfering small amounts since the transfer amount needs to be between MinStake and SenderStakedBalance. The initial specification does take note of this , and If we want to change the specification to reflect small amount transfers then the following rules would be added:

  1. If the transfer amount is below MinStake, the receiver must already be a staked node, otherwise the transaction will fail.

This modification should not use the receivers Account balance due to unauthorized reasons (unless multi sig is supported). I will edit the proposal to make this clear.

The only con to this approach on top of my head is that it will involve more conditionals when explaining how TransferStake works and of course engineering implementation will involve a little more logic. I will most likely edit the proposal to reflect this change in the upcoming days, but will allow for some time for more discussion

This feature second order effect allows for node transfers from one owner to another as well (or provider) without waiting 21 days.

Some additional comments

  • Thanks for the initial round of comments @msa6867 . This proposal is up exactly for these type of conversations. As more thoughts and concerns come in, the engineering details will also take shape and judging through sentiment, it will allow me to scope and create a PoC/Implementation early on once there is deemed enough support for an idea like this.

I wrote a response before heading off for lunch and came back realizing that I wrote it with lack of details. I’ve re-edited the response, give it a re-read if you haven’t already. Cheers

1 Like

I am in favor of this proposal. I believe that the 21 day unstaking period is important for the networks health to remain intact and that lowering the amount of time the period lasts would not be a good solution to that problem. I believe that this is a much easier route for investors who failed to obtain a validator spot to go so that they can transfer stake rather than having to wait 21 days to unstake just to then have to go back and restake all over again.

1 Like

I am in favor.

  • 21 day unstaking rule is unchanged → maintains security.
  • Validator bidding process is less punitive → higher validator threshold → higher security.
  • Node provider switching is non-punitive → free market competition
    among node providers → node fee price discovery and encourage new entrants.

Good for the network and good for the retail node staker, win - win.

1 Like

I’ve edited the proposal to include a potential attack vector if we allow transfer stake without authorization of the receiver.

1 Like

I think there are two goals that we would like to achieve with stake transfer, and I think to accomplish each goal well, we might need to implement separate mechanisms.

The first goal is the one you mentioned (some unstaked/transfer mechanism in order to make the bidding war processs less punitive), and the second is to allow some sort of transfer mechanism to allow stakers to switch node providers.

A mechanism for the second one needs to be introduced carefully for a few reasons (I am still supportive of achieving #2 tho!)

  • Although competition is healthy and we definitely need to see more innovation from some of the incumbent node providers/pools, introducing a frictionless mechanism for stakers to switch providers would create cuttthroat competition and incentivize slice-growing behaviour rather than pie-growing.
    If we went down this path, we would first need to make significant modifications to the cherry picker to modify the reward distribution and prevent manipulation; else we might see providers cheat in a last-ditch effort to survive and keep comprable rewards.
  • Due to current incentive structures, we already do not see much collaboration between node runners. Although fierce competition will lead to innovation, I’m not sure that continuing down this path is healthiest for our network, especially since the path to increasing rewards may not always be increasing QoS.
  • Transferring stake around in the same way as a normal transfer might defeat the point of staking.
  • Centralizing vector as all stakers converge to the best provider

Thus, achieving the second goal needs to be done carefully. Potentially with a limit frequency per node, or a shorter cooldown time for a stake transfer.

However, the first goal is markedly good, and I don’t think we need to introduce any limitations there.

That being said, the introduced mechanism blends goals 1 and 2, because it allows for stake transfers beyond whats needed for servicing (Top bin of pip-22, ex: 60k). When you first brought this up to me, I had imagined a “mini-unstake”, where you could unstake any amount above the top bin for pip22. Some other protocols have auction mechanisms for the validator slots where only the lowest bid is required to be staked (rest kept liquid), so this would be similar. I am curious what other networks have for stake consolidation, transfer, etc–if anyone has some insights.

I think it would be fruitful here to maybe introduce a method of consolidation as well. What happens if you want to switch from servicing back to validating?

I’m still thinking about what can be done (so i unfortunately don’t have anything to offer yet in terms of suggestions on the mechanism), and would very much like things like this to increase effiency; I am just wary of the risks outlined above.

Can I join the fun? :raising_hand_man:

3 Likes

The connection between TransferStake and cheating the gateway is loosely coupled. Given that we have delegated all app stake access to the Portal, it is the Portal’s responsibility to ensure this does not happen. With or without TransferStake, there is always an economic incentive to game the system and such, it is the Portal’s duty to punish these bad actors. There are many other factors on when a entity would cheat the system (i.e POKT price dropping and infra price rising). I highly suggest the Portal owners prepare mechanisms to dis-encourage these bad actors and set some high penalties. I have brought up this concern multiple times. If we are a proof of stake protocol, then it needs to be enforced. Otherwise why are we even staking in the first place :wink:

If we dig too deep… this point becomes a strawman fallacy. TransferStake is 10 leaps forward, one step back. Our network has flaws, but i think it is overall more healthy to continue innovating our v0 protocol rather than having our inherent flaws hold us back. These flaws can be solved as they become more prominent, can be done asynchronously of this proposal, and i would suggest that they are solved with harsh penalties in mind.

The definition of best provider is going to vary per customer. Objectively speaking, the highest rewards and lowest fees would win most customers. However, we have seen that this doesn’t always play out the way it should as there’s always more to this than meets the eye i.e: bulk discounts, customer loyalty, brand loyalty, experience, etc.

If we truly believe the only reason why customers are not transitioning to the objectively best provider is due to the unstaking period, consider this devils advocate scenario in today’s world:

VC company who can afford to be a loss leader for multiple years. They offer extremely low node prices at a loss, capturing the whole market. Finally, they begin to raise their prices, and now investors can’t exit easily without the dilemma of losing rewards for 21 days, so the customers stay and the VC company holds large market share.

This is a centralization risk we have today.

This was my initial idea / proposal, however, Whenever brought up in the v0 contributor hours, it was stated that it could introduce liquid pocket into the market & it is in the best interest of the protocol that the pocket stays locked in which TransferStake still does. Whether the pocket should be actually locked up or not… i’ll stay on the neutral side of this…

@blockjoe brought up the concern of our convoluted economic model and that adding more conditions or mechanisms makes the model even more complex. I’m open to the idea of having two mechanisms for each goal, but the idea of the initial design was a general purpose transfer stake mechanism to keep it stupid simple (KISS) on both ends (engineering implementation and node runners)

I think we should delegate this to the node providers themselves offchain, rather than introducing further state into the protocol on chain. It’s probably about time that node providers flesh out their terms of services, anyways.

If you have 4 servicer nodes, you can select one to be the receiver node. The other 3 would be sender nodes. With transfer stake, you can transfer stake from your sender nodes to your receiver node. The sender nodes would then be unstaked and your receiver node would be staked at 60k. Or at least that is the idea anyway! TransferStake should allow for both consolidation and expansion, the specification is still in works and I’ll be working out an actual implementation as more folks chime in. Overall though, the sentiment is looking good.

image

2 Likes

While I think that the TransferStake would allow this process to be easier, I don’t think that the intention of this was specifically focused around this goal, and really, this would be a consequence of fixing more foundational issue of locking node runners into their validation vs servicer split as opposed to locking them into simply remaining on the network.

It’s helpful to think about the consequences of such a mechanism outside of the current market conditions. The feels like a great way for large sized validators to quickly unstake and dump without giving the rest of the market sufficient time to respond to such a large event.

In reality, this current issue has been caused by having the current Validator vs Servicer economic choice that node runners currently have to make coupled with the 21 day waiting period. The 21 day lock up period was designed under the assumptions that there wouldn’t be this dynamic choice of stake allocation that needed to happen. Having a cap to how much a Servicer is able to stack rewards further complicated this choice. The point of this 21 days wasn’t to lock the node runner into a specific configuration choice, those didn’t exist when that design choice was made, it was to lock the node runner into providing value to our network.

TransferStake could allow node runners to remain locked into providing value on the network through some configuration while also alleviating the pain points of locking node runners into how they provide value back to the network.

2 Likes

@blockjoe This is well said about the current dilemma and what TransferStake aims to solve.

I was thinking about it some more. To add onto my point about a diverse validator network, this pocket lockup makes it extremely hard for someone to “swoop” in and protect the network in the event that there is an attack without being punished for it. Let’s say as an example: X entity decides to take up 50% of the existing validator spots. For someone to dilute that, they’d have to bear the burden of knowing that their pocket would be locked up in 21 days, not exactly incentivizing for folks to actually participate. Additionally… if X entity unintentionally grabs a large portion of validator spots, they may be incentivized to continue being a validator for simple reason that they’d lose more than to unstake and restake after 21 days. Not ideal either…

I am looking to have a finalized spec up sometime early next week. So if you have any further comments or suggestions, please add them to this thread.

High level changes atm:

  • Fractional transfer stake (below MinStake is possible, but only if receiver is staked)
  • Multisig support scoping to prevent any sort of unauthorized stake attacks. 99% sure this is possible where it is a two step transaction where receiver signs tx first, then sender signs tx second, or vice versa. Still not sure if it’s truly needed, will wait for more convo around it. Not a fan of the multi signing process, would want some additional streamlined tooling around it.
  • Fleshed out TransferStake examples with before and after states

Edit: Engineering related - requiring two signatures is no problemo.

1 Like

Found this tweet:

" On Aug 1st, over 3300 nodes began unstaking across the network. Currently there are 7,150 nodes unstaking from the network totaling over 112m $pokt. We are not sure if these nodes are upping their stake in preparation of PIP-22 or if they’ve decided to move providers."

Subjectively speaking, I don’t think that we should ever be in a spot where we have to guess if our network are consolidating or selling. TranferStake helps solves this problem

3 Likes

I agree with and fully support this proposal. Changing stake amounts across nodes is cumbersome, time-consuming, and create too much friction (read: lock-in) with service proiders . The unstaking process (because of the 21-day unstaking period) also make the network less adaptable to change. This is an elegant solution that keeps the tokens staked while providing more flexibility / adaptability for node runners.

Hm. It just came to mind, but will lean on Core team to see if this is a viable security concern.

I was hypothesizing a grinding attack where validators would brute force favorable addresses (key pairs) and transferStake to these generated addresses to be the next block proposer. Not sure how feasible this is, given the pseudo randominess/ticket system of our block proposer code. I’ll need to reread the code and think about it some more, but wanted to put it here in case anyone else wants to dig further.

1 Like

Another concern I have is that it is possible for a runner to game PIP22.

For example sessions last 4 blocks it is possible for a runner to create a script which monitors when a node is in session. At which point it can shift pokt from nodes which aren’t in session, to nodes which are in session gaining a boost on rewards once the session ends. I think there needs to be at least a 4block “cool down” on transfer stake to avoid this happening.

3 Likes

I think that’s a wonderful call out, thank you for this. I believe the “transfer stake only happens at a new session block” is totally valid approach and something that may be covered already in the proposal. Interesting enough, there is similiar logic we already do for unstaking validators pocket-core/valStateChanges.go at 629a38891850507c4374bdd8d75cbdfd343d469c · pokt-network/pocket-core · GitHub

1 Like