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
Exemplo n.º 2
0
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 test_cp_with_permission():
    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())
    unlock_time = 5
    wallet_b.pubkey_permission = pub_a
    wallet_b.unlock_time = unlock_time
    wallet_a.pubkey_approval = pub_a
    b_puzzle = wallet_b.cp_puzzle(pub_b, pub_a, unlock_time)
    b_puzzlehash = ProgramHash(b_puzzle)

    commit_and_notify(remote, wallets, wallet_a)
    # Set time to 4, time needs to exceed 5, unless there is approval from authorizer
    _ = run(remote.skip_milliseconds(ms=uint64(4).to_bytes(4, 'big')))

    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

    puzzlehash_c = wallet_c.get_new_puzzlehash()
    amount = 100
    mode = 2
    transaction = wallet_b.cp_generate_unsigned_transaction(
        puzzlehash_c, amount, mode)
    solution = transaction[0][1].solution
    approval_a = wallet_a.cp_approval_signature_for_transaction(solution).sig
    spend_bundle = wallet_b.cp_generate_signed_transaction_with_approval(
        puzzlehash_c, amount, approval_a)
    _ = run(remote.push_tx(tx=spend_bundle))
    commit_and_notify(remote, wallets, Wallet())

    assert wallet_a.current_balance == 999999000
    assert wallet_b.cp_balance == 900
    assert wallet_c.current_balance == 100
Exemplo n.º 4
0
    def rl_puzzle_for_pk(self, pubkey, rate_amount, interval_time, origin_id,
                         clawback_pk):
        hex_pk = hexbytes(pubkey)
        #breakpoint()
        opcode_aggsig = hexlify(ConditionOpcode.AGG_SIG).decode('ascii')
        opcode_coin_block_age = hexlify(
            ConditionOpcode.ASSERT_BLOCK_AGE_EXCEEDS).decode('ascii')
        opcode_create = hexlify(ConditionOpcode.CREATE_COIN).decode('ascii')
        opcode_myid = hexlify(
            ConditionOpcode.ASSERT_MY_COIN_ID).decode('ascii')
        if (not origin_id):
            return None

        TEMPLATE_MY_PARENT_ID = "(sha256 (f (r (r (r (r (r (r (a)))))))) (f (r (a))) (uint64 (f (r (r (r (r (r (r (r (a)))))))))))"
        TEMPLATE_SINGLETON_RL = f"((c (i (i (= {TEMPLATE_MY_PARENT_ID} (f (a))) (q 1) (= (f (a)) (q 0x{origin_id}))) (q (c (q 1) (q ()))) (q (x (q \"Parent doesnt satisfy RL conditions\")))) (a)))"
        TEMPLATE_BLOCK_AGE = f"((c (i (i (= (* (f (r (r (r (r (r (a))))))) (q {rate_amount})) (* (f (r (r (r (r (a)))))) (q {interval_time}))) (q 1) (q (> (* (f (r (r (r (r (r (a))))))) (q {rate_amount})) (* (f (r (r (r (r (a))))))) (q {interval_time})))) (q (c (q 0x{opcode_coin_block_age}) (c (f (r (r (r (r (r (a))))))) (q ())))) (q (x (q \"wrong min block time\")))) (a) ))"
        TEMPLATE_MY_ID = f"(c (q 0x{opcode_myid}) (c (sha256 (f (a)) (f (r (a))) (uint64 (f (r (r (a)))))) (q ())))"
        CREATE_CHANGE = f"(c (q 0x{opcode_create}) (c (f (r (a))) (c (- (f (r (r (a)))) (f (r (r (r (r (a))))))) (q ()))))"
        CREATE_NEW_COIN = f"(c (q 0x{opcode_create}) (c (f (r (r (r (a))))) (c (f (r (r (r (r (a)))))) (q ()))))"
        RATE_LIMIT_PUZZLE = f"(c {TEMPLATE_SINGLETON_RL} (c {TEMPLATE_BLOCK_AGE} (c {CREATE_CHANGE} (c {TEMPLATE_MY_ID} (c {CREATE_NEW_COIN} (q ()))))))"

        TEMPLATE_MY_PARENT_ID_2 = "(sha256 (f (r (r (r (r (r (r (r (r (a)))))))))) (f (r (a))) (uint64 (f (r (r (r (r (r (r (r (a)))))))))))"
        TEMPLATE_SINGLETON_RL_2 = f"((c (i (i (= {TEMPLATE_MY_PARENT_ID_2} (f (r (r (r (r (r (a)))))))) (q 1) (= (f (r (r (r (r (r (a))))))) (q 0x{origin_id}))) (q (c (q 1) (q ()))) (q (x (q \"Parent doesnt satisfy RL conditions\")))) (a)))"
        CREATE_CONSOLIDATED = f"(c (q 0x{opcode_create}) (c (f (r (a))) (c (+ (f (r (r (r (r (a)))))) (f (r (r (r (r (r (r (a))))))))) (q ()))))"
        MODE_TWO_ME_STRING = f"(c (q 0x{opcode_myid}) (c (sha256 (f (r (r (r (r (r (a))))))) (f (r (a))) (uint64 (f (r (r (r (r (r (r (a)))))))))) (q ())))"
        CREATE_LOCK = f"(c (q 0x{opcode_create}) (c (sha256 (wrap (c (q 7) (c (c (q 5) (c (c (q 1) (c (sha256 (f (r (r (a)))) (f (r (r (r (a))))) (uint64 (f (r (r (r (r (a)))))))) (q ()))) (c (q (q ())) (q ())))) (q ()))))) (c (uint64 (q 0)) (q ()))))"
        MODE_TWO = f"(c {TEMPLATE_SINGLETON_RL_2} (c {MODE_TWO_ME_STRING} (c {CREATE_LOCK} (c {CREATE_CONSOLIDATED} (q ())))))"

        AGGSIG_ENTIRE_SOLUTION = f"(c (q 0x{opcode_aggsig}) (c (q 0x{hex_pk}) (c (sha256 (wrap (a))) (q ()))))"

        WHOLE_PUZZLE = f"(c {AGGSIG_ENTIRE_SOLUTION} ((c (i (= (f (a)) (q 1)) (q ((c (q {RATE_LIMIT_PUZZLE}) (r (a))))) (q {MODE_TWO})) (a))) (q ()))"
        CLAWBACK = f"(c (c (q 0x{opcode_aggsig}) (c (q 0x{clawback_pk}) (c (sha256 (wrap (a))) (q ())))) (r (a)))"
        WHOLE_PUZZLE_WITH_CLAWBACK = f"((c (i (= (f (a)) (q 3)) (q {CLAWBACK}) (q {WHOLE_PUZZLE})) (a)))"

        return Program(binutils.assemble(WHOLE_PUZZLE_WITH_CLAWBACK))
Exemplo n.º 5
0
 def get_keys_pk(self, clawback_pubkey):
     for child in reversed(range(self.next_address)):
         pubkey = self.extended_secret_key.public_child(
             child).get_public_key()
         if hexbytes(pubkey.serialize()) == clawback_pubkey:
             return pubkey, self.extended_secret_key.private_child(
                 child).get_private_key()
Exemplo n.º 6
0
 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
Exemplo n.º 7
0
    def generate_recovery_transaction(self, coins, root_public_key, secret_key,
                                      escrow_duration):
        recovery_pubkey = root_public_key.public_child(
            0).get_public_key().serialize()
        signatures = []
        coin_solutions = []
        secret_key = BLSPrivateKey(secret_key)
        for coin in coins:
            pubkey = self.find_pubkey_for_escrow_puzzle(
                coin, root_public_key, escrow_duration)
            puzzle = self.get_escrow_puzzle_with_params(
                recovery_pubkey, pubkey.serialize(), escrow_duration)

            op_create_coin = ConditionOpcode.CREATE_COIN[0]
            puzzlehash = f'0x' + str(hexbytes(self.get_new_puzzlehash()))
            solution_src = sexp(
                quote(sexp(sexp(op_create_coin, puzzlehash, coin.amount))),
                sexp(), 1)
            solution = Program(binutils.assemble(solution_src))

            puzzle_solution_list = clvm.to_sexp_f([puzzle, solution])
            coin_solution = CoinSolution(coin, puzzle_solution_list)
            coin_solutions.append(coin_solution)

            conditions_dict = conditions_by_opcode(
                conditions_for_solution(puzzle_solution_list))
            for _ in hash_key_pairs_for_conditions_dict(conditions_dict):
                signature = secret_key.sign(_.message_hash)
                signatures.append(signature)

        coin_solution_list = CoinSolutionList(coin_solutions)
        aggsig = BLSSignature.aggregate(signatures)
        spend_bundle = SpendBundle(coin_solution_list, aggsig)
        return spend_bundle
Exemplo n.º 8
0
 def get_backup_string(self):
     d = dict()
     d['root_public_key'] = self.get_recovery_hd_root_public_key(
     ).serialize()
     d['secret_key'] = self.get_recovery_private_key().serialize()
     d['escrow_duration'] = self.get_escrow_duration()
     d['stake_factor'] = self.get_stake_factor().as_tuple()
     return str(hexbytes(cbor.dumps(d)))
Exemplo n.º 9
0
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
Exemplo n.º 10
0
 def can_generate_cp_puzzle_hash(self, hash):
     if self.pubkey_permission is None:
         return None
     return any(
         map(
             lambda child: hash == ProgramHash(
                 self.cp_puzzle(
                     hexbytes(self.extended_secret_key.public_child(child)),
                     self.pubkey_permission, self.unlock_time)),
             reversed(range(self.next_address))))
Exemplo n.º 11
0
 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.cp_puzzle(hexbytes(pubkey), self.pubkey_permission,
                                self.unlock_time)):
             return pubkey, self.extended_secret_key.private_child(child)
def test_cp_send_solo():
    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 = 3
    b_puzzle = wallet_b.cp_puzzle(pub_b, pub_a, 3)
    b_puzzlehash = ProgramHash(b_puzzle)

    # Set ledger api to
    _ = run(remote.skip_milliseconds(ms=uint64(4).to_bytes(4, 'big')))

    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

    puzzlehash_c = wallet_c.get_new_puzzlehash()
    spend_bundle = wallet_b.cp_generate_signed_transaction(puzzlehash_c, 100)
    _ = run(remote.push_tx(tx=spend_bundle))
    commit_and_notify(remote, wallets, Wallet())

    assert wallet_a.current_balance == 999999000
    assert wallet_b.cp_balance == 900
    assert wallet_c.current_balance == 100
Exemplo n.º 13
0
async def main_loop():
    ledger_api = await connect_to_ledger_sim("localhost", 9868)
    selection = ""
    wallet = CPWallet()
    most_recent_header = None
    print_leaf()
    print()
    print("Welcome to your Chia Custody Wallet.")
    print()
    my_pubkey_orig = wallet.get_next_public_key().serialize()
    wallet.pubkey_approval = hexbytes(wallet.get_next_public_key().serialize())
    wallet.pubkey_orig = my_pubkey_orig
    print("Your pubkey is: " + hexlify(my_pubkey_orig).decode('ascii'))

    while selection != "q":
        print()
        print(divider)
        print(" \u2447 Menu \u2447")
        print()
        tip = await ledger_api.get_tip()
        print("Block: ", tip["tip_index"])
        print()
        print("Select a function:")
        print("\u2448 1 Wallet Details")
        print("\u2448 2 View Funds")
        print("\u2448 3 Get Update")
        print("\u2448 4 *GOD MODE* Farm Block / Get Money")
        print("\u2448 5 Create Custody")
        print("\u2448 6 Move Custody")
        print("\u2448 7 Approve Transaction")
        print("\u2448 q Quit")
        print(divider)
        print()

        selection = input(prompt)
        if selection == "1":
            await print_my_details(wallet, ledger_api)
        elif selection == "2":
            view_funds(wallet)
        elif selection == "3":
            most_recent_header = await update_ledger(wallet, ledger_api,
                                                     most_recent_header)
        elif selection == "4":
            most_recent_header = await new_block(wallet, ledger_api)
        elif selection == "5":
            await create_custody(wallet, ledger_api)
        elif selection == "6":
            await move_custody(wallet, ledger_api)
        elif selection == "7":
            await approve_transaction(wallet)
Exemplo n.º 14
0
 def cp_generate_unsigned_transaction(self, new_puzzle_hash, amount, mode):
     outputs = []
     output = new_puzzle_hash, amount
     outputs.append(output)
     change = self.cp_coin.amount - amount
     if change > 0:
         change_output = self.cp_coin.puzzle_hash, change
         outputs.append(change_output)
     spends = []
     puzzle_hash = self.cp_coin.puzzle_hash
     pubkey, secretkey = self.get_keys(puzzle_hash)
     puzzle = self.cp_puzzle(hexbytes(pubkey), self.pubkey_permission,
                             self.unlock_time)
     if mode == 1:
         solution = self.solution_for_cp_solo(outputs)
     else:
         solution = self.solution_for_cp_permission(outputs)
     spends.append((puzzle, CoinSolution(self.cp_coin, solution)))
     return spends
Exemplo n.º 15
0
async def create_rl_coin(wallet, ledger_api):
    utxo_list = list(wallet.my_utxos)
    if len(utxo_list) == 0:
        print("No UTXOs available.")
        return
    print("Select UTXO for origin: ")
    num = 0
    for utxo in utxo_list:
        print(f"{num}) coin_name:{utxo.name()} amount:{utxo.amount}")
        num += 1
    selected = get_int("Select UTXO for origin: ")
    origin = utxo_list[selected]
    print("Rate limit is defined as amount of Chia per time interval.(Blocks)\n")
    rate = get_int("Specify the Chia amount limit: ")
    interval = get_int("Specify the interval length (blocks): ")
    print("Specify the pubkey of receiver")
    pubkey = input(prompt)
    my_pubkey = hexbytes(wallet.get_next_public_key().serialize())
    send_amount = get_int("Enter amount to give recipient: ")
    print(f"\n\nInitialization string: {origin.parent_coin_info}:{origin.puzzle_hash}:"
          f"{origin.amount}:{origin.name()}:{rate}:{interval}:{my_pubkey}")
    print("\nPaste Initialization string to the receiver")
    print("Press Enter to continue:")
    input(prompt)
    pubkey = PublicKey.from_bytes(bytes.fromhex(pubkey)).serialize()
    rl_puzzle = wallet.rl_puzzle_for_pk(pubkey, rate, interval, origin.name(), my_pubkey)
    rl_puzzlehash = ProgramHash(rl_puzzle)
    wallet.clawback_puzzlehash = rl_puzzlehash
    wallet.clawback_origin = origin.name()
    wallet.clawback_limit = rate
    wallet.clawback_interval = interval
    wallet.clawback_pk = my_pubkey
    wallet.rl_receiver_pk = pubkey

    spend_bundle = wallet.generate_signed_transaction_with_origin(send_amount, rl_puzzlehash, origin.name())
    _ = await ledger_api.push_tx(tx=spend_bundle)
Exemplo n.º 16
0
 def get_keys_pk(self, approval_pubkey):
     for child in reversed(range(self.next_address)):
         pubkey = self.extended_secret_key.public_child(child)
         if hexbytes(pubkey) == approval_pubkey:
             return pubkey, self.extended_secret_key.private_child(child)
def puzzle_for_tree_hash(tree_hash):
    TEMPLATE = """
        (q 0x%s)
    """
    return Program(binutils.assemble(TEMPLATE % hexbytes(tree_hash)))
Exemplo n.º 18
0
 def to_hexbytes(s):
     if isinstance(s, bytes):
         return hexbytes(s)
     return s