Skip to content

Feat/tenure change validation #4114

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

Merged
merged 45 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
ab8a906
chore: getters for previous mock miner's block-commits and blocks
jcnelson Dec 1, 2023
4348679
refactor: use new matured miner reward struct
jcnelson Dec 1, 2023
7e47dfa
feat: implement full tenure-change validation by tracking highest-pro…
jcnelson Dec 1, 2023
948595c
testing: expand unit testing for tenure-start block validation, coinb…
jcnelson Dec 1, 2023
13b0f1b
testing: require nodes to begin Nakamoto off of an epoch2 block, and …
jcnelson Dec 1, 2023
bf865d4
chore: sync with tenure-change struct
jcnelson Dec 1, 2023
b753a7c
feat: add support for tenure budget extension
jcnelson Dec 1, 2023
60fee44
feat: tenure-changes identify current and previous tenures by consens…
jcnelson Dec 1, 2023
3a700cb
testing: find the last anchored block in the mock miner even if it's …
jcnelson Dec 1, 2023
a0386c2
chore: try_as_tenure_change()
jcnelson Dec 1, 2023
461b282
chore: add reset_cost() function for tenure-change budget extension
jcnelson Dec 1, 2023
ad1f178
chore: log block rejection
jcnelson Dec 1, 2023
a276e50
chore: tenure-change requires prev_consensus_hash
jcnelson Dec 1, 2023
690fcdc
Merge branch 'next' into feat/tenure-change-validation
jcnelson Dec 1, 2023
5f92195
fix: workspace dependency
jcnelson Dec 1, 2023
d650b72
chore: remove commented-out code
jcnelson Dec 1, 2023
38af405
chore: cargo fmt
jcnelson Dec 7, 2023
e1283ef
testing: return the snapshots created in a fork run
jcnelson Dec 7, 2023
63b2039
testing: expand test coverage over more NakamotoChainState methods, a…
jcnelson Dec 7, 2023
2fe8fb3
chore: alter the Nakamoto block miner so it just takes the coinbase a…
jcnelson Dec 7, 2023
0d8b1d3
feat: flesh out tenure-extension handling, and also, move all tenure-…
jcnelson Dec 7, 2023
5139cf6
feat: test that the query to find the highest tenure works even if th…
jcnelson Dec 7, 2023
6e34e3b
chore: refactor test code so that the caller supplies the tenure-chan…
jcnelson Dec 7, 2023
76009a9
chore: API sync
jcnelson Dec 7, 2023
158f58f
chore: don't reset execution cost in response to a tx
jcnelson Dec 7, 2023
071fd3b
chore: require a tenure-change tx in addition to a coinbase
jcnelson Dec 7, 2023
c46c776
feat: derive tenure extension from a tenure change
jcnelson Dec 7, 2023
259f481
chore: API sync
jcnelson Dec 7, 2023
cddf031
chore: don't allow a transaction to reset the runtime cost
jcnelson Dec 7, 2023
48e6b00
chore: need &mut for sortition handle
jcnelson Dec 7, 2023
aa9cbb7
feat: move all tenure-control logic into its own file
jcnelson Dec 7, 2023
f23694d
Merge branch 'next' into feat/tenure-change-validation
jcnelson Dec 7, 2023
37e134b
chore: address PR feedback and get testnet to build
jcnelson Dec 8, 2023
3f02431
Merge branch 'next' into feat/tenure-change-validation
jcnelson Dec 11, 2023
8155592
chore: extend SortitionDB::get_canonical_stacks_tip_block_hash to als…
jcnelson Dec 11, 2023
ded3b54
chore: modify tests to work with new NakamotoChainState::get_highest_…
jcnelson Dec 11, 2023
863ae14
chore: pull forward canonical block header pointer
jcnelson Dec 11, 2023
5dfbb25
chore: API sync
jcnelson Dec 11, 2023
6934d7d
chore: remove dead code
jcnelson Dec 11, 2023
e52e570
chore: query highest tenure from memoized canonical stacks chain tip
jcnelson Dec 11, 2023
375db58
fix: get fork test to work with new highest-tenure query
jcnelson Dec 11, 2023
0b835e0
Merge branch 'feat/tenure-change-validation' of https://github.com/st…
jcnelson Dec 11, 2023
221b4ba
Merge branch 'next' into feat/tenure-change-validation
jcnelson Dec 11, 2023
6ef458f
Merge branch 'next' into feat/tenure-change-validation
jcnelson Dec 12, 2023
f751c40
Merge branch 'next' into feat/tenure-change-validation
jcnelson Dec 12, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 1 addition & 5 deletions stacks-common/src/types/chainstate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ use crate::codec::{read_next, write_next, Error as CodecError, StacksMessageCode
use crate::consts::{FIRST_BURNCHAIN_CONSENSUS_HASH, FIRST_STACKS_BLOCK_HASH};
use crate::deps_common::bitcoin::util::hash::Sha256dHash;
use crate::util::hash::{to_hex, DoubleSha256, Hash160, Sha512Trunc256Sum, HASH160_ENCODED_SIZE};
use crate::util::secp256k1::{
MessageSignature, SchnorrSignature, Secp256k1PrivateKey, Secp256k1PublicKey,
};
use crate::util::secp256k1::{MessageSignature, Secp256k1PrivateKey, Secp256k1PublicKey};
use crate::util::uint::Uint256;
use crate::util::vrf::{VRFProof, VRF_PROOF_ENCODED_SIZE};

Expand Down Expand Up @@ -338,7 +336,6 @@ impl_byte_array_rusqlite_only!(VRFProof);
impl_byte_array_rusqlite_only!(TrieHash);
impl_byte_array_rusqlite_only!(Sha512Trunc256Sum);
impl_byte_array_rusqlite_only!(MessageSignature);
impl_byte_array_rusqlite_only!(SchnorrSignature);

impl_byte_array_message_codec!(TrieHash, TRIEHASH_ENCODED_SIZE as u32);
impl_byte_array_message_codec!(Sha512Trunc256Sum, 32);
Expand All @@ -349,7 +346,6 @@ impl_byte_array_message_codec!(BurnchainHeaderHash, 32);
impl_byte_array_message_codec!(BlockHeaderHash, 32);
impl_byte_array_message_codec!(StacksBlockId, 32);
impl_byte_array_message_codec!(MessageSignature, 65);
impl_byte_array_message_codec!(SchnorrSignature, 65);

impl BlockHeaderHash {
pub fn to_hash160(&self) -> Hash160 {
Expand Down
2 changes: 0 additions & 2 deletions stacks-common/src/util/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

use std::cell::RefCell;

// is this machine big-endian?
pub fn is_big_endian() -> bool {
u32::from_be(0x1Au32) == 0x1Au32
Expand Down
41 changes: 2 additions & 39 deletions stacks-common/src/util/secp256k1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,45 +118,6 @@ impl Default for Secp256k1PublicKey {
}
}

pub struct SchnorrSignature(pub [u8; 65]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really nice to see this go XD Didn't like it in there to begin with.

impl_array_newtype!(SchnorrSignature, u8, 65);
impl_array_hexstring_fmt!(SchnorrSignature);
impl_byte_array_newtype!(SchnorrSignature, u8, 65);
impl_byte_array_serde!(SchnorrSignature);
pub const SCHNORR_SIGNATURE_ENCODED_SIZE: u32 = 65;

impl Default for SchnorrSignature {
/// Creates a default Schnorr Signature. Note this is not a valid signature.
fn default() -> Self {
Self([0u8; 65])
}
}

impl SchnorrSignature {
/// Attempt to convert a Schnorr signature to a WSTS Signature
pub fn to_wsts_signature(&self) -> Option<WSTSSignature> {
// TODO: update wsts to add a TryFrom for a [u8; 65] and a slice to a Signature
let point_bytes: [u8; 33] = self.0[..33].try_into().ok()?;
let scalar_bytes: [u8; 32] = self.0[33..].try_into().ok()?;
let point = Point::try_from(&Compressed::from(point_bytes)).ok()?;
let scalar = Scalar::from(scalar_bytes);
Some(WSTSSignature {
R: point,
z: scalar,
})
}
}

/// Convert a WSTS Signature to a SchnorrSignature
impl From<&WSTSSignature> for SchnorrSignature {
fn from(signature: &WSTSSignature) -> Self {
let mut buf = [0u8; 65];
buf[..33].copy_from_slice(&signature.R.compress().data);
buf[33..].copy_from_slice(&signature.z.to_bytes());
SchnorrSignature(buf)
}
}

impl Secp256k1PublicKey {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we'd also move away from other libsecp256k1 wrappers. p256k1 wraps everything, including public keys, ecdsa/schnorr sigs, etc.

#[cfg(any(test, feature = "testing"))]
pub fn new() -> Secp256k1PublicKey {
Expand Down Expand Up @@ -744,6 +705,7 @@ mod tests {
);
}

/*
#[test]
fn test_schnorr_signature_serde() {
use wsts::traits::Aggregator;
Expand Down Expand Up @@ -820,4 +782,5 @@ mod tests {
assert!(reverted_signature.verify(&aggregate_public_key, msg));
}
}
*/
}
9 changes: 9 additions & 0 deletions stackslib/src/burnchains/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,15 @@ impl TestMiner {
}
}

pub fn block_commit_at(&self, idx: usize) -> Option<LeaderBlockCommitOp> {
assert!(idx < self.block_commits.len());
self.block_commits.get(idx).cloned()
}

pub fn num_block_commits(&self) -> usize {
self.block_commits.len()
}

pub fn next_VRF_key(&mut self) -> VRFPrivateKey {
let pk = if self.vrf_keys.len() == 0 {
// first key is simply the 32-byte hash of the secret state
Expand Down
49 changes: 39 additions & 10 deletions stackslib/src/chainstate/burn/db/sortdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1664,6 +1664,23 @@ impl<'a> SortitionHandleTx<'a> {
Ok(())
}

/// Update the canonical Stacks tip (testing only)
#[cfg(test)]
pub fn test_update_canonical_stacks_tip(
&mut self,
sort_id: &SortitionId,
consensus_hash: &ConsensusHash,
stacks_block_hash: &BlockHeaderHash,
stacks_block_height: u64,
) -> Result<(), db_error> {
self.update_canonical_stacks_tip(
sort_id,
consensus_hash,
stacks_block_hash,
stacks_block_height,
)
}

/// Mark an existing snapshot's stacks block as accepted at a particular burn chain tip within a PoX fork (identified by the consensus hash),
/// and calculate and store its arrival index.
/// If this Stacks block extends the canonical stacks chain tip, then also update the memoized canonical
Expand Down Expand Up @@ -4392,9 +4409,9 @@ impl SortitionDB {
}

/// Get the canonical Stacks chain tip -- this gets memoized on the canonical burn chain tip.
pub fn get_canonical_stacks_chain_tip_hash(
pub fn get_canonical_stacks_chain_tip_hash_and_height(
conn: &Connection,
) -> Result<(ConsensusHash, BlockHeaderHash), db_error> {
) -> Result<(ConsensusHash, BlockHeaderHash, u64), db_error> {
let sn = SortitionDB::get_canonical_burn_chain_tip(conn)?;
let cur_epoch = SortitionDB::get_stacks_epoch(conn, sn.block_height)?.expect(&format!(
"FATAL: no epoch defined for burn height {}",
Expand All @@ -4407,9 +4424,9 @@ impl SortitionDB {
let mut cursor = sn;
loop {
let result_at_tip = conn.query_row_and_then(
"SELECT consensus_hash,block_hash FROM stacks_chain_tips WHERE sortition_id = ?",
"SELECT consensus_hash,block_hash,block_height FROM stacks_chain_tips WHERE sortition_id = ?",
&[&cursor.sortition_id],
|row| Ok((row.get_unwrap(0), row.get_unwrap(1))),
|row| Ok((row.get_unwrap(0), row.get_unwrap(1), (u64::try_from(row.get_unwrap::<_, i64>(2)).expect("FATAL: block height too high"))))
).optional()?;
if let Some(stacks_tip) = result_at_tip {
return Ok(stacks_tip);
Expand All @@ -4422,8 +4439,16 @@ impl SortitionDB {
// epoch 2.x behavior -- look at the snapshot itself
let stacks_block_hash = sn.canonical_stacks_tip_hash;
let consensus_hash = sn.canonical_stacks_tip_consensus_hash;
let stacks_block_height = sn.canonical_stacks_tip_height;
Ok((consensus_hash, stacks_block_hash, stacks_block_height))
}

Ok((consensus_hash, stacks_block_hash))
/// Get the canonical Stacks chain tip -- this gets memoized on the canonical burn chain tip.
pub fn get_canonical_stacks_chain_tip_hash(
conn: &Connection,
) -> Result<(ConsensusHash, BlockHeaderHash), db_error> {
Self::get_canonical_stacks_chain_tip_hash_and_height(conn)
.map(|(ch, bhh, _height)| (ch, bhh))
}

/// Get the maximum arrival index for any known snapshot.
Expand Down Expand Up @@ -8462,13 +8487,14 @@ pub mod tests {
}
}

fn make_fork_run(
pub fn make_fork_run(
db: &mut SortitionDB,
start_snapshot: &BlockSnapshot,
length: u64,
bit_pattern: u8,
) -> () {
) -> Vec<BlockSnapshot> {
let mut last_snapshot = start_snapshot.clone();
let mut new_snapshots = vec![];
for i in last_snapshot.block_height..(last_snapshot.block_height + length) {
let snapshot = BlockSnapshot {
accumulated_coinbase_ustx: 0,
Expand All @@ -8491,11 +8517,13 @@ pub mod tests {
stacks_block_accepted: false,
stacks_block_height: 0,
arrival_index: 0,
canonical_stacks_tip_height: 0,
canonical_stacks_tip_hash: BlockHeaderHash([0u8; 32]),
canonical_stacks_tip_consensus_hash: ConsensusHash([0u8; 20]),
canonical_stacks_tip_height: last_snapshot.canonical_stacks_tip_height,
canonical_stacks_tip_hash: last_snapshot.canonical_stacks_tip_hash,
canonical_stacks_tip_consensus_hash: last_snapshot
.canonical_stacks_tip_consensus_hash,
miner_pk_hash: None,
};
new_snapshots.push(snapshot.clone());
{
let mut tx = SortitionHandleTx::begin(db, &last_snapshot.sortition_id).unwrap();
let _index_root = tx
Expand All @@ -8515,6 +8543,7 @@ pub mod tests {
.unwrap()
.unwrap();
}
new_snapshots
}

#[test]
Expand Down
Loading