From b52a41c02d10e06a5ef0bbafbd2494b3b761fce3 Mon Sep 17 00:00:00 2001 From: Jude Nelson Date: Sun, 19 Jul 2020 21:44:36 -0400 Subject: [PATCH 01/16] stacks header info tracks burnchain height --- src/chainstate/stacks/db/accounts.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/chainstate/stacks/db/accounts.rs b/src/chainstate/stacks/db/accounts.rs index f0a51c66a..52b641946 100644 --- a/src/chainstate/stacks/db/accounts.rs +++ b/src/chainstate/stacks/db/accounts.rs @@ -584,6 +584,7 @@ mod test { new_tip.block_height = parent_header_info.block_height + 1; new_tip.consensus_hash = ConsensusHash(Hash160::from_data(&Sha512Trunc256Sum::from_data(&parent_header_info.consensus_hash.0).0).0); new_tip.burn_header_hash = BurnchainHeaderHash(Sha512Trunc256Sum::from_data(&parent_header_info.consensus_hash.0).0); + new_tip.burn_header_height = parent_header_info.burn_header_height + 1; block_reward.parent_consensus_hash = parent_header_info.consensus_hash.clone(); block_reward.parent_block_hash = parent_header_info.anchored_header.block_hash().clone(); @@ -602,6 +603,7 @@ mod test { &new_tip.anchored_header, &new_tip.consensus_hash, &new_tip.burn_header_hash, + new_tip.burn_header_height, new_tip.burn_header_timestamp, new_tip.microblock_tail.clone(), &block_reward, From a6e54a08b75602bab7771377173728b3f2e34bcd Mon Sep 17 00:00:00 2001 From: Jude Nelson Date: Sun, 19 Jul 2020 21:45:13 -0400 Subject: [PATCH 02/16] remove unneeded burnchain timestamp -- we can query it directly in append_block() --- src/chainstate/stacks/db/blocks.rs | 62 ++++++++++++++---------------- 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/src/chainstate/stacks/db/blocks.rs b/src/chainstate/stacks/db/blocks.rs index 174845a53..8e87085fc 100644 --- a/src/chainstate/stacks/db/blocks.rs +++ b/src/chainstate/stacks/db/blocks.rs @@ -122,7 +122,6 @@ pub struct StagingMicroblock { #[derive(Debug, Clone, PartialEq)] pub struct StagingBlock { pub consensus_hash: ConsensusHash, - pub burn_header_timestamp: u64, pub anchored_block_hash: BlockHeaderHash, pub parent_consensus_hash: ConsensusHash, pub parent_anchored_block_hash: BlockHeaderHash, @@ -281,7 +280,6 @@ impl FromRow for StagingBlock { let anchored_block_hash : BlockHeaderHash = BlockHeaderHash::from_column(row, "anchored_block_hash")?; let parent_anchored_block_hash : BlockHeaderHash = BlockHeaderHash::from_column(row, "parent_anchored_block_hash")?; let consensus_hash : ConsensusHash = ConsensusHash::from_column(row, "consensus_hash")?; - let burn_header_timestamp = u64::from_column(row, "burn_header_timestamp")?; let parent_consensus_hash: ConsensusHash = ConsensusHash::from_column(row, "parent_consensus_hash")?; let parent_microblock_hash : BlockHeaderHash = BlockHeaderHash::from_column(row, "parent_microblock_hash")?; let parent_microblock_seq : u16 = row.get("parent_microblock_seq"); @@ -302,7 +300,6 @@ impl FromRow for StagingBlock { anchored_block_hash, parent_anchored_block_hash, consensus_hash, - burn_header_timestamp, parent_consensus_hash, parent_microblock_hash, parent_microblock_seq, @@ -421,7 +418,6 @@ const STACKS_BLOCK_INDEX_SQL : &'static [&'static str]= &[ CREATE TABLE staging_blocks(anchored_block_hash TEXT NOT NULL, parent_anchored_block_hash TEXT NOT NULL, consensus_hash TEXT NOT NULL, - burn_header_timestamp INT NOT NULL, parent_consensus_hash TEXT NOT NULL, parent_microblock_hash TEXT NOT NULL, parent_microblock_seq INT NOT NULL, @@ -1135,11 +1131,10 @@ impl StacksChainState { /// Store a preprocessed block, queuing it up for subsequent processing. /// The caller should at least verify that the block is attached to some fork in the burn /// chain. - fn store_staging_block<'a>(tx: &mut BlocksDBTx<'a>, consensus_hash: &ConsensusHash, burn_header_timestamp: u64, block: &StacksBlock, parent_consensus_hash: &ConsensusHash, commit_burn: u64, sortition_burn: u64) -> Result<(), Error> { + fn store_staging_block<'a>(tx: &mut BlocksDBTx<'a>, consensus_hash: &ConsensusHash, block: &StacksBlock, parent_consensus_hash: &ConsensusHash, commit_burn: u64, sortition_burn: u64) -> Result<(), Error> { debug!("Store anchored block {}/{}, parent in {}", consensus_hash, block.block_hash(), parent_consensus_hash); assert!(commit_burn < i64::max_value() as u64); assert!(sortition_burn < i64::max_value() as u64); - assert!(burn_header_timestamp < i64::max_value() as u64); let block_hash = block.block_hash(); let index_block_hash = StacksBlockHeader::make_index_block_hash(&consensus_hash, &block_hash); @@ -1165,7 +1160,6 @@ impl StacksChainState { (anchored_block_hash, \ parent_anchored_block_hash, \ consensus_hash, \ - burn_header_timestamp, \ parent_consensus_hash, \ parent_microblock_hash, \ parent_microblock_seq, \ @@ -1177,12 +1171,11 @@ impl StacksChainState { commit_burn, \ sortition_burn, \ index_block_hash) \ - VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15)"; + VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14)"; let args: &[&dyn ToSql] = &[ &block_hash, &block.header.parent_block, &consensus_hash, - &u64_to_sql(burn_header_timestamp)?, &parent_consensus_hash, &block.header.parent_microblock, &block.header.parent_microblock_sequence, @@ -2255,7 +2248,7 @@ impl StacksChainState { /// /// TODO: consider how full the block is (i.e. how much computational budget it consumes) when /// deciding whether or not it can be processed. - pub fn preprocess_anchored_block(&mut self, sort_ic: &SortitionDBConn, consensus_hash: &ConsensusHash, burn_header_timestamp: u64, block: &StacksBlock, parent_consensus_hash: &ConsensusHash) -> Result { + pub fn preprocess_anchored_block(&mut self, sort_ic: &SortitionDBConn, consensus_hash: &ConsensusHash, block: &StacksBlock, parent_consensus_hash: &ConsensusHash) -> Result { debug!("preprocess anchored block {}/{}", consensus_hash, block.block_hash()); let sort_handle = SortitionHandleConn::open_reader_consensus(sort_ic, consensus_hash)?; @@ -2302,7 +2295,7 @@ impl StacksChainState { debug!("Storing staging block"); // queue block up for processing - StacksChainState::store_staging_block(&mut block_tx, consensus_hash, burn_header_timestamp, &block, parent_consensus_hash, commit_burn, sortition_burn)?; + StacksChainState::store_staging_block(&mut block_tx, consensus_hash, &block, parent_consensus_hash, commit_burn, sortition_burn)?; // store users who burned for this block so they'll get rewarded if we process it StacksChainState::store_staging_block_user_burn_supports(&mut block_tx, consensus_hash, &block.block_hash(), &user_burns)?; @@ -2395,7 +2388,7 @@ impl StacksChainState { sn }; - self.preprocess_anchored_block(sort_ic, &snapshot.consensus_hash, snapshot.burn_header_timestamp, block, &parent_sn.consensus_hash)?; + self.preprocess_anchored_block(sort_ic, &snapshot.consensus_hash, block, &parent_sn.consensus_hash)?; let block_hash = block.block_hash(); for mblock in microblocks.iter() { self.preprocess_streamed_microblock(&snapshot.consensus_hash, &block_hash, mblock)?; @@ -2762,6 +2755,7 @@ impl StacksChainState { parent_chain_tip: &StacksHeaderInfo, chain_tip_consensus_hash: &ConsensusHash, chain_tip_burn_header_hash: &BurnchainHeaderHash, + chain_tip_burn_header_height: u32, chain_tip_burn_header_timestamp: u64, block: &StacksBlock, microblocks: &Vec, // parent microblocks @@ -2899,6 +2893,7 @@ impl StacksChainState { &block.header, chain_tip_consensus_hash, chain_tip_burn_header_hash, + chain_tip_burn_header_height, chain_tip_burn_header_timestamp, microblock_tail_opt, &scheduled_miner_reward, @@ -2954,8 +2949,8 @@ impl StacksChainState { } }; - let burn_header_hash = match SortitionDB::get_block_snapshot_consensus(sort_tx, &next_staging_block.consensus_hash)? { - Some(sn) => sn.burn_header_hash, + let (burn_header_hash, burn_header_height, burn_header_timestamp) = match SortitionDB::get_block_snapshot_consensus(sort_tx, &next_staging_block.consensus_hash)? { + Some(sn) => (sn.burn_header_hash, sn.block_height as u32, sn.burn_header_timestamp), None => { // shouldn't happen panic!("CORRUPTION: staging block {}/{} does not correspond to a burn block", &next_staging_block.consensus_hash, &next_staging_block.anchored_block_hash); @@ -3092,7 +3087,8 @@ impl StacksChainState { &parent_block_header_info, &next_staging_block.consensus_hash, &burn_header_hash, - next_staging_block.burn_header_timestamp, + burn_header_height, + burn_header_timestamp, &block, &next_microblocks, next_staging_block.commit_burn, @@ -3627,9 +3623,9 @@ pub mod test { assert!(StacksChainState::has_block_indexed(&chainstate.blocks_path, &index_block_hash).unwrap()); } - pub fn store_staging_block(chainstate: &mut StacksChainState, consensus_hash: &ConsensusHash, consensus_hash_timestamp: u64, block: &StacksBlock, parent_consensus_hash: &ConsensusHash, commit_burn: u64, sortition_burn: u64) { + pub fn store_staging_block(chainstate: &mut StacksChainState, consensus_hash: &ConsensusHash, block: &StacksBlock, parent_consensus_hash: &ConsensusHash, commit_burn: u64, sortition_burn: u64) { let mut tx = chainstate.blocks_tx_begin().unwrap(); - StacksChainState::store_staging_block(&mut tx, consensus_hash, consensus_hash_timestamp, block, parent_consensus_hash, commit_burn, sortition_burn).unwrap(); + StacksChainState::store_staging_block(&mut tx, consensus_hash, block, parent_consensus_hash, commit_burn, sortition_burn).unwrap(); tx.commit().unwrap(); let index_block_hash = StacksBlockHeader::make_index_block_hash(consensus_hash, &block.block_hash()); @@ -3755,7 +3751,7 @@ pub mod test { assert!(StacksChainState::load_staging_block_data(&chainstate.blocks_db, &chainstate.blocks_path, &ConsensusHash([2u8; 20]), &block.block_hash()).unwrap().is_none()); - store_staging_block(&mut chainstate, &ConsensusHash([2u8; 20]), get_epoch_time_secs(), &block, &ConsensusHash([1u8; 20]), 1, 2); + store_staging_block(&mut chainstate, &ConsensusHash([2u8; 20]), &block, &ConsensusHash([1u8; 20]), 1, 2); assert_block_staging_not_processed(&mut chainstate, &ConsensusHash([2u8; 20]), &block); assert_block_not_stored(&mut chainstate, &ConsensusHash([2u8; 20]), &block); @@ -3779,7 +3775,7 @@ pub mod test { assert!(StacksChainState::load_staging_block_data(&chainstate.blocks_db, &chainstate.blocks_path, &ConsensusHash([2u8; 20]), &block.block_hash()).unwrap().is_none()); - store_staging_block(&mut chainstate, &ConsensusHash([2u8; 20]), get_epoch_time_secs(), &block, &ConsensusHash([1u8; 20]), 1, 2); + store_staging_block(&mut chainstate, &ConsensusHash([2u8; 20]), &block, &ConsensusHash([1u8; 20]), 1, 2); assert_block_staging_not_processed(&mut chainstate, &ConsensusHash([2u8; 20]), &block); assert_block_not_stored(&mut chainstate, &ConsensusHash([2u8; 20]), &block); @@ -3832,7 +3828,7 @@ pub mod test { assert!(StacksChainState::load_staging_microblock(&chainstate.blocks_db, &ConsensusHash([2u8; 20]), &block.block_hash(), µblocks[0].block_hash()).unwrap().is_none()); assert!(StacksChainState::load_staging_microblock_stream(&chainstate.blocks_db, &chainstate.blocks_path, &ConsensusHash([2u8; 20]), &block.block_hash(), u16::max_value()).unwrap().is_none()); - store_staging_block(&mut chainstate, &ConsensusHash([2u8; 20]), get_epoch_time_secs(), &block, &ConsensusHash([1u8; 20]), 1, 2); + store_staging_block(&mut chainstate, &ConsensusHash([2u8; 20]), &block, &ConsensusHash([1u8; 20]), 1, 2); for mb in microblocks.iter() { store_staging_microblock(&mut chainstate, &ConsensusHash([2u8; 20]), &block.block_hash(), mb); } @@ -3884,7 +3880,7 @@ pub mod test { assert!(StacksChainState::load_staging_microblock(&chainstate.blocks_db, &ConsensusHash([2u8; 20]), &block.block_hash(), µblocks[0].block_hash()).unwrap().is_none()); assert!(StacksChainState::load_staging_microblock_stream(&chainstate.blocks_db, &chainstate.blocks_path, &ConsensusHash([2u8; 20]), &block.block_hash(), u16::max_value()).unwrap().is_none()); - store_staging_block(&mut chainstate, &ConsensusHash([2u8; 20]), get_epoch_time_secs(), &block, &ConsensusHash([1u8; 20]), 1, 2); + store_staging_block(&mut chainstate, &ConsensusHash([2u8; 20]), &block, &ConsensusHash([1u8; 20]), 1, 2); for mb in microblocks.iter() { store_staging_microblock(&mut chainstate, &ConsensusHash([2u8; 20]), &block.block_hash(), mb); } @@ -4212,7 +4208,7 @@ pub mod test { // store each block for ((block, consensus_hash), parent_consensus_hash) in blocks.iter().zip(&consensus_hashes).zip(&parent_consensus_hashes) { assert!(StacksChainState::load_staging_block_data(&chainstate.blocks_db, &chainstate.blocks_path, consensus_hash, &block.block_hash()).unwrap().is_none()); - store_staging_block(&mut chainstate, consensus_hash, get_epoch_time_secs(), block, parent_consensus_hash, 1, 2); + store_staging_block(&mut chainstate, consensus_hash, block, parent_consensus_hash, 1, 2); assert_block_staging_not_processed(&mut chainstate, consensus_hash, block); } @@ -4282,7 +4278,7 @@ pub mod test { // store each block, in reverse order! for ((block, consensus_hash), parent_consensus_hash) in blocks.iter().zip(&consensus_hashes).zip(&parent_consensus_hashes).rev() { assert!(StacksChainState::load_staging_block_data(&chainstate.blocks_db, &chainstate.blocks_path, consensus_hash, &block.block_hash()).unwrap().is_none()); - store_staging_block(&mut chainstate, consensus_hash, get_epoch_time_secs(), block, parent_consensus_hash, 1, 2); + store_staging_block(&mut chainstate, consensus_hash, block, parent_consensus_hash, 1, 2); assert_block_staging_not_processed(&mut chainstate, consensus_hash, block); } @@ -4360,7 +4356,7 @@ pub mod test { // store each block in reverse order, except for block_1 for ((block, consensus_hash), parent_consensus_hash) in blocks[1..].iter().zip(&consensus_hashes[1..]).zip(&parent_consensus_hashes[1..]).rev() { assert!(StacksChainState::load_staging_block_data(&chainstate.blocks_db, &chainstate.blocks_path, consensus_hash, &block.block_hash()).unwrap().is_none()); - store_staging_block(&mut chainstate, consensus_hash, get_epoch_time_secs(), block, parent_consensus_hash, 1, 2); + store_staging_block(&mut chainstate, consensus_hash, block, parent_consensus_hash, 1, 2); assert_block_staging_not_processed(&mut chainstate, consensus_hash, block); } @@ -4374,7 +4370,7 @@ pub mod test { // store block 1 assert!(StacksChainState::load_staging_block_data(&chainstate.blocks_db, &chainstate.blocks_path, &consensus_hashes[0], &block_1.block_hash()).unwrap().is_none()); - store_staging_block(&mut chainstate, &consensus_hashes[0], get_epoch_time_secs(), &block_1, &parent_consensus_hashes[0], 1, 2); + store_staging_block(&mut chainstate, &consensus_hashes[0], &block_1, &parent_consensus_hashes[0], 1, 2); assert_block_staging_not_processed(&mut chainstate, &consensus_hashes[0], &block_1); // first block is attachable @@ -4456,7 +4452,7 @@ pub mod test { // store block 1 to staging assert!(StacksChainState::load_staging_block_data(&chainstate.blocks_db, &chainstate.blocks_path, &consensus_hashes[0], &blocks[0].block_hash()).unwrap().is_none()); - store_staging_block(&mut chainstate, &consensus_hashes[0], get_epoch_time_secs(), &blocks[0], &parent_consensus_hashes[0], 1, 2); + store_staging_block(&mut chainstate, &consensus_hashes[0], &blocks[0], &parent_consensus_hashes[0], 1, 2); assert_block_staging_not_processed(&mut chainstate, &consensus_hashes[0], &blocks[0]); set_block_processed(&mut chainstate, &consensus_hashes[0], &blocks[0].block_hash(), true); @@ -4468,7 +4464,7 @@ pub mod test { // this is what happens at the end of append_block() // store block to staging and process it assert!(StacksChainState::load_staging_block_data(&chainstate.blocks_db, &chainstate.blocks_path, &consensus_hashes[i], &blocks[i].block_hash()).unwrap().is_none()); - store_staging_block(&mut chainstate, &consensus_hashes[i], get_epoch_time_secs(), &blocks[i], &parent_consensus_hashes[i], 1, 2); + store_staging_block(&mut chainstate, &consensus_hashes[i], &blocks[i], &parent_consensus_hashes[i], 1, 2); assert_block_staging_not_processed(&mut chainstate, &consensus_hashes[i], &blocks[i]); // set different parts of this stream as confirmed @@ -4540,7 +4536,7 @@ pub mod test { // store blocks to staging for i in 0..blocks.len() { assert!(StacksChainState::load_staging_block_data(&chainstate.blocks_db, &chainstate.blocks_path, &consensus_hashes[i], &blocks[i].block_hash()).unwrap().is_none()); - store_staging_block(&mut chainstate, &consensus_hashes[i], get_epoch_time_secs(), &blocks[i], &parent_consensus_hashes[i], 1, 2); + store_staging_block(&mut chainstate, &consensus_hashes[i], &blocks[i], &parent_consensus_hashes[i], 1, 2); assert_block_staging_not_processed(&mut chainstate, &consensus_hashes[i], &blocks[i]); } @@ -4605,7 +4601,7 @@ pub mod test { // store block to staging assert!(StacksChainState::load_staging_block_data(&chainstate.blocks_db, &chainstate.blocks_path, &consensus_hash, &block.block_hash()).unwrap().is_none()); - store_staging_block(&mut chainstate, &consensus_hash, get_epoch_time_secs(), &block, &parent_consensus_hash, 1, 2); + store_staging_block(&mut chainstate, &consensus_hash, &block, &parent_consensus_hash, 1, 2); assert_block_staging_not_processed(&mut chainstate, &consensus_hash, &block); // drop microblocks @@ -4666,7 +4662,7 @@ pub mod test { } // store block to staging - store_staging_block(&mut chainstate, &consensus_hash, get_epoch_time_secs(), &block, &parent_consensus_hash, 1, 2); + store_staging_block(&mut chainstate, &consensus_hash, &block, &parent_consensus_hash, 1, 2); assert!(StacksChainState::has_block_indexed(&chainstate.blocks_path, &index_block_header).unwrap()); // accept it @@ -4777,7 +4773,7 @@ pub mod test { assert_eq!(stream, stream_2); // store block to staging - store_staging_block(&mut chainstate, &consensus_hash, get_epoch_time_secs(), &block, &parent_consensus_hash, 1, 2); + store_staging_block(&mut chainstate, &consensus_hash, &block, &parent_consensus_hash, 1, 2); // stream it back let mut all_block_bytes = vec![]; @@ -4908,7 +4904,7 @@ pub mod test { } // store block to staging - store_staging_block(&mut chainstate, &consensus_hash, get_epoch_time_secs(), &block, &parent_consensus_hash, 1, 2); + store_staging_block(&mut chainstate, &consensus_hash, &block, &parent_consensus_hash, 1, 2); // accept it set_block_processed(&mut chainstate, &consensus_hash, &block.block_hash(), true); @@ -5016,7 +5012,7 @@ pub mod test { test_debug!("Store block {} to staging", i); assert!(StacksChainState::load_staging_block_data(&chainstate.blocks_db, &chainstate.blocks_path, &consensus_hashes[i], &blocks[i].block_hash()).unwrap().is_none()); - store_staging_block(&mut chainstate, &consensus_hashes[i], get_epoch_time_secs(), &blocks[i], &parent_consensus_hashes[i], 1, 2); + store_staging_block(&mut chainstate, &consensus_hashes[i], &blocks[i], &parent_consensus_hashes[i], 1, 2); assert_block_staging_not_processed(&mut chainstate, &consensus_hashes[i], &blocks[i]); // some anchored blocks are stored (to staging) From b12257456077e3161cf383fc63849500854695cc Mon Sep 17 00:00:00 2001 From: Jude Nelson Date: Sun, 19 Jul 2020 21:45:37 -0400 Subject: [PATCH 03/16] add burnchain block height --- src/chainstate/stacks/db/headers.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/chainstate/stacks/db/headers.rs b/src/chainstate/stacks/db/headers.rs index c393c1b7e..640a6ee9c 100644 --- a/src/chainstate/stacks/db/headers.rs +++ b/src/chainstate/stacks/db/headers.rs @@ -123,6 +123,7 @@ impl StacksChainState { let consensus_hash = &tip_info.consensus_hash; let burn_header_hash = &tip_info.burn_header_hash; let block_height = tip_info.block_height; + let burn_header_height = tip_info.burn_header_height; let burn_header_timestamp = tip_info.burn_header_timestamp; let total_work_str = format!("{}", header.total_work.work); @@ -136,7 +137,8 @@ impl StacksChainState { let args: &[&dyn ToSql] = &[ &header.version, &total_burn_str, &total_work_str, &header.proof, &header.parent_block, &header.parent_microblock, &header.parent_microblock_sequence, &header.tx_merkle_root, &header.state_index_root, &header.microblock_pubkey_hash, - &block_hash, &index_block_hash, &consensus_hash, &burn_header_hash, &(burn_header_timestamp as i64), &(block_height as i64), &index_root]; + &block_hash, &index_block_hash, &consensus_hash, &burn_header_hash, &(burn_header_height as i64), + &(burn_header_timestamp as i64), &(block_height as i64), &index_root]; tx.execute("INSERT INTO block_headers \ (version, \ @@ -153,10 +155,11 @@ impl StacksChainState { index_block_hash, \ consensus_hash, \ burn_header_hash, \ + burn_header_height, \ burn_header_timestamp, \ block_height, \ index_root) \ - VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17)", args) + VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18)", args) .map_err(|e| Error::DBError(db_error::SqliteError(e)))?; Ok(()) From 00c1275de9f24dedd153a71c9aad66d211545e29 Mon Sep 17 00:00:00 2001 From: Jude Nelson Date: Sun, 19 Jul 2020 21:45:50 -0400 Subject: [PATCH 04/16] add burnchain block height when advancing a chain tip --- src/chainstate/stacks/db/mod.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/chainstate/stacks/db/mod.rs b/src/chainstate/stacks/db/mod.rs index 8ef100670..58bebd5e7 100644 --- a/src/chainstate/stacks/db/mod.rs +++ b/src/chainstate/stacks/db/mod.rs @@ -161,6 +161,7 @@ pub struct StacksHeaderInfo { pub index_root: TrieHash, pub consensus_hash: ConsensusHash, pub burn_header_hash: BurnchainHeaderHash, + pub burn_header_height: u32, pub burn_header_timestamp: u64 } @@ -190,6 +191,7 @@ impl StacksHeaderInfo { block_height: 0, index_root: root_hash, burn_header_hash: FIRST_BURNCHAIN_BLOCK_HASH.clone(), + burn_header_height: FIRST_BURNCHAIN_BLOCK_HEIGHT, consensus_hash: FIRST_BURNCHAIN_CONSENSUS_HASH.clone(), burn_header_timestamp: FIRST_BURNCHAIN_BLOCK_TIMESTAMP } @@ -222,6 +224,7 @@ impl FromRow for StacksHeaderInfo { let index_root = TrieHash::from_column(row, "index_root")?; let consensus_hash = ConsensusHash::from_column(row, "consensus_hash")?; let burn_header_hash = BurnchainHeaderHash::from_column(row, "burn_header_hash")?; + let burn_header_height = u64::from_column(row, "burn_header_height")? as u32; let burn_header_timestamp = u64::from_column(row, "burn_header_timestamp")?; let stacks_header = StacksBlockHeader::from_row(row)?; @@ -236,6 +239,7 @@ impl FromRow for StacksHeaderInfo { index_root: index_root, consensus_hash: consensus_hash, burn_header_hash: burn_header_hash, + burn_header_height: burn_header_height, burn_header_timestamp: burn_header_timestamp }) } @@ -400,6 +404,7 @@ const STACKS_CHAIN_STATE_SQL : &'static [&'static str]= &[ index_root TEXT NOT NULL, -- root hash of the internal, not-consensus-critical MARF that allows us to track chainstate /fork metadata consensus_hash TEXT UNIQUE NOT NULL, -- all consensus hashes are guaranteed to be unique burn_header_hash TEXT NOT NULL, -- burn header hash corresponding to the consensus hash (NOT guaranteed to be unique, since we can have 2+ blocks per burn block if there's a PoX fork) + burn_header_height INT NOT NULL, -- height of the burnchain block header that generated this consensus hash burn_header_timestamp INT NOT NULL, -- timestamp from burnchain block header that generated this consensus hash PRIMARY KEY(consensus_hash,block_hash) @@ -878,6 +883,8 @@ impl StacksChainState { Ok((chainstate_tx, clarity_instance)) } + // NOTE: used for testing in the stacks testnet code. + // DO NOT CALL FROM PRODUCTION pub fn clarity_eval_read_only(&mut self, parent_id_bhh: &StacksBlockId, contract: &QualifiedContractIdentifier, code: &str) -> Value { let result = self.clarity_state.eval_read_only(parent_id_bhh, &self.headers_db, contract, code); @@ -1051,6 +1058,7 @@ impl StacksChainState { new_tip: &StacksBlockHeader, new_consensus_hash: &ConsensusHash, new_burn_header_hash: &BurnchainHeaderHash, + new_burnchain_height: u32, new_burnchain_timestamp: u64, microblock_tail_opt: Option, block_reward: &MinerPaymentSchedule, @@ -1090,6 +1098,7 @@ impl StacksChainState { block_height: new_tip.total_work.work, consensus_hash: new_consensus_hash.clone(), burn_header_hash: new_burn_header_hash.clone(), + burn_header_height: new_burnchain_height, burn_header_timestamp: new_burnchain_timestamp }; From e125df800302d2bf342b3d16ff9716004a5de394 Mon Sep 17 00:00:00 2001 From: Jude Nelson Date: Sun, 19 Jul 2020 21:46:03 -0400 Subject: [PATCH 05/16] API sync for miner --- src/chainstate/stacks/miner.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/chainstate/stacks/miner.rs b/src/chainstate/stacks/miner.rs index e835275e7..15d85d0d0 100644 --- a/src/chainstate/stacks/miner.rs +++ b/src/chainstate/stacks/miner.rs @@ -311,7 +311,7 @@ impl StacksBlockBuilder { builder } - fn first_pubkey_hash(miner_id: usize, genesis_consensus_hash: &ConsensusHash, genesis_burn_header_hash: &BurnchainHeaderHash, genesis_burn_header_timestamp: u64, proof: &VRFProof, pubkh: Hash160) -> StacksBlockBuilder { + fn first_pubkey_hash(miner_id: usize, genesis_consensus_hash: &ConsensusHash, genesis_burn_header_hash: &BurnchainHeaderHash, genesis_burn_header_height: u32, genesis_burn_header_timestamp: u64, proof: &VRFProof, pubkh: Hash160) -> StacksBlockBuilder { let genesis_chain_tip = StacksHeaderInfo { anchored_header: StacksBlockHeader::genesis_block_header(), microblock_tail: None, @@ -319,7 +319,8 @@ impl StacksBlockBuilder { index_root: TrieHash([0u8; 32]), consensus_hash: genesis_consensus_hash.clone(), burn_header_hash: genesis_burn_header_hash.clone(), - burn_header_timestamp: genesis_burn_header_timestamp + burn_header_timestamp: genesis_burn_header_timestamp, + burn_header_height: genesis_burn_header_height, }; let mut builder = StacksBlockBuilder::from_parent_pubkey_hash(miner_id, &genesis_chain_tip, &StacksWorkScore::initial(), proof, pubkh); @@ -327,12 +328,12 @@ impl StacksBlockBuilder { builder } - pub fn first(miner_id: usize, genesis_consensus_hash: &ConsensusHash, genesis_burn_header_hash: &BurnchainHeaderHash, genesis_burn_header_timestamp: u64, proof: &VRFProof, microblock_privkey: &StacksPrivateKey) -> StacksBlockBuilder { + pub fn first(miner_id: usize, genesis_consensus_hash: &ConsensusHash, genesis_burn_header_hash: &BurnchainHeaderHash, genesis_burn_header_height: u32, genesis_burn_header_timestamp: u64, proof: &VRFProof, microblock_privkey: &StacksPrivateKey) -> StacksBlockBuilder { let mut pubk = StacksPublicKey::from_private(microblock_privkey); pubk.set_compressed(true); let pubkh = Hash160::from_data(&pubk.to_bytes()); - let mut builder = StacksBlockBuilder::first_pubkey_hash(miner_id, genesis_consensus_hash, genesis_burn_header_hash, genesis_burn_header_timestamp, proof, pubkh); + let mut builder = StacksBlockBuilder::first_pubkey_hash(miner_id, genesis_consensus_hash, genesis_burn_header_hash, genesis_burn_header_height, genesis_burn_header_timestamp, proof, pubkh); builder.miner_privkey = microblock_privkey.clone(); builder } @@ -642,7 +643,7 @@ impl StacksBlockBuilder { let builder = if stacks_parent_header.consensus_hash == FIRST_BURNCHAIN_CONSENSUS_HASH { - StacksBlockBuilder::first_pubkey_hash(0, &FIRST_BURNCHAIN_CONSENSUS_HASH, &FIRST_BURNCHAIN_BLOCK_HASH, FIRST_BURNCHAIN_BLOCK_TIMESTAMP, &proof, pubkey_hash) + StacksBlockBuilder::first_pubkey_hash(0, &FIRST_BURNCHAIN_CONSENSUS_HASH, &FIRST_BURNCHAIN_BLOCK_HASH, FIRST_BURNCHAIN_BLOCK_HEIGHT, FIRST_BURNCHAIN_BLOCK_TIMESTAMP, &proof, pubkey_hash) } else { // building off an existing stacks block @@ -1258,7 +1259,13 @@ pub mod test { let (builder, parent_block_snapshot_opt) = match parent_stacks_block { None => { // first stacks block - let builder = StacksBlockBuilder::first(miner.id, &burn_block.parent_snapshot.consensus_hash, &burn_block.parent_snapshot.burn_header_hash, burn_block.parent_snapshot.burn_header_timestamp, &proof, &miner.next_microblock_privkey()); + let builder = StacksBlockBuilder::first(miner.id, + &burn_block.parent_snapshot.consensus_hash, + &burn_block.parent_snapshot.burn_header_hash, + burn_block.parent_snapshot.block_height as u32, + burn_block.parent_snapshot.burn_header_timestamp, + &proof, + &miner.next_microblock_privkey()); (builder, None) }, Some(parent_stacks_block) => { @@ -1325,7 +1332,7 @@ pub mod test { // "discover" this stacks block test_debug!("\n\nPreprocess Stacks block {}/{} ({})", &commit_snapshot.consensus_hash, &block_hash, StacksBlockHeader::make_index_block_hash(&commit_snapshot.consensus_hash, &block_hash)); - let block_res = node.chainstate.preprocess_anchored_block(&ic, &commit_snapshot.consensus_hash, commit_snapshot.burn_header_timestamp, &stacks_block, &parent_block_consensus_hash).unwrap(); + let block_res = node.chainstate.preprocess_anchored_block(&ic, &commit_snapshot.consensus_hash, &stacks_block, &parent_block_consensus_hash).unwrap(); // "discover" this stacks microblock stream for mblock in stacks_microblocks.iter() { From 49cbefeb1432a83341bedc713fb3f1d34112238f Mon Sep 17 00:00:00 2001 From: Jude Nelson Date: Sun, 19 Jul 2020 21:46:15 -0400 Subject: [PATCH 06/16] placeholder first burnchain block height const --- src/core/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/mod.rs b/src/core/mod.rs index 50772ea1a..13fcdf40e 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -42,6 +42,7 @@ pub const NETWORK_P2P_PORT : u16 = 6265; // first burnchain block hash pub const FIRST_BURNCHAIN_CONSENSUS_HASH : ConsensusHash = ConsensusHash([0u8; 20]); pub const FIRST_BURNCHAIN_BLOCK_HASH : BurnchainHeaderHash = BurnchainHeaderHash([0u8; 32]); +pub const FIRST_BURNCHAIN_BLOCK_HEIGHT : u32 = 0; pub const FIRST_BURNCHAIN_BLOCK_TIMESTAMP : u64 = 0; pub const FIRST_BURNCHAIN_BLOCK_HASH_TESTNET : BurnchainHeaderHash = BurnchainHeaderHash([1u8; 32]); From 646c25e13fdada0031476f806abf56bc5d82d23d Mon Sep 17 00:00:00 2001 From: Jude Nelson Date: Sun, 19 Jul 2020 21:46:26 -0400 Subject: [PATCH 07/16] API sync net tests --- src/net/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/mod.rs b/src/net/mod.rs index 7fe69f5be..7c37ada92 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -2100,7 +2100,7 @@ pub mod test { }; let ic = sortdb.index_conn(); - node.chainstate.preprocess_anchored_block(&ic, &sn.consensus_hash, sn.burn_header_timestamp, block, &parent_sn.consensus_hash) + node.chainstate.preprocess_anchored_block(&ic, &sn.consensus_hash, block, &parent_sn.consensus_hash) .map_err(|e| format!("Failed to preprocess anchored block: {:?}", &e)) }; self.sortdb = Some(sortdb); From bef095a07adff7e2e6b4515fcdccd48d751bb63e Mon Sep 17 00:00:00 2001 From: Jude Nelson Date: Sun, 19 Jul 2020 21:46:35 -0400 Subject: [PATCH 08/16] API sync relayer --- src/net/relay.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/net/relay.rs b/src/net/relay.rs index 0bacaed20..55435846b 100644 --- a/src/net/relay.rs +++ b/src/net/relay.rs @@ -474,14 +474,6 @@ impl Relayer { /// Insert a staging block fn process_new_anchored_block(sort_ic: &SortitionDBConn, chainstate: &mut StacksChainState, consensus_hash: &ConsensusHash, block: &StacksBlock) -> Result { - let sn = match SortitionDB::get_block_snapshot_consensus(sort_ic.conn, consensus_hash)? { - Some(sn) => sn, - None => { - debug!("Received unknown block {}/{}", consensus_hash, block.block_hash()); - return Ok(false); - } - }; - // find the snapshot of the parent of this block let db_handle = SortitionHandleConn::open_reader_consensus(sort_ic, consensus_hash)?; let parent_block_snapshot = match db_handle.get_block_snapshot_of_parent_stacks_block(consensus_hash, &block.block_hash())? { @@ -492,7 +484,7 @@ impl Relayer { } }; - chainstate.preprocess_anchored_block(sort_ic, consensus_hash, sn.burn_header_timestamp, block, &parent_block_snapshot.consensus_hash) + chainstate.preprocess_anchored_block(sort_ic, consensus_hash, block, &parent_block_snapshot.consensus_hash) } /// Coalesce a set of microblocks into relayer hints and MicroblocksData messages, as calculated by From cd044cb0d43d46fdc9eec004ec64e835e2d76d03 Mon Sep 17 00:00:00 2001 From: Jude Nelson Date: Sun, 19 Jul 2020 21:46:49 -0400 Subject: [PATCH 09/16] API sync on tests --- src/net/rpc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/net/rpc.rs b/src/net/rpc.rs index d9c2746be..006fcbca5 100644 --- a/src/net/rpc.rs +++ b/src/net/rpc.rs @@ -1606,7 +1606,7 @@ mod test { let index_block_hash = StacksBlockHeader::make_index_block_hash(&peer_server_consensus_hash, &peer_server_block.block_hash()); test_debug!("Store peer server index block {:?}", &index_block_hash); - store_staging_block(peer_server.chainstate(), &peer_server_consensus_hash, get_epoch_time_secs(), &peer_server_block, &ConsensusHash([0x03; 20]), 456, 123); + store_staging_block(peer_server.chainstate(), &peer_server_consensus_hash, &peer_server_block, &ConsensusHash([0x03; 20]), 456, 123); *server_block_cell.borrow_mut() = Some(peer_server_block); @@ -1642,7 +1642,7 @@ mod test { let index_block_hash = StacksBlockHeader::make_index_block_hash(&peer_server_consensus_hash, &peer_server_block.block_hash()); test_debug!("Store peer server index block {:?}", &index_block_hash); - store_staging_block(peer_server.chainstate(), &peer_server_consensus_hash, get_epoch_time_secs(), &peer_server_block, &ConsensusHash([0x03; 20]), 456, 123); + store_staging_block(peer_server.chainstate(), &peer_server_consensus_hash, &peer_server_block, &ConsensusHash([0x03; 20]), 456, 123); set_block_processed(peer_server.chainstate(), &peer_server_consensus_hash, &peer_server_block.block_hash(), true); *server_block_cell.borrow_mut() = Some(peer_server_block); From 26f7f0eb8b4c0b9217bba4802af8f1c28004f579 Mon Sep 17 00:00:00 2001 From: Jude Nelson Date: Sun, 19 Jul 2020 21:46:58 -0400 Subject: [PATCH 10/16] API sync on tests --- src/net/server.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/net/server.rs b/src/net/server.rs index 08eebe3a3..14d739359 100644 --- a/src/net/server.rs +++ b/src/net/server.rs @@ -729,7 +729,7 @@ mod test { let index_block_hash = StacksBlockHeader::make_index_block_hash(&peer_server_consensus_hash, &peer_server_block.block_hash()); test_debug!("Store peer server index block {:?}", &index_block_hash); - store_staging_block(peer_server.chainstate(), &peer_server_consensus_hash, get_epoch_time_secs(), &peer_server_block, &ConsensusHash([client_id as u8; 20]), 456, 123); + store_staging_block(peer_server.chainstate(), &peer_server_consensus_hash, &peer_server_block, &ConsensusHash([client_id as u8; 20]), 456, 123); let mut request = HttpRequestType::GetBlock(HttpRequestMetadata::from_host(PeerHost::from_host_port("127.0.0.1".to_string(), 51021)), index_block_hash); request.metadata_mut().keep_alive = false; @@ -764,7 +764,7 @@ mod test { let index_block_hash = StacksBlockHeader::make_index_block_hash(&peer_server_consensus_hash, &peer_server_block.block_hash()); test_debug!("Store peer server index block {:?}", &index_block_hash); - store_staging_block(peer_server.chainstate(), &peer_server_consensus_hash, get_epoch_time_secs(), &peer_server_block, &ConsensusHash([client_id as u8; 20]), 456, 123); + store_staging_block(peer_server.chainstate(), &peer_server_consensus_hash, &peer_server_block, &ConsensusHash([client_id as u8; 20]), 456, 123); let mut request = HttpRequestType::GetBlock(HttpRequestMetadata::from_host(PeerHost::from_host_port("127.0.0.1".to_string(), 51031)), index_block_hash); request.metadata_mut().keep_alive = false; @@ -965,7 +965,7 @@ mod test { let index_block_hash = StacksBlockHeader::make_index_block_hash(&peer_server_consensus_hash, &peer_server_block.block_hash()); test_debug!("Store peer server index block {:?}", &index_block_hash); - store_staging_block(peer_server.chainstate(), &peer_server_consensus_hash, get_epoch_time_secs(), &peer_server_block, &ConsensusHash([client_id as u8; 20]), 456, 123); + store_staging_block(peer_server.chainstate(), &peer_server_consensus_hash, &peer_server_block, &ConsensusHash([client_id as u8; 20]), 456, 123); let mut request = HttpRequestType::GetBlock(HttpRequestMetadata::from_host(PeerHost::from_host_port("127.0.0.1".to_string(), 51071)), index_block_hash); request.metadata_mut().keep_alive = false; From 98a6f791f9b619d3cb172622a22c753c51a45841 Mon Sep 17 00:00:00 2001 From: Jude Nelson Date: Sun, 19 Jul 2020 21:47:08 -0400 Subject: [PATCH 11/16] Add trait method for HeadersDB for getting the burnchain block height, given a block-id-hash --- src/vm/database/clarity_db.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/vm/database/clarity_db.rs b/src/vm/database/clarity_db.rs index 9a5809b98..15699e9c3 100644 --- a/src/vm/database/clarity_db.rs +++ b/src/vm/database/clarity_db.rs @@ -57,6 +57,7 @@ pub trait HeadersDB { fn get_burn_header_hash_for_block(&self, id_bhh: &StacksBlockId) -> Option; fn get_vrf_seed_for_block(&self, id_bhh: &StacksBlockId) -> Option; fn get_burn_block_time_for_block(&self, id_bhh: &StacksBlockId) -> Option; + fn get_burn_block_height_for_block(&self, id_bhh: &StacksBlockId) -> Option; fn get_miner_address(&self, id_bhh: &StacksBlockId) -> Option; } @@ -92,6 +93,11 @@ impl HeadersDB for DBConn { .map(|x| x.burn_header_timestamp) } + fn get_burn_block_height_for_block(&self, id_bhh: &StacksBlockId) -> Option { + get_stacks_header_info(self, id_bhh) + .map(|x| x.burn_header_height) + } + fn get_vrf_seed_for_block(&self, id_bhh: &StacksBlockId) -> Option { get_stacks_header_info(self, id_bhh) .map(|x| VRFSeed::from_proof(&x.anchored_header.proof)) @@ -116,6 +122,9 @@ impl HeadersDB for &dyn HeadersDB { fn get_burn_block_time_for_block(&self, bhh: &StacksBlockId) -> Option { (*self).get_burn_block_time_for_block(bhh) } + fn get_burn_block_height_for_block(&self, bhh: &StacksBlockId) -> Option { + (*self).get_burn_block_height_for_block(bhh) + } fn get_miner_address(&self, bhh: &StacksBlockId) -> Option { (*self).get_miner_address(bhh) } @@ -138,6 +147,9 @@ impl HeadersDB for NullHeadersDB { fn get_burn_block_time_for_block(&self, _id_bhh: &StacksBlockId) -> Option { None } + fn get_burn_block_height_for_block(&self, _id_bhh: &StacksBlockId) -> Option { + None + } fn get_miner_address(&self, _id_bhh: &StacksBlockId) -> Option { None } @@ -297,6 +309,13 @@ impl <'a> ClarityDatabase <'a> { self.store.get_current_block_height() } + pub fn get_current_burnchain_block_height(&mut self) -> u32 { + let cur_stacks_height = self.store.get_current_block_height(); + let cur_id_bhh = self.get_index_block_header_hash(cur_stacks_height); + self.get_burnchain_block_height(&cur_id_bhh) + .expect("Block header hash must return for provided burn block height") + } + pub fn get_block_header_hash(&mut self, block_height: u32) -> BlockHeaderHash { let id_bhh = self.get_index_block_header_hash(block_height); self.headers_db.get_stacks_block_header_hash_for_block(&id_bhh) @@ -314,6 +333,10 @@ impl <'a> ClarityDatabase <'a> { self.headers_db.get_burn_header_hash_for_block(&id_bhh) .expect("Failed to get block data.") } + + pub fn get_burnchain_block_height(&mut self, id_bhh: &StacksBlockId) -> Option { + self.headers_db.get_burn_block_height_for_block(id_bhh) + } pub fn get_block_vrf_seed(&mut self, block_height: u32) -> VRFSeed { let id_bhh = self.get_index_block_header_hash(block_height); From 2c7ec8a97e914d621bad075eadf5e79b411a868f Mon Sep 17 00:00:00 2001 From: Jude Nelson Date: Sun, 19 Jul 2020 21:47:27 -0400 Subject: [PATCH 12/16] add documentation for burn-block-height --- src/vm/docs/mod.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/vm/docs/mod.rs b/src/vm/docs/mod.rs index 693121f44..d634c24fb 100644 --- a/src/vm/docs/mod.rs +++ b/src/vm/docs/mod.rs @@ -55,10 +55,17 @@ struct DefineAPI { const BLOCK_HEIGHT: KeywordAPI = KeywordAPI { name: "block-height", output_type: "uint", - description: "Returns the current block height of the Stacks blockchain as an int", + description: "Returns the current block height of the Stacks blockchain as an uint", example: "(> block-height 1000) ;; returns true if the current block-height has passed 1000 blocks." }; +const BURN_BLOCK_HEIGHT: KeywordAPI = KeywordAPI { + name: "burn-block-height", + output_type: "uint", + description: "Returns the current block height of the underlying burn blockchain as a uint", + example: "(> burn-block-height 1000) ;; returns true if the current height of the underlying burn blockchain has passed 1000 blocks." +}; + const CONTRACT_CALLER_KEYWORD: KeywordAPI = KeywordAPI { name: "contract-caller", output_type: "principal", @@ -1392,7 +1399,7 @@ fn make_keyword_reference(variable: &NativeVariables) -> Option { NativeVariables::NativeTrue => Some(TRUE_KEYWORD.clone()), NativeVariables::NativeFalse => Some(FALSE_KEYWORD.clone()), NativeVariables::BlockHeight => Some(BLOCK_HEIGHT.clone()), - NativeVariables::BurnBlockHeight => None, + NativeVariables::BurnBlockHeight => Some(BURN_BLOCK_HEIGHT.clone()), } } @@ -1490,6 +1497,9 @@ mod test { fn get_burn_block_time_for_block(&self, _id_bhh: &StacksBlockId) -> Option { Some(1557860301) } + fn get_burn_block_height_for_block(&self, _id_bhh: &StacksBlockId) -> Option { + Some(567890) + } fn get_miner_address(&self, _id_bhh: &StacksBlockId) -> Option { None } From 8ca4a90ab2c954c27085ac26c2c852eafc92a312 Mon Sep 17 00:00:00 2001 From: Jude Nelson Date: Sun, 19 Jul 2020 21:47:40 -0400 Subject: [PATCH 13/16] implement burn-block-height --- src/vm/variables.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vm/variables.rs b/src/vm/variables.rs index d884370e0..2892fa002 100644 --- a/src/vm/variables.rs +++ b/src/vm/variables.rs @@ -31,7 +31,8 @@ pub fn lookup_reserved_variable(name: &str, _context: &LocalContext, env: &mut E Ok(Some(Value::UInt(block_height as u128))) }, NativeVariables::BurnBlockHeight => { - Err(RuntimeErrorType::NotImplemented.into()) + let burn_block_height = env.global_context.database.get_current_burnchain_block_height(); + Ok(Some(Value::UInt(burn_block_height as u128))) }, NativeVariables::NativeNone => { Ok(Some(Value::none())) From 7d7bf41eaf91b1ea4289136b564b5194cbe33f09 Mon Sep 17 00:00:00 2001 From: Jude Nelson Date: Sun, 19 Jul 2020 21:47:51 -0400 Subject: [PATCH 14/16] API sync --- testnet/stacks-node/src/neon_node.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/testnet/stacks-node/src/neon_node.rs b/testnet/stacks-node/src/neon_node.rs index 8faf00d07..2e876167b 100644 --- a/testnet/stacks-node/src/neon_node.rs +++ b/testnet/stacks-node/src/neon_node.rs @@ -30,7 +30,6 @@ use stacks::chainstate::stacks::StacksPublicKey; use stacks::core::mempool::MemPoolDB; use stacks::net::dns::DNSResolver; use stacks::util::vrf::VRFPublicKey; -use stacks::util::get_epoch_time_secs; use stacks::util::strings::UrlString; use stacks::util::hash::Hash160; use stacks::util::hash::Sha256Sum; @@ -122,7 +121,6 @@ fn inner_process_tenure( chain_state.preprocess_anchored_block( &ic, consensus_hash, - get_epoch_time_secs(), &anchored_block, &parent_consensus_hash)?; } From c42253bafa2f431cc3cacab3a2ca9cb16bee402c Mon Sep 17 00:00:00 2001 From: Jude Nelson Date: Sun, 19 Jul 2020 21:48:03 -0400 Subject: [PATCH 15/16] API sync --- testnet/stacks-node/src/node.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/testnet/stacks-node/src/node.rs b/testnet/stacks-node/src/node.rs index 6204774a9..e601be07a 100644 --- a/testnet/stacks-node/src/node.rs +++ b/testnet/stacks-node/src/node.rs @@ -27,7 +27,6 @@ use stacks::net::{ }; use stacks::util::vrf::VRFPublicKey; -use stacks::util::get_epoch_time_secs; use stacks::util::strings::UrlString; use stacks::util::hash::Sha256Sum; use stacks::util::secp256k1::Secp256k1PrivateKey; @@ -488,7 +487,6 @@ impl Node { self.chain_state.preprocess_anchored_block( &ic, consensus_hash, - get_epoch_time_secs(), &anchored_block, &parent_consensus_hash).unwrap(); From 828843780ca3d5920776a2c71062cbaf5d5cef22 Mon Sep 17 00:00:00 2001 From: Jude Nelson Date: Sun, 19 Jul 2020 21:48:15 -0400 Subject: [PATCH 16/16] add integration test for getting the current burnchain block height --- testnet/stacks-node/src/tests/integrations.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/testnet/stacks-node/src/tests/integrations.rs b/testnet/stacks-node/src/tests/integrations.rs index 280172841..3f79c391f 100644 --- a/testnet/stacks-node/src/tests/integrations.rs +++ b/testnet/stacks-node/src/tests/integrations.rs @@ -43,6 +43,7 @@ const GET_INFO_CONTRACT: &'static str = " (define-private (test-8) (get-block-info? miner-address u1)) (define-private (test-9) (get-block-info? miner-address block-height)) (define-private (test-10) (get-block-info? miner-address u100000)) + (define-private (test-11) burn-block-height) (define-private (get-block-id-hash (height uint)) (unwrap-panic (get id-hash (map-get? block-data ((height height)))))) @@ -258,6 +259,13 @@ fn integration_test_get_info() { chain_state.clarity_eval_read_only( bhh, &contract_identifier, "(test-10)"), Value::none()); + + // verify we can read the burn block height (should be 3, since we sent the + // contract at block 2) + assert_eq!( + chain_state.clarity_eval_read_only( + bhh, &contract_identifier, "(test-11)"), + Value::UInt(3)); }, 3 => {