Fix `burn-block-height` in `at-block`
By Jeff Bencin
- Idea
- Draft
- Accepted
- CAB Voting Open
- CAB Voting Closed
- Recommended
- Activation in Progress
- Ratified
Abstract
This SIP corrects the behavior of the Clarity keyword burn-block-height inside of an at-block statement.
Discussion
Introduction
Currently, burn-block-height does not take into account the context set by at-block, and will always return the burn block height at the latest Stacks block.
This behavior was reported in first reported in issue #1615 on the hirosystems/clarinet repository (link)
The correct behavior would be to return the burn block height at the height of the Stacks block passed to at-block.
This behavior only occurs in Stacks Epoch 3.0 and above, and is due to a change in how the burn block is calculated for Nakamoto blocks.
burn-block-height returns the expected result inside of at-block in Stacks Epoch 2.x and below.
The proposed fix is to correct the behavior for burn-block-height in Stacks Epoch 3.1 and above, and leave the incorrect behavior in Stacks Epoch 3.0, to avoid breaking consensus.
Examples
If we open a session in clarinet console, and enter the following commands:
-
::set_epoch 3.0 -
(define-read-only (get-burn (height uint)) (let ( (id (unwrap! (get-stacks-block-info? id-header-hash height) (err 1))) ) (at-block id (ok { burn-block-height: burn-block-height, stacks-block-height: stacks-block-height }) ) ) ) -
::advance_burn_chain_tip 100 -
(contract-call? .contract-0 get-burn u3)
It will return:
(ok { burn-block-height: u101, stacks-block-height: u3 })
Where we would expect it to return:
(ok { burn-block-height: u3, stacks-block-height: u3 })
Specification
When called in the context of at-block <stacks-block-id>, burn-block-height will return the following result based on the current Stacks Epoch:
| Epoch | burn-block-height returns |
|---|---|
| < 3.0 | Height of burn block associated with parent of stacks-block-id |
| 3.0 | Height of burn block associated with latest Stacks block |
| > 3.0 | Height of burn block associated with stacks-block-id |
Examples
If we open a session in clarinet console, and enter the following commands:
-
::set_epoch 3.0 -
(define-read-only (get-burn (height uint)) (let ( (id (unwrap! (get-stacks-block-info? id-header-hash height) (err 1))) ) (at-block id (ok { burn-block-height: burn-block-height, stacks-block-height: stacks-block-height }) ) ) ) -
::advance_burn_chain_tip 100 -
(contract-call? .contract-0 get-burn u3)
It will return:
(ok { burn-block-height: u101, stacks-block-height: u3 })
Where we would expect it to return:
(ok { burn-block-height: u3, stacks-block-height: u3 })
Related Work
- hirosystems/clarinet#1615: The issue that reports this behavior
- stacks-network/stacks-core#5524: The PR to introduce the correct behavior described in this SIP
Layer
Consensus (hard fork)
Requires
N/A
Backwards Compatibility
To avoid breaking consensus, the behavior of burn-block-height in blocks prior to Stacks Epoch 3.1 will not change
Activation
Since this SIP requires a change to the stacks consensus rules a community vote is additionally required.
Process of Activation
Users can vote to approve this SIP with either their locked/stacked STX or with unlocked/liquid STX, or both. The criteria for the stacker and non-stacker voting is as follows.
For Stackers:
TODO
Process of Activation
Users can vote to approve this SIP with either their locked/stacked STX or with unlocked/liquid STX, or both. The criteria for the stacker and non-stacker voting is as follows.
For Stackers:
TODO
Activation Status
TODO
Reference Implementations
To be implemented in Rust. See https://github.com/stacks-network/stacks-core/pull/5524.
zadao.ai