def test_cached_bls(self):
        n_keys = 10
        seed = b"a" * 31
        sks = [AugSchemeMPL.key_gen(seed + bytes([i])) for i in range(n_keys)]
        pks = [bytes(sk.get_g1()) for sk in sks]

        msgs = [("msg-%d" % (i,)).encode() for i in range(n_keys)]
        sigs = [AugSchemeMPL.sign(sk, msg) for sk, msg in zip(sks, msgs)]
        agg_sig = AugSchemeMPL.aggregate(sigs)

        pks_half = pks[: n_keys // 2]
        msgs_half = msgs[: n_keys // 2]
        sigs_half = sigs[: n_keys // 2]
        agg_sig_half = AugSchemeMPL.aggregate(sigs_half)

        assert AugSchemeMPL.aggregate_verify([G1Element.from_bytes(pk) for pk in pks], msgs, agg_sig)

        # Verify with empty cache and populate it
        assert cached_bls.aggregate_verify(pks_half, msgs_half, agg_sig_half, True)
        # Verify with partial cache hit
        assert cached_bls.aggregate_verify(pks, msgs, agg_sig, True)
        # Verify with full cache hit
        assert cached_bls.aggregate_verify(pks, msgs, agg_sig)

        # Use a small cache which can not accommodate all pairings
        local_cache = LRUCache(n_keys // 2)
        # Verify signatures and cache pairings one at a time
        for pk, msg, sig in zip(pks_half, msgs_half, sigs_half):
            assert cached_bls.aggregate_verify([pk], [msg], sig, True, local_cache)
        # Verify the same messages with aggregated signature (full cache hit)
        assert cached_bls.aggregate_verify(pks_half, msgs_half, agg_sig_half, False, local_cache)
        # Verify more messages (partial cache hit)
        assert cached_bls.aggregate_verify(pks, msgs, agg_sig, False, local_cache)
Beispiel #2
0
    async def create_spend_bundle_relative_amount(self,
                                                  cc_amount,
                                                  zero_coin: Coin = None
                                                  ) -> Optional[SpendBundle]:
        # If we're losing value then get coloured coins with at least that much value
        # If we're gaining value then our amount doesn't matter
        if cc_amount < 0:
            cc_spends = await self.select_coins(abs(cc_amount))
        else:
            if zero_coin is None:
                return None
            cc_spends = set()
            cc_spends.add(zero_coin)

        if cc_spends is None:
            return None

        # Calculate output amount given relative difference and sum of actual values
        spend_value = sum([coin.amount for coin in cc_spends])
        cc_amount = spend_value + cc_amount

        # Loop through coins and create solution for innerpuzzle
        list_of_solutions = []
        output_created = None
        sigs: List[G2Element] = []
        for coin in cc_spends:
            if output_created is None:
                newinnerpuzhash = await self.get_new_inner_hash()
                innersol = self.standard_wallet.make_solution(
                    primaries=[{
                        "puzzlehash": newinnerpuzhash,
                        "amount": cc_amount
                    }])
                output_created = coin
            else:
                innersol = self.standard_wallet.make_solution(
                    consumed=[output_created.name()])
            innerpuz: Program = await self.inner_puzzle_for_cc_puzhash(
                coin.puzzle_hash)
            sigs = sigs + await self.get_sigs(innerpuz, innersol, coin.name())
            lineage_proof = await self.get_lineage_proof_for_coin(coin)
            puzzle_reveal = cc_puzzle_for_inner_puzzle(
                CC_MOD, self.cc_info.my_genesis_checker, innerpuz)
            # Use coin info to create solution and add coin and solution to list of CoinSolutions
            solution = [
                innersol,
                coin.as_list(),
                lineage_proof,
                None,
                None,
                None,
                None,
                None,
            ]
            full_solution = Program.to([puzzle_reveal, solution])

            list_of_solutions.append(CoinSolution(coin, full_solution))

        aggsig = AugSchemeMPL.aggregate(sigs)
        return SpendBundle(list_of_solutions, aggsig)
Beispiel #3
0
    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
Beispiel #4
0
    async def sign(self, spend_bundle: SpendBundle) -> SpendBundle:
        sigs: List[G2Element] = []
        for spend in spend_bundle.coin_spends:
            matched, puzzle_args = match_cat_puzzle(
                spend.puzzle_reveal.to_program())
            if matched:
                _, _, inner_puzzle = puzzle_args
                puzzle_hash = inner_puzzle.get_tree_hash()
                pubkey, private = await self.wallet_state_manager.get_keys(
                    puzzle_hash)
                synthetic_secret_key = calculate_synthetic_secret_key(
                    private, DEFAULT_HIDDEN_PUZZLE_HASH)
                error, conditions, cost = conditions_dict_for_solution(
                    spend.puzzle_reveal.to_program(),
                    spend.solution.to_program(),
                    self.wallet_state_manager.constants.MAX_BLOCK_COST_CLVM,
                )
                if conditions is not None:
                    synthetic_pk = synthetic_secret_key.get_g1()
                    for pk, msg in pkm_pairs_for_conditions_dict(
                            conditions, spend.coin.name(),
                            self.wallet_state_manager.constants.
                            AGG_SIG_ME_ADDITIONAL_DATA):
                        try:
                            assert bytes(synthetic_pk) == pk
                            sigs.append(
                                AugSchemeMPL.sign(synthetic_secret_key, msg))
                        except AssertionError:
                            raise ValueError(
                                "This spend bundle cannot be signed by the CAT wallet"
                            )

        agg_sig = AugSchemeMPL.aggregate(sigs)
        return SpendBundle.aggregate([spend_bundle, SpendBundle([], agg_sig)])
Beispiel #5
0
 async def generate_eve_spend(self, coin: Coin, full_puzzle: Program, innerpuz: Program):
     assert self.did_info.origin_coin is not None
     # innerpuz solution is (mode amount message new_puzhash)
     innersol = Program.to([1, coin.amount, [], innerpuz.get_tree_hash()])
     # full solution is (lineage_proof my_amount inner_solution)
     fullsol = Program.to(
         [
             [self.did_info.origin_coin.parent_coin_info, self.did_info.origin_coin.amount],
             coin.amount,
             innersol,
         ]
     )
     list_of_solutions = [CoinSpend(coin, full_puzzle, fullsol)]
     # sign for AGG_SIG_ME
     message = (
         Program.to([innerpuz.get_tree_hash(), coin.amount, []]).get_tree_hash()
         + coin.name()
         + self.wallet_state_manager.constants.AGG_SIG_ME_ADDITIONAL_DATA
     )
     pubkey = did_wallet_puzzles.get_pubkey_from_innerpuz(innerpuz)
     record: Optional[DerivationRecord] = await self.wallet_state_manager.puzzle_store.record_for_pubkey(pubkey)
     assert record is not None
     private = master_sk_to_wallet_sk_unhardened(self.wallet_state_manager.private_key, record.index)
     signature = AugSchemeMPL.sign(private, message)
     sigs = [signature]
     aggsig = AugSchemeMPL.aggregate(sigs)
     spend_bundle = SpendBundle(list_of_solutions, aggsig)
     return spend_bundle
async def sign_coin_solutions(
    coin_solutions: List[CoinSolution],
    secret_key_for_public_key_f: Callable[[bytes], Optional[PrivateKey]],
) -> SpendBundle:
    signatures = []

    for coin_solution in coin_solutions:
        # Get AGGSIG conditions
        err, conditions_dict, cost = conditions_dict_for_solution(
            coin_solution.solution)
        if err or conditions_dict is None:
            error_msg = f"Sign transaction failed, con:{conditions_dict}, error: {err}"
            raise ValueError(error_msg)

        # Create signature
        for _, msg in pkm_pairs_for_conditions_dict(conditions_dict,
                                                    bytes(coin_solution.coin)):
            secret_key = secret_key_for_public_key_f(_)
            if secret_key is None:
                e_msg = f"no secret key for {_}"
                raise ValueError(e_msg)
            assert bytes(secret_key.get_g1()) == bytes(_)
            signature = AugSchemeMPL.sign(secret_key, msg)
            signatures.append(signature)

    # Aggregate signatures
    aggsig = AugSchemeMPL.aggregate(signatures)
    return SpendBundle(coin_solutions, aggsig)
Beispiel #7
0
    async def respond_signature(self, response: harvester_protocol.RespondSignature):
        """
        Receives a signature on a block header hash, which is required for submitting
        a block to the blockchain.
        """
        header_hash = response.message
        proof_of_space: bytes32 = self.header_hash_to_pos[header_hash]
        validates: bool = False
        for sk in self._get_private_keys():
            pk = sk.get_g1()
            if pk == response.farmer_pk:
                agg_pk = ProofOfSpace.generate_plot_public_key(response.local_pk, pk)
                assert agg_pk == proof_of_space.plot_public_key
                farmer_share = AugSchemeMPL.sign(sk, header_hash, agg_pk)
                agg_sig = AugSchemeMPL.aggregate(
                    [response.message_signature, farmer_share]
                )
                validates = AugSchemeMPL.verify(agg_pk, header_hash, agg_sig)

                if validates:
                    break
        assert validates

        pos_hash: bytes32 = proof_of_space.get_hash()

        request = farmer_protocol.HeaderSignature(pos_hash, header_hash, agg_sig)
        yield OutboundMessage(
            NodeType.FULL_NODE, Message("header_signature", request), Delivery.BROADCAST
        )
Beispiel #8
0
    def sign_transaction(self, spends: List[Tuple[Program, CoinSolution]]):
        sigs = []
        solution: Program
        puzzle: Program
        for puzzle, solution in spends:  # type: ignore # noqa
            pubkey, secretkey = self.get_keys(solution.coin.puzzle_hash)
            code_ = [puzzle, solution.solution]
            sexp = Program.to(code_)
            err, con, cost = conditions_for_solution(sexp)
            if not con:
                return
            conditions_dict = conditions_by_opcode(con)

            for _, msg in pkm_pairs_for_conditions_dict(
                    conditions_dict, bytes(solution.coin)):
                signature = AugSchemeMPL.sign(secretkey, msg)
                sigs.append(signature)
        aggsig = AugSchemeMPL.aggregate(sigs)
        solution_list: List[CoinSolution] = [
            CoinSolution(coin_solution.coin,
                         Program.to([puzzle, coin_solution.solution]))
            for (puzzle, coin_solution) in spends
        ]
        spend_bundle = SpendBundle(solution_list, aggsig)
        return spend_bundle
Beispiel #9
0
def do_inspect_spend_bundle_cmd(ctx, bundles, print_results=True, **kwargs):
    if kwargs and (len(kwargs['spend']) > 0) and (len(kwargs['aggsig']) > 0):
        spend_bundle_objs = [
            SpendBundle(
                do_inspect_coin_spend_cmd(ctx,
                                          kwargs["spend"],
                                          print_results=False),
                AugSchemeMPL.aggregate([
                    G2Element(bytes.fromhex(sanitize_bytes(aggsig)))
                    for aggsig in kwargs["aggsig"]
                ]))
        ]
    else:
        spend_bundle_objs = []
        try:
            if type(bundles[0]) == str:
                spend_bundle_objs = streamable_load(SpendBundle, bundles)
            else:
                spend_bundle_objs = bundles
        except:
            print(
                "One or more of the specified objects was not a spend bundle")

    if print_results:
        inspect_callback(spend_bundle_objs,
                         ctx,
                         id_calc=(lambda e: e.name()),
                         type='SpendBundle')
    else:
        return spend_bundle_objs
Beispiel #10
0
def sign_messages_with_indexes(sign_ops: List[Dict[int, str]]) -> G2Element:
    signatures = []
    for _ in sign_ops:
        for index, message in _.items():
            sk = private_key_for_index(index)
            signatures.append(AugSchemeMPL.sign(sk, bytes(message, "utf-8")))
    return AugSchemeMPL.aggregate(signatures)
Beispiel #11
0
    async def sign_transaction(
            self, coin_solutions: List[CoinSolution]) -> SpendBundle:
        signatures = []

        for coin_solution in coin_solutions:
            await self.hack_populate_secret_key_for_puzzle_hash(
                coin_solution.coin.puzzle_hash)

            # Get AGGSIG conditions
            err, conditions_dict, cost = conditions_dict_for_solution(
                coin_solution.solution)
            if err or conditions_dict is None:
                error_msg = (
                    f"Sign transaction failed, con:{conditions_dict}, error: {err}"
                )
                self.log.error(error_msg)
                raise ValueError(error_msg)

            # Create signature
            for _, msg in pkm_pairs_for_conditions_dict(
                    conditions_dict, bytes(coin_solution.coin)):
                secret_key = self.secret_key_for_public_key(_)
                if secret_key is None:
                    e_msg = f"no secret key for {_}"
                    self.log.error(e_msg)
                    raise ValueError(e_msg)
                signature = AugSchemeMPL.sign(secret_key, msg)
                signatures.append(signature)

        # Aggregate signatures
        aggsig = AugSchemeMPL.aggregate(signatures)
        return SpendBundle(coin_solutions, aggsig)
    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
Beispiel #13
0
 async def generate_eve_spend(self, coin: Coin, full_puzzle: Program,
                              innerpuz: Program):
     assert self.did_info.origin_coin is not None
     # innerpuz solution is (mode amount message my_id my_puzhash parent_innerpuzhash_amounts_for_recovery_ids)
     innersol = Program.to([
         0, coin.amount, coin.puzzle_hash,
         coin.name(), coin.puzzle_hash, []
     ])
     # full solution is (parent_info my_amount innersolution)
     fullsol = Program.to([
         [
             self.did_info.origin_coin.parent_coin_info,
             self.did_info.origin_coin.amount
         ],
         coin.parent_coin_info,
         coin.amount,
         innersol,
     ])
     list_of_solutions = [CoinSolution(coin, full_puzzle, fullsol)]
     # sign for AGG_SIG_ME
     message = (
         Program.to([coin.amount, coin.puzzle_hash]).get_tree_hash() +
         coin.name() +
         self.wallet_state_manager.constants.AGG_SIG_ME_ADDITIONAL_DATA)
     pubkey = did_wallet_puzzles.get_pubkey_from_innerpuz(innerpuz)
     index = await self.wallet_state_manager.puzzle_store.index_for_pubkey(
         pubkey)
     private = master_sk_to_wallet_sk(self.wallet_state_manager.private_key,
                                      index)
     signature = AugSchemeMPL.sign(private, message)
     sigs = [signature]
     aggsig = AugSchemeMPL.aggregate(sigs)
     spend_bundle = SpendBundle(list_of_solutions, aggsig)
     return spend_bundle
Beispiel #14
0
    async def create_spend(self, puzhash: bytes32):
        assert self.did_info.current_inner is not None
        coins = await self.select_coins(1)
        assert coins is not None
        coin = coins.pop()
        # innerpuz solution is (mode amount new_puz identity my_puz)
        innersol: Program = Program.to([0, coin.amount, puzhash, coin.name(), coin.puzzle_hash])
        # full solution is (corehash parent_info my_amount innerpuz_reveal solution)
        innerpuz: Program = self.did_info.current_inner

        full_puzzle: Program = did_wallet_puzzles.create_fullpuz(
            innerpuz,
            self.did_info.my_did,
        )
        parent_info = await self.get_parent_for_coin(coin)
        assert parent_info is not None

        fullsol = Program.to(
            [
                [
                    parent_info.parent_name,
                    parent_info.inner_puzzle_hash,
                    parent_info.amount,
                ],
                coin.amount,
                innersol,
            ]
        )
        list_of_solutions = [CoinSolution(coin, full_puzzle, fullsol)]
        # sign for AGG_SIG_ME
        message = bytes(puzhash) + bytes(coin.name())
        pubkey = did_wallet_puzzles.get_pubkey_from_innerpuz(innerpuz)
        index = await self.wallet_state_manager.puzzle_store.index_for_pubkey(pubkey)
        private = master_sk_to_wallet_sk(self.wallet_state_manager.private_key, index)
        signature = AugSchemeMPL.sign(private, message)
        # assert signature.validate([signature.PkMessagePair(pubkey, message)])
        sigs = [signature]
        aggsig = AugSchemeMPL.aggregate(sigs)
        spend_bundle = SpendBundle(list_of_solutions, aggsig)

        did_record = TransactionRecord(
            confirmed_at_height=uint32(0),
            created_at_time=uint64(int(time.time())),
            to_puzzle_hash=puzhash,
            amount=uint64(coin.amount),
            fee_amount=uint64(0),
            confirmed=False,
            sent=uint32(0),
            spend_bundle=spend_bundle,
            additions=spend_bundle.additions(),
            removals=spend_bundle.removals(),
            wallet_id=self.wallet_info.id,
            sent_to=[],
            trade_id=None,
            type=uint32(TransactionType.OUTGOING_TX.value),
            name=token_bytes(),
        )
        await self.standard_wallet.push_transaction(did_record)
        return spend_bundle
 def aggregate(cls, spend_bundles) -> "SpendBundle":
     coin_spends: List[CoinSpend] = []
     sigs: List[G2Element] = []
     for bundle in spend_bundles:
         coin_spends += bundle.coin_spends
         sigs.append(bundle.aggregated_signature)
     aggregated_signature = AugSchemeMPL.aggregate(sigs)
     return cls(coin_spends, aggregated_signature)
 def aggregate(cls, spend_bundles) -> "SpendBundle":
     coin_solutions: List[CoinSolution] = []
     sigs = []
     for _ in spend_bundles:
         coin_solutions += _.coin_solutions
         sigs.append(_.aggregated_signature)
     aggregated_signature = AugSchemeMPL.aggregate(sigs)
     return cls(coin_solutions, aggregated_signature)
Beispiel #17
0
 def signature_for_solution(self, coin_solution: CoinSolution) -> 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()):
         signature = self.sign(bytes(public_key), message_hash)
         signatures.append(signature)
     return AugSchemeMPL.aggregate(signatures)
async def sign_coin_spends(
    coin_spends: List[CoinSpend],
    secret_key_for_public_key_f:
    Any,  # Potentially awaitable function from G1Element => Optional[PrivateKey]
    additional_data: bytes,
    max_cost: int,
) -> SpendBundle:
    """
    Sign_coin_spends runs the puzzle code with the given argument and searches the
    result for an AGG_SIG_ME condition, which it attempts to sign by requesting a
    matching PrivateKey corresponding with the given G1Element (public key) specified
    in the resulting condition output.

    It's important to note that as mentioned in the documentation about the standard
    spend that the public key presented to the secret_key_for_public_key_f function
    provided to sign_coin_spends must be prepared to do the key derivations required
    by the coin types it's allowed to spend (at least the derivation of the standard
    spend as done by calculate_synthetic_secret_key with DEFAULT_PUZZLE_HASH).

    If a coin performed a different key derivation, the pk presented to this function
    would be similarly alien, and would need to be tried against the first stage
    derived keys (those returned by master_sk_to_wallet_sk from the ['sk'] member of
    wallet rpc's get_private_key method).
    """
    signatures: List[blspy.G2Element] = []
    pk_list: List[blspy.G1Element] = []
    msg_list: List[bytes] = []
    for coin_spend in coin_spends:
        # Get AGG_SIG conditions
        err, conditions_dict, cost = conditions_dict_for_solution(
            coin_spend.puzzle_reveal, coin_spend.solution, max_cost)
        if err or conditions_dict is None:
            error_msg = f"Sign transaction failed, con:{conditions_dict}, error: {err}"
            raise ValueError(error_msg)

        # Create signature
        for pk_bytes, msg in pkm_pairs_for_conditions_dict(
                conditions_dict, coin_spend.coin.name(), additional_data):
            pk = blspy.G1Element.from_bytes(pk_bytes)
            pk_list.append(pk)
            msg_list.append(msg)
            if inspect.iscoroutinefunction(secret_key_for_public_key_f):
                secret_key = await secret_key_for_public_key_f(pk)
            else:
                secret_key = secret_key_for_public_key_f(pk)
            if secret_key is None:
                e_msg = f"no secret key for {pk}"
                raise ValueError(e_msg)
            assert bytes(secret_key.get_g1()) == bytes(pk)
            signature = AugSchemeMPL.sign(secret_key, msg)
            assert AugSchemeMPL.verify(pk, msg, signature)
            signatures.append(signature)

    # Aggregate signatures
    aggsig = AugSchemeMPL.aggregate(signatures)
    assert AugSchemeMPL.aggregate_verify(pk_list, msg_list, aggsig)
    return SpendBundle(coin_spends, aggsig)
Beispiel #19
0
 def signature_for_solution(self, solution, coin_name):
     signatures = []
     conditions = conditions_for_solution(solution)
     assert conditions[1] is not None
     conditions_dict = conditions_by_opcode(conditions[1])
     for pk, msg in pkm_pairs_for_conditions_dict(conditions_dict,
                                                  coin_name):
         signature = self.sign(pk, msg)
         signatures.append(signature)
     return AugSchemeMPL.aggregate(signatures)
Beispiel #20
0
    async def rl_sign_transaction(self, spends: List[CoinSolution]) -> SpendBundle:
        sigs = []
        for coin_solution in spends:
            pubkey, secretkey = await self.get_keys(coin_solution.coin.puzzle_hash)
            signature = AugSchemeMPL.sign(secretkey, coin_solution.solution.get_tree_hash())
            sigs.append(signature)

        aggsig = AugSchemeMPL.aggregate(sigs)

        return SpendBundle(spends, aggsig)
Beispiel #21
0
    async def combine_coins(self, coins):
        # Overall structure:
        # Create len-1 spends that just assert that the final coin is created with full value.
        # Create 1 spend for the final coin that asserts the other spends occurred and
        # Creates the new coin.

        beginning_balance = self.balance()
        beginning_coins = len(self.usable_coins)

        # We need the final coin to know what the announced coin name will be.
        final_coin = CoinWrapper(coins[-1].name(), self.puzzle_hash,
                                 sum(map(lambda x: x.amount, coins)),
                                 self.puzzle)

        destroyed_coin_solutions = []

        # Each coin wants agg_sig_me so we aggregate them at the end.
        signatures = []

        for c in coins[:-1]:
            announce_conditions = [
                # Each coin expects the final coin creation announcement
                [
                    ConditionOpcode.ASSERT_COIN_ANNOUNCEMENT,
                    std_hash(coins[-1].name() + final_coin.name())
                ]
            ]

            coin_solution, signature = c.create_standard_spend(
                self.sk_, announce_conditions)
            destroyed_coin_solutions.append(coin_solution)
            signatures.append(signature)

        final_coin_creation = [
            [ConditionOpcode.CREATE_COIN_ANNOUNCEMENT,
             final_coin.name()],
            [ConditionOpcode.CREATE_COIN, self.puzzle_hash, final_coin.amount],
        ]

        coin_solution, signature = coins[-1].create_standard_spend(
            self.sk_, final_coin_creation)
        destroyed_coin_solutions.append(coin_solution)
        signatures.append(signature)

        signature = AugSchemeMPL.aggregate(signatures)
        spend_bundle = SpendBundle(destroyed_coin_solutions, signature)

        pushed = await self.parent.push_tx(spend_bundle)

        # We should have the same amount of money.
        assert beginning_balance == self.balance()
        # We should have shredded n-1 coins and replaced one.
        assert len(self.usable_coins) == beginning_coins - (len(coins) - 1)

        return SpendResult(pushed)
    async def do_spend(
        self,
        sim: SpendSim,
        sim_client: SimClient,
        tail: Program,
        coins: List[Coin],
        lineage_proofs: List[Program],
        inner_solutions: List[Program],
        expected_result: Tuple[MempoolInclusionStatus, Err],
        reveal_limitations_program: bool = True,
        signatures: List[G2Element] = [],
        extra_deltas: Optional[List[int]] = None,
        additional_spends: List[SpendBundle] = [],
        limitations_solutions: Optional[List[Program]] = None,
        cost_str: str = "",
    ):
        if limitations_solutions is None:
            limitations_solutions = [Program.to([])] * len(coins)
        if extra_deltas is None:
            extra_deltas = [0] * len(coins)

        spendable_cat_list: List[SpendableCAT] = []
        for coin, innersol, proof, limitations_solution, extra_delta in zip(
            coins, inner_solutions, lineage_proofs, limitations_solutions, extra_deltas
        ):
            spendable_cat_list.append(
                SpendableCAT(
                    coin,
                    tail.get_tree_hash(),
                    acs,
                    innersol,
                    limitations_solution=limitations_solution,
                    lineage_proof=proof,
                    extra_delta=extra_delta,
                    limitations_program_reveal=tail if reveal_limitations_program else Program.to([]),
                )
            )

        spend_bundle: SpendBundle = unsigned_spend_bundle_for_spendable_cats(
            CAT_MOD,
            spendable_cat_list,
        )
        agg_sig = AugSchemeMPL.aggregate(signatures)
        result = await sim_client.push_tx(
            SpendBundle.aggregate(
                [
                    *additional_spends,
                    spend_bundle,
                    SpendBundle([], agg_sig),  # "Signing" the spend bundle
                ]
            )
        )
        assert result == expected_result
        self.cost[cost_str] = cost_of_spend_bundle(spend_bundle)
        await sim.farm_block()
Beispiel #23
0
    async def rl_generate_signed_aggregation_transaction(
            self, rl_info, consolidating_coin, rl_parent, rl_coin):
        if (rl_info.limit is None or rl_info.interval is None
                or rl_info.user_pubkey is None
                or rl_info.admin_pubkey is None):
            raise ValueError("One or more of the elements of rl_info is None")
        if self.rl_coin_record is None:
            raise ValueError("Rl coin record is None")

        list_of_coinsolutions = []
        self.rl_coin_record = await self._get_rl_coin_record()
        pubkey, secretkey = await self.get_keys(
            self.rl_coin_record.coin.puzzle_hash)
        # Spend wallet coin
        puzzle = rl_puzzle_for_pk(
            rl_info.user_pubkey,
            rl_info.limit,
            rl_info.interval,
            rl_info.rl_origin_id,
            rl_info.admin_pubkey,
        )

        solution = rl_make_solution_mode_2(
            rl_coin.puzzle_hash,
            consolidating_coin.parent_coin_info,
            consolidating_coin.puzzle_hash,
            consolidating_coin.amount,
            rl_coin.parent_coin_info,
            rl_coin.amount,
            rl_parent.amount,
            rl_parent.parent_coin_info,
        )
        signature = AugSchemeMPL.sign(secretkey, solution.get_tree_hash())
        rl_spend = CoinSolution(self.rl_coin_record.coin,
                                Program.to([puzzle, solution]))

        list_of_coinsolutions.append(rl_spend)

        # Spend consolidating coin
        puzzle = rl_make_aggregation_puzzle(
            self.rl_coin_record.coin.puzzle_hash)
        solution = rl_make_aggregation_solution(
            consolidating_coin.name(),
            self.rl_coin_record.coin.parent_coin_info,
            self.rl_coin_record.coin.amount,
        )
        agg_spend = CoinSolution(consolidating_coin,
                                 Program.to([puzzle, solution]))

        list_of_coinsolutions.append(agg_spend)
        aggsig = AugSchemeMPL.aggregate([signature])

        return SpendBundle(list_of_coinsolutions, aggsig)
Beispiel #24
0
    async def sign_clawback_transaction(self, spends: List[Tuple[Program, CoinSpend]], clawback_pubkey) -> SpendBundle:
        sigs = []
        for puzzle, solution in spends:
            pubkey, secretkey = await self.get_keys_pk(clawback_pubkey)
            signature = AugSchemeMPL.sign(secretkey, solution.solution.get_tree_hash())
            sigs.append(signature)
        aggsig = AugSchemeMPL.aggregate(sigs)
        solution_list = []
        for puzzle, coin_spend in spends:
            solution_list.append(coin_spend)

        return SpendBundle(solution_list, aggsig)
def cc_generate_eve_spend(coin: Coin, full_puzzle: Program):
    solution = cc_make_eve_solution(coin.parent_coin_info, coin.puzzle_hash,
                                    coin.amount)
    list_of_solutions = [
        CoinSolution(
            coin,
            Program.to([full_puzzle, solution]),
        )
    ]
    aggsig = AugSchemeMPL.aggregate([])
    spend_bundle = SpendBundle(list_of_solutions, aggsig)
    return spend_bundle
Beispiel #26
0
 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):
         signature = self.sign(bytes(public_key), message_hash)
         signatures.append(signature)
     return AugSchemeMPL.aggregate(signatures)
    def get_plot_signature(self, m: bytes32, plot_pk: G1Element) -> G2Element:
        """
        Returns the plot signature of the header data.
        """
        farmer_sk = master_sk_to_farmer_sk(self.all_sks[0])
        for _, plot_info in self.plots.items():
            agg_pk = ProofOfSpace.generate_plot_public_key(plot_info.local_sk.get_g1(), plot_info.farmer_public_key)
            if agg_pk == plot_pk:
                harv_share = AugSchemeMPL.sign(plot_info.local_sk, m, agg_pk)
                farm_share = AugSchemeMPL.sign(farmer_sk, m, agg_pk)
                return AugSchemeMPL.aggregate([harv_share, farm_share])

        raise ValueError(f"Do not have key {plot_pk}")
Beispiel #28
0
    async def rl_sign_transaction(self, spends: List[Tuple[Program, CoinSolution]]) -> SpendBundle:
        sigs = []
        for puzzle, solution in spends:
            pubkey, secretkey = await self.get_keys(solution.coin.puzzle_hash)
            signature = AugSchemeMPL.sign(secretkey, Program.to(solution.solution).get_tree_hash())
            sigs.append(signature)

        aggsig = AugSchemeMPL.aggregate(sigs)

        solution_list: List[CoinSolution] = []
        for puzzle, coin_solution in spends:
            solution_list.append(CoinSolution(coin_solution.coin, Program.to([puzzle, coin_solution.solution])))

        return SpendBundle(solution_list, aggsig)
Beispiel #29
0
    async def test_did_recovery_with_empty_set(self, two_wallet_nodes):
        num_blocks = 5
        full_nodes, wallets = two_wallet_nodes
        full_node_1 = full_nodes[0]
        server_1 = full_node_1.server
        wallet_node, server_2 = wallets[0]
        wallet_node_2, server_3 = wallets[1]
        wallet = wallet_node.wallet_state_manager.main_wallet

        ph = await wallet.get_new_puzzlehash()

        await server_2.start_client(
            PeerInfo("localhost", uint16(server_1._port)), None)
        await server_3.start_client(
            PeerInfo("localhost", uint16(server_1._port)), None)

        for i in range(1, num_blocks):
            await full_node_1.farm_new_transaction_block(
                FarmNewBlockProtocol(ph))

        funds = sum([
            calculate_pool_reward(uint32(i)) +
            calculate_base_farmer_reward(uint32(i))
            for i in range(1, num_blocks - 1)
        ])

        await time_out_assert(15, wallet.get_confirmed_balance, funds)

        async with wallet_node.wallet_state_manager.lock:
            did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet(
                wallet_node.wallet_state_manager, wallet, uint64(101))

        for i in range(1, num_blocks):
            await full_node_1.farm_new_transaction_block(
                FarmNewBlockProtocol(ph))

        await time_out_assert(15, did_wallet.get_confirmed_balance, 101)
        await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101)
        coins = await did_wallet.select_coins(1)
        coin = coins.pop()
        info = Program.to([])
        pubkey = (await
                  did_wallet.wallet_state_manager.get_unused_derivation_record(
                      did_wallet.wallet_info.id)).pubkey
        spend_bundle = await did_wallet.recovery_spend(
            coin, ph, info, pubkey, SpendBundle([],
                                                AugSchemeMPL.aggregate([])))
        additions = spend_bundle.additions()
        assert additions == []
Beispiel #30
0
    def get_plot_signature(self, header_data: HeaderData,
                           plot_pk: G1Element) -> Optional[G2Element]:
        """
        Returns the plot signature of the header data.
        """
        farmer_sk = master_sk_to_farmer_sk(self.all_sks[0][0])
        for _, plot_info in self.plots.items():
            agg_pk = ProofOfSpace.generate_plot_public_key(
                plot_info.local_sk.get_g1(), plot_info.farmer_public_key)
            if agg_pk == plot_pk:
                m = header_data.get_hash()
                harv_share = AugSchemeMPL.sign(plot_info.local_sk, m, agg_pk)
                farm_share = AugSchemeMPL.sign(farmer_sk, m, agg_pk)
                return AugSchemeMPL.aggregate([harv_share, farm_share])

        return None