Skip to content
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

extend SpendBundleConditions with the cost broken out #866

Merged
merged 1 commit into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions crates/chia-consensus/fuzz/fuzz_targets/run-generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ fuzz_target!(|data: &[u8]| {
}
(Ok(a), Ok(b)) => {
assert!(a.cost >= b.cost);
assert!(a.execution_cost > b.execution_cost);
assert_eq!(a.condition_cost, b.condition_cost);
assert_eq!(a.reserve_fee, b.reserve_fee);
assert_eq!(a.removal_amount, b.removal_amount);
assert_eq!(a.addition_amount, b.addition_amount);
Expand Down
9 changes: 9 additions & 0 deletions crates/chia-consensus/src/gen/conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,12 @@ pub struct SpendBundleConditions {
// the total cost)
pub cost: u64,

// the cost of executing the Chialisp
pub execution_cost: u64,

// the cost of the conditions
pub condition_cost: u64,

// the sum of all values of all spent coins
pub removal_amount: u128,

Expand Down Expand Up @@ -921,6 +927,7 @@ pub fn parse_conditions<V: SpendVisitor>(
return Err(ValidationErr(c, ErrorCode::CostExceeded));
}
*max_cost -= CREATE_COIN_COST;
ret.condition_cost += CREATE_COIN_COST;
}
AGG_SIG_UNSAFE
| AGG_SIG_ME
Expand All @@ -934,6 +941,7 @@ pub fn parse_conditions<V: SpendVisitor>(
return Err(ValidationErr(c, ErrorCode::CostExceeded));
}
*max_cost -= AGG_SIG_COST;
ret.condition_cost += AGG_SIG_COST;
}
_ => (),
}
Expand Down Expand Up @@ -1212,6 +1220,7 @@ pub fn parse_conditions<V: SpendVisitor>(
return Err(ValidationErr(c, ErrorCode::CostExceeded));
}
*max_cost -= cost;
ret.condition_cost += cost;
}
Condition::SendMessage(src_mode, dst, msg) => {
decrement(&mut announce_countdown, msg)?;
Expand Down
4 changes: 4 additions & 0 deletions crates/chia-consensus/src/gen/owned_conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ pub struct OwnedSpendBundleConditions {
// set if the aggregate signature of the block/spend bundle was
// successfully validated
pub validated_signature: bool,
pub execution_cost: u64,
pub condition_cost: u64,
}

impl OwnedSpendConditions {
Expand Down Expand Up @@ -144,6 +146,8 @@ impl OwnedSpendBundleConditions {
removal_amount: sb.removal_amount,
addition_amount: sb.addition_amount,
validated_signature: sb.validated_signature,
execution_cost: sb.execution_cost,
condition_cost: sb.condition_cost,
}
}
}
Expand Down
7 changes: 6 additions & 1 deletion crates/chia-consensus/src/gen/run_block_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ where
constants,
)?;
result.cost += max_cost - cost_left;
result.execution_cost = clvm_cost;
Ok(result)
}

Expand Down Expand Up @@ -189,13 +190,16 @@ where
let Reduction(clvm_cost, mut all_spends) = run_program(a, &dialect, program, args, cost_left)?;

subtract_cost(a, &mut cost_left, clvm_cost)?;

let mut ret = SpendBundleConditions::default();

all_spends = first(a, all_spends)?;
ret.execution_cost += clvm_cost;

// at this point all_spends is a list of:
// (parent-coin-id puzzle-reveal amount solution . extra)
// where extra may be nil, or additional extension data

let mut ret = SpendBundleConditions::default();
let mut state = ParseState::default();
let mut cache = HashMap::<NodePtr, TreeHash>::new();

Expand All @@ -209,6 +213,7 @@ where
run_program(a, &dialect, puzzle, solution, cost_left)?;

subtract_cost(a, &mut cost_left, clvm_cost)?;
ret.execution_cost += clvm_cost;

let buf = tree_hash_cached(a, puzzle, &backrefs, &mut cache);
let puzzle_hash = a.new_atom(&buf)?;
Expand Down
16 changes: 15 additions & 1 deletion crates/chia-consensus/src/spendbundle_conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ pub fn run_spendbundle(
let amount = a.new_number(coin_spend.coin.amount.into())?;
let Reduction(clvm_cost, conditions) = run_program(a, &dialect, puz, sol, cost_left)?;

ret.execution_cost += clvm_cost;
subtract_cost(a, &mut cost_left, clvm_cost)?;

let buf = tree_hash(a, puz);
Expand Down Expand Up @@ -169,6 +170,12 @@ mod tests {
conditions.cost,
block_conds.cost - QUOTE_EXECUTION_COST - QUOTE_BYTES_COST
);

assert_eq!(
conditions.execution_cost,
block_conds.execution_cost - QUOTE_EXECUTION_COST
);
assert_eq!(conditions.condition_cost, block_conds.condition_cost);
}

#[rstest]
Expand Down Expand Up @@ -382,10 +389,17 @@ mod tests {
- QUOTE_BYTES;
let bundle_byte_cost =
generator_length_without_quote as u64 * TEST_CONSTANTS.cost_per_byte;
println!("block_cost: {block_cost} bytes: {block_byte_cost}");
println!(" block_cost: {block_cost} bytes: {block_byte_cost}");
println!("bundle_cost: {} bytes: {bundle_byte_cost}", conditions.cost);
println!("execution_cost: {}", conditions.execution_cost);
println!("condition_cost: {}", conditions.condition_cost);
assert!(conditions.cost - bundle_byte_cost <= block_cost - block_byte_cost);
assert!(conditions.cost > 0);
assert!(conditions.execution_cost > 0);
assert_eq!(
conditions.cost,
conditions.condition_cost + conditions.execution_cost + bundle_byte_cost
);
// update the cost we print here, just to be compatible with
// the test cases we have. We've already ensured the cost is
// lower
Expand Down
19 changes: 17 additions & 2 deletions tests/test_run_block_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,16 @@ def test_run_block_generator_cost() -> None:
# longer pay the cost of the generator ROM
hard_fork_consensus_cost = 596498808

# the generator always produce the same set of conditions, and their cost
# is the same regardless of pre- or post- hard fork.
condition_cost = 122400000

generator = bytes.fromhex(
open("generator-tests/block-834768.txt", "r").read().split("\n")[0]
)

byte_cost = len(generator) * 12000

err, conds = run_block_generator(
generator,
[],
Expand All @@ -29,6 +36,9 @@ def test_run_block_generator_cost() -> None:
)
assert err is None
assert conds is not None
assert conds.cost == original_consensus_cost
assert conds.execution_cost + condition_cost + byte_cost == original_consensus_cost
assert conds.condition_cost == condition_cost

err2, conds2 = run_block_generator2(
generator,
Expand All @@ -41,6 +51,11 @@ def test_run_block_generator_cost() -> None:
)
assert err2 is None
assert conds2 is not None
assert conds2.cost == hard_fork_consensus_cost
assert conds2.condition_cost == condition_cost
assert (
conds2.execution_cost + condition_cost + byte_cost == hard_fork_consensus_cost
)

output1 = print_spend_bundle_conditions(conds)
output2 = print_spend_bundle_conditions(conds2)
Expand Down Expand Up @@ -81,7 +96,7 @@ def test_run_block_generator_cost() -> None:
err, conds = run_block_generator(
generator,
[],
len(generator) * 12000 - 1,
byte_cost - 1,
DONT_VALIDATE_SIGNATURE,
G2Element(),
None,
Expand All @@ -95,7 +110,7 @@ def test_run_block_generator_cost() -> None:
err, conds = run_block_generator2(
generator,
[],
len(generator) * 12000 - 1,
byte_cost - 1,
DONT_VALIDATE_SIGNATURE,
G2Element(),
None,
Expand Down
74 changes: 69 additions & 5 deletions tests/test_streamable.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,34 @@ def test_hash_spend() -> None:
def test_hash_spend_bundle_conditions() -> None:

a1 = SpendBundleConditions(
[], 1000, 1337, 42, None, None, [(pk, b"msg")], 12345678, 123, 456, False
[],
1000,
1337,
42,
None,
None,
[(pk, b"msg")],
12345678,
123,
456,
False,
4321,
8765,
)
a2 = SpendBundleConditions(
[], 1001, 1337, 42, None, None, [(pk, b"msg")], 12345678, 123, 456, False
[],
1001,
1337,
42,
None,
None,
[(pk, b"msg")],
12345678,
123,
456,
False,
4321,
8765,
)
b = hash(a1)
c = hash(a2)
Expand Down Expand Up @@ -391,7 +415,19 @@ def test_missing_field() -> None:
def test_json_spend_bundle_conditions() -> None:

a = SpendBundleConditions(
[], 1000, 1337, 42, None, None, [(pk, b"msg")], 12345678, 123, 456, False
[],
1000,
1337,
42,
None,
None,
[(pk, b"msg")],
12345678,
123,
456,
False,
4321,
8765,
)

assert a.to_json_dict() == {
Expand All @@ -406,13 +442,27 @@ def test_json_spend_bundle_conditions() -> None:
"removal_amount": 123,
"addition_amount": 456,
"validated_signature": False,
"execution_cost": 4321,
"condition_cost": 8765,
}


def test_from_json_spend_bundle_conditions() -> None:

a = SpendBundleConditions(
[], 1000, 1337, 42, None, None, [(pk, b"msg")], 12345678, 123, 456, False
[],
1000,
1337,
42,
None,
None,
[(pk, b"msg")],
12345678,
123,
456,
False,
4321,
8765,
)
b = SpendBundleConditions.from_json_dict(
{
Expand All @@ -427,6 +477,8 @@ def test_from_json_spend_bundle_conditions() -> None:
"removal_amount": 123,
"addition_amount": 456,
"validated_signature": False,
"execution_cost": 4321,
"condition_cost": 8765,
}
)
assert a == b
Expand Down Expand Up @@ -468,7 +520,19 @@ def test_copy_spend() -> None:
def test_copy_spend_bundle_conditions() -> None:

a = SpendBundleConditions(
[], 1000, 1337, 42, None, None, [(pk, b"msg")], 12345678, 123, 456, False
[],
1000,
1337,
42,
None,
None,
[(pk, b"msg")],
12345678,
123,
456,
False,
4321,
8765,
)
b = copy.copy(a)

Expand Down
2 changes: 2 additions & 0 deletions wheel/generate_type_stubs.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,8 @@ def __init__(
"removal_amount: int",
"addition_amount: int",
"validated_signature: bool",
"execution_cost: int",
"condition_cost: int",
],
)

Expand Down
10 changes: 8 additions & 2 deletions wheel/python/chia_rs/chia_rs.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,8 @@ class SpendBundleConditions:
removal_amount: int
addition_amount: int
validated_signature: bool
execution_cost: int
condition_cost: int
def __init__(
self,
spends: Sequence[SpendConditions],
Expand All @@ -362,7 +364,9 @@ class SpendBundleConditions:
cost: int,
removal_amount: int,
addition_amount: int,
validated_signature: bool
validated_signature: bool,
execution_cost: int,
condition_cost: int
) -> None: ...
def __hash__(self) -> int: ...
def __repr__(self) -> str: ...
Expand Down Expand Up @@ -391,7 +395,9 @@ class SpendBundleConditions:
cost: Union[ int, _Unspec] = _Unspec(),
removal_amount: Union[ int, _Unspec] = _Unspec(),
addition_amount: Union[ int, _Unspec] = _Unspec(),
validated_signature: Union[ bool, _Unspec] = _Unspec()) -> SpendBundleConditions: ...
validated_signature: Union[ bool, _Unspec] = _Unspec(),
execution_cost: Union[ int, _Unspec] = _Unspec(),
condition_cost: Union[ int, _Unspec] = _Unspec()) -> SpendBundleConditions: ...

@final
class BlockRecord:
Expand Down
Loading