View Source Ed25519 Signed Payload Signature
Context
The Ed25519 Signed Payload
is a new signer type introduced in CAP-40.
You start with a keypair, (pk, sk)
and a payload P
. Then, you configure a "signed payload" signer with (pk, P)
. This means that Sign(sk, P)
is a valid transaction signature.
So basically, you should provide:
- public key and payload to establish the signer of type
ed25519_signed_payload
- secret key and payload to sign a transaction using the
ed25519_signed_payload
signature
Guide
This guide will explain in detail the process to establish a signer of type Ed25519 Signed Payload and use the signature of this type to send valid transactions to the network.
In this guide, we will use a payment transaction as an example, but the process is the same for any other transaction type.
1. Prerequisites
You need to have two funded accounts.
- For the first one: you will need to know the public and secret key. This account will send the payment.
- For the second one: you will need to know the public key. This account will receive the payment.
# payer's keypair
payer_pk = "GA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVSGZ"
payer_sk = "SECRET_SEED"
# destination public key
destination_pk = "GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW"
2. Generate payload
The payload
is a value of up to 32 bytes (256 bits).
You can generate the payload
using the following code:
# you can use a different byte size up to 32
payload = 32 |> :crypto.strong_rand_bytes() |> Base.encode16(case: :lower)
For example, for a raw payload of:
<<1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32>>
Then, the payload
will be:
payload = "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"
Notice that payload
is hexadecimal encoded and lowercase.
3. Establish signer
Now, you need to establish a signer of type ed25519_signed_payload
using the payload
and the public key of the account that will send the payment (payer_pk
).
So here, you use the Stellar.TxBuild.SetOptions
operation to set the signer and this transaction is signed just by the secret key of the payer (payer_sk
).
# 1. set the source account
source_account = Stellar.TxBuild.Account.new(payer_pk)
# 2. set the next sequence number for the source account
server = Stellar.Horizon.Server.testnet()
{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number(server, payer_pk)
sequence_number = Stellar.TxBuild.SequenceNumber.new(seq_num)
# 3. build the set_options operation setting the ed25519 signed payload as a signer with weight 1
set_options_op =
Stellar.TxBuild.SetOptions.new(
signer: [
signed_payload: [ed25519: payer_pk, payload: payload],
weight: 1
]
)
# 4. build the tx signature
signature = Stellar.TxBuild.Signature.new(ed25519: payer_sk)
# 5. submit the transaction to Horizon
{:ok, envelope} =
source_account
|> Stellar.TxBuild.new(sequence_number: sequence_number)
|> Stellar.TxBuild.add_operation(set_options_op)
|> Stellar.TxBuild.sign(signature)
|> Stellar.TxBuild.envelope()
{:ok, submitted_tx} = Stellar.Horizon.Transactions.create(server, envelope)
4. Send a payment using the Ed25519 Signed Payload signature
Once you have established the signer, you can use the payload
and the secret key of the payer (payer_sk
) to sign the transaction and send the payment.
# 1. set the founder account
source_account = Stellar.TxBuild.Account.new(payer_pk)
# 2. set the next sequence number for the founder account
server = Stellar.Horizon.Server.testnet()
{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number(server, payer_pk)
sequence_number = Stellar.TxBuild.SequenceNumber.new(seq_num)
# 3. build the payment operation
payment_op =
Stellar.TxBuild.Payment.new(
destination: destination_pk,
asset: :native,
amount: 25
)
# 4. build the tx signature with a signed payload
# by providing the hex-encoded payload, and the secret key
signature = Stellar.TxBuild.Signature.new(signed_payload: [payload: payload, ed25519: payer_sk])
# 5. submit the transaction to Horizon
{:ok, envelope} =
source_account
|> Stellar.TxBuild.new(sequence_number: sequence_number)
|> Stellar.TxBuild.add_operation(payment_op)
|> Stellar.TxBuild.sign(signature)
|> Stellar.TxBuild.envelope()
{:ok, submitted_tx} = Stellar.Horizon.Transactions.create(server, envelope)
👍 That's it!
The payment was sent using the Ed25519 Signed Payload as a signature!