Creating an Approved Payment transaction

Hi,

I noticed that there’s a new transaction script available, approved_payment with register_approved_payment https://github.com/libra/libra/blob/master/language/stdlib/transaction_scripts/approved_payment.move

I tried to create transactions with this script but it always fails with ‘Aborted’. (I am able to register the approved payment with the register script, but the transaction where the payment is made fails)

I’m guessing the problem is with signing the metadata. How is the metadata supposed to be signed? Is it like with a transaction, that you hash the data first, add salt and then sign? And is the salt the same as on the transaction signature? I was not able to find any examples in the repository where the signature is created, only ones with a ready-made signature.

I really appreciate any help!

1 Like

Hi @2kSiika,
Apologies for the lack of documentation here. We are actually in the process of replacing ApprovedPayment with the metadata_signature field of a payment transaction script.

https://github.com/libra/libra/pull/3766 has an example of how to craft the message to be signed in language/e2e-tests/src/tests/transaction_builder.rs , which should hopefully be helpful!

2 Likes

I really wanna be one of the biggest developer

Now that the metada_signature was published in testnet, I tried to create a transaction using it. But if I understand the code correctly (https://github.com/libra/libra/blob/testnet/language/stdlib/modules/libra_account.move#L170),

-> I cannot test this

I think the earlier approach of having separate transaction scripts for the approved transaction was cleaner. This new one is not very clean or obvious:

  • The method signature of the transaction_with_metadata script now has a signature parameter, but it’s not required
  • If you add the signature it means that the signature has to be created in a certain way (concat the bytes of metada + sender address + amount + salt and sign that) to work
  • it has to be signed by the parent vasp account of your account, not any account is ok

Improvement ideas:

  • I think it would be good to allow the approved transaction for any account not just vasps, because I think it would be a pretty useful feature to be able to make sure the correct amount is paid. If you for example create a bill for some amount, with this feature you can validate that the correct amount will be paid.
  • Separating this feature into another transaction script would make this cleaner. Now the script can only partly be used by a normal account and the part that cannot be used just makes it confusing.
  • The signing process of the metadata is not similar to the one used for a transaction. The data is not hashed before adding salt and signing. I don’t see why the signing has to be different for this.
    -Also, the salt / domain separator is very different from the one used for signing a transaction libra_types::transaction::RawTransaction@@$$LIBRA$$@@ vs @$LIBRA_ATTEST$@
  • Consider adding a structure containing all the fields that are required for the signature. Then the signing would be pretty close to signing a transaction: just serialize the structure using lcs, create a domain separator the same way it’s done in transactions and sign it using the same process.

Good questions/ideas here! I agree with you that ApprovedPayment is cleaner and more flexible. However, the problem is that we must have dual attestation on all transactions between VASPs over a certain amount–there can’t be any loopholes. Because ApprovedPayment is opt-in, it doesn’t satisfy this requirement.

Now let me try to reply to some of your individual questions:

I cannot have a VASP account in testnet
I don’t know the private key for the hardcoded default vasp account https://github.com/libra/libra/blob/testnet/language/stdlib/modules/libra_account.move#L400 and cannot use that for testing

All testnet accounts are now VASP accounts (though this is a fairly recent change). Although the compliance key starts off as a dummy key, you can rotate it to something you know using this code. That will allow you to test the dual attestation functionality.

I think it would be good to allow the approved transaction for any account not just vasps, because I think it would be a pretty useful feature to be able to make sure the correct amount is paid. If you for example create a bill for some amount, with this feature you can validate that the correct amount will be paid.

I think this is a great idea and would be very easy to implement by tweaking the existing scheme–we can simply opt in to doing the check whenever the signature parameter is nonempty.

Separating this feature into another transaction script would make this cleaner. Now the script can only partly be used by a normal account and the part that cannot be used just makes it confusing.

I agree with this. We are planning to add simpler transaction scripts for payments without dual attestation (to eliminate the signature parameter) and for payments that cannot create new accounts (to eliminate the auth_key_prefix parameter). We are currently in a confusing middle ground between the old, simpler testnet and the new one with VASPs etc.

The signing process of the metadata is not similar to the one used for a transaction. The data is not hashed before adding salt and signing. I don’t see why the signing has to be different for this.

Agreed that consistency would be valuable here. We are actually working on changing the transaction signing to sign the raw bytes.

-Also, the salt / domain separator is very different from the one used for signing a transaction libra_types::transaction::RawTransaction@@$$LIBRA$$@@ vs @LIBRA_ATTEST@

This is intentional. The purpose of domain separators is to use a distinct separator for each kind of message (to avoid, e.g., signing dual attestation bytes and then interpreting them as a signature on a transaction).

Consider adding a structure containing all the fields that are required for the signature. Then the signing would be pretty close to signing a transaction: just serialize the structure using lcs, create a domain separator the same way it’s done in transactions and sign it using the same process.

We considered this, but felt that the flat bytearray was simpler to implement for clients (fewer LCS concepts to implement/worry about).

1 Like

First of all, thank you for this thorough anwer.
I quess I misunderstood how the testnet accounts work, I thought that there’s one vasp account and all accounts created by minting etc. would be child accounts of that account. I also was not aware of the possiblity to rotate the compliance key, so this was really interesting information and I have to try out these soon :+1:

1 Like