It has repeatedly come up in developer discussions how you would generate a random number in script, the usecase is often related to gambling or lotteries.
Deterministic Transactions
Bitcoin Cash transactions are deterministic which means the transaction will always fail/succeed with the same transaction context. This obviously means there could not be a true OP_GETRANDOMNUMBER
as this would violate this core principle.
Trusted Oracle
One solution would be to have a trusted oracle provide a random number, if this oracle is credibly neutral then this could be an option, but if âthe houseâ runs the oracle then you are essentially playing a rigged game.
Provably Fair
One interesting non-contract solution has been developed and used for a long time by Satoshi Dice: its trust model is that it is provably fair with some delay. So should the service ever do payouts dishonestly/incorrectly this would be auditable by the lack of published proof or an invalid proof. This does not mean it cannot cheat, it simply means that the service is committed to transparency and has built up reputation by having a long series of provably fair bets before hand.
from the website âProvably Fairâ page:
In order to ensure that there is no way for the system to change the outcome of a bet, the secret keys used are decided ahead of time. They are not released right away, since they could be used to submit selective transactions and win bets unfairly. However, the hash of the secrets is released and forever recorded in the blockchain. After the secrets are release users can verify that preceeding bets were provably fair.
Each bet transaction that comes in is assigned to the secret key of the current day when it is first processed. In most cases this will be as soon as the transaction is broadcast on the bitcoin network. However it could be later if the system has some problems processing or an outage. All times are in UTC (GMT).
Hashes Are Not Random
First some things which are not random:
- the transaction id is not random, it can be pre-computed and manipulated by changing inputs/outputs/locktimes before broadcasting
- blockhashes are not even truly random, if your lottery grows to millions worth of USD, you need to take into consideration that miners can manipulate the block contents and hence change the resulting hash and outcome of the contract
Just generally, hashes are not random if their underlying contents are not random, and can be manipulated by someone.
Even hashes of a random number are not random when the space of numbers is too small: you can easily pre-compute all hashes of 1 byte numbers, hence the hashes are not true one-way functions anymore.
Start of a Solution
Instead of having a trusted party generate a number or using hashes which are available on the BCH blockchain, the design will be involve having at least two parties independently generate a number and committing to this hidden number without revealing it. The numbers together can then be hashed or XORed and the result will be random if atleast one of the generated numbers is random.
Now the question becomes: if a user and a betting service would enter into a contract and they would both have to commit to a hidden number, what would their incentives be to pick a random number?
Hidden Commitments Are Not Random
Importantly we need to reason in a setting with a adversarial counterparty, and have to think about the game theory of what happens when parties act dishonestly.
The fact that unknown != random
is important for designing multi party randomness, for example in BCH Guru contracts players secretly commit to a prediction on the future price of a crypto asset, these hidden predictions are unknown from the perspective of player2 but they arenât random! Players will predict in a calculated way based on the current price and the general price momentum.
Using multi-party Commitments for Randomness
The argument from a game-theory POV is that if the counterparty would give a non random number, it would be at their disadvantage for winning the bet. This is because both numbers would be used to produce the hash so if you can get any information about the counter party number, you could pick a number that will win with greater probability by pre-calculating the hashes.
@bitcoincashautist wrote
if you want to lose you pick a guessable number. if you want the game be fair to you you gen a random number and hash it and release the hash
your counterparty does the same
then when itâs time to settle you both reveal the numbers do H(a+b) and the hash determines the winner
Simultaneous Commitments
A remaining difficulty in a setting of UTXOs and transactions is how to make sure both commitments are also tied to each other and that the commitments are revealed simultaneously, or at least in a way where neither person can still opt-out easily by double spending after the reveal.
also the last party to publish their number can publish the number itself instead of hash since there is no party after them that could try to abuse this knowledge
this makes calculating the outcome easier since at least one party donât need to reveal the number separately
So what we arrived at was similar to how BCH Guru contracts work to enable a 2 player game of hidden price predictions. For the Guru bets there are 2 smart contracts and 3 transactions for a full bet:
- offer is created by Player 1 with commits to his hidden number (prediction)
- offer is accepted by a player 2 (original uxto destroyed &hidden commitment is carried over), 2nd player does not have to hide his number (prediction)
â player 1 reveals the number of his commitmentâ - bet is resolved and resulting payouts happen
Note: Player 1 (the service) could withhold the number of his commitment, so there should be way where the contract is resolved without this information and the withholding party is punished. Withholding should not result in a better outcome than losing, so game theory matters for the implementation details.
The Guru contracts were open sourced some time ago, and have a similar mechanism already implemented and live on mainnet:
By extending the guru contracts for two-party commitments to combine both results, either through hashing or XORing, the end result would be random if either one of the numbers is random.
Interested to hear what other schemes exist for randomness in BCH Script!