Create Publication

We are looking for publications that demonstrate building dApps or smart contracts!
See the full list of Gitcoin bounties that are eligible for rewards.

Tutorial Thumbnail
Intermediate · 1 hour

Hybrid Online / Offline Shared Management of Community ASA through Multisig Account

In this video tutorial you will learn how to share the management of a “Community Membership ASA” among the Community Board members with a Multisignature Account using a hybrid Online / Offline approach.

With this “hybrid approach” not all addresses in the Multisignature Account need to run a node synchronized with the MainNet to operate, which facilitates the sharing of ASA management. The signatures necessary to authorize the transactions from a Multisignature Account can be performed Offline by the Community Board members. For this reason, in this tutorial we will teach you how to complete the task on the command line with the goal and algokey utilities.

We can think about this hybrid approach through an analogy. Imagine a group of people who need to register a contract with a notary. To validate the contract, the stakeholders must sign it. At a high-level, the process would look something like this:

Step Description On Algorand
1 Write the terms of the contract An account generates a raw unsigned transaction into a file offline.txn
2 Sign the contract Accounts append their digital signatures to the raw transaction file offline.txn
3 Register the contract with the notary The signed raw transaction file is pushed online to the network.

We will go through each step together, then the video will show you the whole process actually executed by the Community Board members.

Requirements

Background

“Blockchain e dintorni” is an Italian MeetUp born around an open community of enthusiasts of the crypto scene. As part of the community management process the Community Board decided to tokenize the community affiliation on Algorand through a “Community Membership Algorand Standard Asset”. Owning this ASA, each member of the community can take part, for example, in the future community’s open decision-making processes.

The properties of the Algorand Standard Asset “BED” were determined by the community members themselves collectively, through an online survey, in which each member expressed their preferences on the ASA’s characteristics (like asset name, unit name, total supply, decimals, etc.) as well as the ASA’s management properties.

The ASA creation process was livestreamed during a community MeetUp in which the asset create and asset config transactions and subsequent distribution of “BED” were carried out on the command line using goal. The whole process is demonstrated in the video tutorial below (starting at minute 54:50).

“Blockchain e Dintroni” Community ASA: livestream creation and configuration (in Italian with English subtitles)

Steps

1. Introduction

This is a follow-on tutorial for the Community Membership ASA based on “Blockchain e dintorni” (BED). In Background video tutorial above, we tackled the process of creating and configuring the ASA in small steps according to community preferences. Now we will take it a step further! As usual, let’s lay out the use case.

USE-CASE: “Blockchain e dintorni” is an Italian MeetUp born around an open community of enthusiasts of the crypto scene. This is why the MeetUp board members want the BED “Community Token”, created as a digital representation of community membership, to be managed collectively by the MeetUp’s Board members.

To implement this management scheme we will use Algorand Multisignature Accounts. To let the Board manage the community ASA, we will assign its manager address and reserve address to the Multisignature Account.

From now on in the tutorial, we will refer to the Board members and their respective public keys, in this way:

  1. Riccardo Account Standalone Public Address: <ADDR_RICC>
  2. Giovanna Account Standalone Public Address: <ADDR_GIOVA>
  3. Giancarlo Account Standalone Public Address: <ADDR_GIANCA>
  4. Cosimo Account Standalone Public Address: <ADDR_CUSMA>

In designing our Multisignature management scheme we will take advantage of the fact that not all the addresses in the Multisignature account need to run a node synchronized to MainNet to operate. A transaction from a Multisignature Account can be signed offline. This tutorial will teach you how to complete this task via CLI through the goal and algokey utilities.

Specifically, we will create the Multisignature Account <ADDR_MULTISIG_BED> composed of 4 Standalone Accounts of the MeetUp’s Board members: <ADDR_RICC>, <ADDR_GIOVA>, <ADDR_GIANCA> and <ADDR_CUSMA>. We make the following assumptions about the board members:

  1. <ADDR_CUSMA>, runs a node synchronized with the MainNet, and will execute only online operations with goal.
  2. <ADDR_RICC>, <ADDR_GIOVA> and <ADDR_GIANCA>, do not run nodes synchronized with the MainNet, and will execute only offline operations using the algokey utility (on MAC, Linux or Windows systems).

The tutorial specifies whether the commands are executed online or offline.

Let’s go!


Learn More
- Algorand Standard Assets properties and configuration

2. Offline Creation of the Board’s Multisignature Account

Algorand Multisignature Accounts are logical representations of an ordered set of public keys for which a [--threshold] is defined. The threshold is the minimum number of signatures necessary to authorize any transaction with this Multisignature Account.

Multisignature Accounts can perform the same operations as other accounts, such as sending transactions and participating in the PPoS consensus protocol. The public address of a Multisignature Account is essentially a hash of the ordered list of public keys and the [--threshold]. Hash functions are very sensitive to any small variation of the inputs, so the public address of the Multisignature Account obtained as a logical representation of the ordered series:

  1. Public Address <ADDR_RICC>
  2. Public Address <ADDR_GIOVA>
  3. Public Address <ADDR_GIANCA>
  4. Public Address <ADDR_CUSMA>

Will be totally different from what you get as a logical representation of the ordered series:

  1. Public Address <ADDR_GIOVA>
  2. Public Address <ADDR_RICC>
  3. Public Address <ADDR_CUSMA>
  4. Public Address <ADDR_GIANCA>

Important

Although the creation of a Multisignature public address is sensitive to the order of Standalone public addresses from which it is composed, this does not apply to signing. A transaction from a multisignature account can be signed in any order.

Important

Multisignature Accounts cannot be nested in other Multisignature Accounts.

<ADDR_CUSMA> is currently the creator address of the community ASA. The Board has stated that <ADDR_GIANCA> will generate a Multisignature Account using the following list of 4 public addresses: <ADDR_RICC>, <ADDR_GIOVA>, <ADDR_GIANCA>, <ADDR_CUSMA> with [--threshold] 2. So, the Board will be represented by a [2/4] Multisignature Account, meaning that any transaction needs 2 signatures out of 4 to be authorized.

To do so, Gianca will use the goal account multisig new command from the CLI.

Offline Input

$ ./goal account multisig new --threshold 2 <ADDR_RICC> <ADDR_GIOVA> <ADDR_GIANCA> <ADDR_CUSMA> \
--datadir <node_data_directory> \
--wallet <node_wallet_name>

Output

<ADDR_MULTISIG_BED>

The public key <ADDR_MULTISIG_BED> has been generated purely offline. This means that at this point nobody outside of Gianca is aware of its existence yet, unless of course they also used the same public addresses in the same order to generate this address.

3. Online Activation of Board’s Multisignature Account

In order to make the blockchain aware of the existence of the Board’s Multisignature public key we need to send it some funds. In other words, we will turn it into an actual Online Multisignature Account by funding it with at least with 0.1 ALGO.

<ADDR_CUSMA>, the only one that can execute Online transactions, decides to send 1 ALGO (expressed as 1,000,000 microALGO) to <ADDR_MULTISIG_BED>:

Online Input

$ ./goal clerk send \
--amount 1000000 \
--from <ADDR_CUSMA> \
--to <ADDR_MULTISIG_BED> \
--datadir <node_data_directory> \
--wallet <node_wallet_name>

Output

<SEND_TX_ID>

Now <ADDR_MULTISIG_BED> has been initialized and everybody is publicly aware of its existence on the blockchain!


Learn More
- Algorand Accounts Initialization

4. Multisignature ASA Opt-In Transaction

Before being able to receive any ASA, accounts must voluntarily accept to receive them. This acceptance of a specific ASA prevents Accounts from being spammed by undesired ASAs which would increase their minimum balance requirement. This authorization is carried out through an opt-in transaction.

In order to become the reserve address (i.e. hold the unminted funds) of the Community Token, the new Multisignature Account <ADDR_MULTISIG_BED> must execute an opt-in transaction for this ASA! Once the opt-in transaction has been performed, we will be able to transfer the entire ASA supply to the Multisignature Account.

An account opt-in transaction for a specific ASA is equivalent to a send transaction of zero amount of the ASA from the account to itself.

To perform this hybrid offline / online opt-in transaction, it is necessary to:

  1. Create the transaction and write it to a file.
  2. Sign the raw opt-in transaction with at least two signatures.
  3. Push the signed opt-in transaction online to the network.

Learn More
- Receiving an Asset

5. Offline Multisignature Account Opt-In Transaction Creation

All offline parties use goal to write raw transactions or signatures to files. You may think of a raw unsigned transaction file as a contract, written on paper by a third party, that needs to be signed by the counterparts in order to be executed.

Since offline raw transaction creation and signing are asynchronous with respect to online submission, it is worth spending some time understanding the concept of transactions’ round validity range.

Important

Algorand’s transactions are characterized by a validity range, expressed as the number of blocks between a [--firstvalid] block and a [--lastvalid] block declared with command line flags. The maximum validity range is 1000 blocks.

When a transaction is generated, signed and pushed while synced with a node, the [--firstvalid] block usually coincides with the current MainNet block.

On the other hand, when a transaction is meant to be authorized offline, it is important to take into account the time required to complete the whole authorization process. For the offline case we must tune the transaction’s “validity range”, picking a future [--firstvalid] block according to when it is expected to be pushed to the network.

Calculation of future [--firstvalid] blocks depends on block throughput, which generally varies with the performance of the consensus protocol. Algorand’s Pure PoS generates, on average, one block every 4.5 seconds (1000 blocks therefore corresponds to about 1 hour and 25 minutes).

<ADDR_GIANCA> has been commissioned by the Board to create the unsigned_transaction.txn file, containing the opt-in transaction. <ADDR_GIANCA> must specify [--firstvalid] and [--lastvalid] flags that take into account the time delay between the offline transaction generation and signing and the online submission of the fully authorized transaction.

Offline Input

$ ./goal asset send \
--amount 0 \
--assetid <ASSET_ID> \
--creator <ADDR_ASA_CREATOR> \
--from <ADDR_MULTISIG_BED> \
--to <ADDR_MULTISIG_BED> \
--firstvalid <first_valid_block_number> \
--lastvalid <last_valid_block_number> \
--out "unsigned_transaction.txn" \
--datadir <node_data_directory> \
--wallet <node_wallet_name>

Output

unsigned_transaction.txn

Tips

The transaction file’s extension is completely arbitrary. We suggest the following good practice to avoid confusion between unsigned transaction files and signatures files: use “.txn” for unsigned transactions, “.sig” for partial signatures and “.stxn” for signed transactions.

The raw transaction has been written offline to unsigned_transaction.txn file, now it must be signed by at least 2 addresses of the Multisignature Account. So, <ADDR_GIANCA> sends the raw unsigned transaction to <ADDR_RICC> and <ADDR_GIOVA> and asks them to sign it.


Learn More
- Sending a transaction in the future

6. Offline Signing using algokey

Once <ADDR_RICC> and <ADDR_GIOVA> receive the raw unsigned transaction they have to sign it. As we pointed out in the introduction neither <ADDR_RICC> nor <ADDR_GIOVA> run a node, their Standalone Accounts were created on an Algorand Mobile Wallet that does not support Multisignatures yet. How should they sign the transaction then? The signing process can be executed offline using the command line utility algokey.

The algokey utility allows you to sign transactions with only the mnemonic passphrases, and without having to import any Standalone Account into a wallet or in memory.

Both <ADDR_RICC> and <ADDR_GIOVA> will sign the unsigned_transaction.txn file. Each address appends its own digital signature via the CLI using the command algokey multisig:

<ADDR_RICC> Offline Input

$ ./algokey multisig \
--txfile "unsigned_transaction.txn" \
--outfile "ricc_signature.sig" \
--mnemonic "RICC_ADDR MNEMONIC PASSPHRASE"

Output

ricc_signature.sig

<ADDR_GIOVA> Offline Input

$ ./algokey multisig \
--txfile "unsigned_transaction.txn" \
--outfile "giova_signature.sig" \
--mnemonic "GIOVA_ADDR MNEMONIC PASSPHRASE"

Output

giova_signature.sig

The signing process is performed independently by the accounts <ADDR_RICC> and <ADDR_GIOVA>. The order of appending signatures is irrelevant. The files “.sig” thus generated, containing partially signed transactions, are sent to <ADDR_GIANCA> who will merge them into a signed transaction.


Learn More
- Algorand ALGOKEY CLI

7. Offline Signatures Merging

The files ricc_signature.sig and giova_signature.sig must be merged to authorize the transaction from the Multisignature Account. <ADDR_GIANCA> executes the command [goal clerk multisig merge] to generate the single file signed_transaction.stxn:

Offline Input

$ ./goal clerk multisig merge \
"ricc_signature.sig" \
"giova_signature.sig" \
--out "signed_transaction.stxn" \
--datadir <node_data_directory>

Output

signed_transaction.stxn

At this point the Board has generated the single file signed_transaction.stxn containing the transaction signed by at least 2 private keys. <ADDR_GIANCA> just needs to send the signed transaction to <ADDR_CUSMA> who will push it onto the blockchain!

8. Online Transaction Sending

The signed_transaction.stxn file containing the signed transaction can now be pushed to the network by Cosimo (the one with the synced node), who will send the transaction written to a file using the [goal clerk rawsend] command. This must be done from a node synchronized with the MainNet.

Online Input

$ ./goal clerk rawsend \
--filename "signed_transaction.stxn" \
--datadir <node_data_directory>

Output

<SEND_TX_ID>

<ADDR_MULTISIG_BED> is now ready to receive the community ASA!

9. Online Multisignature ASA Configuration

<ADDR_CUSMA>, the original asset creator, must now transfer its ASA management powers to the newly created Multisignature Account. To do so he will perform the [asset config] transaction to set <ADDR_MULTISIG_BED> as manager address and reserve address of the community ASA, referring to his AssetID:

Online Input

$ ./goal asset config \
--assetid <ASSET_ID> \
--creator <ADDR_ASA_CREATOR> \
--manager <ADDR_CUSMA> \
--new-manager <ADDR_MULTISIG_BED> \
--new-reserve <ADDR_MULTISIG_BED> \
--datadir <node_data_directory> \
--wallet <node_wallet_name>

Output

<ASSET_CONFIG_TX_ID>

As the MeetUp’s Board stated, from now on <ADDR_MULTISIG_BED> is officially in charge of the community ASA management!

10. Online ASA Total Supply Transferring

Both the ASA management and the “unminted” ASA reserve are entrusted to the Board’s Multisignature Account. The reserve address is only a logical representation of the distinction between circulating supply and the unminted supply. Changing the reserve address does not automatically mean transferring the unminted supply, which is still in the hands of the asset creator. It is therefore necessary that the asset creator transfers all the remaining supply to the new reserve address assigned to Multisignature Account:

Online Input

$ ./goal asset send \
--amount <remaining_supply> \
--assetid <ASSET_ID> \
--creator <ADDR_ASA_CREATOR> \
--from <ADDR_ASA_CREATOR> \
--to <ADDR_MULTISIG_BED> \
--datadir <node_data_directory> \
--wallet <node_wallet_name>

Output

<ASSET_SEND_TX_ID>

Now the Multisignature Account actually owns the ASA supply as the reserve address.

11. Conclusion

Finally, as requested, the MeetUp’s Board of organizers shares the control of the community ASA through a Multisignature Account. The whole process required only one member to interact online from a node synchronized with the MainNet, while 80% of the process was conducted completely offline.

The advantages of having shared the management of the ASA through a Multisignature Account are:

  1. The management of the ASA is shared between the organizers of the MeetUp. No one can act independently without agreeing with others.
  2. A Multisignature Account improves the security of the community asset. In fact, in order to be able to transfer the ASA, a possible “malicious” adversary would need to know a number of private keys at least equal to the threshold.

12. Video tutorial