def _derive_path_unhardened(sk: PrivateKey, path: List[int]) -> PrivateKey: for index in path: sk = AugSchemeMPL.derive_child_sk_unhardened(sk, index) return sk
def test_readme(): seed: bytes = bytes([ 0, 50, 6, 244, 24, 199, 1, 25, 52, 88, 192, 19, 18, 12, 89, 6, 220, 18, 102, 58, 209, 82, 12, 62, 89, 110, 182, 9, 44, 20, 254, 22, ]) sk: PrivateKey = AugSchemeMPL.key_gen(seed) pk: G1Element = sk.get_g1() message: bytes = bytes([1, 2, 3, 4, 5]) signature: G2Element = AugSchemeMPL.sign(sk, message) ok: bool = AugSchemeMPL.verify(pk, message, signature) assert ok sk_bytes: bytes = bytes(sk) # 32 bytes pk_bytes: bytes = bytes(pk) # 48 bytes signature_bytes: bytes = bytes(signature) # 96 bytes print(sk_bytes.hex(), pk_bytes.hex(), signature_bytes.hex()) sk = PrivateKey.from_bytes(sk_bytes) pk = G1Element.from_bytes(pk_bytes) signature = G2Element.from_bytes(signature_bytes) seed = bytes([1]) + seed[1:] sk1: PrivateKey = AugSchemeMPL.key_gen(seed) seed = bytes([2]) + seed[1:] sk2: PrivateKey = AugSchemeMPL.key_gen(seed) message2: bytes = bytes([1, 2, 3, 4, 5, 6, 7]) pk1: G1Element = sk1.get_g1() sig1: G2Element = AugSchemeMPL.sign(sk1, message) pk2: G1Element = sk2.get_g1() sig2: G2Element = AugSchemeMPL.sign(sk2, message2) agg_sig: G2Element = AugSchemeMPL.aggregate([sig1, sig2]) ok = AugSchemeMPL.aggregate_verify([pk1, pk2], [message, message2], agg_sig) assert ok seed = bytes([3]) + seed[1:] sk3: PrivateKey = AugSchemeMPL.key_gen(seed) pk3: G1Element = sk3.get_g1() message3: bytes = bytes([100, 2, 254, 88, 90, 45, 23]) sig3: G2Element = AugSchemeMPL.sign(sk3, message3) agg_sig_final: G2Element = AugSchemeMPL.aggregate([agg_sig, sig3]) ok = AugSchemeMPL.aggregate_verify([pk1, pk2, pk3], [message, message2, message3], agg_sig_final) assert ok pop_sig1: G2Element = PopSchemeMPL.sign(sk1, message) pop_sig2: G2Element = PopSchemeMPL.sign(sk2, message) pop_sig3: G2Element = PopSchemeMPL.sign(sk3, message) pop1: G2Element = PopSchemeMPL.pop_prove(sk1) pop2: G2Element = PopSchemeMPL.pop_prove(sk2) pop3: G2Element = PopSchemeMPL.pop_prove(sk3) ok = PopSchemeMPL.pop_verify(pk1, pop1) assert ok ok = PopSchemeMPL.pop_verify(pk2, pop2) assert ok ok = PopSchemeMPL.pop_verify(pk3, pop3) assert ok pop_sig_agg: G2Element = PopSchemeMPL.aggregate( [pop_sig1, pop_sig2, pop_sig3]) ok = PopSchemeMPL.fast_aggregate_verify([pk1, pk2, pk3], message, pop_sig_agg) assert ok pop_agg_pk: G1Element = pk1 + pk2 + pk3 ok = PopSchemeMPL.verify(pop_agg_pk, message, pop_sig_agg) assert ok pop_agg_sk: PrivateKey = PrivateKey.aggregate([sk1, sk2, sk3]) ok = PopSchemeMPL.sign(pop_agg_sk, message) == pop_sig_agg assert ok master_sk: PrivateKey = AugSchemeMPL.key_gen(seed) child: PrivateKey = AugSchemeMPL.derive_child_sk(master_sk, 152) grandchild: PrivateKey = AugSchemeMPL.derive_child_sk(child, 952) master_pk: G1Element = master_sk.get_g1() child_u: PrivateKey = AugSchemeMPL.derive_child_sk_unhardened( master_sk, 22) grandchild_u: PrivateKey = AugSchemeMPL.derive_child_sk_unhardened( child_u, 0) child_u_pk: G1Element = AugSchemeMPL.derive_child_pk_unhardened( master_pk, 22) grandchild_u_pk: G1Element = AugSchemeMPL.derive_child_pk_unhardened( child_u_pk, 0) ok = grandchild_u_pk == grandchild_u.get_g1() assert ok
def sign_tx(intermediate_sk: PrivateKey, spend_bundle: SpendBundle, use_hardened_keys: bool): """ Takes in an unsigned transaction (called a spend bundle in chia), and a 24 word mnemonic (master sk) and generates the aggregate BLS signature for the transaction. """ # This field is the ADDITIONAL_DATA found in the constants additional_data: bytes = bytes.fromhex( "ccd5bb71183532bff220ba46c268991a3ff07eb358e8255a65c30a2dce0e5fbb") puzzle_hash_to_sk: Dict[bytes32, PrivateKey] = {} if use_hardened_keys: # Change this loop to scan more keys if you have more for i in range(5000): child_sk: PrivateKey = AugSchemeMPL.derive_child_sk( intermediate_sk, i) child_pk: G1Element = child_sk.get_g1() puzzle = puzzle_for_pk(child_pk) puzzle_hash = puzzle.get_tree_hash() puzzle_hash_to_sk[puzzle_hash] = child_sk else: # Change this loop to scan more keys if you have more for i in range(5000): child_sk: PrivateKey = AugSchemeMPL.derive_child_sk_unhardened( intermediate_sk, i) child_pk: G1Element = child_sk.get_g1() puzzle = puzzle_for_pk(child_pk) puzzle_hash = puzzle.get_tree_hash() puzzle_hash_to_sk[puzzle_hash] = child_sk aggregate_signature: G2Element = G2Element() for coin_solution in spend_bundle.coin_solutions: if coin_solution.coin.puzzle_hash not in puzzle_hash_to_sk: print( f"Puzzle hash {coin_solution.coin.puzzle_hash} not found for this key." ) return sk: PrivateKey = puzzle_hash_to_sk[coin_solution.coin.puzzle_hash] synthetic_secret_key: PrivateKey = calculate_synthetic_secret_key( sk, DEFAULT_HIDDEN_PUZZLE_HASH) err, conditions_dict, cost = conditions_dict_for_solution( coin_solution.puzzle_reveal, coin_solution.solution, 11000000000) if err or conditions_dict is None: print( f"Sign transaction failed, con:{conditions_dict}, error: {err}" ) return pk_msgs = pkm_pairs_for_conditions_dict( conditions_dict, bytes(coin_solution.coin.name()), additional_data) assert len(pk_msgs) == 1 _, msg = pk_msgs[0] signature = AugSchemeMPL.sign(synthetic_secret_key, msg) aggregate_signature = AugSchemeMPL.aggregate( [aggregate_signature, signature]) new_spend_bundle = SpendBundle(spend_bundle.coin_solutions, aggregate_signature) print("") print("Signed spend bundle JSON:\n") print(json.dumps(new_spend_bundle.to_json_dict()))