def parse_condition(cond: SExp, safe_mode: bool) -> Tuple[int, Optional[ConditionWithArgs]]: condition = cond.first().as_atom() if condition in CONDITION_OPCODES: opcode: ConditionOpcode = ConditionOpcode(condition) cost, args = parse_condition_args(cond.rest(), opcode, safe_mode) cvl = ConditionWithArgs(opcode, args) if args is not None else None elif not safe_mode: opcode = ConditionOpcode.UNKNOWN cvl = ConditionWithArgs(opcode, cond.rest().as_atom_list()) cost = 0 else: raise ValidationError(Err.INVALID_CONDITION) return cost, cvl
def parse_aggsig(args: SExp) -> List[bytes]: pubkey = args.first().atom args = args.rest() message = args.first().atom if len(pubkey) != 48: raise ValidationError(Err.INVALID_CONDITION) if len(message) > 1024: raise ValidationError(Err.INVALID_CONDITION) # agg sig conditions only take 2 parameters args = args.rest() # the list is terminated by having a right-element that's not another pair, # just like as_atom_list() (see chia/types/blockchain_format/program.py) if args.pair is not None: raise ValidationError(Err.INVALID_CONDITION) return [pubkey, message]
def parse_aggsig(args: SExp) -> List[bytes]: pubkey = args.first().atom args = args.rest() message = args.first().atom if len(pubkey) != 48: raise ValidationError(Err.INVALID_CONDITION) if len(message) > 1024: raise ValidationError(Err.INVALID_CONDITION) return [pubkey, message]
def parse_create_coin(args: SExp, safe_mode: bool) -> List[bytes]: puzzle_hash = args.first().atom args = args.rest() if len(puzzle_hash) != 32: raise ValidationError(Err.INVALID_CONDITION) amount_int = sanitize_int(args.first(), safe_mode) if amount_int >= 2**64: raise ValidationError(Err.COIN_AMOUNT_EXCEEDS_MAXIMUM) if amount_int < 0: raise ValidationError(Err.COIN_AMOUNT_NEGATIVE) # note that this may change the representation of amount. If the original # buffer had redundant leading zeroes, they will be stripped return [puzzle_hash, int_to_bytes(amount_int)]
def _tree_hash(node: SExp, precalculated: Set[bytes32]) -> bytes32: """ Hash values in `precalculated` are presumed to have been hashed already. """ if node.listp(): left = _tree_hash(node.first(), precalculated) right = _tree_hash(node.rest(), precalculated) s = b"\2" + left + right else: atom = node.as_atom() if atom in precalculated: return bytes32(atom) s = b"\1" + atom return bytes32(std_hash(s))
def parse_condition( cond: SExp, safe_mode: bool) -> Tuple[int, Optional[ConditionWithArgs]]: condition = cond.first().as_atom() if condition in CONDITION_OPCODES: opcode: ConditionOpcode = ConditionOpcode(condition) cost, args = parse_condition_args(cond.rest(), opcode, safe_mode) cvl = ConditionWithArgs(opcode, args) if args is not None else None elif not safe_mode: # we don't need to save unknown conditions. We can't do anything with them anyway # safe_mode just tells us whether we can tolerate them or not return 0, None else: raise ValidationError(Err.INVALID_CONDITION) return cost, cvl
def ir_rest(ir_sexp: SExp) -> SExp: return ir_sexp.rest().rest()
def ir_as_atom(ir_sexp: SExp) -> bytes: return bytes(ir_sexp.rest().as_atom())
def ir_as_sexp(ir_sexp: SExp) -> SExp: if ir_nullp(ir_sexp): return [] if ir_type(ir_sexp) == Type.CONS: return ir_as_sexp(ir_first(ir_sexp)).cons(ir_as_sexp(ir_rest(ir_sexp))) return ir_sexp.rest()
def ir_val(ir_sexp: SExp) -> SExp: return ir_sexp.rest()