Skip to content

Commit

Permalink
enable message conditions unconditionally, and remove the flag contro…
Browse files Browse the repository at this point in the history
…lling it. Soft-fork 4 has activated.
  • Loading branch information
arvidn committed Aug 6, 2024
1 parent 5c68492 commit 1c29b5d
Show file tree
Hide file tree
Showing 11 changed files with 89 additions and 154 deletions.
4 changes: 2 additions & 2 deletions crates/chia-consensus/fuzz/fuzz_targets/parse-cond-args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use chia_consensus::gen::conditions::parse_args;
use clvmr::allocator::Allocator;
use fuzzing_utils::{make_list, BitCursor};

use chia_consensus::gen::flags::{ENABLE_MESSAGE_CONDITIONS, STRICT_ARGS_COUNT};
use chia_consensus::gen::flags::STRICT_ARGS_COUNT;

use chia_consensus::gen::opcodes::{
AGG_SIG_AMOUNT, AGG_SIG_ME, AGG_SIG_PARENT, AGG_SIG_PARENT_AMOUNT, AGG_SIG_PARENT_PUZZLE,
Expand All @@ -20,7 +20,7 @@ fuzz_target!(|data: &[u8]| {
let mut a = Allocator::new();
let input = make_list(&mut a, &mut BitCursor::new(data));

for flags in &[0, STRICT_ARGS_COUNT, ENABLE_MESSAGE_CONDITIONS] {
for flags in &[0, STRICT_ARGS_COUNT] {
for op in &[
AGG_SIG_ME,
AGG_SIG_UNSAFE,
Expand Down
9 changes: 2 additions & 7 deletions crates/chia-consensus/fuzz/fuzz_targets/parse-conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use fuzzing_utils::{make_list, BitCursor};
use std::collections::HashSet;
use std::sync::Arc;

use chia_consensus::gen::flags::{ENABLE_MESSAGE_CONDITIONS, NO_UNKNOWN_CONDS, STRICT_ARGS_COUNT};
use chia_consensus::gen::flags::{NO_UNKNOWN_CONDS, STRICT_ARGS_COUNT};

fuzz_target!(|data: &[u8]| {
let mut a = Allocator::new();
Expand All @@ -40,12 +40,7 @@ fuzz_target!(|data: &[u8]| {

let mut state = ParseState::default();

for flags in &[
0,
STRICT_ARGS_COUNT,
NO_UNKNOWN_CONDS,
ENABLE_MESSAGE_CONDITIONS,
] {
for flags in &[0, STRICT_ARGS_COUNT, NO_UNKNOWN_CONDS] {
let mut coin_spend = Spend {
parent_id,
coin_amount: amount,
Expand Down
9 changes: 2 additions & 7 deletions crates/chia-consensus/fuzz/fuzz_targets/parse-spends.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,14 @@ use clvmr::{Allocator, NodePtr};
use fuzzing_utils::{make_list, BitCursor};

use chia_consensus::consensus_constants::TEST_CONSTANTS;
use chia_consensus::gen::flags::{ENABLE_MESSAGE_CONDITIONS, NO_UNKNOWN_CONDS, STRICT_ARGS_COUNT};
use chia_consensus::gen::flags::{NO_UNKNOWN_CONDS, STRICT_ARGS_COUNT};

fuzz_target!(|data: &[u8]| {
let mut a = Allocator::new();
let input = make_list(&mut a, &mut BitCursor::new(data));
// spends is a list of spends
let input = a.new_pair(input, NodePtr::NIL).unwrap();
for flags in &[
0,
STRICT_ARGS_COUNT,
NO_UNKNOWN_CONDS,
ENABLE_MESSAGE_CONDITIONS,
] {
for flags in &[0, STRICT_ARGS_COUNT, NO_UNKNOWN_CONDS] {
let _ret =
parse_spends::<MempoolVisitor>(&a, input, 33_000_000_000, *flags, &TEST_CONSTANTS);
}
Expand Down
141 changes: 67 additions & 74 deletions crates/chia-consensus/src/gen/conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1722,9 +1722,6 @@ fn cond_test_cb(
#[cfg(test)]
use crate::gen::flags::MEMPOOL_MODE;

#[cfg(test)]
use crate::gen::flags::ENABLE_MESSAGE_CONDITIONS;

#[cfg(test)]
fn cond_test(input: &str) -> Result<(Allocator, SpendBundleConditions), ValidationErr> {
// by default, run all tests in strict mempool mode
Expand Down Expand Up @@ -1931,7 +1928,7 @@ fn test_message_strict_args_count(
&format!(
"((({{h1}} ({{h2}} (123 (((66 ({mode} ({msg} {arg} {extra1} ) ((67 ({mode} ({msg} {extra2} ) ))))"
),
flags | ENABLE_MESSAGE_CONDITIONS,
flags,
);
if flags == 0 {
ret.unwrap();
Expand Down Expand Up @@ -4676,29 +4673,28 @@ enum Ex {
#[case("(67 (0x12 ({msg1} ({coin12} )", Ex::Fail)]
#[case("(66 (0x12 ({msg1} ({coin12} )", Ex::Fail)]
fn test_message_conditions_single_spend(#[case] test_case: &str, #[case] expect: Ex) {
for flags in &[ENABLE_MESSAGE_CONDITIONS, MEMPOOL_MODE] {
let ret = cond_test_flag(&format!("((({{h1}} ({{h2}} (123 (({test_case}))))"), *flags);
let flags = MEMPOOL_MODE;
let ret = cond_test_flag(&format!("((({{h1}} ({{h2}} (123 (({test_case}))))"), flags);

let expect_pass = match expect {
Ex::Pass => true,
Ex::Fail => false,
};
let expect_pass = match expect {
Ex::Pass => true,
Ex::Fail => false,
};

if let Ok((a, conds)) = ret {
assert!(expect_pass);
assert_eq!(conds.cost, 0);
assert_eq!(conds.spends.len(), 1);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash).as_ref(), H2);
assert_eq!(spend.flags, 0);
} else if expect_pass {
panic!("failed: {:?}", ret.unwrap_err().1);
} else {
let actual_err = ret.unwrap_err().1;
println!("Error: {actual_err:?}");
assert_eq!(ErrorCode::MessageNotSentOrReceived, actual_err);
}
if let Ok((a, conds)) = ret {
assert!(expect_pass);
assert_eq!(conds.cost, 0);
assert_eq!(conds.spends.len(), 1);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash).as_ref(), H2);
assert_eq!(spend.flags, 0);
} else if expect_pass {
panic!("failed: {:?}", ret.unwrap_err().1);
} else {
let actual_err = ret.unwrap_err().1;
println!("Error: {actual_err:?}");
assert_eq!(ErrorCode::MessageNotSentOrReceived, actual_err);
}
}

Expand All @@ -4709,7 +4705,7 @@ fn test_message_conditions_single_spend(#[case] test_case: &str, #[case] expect:
fn test_limit_messages(#[case] count: i32, #[case] expect_err: Option<ErrorCode>) {
let r = cond_test_cb(
"((({h1} ({h1} (123 ({} )))",
ENABLE_MESSAGE_CONDITIONS,
0,
Some(Box::new(move |a: &mut Allocator| -> NodePtr {
let mut rest: NodePtr = a.nil();

Expand Down Expand Up @@ -4864,14 +4860,13 @@ fn test_limit_messages(#[case] count: i32, #[case] expect_err: Option<ErrorCode>
ErrorCode::CoinAmountNegative
)]
fn test_message_conditions_failures(#[case] test_case: &str, #[case] expect: ErrorCode) {
for flags in [ENABLE_MESSAGE_CONDITIONS, MEMPOOL_MODE] {
let ret = cond_test_flag(&format!("((({{h1}} ({{h2}} (123 (({test_case}))))"), flags);
let flags = MEMPOOL_MODE;
let ret = cond_test_flag(&format!("((({{h1}} ({{h2}} (123 (({test_case}))))"), flags);

let Err(ValidationErr(_, code)) = ret else {
panic!("expected failure: {expect:?}");
};
assert_eq!(code, expect);
}
let Err(ValidationErr(_, code)) = ret else {
panic!("expected failure: {expect:?}");
};
assert_eq!(code, expect);
}

#[cfg(test)]
Expand Down Expand Up @@ -5081,45 +5076,44 @@ fn test_message_conditions_two_spends(
#[case] coin2_case: &str,
#[case] expect: Ex,
) {
for flags in &[ENABLE_MESSAGE_CONDITIONS, MEMPOOL_MODE] {
let test = format!(
"(\
(({{h1}} ({{h2}} (123 (\
({coin1_case} \
))\
(({{h2}} ({{h1}} (123 (\
({coin2_case} \
))\
))"
);
let ret = cond_test_flag(&test, *flags);
let flags = MEMPOOL_MODE;
let test = format!(
"(\
(({{h1}} ({{h2}} (123 (\
({coin1_case} \
))\
(({{h2}} ({{h1}} (123 (\
({coin2_case} \
))\
))"
);
let ret = cond_test_flag(&test, flags);

let expect_pass = match expect {
Ex::Pass => true,
Ex::Fail => false,
};
let expect_pass = match expect {
Ex::Pass => true,
Ex::Fail => false,
};

if let Ok((a, conds)) = ret {
assert!(expect_pass);
assert_eq!(conds.cost, 0);
assert_eq!(conds.spends.len(), 2);

let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash).as_ref(), H2);
assert_eq!(spend.flags, 0);

let spend = &conds.spends[1];
assert_eq!(*spend.coin_id, test_coin_id(H2, H1, 123));
assert_eq!(a.atom(spend.puzzle_hash).as_ref(), H1);
assert_eq!(spend.flags, 0);
} else if expect_pass {
panic!("failed: {:?}", ret.unwrap_err().1);
} else {
let actual_err = ret.unwrap_err().1;
println!("Error: {actual_err:?}");
assert_eq!(ErrorCode::MessageNotSentOrReceived, actual_err);
}
if let Ok((a, conds)) = ret {
assert!(expect_pass);
assert_eq!(conds.cost, 0);
assert_eq!(conds.spends.len(), 2);

let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash).as_ref(), H2);
assert_eq!(spend.flags, 0);

let spend = &conds.spends[1];
assert_eq!(*spend.coin_id, test_coin_id(H2, H1, 123));
assert_eq!(a.atom(spend.puzzle_hash).as_ref(), H1);
assert_eq!(spend.flags, 0);
} else if expect_pass {
panic!("failed: {:?}", ret.unwrap_err().1);
} else {
let actual_err = ret.unwrap_err().1;
println!("Error: {actual_err:?}");
assert_eq!(ErrorCode::MessageNotSentOrReceived, actual_err);
}
}

Expand Down Expand Up @@ -5165,8 +5159,7 @@ fn test_all_message_conditions() {
))\
))"
);
let (a, conds) =
cond_test_flag(&test, ENABLE_MESSAGE_CONDITIONS).expect("condition expected to pass");
let (a, conds) = cond_test_flag(&test, 0).expect("condition expected to pass");

assert_eq!(conds.cost, 0);
assert_eq!(conds.spends.len(), 2);
Expand Down Expand Up @@ -5237,7 +5230,7 @@ fn test_message_eligible_for_ff() {
))"
);

let (_a, cond) = cond_test_flag(&test, ENABLE_MESSAGE_CONDITIONS).expect("cond_test");
let (_a, cond) = cond_test_flag(&test, 0).expect("cond_test");
assert!(cond.spends.len() == 2);
assert_eq!(
(cond.spends[0].flags & ELIGIBLE_FOR_FF) != 0,
Expand All @@ -5261,7 +5254,7 @@ fn test_message_eligible_for_ff() {
))"
);

let (_a, cond) = cond_test_flag(&test, ENABLE_MESSAGE_CONDITIONS).expect("cond_test");
let (_a, cond) = cond_test_flag(&test, 0).expect("cond_test");
assert!(cond.spends.len() == 2);
assert_eq!(
(cond.spends[0].flags & ELIGIBLE_FOR_FF) != 0,
Expand Down
4 changes: 0 additions & 4 deletions crates/chia-consensus/src/gen/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ pub const ALLOW_BACKREFS: u32 = 0x0200_0000;
// what features are detected of the spends
pub const ANALYZE_SPENDS: u32 = 0x0400_0000;

// This enables support for the new SEND_MESSAGE and RECEIVE_MESSAGE conditions
pub const ENABLE_MESSAGE_CONDITIONS: u32 = 0x0800_0000;

// When this flag is set, we reject AGG_SIG_* conditions whose public key is the
// infinity G1 point. Such public keys are mathematically valid, but do not
// provide any security guarantees. Chia has historically allowed them. Enabling
Expand All @@ -30,5 +27,4 @@ pub const MEMPOOL_MODE: u32 = CLVM_MEMPOOL_MODE
| NO_UNKNOWN_CONDS
| STRICT_ARGS_COUNT
| ANALYZE_SPENDS
| ENABLE_MESSAGE_CONDITIONS
| DISALLOW_INFINITY_G1;
56 changes: 8 additions & 48 deletions crates/chia-consensus/src/gen/opcodes.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::gen::flags::ENABLE_MESSAGE_CONDITIONS;
use clvmr::allocator::{Allocator, NodePtr, SExp};
use clvmr::cost::Cost;

Expand Down Expand Up @@ -105,7 +104,7 @@ pub fn compute_unknown_condition_cost(op: ConditionOpcode) -> Cost {
}
}

pub fn parse_opcode(a: &Allocator, op: NodePtr, flags: u32) -> Option<ConditionOpcode> {
pub fn parse_opcode(a: &Allocator, op: NodePtr, _flags: u32) -> Option<ConditionOpcode> {
let buf = match a.sexp(op) {
SExp::Atom => a.atom(op),
SExp::Pair(..) => return None,
Expand Down Expand Up @@ -154,16 +153,10 @@ pub fn parse_opcode(a: &Allocator, op: NodePtr, flags: u32) -> Option<ConditionO
| AGG_SIG_AMOUNT
| AGG_SIG_PUZZLE_AMOUNT
| AGG_SIG_PARENT_AMOUNT
| AGG_SIG_PARENT_PUZZLE => Some(b0),
_ => {
if (flags & ENABLE_MESSAGE_CONDITIONS) != 0
&& [SEND_MESSAGE, RECEIVE_MESSAGE].contains(&b0)
{
Some(b0)
} else {
None
}
}
| AGG_SIG_PARENT_PUZZLE
| SEND_MESSAGE
| RECEIVE_MESSAGE => Some(b0),
_ => None,
}
} else {
None
Expand Down Expand Up @@ -215,10 +208,7 @@ use rstest::rstest;
fn test_parse_opcode(#[case] input: &[u8], #[case] expected: Option<ConditionOpcode>) {
let mut a = Allocator::new();
assert_eq!(opcode_tester(&mut a, input, 0), expected);
assert_eq!(
opcode_tester(&mut a, input, ENABLE_MESSAGE_CONDITIONS),
expected
);
assert_eq!(opcode_tester(&mut a, input, 0), expected);
}

#[cfg(test)]
Expand All @@ -236,43 +226,13 @@ fn test_parse_opcode(#[case] input: &[u8], #[case] expected: Option<ConditionOpc
#[case(&[AGG_SIG_PARENT_PUZZLE as u8], Some(AGG_SIG_PARENT_PUZZLE))]
#[case(&[ASSERT_EPHEMERAL as u8], Some(ASSERT_EPHEMERAL))]
#[case(&[ASSERT_BEFORE_SECONDS_RELATIVE as u8], Some(ASSERT_BEFORE_SECONDS_RELATIVE))]
#[case(&[SEND_MESSAGE as u8], None)]
#[case(&[RECEIVE_MESSAGE as u8], None)]
#[case(&[SEND_MESSAGE as u8], Some(SEND_MESSAGE))]
#[case(&[RECEIVE_MESSAGE as u8], Some(RECEIVE_MESSAGE))]
fn test_parse_opcode_softfork(#[case] input: &[u8], #[case] expected: Option<ConditionOpcode>) {
let mut a = Allocator::new();
assert_eq!(opcode_tester(&mut a, input, 0), expected);
}

#[cfg(test)]
#[rstest]
#[case(&[AGG_SIG_UNSAFE as u8], Some(AGG_SIG_UNSAFE), Some(AGG_SIG_UNSAFE))]
#[case(&[AGG_SIG_ME as u8], Some(AGG_SIG_ME), Some(AGG_SIG_ME))]
#[case(&[CREATE_COIN as u8], Some(CREATE_COIN), Some(CREATE_COIN))]
// the SOFTOFORK and new AGG_SIG_* condition is only recognized when the flag is set
#[case(&[SOFTFORK as u8], Some(SOFTFORK), Some(SOFTFORK))]
#[case(&[AGG_SIG_PARENT as u8], Some(AGG_SIG_PARENT), Some(AGG_SIG_PARENT))]
#[case(&[AGG_SIG_PUZZLE as u8], Some(AGG_SIG_PUZZLE), Some(AGG_SIG_PUZZLE))]
#[case(&[AGG_SIG_AMOUNT as u8], Some(AGG_SIG_AMOUNT), Some(AGG_SIG_AMOUNT))]
#[case(&[AGG_SIG_PUZZLE_AMOUNT as u8], Some(AGG_SIG_PUZZLE_AMOUNT), Some(AGG_SIG_PUZZLE_AMOUNT))]
#[case(&[AGG_SIG_PARENT_AMOUNT as u8], Some(AGG_SIG_PARENT_AMOUNT), Some(AGG_SIG_PARENT_AMOUNT))]
#[case(&[AGG_SIG_PARENT_PUZZLE as u8], Some(AGG_SIG_PARENT_PUZZLE), Some(AGG_SIG_PARENT_PUZZLE))]
#[case(&[ASSERT_EPHEMERAL as u8], Some(ASSERT_EPHEMERAL), Some(ASSERT_EPHEMERAL))]
#[case(&[ASSERT_BEFORE_SECONDS_RELATIVE as u8], Some(ASSERT_BEFORE_SECONDS_RELATIVE), Some(ASSERT_BEFORE_SECONDS_RELATIVE))]
#[case(&[SEND_MESSAGE as u8], None, Some(SEND_MESSAGE))]
#[case(&[RECEIVE_MESSAGE as u8], None, Some(RECEIVE_MESSAGE))]
fn test_parse_opcode_message(
#[case] input: &[u8],
#[case] expected: Option<ConditionOpcode>,
#[case] expected2: Option<ConditionOpcode>,
) {
let mut a = Allocator::new();
assert_eq!(opcode_tester(&mut a, input, 0), expected);
assert_eq!(
opcode_tester(&mut a, input, ENABLE_MESSAGE_CONDITIONS),
expected2
);
}

#[test]
fn test_parse_invalid_opcode() {
// a pair is never a valid condition
Expand Down
4 changes: 2 additions & 2 deletions crates/chia-consensus/src/gen/test_generators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::conditions::{MempoolVisitor, NewCoin, Spend, SpendBundleConditions};
use super::run_block_generator::{run_block_generator, run_block_generator2};
use crate::allocator::make_allocator;
use crate::consensus_constants::TEST_CONSTANTS;
use crate::gen::flags::{ALLOW_BACKREFS, ENABLE_MESSAGE_CONDITIONS, MEMPOOL_MODE};
use crate::gen::flags::{ALLOW_BACKREFS, MEMPOOL_MODE};
use chia_protocol::{Bytes, Bytes48};
use clvmr::allocator::NodePtr;
use clvmr::Allocator;
Expand Down Expand Up @@ -227,7 +227,7 @@ fn run_generator(#[case] name: &str) {
block_refs.push(hex::decode(env_hex).expect("hex decode env-file"));
}

const DEFAULT_FLAGS: u32 = ALLOW_BACKREFS | ENABLE_MESSAGE_CONDITIONS;
const DEFAULT_FLAGS: u32 = ALLOW_BACKREFS;
for (flags, expected) in zip(&[DEFAULT_FLAGS, DEFAULT_FLAGS | MEMPOOL_MODE], expected) {
println!("flags: {flags:x}");
let mut a = make_allocator(*flags);
Expand Down
Loading

0 comments on commit 1c29b5d

Please sign in to comment.