4.5. Access-Control-List
Last updated
Last updated
Access-Control-Lists (ACLs) are specific limitations that can be enforced on transactions of a given token. ACLs make it possible to issue or update security tokens in compliance with company policies or other legal requirements: receiving addresses can be whitelisted or blacklisted, and in general, ACLs provide conditions on how tokens can be spent, determining how non-fungible the token is. For example, they can make it impossible to transfer a certain amount of tokens per transaction under a minimum or over a maximum threshold or enforce a time lock that limits the token’s transferability at a particular time.
ACL conditions can be implemented on RAS tokens, and token issuers can update these conditions merely by creating a new transaction on Sequentia containing the updated rules. Such centralized governance of ACL rules is possible only if it is established in the set of rules originating from the token’s creation. To update an ACL, token issuers could also require executing a particular script or signing a transaction with a particular set of keys (such as n of m multi-sig).
Access-Control-Lists (ACLs) act as a filter dedicated to limiting the transferability properties of a token. By default, any address can transfer and use a token without limitations unless the token creator defined some ACL during its issuance. Among the rules to be defined, token issuers should decide on the possibility (or impossibility) of changing the ACL rules in the future, such as once the token has been issued on the network, as well as whether some rules should be changeable while others are not, and to whom the rights to change the rules (if any) should be conferred.
One possible purpose of ACLs is to enable peer-to-peer trading and transfer of security tokens that need to comply with particular company policies or legislation. Different limits can be enforced on a transaction’s input or output.
On the input side:
It is possible to enforce an upper or lower bound on the amount transferred;
Timelocks can be enforced (i.e., the UTXO cannot be spent until block x);
A particular address can be blocked so that all UTXOs from that address are frozen and cannot be transferred.
On the output side, it is possible to make it so:
Only specific addresses can receive a transaction: in this case, the standard policy is to deny the transaction unless the requirement is met (the output address is whitelisted);
A specific address cannot receive a transaction: in this case, the standard policy is to allow any transaction unless the restriction is met (the output address is blacklisted);
A particular address can or cannot receive the transaction depending on the amount transferred (upper or lower bounds) or the lock time (Conditional whitelisting/blacklisting);
From a technical point of view, the rules are enforced through one or a series of filters and an action: allow, deny, or check:
If the action is ‘deny’, and at least one of the filters is met, then the transaction cannot be validated;
In the case of the ‘allow’ action, the transaction can be validated only if all the filters are met;
In the case of the ‘check’ action, the transaction is validated only if it meets another set of rules used for another token. The check action can be used in case of multiple tokens issued with the same policy conditions or if more tokens share a standard set of rules (recalled with check), on top of which other rules are enforced for each different token. For example, the token issuer can specify or inherit an ACL already defined by a trusted third party in charge of AML/KYC procedures.
An additional control parameter can be configured when a particular entity needs to approve each token transfer. The entity is defined as a “controller” and shall “countersign” the transaction for validation. The difference with a simple 2-of-2 multi-signature is that this ACL control rule requiring the controller’s signature can be combined with other ACL rules or any other desired multi-signature scheme for the UTXO. For example, users might use a 3-of-5 multi-sig account to hold the tokens, which can only be transferred by providing at least 3 signatures together with the controller’s signature (so that it effectively becomes a 4-of-6 scheme) and whatever other ACL rules are configured for that token. The controller can be the token issuer, a service, an identity provider, or, more generically, an oracle.
Generally, the scripts contained in ACL rules are relatively small, making them manageable for nodes to validate. They do not require much space in terms of storage unless it is necessary to blacklist and whitelist multiple addresses. For this reason, there are three different possible implementations of ACL for blacklisting and whitelisting to choose from depending on scalability considerations, such as based on the number of addresses to be blacklisted or whitelisted, as well as the expected frequency of transactions in tokens complying with ACL rules:
The list of addresses can be held off-chain by a third party that will countersign any whitelisted (or not blacklisted) transaction, like in a traditional multi-signature scheme.
The list of addresses can be written in one or more on-chain transactions. Each validator will then check if the transaction is valid according to this set of addresses, checking all transactions and blocks and adding or deleting whitelisted or blacklisted addresses to a particular ACL rule.
The list of addresses can be held off-chain by one or multiple third parties, possibly in a distributed hash table that users can freely sync. Not storing the list on-chain means the blockchain is not burdened with more data and may also help keep the list of addresses private. The list of addresses is a Merkleized binary trie (12), whose root is the only piece saved in on-chain (13) transactions containing the ACL rule, and that can be updated in the future. Each user making a transaction then needs to provide (in that same transaction) proof that the address is in the Merkleized binary trie through a Merkle audit proof (14). Therefore, the burden of proof is with users sending transactions according to their respective ACL, rather than each validator node, without weighing on the blockchain.
The first solution (countersigning each transaction) grants more scalability but requires an always-online third-party node to sign transactions.
The second solution is feasible only if the list of addresses is small and changes infrequently. Assuming a public key is 256bit, 15 whitelisted public keys weigh around 3.8KB. If, instead, the list is made of 1,000 or 10,000 elements, the cost for on-chain transaction(s) to store and maintain this list on-chain goes against any reasonable principle of scalability.
The third solution is appropriate when the number of addresses is extensive whilst the number of expected transactions in tokens complying with those rules is relatively infrequent, and/or the transactions’ value will be high enough to justify a higher-than-average fee. With this solution, it is enough to store the Merkle root on-chain rather than the entire list of addresses, making it very efficient in terms of storage. However, each transaction must carry a proof showing that it is valid, containing the Merkle audit path that proves the whitelisted address is in a leaf of the Merkle tree. The Merkle audit path is the shortest list of additional nodes in the tree required to compute the root hash for that tree. To verify that a leaf node belongs to a tree, it is only necessary to know the direct neighbouring leaf node’s hash, if any, and the neighbouring parent node hashes directly above the leaf nodes.
For example, to prove that leaf “7” is in the Merkle tree (see the figure below), it is only necessary to know leaf 8, H(C), and H(A,B). For a list of only eight addresses like this (the leaves), the Merkleized structure is inefficient: storing all addresses on-chain is better than requiring a proof that utilizes the Merkle audit path for each transaction.
However, a Merkle tree of 1 million addresses requires only 20 steps to reach the leaf from the root (15). Therefore, a high number of whitelisted addresses is feasible if transactions in that token are not that frequent and all have a relatively high value, for which it is reasonable to pay an above-average fee.
A proof that a particular element is in a tree takes O(n) time to construct where n is the number of elements in the Merkle tree but then takes only O(log n) space to store and O(log n) time to verify (16).
13. Example of merkle tree for whitelisting in Ethereum NFTs: https://medium.com/@ItsCuzzo/using-merkle-trees-for-nft-whitelists-523b58ada3f9
15. https://www.derpturkey.com/merkle-tree-construction-and-proof-of-inclusion/