diff --git a/crates/chia-consensus/src/gen/conditions.rs b/crates/chia-consensus/src/gen/conditions.rs index 3fd16e15b..e2a491ee3 100644 --- a/crates/chia-consensus/src/gen/conditions.rs +++ b/crates/chia-consensus/src/gen/conditions.rs @@ -1260,7 +1260,7 @@ pub fn parse_spends( )?; } - validate_conditions(a, &ret, state, spends, flags)?; + validate_conditions(a, &ret, &state, spends, flags)?; ret.cost = max_cost - cost_left; Ok(ret) @@ -1269,7 +1269,7 @@ pub fn parse_spends( pub fn validate_conditions( a: &Allocator, ret: &SpendBundleConditions, - state: ParseState, + state: &ParseState, spends: NodePtr, _flags: u32, ) -> Result<(), ValidationErr> { @@ -1309,13 +1309,13 @@ pub fn validate_conditions( } // check concurrent spent assertions - for coin_id in state.assert_concurrent_spend { + for coin_id in &state.assert_concurrent_spend { if !state .spent_coins - .contains_key(&Bytes32::try_from(a.atom(coin_id).as_ref()).unwrap()) + .contains_key(&Bytes32::try_from(a.atom(*coin_id).as_ref()).unwrap()) { return Err(ValidationErr( - coin_id, + *coin_id, ErrorCode::AssertConcurrentSpendFailed, )); } @@ -1326,14 +1326,14 @@ pub fn validate_conditions( // expand all the spent puzzle hashes into a set, to allow // fast lookups of all assertions - for ph in state.spent_puzzles { - spent_phs.insert(a.atom(ph).as_ref().try_into().unwrap()); + for ph in &state.spent_puzzles { + spent_phs.insert(a.atom(*ph).as_ref().try_into().unwrap()); } - for puzzle_assert in state.assert_concurrent_puzzle { - if !spent_phs.contains(&a.atom(puzzle_assert).as_ref().try_into().unwrap()) { + for puzzle_assert in &state.assert_concurrent_puzzle { + if !spent_phs.contains(&a.atom(*puzzle_assert).as_ref().try_into().unwrap()) { return Err(ValidationErr( - puzzle_assert, + *puzzle_assert, ErrorCode::AssertConcurrentPuzzleFailed, )); } @@ -1345,41 +1345,41 @@ pub fn validate_conditions( if !state.assert_coin.is_empty() { let mut announcements = HashSet::::new(); - for (coin_id, announce) in state.announce_coin { + for (coin_id, announce) in &state.announce_coin { let mut hasher = Sha256::new(); - hasher.update(*coin_id); - hasher.update(a.atom(announce)); + hasher.update(**coin_id); + hasher.update(a.atom(*announce)); let announcement_id: [u8; 32] = hasher.finalize(); announcements.insert(announcement_id.into()); } - for coin_assert in state.assert_coin { - if !announcements.contains(&a.atom(coin_assert).as_ref().try_into().unwrap()) { + for coin_assert in &state.assert_coin { + if !announcements.contains(&a.atom(*coin_assert).as_ref().try_into().unwrap()) { return Err(ValidationErr( - coin_assert, + *coin_assert, ErrorCode::AssertCoinAnnouncementFailed, )); } } } - for spend_idx in state.assert_ephemeral { + for spend_idx in &state.assert_ephemeral { // make sure this coin was created in this block - if !is_ephemeral(a, spend_idx, &state.spent_coins, &ret.spends) { + if !is_ephemeral(a, *spend_idx, &state.spent_coins, &ret.spends) { return Err(ValidationErr( - ret.spends[spend_idx].parent_id, + ret.spends[*spend_idx].parent_id, ErrorCode::AssertEphemeralFailed, )); } } - for spend_idx in state.assert_not_ephemeral { + for spend_idx in &state.assert_not_ephemeral { // make sure this coin was NOT created in this block // because consensus rules do not allow relative conditions on // ephemeral spends - if is_ephemeral(a, spend_idx, &state.spent_coins, &ret.spends) { + if is_ephemeral(a, *spend_idx, &state.spent_coins, &ret.spends) { return Err(ValidationErr( - ret.spends[spend_idx].parent_id, + ret.spends[*spend_idx].parent_id, ErrorCode::EphemeralRelativeCondition, )); } @@ -1388,18 +1388,18 @@ pub fn validate_conditions( if !state.assert_puzzle.is_empty() { let mut announcements = HashSet::::new(); - for (puzzle_hash, announce) in state.announce_puzzle { + for (puzzle_hash, announce) in &state.announce_puzzle { let mut hasher = Sha256::new(); - hasher.update(a.atom(puzzle_hash)); - hasher.update(a.atom(announce)); + hasher.update(a.atom(*puzzle_hash)); + hasher.update(a.atom(*announce)); let announcement_id: [u8; 32] = hasher.finalize(); announcements.insert(announcement_id.into()); } - for puzzle_assert in state.assert_puzzle { - if !announcements.contains(&a.atom(puzzle_assert).as_ref().try_into().unwrap()) { + for puzzle_assert in &state.assert_puzzle { + if !announcements.contains(&a.atom(*puzzle_assert).as_ref().try_into().unwrap()) { return Err(ValidationErr( - puzzle_assert, + *puzzle_assert, ErrorCode::AssertPuzzleAnnouncementFailed, )); } @@ -1434,19 +1434,6 @@ pub fn validate_conditions( Ok(()) } -#[cfg(test)] -pub(crate) fn u64_to_bytes(n: u64) -> Vec { - let mut buf = Vec::::new(); - buf.extend_from_slice(&n.to_be_bytes()); - if (buf[0] & 0x80) != 0 { - buf.insert(0, 0); - } else { - while buf.len() > 1 && buf[0] == 0 && (buf[1] & 0x80) == 0 { - buf.remove(0); - } - } - buf -} #[cfg(test)] use crate::consensus_constants::TEST_CONSTANTS; #[cfg(test)] @@ -1521,6 +1508,9 @@ const LONGMSG: &[u8; 1025] = &[ 4, ]; +#[cfg(test)] +use crate::gen::make_aggsig_final_message::u64_to_bytes; + #[cfg(test)] fn hash_buf(b1: &[u8], b2: &[u8]) -> Vec { let mut ctx = Sha256::new(); diff --git a/crates/chia-consensus/src/gen/flags.rs b/crates/chia-consensus/src/gen/flags.rs index 13ca7d6ce..830e4d50d 100644 --- a/crates/chia-consensus/src/gen/flags.rs +++ b/crates/chia-consensus/src/gen/flags.rs @@ -1,13 +1,16 @@ use clvmr::MEMPOOL_MODE as CLVM_MEMPOOL_MODE; -// flags controlling to condition parsing +// flags controlling the condition parsing +// These flags are combined in the same fields as clvm_rs flags, controlling the +// CLVM execution. To avoid clashes, CLVM flags are in the lower two bytes and +// condition parsing and validation flags are in the top two bytes. // unknown condition codes are disallowed -pub const NO_UNKNOWN_CONDS: u32 = 0x20000; +pub const NO_UNKNOWN_CONDS: u32 = 0x2_0000; // With this flag, conditions will require the exact number of arguments // currently supported for those conditions. This is meant for mempool-mode -pub const STRICT_ARGS_COUNT: u32 = 0x80000; +pub const STRICT_ARGS_COUNT: u32 = 0x8_0000; // when this flag is set, the block generator serialization is allowed to // contain back-references diff --git a/crates/chia-consensus/src/gen/get_puzzle_and_solution.rs b/crates/chia-consensus/src/gen/get_puzzle_and_solution.rs index 37dc735e8..53c1e839a 100644 --- a/crates/chia-consensus/src/gen/get_puzzle_and_solution.rs +++ b/crates/chia-consensus/src/gen/get_puzzle_and_solution.rs @@ -61,8 +61,8 @@ pub fn get_puzzle_and_solution_for_coin( mod test { use super::*; use crate::consensus_constants::TEST_CONSTANTS; - use crate::gen::conditions::u64_to_bytes; use crate::gen::flags::{ALLOW_BACKREFS, MEMPOOL_MODE}; + use crate::gen::make_aggsig_final_message::u64_to_bytes; use crate::gen::run_block_generator::{run_block_generator2, setup_generator_args}; use chia_protocol::Bytes32; use chia_sha2::Sha256; diff --git a/crates/chia-consensus/src/gen/make_aggsig_final_message.rs b/crates/chia-consensus/src/gen/make_aggsig_final_message.rs index 577e9530a..a0ad6dabd 100644 --- a/crates/chia-consensus/src/gen/make_aggsig_final_message.rs +++ b/crates/chia-consensus/src/gen/make_aggsig_final_message.rs @@ -4,7 +4,6 @@ use crate::gen::opcodes::{ AGG_SIG_PARENT_PUZZLE, AGG_SIG_PUZZLE, AGG_SIG_PUZZLE_AMOUNT, }; use crate::gen::owned_conditions::OwnedSpendConditions; -use chia_protocol::Bytes; use chia_protocol::Coin; pub fn make_aggsig_final_message( @@ -51,13 +50,13 @@ pub fn make_aggsig_final_message( } } -fn u64_to_bytes(val: u64) -> Bytes { +pub fn u64_to_bytes(val: u64) -> Vec { let amount_bytes: [u8; 8] = val.to_be_bytes(); if val >= 0x8000_0000_0000_0000_u64 { let mut ret = Vec::::new(); ret.push(0_u8); ret.extend(amount_bytes); - Bytes::new(ret) + ret } else { let start = match val { n if n >= 0x0080_0000_0000_0000_u64 => 0, @@ -70,7 +69,7 @@ fn u64_to_bytes(val: u64) -> Bytes { n if n > 0 => 7, _ => 8, }; - Bytes::new(amount_bytes[start..].to_vec()) + amount_bytes[start..].to_vec() } } diff --git a/crates/chia-consensus/src/gen/run_block_generator.rs b/crates/chia-consensus/src/gen/run_block_generator.rs index b7f99b993..af767294f 100644 --- a/crates/chia-consensus/src/gen/run_block_generator.rs +++ b/crates/chia-consensus/src/gen/run_block_generator.rs @@ -216,7 +216,7 @@ where return Err(ValidationErr(all_spends, ErrorCode::GeneratorRuntimeError)); } - validate_conditions(a, &ret, state, a.nil(), flags)?; + validate_conditions(a, &ret, &state, a.nil(), flags)?; ret.cost = max_cost - cost_left; Ok(ret) diff --git a/crates/chia-consensus/src/spendbundle_conditions.rs b/crates/chia-consensus/src/spendbundle_conditions.rs index 629fa909d..c033ce5ba 100644 --- a/crates/chia-consensus/src/spendbundle_conditions.rs +++ b/crates/chia-consensus/src/spendbundle_conditions.rs @@ -66,7 +66,7 @@ pub fn get_conditions_from_spendbundle( )?; } - validate_conditions(a, &ret, state, a.nil(), flags)?; + validate_conditions(a, &ret, &state, a.nil(), flags)?; assert!(max_cost >= cost_left); ret.cost = max_cost - cost_left; Ok(ret) diff --git a/crates/chia-consensus/src/spendbundle_validation.rs b/crates/chia-consensus/src/spendbundle_validation.rs index ef670fe0f..19b8aaae9 100644 --- a/crates/chia-consensus/src/spendbundle_validation.rs +++ b/crates/chia-consensus/src/spendbundle_validation.rs @@ -122,7 +122,7 @@ pub fn get_flags_for_height_and_constants(height: u32, constants: &ConsensusCons mod tests { use super::*; use crate::consensus_constants::TEST_CONSTANTS; - use crate::gen::conditions::u64_to_bytes; + use crate::gen::make_aggsig_final_message::u64_to_bytes; use chia_bls::{sign, G2Element, SecretKey, Signature}; use chia_protocol::{Bytes, Bytes32}; use chia_protocol::{Coin, CoinSpend, Program};