Merge pull request #260 from hirosystems/add-block-height

feat: add block height to `commit-block` event
This commit is contained in:
Brice Dobry
2023-04-19 21:56:37 -04:00
committed by GitHub
10 changed files with 72 additions and 19 deletions

View File

@@ -55,7 +55,7 @@
(asserts! (>= (len provided-checked) signers-required) (err ERR_NOT_ENOUGH_SIGNERS))
(ok true)))
(define-read-only (make-block-commit-hash (block-data { block: (buff 32), withdrawal-root: (buff 32), target-tip: (buff 32) }))
(define-read-only (make-block-commit-hash (block-data { block: (buff 32), subnet-block-height: uint, withdrawal-root: (buff 32), target-tip: (buff 32) }))
(let ((data-buff (unwrap-panic (to-consensus-buff? (merge block-data { multi-contract: CONTRACT_ADDRESS }))))
(data-hash (sha256 data-buff))
;; in 2.0, this is a constant: 0xe2f4d0b1eca5f1b4eb853cd7f1c843540cfb21de8bfdaa59c504a6775cd2cfe9
@@ -74,7 +74,7 @@
signers: (unwrap-panic (as-max-len? (append (get signers prior-okay) curr-signer) u9)) }))
prior-err (err prior-err)))
(define-public (commit-block (block-data { block: (buff 32), withdrawal-root: (buff 32), target-tip: (buff 32) })
(define-public (commit-block (block-data { block: (buff 32), subnet-block-height: uint, withdrawal-root: (buff 32), target-tip: (buff 32) })
(signatures (list 9 (buff 65))))
(let ((block-data-hash (make-block-commit-hash block-data))
(signer-principals (try! (fold verify-sign-helper signatures (ok { block-hash: block-data-hash, signers: (list) })))))
@@ -83,6 +83,6 @@
;; check that we have enough signatures
(try! (check-miners (append (get signers signer-principals) tx-sender)))
;; execute the block commit
(as-contract (contract-call? .subnet commit-block (get block block-data) (get target-tip block-data) (get withdrawal-root block-data)))
(as-contract (contract-call? .subnet commit-block (get block block-data) (get subnet-block-height block-data) (get target-tip block-data) (get withdrawal-root block-data)))
)
)

View File

@@ -109,10 +109,10 @@
;; Helper function: determines whether the commit-block operation satisfies pre-conditions
;; listed in `commit-block`.
;; Returns response<bool, int>
(define-private (can-commit-block? (commit-block-height uint) (target-chain-tip (buff 32)))
(define-private (can-commit-block? (l1-block-height uint) (target-chain-tip (buff 32)))
(begin
;; check no block has been committed at this height
(asserts! (is-none (map-get? block-commits commit-block-height)) (err ERR_BLOCK_ALREADY_COMMITTED))
(asserts! (is-none (map-get? block-commits l1-block-height)) (err ERR_BLOCK_ALREADY_COMMITTED))
;; check that `target-chain-tip` matches the burn chain tip
(asserts! (is-eq
@@ -132,15 +132,21 @@
;; Helper function: modifies the block-commits map with a new commit and prints related info
;; Returns response<(buff 32), ?>
(define-private (inner-commit-block (block (buff 32)) (commit-block-height uint) (withdrawal-root (buff 32)))
(define-private (inner-commit-block
(block (buff 32))
(subnet-block-height uint)
(l1-block-height uint)
(withdrawal-root (buff 32))
)
(begin
(map-set block-commits commit-block-height block)
(map-set block-commits l1-block-height block)
(map-set withdrawal-roots-map withdrawal-root true)
(print {
event: "block-commit",
block-commit: block,
subnet-block-height: subnet-block-height,
withdrawal-root: withdrawal-root,
block-height: commit-block-height
l1-block-height: l1-block-height
})
(ok block)
)
@@ -155,10 +161,15 @@
;; 1) we have already committed at this block height
;; 2) `target-chain-tip` is not the burn chain tip (i.e., on this chain)
;; 3) the sender is not a miner
(define-public (commit-block (block (buff 32)) (target-chain-tip (buff 32)) (withdrawal-root (buff 32)))
(let ((commit-block-height block-height))
(try! (can-commit-block? commit-block-height target-chain-tip))
(inner-commit-block block commit-block-height withdrawal-root)
(define-public (commit-block
(block (buff 32))
(subnet-block-height uint)
(target-chain-tip (buff 32))
(withdrawal-root (buff 32))
)
(let ((l1-block-height block-height))
(try! (can-commit-block? l1-block-height target-chain-tip))
(inner-commit-block block subnet-block-height l1-block-height withdrawal-root)
)
)

View File

@@ -112,6 +112,7 @@ Clarinet.test({
.toString();
const commit_data_1 = types.tuple({
block: buffFromHex(block_hash_1.slice(2)),
"subnet-block-height": types.uint(0),
"withdrawal-root": buffFromHex(withdrawal_root_1.slice(2)),
"target-tip": id_header_hash_1,
});
@@ -149,6 +150,7 @@ Clarinet.test({
.toString();
const commit_data_2 = types.tuple({
block: buffFromHex(block_hash_1.slice(2)),
"subnet-block-height": types.uint(1),
"withdrawal-root": buffFromHex(withdrawal_root_1.slice(2)),
"target-tip": id_header_hash_2,
});
@@ -278,6 +280,7 @@ Clarinet.test({
.toString();
const commit_data_1 = types.tuple({
block: buffFromHex(block_hash_1.slice(2)),
"subnet-block-height": types.uint(0),
"withdrawal-root": buffFromHex(withdrawal_root_1.slice(2)),
"target-tip": id_header_hash_1,
});
@@ -317,6 +320,7 @@ Clarinet.test({
.toString();
const commit_data_2 = types.tuple({
block: buffFromHex(block_hash_1.slice(2)),
"subnet-block-height": types.uint(0),
"withdrawal-root": buffFromHex(withdrawal_root_1.slice(2)),
"target-tip": id_header_hash_2,
});
@@ -357,6 +361,7 @@ Clarinet.test({
.toString();
const commit_data_3 = types.tuple({
block: buffFromHex(block_hash_1.slice(2)),
"subnet-block-height": types.uint(0),
"withdrawal-root": buffFromHex(withdrawal_root_1.slice(2)),
"target-tip": id_header_hash_3,
});

View File

@@ -8,9 +8,7 @@ import {
} from "https://deno.land/x/clarinet@v1.2.0/index.ts";
import { assertEquals } from "https://deno.land/std@0.90.0/testing/asserts.ts";
import {
decode as decHex,
} from "https://deno.land/std@0.149.0/encoding/hex.ts";
import { decode as decHex } from "https://deno.land/std@0.149.0/encoding/hex.ts";
function fromHex(input: string) {
const hexBytes = new TextEncoder().encode(input);
@@ -135,6 +133,7 @@ Clarinet.test({
"commit-block",
[
types.buff(new Uint8Array([0, 1, 1, 1, 1])),
types.uint(0),
id_header_hash1,
types.buff(new Uint8Array([0, 1, 1, 1, 2])),
],
@@ -146,6 +145,7 @@ Clarinet.test({
"commit-block",
[
types.buff(new Uint8Array([0, 2, 2, 2, 2])),
types.uint(1),
id_header_hash1,
types.buff(new Uint8Array([0, 2, 2, 2, 3])),
],
@@ -170,6 +170,7 @@ Clarinet.test({
"commit-block",
[
types.buff(new Uint8Array([0, 2, 2, 2, 2])),
types.uint(1),
id_header_hash2,
types.buff(new Uint8Array([0, 2, 2, 2, 3])),
],
@@ -181,6 +182,7 @@ Clarinet.test({
"commit-block",
[
types.buff(new Uint8Array([0, 2, 2, 2, 1])),
types.uint(1),
types.buff(new Uint8Array([0, 2, 2, 2, 2])),
types.buff(new Uint8Array([0, 2, 2, 2, 3])),
],
@@ -203,6 +205,7 @@ Clarinet.test({
"commit-block",
[
types.buff(new Uint8Array([0, 2, 2, 2, 2])),
types.uint(1),
id_header_hash3,
types.buff(new Uint8Array([0, 2, 2, 2, 3])),
],
@@ -429,7 +432,6 @@ Clarinet.test({
charlie.address
),
]);
console.log("BLOCK:", block);
// should return (err ERR_DISALLOWED_ASSET)
block.receipts[0].result.expectErr().expectInt(5);
@@ -523,6 +525,7 @@ Clarinet.test({
"commit-block",
[
types.buff(new Uint8Array([0, 1, 1, 1, 1])),
types.uint(0),
id_header_hash,
types.buff(root_hash),
],
@@ -712,6 +715,7 @@ Clarinet.test({
"commit-block",
[
types.buff(new Uint8Array([0, 1, 1, 1, 1])),
types.uint(0),
id_header_hash,
types.buff(root_hash),
],
@@ -1100,6 +1104,7 @@ Clarinet.test({
"commit-block",
[
types.buff(new Uint8Array([0, 1, 1, 1, 1])),
types.uint(0),
id_header_hash,
types.buff(root_hash),
],
@@ -1295,6 +1300,7 @@ Clarinet.test({
"commit-block",
[
types.buff(new Uint8Array([0, 1, 1, 1, 1])),
types.uint(0),
id_header_hash,
types.buff(root_hash),
],
@@ -1622,6 +1628,7 @@ Clarinet.test({
"commit-block",
[
types.buff(new Uint8Array([0, 1, 1, 1, 1])),
types.uint(0),
id_header_hash,
types.buff(root_hash),
],
@@ -1919,6 +1926,7 @@ Clarinet.test({
"commit-block",
[
types.buff(new Uint8Array([0, 1, 1, 1, 1])),
types.uint(0),
id_header_hash,
types.buff(root_hash),
],
@@ -2210,6 +2218,7 @@ Clarinet.test({
"commit-block",
[
types.buff(new Uint8Array([0, 1, 1, 1, 1])),
types.uint(0),
id_header_hash,
types.buff(root_hash),
],
@@ -2319,6 +2328,7 @@ Clarinet.test({
"commit-block",
[
types.buff(new Uint8Array([0, 1, 1, 1, 1])),
types.uint(0),
id_header_hash,
types.buff(root_hash),
],
@@ -2426,7 +2436,8 @@ Clarinet.test({
block.receipts[0].result.expectOk().expectBool(true);
// Check that user does not own this NFT on the L1
const assets = chain.getAssetsMaps().assets[".simple-nft-no-mint.nft-token"];
const assets =
chain.getAssetsMaps().assets[".simple-nft-no-mint.nft-token"];
assertEquals(assets, undefined);
// Miner should commit a block with the appropriate root hash (mocking a withdrawal Merkle tree)
@@ -2451,6 +2462,7 @@ Clarinet.test({
"commit-block",
[
types.buff(new Uint8Array([0, 1, 1, 1, 1])),
types.uint(0),
id_header_hash,
types.buff(root_hash),
],
@@ -2585,6 +2597,7 @@ Clarinet.test({
"commit-block",
[
types.buff(new Uint8Array([0, 1, 1, 1, 1])),
types.uint(0),
id_header_hash,
types.buff(root_hash),
],
@@ -2736,6 +2749,7 @@ Clarinet.test({
"commit-block",
[
types.buff(new Uint8Array([0, 1, 1, 1, 1])),
types.uint(0),
id_header_hash,
types.buff(root_hash),
],

View File

@@ -2342,6 +2342,7 @@ impl Proposal {
// when using a 2.1 layer-1, this will need to use the structured data hash
let block_hash_buff = Value::buff_from(self.block.block_hash().0.to_vec())
.expect("Failed to form Clarity buffer from block hash");
let subnet_block_height = Value::UInt(self.block.header.total_work.work.into());
let withdrawal_root_buff =
Value::buff_from(self.block.header.withdrawal_merkle_root.0.to_vec())
.expect("Failed to form Clarity buffer from withdrawal root");
@@ -2352,6 +2353,7 @@ impl Proposal {
let data_tuple = Value::Tuple(
TupleData::from_data(vec![
("block".into(), block_hash_buff),
("subnet-block-height".into(), subnet_block_height),
("withdrawal-root".into(), withdrawal_root_buff),
("target-tip".into(), target_tip),
("multi-contract".into(), signing_contract),

View File

@@ -40,6 +40,7 @@ pub trait Layer1Committer {
fn make_commit_tx(
&self,
committed_block_hash: BlockHeaderHash,
committed_block_height: u64,
target_tip: BurnchainHeaderHash,
withdrawal_merkle_root: Sha512Trunc256Sum,
signatures: Vec<ClaritySignature>,
@@ -231,6 +232,7 @@ impl MultiPartyCommitter {
sender_nonce: u64,
tx_fee: u64,
commit_to: BlockHeaderHash,
committed_block_height: u64,
target_tip: BurnchainHeaderHash,
withdrawal_root: Sha512Trunc256Sum,
signatures: Vec<ClaritySignature>,
@@ -247,6 +249,7 @@ impl MultiPartyCommitter {
let block_val = ClarityValue::buff_from(commit_to.as_bytes().to_vec())
.map_err(|_| Error::BadCommitment)?;
let height_val = ClarityValue::UInt(committed_block_height.into());
let target_tip_val = ClarityValue::buff_from(target_tip.as_bytes().to_vec())
.map_err(|_| Error::BadCommitment)?;
let withdrawal_root_val = ClarityValue::buff_from(withdrawal_root.as_bytes().to_vec())
@@ -264,6 +267,7 @@ impl MultiPartyCommitter {
let block_data_val = TupleData::from_data(vec![
("block".into(), block_val),
("subnet-block-height".into(), height_val),
("withdrawal-root".into(), withdrawal_root_val),
("target-tip".into(), target_tip_val),
])
@@ -300,6 +304,7 @@ impl MultiPartyCommitter {
pub fn make_commit_tx(
&self,
committed_block_hash: BlockHeaderHash,
committed_block_height: u64,
target_tip: BurnchainHeaderHash,
withdrawal_merkle_root: Sha512Trunc256Sum,
signatures: Vec<ClaritySignature>,
@@ -325,6 +330,7 @@ impl MultiPartyCommitter {
nonce,
DEFAULT_MINER_COMMITMENT_FEE,
committed_block_hash,
committed_block_height,
target_tip,
withdrawal_merkle_root,
signatures.clone(),
@@ -347,6 +353,7 @@ impl MultiPartyCommitter {
nonce,
computed_fee,
committed_block_hash,
committed_block_height,
target_tip,
withdrawal_merkle_root,
signatures,
@@ -427,6 +434,7 @@ impl Layer1Committer for MultiPartyCommitter {
fn make_commit_tx(
&self,
committed_block_hash: BlockHeaderHash,
committed_block_height: u64,
target_tip: BurnchainHeaderHash,
withdrawal_merkle_root: Sha512Trunc256Sum,
signatures: Vec<ClaritySignature>,
@@ -435,6 +443,7 @@ impl Layer1Committer for MultiPartyCommitter {
) -> Result<StacksTransaction, Error> {
self.make_commit_tx(
committed_block_hash,
committed_block_height,
target_tip,
withdrawal_merkle_root,
signatures,
@@ -452,6 +461,7 @@ impl Layer1Committer for DirectCommitter {
fn make_commit_tx(
&self,
committed_block_hash: BlockHeaderHash,
committed_block_height: u64,
target_tip: BurnchainHeaderHash,
withdrawal_merkle_root: Sha512Trunc256Sum,
_signatures: Vec<ClaritySignature>,
@@ -460,6 +470,7 @@ impl Layer1Committer for DirectCommitter {
) -> Result<StacksTransaction, Error> {
self.make_commit_tx(
committed_block_hash,
committed_block_height,
target_tip,
withdrawal_merkle_root,
attempt,
@@ -483,6 +494,7 @@ impl DirectCommitter {
sender_nonce: u64,
tx_fee: u64,
commit_to: BlockHeaderHash,
committed_block_height: u64,
target_tip: BurnchainHeaderHash,
withdrawal_root: Sha512Trunc256Sum,
) -> Result<StacksTransaction, Error> {
@@ -504,6 +516,7 @@ impl DirectCommitter {
function_name: ClarityName::from("commit-block"),
function_args: vec![
ClarityValue::buff_from(committed_block).map_err(|_| Error::BadCommitment)?,
ClarityValue::UInt(committed_block_height.into()),
ClarityValue::buff_from(target_tip_bytes).map_err(|_| Error::BadCommitment)?,
ClarityValue::buff_from(withdrawal_root_bytes).map_err(|_| Error::BadCommitment)?,
],
@@ -533,6 +546,7 @@ impl DirectCommitter {
pub fn make_commit_tx(
&self,
committed_block_hash: BlockHeaderHash,
committed_block_height: u64,
target_tip: BurnchainHeaderHash,
withdrawal_merkle_root: Sha512Trunc256Sum,
attempt: u64,
@@ -557,6 +571,7 @@ impl DirectCommitter {
nonce,
DEFAULT_MINER_COMMITMENT_FEE,
committed_block_hash,
committed_block_height,
target_tip,
withdrawal_merkle_root,
)
@@ -578,6 +593,7 @@ impl DirectCommitter {
nonce,
computed_fee,
committed_block_hash,
committed_block_height,
target_tip,
withdrawal_merkle_root,
)

View File

@@ -263,6 +263,7 @@ impl BurnchainController for L1Controller {
fn submit_commit(
&mut self,
committed_block_hash: BlockHeaderHash,
committed_block_height: u64,
target_tip: BurnchainHeaderHash,
withdrawal_merkle_root: Sha512Trunc256Sum,
signatures: Vec<super::ClaritySignature>,
@@ -271,6 +272,7 @@ impl BurnchainController for L1Controller {
) -> Result<Txid, Error> {
let tx = self.committer.make_commit_tx(
committed_block_hash,
committed_block_height,
target_tip,
withdrawal_merkle_root,
signatures,

View File

@@ -418,6 +418,7 @@ impl BurnchainController for MockController {
fn submit_commit(
&mut self,
committed_block_hash: BlockHeaderHash,
_committed_block_height: u64,
_target_block: BurnchainHeaderHash,
withdrawal_merkle_root: Sha512Trunc256Sum,
_signatures: Vec<ClaritySignature>,

View File

@@ -94,6 +94,7 @@ pub trait BurnchainController {
fn submit_commit(
&mut self,
committed_block_hash: BlockHeaderHash,
committed_block_height: u64,
target_burn_chain: BurnchainHeaderHash,
withdrawal_merkle_root: Sha512Trunc256Sum,
signatures: Vec<ClaritySignature>,
@@ -202,6 +203,7 @@ impl BurnchainController for PanicController {
fn submit_commit(
&mut self,
_committed_block_hash: BlockHeaderHash,
_committed_block_height: u64,
_target_block: BurnchainHeaderHash,
_withdrawal_merkle_root: Sha512Trunc256Sum,
_signatures: Vec<ClaritySignature>,

View File

@@ -2003,6 +2003,7 @@ impl StacksNode {
let res = bitcoin_controller.submit_commit(
committed_block_hash,
block_height,
target_burn_hash,
withdrawal_merkle_root,
signatures,
@@ -2017,10 +2018,9 @@ impl StacksNode {
Err(e) => {
if !config.node.mock_mining {
warn!("Failed to submit miner commitment L1 transaction: {}", e);
warn!("Failed to submit Bitcoin transaction");
return None;
} else {
debug!("Mock-mining enabled; not sending Bitcoin transaction");
debug!("Mock-mining enabled; not sending L1 transaction");
}
}
}