Skip to content

Latest commit

 

History

History
104 lines (73 loc) · 4.62 KB

File metadata and controls

104 lines (73 loc) · 4.62 KB
title Blockchain Information and Random Number
actions
checkAnswer
hints
material
editor
language startingCode answer
c#
public class AlienFinder : SmartContract { public class Alien { public uint xna; public string alienName; } public static void Main (string alienName) { ulong randomNumber; // Enter (3) here uint xna; Alien someAlien = new Alien (); } private static ulong RandomNumber () { uint blockHeight // Enter (1) here // Enter (2) here } private static uint FindXna (ulong randomNumber) { } }
public class AlienFinder : SmartContract { public class Alien { public uint xna; public string alienName; } public static void Main (string alienName) { ulong randomNumber = RandomNumber (); uint xna; Alien someAlien = new Alien (); } private static ulong RandomNumber () { uint blockHeight = Blockchain.GetHeight (); return Blockchain.GetHeader (blockHeight).ConsensusData; } private static uint FindXna (ulong n) { } }

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.

Blocks

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 height
  • Blockchain.GetHeight () returns the current height of the blockchain in uint
  • Blockchain.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 ();

Random Number

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 the Header object of a designated block. Every block has a Header. It contains the block's height, timestamp, reference to the previous block, consensus data and other variables.

  • Here is NEO's documentation on Header.

Instructions:

  1. In RandomNumber (), assign current blockchain height to blockHeight.

  2. Get consensus data at current height, and then return it.

  3. In the main method, make a call to RandomNumber (), pass it into the randomNumber variable.