Multi-signature account

Multi-signature accounts can be used to require that transactions require multiple public keys to sign before they are considered valid. This is done by first configuring your account’s threshold levels. Each operation has a threshold level of either low, medium, or high. You give each threshold level a number between 1-255 in your account. Then, for each key in your account, you assign it a weight (1-255, setting a 0 weight deletes the key). Any transaction must be signed with enough keys to meet the threshold.

For example, let’s say you set your threshold levels; low = 1, medium = 2, high = 3. You want to send a payment operation, which is a medium threshold operation. Your master key has weight 1. Additionally, you have a secondary key associated with your account which has a weight of 1. Now, the transaction you submit for this payment must include both signatures of your master key and secondary key since their combined weight is 2 which is enough to authorize the payment operation.

In this example, we will:

  • Add a second signer to the account

  • Set our account’s masterkey weight and threshold levels

  • Create a multi signature transaction that sends a payment

 1"""
 2Stellar uses signatures as authorization. Transactions always need authorization
 3from at least one public key in order to be considered valid. Generally,
 4transactions only need authorization from the public key of the source account.
 5
 6Transaction signatures are created by cryptographically signing the
 7transaction object contents with a secret key. Stellar currently uses the ed25519 signature
 8scheme, but there’s also a mechanism for adding additional types of public/private key schemes.
 9A transaction with an attached signature is considered to have authorization from that public key.
10
11In two cases, a transaction may need more than one signature. If the transaction has
12operations that affect more than one account, it will need authorization from every account
13in question. A transaction will also need additional signatures if the account associated
14with the transaction has multiple public keys.
15
16See: https://developers.stellar.org/docs/glossary/multisig/
17"""
18from stellar_sdk import Keypair, Network, Server, Signer, TransactionBuilder
19
20server = Server(horizon_url="https://horizon-testnet.stellar.org")
21root_keypair = Keypair.from_secret(
22    "SA6XHAH4GNLRWWWF6TEVEWNS44CBNFAJWHWOPZCVZOUXSQA7BOYN7XHC"
23)
24root_account = server.load_account(account_id=root_keypair.public_key)
25secondary_keypair = Keypair.from_secret(
26    "SAMZUAAPLRUH62HH3XE7NVD6ZSMTWPWGM6DS4X47HLVRHEBKP4U2H5E7"
27)
28
29secondary_signer = Signer.ed25519_public_key(
30    account_id=secondary_keypair.public_key, weight=1
31)
32transaction = (
33    TransactionBuilder(
34        source_account=root_account,
35        network_passphrase=Network.TESTNET_NETWORK_PASSPHRASE,
36        base_fee=100,
37    )
38    .append_set_options_op(
39        master_weight=1,  # set master key weight
40        low_threshold=1,
41        med_threshold=2,  # a payment is medium threshold
42        high_threshold=2,  # make sure to have enough weight to add up to the high threshold!
43        signer=secondary_signer,
44    )
45    .set_timeout(30)
46    .build()
47)
48
49# only need to sign with the root signer as the 2nd signer won't
50# be added to the account till after this transaction completes
51transaction.sign(root_keypair)
52response = server.submit_transaction(transaction)
53print(response)
54
55# now create a payment with the account that has two signers
56destination = "GBA5SMM5OYAOOPL6R773MV7O3CCLUDVLCWHIVVL3W4XTD3DA5FJ4JSEZ"
57transaction = (
58    TransactionBuilder(
59        source_account=root_account,
60        network_passphrase=Network.TESTNET_NETWORK_PASSPHRASE,
61        base_fee=100,
62    )
63    .append_payment_op(destination=destination, amount="2000", asset_code="XLM")
64    .set_timeout(30)
65    .build()
66)
67
68# now we need to sign the transaction with both the root and the secondary_keypair
69transaction.sign(root_keypair)
70transaction.sign(secondary_keypair)
71response = server.submit_transaction(transaction)
72print(response)