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

Reward set calculation and RPC endpoint #4311

Merged
merged 12 commits into from
Feb 6, 2024
Merged

Conversation

kantai
Copy link
Member

@kantai kantai commented Jan 30, 2024

Description

Implement #4295 and #4298

4295: Reading the reward set data from .signers

Implementation of #4295 is kind of subtle, and will have to impose additional constraints on Epoch-2.5 (one of which isn't implemented in this PR, but could be added, I suppose).

Reading the reward set state from the calculation performed for .signers is only possible after that calculation is performed (due to the general nature of causality and the linear passage of time). This calculation is performed during the first block of a prepare phase. This does not pose a challenge for nakamoto, because that's the block it chooses as the PoX anchor block anyways, so, of course it can read that data. For Epoch 2.5, however, this is a challenge: the PoX anchor block always comes before the prepare phase.

To deal with this, this PR splits the reward set loading by epoch -- in Nakamoto, it reads from the .signers, but in Epoch 2.5, it continues to use the 2.x reward set routine. However, we still want to ensure that the calculation done by the 2.x reward set routine at the PoX anchor block and the calculation performed by .signers work out to the same result. The PoX anchor block (if one is chosen) in any given fork is the last block before the prepare phase. This means that the .signers
calculation will always occur with the PoX anchor block as its anchor block parent. Because the 2.x reward set routine uses the state at the end of block processing, we can ensure that the reward set calculations are the same if:

  1. The .signers calculation occurs before any burn operation processing.
  2. There is no microblock.

This PR implements the first step there. For the second step, I'd propose to disable microblocks in Epoch 2.5.

4298: New RPC endpoint `/v2/stacker_set/{cycle_number}

This endpoint returns the same RewardSet JSON data propagated over the event observer interface. Callers must supply a cycle number to query for. It will return 400 if the set hasn't been calculated yet or if the requested cycle wasn't a PoX-4 cycle.

Copy link

codecov bot commented Jan 30, 2024

Codecov Report

Attention: 209 lines in your changes are missing coverage. Please review.

Comparison is base (2d1f1ae) 44.92% compared to head (c5f4d81) 76.67%.

Files Patch % Lines
stackslib/src/net/api/getstackers.rs 5.14% 129 Missing ⚠️
...net/stacks-node/src/tests/nakamoto_integrations.rs 0.00% 26 Missing ⚠️
stackslib/src/chainstate/nakamoto/signer_set.rs 89.45% 25 Missing ⚠️
...ackslib/src/chainstate/nakamoto/coordinator/mod.rs 68.00% 16 Missing ⚠️
stackslib/src/chainstate/coordinator/tests.rs 0.00% 9 Missing ⚠️
stackslib/src/chainstate/coordinator/mod.rs 93.54% 2 Missing ⚠️
stackslib/src/chainstate/nakamoto/mod.rs 94.11% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             next    #4311       +/-   ##
===========================================
+ Coverage   44.92%   76.67%   +31.74%     
===========================================
  Files         443      445        +2     
  Lines      316901   317161      +260     
===========================================
+ Hits       142370   243184   +100814     
+ Misses     174531    73977   -100554     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@kantai kantai force-pushed the feat/reward-set-endpoint branch 2 times, most recently from 105860f to b92dcdd Compare January 31, 2024 20:25
@@ -611,6 +611,22 @@ impl<'a> ClarityDatabase<'a> {
self.store.insert_metadata(contract_identifier, key, data);
}

/// Set a metadata entry if it hasn't already been set, yielding
/// a runtime error if it was. This should only be called by post-nakamoto
/// contexts.
Copy link
Member

Choose a reason for hiding this comment

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

Can you help me understand how this error could be triggered?

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually, this function should just be removed -- at first I was going to try to store the computed reward set as metadata, in which case, this function might have been needed. But metadata storage in Clarity is very closely tied to contract instantiation, so it would be really cumbersome to have done things this way.

//
// Data **cannot** be read from `.signers` in epoch 2.5 because the write occurs
// in the first block of the prepare phase, but the PoX anchor block is *before*
// the prepare phase. Therefore
Copy link
Member

Choose a reason for hiding this comment

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

unfinished thought?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, I think I completed the thought in my latest commit, but it's hard to know exactly where I was planning to go with that sentence.

.expect_optional()
.map(|x| u64::try_from(x.expect_u128()).expect("FATAL: block height exceeded u64"))
else {
if debug_log {
Copy link
Member

Choose a reason for hiding this comment

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

Is there a way to DRY this up? Perhaps a custom logging function?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, a new macro definition would be necessary. I can add.

Copy link
Member Author

Choose a reason for hiding this comment

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

Added a local macro for this.

"checked_block" => %reward_set_block.index_block_hash()
);
} else {
error!(
Copy link
Member

Choose a reason for hiding this comment

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

Got a log discrepancy (needs to be DRY'ed up)

@@ -0,0 +1,387 @@
// Copyright (C) 2013-2020 Blockstack PBC, a public benefit corporation
// Copyright (C) 2020-2023 Stacks Open Internet Foundation
Copy link
Member

Choose a reason for hiding this comment

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

2024

@@ -114,6 +115,7 @@ impl StacksHttp {
self.register_rpc_endpoint(postmicroblock::RPCPostMicroblockRequestHandler::new());
self.register_rpc_endpoint(poststackerdbchunk::RPCPostStackerDBChunkRequestHandler::new());
self.register_rpc_endpoint(posttransaction::RPCPostTransactionRequestHandler::new());
self.register_rpc_endpoint(getstackers::GetStackersRequestHandler::default());
Copy link
Member

Choose a reason for hiding this comment

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

Miner code aesthetic: can you place the call to self.register_rpc_endpoint() in alphabetical order with the other RPC endpoints? So, after the one for getstackerdbmetadata?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure, but are we sure it shouldn't be after getstackerdbchunk and before getpoxinfo ;) ?

@@ -68,13 +68,19 @@ fn advance_to_nakamoto(
)
.unwrap();

// use the signing key of addr, otherwise the test stackers
// will not stack enough for any single signing key
// let signing_key = StacksPublicKey::from_private(&private_key);
Copy link
Member

Choose a reason for hiding this comment

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

Commented code

@kantai kantai requested a review from jcnelson February 1, 2024 20:50
@jcnelson
Copy link
Member

jcnelson commented Feb 2, 2024

LGTM; just fix merge conflicts and make sure CI passes. Thanks!

@kantai kantai force-pushed the feat/reward-set-endpoint branch from cda02b1 to c6a54db Compare February 3, 2024 03:17
Copy link
Collaborator

@jferrant jferrant left a comment

Choose a reason for hiding this comment

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

LGTM :D

Copy link
Contributor

@obycode obycode left a comment

Choose a reason for hiding this comment

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

This looks good. I just had two minor comments.

docs/rpc/api/core-node/get_stacker_set.400.example.json Outdated Show resolved Hide resolved
docs/rpc/openapi.yaml Outdated Show resolved Hide resolved
Copy link
Contributor

@obycode obycode left a comment

Choose a reason for hiding this comment

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

👍

@kantai kantai merged commit 7c7a527 into next Feb 6, 2024
2 checks passed
@blockstack-devops
Copy link
Contributor

This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@stacks-network stacks-network locked as resolved and limited conversation to collaborators Nov 6, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
5 participants