Introduction
We are enhancing the VideoCoin Network with a major feature called DPoS (Distributed Proof of Stake) that mitigates the risk of opening up the Network to third party(untrusted) Worker nodes. DPoS prompts the participation of the VideoCoin token holders in securing the Network by selecting and backing the Worker nodes which result in ranking these nodes. This makes the Network dynamic and secure by making all the stakeholders of the Network to actively participate and get rewarded.
DPoS has already successfully been used in several Blockchains such as Cosmos Hub, EoS and Tezos with some variations. It is mostly used to secure the Block producers in these Networks. In VideoCoin we are using this algorithm to ensure the fault-free operation of the Worker nodes.
What is Proof of Stake and why do we need it on VideoCoin network?
The work outsourced to Worker nodes is being verified and rewarded by the Network. A Worker node may fault either a due to compute resources falling below commitment or with an intention to attack Network. Both these issues can be avoided, if the Worker node is required to stake an amount proportionally very high compared to the rewards and it will lose a portion of the amount.
Delegated Proof of Stake and Securing the Network
New Worker nodes joining the network may not have enough VIDs to stake to get the work. Delegated Proof of Stake allows any VID holders to delegate their tokens to a Worker node. These delegations will be rewarded with a portion of the rewards that Worker node receives. It also has an associated risk of losing portion of the delegated amount, if the worker faults. But the overall dynamics of the delegation and associated rewards/losses will result in ranking the worker nodes based on the amount of delegations received. This ranking can be further supplemented with reputation metrics based on the work history and wattage capacity. This creates an environment where worker nodes will be competing for higher ranking in order to receive more work, which in turn results in a secure Network of well behaving worker nodes.
Core Components of VideoCoin DPoS
Staking Manager
VideoCoin Network uses a Staking Manager that maintains an on-chain database of all the Worker Nodes, Delegators and their delegations. This database also maintains information related to worker’s capacity and work history that helps in ranking the worker.
A Worker node is required to self-stake some minimum VIDs as well as secure a minimum total stake that can come from other VID holders in the Network called delegators . The Worker also needs to wait a certain amount of period before obtaining the work.
Any VID holders can become delegators and choose a Worker node for delegation. Delegations are bonded to the worker and a certain time period has to elapse while withdrawing the delegation.
Slashing
When a Worker node is faulted, some portion of the the stake(self+delegated) is slashed and transferred to a Network Maintenance pool account. Slashing may occur due to either failure to submit proof-of-transcode, or failed proof-verification. It also may occur due to unavailability of the miner to perform the transcode mining when in bonded state.
Reward Distribution
Worker nodes earn rewards for the work. However, some percentage of the reward amount is distributed to delegators (including self) in proportion to amounts being delegated. Reward amounts can be withdrawn immediately and are not included in slashing.
Worker State
After transcoder registered it can be in one of the four states:
-
BONDING
-
BONDED
-
UNBONDING
-
UNBONDED
Contract variables:
-
transcoderApprovalPeriod
. Should pass after registration to enter BONDED state. This time can be used to run tests for transcodeer. -
unbondingPeriod
. After delegator (including transcoder) made withdrawal request this amount of time should pass for request to become withdrawable. During this time funds still can be slashed. -
minSelfStake
. Required funds that transcoder should lock in the contract to become BONDED. -
minDelegation
. Minimum amount of delegated funds that will be accepted.
BONDING
After transcoder registered it should wait for transcoderApprovalPeriod
. During this time transcoder can accept delegations from any other delegator, and transcoder must stake minSelfStake
funds.
Once two conditions are satisfied transcoder becomes bonded.
If transcoder wishes to withdraw funds while BONDING funds will be transfered immediatly.
BONDED
BONDED transcoder is eligible for work and rewards. In current implementaton transcoder selection is performed offchain, using information stored in staking contract.
If BONDED transcoder wishes to withdraw funds it must wait for unbondingPeriod
. If after withdrawal transcoder has less than minSelfStake
transcoder enters UNBONDING state.
Also while BONDED - transcoder can be slashed/jailed and become UNBONDED.
UNBONDING
This state is required to prevent transcoder from manipulating stake in such way that will allow to withdraw large part of it without waiting for unbondingPeriod
.
Example that was possible before introducing UNBONDING:
-
transcoder BONDED with stake 100 vid (min self stake)
-
transcoder tries to withdraw 1 vid. Withdraw protected with
unbondingPeriod
. Enters BONDING state. -
transcoder withdraws the rest (99 vid), while in BONDING state funds trasnferred immediatly.
Transcoder in UNBONDING can be slashed and enter UNBONDED state. If unbondingPeriod
passes for requested withdrawal transcoder enters BONDING state.
UNBONDED
In current implementation this state is used exclusively for slashed/jailed transcoders. The only way to leave this state is for the contract owner to unjail transcoder.
In such case transcoder enters BONDING, or BONDED if stake is larger than minSelfStake
.
To become a transcoder you need to stake a minimal amount required. Transcoder is bonded if approval period passes and self stake is higher than minimum stake. Transcoders and delegators can withdraw stake after a set amount of time.
API
setSelfMinStake
Setter for minimum self-stake, i.e. bonding treshold.
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | uint256 | amount | minimum self stake amount |
setApprovalPeriod
Setter for approval period
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | uint256 | period | aproval period in seconds |
setZone
Setter for trancoder zone.
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | address | addr | transcoder address |
input | uint256 | zone | zone id |
setSlashFundAddress
Can be 0x0
Setter for slash pool address.
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | address | addr | new slash pool address |
setCapacity
Setter for trancoder capacity.
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | address | addr | transcoder address |
input | uint256 | capacity | transcoder capacity in uwatt |
registerTranscoder
rate parameter not used for now
Method to register as transcoder.
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | uint256 | rate | Percentage of rewards that the transcoder will share with delegators |
delegate
Needs to send minimal delegation amount.
Delegate tokens to a transcoder. Transcoders will call this to self-delegate.
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | address | transcoderAddr | Transcoder address. |
requestUnbonding
Requests get approved immediately if tcoder`s state is BONDING or UNBONDED
Delegator requests stake unbonding. Delegator has to wait for unbondingPeriod before calling withdrawStake() with the returned ID.
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | address | transcoderAddr | transcoder address from which to unbond |
input | uint256 | amount | amount to unbond |
output | uint256 | N/A | N/A |
withdrawPending
Callable by both tcoders & delegators. Delegators can also withdraw no matter what the tcoder state is if they made an unbonding requested and the wait period passed. If transfer cannot be withdrawn transaction will fail.
Withdraw first pending unbonding request.
withdrawAllPending
Callable by both tcoders & delegators. Delegators can also withdraw no matter what the tcoder state is if they made an unbonding requested and the wait period passed. Silently returns if there are no pending transfers that can be withdrawn.
Withdraw all pending unbonding requests.
pendingWithdrawalsExist
Query state if there are any pending withdrawals ready to be executed.
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
output | bool | N/A | N/A |
withdrawStake
Callable by both tcoders & delegators. Delegators can also withdraw no matter what the tcoder state is if they made an unbonding requested and the wait period passed.
Withdraw stake in transcoder.
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | uint256 | unbondingID | ID of unbonding request |
output | bool | N/A | N/A |
getUnbondingRequest
If the request does not exist all the fields will be 0
Getter for unbonding requests
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | address | delegatorAddr | delegator address |
input | uint256 | unbondingID | unbonding request ID for which to rebond |
output | undefined | N/A | N/A |
slash
Callable only by a staking manager. Increments the slash counter for lazy slashing of delegators. Transcoder total stake is slashed when method is called. Actual delegator stake values are updated lazily when withdraw, delegate or unbond are called.
Slash the transcoder stake including it`s delegators.
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | address | addr | transcoder address |
output | bool | N/A | N/A |
applySlash
Lazy slash for delegators stakes. Callable from anywhere; if conditions are met it will execute. Applied during bonding or unbonding.
Applies slashing.
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | address | transcoderAddr | transcoder address |
input | address | delegatorAddr | delegator address |
getSlashableAmount
Used for lazy slash for delegators stakes and to compute the real bonded value of the stake
Returns ammount that is up for slashing of a delegator`s stake.
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | address | transcoderAddr | transcoder address |
input | address | delegatorAddr | delegator address |
output | uint256 | N/A | N/A |
jail
Called when slashing
Jail a transcoder.
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | address | transcoderAddr | transcoder address |
unjail
Unjail a transcoder.
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | address | transcoderAddr | transcoder address |
getTotalStake
Get total amount staked for a transcoder
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | address | _addr | transcoder address |
output | uint256 | N/A | N/A |
getSelfStake
Get transcoder self-stake
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | address | _addr | transcoder address |
output | uint256 | N/A | N/A |
getDelegatorStake
Get delegator stake in a transcoder
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | address | transcoderAddr | transcoder address |
input | address | delegAddr | delegator address |
output | uint256 | N/A | N/A |
getTrancoderSlashes
Get number of slashes applied to a transcoder
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | address | transcoderAddr | transcoder address |
output | uint256 | N/A | N/A |
transcodersCount
Get number of registered transcoders. *
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
output | uint256 | N/A | N/A |
getTranscoderState
Used by miner sleection, slashing, rewards. enum TranscoderState { BONDING, BONDED, UNBONDED }
Get the transcoder state
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | address | transcoderAddr | transcoder address |
output | undefined | N/A | N/A |
isJailed
Gettter for jailed state
Input/Output | Data Type | Variable Name | Comment |
---|---|---|---|
input | address | transcoderAddr | transcoder address |
output | bool | N/A | N/A |