| title | Blockchain Information and Random Number | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| actions |
|
||||||||
| material |
|
Our goal is to generate different and randomised XNA's each time the contract is run. To do that, we need random numbers. Although the deterministic nature of blockchains makes it difficult, a random number can be acquired from the consensus data on NEO's blockchain.
Blockchains are made up of 'blocks' generated in sequence. Each block contains many transactions, which record all the changes that happened on the network over the last 15 seconds. In the NEO blockchain, a block is generated roughly every 15 seconds.
The 'height' of a block is the index of the order in which the block is generated. The first block has a height of 0; And the 'current height' for the network is the height index of the latest block.
NEO provides ways to access the state of the blockchain using the Blockchain class. It is from the Neo.SmartContract.Framework.Services.Neo namespace. So to access the class, this line needs to be added at the start of your code:
using Neo.SmartContract.Framework.Services.Neo;Here are some of the useful methods from Blockchain:
Blockchain.GetBlock (uint)returns a block object from the given block heightBlockchain.GetHeight ()returns the current height of the blockchain inuintBlockchain.GetHeader (uint)returns a block header object from the given block hash (see below for block header)
See the NEO documentation for a full list of Blockchain methods.
From what we know so far, we can write something in our contract to 'ask' the network what the current height is:
uint blockHeight = Blockchain.GetHeight ();In NEO, the same contract need to be executed in different nodes, and they need to produce the same result in order to achieve censensus. Only with consensus from nodes can new blocks be added onto a blockchain, and that is precisely why blockchain works as a distributed ledger. But this kind of system must be a deterministic system, that means there can be no randomness involved in the code itself. As a result, we cannot use the Random class provided by C#.
But there is a work-around. For each block generated, the NEO blockchain produces a pseudo-random number named Consensus Data. Consensus Data is specific to this generated block, and so we need to specify block height when accessing consensus data.
For example, to access consensus data of the 1000th block, you can write:
ulong consensusData = Blockchain.GetHeader (999).ConsensusData; -
GetHeader (i)returns theHeaderobject of a designated block. Every block has aHeader. It contains the block's height, timestamp, reference to the previous block, consensus data and other variables. -
Here is NEO's documentation on
Header.
-
In
RandomNumber (), assign current blockchain height toblockHeight. -
Get consensus data at current height, and then return it.
-
In the main method, make a call to
RandomNumber (), pass it into therandomNumbervariable.