A few days ago, on the Blurt Discord server's #dev channel, @khrom asked about the technical and conceptual aspects of how private memo messages work.
It's important to note that the encryption of the memo field in a transfer operation is not performed within the Blurt blockchain. This is consistent with its sister chains. Instead, the blockchain simply records the field as it is, as specified in its open-source code (see here)
/**
* @ingroup operations
*
* @brief Transfers BLURT from one account to another.
*/
struct transfer_operation : public base_operation
{
account_name_type from;
/// Account to transfer asset to
account_name_type to;
/// The amount of asset to transfer from @ref from to @ref to
asset amount;
/// The memo is plain-text, any encryption on the memo is up to
/// a higher level protocol.
string memo;
void validate()const;
void get_required_active_authorities( flat_set<account_name_type>& a )const{ a.insert(from); }
};
After researching, I came across this update of dhive that added the Memo encryption/decrypt feature using AES. I informed him that I would be interested to integrate it to the dblurt library.
So I started to take a closer look at this Typescript code and I made some modifications to the code, resulting in a clearer and more concise code than the original. Overall, I am pleased with the outcome.
As a result of these changes, the functions encodeMemo()
and decodeMemo()
were added. To ensure compatibility, encrypted memo decoding tests have been successfully performed on Blurt's sister channels too. For those interested in the code I invite you to consult the merge:
Usage
The encodeMemo()
and decodeMemo()
functions are called directly from the library.
import { encodeMemo, decodeMemo } from "@beblurt/dblurt"
Encode Memo
The function encodeMemo()
takes as parameters:
- memo - The memo to encrypt (need to start with #).
- senderPrivateMemoKey - The private Memo key of the sender (PrivateKey | string).
- receiverPublicMemoKey - The publicKey Memo key of the recipient (PublicKey | string).
const memo = "#MY MEMO TO ENCODE"
const encryptedMemo = encodeMemo(memo, senderPrivateMemoKey, receiverPublicMemoKey)
Decode Memo
The function decodeMemo()
takes as parameters:
- memo - The encrypted memo to decrypt (need to start with #).
- receiverPrivateMemoKey - The private Memo key of the recipient (PrivateKey | string).
const encryptedMemo = "#XYZXYZXYZXYZXYZXYZXYZXYZXYZXYZXYZXYZ"
const memo = decodeMemo(encryptedMemo, receiverPrivateMemoKey)
Example of use
To demonstrate the usage of encodeMemo()
and decodeMemo()
functions with Memo Keys, let's consider an example. Suppose that I want to transfer 1 BLURT from my witness account @nalexadre's wallet to the wallet of @beblurt account. For added privacy, I want to include a memo that only @beblurt can read.
To execute this operation, we'll use the dblurt library, and the code required for it is provided below.
/** import dBlurt */
import { Client, PrivateKey, PublicKey, encodeMemo } from "@beblurt/dblurt"
/** Prepare the dblurt with the RPC node to use */
const client = new Client(['https://rpc.beblurt.com'], { timeout: 1500 })
/**
* Encoding the memo
*/
const senderPrivateMemoKey = PrivateKey.from('5XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX') // @nalexadre private memo key
const receiverPublicMemoKey = PublicKey.from('BLTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX') // @beblurt public memo key
/** Prepare the memo by adding # at the beginning to specify that the memo must be encrypted */
const memo = "#my message that only @beblurt can decode with his private MEMO key"
/** Encode the Memo */
const encryptedMemo = encodeMemo(memo, senderPrivateMemoKey, receiverPublicMemoKey)
/** Broadcast the transfer operation */
client.broadcast.transfer({ from: 'nalexadre', to: 'beblurt', amount: '1.000 BLURT', memo: encryptedMemo}, privateActiveKey)
.then(r => console.log(r))
.catch(e => console.log(e))
After receiving the transfer, @beblurt will only need to decode the Memo using the method outlined below.
/** import dBlurt */
import { PrivateKey, decodeMemo } from "@beblurt/dblurt"
/**
* Decoding the memo
*/
const receiverPrivateMemoKey = PrivateKey.from('5XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX') // @beblurt private memo key
const memo = decodeMemo(operation['memo'], receiverPrivateMemoKey)
console.log('[memo]', decodedMemo)
I also added 2 new functions in the client.condenser
class which are getProposals
to get the list of Proposals for the Decentralized BLURT Fund and getProposalVotes
for the list of voters to the proposals. More info: https://dblurt.beblurt.com/classes/condenserapi.html#getproposalvotes
dblurt is available on:
gitlab: https://gitlab.com/beblurt/dblurt
npm: https://www.npmjs.com/package/@beblurt/dblurt
and a documentation generated using TypeDoc is available at https://dblurt.beblurt.com/
Witnesses
You are not a dev but still want to support the development on Blurt? It's easy and it doesn't cost you anything!
Just vote for my witness here: https://beblurt.com/@nalexadre/witness
or here https://blurtwallet.com/~witnesses?highlight=nalexadre
And/or for the many other developers on Blurt with a Witness ;)
https://beblurt.com/witnesses
Have fun
@nalexadre
