Dual attestation signature example

I’ve been trying to implement the dual attestation signature for transfers between vasp:s, but cannot get it right, I get an error that the signature is not correct. So I believe I have been able to set the compliance keys correctly for the account but forming the message is wrong.

Would someone provide an example of a message that could be signed? For example with:

metadata: foo
payer address: 95f6ce2c353b3fb1f6a7636f38883ddd
transfer amount: 1000 libras

What should the message look like before signing it? If someone could provide for example the hex encoded byte array, I think I could work it out from there.

1 Like


I’ve included a small code snippet in this libra proposal: https://github.com/libra/lip/blob/master/lips/lip-1.mdx#recipient-signature. You can test it with the Libra Python SDK (pip3 install pylibra-beta).

An example here:

        metadata: Metadata = Metadata__TravelRuleMetadata(

        dual_attest_msg_bytes: bytearray = bytearray()
        dual_attest_msg_bytes.extend(lcs.serialize(metadata, Metadata))  # Travel Rule metadata
        dual_attest_msg_bytes.extend(lcs.serialize(bytes.fromhex("793251de1a61e9b4d1a17d13aa015e45"), bytes))  # Sender Address
        dual_attest_msg_bytes.extend(lcs.serialize(st.uint64(1000000), st.uint64))  # Amount
        dual_attest_msg_bytes.extend(lcs.serialize(b"@@$$LIBRA_ATTEST$$@@", bytes))  # Libra Domain Separator

        dual_attest_msg: TransactionArgument__U8Vector = TransactionArgument__U8Vector(bytes(dual_attest_msg_bytes))
        dual_attest_msg_lcs = lcs.serialize(dual_attest_msg, TransactionArgument__U8Vector)

        print("Result:", dual_attest_msg_lcs)

Result: b'>\x02\x00\x01\x0creference_id\x10y2Q\xde\x1aa\xe9\xb4\xd1\xa1}\x13\xaa\x01^E@B\x0f\x00\x00\x00\x00\x00\x14@@$$LIBRA_ATTEST$$@@'

or in hex: b'3e0200010c7265666572656e63655f696410793251de1a61e9b4d1a17d13aa015e4540420f000000000014404024244c494252415f41545445535424244040'

Note: The ed25519 compliance key signs directly the bytes, not a hash of this dual attestation signable.


Thank you very much! I can immediately see that I have completely missed that metadata can have types. I think that’s the first thing i need to fix.
Should’t the type be visible also in the peer_to_peer_transaction_with_metadata function signature?

Now it is:
fun peer_to_peer_with_metadata(
payer: &signer,
payee: address,
amount: u64,
metadata: vector,
metadata_signature: vector

1 Like

No, the blockchain doesn’t really care about the type of the metadata field as it doesn’t parse it, this is just an opaque byte vector that your VASP agreed upon during the pre-flight dual attestation.

Encoded Travel Rule metadata could be b"foo" in this example, the chain wouldn’t know that it doesn’t deserialize to a correct Metadata struct. All it knows is that you agreed to it.


Yes, now I got it to work, the problem was in serializing the domain separator. I did not have lcs serialization for it. And it was like you said, the metadata can be any byte array.
And thanks again, I wouldn’t have got it working without your example :+1: