Skip to content
This repository has been archived by the owner on Jan 10, 2025. It is now read-only.

Commit

Permalink
stake-pool-py: Add and use new decrease instruction (#5334)
Browse files Browse the repository at this point in the history
  • Loading branch information
joncinque authored Sep 26, 2023
1 parent 00b6727 commit 1d5e088
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 7 deletions.
7 changes: 4 additions & 3 deletions stake-pool/py/stake_pool/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -569,17 +569,18 @@ async def decrease_validator_stake(

txn = Transaction()
txn.add(
sp.decrease_validator_stake(
sp.DecreaseValidatorStakeParams(
sp.decrease_validator_stake_with_reserve(
sp.DecreaseValidatorStakeWithReserveParams(
program_id=STAKE_POOL_PROGRAM_ID,
stake_pool=stake_pool_address,
staker=staker.public_key,
withdraw_authority=withdraw_authority,
validator_list=stake_pool.validator_list,
reserve_stake=stake_pool.reserve_stake,
validator_stake=validator_stake,
transient_stake=transient_stake,
clock_sysvar=SYSVAR_CLOCK_PUBKEY,
rent_sysvar=SYSVAR_RENT_PUBKEY,
stake_history_sysvar=SYSVAR_STAKE_HISTORY_PUBKEY,
system_program_id=sys.SYS_PROGRAM_ID,
stake_program_id=STAKE_PROGRAM_ID,
lamports=lamports,
Expand Down
78 changes: 78 additions & 0 deletions stake-pool/py/stake_pool/instructions.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,42 @@ class DecreaseValidatorStakeParams(NamedTuple):
"""Seed to used to create the transient stake account."""


class DecreaseValidatorStakeWithReserveParams(NamedTuple):
"""(Staker only) Decrease active stake on a validator, eventually moving it to the reserve"""

# Accounts
program_id: PublicKey
"""SPL Stake Pool program account."""
stake_pool: PublicKey
"""`[]` Stake pool."""
staker: PublicKey
"""`[s]` Staker."""
withdraw_authority: PublicKey
"""`[]` Stake pool withdraw authority."""
validator_list: PublicKey
"""`[w]` Validator stake list storage account."""
reserve_stake: PublicKey
"""`[w]` Stake pool's reserve."""
validator_stake: PublicKey
"""`[w]` Canonical stake to split from."""
transient_stake: PublicKey
"""`[w]` Transient stake account to receive split."""
clock_sysvar: PublicKey
"""`[]` Clock sysvar."""
stake_history_sysvar: PublicKey
"""'[]' Stake history sysvar."""
system_program_id: PublicKey
"""`[]` System program."""
stake_program_id: PublicKey
"""`[]` Stake program."""

# Params
lamports: int
"""Amount of lamports to split into the transient stake account."""
transient_stake_seed: int
"""Seed to used to create the transient stake account."""


class IncreaseValidatorStakeParams(NamedTuple):
"""(Staker only) Increase stake on a validator from the reserve account."""

Expand Down Expand Up @@ -529,6 +565,10 @@ class InstructionType(IntEnum):
WITHDRAW_SOL = 16
CREATE_TOKEN_METADATA = 17
UPDATE_TOKEN_METADATA = 18
INCREASE_ADDITIONAL_VALIDATOR_STAKE = 19
DECREASE_ADDITIONAL_VALIDATOR_STAKE = 20
DECREASE_VALIDATOR_STAKE_WITH_RESERVE = 21
REDELEGATE = 22


INITIALIZE_LAYOUT = Struct(
Expand All @@ -544,6 +584,12 @@ class InstructionType(IntEnum):
"transient_stake_seed" / Int64ul,
)

MOVE_STAKE_LAYOUT_WITH_EPHEMERAL_STAKE = Struct(
"lamports" / Int64ul,
"transient_stake_seed" / Int64ul,
"ephemeral_stake_seed" / Int64ul,
)

UPDATE_VALIDATOR_LIST_BALANCE_LAYOUT = Struct(
"start_index" / Int32ul,
"no_merge" / Int8ul,
Expand Down Expand Up @@ -588,6 +634,9 @@ class InstructionType(IntEnum):
InstructionType.WITHDRAW_SOL: AMOUNT_LAYOUT,
InstructionType.CREATE_TOKEN_METADATA: TOKEN_METADATA_LAYOUT,
InstructionType.UPDATE_TOKEN_METADATA: TOKEN_METADATA_LAYOUT,
InstructionType.DECREASE_ADDITIONAL_VALIDATOR_STAKE: MOVE_STAKE_LAYOUT_WITH_EPHEMERAL_STAKE,
InstructionType.INCREASE_ADDITIONAL_VALIDATOR_STAKE: MOVE_STAKE_LAYOUT_WITH_EPHEMERAL_STAKE,
InstructionType.DECREASE_VALIDATOR_STAKE_WITH_RESERVE: MOVE_STAKE_LAYOUT,
},
),
)
Expand Down Expand Up @@ -988,6 +1037,35 @@ def decrease_validator_stake(params: DecreaseValidatorStakeParams) -> Transactio
)


def decrease_validator_stake_with_reserve(params: DecreaseValidatorStakeWithReserveParams) -> TransactionInstruction:
"""Creates instruction to decrease the stake on a validator."""
return TransactionInstruction(
keys=[
AccountMeta(pubkey=params.stake_pool, is_signer=False, is_writable=False),
AccountMeta(pubkey=params.staker, is_signer=True, is_writable=False),
AccountMeta(pubkey=params.withdraw_authority, is_signer=False, is_writable=False),
AccountMeta(pubkey=params.validator_list, is_signer=False, is_writable=True),
AccountMeta(pubkey=params.reserve_stake, is_signer=False, is_writable=True),
AccountMeta(pubkey=params.validator_stake, is_signer=False, is_writable=True),
AccountMeta(pubkey=params.transient_stake, is_signer=False, is_writable=True),
AccountMeta(pubkey=params.clock_sysvar, is_signer=False, is_writable=False),
AccountMeta(pubkey=params.stake_history_sysvar, is_signer=False, is_writable=False),
AccountMeta(pubkey=params.system_program_id, is_signer=False, is_writable=False),
AccountMeta(pubkey=params.stake_program_id, is_signer=False, is_writable=False),
],
program_id=params.program_id,
data=INSTRUCTIONS_LAYOUT.build(
dict(
instruction_type=InstructionType.DECREASE_VALIDATOR_STAKE_WITH_RESERVE,
args={
'lamports': params.lamports,
'transient_stake_seed': params.transient_stake_seed
}
)
)
)


def create_token_metadata(params: CreateTokenMetadataParams) -> TransactionInstruction:
"""Creates an instruction to create metadata using the mpl token metadata program for the pool token."""

Expand Down
2 changes: 1 addition & 1 deletion stake-pool/py/tests/test_a_time_sensitive.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ async def test_increase_decrease_this_is_very_slow(async_client, validators, pay
data = resp['result']['value']['data']
validator_list = ValidatorList.decode(data[0], data[1])
for validator in validator_list.validators:
assert validator.transient_stake_lamports == decrease_amount
assert validator.transient_stake_lamports == decrease_amount + stake_rent_exemption
assert validator.active_stake_lamports == increase_amount - decrease_amount + minimum_amount

print("Waiting for epoch to roll over")
Expand Down
6 changes: 3 additions & 3 deletions stake-pool/py/tests/test_bot_rebalance.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,18 @@ async def test_rebalance_this_is_very_slow(async_client, validators, payer, stak
max_in_reserve = total_lamports - minimum_amount * len(validators)
await rebalance(ENDPOINT, stake_pool_address, payer, max_in_reserve / LAMPORTS_PER_SOL)

# should still only have minimum left + rent exemptions from increase
# should still only have minimum left
resp = await async_client.get_account_info(stake_pool.reserve_stake, commitment=Confirmed)
reserve_lamports = resp['result']['value']['lamports']
assert reserve_lamports == stake_rent_exemption * (1 + len(validator_list.validators)) + MINIMUM_RESERVE_LAMPORTS
assert reserve_lamports == stake_rent_exemption + MINIMUM_RESERVE_LAMPORTS

# should all be decreasing now
resp = await async_client.get_account_info(validator_list_address, commitment=Confirmed)
data = resp['result']['value']['data']
validator_list = ValidatorList.decode(data[0], data[1])
for validator in validator_list.validators:
assert validator.active_stake_lamports == minimum_amount
assert validator.transient_stake_lamports == max_in_reserve / len(validators) - stake_rent_exemption
assert validator.transient_stake_lamports == max_in_reserve / len(validators)

# Test case 3: Do nothing
print('Waiting for next epoch')
Expand Down

0 comments on commit 1d5e088

Please # to comment.