Skip to content

Commit

Permalink
pass ParseState by reference (instead of move) into validate_conditio…
Browse files Browse the repository at this point in the history
…ns(). Remove redundant u64_to_bytes() function. Improve documentation of condition flags
  • Loading branch information
arvidn committed Sep 27, 2024
1 parent c6cd98f commit aa44204
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 52 deletions.
72 changes: 31 additions & 41 deletions crates/chia-consensus/src/gen/conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1260,7 +1260,7 @@ pub fn parse_spends<V: SpendVisitor>(
)?;
}

validate_conditions(a, &ret, state, spends, flags)?;
validate_conditions(a, &ret, &state, spends, flags)?;
ret.cost = max_cost - cost_left;

Ok(ret)
Expand All @@ -1269,7 +1269,7 @@ pub fn parse_spends<V: SpendVisitor>(
pub fn validate_conditions(
a: &Allocator,
ret: &SpendBundleConditions,
state: ParseState,
state: &ParseState,
spends: NodePtr,
_flags: u32,
) -> Result<(), ValidationErr> {
Expand Down Expand Up @@ -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,
));
}
Expand All @@ -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,
));
}
Expand All @@ -1345,41 +1345,41 @@ pub fn validate_conditions(
if !state.assert_coin.is_empty() {
let mut announcements = HashSet::<Bytes32>::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,
));
}
Expand All @@ -1388,18 +1388,18 @@ pub fn validate_conditions(
if !state.assert_puzzle.is_empty() {
let mut announcements = HashSet::<Bytes32>::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,
));
}
Expand Down Expand Up @@ -1434,19 +1434,6 @@ pub fn validate_conditions(
Ok(())
}

#[cfg(test)]
pub(crate) fn u64_to_bytes(n: u64) -> Vec<u8> {
let mut buf = Vec::<u8>::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)]
Expand Down Expand Up @@ -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<u8> {
let mut ctx = Sha256::new();
Expand Down
9 changes: 6 additions & 3 deletions crates/chia-consensus/src/gen/flags.rs
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion crates/chia-consensus/src/gen/get_puzzle_and_solution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 clvm_traits::FromClvm;
Expand Down
7 changes: 3 additions & 4 deletions crates/chia-consensus/src/gen/make_aggsig_final_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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<u8> {
let amount_bytes: [u8; 8] = val.to_be_bytes();
if val >= 0x8000_0000_0000_0000_u64 {
let mut ret = Vec::<u8>::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,
Expand All @@ -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()
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/chia-consensus/src/gen/run_block_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion crates/chia-consensus/src/spendbundle_conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion crates/chia-consensus/src/spendbundle_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down

0 comments on commit aa44204

Please sign in to comment.