Пример #1
0
 def as_create_spend_bundle(self,
                            as_puzzlehash,
                            as_amount,
                            as_timelock_block,
                            as_secret_hash,
                            as_pubkey_sender=None,
                            as_pubkey_receiver=None,
                            who=None,
                            as_sec_to_try=None):
     utxos = self.as_select_coins(as_amount, as_puzzlehash)
     spends = []
     for coin in utxos:
         puzzle = self.as_make_puzzle(as_pubkey_sender, as_pubkey_receiver,
                                      as_amount, as_timelock_block,
                                      as_secret_hash)
         if who == "sender":
             solution = self.as_make_solution_sender()
         elif who == "receiver":
             solution = self.as_make_solution_receiver(as_sec_to_try)
         pair = solution.to([puzzle, solution])
         signer = self.make_signer()
         spend_bundle = build_spend_bundle(coin,
                                           Program(pair),
                                           sign_f=signer)
         spends.append(spend_bundle)
     return SpendBundle.aggregate(spends)
Пример #2
0
def test_farm_block_one_spendbundle():
    REWARD = 10000
    unspent_db = RAM_DB()
    chain_view = ChainView.for_genesis_hash(GENESIS_BLOCK, unspent_db)

    pos = ProofOfSpace(get_pool_public_key(), get_plot_public_key())

    puzzle_hash = puzzle_hash_for_index(1)

    empty_spend_bundle = SpendBundle.aggregate([])
    header, header_signature, body = farm_block(GENESIS_BLOCK,
                                                Signature.zero(), 1, pos,
                                                empty_spend_bundle,
                                                puzzle_hash, REWARD)
    coinbase_coin = body.coinbase_coin

    conditions = standard_conditions()
    spend_bundle = spend_coin(coin=coinbase_coin,
                              conditions=conditions,
                              index=1)

    header, header_signature, body = farm_block(GENESIS_BLOCK,
                                                Signature.zero(), 1, pos,
                                                spend_bundle, puzzle_hash,
                                                REWARD)
    removals = removals_for_body(body)
    assert len(removals) == 1
    assert removals[0] == list(spend_bundle.coin_solutions)[0].coin.name()

    run = asyncio.get_event_loop().run_until_complete
    additions, removals = run(
        chain_view.accept_new_block(header, unspent_db, REWARD, 0))
    assert len(additions) == 4
    assert len(removals) == 1
Пример #3
0
def farm_new_block(previous_header: HeaderHash, previous_signature: Signature,
                   block_index: int, proof_of_space: ProofOfSpace,
                   spend_bundle: SpendBundle, coinbase_coin: Coin,
                   coinbase_signature: BLSSignature,
                   fees_puzzle_hash: ProgramHash, timestamp: uint64):
    """
    Steps:
        - collect up a consistent set of removals and solutions
        - run solutions to get the additions
        - select a timestamp = max(now, minimum_legal_timestamp)
        - create blank extension data
        - collect up coinbase coin with coinbase signature (if solo mining, we get these locally)
        - return Header, Body
    """

    program_cost = 0

    assert validate_spend_bundle_signature(spend_bundle)
    solution_program = best_solution_program(spend_bundle)
    extension_data = std_hash(b'')

    block_index_hash = block_index.to_bytes(32, "big")
    fees_coin = Coin(block_index_hash, fees_puzzle_hash, spend_bundle.fees())
    body = Body(coinbase_signature, coinbase_coin, fees_coin, solution_program,
                program_cost, spend_bundle.aggregated_signature)

    header = Header(previous_header, previous_signature, timestamp,
                    proof_of_space, body, extension_data)
    return header, body
Пример #4
0
def test_farm_two_blocks():
    """
    In this test, we farm two blocks: one empty block,
    then one block which spends the coinbase transaction from the empty block.
    """
    REWARD = 10000
    unspent_db = RAM_DB()
    chain_view = ChainView.for_genesis_hash(GENESIS_BLOCK, unspent_db)

    assert chain_view.genesis_hash == GENESIS_BLOCK
    assert chain_view.tip_hash == HeaderHash(GENESIS_BLOCK)
    assert chain_view.tip_index == 0
    assert chain_view.unspent_db == unspent_db

    pos_1 = ProofOfSpace(get_pool_public_key(), get_plot_public_key())

    puzzle_hash = puzzle_hash_for_index(1)

    empty_spend_bundle = SpendBundle.aggregate([])
    header, header_signature, body = farm_block(GENESIS_BLOCK,
                                                Signature.zero(), 1, pos_1,
                                                empty_spend_bundle,
                                                puzzle_hash, REWARD)

    run = asyncio.get_event_loop().run_until_complete
    additions, removals = run(
        chain_view.accept_new_block(header, unspent_db, REWARD, 0))
    assert len(additions) == 2
    assert len(removals) == 0
    # TODO: check additions
    assert additions[1].puzzle_hash == body.fees_coin.puzzle_hash
    assert additions[1].amount == 0

    chain_view = run(
        chain_view.augment_chain_view(header, header_signature, unspent_db,
                                      unspent_db, REWARD, 0))

    assert chain_view.genesis_hash == GENESIS_BLOCK
    assert chain_view.tip_hash == HeaderHash(header)
    assert chain_view.tip_index == 1
    assert chain_view.unspent_db == unspent_db

    conditions = standard_conditions()
    spend_bundle_2 = spend_coin(coin=additions[0],
                                conditions=conditions,
                                index=1)

    assert validate_spend_bundle_signature(spend_bundle_2)

    pos_2 = ProofOfSpace(get_pool_public_key(1), get_plot_public_key())

    header_2, header_signature_2, body_2 = farm_block(header, header_signature,
                                                      2, pos_2, spend_bundle_2,
                                                      puzzle_hash, REWARD)
    print(header_2)
    print(header_signature_2)

    removals = removals_for_body(body_2)
    assert len(removals) == 1
    assert removals[0] == list(spend_bundle_2.coin_solutions)[0].coin.name()
Пример #5
0
    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)
Пример #6
0
    async def new_chain_view(self, chain_view, spend_bundles,
                             coinbase_puzzle_hash, fees_puzzle_hash, storage,
                             unspent_db):
        block_number = chain_view.tip_index + 1

        REWARD = int(1e9)
        timestamp = uint64(self._now / 1000)

        pool_public_key = get_pool_public_key()
        plot_public_key = get_plot_public_key()

        pos = ProofOfSpace(pool_public_key, plot_public_key)
        coinbase_coin, coinbase_signature = create_coinbase_coin_and_signature(
            block_number, coinbase_puzzle_hash, REWARD, pool_public_key)

        spend_bundle = SpendBundle.aggregate(spend_bundles)

        header, body = farm_new_block(chain_view.tip_hash,
                                      chain_view.tip_signature, block_number,
                                      pos, spend_bundle, coinbase_coin,
                                      coinbase_signature, fees_puzzle_hash,
                                      timestamp)

        header_signature = sign_header(header, plot_public_key)

        [await storage.add_preimage(bytes(_)) for _ in (header, body)]

        chain_view = await chain_view.augment_chain_view(
            header, header_signature, storage, unspent_db, REWARD, self._now)

        return chain_view
Пример #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
Пример #8
0
 def sign_clawback_transaction(self, spends: (Program, [CoinSolution]), clawback_pubkey):
     sigs = []
     for puzzle, solution in spends:
         pubkey, secretkey = self.get_keys_pk(clawback_pubkey)
         signature = secretkey.sign(
             ProgramHash(Program(solution.solution)))
         sigs.append(signature)
     aggsig = BLSSignature.aggregate(sigs)
     solution_list = CoinSolutionList(
         [CoinSolution(coin_solution.coin, clvm.to_sexp_f([puzzle, coin_solution.solution])) for
          (puzzle, coin_solution) in spends])
     spend_bundle = SpendBundle(solution_list, aggsig)
     return spend_bundle
Пример #9
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)
Пример #10
0
 def ap_sign_transaction(self, spends: (Program, [CoinSolution]), signatures_from_a):
     sigs = []
     for puzzle, solution in spends:
         pubkey, secretkey = self.get_keys(
             solution.coin.puzzle_hash, self.a_pubkey)
         signature = secretkey.sign(
             ProgramHash(Program(solution.solution)))
         sigs.append(signature)
     for s in signatures_from_a:
         sigs.append(s)
     aggsig = BLSSignature.aggregate(sigs)
     solution_list = CoinSolutionList(
         [CoinSolution(coin_solution.coin, clvm.to_sexp_f([puzzle, coin_solution.solution])) for
          (puzzle, coin_solution) in spends])
     spend_bundle = SpendBundle(solution_list, aggsig)
     return spend_bundle
Пример #11
0
 def sign_transaction(self, spends: (Program, [CoinSolution])):
     sigs = []
     for puzzle, solution in spends:
         pubkey, secretkey = self.get_keys(solution.coin.puzzle_hash)
         code_ = [puzzle, solution.solution]
         sexp = clvm.to_sexp_f(code_)
         conditions_dict = conditions_by_opcode(
             conditions_for_solution(sexp))
         for _ in hash_key_pairs_for_conditions_dict(conditions_dict):
             signature = secretkey.sign(_.message_hash)
             sigs.append(signature)
     aggsig = BLSSignature.aggregate(sigs)
     solution_list = CoinSolutionList(
         [CoinSolution(coin_solution.coin, clvm.to_sexp_f([puzzle, coin_solution.solution])) for
          (puzzle, coin_solution) in spends])
     spend_bundle = SpendBundle(solution_list, aggsig)
     return spend_bundle
Пример #12
0
 def cp_sign_transaction(self,
                         spends: (Program, [CoinSolution]),
                         approval=None):
     sigs = []
     for puzzle, solution in spends:
         pubkey, secretkey = self.get_keys(solution.coin.puzzle_hash)
         signature = secretkey.sign(ProgramHash(Program(solution.solution)))
         sigs.append(signature)
     if approval is not None:
         app = BLSSignature(approval)
         sigs.append(app)
     aggsig = BLSSignature.aggregate(sigs)
     solution_list = CoinSolutionList([
         CoinSolution(coin_solution.coin,
                      clvm.to_sexp_f([puzzle, coin_solution.solution]))
         for (puzzle, coin_solution) in spends
     ])
     spend_bundle = SpendBundle(solution_list, aggsig)
     return spend_bundle
Пример #13
0
def test_farm_block_empty():
    REWARD = 10000
    unspent_db = RAM_DB()
    chain_view = ChainView.for_genesis_hash(GENESIS_BLOCK, unspent_db)

    pos = ProofOfSpace(get_pool_public_key(), get_plot_public_key())

    puzzle_hash = puzzle_hash_for_index(1)

    spend_bundle = SpendBundle.aggregate([])

    header, header_signature, body = farm_block(GENESIS_BLOCK,
                                                Signature.zero(), 1, pos,
                                                spend_bundle, puzzle_hash,
                                                REWARD)
    removals = removals_for_body(body)
    assert len(removals) == 0

    run = asyncio.get_event_loop().run_until_complete
    additions, removals = run(
        chain_view.accept_new_block(header, unspent_db, REWARD, 0))
    assert len(additions) == 2
    assert len(removals) == 0
Пример #14
0
def build_spend_bundle(coin, solution, sign_f=DEFAULT_SIGNER):
    coin_solution = CoinSolution(coin, solution)
    signature = signature_for_solution(solution, sign_f)
    return SpendBundle([coin_solution], signature)
Пример #15
0
def collect_best_bundle(known_bundles) -> SpendBundle:
    # this is way too simple
    spend_bundle = SpendBundle.aggregate(known_bundles)
    assert spend_bundle.fees() >= 0
    return spend_bundle
Пример #16
0
def finalize_pst(wallet, pst, sigs):
    """
    Return a pair (SpendBundle or None, summary_list).

    If we have a finalized SpendBundle, it's returned, otherwise None,
    The summary_list item is a list of items (coin, hkp_list, sigs_to_use, m)
    which allows the UI to give the end user information about which
    coins still need signatures.

    Note that hkp is short for hash_key_pair (ie. aggsig pair)
    """
    m = wallet.m()
    coin_solutions = []
    sig_dict = sigs_to_aggsig_sig_dict(wallet, pst, sigs)

    all_sigs_to_use = []

    summary_list = []

    for coin_solution in pst.get("coin_solutions"):
        coin, solution = coin_solution.coin, coin_solution.solution
        # run maximal_solution and get conditions
        conditions_dict = conditions_dict_for_solution(solution)
        # look for AGG_SIG conditions
        hkp_list = hash_key_pairs_for_conditions_dict(conditions_dict)
        # see if we have enough info to build signatures
        found_list = []
        sigs_to_use = []
        for aggsig_pair in hkp_list:
            add_me = 0
            if len(sigs_to_use) < m:
                if aggsig_pair in sig_dict:
                    sigs_to_use.append(sig_dict[aggsig_pair])
                    add_me = 1
            found_list.append(add_me)

        all_sigs_to_use.extend(sigs_to_use)

        conditions = pst.get("conditions")
        delegated_puzzle = puzzle_for_conditions(conditions)
        delegated_solution = solution_for_conditions(conditions)

        index = wallet.index_for_puzzle_hash(coin.puzzle_hash, GAP_LIMIT)
        pub_keys = wallet.pub_keys_for_index(index)
        actual_solution = solution_for_delegated_puzzle(
            m, pub_keys, found_list, delegated_puzzle, delegated_solution
        )

        coin_solution = CoinSolution(coin, actual_solution)
        coin_solutions.append(coin_solution)
        summary = (coin, hkp_list, sigs_to_use, m)
        summary_list.append(summary)

    if len(all_sigs_to_use) > 0:
        aggregated_sig = all_sigs_to_use[0].aggregate(all_sigs_to_use)
        spend_bundle = SpendBundle(coin_solutions, aggregated_sig)
        try:
            if validate_spend_bundle_signature(spend_bundle):
                return spend_bundle, summary_list
        except Exception:
            pass

    return None, summary_list
Пример #17
0
def build_spend_bundle(coin, solution, keychain=DEFAULT_KEYCHAIN):
    coin_solution = CoinSolution(coin, solution)
    signature = keychain.signature_for_solution(solution)
    return SpendBundle([coin_solution], signature)
Пример #18
0
 def fuzz_signature(spend_bundle: SpendBundle):
     bls_private_key = bls_private_key_for_index(0)
     signature = bls_private_key.sign(b'\x11' * 32)
     return SpendBundle(spend_bundle.coin_solutions, signature)