From 26d2f4180d41a583548602eb96936b67f9ac50e2 Mon Sep 17 00:00:00 2001 From: "razvan.angheluta" Date: Tue, 9 Sep 2025 13:20:27 +0300 Subject: [PATCH 1/4] Continuous Staking ACP --- ACPs/236-continuous-staking/README.md | 101 ++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 ACPs/236-continuous-staking/README.md diff --git a/ACPs/236-continuous-staking/README.md b/ACPs/236-continuous-staking/README.md new file mode 100644 index 00000000..22d38f87 --- /dev/null +++ b/ACPs/236-continuous-staking/README.md @@ -0,0 +1,101 @@ +| ACP | 236 | +|:--------------|:------------------------------------------------------------| +| **Title** | Continuous Staking | +| **Author(s)** | Razvan Angheluta ([@rrazvan1](https://github.com/rrazvan1)) | +| **Status** | | +| **Track** | Standards | + +## Abstract + +This proposal introduces continuous staking for validators on the Avalanche P-Chain. Validators can stake their tokens +continuously, allowing their stake to compound over time. + +## Motivation + +The current staking system on the Avalanche P-Chain restricts flexibility for stakers, limiting their ability to respond +to changing market conditions or liquidity needs. Managing a large number of nodes is also challenging, as re-staking at +the end of each period is labor-intensive, time-consuming, and poses security risks due to +the required transaction signing. Additionally, tokens can remain idle at the end of a staking period +until stakers initiate the necessary transactions to stake them again. + +## Specification + +When validators wish to start staking, they submit an `AddContinuousValidatorTx`, specifying the desired cycle +duration (period). To stop staking at any time, they submit a `StopContinuousValidatorTx`. + +Note: Submitting an AddContinuousValidatorTx immediately followed by a StopContinuousValidatorTx effectively replicates +the behavior of the current staking system. + +### New P-Chain Transaction Types + +The following new transaction types are introduced on the P-Chain to support this functionality: + +- `AddContinuousValidatorTx` +- `StopContinuousValidatorTx` + +```golang +type AddContinuousValidatorTx struct { + // Metadata, inputs and outputs + BaseTx `serialize:"true"` + + // Node ID of the validator + ValidatorNodeID ids.NodeID `serialize:"true" json:"validatorNodeID"` + + // Period (in seconds). + Period uint64 `serialize:"true" json:"period"` + + // [Signer] is the BLS key for this validator. + Signer signer.Signer `serialize:"true" json:"signer"` + + // Where to send staked tokens when done validating + StakeOuts []*avax.TransferableOutput `serialize:"true" json:"stake"` + + // Where to send validation rewards when done validating + ValidatorRewardsOwner fx.Owner `serialize:"true" json:"validationRewardsOwner"` + + // Where to send delegation rewards when done validating + DelegatorRewardsOwner fx.Owner `serialize:"true" json:"delegationRewardsOwner"` + + // Fee this validator charges delegators as a percentage, times 10,000 + // For example, if this validator has DelegationShares=300,000 then they + // take 30% of rewards from delegators + DelegationShares uint32 `serialize:"true" json:"shares"` + + // Weight of this validator used when sampling + Wght uint64 `serialize:"true" json:"weight"` +} +``` + +```golang +type StopContinuousValidatorTx struct { + // Metadata, inputs and outputs + BaseTx `serialize:"true"` + + // ID of the tx that created the continuous validator. + TxID ids.ID `serialize:"true" json:"txID"` + + // Authorizes this validator to be stopped. + // It is a BLS Proof of Possession signature using validator key of the TxID. + StopSignature [bls.SignatureLen]byte `serialize:"true" json:"stopSignature"` +} +``` + +### New Transactions + +- P-Chain + - `AddContinuousValidatorTx` + - `StopContinuousValidatorTx` + +## Backwards Compatibility + +This change requires a network upgrade to make sure that all validators are able to verify and execute the new +introduced transactions. + +Another subsequent ACP could eventually remove `AddPermissionlessValidatorTx`, and use `AddContinuousValidatorTx` and +`StopContinuousValidatorTx` to replicate the same behaviour. + +## Acknowledgements + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From 8be034c4f4ed67c867ec2cedbdc021bb19844104 Mon Sep 17 00:00:00 2001 From: "razvan.angheluta" Date: Tue, 9 Sep 2025 19:06:54 +0300 Subject: [PATCH 2/4] Add considerations + small clarifications --- ACPs/236-continuous-staking/README.md | 76 ++++++++++++++++----------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/ACPs/236-continuous-staking/README.md b/ACPs/236-continuous-staking/README.md index 22d38f87..0c211c19 100644 --- a/ACPs/236-continuous-staking/README.md +++ b/ACPs/236-continuous-staking/README.md @@ -35,34 +35,34 @@ The following new transaction types are introduced on the P-Chain to support thi ```golang type AddContinuousValidatorTx struct { - // Metadata, inputs and outputs - BaseTx `serialize:"true"` - - // Node ID of the validator - ValidatorNodeID ids.NodeID `serialize:"true" json:"validatorNodeID"` - - // Period (in seconds). - Period uint64 `serialize:"true" json:"period"` - - // [Signer] is the BLS key for this validator. - Signer signer.Signer `serialize:"true" json:"signer"` - - // Where to send staked tokens when done validating - StakeOuts []*avax.TransferableOutput `serialize:"true" json:"stake"` - - // Where to send validation rewards when done validating - ValidatorRewardsOwner fx.Owner `serialize:"true" json:"validationRewardsOwner"` - - // Where to send delegation rewards when done validating - DelegatorRewardsOwner fx.Owner `serialize:"true" json:"delegationRewardsOwner"` - - // Fee this validator charges delegators as a percentage, times 10,000 - // For example, if this validator has DelegationShares=300,000 then they - // take 30% of rewards from delegators - DelegationShares uint32 `serialize:"true" json:"shares"` +// Metadata, inputs and outputs +BaseTx `serialize:"true"` + +// Node ID of the validator +ValidatorNodeID ids.NodeID `serialize:"true" json:"nodeID"` - // Weight of this validator used when sampling - Wght uint64 `serialize:"true" json:"weight"` +// Period (in seconds). +Period uint64 `serialize:"true" json:"period"` + +// [Signer] is the BLS key for this validator. +Signer signer.Signer `serialize:"true" json:"signer"` + +// Where to send staked tokens when done validating +StakeOuts []*avax.TransferableOutput `serialize:"true" json:"stake"` + +// Where to send validation rewards when done validating +ValidatorRewardsOwner fx.Owner `serialize:"true" json:"validationRewardsOwner"` + +// Where to send delegation rewards when done validating +DelegatorRewardsOwner fx.Owner `serialize:"true" json:"delegationRewardsOwner"` + +// Fee this validator charges delegators as a percentage, times 10,000 +// For example, if this validator has DelegationShares=300,000 then they +// take 30% of rewards from delegators +DelegationShares uint32 `serialize:"true" json:"shares"` + +// Weight of this validator used when sampling +Wght uint64 `serialize:"true" json:"weight"` } ``` @@ -75,7 +75,7 @@ type StopContinuousValidatorTx struct { TxID ids.ID `serialize:"true" json:"txID"` // Authorizes this validator to be stopped. - // It is a BLS Proof of Possession signature using validator key of the TxID. + // It is a BLS Proof of Possession signature of the TxID using validator key. StopSignature [bls.SignatureLen]byte `serialize:"true" json:"stopSignature"` } ``` @@ -83,16 +83,28 @@ type StopContinuousValidatorTx struct { ### New Transactions - P-Chain - - `AddContinuousValidatorTx` - - `StopContinuousValidatorTx` + - `AddContinuousValidatorTx` + - `StopContinuousValidatorTx` ## Backwards Compatibility This change requires a network upgrade to make sure that all validators are able to verify and execute the new introduced transactions. -Another subsequent ACP could eventually remove `AddPermissionlessValidatorTx`, and use `AddContinuousValidatorTx` and -`StopContinuousValidatorTx` to replicate the same behaviour. +Another subsequent ACP could eventually remove `AddPermissionlessValidatorTx`, since the old staking behaviour is +replicable by using the newly added transactions. + +## Considerations + +Continuous staking makes it easier for users to keep their funds staked longer than with fixed-period staking, since it +involves fewer transactions, lower friction, and reduced risks. +Greater staking participation leads to stronger overall network security. + +Validators benefit by not having to manually restart at the end of each cycle, which reduces transaction volume and the +risk of network congestion. + +However, the risk per cycle slightly increases depending on cycle length and validator performance. For example, missing +five days in a one-year cycle may still yield rewards, whereas missing five days in a two-week cycle may affect rewards. ## Acknowledgements From 4866d9b72879130dac8b50b89515841908c228d6 Mon Sep 17 00:00:00 2001 From: "razvan.angheluta" Date: Fri, 19 Sep 2025 13:56:50 +0300 Subject: [PATCH 3/4] Add clarifications --- ACPs/236-continuous-staking/README.md | 87 +++++++++++++++------------ 1 file changed, 48 insertions(+), 39 deletions(-) diff --git a/ACPs/236-continuous-staking/README.md b/ACPs/236-continuous-staking/README.md index 0c211c19..5587e820 100644 --- a/ACPs/236-continuous-staking/README.md +++ b/ACPs/236-continuous-staking/README.md @@ -8,7 +8,7 @@ ## Abstract This proposal introduces continuous staking for validators on the Avalanche P-Chain. Validators can stake their tokens -continuously, allowing their stake to compound over time. +continuously, allowing their stake to compound over time, accruing rewards once per specified cycle. ## Motivation @@ -20,52 +20,64 @@ until stakers initiate the necessary transactions to stake them again. ## Specification -When validators wish to start staking, they submit an `AddContinuousValidatorTx`, specifying the desired cycle -duration (period). To stop staking at any time, they submit a `StopContinuousValidatorTx`. +Continuous staking introduces a mechanism that allows validators to remain staked indefinitely, without having to +manually submit new staking transactions at the end of each period. -Note: Submitting an AddContinuousValidatorTx immediately followed by a StopContinuousValidatorTx effectively replicates +Instead of committing to a fixed end time upfront, validators specify a cycle duration (period) when they +submit an `AddContinuousValidatorTx`. At the end of each cycle, the validator is automatically re-staked for a new cycle +of the same duration, unless the validator has submitted a `StopContinuousValidatorTx`. + +Rewards accrue once per cycle, and they are automatically added to principal in subsequent cycles. + +At the end of each cycle, if the updated stake weight (previous stake + staking rewards + delegatee rewards) exceeds the +maximum stake limit defined in the network configuration, the excess amount is automatically withdrawn and sent to the +wallets specified in the original transaction. + +Note: Submitting an `AddContinuousValidatorTx` immediately followed by a `StopContinuousValidatorTx` replicates the behavior of the current staking system. ### New P-Chain Transaction Types The following new transaction types are introduced on the P-Chain to support this functionality: -- `AddContinuousValidatorTx` -- `StopContinuousValidatorTx` +#### AddContinuousValidatorTx ```golang type AddContinuousValidatorTx struct { -// Metadata, inputs and outputs -BaseTx `serialize:"true"` - -// Node ID of the validator -ValidatorNodeID ids.NodeID `serialize:"true" json:"nodeID"` - -// Period (in seconds). -Period uint64 `serialize:"true" json:"period"` - -// [Signer] is the BLS key for this validator. -Signer signer.Signer `serialize:"true" json:"signer"` - -// Where to send staked tokens when done validating -StakeOuts []*avax.TransferableOutput `serialize:"true" json:"stake"` - -// Where to send validation rewards when done validating -ValidatorRewardsOwner fx.Owner `serialize:"true" json:"validationRewardsOwner"` - -// Where to send delegation rewards when done validating -DelegatorRewardsOwner fx.Owner `serialize:"true" json:"delegationRewardsOwner"` - -// Fee this validator charges delegators as a percentage, times 10,000 -// For example, if this validator has DelegationShares=300,000 then they -// take 30% of rewards from delegators -DelegationShares uint32 `serialize:"true" json:"shares"` - -// Weight of this validator used when sampling -Wght uint64 `serialize:"true" json:"weight"` + // Metadata, inputs and outputs + BaseTx `serialize:"true"` + + // Node ID of the validator + ValidatorNodeID ids.NodeID `serialize:"true" json:"nodeID"` + + // Period (in seconds). + Period uint64 `serialize:"true" json:"period"` + + // [Signer] is the BLS key for this validator. + Signer signer.Signer `serialize:"true" json:"signer"` + + // Where to send staked tokens when done validating + StakeOuts []*avax.TransferableOutput `serialize:"true" json:"stake"` + + // Where to send validation rewards when done validating + ValidatorRewardsOwner fx.Owner `serialize:"true" json:"validationRewardsOwner"` + + // Where to send delegation rewards when done validating + DelegatorRewardsOwner fx.Owner `serialize:"true" json:"delegationRewardsOwner"` + + // Fee this validator charges delegators as a percentage, times 10,000 + // For example, if this validator has DelegationShares=300,000 then they + // take 30% of rewards from delegators + DelegationShares uint32 `serialize:"true" json:"shares"` + + // Weight of this validator used when sampling + Wght uint64 `serialize:"true" json:"weight"` } + ``` +#### StopContinuousValidatorTx + ```golang type StopContinuousValidatorTx struct { // Metadata, inputs and outputs @@ -80,11 +92,8 @@ type StopContinuousValidatorTx struct { } ``` -### New Transactions - -- P-Chain - - `AddContinuousValidatorTx` - - `StopContinuousValidatorTx` +`StopSignature` is the BLS Proof of Possession signature of the tx ID of `AddContinuousValidatorTx` using the validator +key. ## Backwards Compatibility From f0fc021493cf61c22f99e5f737986da5f50f4a24 Mon Sep 17 00:00:00 2001 From: "razvan.angheluta" Date: Wed, 24 Sep 2025 17:18:51 +0300 Subject: [PATCH 4/4] Add clarifications + extra tx --- ACPs/236-continuous-staking/README.md | 48 ++++++++++++++++++++------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/ACPs/236-continuous-staking/README.md b/ACPs/236-continuous-staking/README.md index 5587e820..689dea79 100644 --- a/ACPs/236-continuous-staking/README.md +++ b/ACPs/236-continuous-staking/README.md @@ -23,15 +23,27 @@ until stakers initiate the necessary transactions to stake them again. Continuous staking introduces a mechanism that allows validators to remain staked indefinitely, without having to manually submit new staking transactions at the end of each period. -Instead of committing to a fixed end time upfront, validators specify a cycle duration (period) when they -submit an `AddContinuousValidatorTx`. At the end of each cycle, the validator is automatically re-staked for a new cycle -of the same duration, unless the validator has submitted a `StopContinuousValidatorTx`. - -Rewards accrue once per cycle, and they are automatically added to principal in subsequent cycles. - -At the end of each cycle, if the updated stake weight (previous stake + staking rewards + delegatee rewards) exceeds the -maximum stake limit defined in the network configuration, the excess amount is automatically withdrawn and sent to the -wallets specified in the original transaction. +Instead of committing to a fixed end time upfront, validators specify a cycle duration (period) when they submit an +AddContinuousValidatorTx. At the end of each cycle, the validator is automatically re-staked for a new cycle of the same +duration, unless the validator has submitted a StopContinuousValidatorTx. If a validator submits a +StopContinuousValidatorTx during a cycle, the validator will continue validating until the end of the current cycle, at +which point the validator exits and funds unlock. The minimum and maximum cycle lengths follow the same protocol +parameters as before (`MinStakeDuration` and `MaxStakeDuration`). + +Delegators interact with continuous validators in the same way as with fixed-period validators, and the same constraints +apply: a delegation period must fit entirely within the validator’s cycle. Delegators cannot delegate across multiple +cycles, since there is no guarantee that a validator will continue validating after the current cycle. + +Rewards accrue once per cycle, and they are automatically added to principal in subsequent cycles, both for validator +rewards and for delegation rewards. If the updated stake weight (previous stake + staking rewards + delegatee rewards) +exceeds the maximum stake limit defined in the network configuration, the excess amount is automatically withdrawn and +sent to `ValidatorRewardsOwner` and `DelegatorRewardsOwner`. + +Because of the way `RewardValidatorTx` is structured, multiple instances cannot be issued without resulting in identical +transaction IDs. To resolve this, a new transaction type has been introduced for both rewarding and stopping continuous +validators: `RewardContinuousValidatorTx`. Along with the validator’s creation transaction ID, it also includes a +timestamp. For simplicity and consistency, any stake exceeding the maximum limit is withdrawn from the validator, and +the resulting UTXOs are tied to the `RewardContinuousValidatorTx` ID. Note: Submitting an `AddContinuousValidatorTx` immediately followed by a `StopContinuousValidatorTx` replicates the behavior of the current staking system. @@ -95,14 +107,26 @@ type StopContinuousValidatorTx struct { `StopSignature` is the BLS Proof of Possession signature of the tx ID of `AddContinuousValidatorTx` using the validator key. +#### RewardContinuousValidatorTx + +```golang +type RewardContinuousValidatorTx struct { + // ID of the tx that created the validator being removed/rewarded + TxID ids.ID `serialize:"true" json:"txID"` + + // End time of the validator. + Timestamp uint64 `serialize:"true" json:"timestamp"` + + unsignedBytes []byte // Unsigned byte representation of this data +} + +``` + ## Backwards Compatibility This change requires a network upgrade to make sure that all validators are able to verify and execute the new introduced transactions. -Another subsequent ACP could eventually remove `AddPermissionlessValidatorTx`, since the old staking behaviour is -replicable by using the newly added transactions. - ## Considerations Continuous staking makes it easier for users to keep their funds staked longer than with fixed-period staking, since it