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
def signature_for_solution(self, solution): signatures = [] conditions_dict = conditions_by_opcode(conditions_for_solution(solution)) for _ in hash_key_pairs_for_conditions_dict(conditions_dict): signature = self.sign(_) signatures.append(signature) return BLSSignature.aggregate(signatures)
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)
def xform_aggsig_sig_pair(pair): """ Transform a pair (aggsig_pair_bytes, sig_bytes) to (aggsig_pair, BLSSignature). """ aggsig = BLSSignature.aggsig_pair.from_bytes(pair[0]) sig = BLSSignature.from_bytes(pair[1]) return (aggsig, sig)
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
async def do_spend_coin(wallet, storage, input): """ UI to spend a coin. """ coins = [] while True: coin_str = input("Enter hex id of coin to spend> ") if len(coin_str) == 0: break coin_name = bytes.fromhex(coin_str) preimage = await storage.hash_preimage(hash=coin_name) if preimage is None: print(f"can't find coin id {coin_name.hex()}") continue coin = Coin.from_bytes(preimage) coin_puzzle_hash_hex = coin.puzzle_hash.hex() print(f"coin puzzle hash is {coin_puzzle_hash_hex}") coins.append(coin) if len(coins) == 0: return dest_address = "14c56fdefb47e2208de54b6c609a907c522348c96e8cfb41c7a8c75f44835dd9" print(f"sending 1 coin to {dest_address}, rest fees") # create an unfinalized SpendBundle pst = spend_coin(wallet, coins, dest_address) pst_encoded = bytes(pst) print(pst_encoded.hex()) # keep requesting signatures until finalized sigs = [] while True: sig_str = input("Enter a signature> ") try: sig = BLSSignature.from_bytes(bytes.fromhex(sig_str)) except Exception as ex: print("failed: %s" % ex) continue sigs.append(sig) sigs = list(set(sigs)) spend_bundle, summary_list = finalize_pst(wallet, pst, sigs) if spend_bundle: break for summary in summary_list: print( "coin %s has %d of %d sigs" % (summary[0].name(), len(summary[2]), summary[3]) ) print("spend bundle = %s" % bytes(spend_bundle).hex()) # optionally send to ledger sim r = input(f"Send to ledger sim? (y/n)> ") if r.lower().startswith("y"): r = await storage.ledger_sim().push_tx(tx=spend_bundle) return spend_bundle
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
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)
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
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
def BLSSignature_from_string(signature): try: sig = BLSSignature(bytes.fromhex(signature)) except Exception: raise Exception return sig
def signature_for_coinbase(coin: Coin, pool_private_key: blspy.PrivateKey): message_hash = coin.name() return BLSSignature( pool_private_key.sign_prepend_prehashed(message_hash).serialize())
def sign(self, message_hash: bytes32) -> BLSSignature: return BLSSignature(self.pk.sign_prepend_prehashed(message_hash).serialize())