|
6 | 6 | from typing import Callable, Dict, List, Optional, Tuple |
7 | 7 |
|
8 | 8 | import pytest |
9 | | -from chia_rs import G1Element, G2Element |
| 9 | +from chia_rs import G1Element, G2Element, get_flags_for_height_and_constants |
10 | 10 | from clvm.casts import int_to_bytes |
11 | 11 | from clvm_tools import binutils |
| 12 | +from clvm_tools.binutils import assemble |
12 | 13 |
|
13 | 14 | from chia._tests.blockchain.blockchain_test_utils import _validate_and_add_block |
14 | 15 | from chia._tests.connection_utils import add_dummy_connection, connect_and_get_peer |
|
27 | 28 | from chia._tests.util.time_out_assert import time_out_assert |
28 | 29 | from chia.consensus.condition_costs import ConditionCost |
29 | 30 | from chia.consensus.cost_calculator import NPCResult |
| 31 | +from chia.consensus.default_constants import DEFAULT_CONSTANTS |
30 | 32 | from chia.full_node.bitcoin_fee_estimator import create_bitcoin_fee_estimator |
31 | 33 | from chia.full_node.fee_estimation import EmptyMempoolInfo, MempoolInfo |
32 | 34 | from chia.full_node.full_node_api import FullNodeAPI |
@@ -107,7 +109,7 @@ def make_item( |
107 | 109 | return MempoolItem( |
108 | 110 | SpendBundle([], G2Element()), |
109 | 111 | fee, |
110 | | - SpendBundleConditions([], 0, 0, 0, None, None, [], cost, 0, 0), |
| 112 | + SpendBundleConditions([], 0, 0, 0, None, None, [], cost, 0, 0, False), |
111 | 113 | spend_bundle_name, |
112 | 114 | uint32(0), |
113 | 115 | assert_height, |
@@ -3178,3 +3180,79 @@ def test_get_puzzle_and_solution_for_coin_failure() -> None: |
3178 | 3180 | ValueError, match=f"Failed to get puzzle and solution for coin {TEST_COIN}, error: \\('coin not found', '80'\\)" |
3179 | 3181 | ): |
3180 | 3182 | get_puzzle_and_solution_for_coin(BlockGenerator(SerializedProgram.to(None), []), TEST_COIN, 0, test_constants) |
| 3183 | + |
| 3184 | + |
| 3185 | +# TODO: import this from chia_rs once we bump the version we depend on |
| 3186 | +ENABLE_KECCAK = 0x200 |
| 3187 | +ENABLE_KECCAK_OPS_OUTSIDE_GUARD = 0x100 |
| 3188 | + |
| 3189 | + |
| 3190 | +def test_flags_for_height() -> None: |
| 3191 | + |
| 3192 | + # the keccak operator is supposed to be enabled at soft-fork 6 height |
| 3193 | + flags = get_flags_for_height_and_constants(DEFAULT_CONSTANTS.SOFT_FORK6_HEIGHT, DEFAULT_CONSTANTS) |
| 3194 | + print(f"{flags:x}") |
| 3195 | + assert (flags & ENABLE_KECCAK) != 0 |
| 3196 | + |
| 3197 | + flags = get_flags_for_height_and_constants(DEFAULT_CONSTANTS.SOFT_FORK6_HEIGHT - 1, DEFAULT_CONSTANTS) |
| 3198 | + print(f"{flags:x}") |
| 3199 | + assert (flags & ENABLE_KECCAK) == 0 |
| 3200 | + |
| 3201 | + |
| 3202 | +def test_keccak() -> None: |
| 3203 | + |
| 3204 | + # the keccak operator is 62. The assemble() function doesn't support it |
| 3205 | + # (yet) |
| 3206 | + |
| 3207 | + # keccak256 is available when the softfork has activated |
| 3208 | + keccak_prg = Program.to( |
| 3209 | + assemble( |
| 3210 | + "(softfork (q . 1134) (q . 1) (q a (i " |
| 3211 | + "(= " |
| 3212 | + '(62 (q . "foobar"))' |
| 3213 | + "(q . 0x38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e))" |
| 3214 | + "(q . 0) (q x)) (q . ())) (q . ()))" |
| 3215 | + ) |
| 3216 | + ) |
| 3217 | + |
| 3218 | + cost, ret = keccak_prg.run_with_flags(1215, ENABLE_KECCAK, []) |
| 3219 | + assert cost == 1215 |
| 3220 | + assert ret.atom == b"" |
| 3221 | + |
| 3222 | + # keccak is ignored when the softfork has not activated |
| 3223 | + cost, ret = keccak_prg.run_with_flags(1215, 0, []) |
| 3224 | + assert cost == 1215 |
| 3225 | + assert ret.atom == b"" |
| 3226 | + |
| 3227 | + # make sure keccak is actually executed, by comparing with the wrong output |
| 3228 | + keccak_prg = Program.to( |
| 3229 | + assemble( |
| 3230 | + "(softfork (q . 1134) (q . 1) (q a (i " |
| 3231 | + '(= (62 (q . "foobar")) ' |
| 3232 | + "(q . 0x58d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e))" |
| 3233 | + "(q . 0) (q x)) (q . ())) (q . ()))" |
| 3234 | + ) |
| 3235 | + ) |
| 3236 | + with pytest.raises(ValueError, match="clvm raise"): |
| 3237 | + keccak_prg.run_with_flags(1215, ENABLE_KECCAK, []) |
| 3238 | + |
| 3239 | + # keccak is ignored when the softfork has not activated |
| 3240 | + cost, ret = keccak_prg.run_with_flags(1215, 0, []) |
| 3241 | + assert cost == 1215 |
| 3242 | + assert ret.atom == b"" |
| 3243 | + |
| 3244 | + # === HARD FORK === |
| 3245 | + # new operators *outside* the softfork guard |
| 3246 | + # keccak256 is available outside the guard with the appropriate flag |
| 3247 | + keccak_prg = Program.to( |
| 3248 | + assemble( |
| 3249 | + "(a (i (= " |
| 3250 | + '(62 (q . "foobar")) ' |
| 3251 | + "(q . 0x38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e)) " |
| 3252 | + "(q . 0) (q x)) (q . ()))" |
| 3253 | + ) |
| 3254 | + ) |
| 3255 | + |
| 3256 | + cost, ret = keccak_prg.run_with_flags(994, ENABLE_KECCAK | ENABLE_KECCAK_OPS_OUTSIDE_GUARD, []) |
| 3257 | + assert cost == 994 |
| 3258 | + assert ret.atom == b"" |
0 commit comments