def sign_transaction(self, coin_solutions: List[CoinSolution]) -> SpendBundle: signatures = [] solution: Program puzzle: Program for coin_solution in coin_solutions: # type: ignore # noqa secret_key = self.get_private_key_for_puzzle_hash( coin_solution.coin.puzzle_hash) synthetic_secret_key = calculate_synthetic_secret_key( secret_key, DEFAULT_HIDDEN_PUZZLE_HASH) err, con, cost = conditions_for_solution( coin_solution.puzzle_reveal, coin_solution.solution, self.constants.MAX_BLOCK_COST_CLVM) if not con: raise ValueError(err) conditions_dict = conditions_by_opcode(con) for _, msg in pkm_pairs_for_conditions_dict( conditions_dict, bytes(coin_solution.coin.name()), self.constants.AGG_SIG_ME_ADDITIONAL_DATA): signature = AugSchemeMPL.sign(synthetic_secret_key, msg) signatures.append(signature) aggsig = AugSchemeMPL.aggregate(signatures) spend_bundle = SpendBundle(coin_solutions, aggsig) return spend_bundle
def sign_transaction(self, coin_spends: List[CoinSpend]) -> SpendBundle: signatures = [] solution: Program puzzle: Program for coin_spend in coin_spends: # noqa secret_key = self.get_private_key_for_puzzle_hash(coin_spend.coin.puzzle_hash) synthetic_secret_key = calculate_synthetic_secret_key(secret_key, DEFAULT_HIDDEN_PUZZLE_HASH) err, con, cost = conditions_for_solution( coin_spend.puzzle_reveal, coin_spend.solution, self.constants.MAX_BLOCK_COST_CLVM ) if not con: raise ValueError(err) conditions_dict = conditions_by_opcode(con) for cwa in conditions_dict.get(ConditionOpcode.AGG_SIG_UNSAFE, []): msg = cwa.vars[1] signature = AugSchemeMPL.sign(synthetic_secret_key, msg) signatures.append(signature) for cwa in conditions_dict.get(ConditionOpcode.AGG_SIG_ME, []): msg = cwa.vars[1] + bytes(coin_spend.coin.name()) + self.constants.AGG_SIG_ME_ADDITIONAL_DATA signature = AugSchemeMPL.sign(synthetic_secret_key, msg) signatures.append(signature) aggsig = AugSchemeMPL.aggregate(signatures) spend_bundle = SpendBundle(coin_spends, aggsig) return spend_bundle
def signature_for_solution(self, coin_solution: CoinSolution, additional_data: bytes) -> AugSchemeMPL: signatures = [] err, conditions, cost = conditions_for_solution(coin_solution.puzzle_reveal, coin_solution.solution) assert conditions is not None conditions_dict = conditions_by_opcode(conditions) for public_key, message_hash in pkm_pairs_for_conditions_dict( conditions_dict, coin_solution.coin.name(), additional_data ): signature = self.sign(bytes(public_key), message_hash) signatures.append(signature) return AugSchemeMPL.aggregate(signatures)
def get_name_puzzle_conditions( block_program: SerializedProgram, safe_mode: bool ) -> Tuple[Optional[str], Optional[List[NPC]], Optional[uint64]]: # TODO: allow generator mod to take something (future) # TODO: write more tests block_program_args = SerializedProgram.from_bytes(b"\x80") try: if safe_mode: cost, result = GENERATOR_MOD.run_safe_with_cost( block_program, block_program_args) else: cost, result = GENERATOR_MOD.run_with_cost(block_program, block_program_args) npc_list: List[NPC] = [] opcodes: Set[bytes] = set(item.value for item in ConditionOpcode) for res in result.as_iter(): conditions_list: List[ConditionWithArgs] = [] spent_coin_parent_id: bytes32 = res.first().first().as_atom() spent_coin_puzzle_hash: bytes32 = res.first().rest().first( ).as_atom() spent_coin_amount: uint64 = uint64( res.first().rest().rest().first().as_int()) spent_coin: Coin = Coin(spent_coin_parent_id, spent_coin_puzzle_hash, spent_coin_amount) for cond in res.rest().first().as_iter(): if cond.first().as_atom() in opcodes: opcode: ConditionOpcode = ConditionOpcode( cond.first().as_atom()) elif not safe_mode: opcode = ConditionOpcode.UNKNOWN else: return "Unknown operator in safe mode.", None, None conditions_list.append( ConditionWithArgs(opcode, cond.rest().as_atom_list())) conditions_dict = conditions_by_opcode(conditions_list) if conditions_dict is None: conditions_dict = {} npc_list.append( NPC(spent_coin.name(), spent_coin.puzzle_hash, [(a, b) for a, b in conditions_dict.items()])) return None, npc_list, uint64(cost) except Exception: tb = traceback.format_exc() return tb, None, None
def get_name_puzzle_conditions(block_program: SerializedProgram, safe_mode: bool): # TODO: allow generator mod to take something (future) # TODO: write more tests block_program_args = SerializedProgram.from_bytes(b"\x80") try: if safe_mode: cost, result = GENERATOR_MOD.run_safe_with_cost( block_program, block_program_args) else: cost, result = GENERATOR_MOD.run_with_cost(block_program, block_program_args) npc_list = [] opcodes = set(item.value for item in ConditionOpcode) for res in result.as_iter(): conditions_list = [] name = std_hash( bytes(res.first().first().as_atom() + res.first().rest().first().as_atom() + res.first().rest().rest().first().as_atom())) puzzle_hash = bytes32(res.first().rest().first().as_atom()) for cond in res.rest().first().as_iter(): if cond.first().as_atom() in opcodes: opcode = ConditionOpcode(cond.first().as_atom()) elif not safe_mode: opcode = ConditionOpcode.UNKNOWN else: return "Unknown operator in safe mode.", None, None if len(list(cond.as_iter())) > 1: cond_var_list = [] for cond_1 in cond.rest().as_iter(): cond_var_list.append(cond_1.as_atom()) cvl = ConditionVarPair(opcode, cond_var_list) else: cvl = ConditionVarPair(opcode, []) conditions_list.append(cvl) conditions_dict = conditions_by_opcode(conditions_list) if conditions_dict is None: conditions_dict = {} npc_list.append( NPC(name, puzzle_hash, [(a, b) for a, b in conditions_dict.items()])) return None, npc_list, uint64(cost) except Exception: tb = traceback.format_exc() return tb, None, None
def signature_for_solution(self, coin_spend: CoinSpend, additional_data: bytes) -> AugSchemeMPL: signatures = [] err, conditions, cost = conditions_for_solution( coin_spend.puzzle_reveal, coin_spend.solution, test_constants.MAX_BLOCK_COST_CLVM) assert conditions is not None conditions_dict = conditions_by_opcode(conditions) for public_key, message_hash in pkm_pairs_for_conditions_dict( conditions_dict, coin_spend.coin.name(), additional_data): # TODO: address hint error and remove ignore # error: Argument 2 to "sign" of "KeyTool" has incompatible type "bytes"; expected "bytes32" # [arg-type] signature = self.sign(public_key, message_hash) # type: ignore[arg-type] signatures.append(signature) return AugSchemeMPL.aggregate(signatures)
def get_name_puzzle_conditions(generator: BlockGenerator, max_cost: int, safe_mode: bool) -> NPCResult: try: block_program, block_program_args = setup_generator_args(generator) if safe_mode: cost, result = GENERATOR_MOD.run_safe_with_cost( max_cost, block_program, block_program_args) else: cost, result = GENERATOR_MOD.run_with_cost(max_cost, block_program, block_program_args) npc_list: List[NPC] = [] opcodes: Set[bytes] = set(item.value for item in ConditionOpcode) for res in result.as_iter(): conditions_list: List[ConditionWithArgs] = [] spent_coin_parent_id: bytes32 = res.first().first().as_atom() spent_coin_puzzle_hash: bytes32 = res.first().rest().first( ).as_atom() spent_coin_amount: uint64 = uint64( res.first().rest().rest().first().as_int()) spent_coin: Coin = Coin(spent_coin_parent_id, spent_coin_puzzle_hash, spent_coin_amount) for cond in res.rest().first().as_iter(): if cond.first().as_atom() in opcodes: opcode: ConditionOpcode = ConditionOpcode( cond.first().as_atom()) elif not safe_mode: opcode = ConditionOpcode.UNKNOWN else: return NPCResult(uint16(Err.GENERATOR_RUNTIME_ERROR.value), [], uint64(0)) cvl = ConditionWithArgs(opcode, cond.rest().as_atom_list()) conditions_list.append(cvl) conditions_dict = conditions_by_opcode(conditions_list) if conditions_dict is None: conditions_dict = {} npc_list.append( NPC(spent_coin.name(), spent_coin.puzzle_hash, [(a, b) for a, b in conditions_dict.items()])) return NPCResult(None, npc_list, uint64(cost)) except Exception: return NPCResult(uint16(Err.GENERATOR_RUNTIME_ERROR.value), [], uint64(0))
def get_name_puzzle_conditions_python(generator: BlockGenerator, max_cost: int, *, cost_per_byte: int, safe_mode: bool) -> NPCResult: """ This executes the generator program and returns the coins and their conditions. If the cost of the program (size, CLVM execution and conditions) exceed max_cost, the function fails. In order to accurately take the size of the program into account when calculating cost, cost_per_byte must be specified. safe_mode determines whether the clvm program and conditions are executed in strict mode or not. When in safe/strict mode, unknow operations or conditions are considered failures. This is the mode when accepting transactions into the mempool. """ block_program, block_program_args = setup_generator_args(generator) max_cost -= len(bytes(generator.program)) * cost_per_byte if max_cost < 0: return NPCResult(uint16(Err.INVALID_BLOCK_COST.value), [], uint64(0)) if safe_mode: clvm_cost, result = GENERATOR_MOD.run_safe_with_cost( max_cost, block_program, block_program_args) else: clvm_cost, result = GENERATOR_MOD.run_with_cost( max_cost, block_program, block_program_args) max_cost -= clvm_cost if max_cost < 0: return NPCResult(uint16(Err.INVALID_BLOCK_COST.value), [], uint64(0)) npc_list: List[NPC] = [] for res in result.first().as_iter(): conditions_list: List[ConditionWithArgs] = [] if len(res.first().atom) != 32: raise ValidationError(Err.INVALID_CONDITION) spent_coin_parent_id: bytes32 = res.first().as_atom() res = res.rest() if len(res.first().atom) != 32: raise ValidationError(Err.INVALID_CONDITION) spent_coin_puzzle_hash: bytes32 = res.first().as_atom() res = res.rest() spent_coin_amount: uint64 = uint64(sanitize_int( res.first(), safe_mode)) res = res.rest() spent_coin: Coin = Coin(spent_coin_parent_id, spent_coin_puzzle_hash, spent_coin_amount) for cond in res.first().as_iter(): cost, cvl = parse_condition(cond, safe_mode) max_cost -= cost if max_cost < 0: return NPCResult(uint16(Err.INVALID_BLOCK_COST.value), [], uint64(0)) if cvl is not None: conditions_list.append(cvl) conditions_dict = conditions_by_opcode(conditions_list) if conditions_dict is None: conditions_dict = {} npc_list.append( NPC(spent_coin.name(), spent_coin.puzzle_hash, [(a, b) for a, b in conditions_dict.items()])) return NPCResult(None, npc_list, uint64(clvm_cost))