Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stake-pool: add bindings to js #2806

Merged
merged 24 commits into from Feb 23, 2022

Conversation

AlexanderRay
Copy link
Contributor

@AlexanderRay AlexanderRay commented Jan 25, 2022

  • add new bindings

    • IncreaseValidatorStake
    • DecreaseValidatorStake
    • UpdateValidatorListBalance
    • UpdateStakePoolBalance
    • CleanupRemovedValidatorEntries
    • DepositStake
  • add new function

    • stakePoolInfo

@joncinque

add new bindings
  | 'IncreaseValidatorStake'
  | 'DecreaseValidatorStake'
  | 'UpdateValidatorListBalance'
  | 'UpdateStakePoolBalance'
  | 'CleanupRemovedValidatorEntries'
@mergify mergify bot added the community Community contribution label Jan 25, 2022
add new bindings
  | 'IncreaseValidatorStake'
  | 'DecreaseValidatorStake'
  | 'UpdateValidatorListBalance'
  | 'UpdateStakePoolBalance'
  | 'CleanupRemovedValidatorEntries'
stake-pool/js/package.json Outdated Show resolved Hide resolved
@joncinque
Copy link
Contributor

As @CMEONE pointed out, it looks like this blasted the changes made during #2681. Could you rebase your changes onto that commit at least?

@AlexanderRay
Copy link
Contributor Author

As @CMEONE pointed out, it looks like this blasted the changes made during #2681. Could you rebase your changes onto that commit at least?

yea, sorry, my fault, will fix it...

@joncinque
Copy link
Contributor

Looks like there are still a few regressions introduced -- could you run this with npm version 7 so that package.lock stays on version 2, and also run the linting / formatting / building?

@AlexanderRay
Copy link
Contributor Author

AlexanderRay commented Jan 26, 2022

Looks like there are still a few regressions introduced -- could you run this with npm version 7 so that package.lock stays on version 2, and also run the linting / formatting / building?

is seems like prettier for some reason has different formatting options in the tests ... checking ...

@CMEONE
Copy link
Contributor

CMEONE commented Jan 27, 2022

@AlexanderRay I just wanted to clarify a small thing: in the code, there are references to stakePoolPubKey, stakePoolProgramAddress, and stakePoolAddress (as function parameters). Is there any difference between the three, or is it possible to make it so that the naming is consistent to avoid any confusion?

@AlexanderRay
Copy link
Contributor Author

@AlexanderRay I just wanted to clarify a small thing: in the code, there are references to stakePoolPubKey, stakePoolProgramAddress, and stakePoolAddress (as function parameters). Is there any difference between the three, or is it possible to make it so that the naming is consistent to avoid any confusion?

fixed

stake-pool/js/package.json Outdated Show resolved Hide resolved
@CMEONE
Copy link
Contributor

CMEONE commented Jan 31, 2022

Again, great work on these bindings! I am receiving an error with the depositSol command from your previous PR:

Program log: Error: First update old validator stake account balances and then pool stake balance

I assume that updateStakePool (added in this PR) would need to be called first to update the stake pool before new stake can be deposited. I also see that updateRequired in stakePoolInfo would tell me if the stake pool needs to be updated.

Is there any way to create an updateStakePoolAndDepositSol function or something that detects automatically if the stake pool needs to be updated (by just checking for the updateRequired part and not running all the other computations in stakePoolInfo) and adds those update instructions along with deposit instructions, otherwise just returns the deposit instructions if an update is not needed? I don't think that this can be done atomically, but it would be nice to have a function that can achieve this functionality in the most efficient way possible.

@CMEONE
Copy link
Contributor

CMEONE commented Feb 1, 2022

Correction to my previous comment: it may be better to remove the detection step entirely and just have a helper function call the two instruction functions and concatenate the instructions. However, this is probably best to have in a separate, third-party library and not in the main bindings.

Copy link
Contributor

@joncinque joncinque left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The meat of this looks really good! A few bits to clean up and fix -- let me know if you have any questions

stake-pool/js/package.json Outdated Show resolved Hide resolved
stake-pool/js/tsconfig.json Outdated Show resolved Hide resolved
stake-pool/js/tsconfig.json Outdated Show resolved Hide resolved
stake-pool/js/test/equal.ts Outdated Show resolved Hide resolved
stake-pool/js/src/buffer-layout.d.ts Outdated Show resolved Hide resolved
stake-pool/js/src/index.ts Outdated Show resolved Hide resolved
stake-pool/js/src/instructions.ts Outdated Show resolved Hide resolved
stake-pool/js/src/utils/stake.ts Outdated Show resolved Hide resolved
stake-pool/js/src/utils/stake.ts Outdated Show resolved Hide resolved
stake-pool/js/src/utils/token.ts Outdated Show resolved Hide resolved
@CMEONE
Copy link
Contributor

CMEONE commented Feb 9, 2022

@AlexanderRay small issue: after doing some testing on devnet, I discovered that withdrawStake doesn't always properly honor the minimum balance for stake accounts:

This is one example of trying to withdraw lamports in a way that technically looks like it would be allowed given the total stake lamports in the validator account but doesn't honor the minimum amount of lamports that must be stored in a stake pool program validator account:

Transaction simulation failed: Error processing Instruction 2: custom program error: 0x17 
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [1]
    Program log: Instruction: Approve
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 2024 of 200000 compute units
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success
    Program 11111111111111111111111111111111 invoke [1]
    Program 11111111111111111111111111111111 success
    Program SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy invoke [1]
    Program log: Instruction: WithdrawStake
    Program log: Attempting to withdraw 99900000 lamports from validator account with 100000000 stake lamports, 1000000 must remain
    Program log: Error: The lamports in the validator stake account is not equal to the minimum
    Program SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy consumed 16664 of 200000 compute units
    Program SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy failed: custom program error: 0x17

Here's another example, this time the amount requested for withdrawal is above the amount available in the validator account, and although there is another validator account that has enough lamports to make up the difference, the bindings still attempt to withdraw more from the first validator account than possible:

Transaction simulation failed: Error processing Instruction 2: custom program error: 0x17 
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [1]
    Program log: Instruction: Approve
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 2024 of 200000 compute units
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success
    Program 11111111111111111111111111111111 invoke [1]
    Program 11111111111111111111111111111111 success
    Program SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy invoke [1]
    Program log: Instruction: WithdrawStake
    Program log: Attempting to withdraw 102282880 lamports from validator account with 100000000 stake lamports, 1000000 must remain
    Program log: Error: The lamports in the validator stake account is not equal to the minimum
    Program SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy consumed 16683 of 200000 compute units
    Program SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy failed: custom program error: 0x17

The bindings have previously dipped into multiple validator accounts and successfully withdrawn stakes from multiple validator accounts in a single transaction, so I know that can't be the issue.

Copy link
Contributor

@joncinque joncinque left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple last bits and this should be good, pending @CMEONE 's issue

stake-pool/js/tsconfig.json Outdated Show resolved Hide resolved
stake-pool/js/src/buffer-layout.d.ts Outdated Show resolved Hide resolved
stake-pool/js/src/copied-from-solana-web3/layout.ts Outdated Show resolved Hide resolved
@AlexanderRay
Copy link
Contributor Author

@AlexanderRay small issue: after doing some testing on devnet, I discovered that withdrawStake doesn't always properly honor the minimum balance for stake accounts:

This is one example of trying to withdraw lamports in a way that technically looks like it would be allowed given the total stake lamports in the validator account but doesn't honor the minimum amount of lamports that must be stored in a stake pool program validator account:

Transaction simulation failed: Error processing Instruction 2: custom program error: 0x17 
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [1]
    Program log: Instruction: Approve
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 2024 of 200000 compute units
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success
    Program 11111111111111111111111111111111 invoke [1]
    Program 11111111111111111111111111111111 success
    Program SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy invoke [1]
    Program log: Instruction: WithdrawStake
    Program log: Attempting to withdraw 99900000 lamports from validator account with 100000000 stake lamports, 1000000 must remain
    Program log: Error: The lamports in the validator stake account is not equal to the minimum
    Program SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy consumed 16664 of 200000 compute units
    Program SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy failed: custom program error: 0x17

Here's another example, this time the amount requested for withdrawal is above the amount available in the validator account, and although there is another validator account that has enough lamports to make up the difference, the bindings still attempt to withdraw more from the first validator account than possible:

Transaction simulation failed: Error processing Instruction 2: custom program error: 0x17 
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [1]
    Program log: Instruction: Approve
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 2024 of 200000 compute units
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success
    Program 11111111111111111111111111111111 invoke [1]
    Program 11111111111111111111111111111111 success
    Program SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy invoke [1]
    Program log: Instruction: WithdrawStake
    Program log: Attempting to withdraw 102282880 lamports from validator account with 100000000 stake lamports, 1000000 must remain
    Program log: Error: The lamports in the validator stake account is not equal to the minimum
    Program SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy consumed 16683 of 200000 compute units
    Program SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy failed: custom program error: 0x17

The bindings have previously dipped into multiple validator accounts and successfully withdrawn stakes from multiple validator accounts in a single transaction, so I know that can't be the issue.

can you please check now if i works properly on your side

@CMEONE
Copy link
Contributor

CMEONE commented Feb 10, 2022

Ok @AlexanderRay I will check if it works and let you know, also for instances where there are more instructions that can be fit into a transaction (like if it has to withdraw stake from multiple validator accounts), how should the instructions be split most optimally (or how should they be grouped in transactions if the unstake requires multiple transactions)?

stake-pool/js/package.json Outdated Show resolved Hide resolved
@CMEONE
Copy link
Contributor

CMEONE commented Feb 15, 2022

@AlexanderRay the minimum balance issue seems to be fixed for withdrawStake, but I am now sometimes getting another error:

ransaction simulation failed: Error processing Instruction 4: custom program error: 0xf 
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [1]
    Program log: Instruction: Approve
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 2024 of 200000 compute units
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success
    Program 11111111111111111111111111111111 invoke [1]
    Program 11111111111111111111111111111111 success
    Program SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy invoke [1]
    Program log: Instruction: WithdrawStake
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]
    Program log: Instruction: Burn
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 2667 of 179733 compute units
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success
    Program Stake11111111111111111111111111111111111111 invoke [2]
    Program Stake11111111111111111111111111111111111111 success
    Program Stake11111111111111111111111111111111111111 invoke [2]
    Program Stake11111111111111111111111111111111111111 success
    Program Stake11111111111111111111111111111111111111 invoke [2]
    Program Stake11111111111111111111111111111111111111 success
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]
    Program log: Instruction: Transfer
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 2781 of 156548 compute units
    Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success
    Program SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy consumed 50390 of 200000 compute units
    Program SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy success
    Program 11111111111111111111111111111111 invoke [1]
    Program 11111111111111111111111111111111 success
    Program SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy invoke [1]
    Program log: Instruction: WithdrawStake
    Program log: Incorrect stake account address for vote vgcDar2pryHvMgPkKaZfh8pQy4BJxv7SpwUG7zinWjG, expected JCds2mFABFyurTV7NCwVSpG1JupXjP2ofjSRn6nCA82h, received HL5ixN3TipmVagAyYxtRW7xVjEwiL9rbJ7nd3RdqoZpY
    Program log: Error: Stake account address not properly derived from the validator address
    Program SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy consumed 49910 of 200000 compute units
    Program SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy failed: custom program error: 0xf

The expected address JCds2mFABFyurTV7NCwVSpG1JupXjP2ofjSRn6nCA82h is an activated stake account with a very low balance, the address input HL5ixN3TipmVagAyYxtRW7xVjEwiL9rbJ7nd3RdqoZpY is an activating stake account with a significantly higher balance, both are pointed to vote vgcDar2pryHvMgPkKaZfh8pQy4BJxv7SpwUG7zinWjG. I ran withdrawStake a few minutes after adding stake to the vgcDar2pryHvMgPkKaZfh8pQy4BJxv7SpwUG7zinWjG from the CLI as a pool manager, I believe the inputted one was the stake account which was just created from CLI but is still activating and unmerged, while the expected one was the original stake account.

@CMEONE
Copy link
Contributor

CMEONE commented Feb 15, 2022

The issue described above also seems to be the reason that CI is now failing.

[2022-02-14T22:11:54.411778810Z DEBUG solana_runtime::message_processor::stable_log] Program SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy invoke [1]
[2022-02-14T22:11:54.413795840Z DEBUG solana_runtime::message_processor::stable_log] Program log: Instruction: WithdrawStake
[2022-02-14T22:11:54.432528349Z DEBUG solana_runtime::message_processor::stable_log] Program log: Incorrect stake account address for vote DiyGABdP7sn1Z3Fdhr394nYcteY4dRKBgaRJDWSWmQGq, expected 9qM4cezSUh9jvBL91PboTrG6kph8gc4UoJJ2NCr4vQYt, received 5U3k2hovWDvFrbmRK4wT4ZTgtiwh3Zg4RSesF2aMd8Rw
[2022-02-14T22:11:54.433012780Z DEBUG solana_runtime::message_processor::stable_log] Program log: Error: Stake account address not properly derived from the validator address

@CMEONE
Copy link
Contributor

CMEONE commented Feb 16, 2022

@AlexanderRay I think the issue is that withdrawStake is including accounts which cannot be used for withdrawal such as transient stake accounts which have not yet been merged with the validator stake account. Would it be possible to remove those from the list of valid stake accounts which can be withdrawn, since that seems to be the source of the error?

numerator: fee.denominator.sub(fee.numerator),
denominator: fee.denominator,
};

for (const type of ['preferred', 'active', 'transient', 'reserve']) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried removing transient from this list, but then the the error said:

Program log: Error withdrawing from reserve: validator stake accounts have lamports available, please use those first.
    Program log: Error: The lamports in the validator stake account is not equal to the minimum

Maybe the issue is way back in the findStakeProgramAddress function?

@CMEONE
Copy link
Contributor

CMEONE commented Feb 16, 2022

I just don't understand why I'm getting the error Incorrect stake account address for vote <VOTE_ACCOUNT>, expected <ACTIVE_STAKE_ADDRESS>, received <ACTIVATING_TRANSIENT_STAKE_ADDRESS> when I feel like the one that's being used/received is in fact the correct one in that context. Maybe @joncinque you might be able to better interpret the reasoning behind this error?

continue;
}

let availableForWithdrawal = calcPoolTokensForDeposit(stakePool, lamports - minBalance);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@CMEONE the issue comes from this line. Instead of always subtracting minBalance, it should only be subtracted from the transient accounts, as done in #2900. The errors comes from not withdrawing everything possible from the main stake account before withdrawing from the transient stake account.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense, but when I tried modifying that line to let availableForWithdrawal = calcPoolTokensForDeposit(stakePool, type == 'transient' ? lamports - minBalance : lamports);, I still got the same error Incorrect stake account address for vote <VOTE_ACCOUNT>, expected <ACTIVE_STAKE_ADDRESS>, received <ACTIVATING_TRANSIENT_STAKE_ADDRESS>.

Copy link
Contributor

@CMEONE CMEONE Feb 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the logs, it seems like the issue is not just with not withdrawing everything possible, it's also with trying to withdraw from transient stake accounts before the validator account.

These are the accounts available in the pool on devnet:

  • Validator 1 active
  • Validator 2 active
  • Validator 3 active
  • Validator 3 transient

This is the order that the bindings chose for withdrawing stake:

  • Validator 1 active
  • Validator 3 transient

As you see, the bindings chose to try to withdraw from validator 3 transient before trying validator 3 active (which is where the error occurred).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, when useReserve is set to true, it tries withdrawing all the balance from the reserve even if there aren't enough lamports in reserve to cover it fully.

@AlexanderRay
Copy link
Contributor Author

@CMEONE @joncinque please check, last commit should fix the issue

@CMEONE
Copy link
Contributor

CMEONE commented Feb 17, 2022

@AlexanderRay Unfortunately, I am still experiencing the same two issues. When useReserve is set to false, I am getting the error Incorrect stake account address for vote <VOTE_ACCOUNT>, expected <ACTIVE_STAKE_ADDRESS>, received <ACTIVATING_TRANSIENT_STAKE_ADDRESS> (the wrong validator account was used), and when useReserve is true, the reserve account is withdrawn from first, causing the error The lamports in the validator stake account is not equal to the minimum. I think there might be an issue on how the accounts get prioritized.

const stakeAccountRentExemption = await connection.getMinimumBalanceForRentExemption(
StakeProgram.space,
);

const withdrawAuthority = await findWithdrawAuthorityProgramAddress(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few lines below this one, there is the following code:

if (useReserve) {
  withdrawAccounts.push({
    stakeAddress: stakePool.account.data.reserveStake,
    voteAddress: undefined,
    poolAmount,
  });
}

Won't this always fail if there is still stake in the validator accounts? In that case, I think it might be better to remove this part and pass useReserve into the prepareWithdrawAccounts method.

Then, in prepareWithdrawAccounts, we can change this:

if (reserveStakeBalance > 0) {
  accounts.push({
    type: 'reserve',
    stakeAddress: stakePool.reserveStake,
    lamports: reserveStakeBalance,
  });
}

to this:

if (useReserve && reserveStakeBalance > 0) {
  accounts.push({
    type: 'reserve',
    stakeAddress: stakePool.reserveStake,
    lamports: reserveStakeBalance,
  });
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few lines below this one, there is the following code:

if (useReserve) {
  withdrawAccounts.push({
    stakeAddress: stakePool.account.data.reserveStake,
    voteAddress: undefined,
    poolAmount,
  });
}

Won't this always fail if there is still stake in the validator accounts? In that case, I think it might be better to remove this part and pass useReserve into the prepareWithdrawAccounts method.

Then, in prepareWithdrawAccounts, we can change this:

if (reserveStakeBalance > 0) {
  accounts.push({
    type: 'reserve',
    stakeAddress: stakePool.reserveStake,
    lamports: reserveStakeBalance,
  });
}

to this:

if (useReserve && reserveStakeBalance > 0) {
  accounts.push({
    type: 'reserve',
    stakeAddress: stakePool.reserveStake,
    lamports: reserveStakeBalance,
  });
}

When processing withdrawals, the order of priority goes:

preferred withdraw validator stake account (if set)
validator stake accounts
transient stake accounts
reserve stake account

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, that's what it should be. However, when useReserve is set to true, the order becomes:

reserve stake account

which will never work because: The lamports in the validator stake account is not equal to the minimum

The stake pool program won't allow for a stake withdrawal from reserve stake account until all the validator stake accounts have been fully withdrawn.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

argh ... checking .. anyway to withdraw from reserve account you should use withdrawSol

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right of course, withdrawSol is most optimal, useReserve seems a bit out of place as a parameter and can probably be removed altogether.

Copy link
Contributor

@CMEONE CMEONE Feb 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I have a solution for the other bug (Incorrect stake account address for vote <VOTE_ACCOUNT>, expected <ACTIVE_STAKE_ADDRESS>, received <ACTIVATING_TRANSIENT_STAKE_ADDRESS>), I'll add another comment once I test that it works (currently dealing with splitting transactions up since transaction sizes can get a bit large sometimes).

@AlexanderRay
Copy link
Contributor Author

AlexanderRay commented Feb 17, 2022

@CMEONE is your test pool on devnet? can you share your test environment with us?

);
if (!stakePool.stakeWithdrawalFee.denominator.isZero()) {
for (const { stakeAddress, voteAddress, lamports } of filteredAccounts) {
if (lamports <= minBalance) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this condition should be changed to (lamports <= minBalance && type == "transient") because I think @joncinque was saying that the minimum balance part only applies to transient stake accounts.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this fix, everything seems to be working on devnet.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reserve part is still problematic, but from inspecting the issue, it seems like there's not much that can be done in the bindings themselves (seems to be an issue in the program itself). For instance, with completely empty validator stake accounts and all the transient stake set to the minimum balance, the program still returns:

Program log: Error withdrawing from reserve: validator stake accounts have lamports available, please use those first.
Program log: Error: The lamports in the validator stake account is not equal to the minimum

It seems like it might actually be impossible to withdraw stake from the reserve account even when all other accounts have been fully depleted! In that case, it's probably not worth spending too much time trying to fix that on the bindings side.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can confirm the reserve part does have a corner case, since it's impossible to totally drain a transient account. I think it's possible to relax that requirement, but I have to think through the implications.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'use_reserve' functionality is just reimplemented bases on cli version

let withdraw_accounts = if use_reserve {

@joncinque should I also remove it from cli or make it still sense there?

if (!stakePool.stakeWithdrawalFee.denominator.isZero()) {
for (const { stakeAddress, voteAddress, lamports } of filteredAccounts) {
if (lamports <= minBalance) {
continue;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change the above condition to (lamports <= minBalance && type == "transient") as the minBalance only applies to transient stake accounts. I believe that is all that needs to be fixed (besides useReserve which is a larger issue related to reserve accounts in general).

Copy link
Contributor

@CMEONE CMEONE left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoroughly tested the following methods on devnet: getStakePoolAccount, updateStakePool, depositSol, withdrawSol, withdrawStake, stakePoolInfo

If @joncinque thinks everything looks good, I think this PR can be merged (and pushed to NPM with a minor version bump), and we can revisit the reserve issues in another PR (since that's a larger issue that involves the program itself).

I can't wait to launch BlazeStake on mainnet-beta soon, which would not have been possible without both of you. Thank you so much for your work on these bindings (and for persisting despite all the errors)!

Copy link
Contributor

@joncinque joncinque left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your patience, looks great!

@joncinque joncinque merged commit 27a5828 into solana-labs:master Feb 23, 2022
@AlexanderRay AlexanderRay deleted the stake_pool_bindings branch March 16, 2022 08:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
community Community contribution
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants