mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2024-09-11 10:56:14 +03:00
Implement generator_for_single_coin() in python instead of clvm and apply quex' optimization to only computing the puzzle hash if the parent and amount matches (#13237)
This commit is contained in:
parent
18c40d6269
commit
163552b8d9
@ -382,11 +382,7 @@ class SimClient:
|
||||
coin_record = await self.service.mempool_manager.coin_store.get_coin_record( # type: ignore[assignment]
|
||||
coin_id,
|
||||
)
|
||||
error, puzzle, solution = get_puzzle_and_solution_for_coin(
|
||||
generator,
|
||||
coin_id,
|
||||
self.service.defaults.MAX_BLOCK_COST_CLVM,
|
||||
)
|
||||
error, puzzle, solution = get_puzzle_and_solution_for_coin(generator, coin_record.coin)
|
||||
if error:
|
||||
return None
|
||||
else:
|
||||
|
@ -1286,9 +1286,7 @@ class FullNodeAPI:
|
||||
|
||||
block_generator: Optional[BlockGenerator] = await self.full_node.blockchain.get_block_generator(block)
|
||||
assert block_generator is not None
|
||||
error, puzzle, solution = get_puzzle_and_solution_for_coin(
|
||||
block_generator, coin_name, self.full_node.constants.MAX_BLOCK_COST_CLVM
|
||||
)
|
||||
error, puzzle, solution = get_puzzle_and_solution_for_coin(block_generator, coin_record.coin)
|
||||
|
||||
if error is not None:
|
||||
return reject_msg
|
||||
|
@ -1,20 +1,25 @@
|
||||
import logging
|
||||
from typing import Dict, Optional
|
||||
from typing import Dict, Optional, Tuple
|
||||
from chia_rs import MEMPOOL_MODE, NO_NEG_DIV
|
||||
from chia.types.blockchain_format.coin import Coin
|
||||
|
||||
from chia.consensus.cost_calculator import NPCResult
|
||||
from chia.types.spend_bundle_conditions import SpendBundleConditions
|
||||
from chia.full_node.generator import create_generator_args, setup_generator_args
|
||||
from chia.full_node.generator import setup_generator_args
|
||||
from chia.types.coin_record import CoinRecord
|
||||
from chia.types.generator_types import BlockGenerator
|
||||
from chia.types.blockchain_format.sized_bytes import bytes32
|
||||
from chia.util.errors import Err
|
||||
from chia.util.ints import uint32, uint64, uint16
|
||||
from chia.wallet.puzzles.generator_loader import GENERATOR_FOR_SINGLE_COIN_MOD
|
||||
from chia.wallet.puzzles.rom_bootstrap_generator import get_generator
|
||||
from chia.types.blockchain_format.program import Program
|
||||
from chia.wallet.puzzles.load_clvm import load_serialized_clvm
|
||||
from chia.consensus.default_constants import DEFAULT_CONSTANTS
|
||||
|
||||
GENERATOR_MOD = get_generator()
|
||||
|
||||
DESERIALIZE_MOD = load_serialized_clvm("chialisp_deserialisation.clvm", package_or_requirement="chia.wallet.puzzles")
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -55,17 +60,26 @@ def get_name_puzzle_conditions(
|
||||
return NPCResult(uint16(Err.GENERATOR_RUNTIME_ERROR.value), None, uint64(0))
|
||||
|
||||
|
||||
def get_puzzle_and_solution_for_coin(generator: BlockGenerator, coin_name: bytes, max_cost: int):
|
||||
def get_puzzle_and_solution_for_coin(
|
||||
generator: BlockGenerator, coin: Coin
|
||||
) -> Tuple[Optional[Exception], Optional[Program], Optional[Program]]:
|
||||
try:
|
||||
block_program = generator.program
|
||||
block_program_args = create_generator_args(generator.generator_refs)
|
||||
args = [bytes(a) for a in generator.generator_refs]
|
||||
cost, result = generator.program.run_with_cost(DEFAULT_CONSTANTS.MAX_BLOCK_COST_CLVM, DESERIALIZE_MOD, args)
|
||||
|
||||
cost, result = GENERATOR_FOR_SINGLE_COIN_MOD.run_with_cost(
|
||||
max_cost, block_program, block_program_args, coin_name
|
||||
)
|
||||
puzzle = result.first()
|
||||
solution = result.rest().first()
|
||||
return None, puzzle, solution
|
||||
requested_parent = Program.to(coin.parent_coin_info)
|
||||
requested_amount = Program.to(coin.amount)
|
||||
|
||||
coin_spends = result.first()
|
||||
for spend in coin_spends.as_iter():
|
||||
parent, puzzle, amount, solution = spend.as_iter()
|
||||
if (
|
||||
parent == requested_parent
|
||||
and amount == requested_amount
|
||||
and Program.to(puzzle).get_tree_hash() == coin.puzzle_hash
|
||||
):
|
||||
return None, Program.to(puzzle), Program.to(solution)
|
||||
return ValueError(f"coin not found {coin.name().hex()}"), None, None
|
||||
except Exception as e:
|
||||
return e, None, None
|
||||
|
||||
|
@ -696,9 +696,7 @@ class FullNodeRpcApi:
|
||||
|
||||
block_generator: Optional[BlockGenerator] = await self.service.blockchain.get_block_generator(block)
|
||||
assert block_generator is not None
|
||||
error, puzzle, solution = get_puzzle_and_solution_for_coin(
|
||||
block_generator, coin_name, self.service.constants.MAX_BLOCK_COST_CLVM
|
||||
)
|
||||
error, puzzle, solution = get_puzzle_and_solution_for_coin(block_generator, coin_record.coin)
|
||||
if error is not None:
|
||||
raise ValueError(f"Error: {error}")
|
||||
|
||||
|
@ -1,35 +0,0 @@
|
||||
(mod (block_program (block_ref) coinname)
|
||||
|
||||
(defconstant local_deserialize_mod
|
||||
;; this monstrosity is the assembly output of `chialisp_deserialisation.clvm`
|
||||
;; it's pasted in here because the compiler doesn't yet support nested `mod`
|
||||
;; my apologies -- RK
|
||||
|
||||
(a (q 5 (a 62 (c 2 (c 5 ()))))
|
||||
(c (q ((-1 . 127) -33 . -65) ((a (i (= 11 (q . -128)) (q 4 () (c 5 ())) (q 2 (i (>s 11 24) (q 2 26 (c 2 (c (a (i (>s 11 28) (q 2 (i (>s 11 20) (q 8) (q 4 (concat (logand (q . 31) 11) (substr 5 () (q . 1))) (c (substr 5 (q . 1)) ()))) 1) (q 4 (logand (q . 63) 11) (c 5 ()))) 1) ()))) (q 4 11 (c 5 ()))) 1)) 1) 4 (substr 21 () 9) (c (substr 21 9) ())) (c (c 5 19) (c 43 ())) (a 22 (c 2 (c 9 (c (a 62 (c 2 (c 21 ()))) ())))) 2 (i (= (substr 5 () (q . 1)) 16) (q 2 46 (c 2 (c (a 62 (c 2 (c (substr 5 (q . 1)) ()))) ()))) (q 2 18 (c 2 (c (substr 5 (q . 1)) (c (substr 5 () (q . 1)) ()))))) 1)
|
||||
1))
|
||||
)
|
||||
|
||||
; takes a lisp tree and returns the hash of it
|
||||
(defun sha256tree1 (TREE)
|
||||
(if (l TREE)
|
||||
(sha256 2 (sha256tree1 (f TREE)) (sha256tree1 (r TREE)))
|
||||
(sha256 1 TREE)))
|
||||
|
||||
(defun check_coin_spend ((parent puzzle amount solution) coinname)
|
||||
(= (sha256 parent (sha256tree1 puzzle) amount) coinname)
|
||||
)
|
||||
|
||||
(defun check_for_coinname (coin_spends coinname)
|
||||
(if coin_spends
|
||||
(if (check_coin_spend (f coin_spends) coinname)
|
||||
(list (f (r (f coin_spends))) (f (r (r (r (f coin_spends))))))
|
||||
(check_for_coinname (r coin_spends) coinname)
|
||||
)
|
||||
(x)
|
||||
)
|
||||
)
|
||||
|
||||
; main
|
||||
(check_for_coinname (f (a block_program (list local_deserialize_mod block_ref))) coinname)
|
||||
)
|
@ -1 +0,0 @@
|
||||
ff02ffff01ff02ff0cffff04ff02ffff04ffff05ffff02ff05ffff04ff0affff04ff13ff8080808080ffff04ff17ff8080808080ffff04ffff01ffffff09ffff0bff09ffff02ff0effff04ff02ffff04ff15ff80808080ff2d80ff0b80ff02ffff03ff05ffff01ff02ffff03ffff02ff08ffff04ff02ffff04ff09ffff04ff0bff8080808080ffff01ff04ff29ffff04ff81b9ff808080ffff01ff02ff0cffff04ff02ffff04ff0dffff04ff0bff808080808080ff0180ffff01ff088080ff0180ffff02ffff01ff05ffff02ff3effff04ff02ffff04ff05ff8080808080ffff04ffff01ffffff81ff7fff81df81bfffffff02ffff03ffff09ff0bffff01818080ffff01ff04ff80ffff04ff05ff808080ffff01ff02ffff03ffff0aff0bff1880ffff01ff02ff1affff04ff02ffff04ffff02ffff03ffff0aff0bff1c80ffff01ff02ffff03ffff0aff0bff1480ffff01ff0880ffff01ff04ffff0effff18ffff011fff0b80ffff0cff05ff80ffff01018080ffff04ffff0cff05ffff010180ff80808080ff0180ffff01ff04ffff18ffff013fff0b80ffff04ff05ff80808080ff0180ff80808080ffff01ff04ff0bffff04ff05ff80808080ff018080ff0180ff04ffff0cff15ff80ff0980ffff04ffff0cff15ff0980ff808080ffff04ffff04ff05ff1380ffff04ff2bff808080ffff02ff16ffff04ff02ffff04ff09ffff04ffff02ff3effff04ff02ffff04ff15ff80808080ff8080808080ff02ffff03ffff09ffff0cff05ff80ffff010180ff1080ffff01ff02ff2effff04ff02ffff04ffff02ff3effff04ff02ffff04ffff0cff05ffff010180ff80808080ff80808080ffff01ff02ff12ffff04ff02ffff04ffff0cff05ffff010180ffff04ffff0cff05ff80ffff010180ff808080808080ff0180ff018080ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff0effff04ff02ffff04ff09ff80808080ffff02ff0effff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080
|
@ -1 +0,0 @@
|
||||
9eb0d58814fff6aec8e9eb9522c08a68d8f004bf1506e6c98388758beee2f80e
|
@ -1,3 +0,0 @@
|
||||
from chia.wallet.puzzles.load_clvm import load_serialized_clvm
|
||||
|
||||
GENERATOR_FOR_SINGLE_COIN_MOD = load_serialized_clvm("generator_for_single_coin.clvm", package_or_requirement=__name__)
|
@ -13,7 +13,6 @@ wallet_program_files = set(
|
||||
"chia/wallet/puzzles/cat_v2.clvm",
|
||||
"chia/wallet/puzzles/chialisp_deserialisation.clvm",
|
||||
"chia/wallet/puzzles/rom_bootstrap_generator.clvm",
|
||||
"chia/wallet/puzzles/generator_for_single_coin.clvm",
|
||||
"chia/wallet/puzzles/lock.inner.puzzle.clvm",
|
||||
"chia/wallet/puzzles/p2_conditions.clvm",
|
||||
"chia/wallet/puzzles/p2_delegated_conditions.clvm",
|
||||
|
@ -9,7 +9,9 @@ from chia.consensus.condition_costs import ConditionCost
|
||||
from chia.consensus.cost_calculator import NPCResult
|
||||
from chia.full_node.bundle_tools import simple_solution_generator
|
||||
from chia.full_node.mempool_check_conditions import get_name_puzzle_conditions, get_puzzle_and_solution_for_coin
|
||||
from chia.types.blockchain_format.coin import Coin
|
||||
from chia.types.blockchain_format.program import Program, SerializedProgram
|
||||
from chia.types.blockchain_format.sized_bytes import bytes32
|
||||
from chia.types.generator_types import BlockGenerator
|
||||
from chia.wallet.puzzles import p2_delegated_puzzle_or_hidden_puzzle
|
||||
from tests.setup_nodes import test_constants
|
||||
@ -79,11 +81,12 @@ class TestCostCalculation:
|
||||
assert npc_result.error is None
|
||||
assert len(bytes(program.program)) == 433
|
||||
|
||||
coin_name = npc_result.conds.spends[0].coin_id
|
||||
error, puzzle, solution = get_puzzle_and_solution_for_coin(
|
||||
program, coin_name, test_constants.MAX_BLOCK_COST_CLVM
|
||||
)
|
||||
coin_spend = spend_bundle.coin_spends[0]
|
||||
assert coin_spend.coin.name() == npc_result.conds.spends[0].coin_id
|
||||
error, puzzle, solution = get_puzzle_and_solution_for_coin(program, coin_spend.coin)
|
||||
assert error is None
|
||||
assert puzzle == coin_spend.puzzle_reveal.to_program()
|
||||
assert solution == coin_spend.solution.to_program()
|
||||
|
||||
assert npc_result.conds.cost == ConditionCost.CREATE_COIN.value + ConditionCost.AGG_SIG.value + 404560
|
||||
|
||||
@ -155,10 +158,12 @@ class TestCostCalculation:
|
||||
)
|
||||
assert npc_result.error is None
|
||||
|
||||
coin_name = npc_result.conds.spends[0].coin_id
|
||||
error, puzzle, solution = get_puzzle_and_solution_for_coin(
|
||||
generator, coin_name, test_constants.MAX_BLOCK_COST_CLVM
|
||||
coin = Coin(
|
||||
bytes32.fromhex("3d2331635a58c0d49912bc1427d7db51afe3f20a7b4bcaffa17ee250dcbcbfaa"),
|
||||
bytes32.fromhex("14947eb0e69ee8fc8279190fc2d38cb4bbb61ba28f1a270cfd643a0e8d759576"),
|
||||
300,
|
||||
)
|
||||
error, puzzle, solution = get_puzzle_and_solution_for_coin(generator, coin)
|
||||
assert error is None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
@ -146,14 +146,14 @@ class TestCompression(TestCase):
|
||||
start, end = match_standard_transaction_at_any_index(original_generator)
|
||||
ca = CompressorArg(uint32(0), SerializedProgram.from_bytes(original_generator), start, end)
|
||||
c = compressed_spend_bundle_solution(ca, sb)
|
||||
removal = sb.coin_spends[0].coin.name()
|
||||
error, puzzle, solution = get_puzzle_and_solution_for_coin(c, removal, INFINITE_COST)
|
||||
removal = sb.coin_spends[0].coin
|
||||
error, puzzle, solution = get_puzzle_and_solution_for_coin(c, removal)
|
||||
assert error is None
|
||||
assert bytes(puzzle) == bytes(sb.coin_spends[0].puzzle_reveal)
|
||||
assert bytes(solution) == bytes(sb.coin_spends[0].solution)
|
||||
# Test non compressed generator as well
|
||||
s = simple_solution_generator(sb)
|
||||
error, puzzle, solution = get_puzzle_and_solution_for_coin(s, removal, INFINITE_COST)
|
||||
error, puzzle, solution = get_puzzle_and_solution_for_coin(s, removal)
|
||||
assert error is None
|
||||
assert bytes(puzzle) == bytes(sb.coin_spends[0].puzzle_reveal)
|
||||
assert bytes(solution) == bytes(sb.coin_spends[0].solution)
|
||||
|
Loading…
Reference in New Issue
Block a user