← All proposals
PR #203Draft

Fix `burn-block-height` in `at-block`

By Jeff Bencin

  1. Idea
  2. Draft
  3. Accepted
  4. CAB Voting Open
  5. CAB Voting Closed
  6. Recommended
  7. Activation in Progress
  8. Ratified

Abstract

This SIP corrects the behavior of the Clarity keyword burn-block-height inside of an at-block statement.

Discussion

No forum discussion found yetNothing on the Stacks forum is linked to this SIP. Open its forum thread.

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:

  1. ::set_epoch 3.0
    
  2. (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 })
            )
        )
    )
    
  3. ::advance_burn_chain_tip 100
    
  4. (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:

Epochburn-block-height returns
< 3.0Height of burn block associated with parent of stacks-block-id
3.0Height of burn block associated with latest Stacks block
> 3.0Height of burn block associated with stacks-block-id

Examples

If we open a session in clarinet console, and enter the following commands:

  1. ::set_epoch 3.0
    
  2. (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 })
            )
        )
    )
    
  3. ::advance_burn_chain_tip 100
    
  4. (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

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