-
Notifications
You must be signed in to change notification settings - Fork 660
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
Feat: Add TenureChange
transaction type
#3974
Conversation
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## next #3974 +/- ##
==========================================
- Coverage 0.04% 0.04% -0.01%
==========================================
Files 419 419
Lines 297581 297643 +62
==========================================
Hits 136 136
- Misses 297445 297507 +62 ☔ View full report in Codecov by Sentry. |
05ab9e9
to
40836f7
Compare
2af12b5
to
036153d
Compare
return Err(Error::InvalidStacksTransaction(msg, false)); | ||
} | ||
|
||
// TODO: More checks before adding to block? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few:
- This must be the first block in the miner's tenure. It cannot be in a subsequent block
- This
TenureChange
must be forlast_tenure + 1
. NoTenureChange
s can be skipped. - It must point to the last active miner's block-commit's
StacksBlockId
- It must count up the number of blocks since the last block with a
TenureChange
(it may be zero; a block can have multipleTenureChange
transactions per the design doc) - It must be signed by the current Stacker set (this could be checked on
consensus_deserialize
) - It must precede any other kinds of transactions (this could be checked in
StacksBlock::consensus_deserialize
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should live as a separate issue from this PR and let this PR function mostly just as a wire format implementation (#4014)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed
TransactionPayload::TenureChange(tc) => { | ||
write_next(fd, &(TransactionPayloadID::TenureChange as u8))?; | ||
tc.consensus_serialize(fd)?; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're going to somehow need to epoch-gate consensus_deserialize
below so that this new transaction variant does not even decode until epoch 3.0. I think we're going to need a separate trait for this (see here: #3710 (comment))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this makes sense. I'll check with Vlad to see if he's working on this for his PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now, there are at least two PRs in flight (Vlad's and Cyle's) that do this. We should just bite the bullet and get one of them shipped, and then base this PR off of it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. I guess we should let @fess-v know as well, since he's working on this too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No -- #3992 isn't going to implement that logic -- so you should continue with your work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, thanks @kantai
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to close the loop on this PR: I don't think it's strictly necessary to epoch gate this deserialization. All that matters is whether or not the transaction is valid for inclusion in a block. During block processing, the transaction processor should just yield an invalid block error if this transaction payload is matched.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that's fine for now. Furthermore, the block validation code reached from accept_block()
can reject blocks that include them too early. I'm already doing this in my coordinator branch.
} | ||
|
||
impl TenureChangePayload { | ||
pub fn validate(&self) -> Result<(), TenureChangeError> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is going to require access to a lot more context, such as access to the chainstate databases. In fact, the code for this might instead belong in NakamotoChainState
.
Before this comes out of draft, we need unit tests for the new functionality. |
@jcnelson or @kantai, I'm trying to finish up this PR now, and I've got a couple minor questions regarding how to sign. Right now I have the following struct: pub struct TenureChangePayload {
pub previous_tenure_end: StacksBlockId,
pub previous_tenure_blocks: u16,
pub cause: TenureChangeCause,
pub pubkey_hash: Hash160,
pub signature: ThresholdSignature,
pub signers: Vec<u8>,
} What I'm wondering is:
pub struct TenureChange {
pub previous_tenure_end: StacksBlockId,
pub previous_tenure_blocks: u16,
pub cause: TenureChangeCause,
pub pubkey_hash: Hash160,
pub signers: Vec<u8>,
}
pub struct TenureChangePayload {
pub tenure_change: TenureChange,
pub signature: ThresholdSignature,
} so I can serialize |
Yes, it needs to cover
I would recommend just adding a function: impl TenureChangePayload {
/// Serialize the parts of this payload to `out` required for signing and validating
/// stacker signatures.
pub fn serialize_for_sign<W: Write>(&self, out: &mut W) -> Result<(), CodecError> {
s.previous_tenure_end.consensus_serialize(out)?;
...
}
} |
Cool, this works too. The only other change then I'll need is to move |
8a1b9c9
to
28dd0a6
Compare
I've finished up with the structure and wire format for a There's one thing that needs to be fixed before merging: There are still 2 unit tests failing. I've been looking into this since yesterday but haven't made any progress:
Any ideas what in here might have broken these tests @kantai? |
I've scrapped those two tests in my coordinator PR and replaced them into the |
I'm not sure -- I know that I needed to fix those tests when I merged some of this work into my previous PR. I'd recommend rebasing this PR off of |
Okay, I'm just adding |
Can you rebase this to |
7ff13df
to
2c5593d
Compare
2c5593d
to
34b07e8
Compare
Rebased, force pushed, and changed target to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A good chunk of this got merged to next
as part of the coordinator PR. If you rebase to next
then the rest of it is fine with me. Thanks!
There's one more thing I want to do with I'll make a PR to WSTS adding the cc @xoloki |
35045e2
to
c15f8b7
Compare
Description
Add a new Stacks transaction type,
TenureChange
, that Stackers will use to control mining tenure in Nakamoto release.This PR adds the enum variant
TransactionPayload::TenureChange
and establishes the wire format for a tenure change. It does not do much in the way of checking whether the trenure change is valid. That will come in a separate PR.Applicable issues
TenureChange
Stacks transaction #3944Additional info (benefits, drawbacks, caveats)
Checklist
TenureChange
variant toTransactionPayload
enumdb/transactions.rs
, verify that the current block is a Nakamoto block and that theStacksBlockId
of the last block from the previous tenure is the current block's parentNakamotoChainState
that checks for the presence of aTenureChange
transaction, confirming that the current block was signed by the appropriate hashdocs/rpc/openapi.yaml
andrpc-endpoints.md
for v2 endpoints,event-dispatcher.md
for new events)clarity-benchmarking
repobitcoin-tests.yml