aelf Tech Talks: Generating a Random Number on Blockchain Securely (ACS6)
AElf random number contract standard (ACS6)
This article focuses on common solutions for random numbers in blockchain systems, the standard interfaces provided by AElf for smart contracts that provide random numbers, and the implementation of AEDPoS contracts for ACS6.
Blockchain and random number
In blockchain development, there are several scenarios for contract-related random number applications: lotteries, verification codes, password correlations, and so on.
Since blockchain is essentially a distributed system, it requires that operation results of each node are verifiable. The traditional random number generation solutions will not create results that are consistent on different machines, ensuring that all nodes generate the same random number. As such, it is impossible not to cause excessive delays with such systems.
There are clear benefits to being able to generate a random number that is accepted within a blockchain network. There are several options available:
- A centralized party generates the random numbers. Random numbers are provided by a trusted third party (i.e. random.org).
-Commitment method (hash-commit-reveal method). As mentioned in the AElf whitepaper, the AElf mainchain consensus is used to determine both the in_value and out_value of each block to determine the production order. The block producer generates a random hash locally. After an in_value is set privately, the promise (ie out_value) is announced, where out_value = hash(in_value), and the random hash value in_value is published later at the appropriate time. Other nodes only need to verify out_value == hash(in_value). The in_value here can be thought of as a random number.
- Collect blockchain state information as a seed and generate a random number in the contract with a set algorithm. Should the algorithm become known (the code of the smart contract is public) and the correct seed obtained, the random number generated by this scheme can then be successfully predicted.
Obviously, from the perspective of decentralization, the Commitment method is the only usable solution from the above mentioned options. In this situation the main concern can be alleviated by ensuring the person making generating the random number does not secretly disclose it in advance, or use it to cheat.
However, unfortunately, in the blockchain system, this cannot be guaranteed: we cannot guarantee that the person who generates the random number will not use the information for ulterior motives, such as when the random number is used as a gamble. When the lottery is set, the producer of the random number can still suspend the disclosure of the random number even if the promise is made before the start of the game — this is equivalent to an opportunity to “play again” because if the node doesn’t disclose this random number, either the system will choose another random number from another node, or the gamble will be void.
What if stochastic number producers were prevented from choosing to stop the attack? There are a series of mature solutions, see Secret Sharing.
Example: Now there are five people A~E, each of whom has a public-private key pair. At this time, A generates a random number Random, which generates the corresponding commitment. At the same time, the random number Random is encrypted with the public keys of B, C, D and E to get four Sharing Parts. When encrypting Sharing Parts, it is guaranteed that only two people in B~E can recover Random and make Sharing Parts and Commitment public together. So even if A does not publish Random’s value for his own reasons, any two people in B~Eare capable of decrypting Sharing Parts received by themselves with their own private key, and compile two decrypted values (to be encrypted according to A). Random can then be restored. In case one or two Sharing Parts fail to recover Random, they can only assume that A decided to act maliciously from the very beginning — In this occurrence, according to the blockchain economic system, only A will be penalized. For example, the direct deduction of A’s application is referred to as the margin paid by a random number producer.
In addition, we can choose not to rely on the random number generated by an individual, but select multiple individuals’ random numbers to further calculate the hash value as the available random number in the application scenario. In this way, we can obtain random numbers within a blockchain system with more stability and security.
ACS6 — Random Number Provider Contract Standard
In a previous article, we explained AElf blockchain’s contract standard for consensus, which is actually the recommended interface for the AElf mainchain developer to implement consensus mechanisms for contract developers. With regard to random number generation, we have developed ACS6 as an interface to be implemented for any contract recommendation that provides random numbers.
Not surprisingly, ACS6 chose to abstract the Commitment scheme and get the contract standard.
The scenario that supports the use of ACS6 is as follows:
Users apply for a random number for a contract that implements ACS6, similar to sending an order.
The contract of ACS6 is implemented and some information is returned to the user, including which block height (H) the user can get a random number, and the credential T (also a hash value) the user can get for the random number.
After waiting for the blockchain height to reach the specified height H, the user sends the transaction to try to get the random number, and the credential T needs to be the parameter of the transaction.
The contract of ACS6 returns a random number according to credential T.
If the user tries to get the random number before the height H, the call fails to execute and throws an Assertion Exception, indicating that the height has not yet arrived.
Based on the above scenario, we designed ACS6 as follows:
The user sends a RequestRandomNumber transaction to apply for a random number. The contract needs to generate a token_hash for the request, and then return the token to the user along with the block height that the user can obtain the random number. When the height is reached, the user sends the GetRandomNumber transaction using the token_hash received to get an available random number. As a contract, the user-generated credentials should be cached when implementing this method. As a key of a Map, the value of the Map should define its own data structure according to the contract’s implementation of random numbers.
For example, when the AEDPoS contract implements ACS6, the value of the Map can be defined as:
Round_number indicates which previous_in_value value published by each CDC should be used in order to generate the random number applied for by the user. Order is the RandomNumberProviderControl transaction for which order applies for random number is packaged by the CDC of the round (so previous published later in the round is needed). We_in_value is the raw material for random number generation. Expected_block_height is the height of the block the user must wait for.
An implementation of AEDPoS contract for ACS6
Because of the hash-commit-reveal approach adopted in the process of advancing AEDPoS consensus, the previous_in_value published during the generation of ordinary blocks (different from extra blocks) for each CDC can be directly used as the raw material for generating random numbers. The newly published previous_in_value verification (i.e. verification hash (previous_in_value) == previous_out_value) occurs before any node executes a new block. As long as the block is successfully synchronized with the best chain, there is no need to worry about fraudulent behavior of the published previous_in_value.
Note that the implementation of this section is only an attempt after the definition of ACS6 has just been completed, and there may be significant changes at any time thereafter.
The only concern is the CDC conspiracy. Therefore, when AEDPoS implements random number generation, it does not only use a CDC’s previous_in_value to generate random number, but sets of five:
When a user requests a random number from AEDPoS, he can only wait until the last slot of the current round (extra block slot) to guarantee that the publishable previous_in_value of the current round has been published. If there is a CDC that has just been added to this round (perhaps they just solved the bifurcation), they will have no previous_in_value to publish; or they may have failed to publish previous_in_value due to local caching issues, and when it comes to the slot of additional blocks, their previous_in_value completes with the reveal stage of secret sharing. Restored — If we allow users to send GetRandomNumber transactions before the reveal phase to get random numbers, the random numbers obtained before and after the reveal phase may be inconsistent, which could cause serious issues.
When users attempt to obtain random numbers with credentials, AEDPoS collects five previous_in_values published by CDCs after users apply for random numbers, calculates a hash value with these five hashes, and returns them to users as a usable random number.
Next, BVT test cases were added to these two methods. (There is a framework for testing AElf contracts. A code generator can be used to generate a Stub that can call a contract method. The Stub can simulate user-sent transactions on a blockchain, and each transaction is packaged separately into a block.
At the beginning of the chain, the Stub of any simulated user sends the RequestRandomNumber transaction, checking to see if it can obtain an available RandomNumberOrder. Since the required contracts were deployed through a large number of transactions (currently 19) before the test case was executed, the block height reached 20 when the RequestRandomNumber was executed.
After a certain height (one round of time), the simulated user sends the GetRandomNumber transaction to get the random number. The following test cases simulate the first round of CDC for normal block operation, and also attempt to send GetRandomNumber before and after ExpectedBlockHeight. When the height is not reached, the transaction execution fails, and the error message containing “Still preparing random number.” When the second GetRandomNumber is sent, the transaction execution succeeds and the available random number is returned; and the third GetRandomNumber is sent because the information about the random number has been deleted by the AEDPoS contract.（Saving space mechanism), thus returns an empty hash value.
Other Topics in aelf Tech Talks:
— Join the Community:
· Read weekly articles on the aelf blog
· Catch up with the develop progress on Github
· Instagram: aelfblockchain
· YouTube Channel: aelf
For more information, visit aelf.io