Skip to content

Commit

Permalink
multisig example
Browse files Browse the repository at this point in the history
  • Loading branch information
smartgoo committed Dec 7, 2024
1 parent 2da757d commit b8b0c32
Showing 1 changed file with 85 additions and 0 deletions.
85 changes: 85 additions & 0 deletions python/examples/transactions/multisig.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# A very simple non-PSKT multisig example

import asyncio
from kaspa import (
Mnemonic,
Opcodes,
RpcClient,
Resolver,
ScriptBuilder,
SighashType,
XPrv,
create_transactions,
address_from_script_public_key,
kaspa_to_sompi
)

def derive(seed, account_index):
xprv = XPrv(seed).derive_path(f"m/45'/111111'/{account_index}'")
xpub = xprv.to_xpub()
prv = xprv.derive_child(1).to_private_key()
pub = xpub.derive_child(1).to_public_key()
return prv, pub

async def main():
seed = Mnemonic('predict cloud noise economy home stereo tag cancel adult pistol act remove equip cricket man summer neutral black art miracle foam world clown say').to_seed()

prv1, pub1 = derive(seed, 0)
print(f'Account 1:\n - prv: {prv1.to_string()}\n - pub: {pub1.to_string()}\n')

prv2, pub2 = derive(seed, 1)
print(f'Account 2:\n - prv: {prv2.to_string()}\n - pub: {pub2.to_string()}\n')

prv3, pub3 = derive(seed, 2)
print(f'Account 3:\n - prv: {prv3.to_string()}\n - pub: {pub3.to_string()}\n')

redeem_script = ScriptBuilder()\
.add_i64(2)\
.add_data(pub1.to_x_only_public_key().to_string())\
.add_data(pub2.to_x_only_public_key().to_string())\
.add_data(pub3.to_x_only_public_key().to_string())\
.add_i64(3)\
.add_op(Opcodes.OpCheckMultiSig)

# TODO ECDSA version
# TODO include create_multisig_address function when available

spk = redeem_script.create_pay_to_script_hash_script()
address = address_from_script_public_key(spk, network="testnet")
print(f"Multisig Address: {address.to_string()}\n")

proceed = input("Send funds to address above before proceeding (enter 'y' to proceed): ")
if proceed != 'y':
return

client = RpcClient(resolver=Resolver(), network_id='testnet-10')
await client.connect(strategy='fallback')
utxos = await client.get_utxos_by_addresses(request={'addresses': [address]})

tx = create_transactions(
entries=utxos['entries'],
outputs=[{'address': 'kaspatest:prsajwtrefzex5wsmyk3rfkyzaq3wdwzczzr6jptgyzk4pacl9lzvtv8h30j9', 'amount': kaspa_to_sompi(1)}],
change_address=address,
priority_fee=kaspa_to_sompi(1),
network_id='testnet-10',
minimum_signatures=2,
sig_op_count=3
)

for transaction in tx['transactions']:
for idx, _ in enumerate(transaction.transaction.inputs):

sig_1 = transaction.create_input_signature(idx, prv1)
sig_2 = transaction.create_input_signature(idx, prv2)

script_sig = ScriptBuilder()\
.add_data(sig_1[2:])\
.add_data(sig_2[2:])\
.add_data(redeem_script.to_string())

transaction.fill_input(idx, script_sig.to_string())

print('tx id', await transaction.submit(client))

if __name__ == "__main__":
asyncio.run(main())

0 comments on commit b8b0c32

Please sign in to comment.