def run_test_p2_delegated_puzzle_or_hidden_puzzle_with_delegated_puzzle( self, hidden_pub_key_index): payments, conditions = default_payments_and_conditions() hidden_puzzle = p2_conditions.puzzle_for_conditions(conditions) hidden_public_key = public_key_bytes_for_index(hidden_pub_key_index) puzzle = p2_delegated_puzzle_or_hidden_puzzle.puzzle_for_public_key_and_hidden_puzzle( hidden_public_key, hidden_puzzle) puzzle_hash = ProgramHash(puzzle) payable_payments, payable_conditions = default_payments_and_conditions( 5) delegated_puzzle = p2_conditions.puzzle_for_conditions( payable_conditions) delegated_solution = [] synthetic_public_key = p2_delegated_puzzle_or_hidden_puzzle.calculate_synthetic_public_key( hidden_public_key, hidden_puzzle) solution = p2_delegated_puzzle_or_hidden_puzzle.solution_with_delegated_puzzle( synthetic_public_key, delegated_puzzle, delegated_solution) hidden_puzzle_hash = ProgramHash(hidden_puzzle) synthetic_offset = p2_delegated_puzzle_or_hidden_puzzle.calculate_synthetic_offset( hidden_public_key, hidden_puzzle_hash) private_key = bls_private_key_for_index(hidden_pub_key_index) assert private_key.public_key() == hidden_public_key secret_exponent = private_key.secret_exponent() synthetic_secret_exponent = secret_exponent + synthetic_offset DEFAULT_KEYCHAIN.add_secret_exponents([synthetic_secret_exponent]) run_test(puzzle_hash, solution, payable_payments)
def as_make_puzzle(self, as_pubkey_sender, as_pubkey_receiver, as_amount, as_timelock_block, as_secret_hash): as_pubkey_sender_cl = "0x%s" % ( hexlify(as_pubkey_sender).decode('ascii')) as_pubkey_receiver_cl = "0x%s" % ( hexlify(as_pubkey_receiver).decode('ascii')) as_payout_puzzlehash_receiver = ProgramHash( puzzle_for_pk(as_pubkey_receiver)) as_payout_puzzlehash_sender = ProgramHash( puzzle_for_pk(as_pubkey_sender)) payout_receiver = "(c (q 0x%s) (c (q 0x%s) (c (q %d) (q ()))))" % ( hexlify(ConditionOpcode.CREATE_COIN).decode('ascii'), hexlify(as_payout_puzzlehash_receiver).decode('ascii'), as_amount) payout_sender = "(c (q 0x%s) (c (q 0x%s) (c (q %d) (q ()))))" % ( hexlify(ConditionOpcode.CREATE_COIN).decode('ascii'), hexlify(as_payout_puzzlehash_sender).decode('ascii'), as_amount) aggsig_receiver = "(c (q 0x%s) (c (q %s) (c (sha256 (wrap (a))) (q ()))))" % ( hexlify(ConditionOpcode.AGG_SIG).decode('ascii'), as_pubkey_receiver_cl) aggsig_sender = "(c (q 0x%s) (c (q %s) (c (sha256 (wrap (a))) (q ()))))" % ( hexlify( ConditionOpcode.AGG_SIG).decode('ascii'), as_pubkey_sender_cl) receiver_puz = ("((c (i (= (sha256 (f (r (a)))) (q %s)) (q (c " + aggsig_receiver + " (c " + payout_receiver + " (q ())))) (q (x (q 'invalid secret')))) (a))) ) " ) % (as_secret_hash) timelock = "(c (q 0x%s) (c (q %d) (q ()))) " % (hexlify( ConditionOpcode.ASSERT_BLOCK_INDEX_EXCEEDS).decode('ascii'), as_timelock_block) sender_puz = "(c " + aggsig_sender + " (c " + timelock + " (c " + payout_sender + " (q ()))))" as_puz_sender = "((c (i (= (f (a)) (q 77777)) (q " + sender_puz + ") (q (x (q 'not a valid option'))) ) (a)))" as_puz = "((c (i (= (f (a)) (q 33333)) (q " + receiver_puz + " (q " + as_puz_sender + ")) (a)))" return Program(binutils.assemble(as_puz))
def ap_generate_signed_aggregation_transaction(self): list_of_coinsolutions = [] if self.aggregation_coins is False: # empty sets evaluate to false in python return consolidating_coin = self.aggregation_coins.pop() pubkey, secretkey = self.get_keys( self.temp_coin.puzzle_hash, self.a_pubkey) # Spend wallet coin puzzle = ap_make_puzzle(self.a_pubkey, bytes(pubkey)) solution = self.ap_make_solution_mode_2(self.temp_coin.puzzle_hash, consolidating_coin.parent_coin_info, consolidating_coin.puzzle_hash, consolidating_coin.amount, self.temp_coin.parent_coin_info, self.temp_coin.amount) signature = secretkey.sign(ProgramHash(solution)) list_of_coinsolutions.append(CoinSolution( self.temp_coin, clvm.to_sexp_f([puzzle, solution]))) # Spend consolidating coin puzzle = ap_make_aggregation_puzzle(self.temp_coin.puzzle_hash) solution = self.ac_make_aggregation_solution(consolidating_coin.name( ), self.temp_coin.parent_coin_info, self.temp_coin.amount) list_of_coinsolutions.append(CoinSolution( consolidating_coin, clvm.to_sexp_f([puzzle, solution]))) # Spend lock puzstring = f"(r (c (q 0x{consolidating_coin.name().hex()}) (q ())))" puzzle = Program(binutils.assemble(puzstring)) solution = Program(binutils.assemble("()")) list_of_coinsolutions.append(CoinSolution(Coin(self.temp_coin, ProgramHash( puzzle), 0), clvm.to_sexp_f([puzzle, solution]))) self.temp_coin = Coin(self.temp_coin, self.temp_coin.puzzle_hash, self.temp_coin.amount + consolidating_coin.amount) aggsig = BLSSignature.aggregate([signature]) solution_list = CoinSolutionList(list_of_coinsolutions) return SpendBundle(solution_list, aggsig)
async def move_custody(wallet, ledger_api): print("Moving custody") print(f"Amount being moved: {wallet.cp_balance}") amount = wallet.cp_balance unlock_time = wallet.unlock_time pubkey_permission = wallet.pubkey_permission current_time = await ledger_api.skip_milliseconds( ms=uint64(0).to_bytes(4, 'big')) if unlock_time > current_time: new_pub = input("Enter pubkey of the new custodian wallet: ") print("Permission needed before moving funds: ") puzzle_hash = ProgramHash( wallet.cp_puzzle(new_pub, pubkey_permission, unlock_time)) approval = input("\nAdd authorization: ") approval = bytes.fromhex(approval) spend_bundle = wallet.cp_generate_signed_transaction_with_approval( puzzle_hash, amount, approval) _ = await ledger_api.push_tx(tx=spend_bundle) else: print("Permission not needed for moving funds") pubkey = input("Enter receiver pubkey: ") pub_bytes = bytes.fromhex(pubkey) reg_puzzle = wallet.puzzle_for_pk(pub_bytes) puzzle_hash = ProgramHash(reg_puzzle) spend_bundle = wallet.cp_generate_signed_transaction( puzzle_hash, amount) _ = await ledger_api.push_tx(tx=spend_bundle)
def get_keys(self, hash, a_pubkey_used=None, b_pubkey_used=None): for child in reversed(range(self.next_address)): pubkey = self.extended_secret_key.public_child(child) if hash == ProgramHash(puzzle_for_pk(bytes(pubkey))): return (pubkey, self.extended_secret_key.private_child(child)) if a_pubkey_used is not None and b_pubkey_used is None: if hash == ProgramHash(ap_make_puzzle(a_pubkey_used, bytes(pubkey))): return (pubkey, self.extended_secret_key.private_child(child)) elif a_pubkey_used is None and b_pubkey_used is not None: if hash == ProgramHash(ap_make_puzzle(bytes(pubkey), b_pubkey_used)): return (pubkey, self.extended_secret_key.private_child(child))
def test_standard_spend(): remote = make_client_server() run = asyncio.get_event_loop().run_until_complete wallet_a = Wallet() wallet_b = Wallet() wallets = [wallet_a, wallet_b] commit_and_notify(remote, wallets, wallet_a) assert wallet_a.current_balance == 1000000000 assert len(wallet_a.my_utxos) == 2 assert wallet_b.current_balance == 0 assert len(wallet_b.my_utxos) == 0 # wallet a send to wallet b pubkey_puz_string = "(0x%s)" % hexlify( wallet_b.get_next_public_key().serialize()).decode('ascii') args = binutils.assemble(pubkey_puz_string) program = Program( clvm.eval_f( clvm.eval_f, binutils.assemble( wallet_a.generator_lookups[wallet_b.puzzle_generator_id]), args)) puzzlehash = ProgramHash(program) amount = 5000 spend_bundle = wallet_a.generate_signed_transaction(amount, puzzlehash) _ = run(remote.push_tx(tx=spend_bundle)) # give new wallet the reward to not complicate the one's we're tracking commit_and_notify(remote, wallets, Wallet()) assert wallet_a.current_balance == 999995000 assert wallet_b.current_balance == 5000 assert len(wallet_b.my_utxos) == 1 # wallet b sends back to wallet a pubkey_puz_string = "(0x%s)" % hexlify( wallet_a.get_next_public_key().serialize()).decode('ascii') args = binutils.assemble(pubkey_puz_string) program = Program( clvm.eval_f( clvm.eval_f, binutils.assemble( wallet_b.generator_lookups[wallet_a.puzzle_generator_id]), args)) puzzlehash = ProgramHash(program) amount = 5000 spend_bundle = wallet_b.generate_signed_transaction(amount, puzzlehash) _ = run(remote.push_tx(tx=spend_bundle)) # give new wallet the reward to not complicate the one's we're tracking commit_and_notify(remote, wallets, Wallet()) assert wallet_a.current_balance == 1000000000 assert wallet_b.current_balance == 0
def rl_generate_signed_aggregation_transaction(self): list_of_coinsolutions = [] if self.aggregation_coins is False: # empty sets evaluate to false in python return consolidating_coin = self.aggregation_coins.pop() pubkey, secretkey = self.get_keys(self.rl_coin.puzzle_hash) # Spend wallet coin puzzle = self.rl_puzzle_for_pk(pubkey.serialize(), self.limit, self.interval, self.rl_origin, self.rl_clawback_pk) if isinstance(self.rl_parent, Coin): solution = self.rl_make_solution_mode_2( self.rl_coin.puzzle_hash, consolidating_coin.parent_coin_info, consolidating_coin.puzzle_hash, consolidating_coin.amount, self.rl_coin.parent_coin_info, self.rl_coin.amount, self.rl_parent.amount, self.rl_parent.parent_coin_info) else: solution = self.rl_make_solution_mode_2( self.rl_coin.puzzle_hash, consolidating_coin.parent_coin_info, consolidating_coin.puzzle_hash, consolidating_coin.amount, self.rl_coin.parent_coin_info, self.rl_coin.amount, self.rl_parent["amount"], self.rl_parent["parent_coin_info"]) signature = BLSPrivateKey(secretkey).sign(ProgramHash(solution)) list_of_coinsolutions.append( CoinSolution(self.rl_coin, clvm.to_sexp_f([puzzle, solution]))) # Spend consolidating coin puzzle = self.rl_make_aggregation_puzzle(self.rl_coin.puzzle_hash) solution = self.rl_make_aggregation_solution( consolidating_coin.name(), self.rl_coin.parent_coin_info, self.rl_coin.amount) list_of_coinsolutions.append( CoinSolution(consolidating_coin, clvm.to_sexp_f([puzzle, solution]))) # Spend lock puzstring = "(r (c (q 0x" + hexlify( consolidating_coin.name()).decode('ascii') + ") (q ())))" puzzle = Program(binutils.assemble(puzstring)) solution = Program(binutils.assemble("()")) list_of_coinsolutions.append( CoinSolution(Coin(self.rl_coin, ProgramHash(puzzle), 0), clvm.to_sexp_f([puzzle, solution]))) aggsig = BLSSignature.aggregate([signature]) solution_list = CoinSolutionList(list_of_coinsolutions) return SpendBundle(solution_list, aggsig)
async def create_custody(wallet, ledger_api): option = input("Press (c) for custodian, or press (a) for authorizer") if option == "c": print("Custodian selected") pubkey = hexbytes(wallet.get_next_public_key().serialize()) print(f"Custodian pubkey: {pubkey}") pubkey_auth = input("Enter Authorizer's pubkey: ") wallet.pubkey_permission = pubkey_auth unlock_time = get_int( "Specify unlock time (milliseconds since 1970): ") wallet.unlock_time = unlock_time return elif option == "a": pubkey = hexbytes(wallet.get_next_public_key().serialize()) wallet.pubkey_approval = pubkey print("Authorizer Selected") print(f"Authorizer pubkey is: {pubkey}") pubkey_custody = input("Enter Custodian's pubkey: ") unlock_time = get_int( "Enter the same lock time as in custody wallet: ") amount = get_int("Enter Chia amount to send to custody: ") wallet.unlock_time = unlock_time puzzle_hash = ProgramHash( wallet.cp_puzzle(pubkey_custody, pubkey, unlock_time)) spend_bundle = wallet.generate_signed_transaction(amount, puzzle_hash) _ = await ledger_api.push_tx(tx=spend_bundle) return else: print("Invalid option, returning...") return
def name_puzzle_conditions_list(body_program): """ Return a list of tuples of (coin_name, solved_puzzle_hash, conditions_dict) """ try: cost, sexp = run_program(body_program, []) except EvalError: breakpoint() raise ConsensusError(Err.INVALID_BLOCK_SOLUTION, body_program) npc_list = [] for name_solution in sexp.as_iter(): _ = name_solution.as_python() if len(_) != 2: raise ConsensusError(Err.INVALID_COIN_SOLUTION, name_solution) if not isinstance(_[0], bytes) or len(_[0]) != 32: raise ConsensusError(Err.INVALID_COIN_SOLUTION, name_solution) coin_name = CoinName(_[0]) if not isinstance(_[1], list) or len(_[1]) != 2: raise ConsensusError(Err.INVALID_COIN_SOLUTION, name_solution) puzzle_solution_program = name_solution.rest().first() puzzle_program = puzzle_solution_program.first() puzzle_hash = ProgramHash(Program(puzzle_program)) try: conditions_dict = conditions_dict_for_solution( puzzle_solution_program) except EvalError: raise ConsensusError(Err.INVALID_COIN_SOLUTION, coin_name) npc_list.append((coin_name, puzzle_hash, conditions_dict)) return npc_list
def as_get_new_puzzlehash(self, as_pubkey_sender, as_pubkey_receiver, as_amount, as_timelock_block, as_secret_hash): as_puz = self.as_make_puzzle(as_pubkey_sender, as_pubkey_receiver, as_amount, as_timelock_block, as_secret_hash) as_puzzlehash = ProgramHash(as_puz) return as_puzzlehash
def get_keys(self, hash): for child in range(self.next_address): pubkey = self.extended_secret_key.public_child( child).get_public_key() if hash == ProgramHash(self.puzzle_for_pk(pubkey.serialize())): return (pubkey, self.extended_secret_key.private_child( child).get_private_key())
def test_p2_puzzle_hash(self): payments, conditions = default_payments_and_conditions() underlying_puzzle = p2_delegated_conditions.puzzle_for_pk( public_key_bytes_for_index(4)) underlying_solution = p2_delegated_conditions.solution_for_conditions( underlying_puzzle, conditions) underlying_puzzle_hash = ProgramHash(underlying_puzzle) puzzle_program = p2_puzzle_hash.puzzle_for_puzzle_hash( underlying_puzzle_hash) puzzle_hash = ProgramHash(puzzle_program) solution = p2_puzzle_hash.solution_for_puzzle_and_solution( underlying_puzzle, underlying_solution) run_test(puzzle_hash, solution, payments)
def test_assert_block_age_exceeds(self): run = asyncio.get_event_loop().run_until_complete remote = make_client_server() puzzle_program = p2_delegated_conditions.puzzle_for_pk( public_key_bytes_for_index(8)) puzzle_hash = ProgramHash(puzzle_program) # farm a bunch of blocks to start for _ in range(20): farm_spendable_coin(remote, puzzle_hash) coin_1 = farm_spendable_coin(remote, puzzle_hash) conditions_block_age_exceeds_1 = [ make_assert_block_age_exceeds_condition(1) ] # try to spend coin_1 with limit set to age 1. Should fail solution_1 = p2_delegated_conditions.solution_for_conditions( puzzle_program, conditions_block_age_exceeds_1) spend_bundle_1 = build_spend_bundle(coin_1, solution_1) r = run(remote.push_tx(tx=spend_bundle_1)) assert r.args[0].startswith( "exception: (<Err.ASSERT_BLOCK_AGE_EXCEEDS_FAILED") # farm a block and try again. Should succeed farm_spendable_coin(remote, puzzle_hash) r = run(remote.push_tx(tx=spend_bundle_1)) assert r["response"].startswith("accepted")
def test_assert_time_exceeds(self): run = asyncio.get_event_loop().run_until_complete remote = make_client_server() puzzle_program = p2_delegated_conditions.puzzle_for_pk( public_key_bytes_for_index(8)) puzzle_hash = ProgramHash(puzzle_program) coin_1 = farm_spendable_coin(remote, puzzle_hash) now = run(remote.skip_milliseconds(ms=uint64(0).to_bytes(4, 'big'))) assert (type(now) == int) min_time = now + 1000 conditions_time_exceeds = [ make_assert_time_exceeds_condition(min_time) ] # try to spend coin_1 with limit set to age 1. Should fail solution_1 = p2_delegated_conditions.solution_for_conditions( puzzle_program, conditions_time_exceeds) spend_bundle_1 = build_spend_bundle(coin_1, solution_1) r = run(remote.push_tx(tx=spend_bundle_1)) assert r.args[0].startswith( "exception: (<Err.ASSERT_TIME_EXCEEDS_FAILED") # wait a second, should succeed r = run(remote.skip_milliseconds(ms=uint64(1001))) r = run(remote.push_tx(tx=spend_bundle_1)) assert r["response"].startswith("accepted")
def ac_notify(self, additions): if len(self.my_utxos) >= 1: self.temp_coin = self.my_utxos.copy().pop() # reset temp_coin else: return # prevent unnecessary searching spend_bundle_list = [] for coin in additions: my_utxos_copy = self.my_utxos.copy() for mycoin in self.my_utxos: # Check if we have already spent any coins in our utxo set if coin.parent_coin_info == mycoin.name(): my_utxos_copy.remove(mycoin) self.current_balance -= mycoin.amount self.my_utxos = my_utxos_copy.copy() self.temp_coin = my_utxos_copy.copy().pop() if ProgramHash( ap_make_aggregation_puzzle( self.temp_coin.puzzle_hash)) == coin.puzzle_hash: self.aggregation_coins.add(coin) spend_bundle = self.ap_generate_signed_aggregation_transaction( ) spend_bundle_list.append(spend_bundle) if spend_bundle_list: return spend_bundle_list else: return None
def test_cp_receive(): remote = make_client_server() run = asyncio.get_event_loop().run_until_complete wallet_a = CPWallet() wallet_b = CPWallet() wallet_c = CPWallet() wallets = [wallet_a, wallet_b, wallet_c] pub_a = hexbytes(wallet_a.get_next_public_key()) pub_b = hexbytes(wallet_b.get_next_public_key()) wallet_b.pubkey_permission = pub_a wallet_b.unlock_time = 100 b_puzzle = wallet_b.cp_puzzle(pub_b, pub_a, 100) b_puzzlehash = ProgramHash(b_puzzle) commit_and_notify(remote, wallets, wallet_a) assert wallet_a.current_balance == 1000000000 assert wallet_b.current_balance == 0 assert wallet_c.current_balance == 0 spend_bundle = wallet_a.generate_signed_transaction(1000, b_puzzlehash) _ = run(remote.push_tx(tx=spend_bundle)) commit_and_notify(remote, wallets, Wallet()) assert wallet_a.current_balance == 999999000 assert wallet_b.cp_balance == 1000 assert wallet_c.current_balance == 0
def do_multisig(selectors, fuzz_coin=None, fuzz_signature=None): payments = [ (puzzle_hash_for_index(0), 1000), (puzzle_hash_for_index(1), 2000), ] conditions = conditions_for_payment(payments) pks = [public_key_bytes_for_index(_) for _ in range(1, 4)] M = 2 puzzle_program = p2_m_of_n_delegate_direct.puzzle_for_m_of_public_key_list( M, pks) puzzle_hash = ProgramHash(puzzle_program) def solution_maker(coin, remote): print(coin.name()) if fuzz_coin: coin = fuzz_coin(remote, puzzle_hash) print(coin.name()) id_condition = make_assert_my_coin_id_condition(coin.name()) delegated_puzzle = p2_conditions.puzzle_for_conditions( conditions + [id_condition]) delegated_solution = p2_delegated_conditions.solution_for_conditions( delegated_puzzle, []) solution = p2_m_of_n_delegate_direct.solution_for_delegated_puzzle( M, pks, selectors, delegated_puzzle, delegated_solution) return solution run_test(puzzle_hash, payments, solution_maker, fuzz_signature)
def get_new_puzzle_with_params_and_root(self, recovery_pubkey, pubkey, stake_factor, duration): op_create = ConditionOpcode.CREATE_COIN[0] op_consumed = ConditionOpcode.ASSERT_COIN_CONSUMED[0] solution = args(0) solution_args = args(1) secure_switch = args(2) parent = args(3) puzzle_hash = args(4) value = args(5) new_value = args(6) evaluate_solution = eval(solution, solution_args) standard_conditions = make_list(aggsig_condition(pubkey), terminator=evaluate_solution) escrow_program = self.get_escrow_puzzle_with_params( recovery_pubkey, pubkey, duration) escrow_puzzlehash = f'0x' + str(hexbytes(ProgramHash(escrow_program))) f = Fraction(stake_factor) stake_factor_numerator = quote(f.numerator) stake_factor_denominator = quote(f.denominator) create_condition = make_if( equal(multiply(new_value, stake_factor_denominator), multiply(value, stake_factor_numerator)), make_list(quote(op_create), quote(escrow_puzzlehash), new_value), fail()) coin_id = sha256(parent, puzzle_hash, uint64(value)) consumed_condition = make_list(quote(op_consumed), coin_id) escrow_conditions = make_list(create_condition, consumed_condition) puzzle = make_if(is_zero(secure_switch), standard_conditions, escrow_conditions) program = Program(binutils.assemble(puzzle)) return program
def can_generate_puzzle_hash(self, hash): return any( map( lambda child: hash == ProgramHash( puzzle_for_pk( bytes(self.extended_secret_key.public_child(child)))), reversed(range(self.next_address))))
def test_assert_coin_consumed(self): run = asyncio.get_event_loop().run_until_complete remote = make_client_server() puzzle_program = p2_delegated_conditions.puzzle_for_pk( public_key_bytes_for_index(8)) puzzle_hash = ProgramHash(puzzle_program) coin_1 = farm_spendable_coin(remote, puzzle_hash) coin_2 = farm_spendable_coin(remote, puzzle_hash) conditions_coin_1 = [ make_assert_coin_consumed_condition(coin_2.name()) ] solution_1 = p2_delegated_conditions.solution_for_conditions( puzzle_program, conditions_coin_1) spend_bundle_1 = build_spend_bundle(coin_1, solution_1) # try to spend coin_1 without coin_2. Should fail. r = run(remote.push_tx(tx=spend_bundle_1)) assert r.args[0].startswith( "exception: (<Err.ASSERT_COIN_CONSUMED_FAILED") # try to spend coin_1 with coin_2. Should be okay spend_bundle_2 = build_spend_bundle(coin_2, solution_1) spend_bundle = spend_bundle_1.aggregate( [spend_bundle_1, spend_bundle_2]) r = run(remote.push_tx(tx=spend_bundle)) assert r["response"].startswith("accepted") spend_bundle_2 = build_spend_bundle(coin_2, solution_1)
def test_assert_my_id(self): run = asyncio.get_event_loop().run_until_complete remote = make_client_server() puzzle_program = p2_delegated_conditions.puzzle_for_pk( public_key_bytes_for_index(8)) puzzle_hash = ProgramHash(puzzle_program) coin_1 = farm_spendable_coin(remote, puzzle_hash) coin_2 = farm_spendable_coin(remote, puzzle_hash) coin_3 = farm_spendable_coin(remote, puzzle_hash) conditions_coin_1 = [make_assert_my_coin_id_condition(coin_1.name())] solution_1 = p2_delegated_conditions.solution_for_conditions( puzzle_program, conditions_coin_1) spend_bundle = build_spend_bundle(coin_1, solution_1) r = run(remote.push_tx(tx=spend_bundle)) assert r["response"].startswith("accepted") spend_bundle = build_spend_bundle(coin_2, solution_1) r = run(remote.push_tx(tx=spend_bundle)) assert r.args[0].startswith( "exception: (<Err.ASSERT_MY_COIN_ID_FAILED") spend_bundle = build_spend_bundle(coin_3, solution_1) r = run(remote.push_tx(tx=spend_bundle)) assert r.args[0].startswith( "exception: (<Err.ASSERT_MY_COIN_ID_FAILED")
def test_p2_conditions(self): payments, conditions = default_payments_and_conditions() puzzle_hash = ProgramHash( p2_conditions.puzzle_for_conditions(conditions)) solution = p2_conditions.solution_for_conditions(conditions) run_test(puzzle_hash, solution, payments)
def test_rl_spend_all(): remote = make_client_server() run = asyncio.get_event_loop().run_until_complete # A gives B some money, but B can only send that money to C (and generate change for itself) wallet_a = RLWallet() wallet_b = RLWallet() wallet_c = RLWallet() wallets = [wallet_a, wallet_b, wallet_c] limit = 100 interval = 1 commit_and_notify(remote, wallets, wallet_a) origin_coin = wallet_a.my_utxos.copy().pop() wallet_b_pk = wallet_b.get_next_public_key().serialize() wallet_b.set_origin(origin_coin) wallet_b.limit = limit wallet_b.interval = interval clawback_pk = wallet_a.get_next_public_key().serialize() clawback_pk = hexbytes(clawback_pk) wallet_b.rl_clawback_pk = clawback_pk rl_puzzle = wallet_b.rl_puzzle_for_pk(wallet_b_pk, limit, interval, origin_coin.name(), clawback_pk) rl_puzzlehash = ProgramHash(rl_puzzle) wallet_a.clawback_puzzlehash = rl_puzzlehash wallet_a.rl_receiver_pk = wallet_b_pk wallet_a.clawback_pk = clawback_pk wallet_a.clawback_interval = interval wallet_a.clawback_limit = limit wallet_a.clawback_origin = origin_coin.name() # wallet A is normal wallet, it sends coin that's rate limited to wallet B amount = 300 spend_bundle = wallet_a.generate_signed_transaction_with_origin( amount, rl_puzzlehash, origin_coin.name()) _ = run(remote.push_tx(tx=spend_bundle)) commit_and_notify(remote, wallets, Wallet()) assert wallet_a.current_balance == 999999700 assert wallet_b.current_rl_balance == 300 assert wallet_c.current_balance == 0 commit_and_notify(remote, wallets, Wallet()) assert wallet_b.rl_available_balance() == 100 commit_and_notify(remote, wallets, Wallet()) assert wallet_b.rl_available_balance() == 200 commit_and_notify(remote, wallets, Wallet()) assert wallet_b.rl_available_balance() == 300 amount = 300 spend_bundle = wallet_b.rl_generate_signed_transaction( amount, wallet_c.get_new_puzzlehash()) _ = run(remote.push_tx(tx=spend_bundle)) commit_and_notify(remote, wallets, Wallet()) assert wallet_a.current_balance == 999999700 assert wallet_b.current_rl_balance == 0 assert wallet_c.current_balance == 300
def get_keys(self, hash): for child in range(self.next_address): pubkey = self.extended_secret_key.public_child(child) if hash == ProgramHash( self.get_new_puzzle_with_params(bytes(pubkey), self.get_stake_factor(), self.get_escrow_duration(), self.get_duration_type())): return pubkey, self.extended_secret_key.private_child(child)
def get_keys(self, hash): s = super().get_keys(hash) if s is not None: return s for child in reversed(range(self.next_address)): pubkey = self.extended_secret_key.public_child(child) if hash == ProgramHash( self.rl_puzzle_for_pk(bytes(pubkey), self.limit, self.interval, self.rl_origin, self.rl_clawback_pk)): return pubkey, self.extended_secret_key.private_child(child)
def can_generate_puzzle_hash(self, hash): return any( map( lambda child: hash == ProgramHash( self.get_new_puzzle_with_params( self.extended_secret_key.public_child(child). get_public_key().serialize(), self.get_stake_factor(), self.get_escrow_duration())), reversed(range(self.next_address))))
def get_keys_for_escrow_puzzle(self, hash): for child in range(self.next_address): pubkey = self.extended_secret_key.public_child(child) escrow_hash = ProgramHash( self.get_escrow_puzzle_with_params( bytes(self.get_recovery_public_key()), bytes(pubkey), self.get_escrow_duration(), self.get_duration_type())) if hash == escrow_hash: return pubkey, self.extended_secret_key.private_child(child)
def can_generate_rl_puzzle_hash(self, hash): if self.rl_origin is None: return None if self.rl_clawback_pk is None: return None return any(map(lambda child: hash == ProgramHash(self.rl_puzzle_for_pk( bytes(self.extended_secret_key.public_child(child)), self.limit, self.interval, self.rl_origin, self.rl_clawback_pk)), reversed(range(self.next_address))))
async def spend_coins(wallet, ledger_api): puzzlehash_string = input('Enter PuzzleHash: ') puzzlehash = ProgramHash.from_bytes(bytes.fromhex(puzzlehash_string)) amount = int(input('Amount: ')) if amount > wallet.current_balance or amount < 0: print('Insufficient funds') return None tx = wallet.generate_signed_transaction(amount, puzzlehash) if tx is not None: await ledger_api.push_tx(tx=tx)
def puzzlehash_from_string(puzhash): if hasattr(puzhash, 'decode'): # check if serialized puz = puzhash.decode("utf-8") else: puz = puzhash try: ret = ProgramHash(bytes.fromhex(puz)) except Exception: raise Exception return ret