|
Caution
|
Incomplete Content: Since this documentation was written a new
feature was implemented.
|
This example demonstrates a strategy for applying determinism to the task of inserting a randomly generated number into a blockchain’s state, using a simple implementation of Odd or Even.
We can handle generating randomness in an Interbit application in 2 ways:
-
Use a pseudo-random number generator inside of the smart contract with a seed value stored in state.
-
Generate a random number outside of the blockchain and dispatch the result to the chain.
The standard way to generate random data in JavaScript is with
Math.random(). Although it is a pseudo-random number generator (PRNG),
it cannot be deterministic because it does not accept a seed value. To
handle this oddness, we can simply dispatch a value from Math.random()
to the blockchain.
In the following sample is a simple smart contract that accepts an
action called RANDOM and replaces the random value in state with the
one it received from the action.
// Option 1a: Dispatch some random data to your smart contract
// ... the action
RANDOM: 'RANDOM',
random: (number) => {
return {
type: actions.RANDOM,
payload: { number }
}
},
// ... inside the smart contract
if (action.type === actions.RANDOM) {
return state.set('number', action.payload.number)
}
// ... dispatching the action
const randomInt = Math.floor(Math.random() * 100)
const randomAction = actions.random(randomInt)
chain.dispatch(randomAction)If you need something more random, then it is also possible to generate random data and dispatch that value to the blockchain as we have here.
// Option 1b: Dispatch some random data to your smart contract
// ... dispatching the action
fetchRandom()
.then(trulyRandomInt => {
const trulyRandomAction = actions.random(trulyRandomInt)
chain.dispatch(trulyRandomAction)
})
.catch(error => {
console.log(error)
})If a PRNG is given a seed value it can be used to give sufficiently random values for many purposes and arrive at the same value on every node in the blockchain. You just need to be sure that the seed value changes every time a random number is generated (in a deterministic way), otherwise the same value will be produced every time. In our case we have simply concatenated the number of times the action has been called to our initial seed value.
Option 2 in our example demonstrates this.
// Option 2: Use a seeded PRNG to make a deterministic "random" value
// ... the action
PSEUDO_RANDOM: 'PSEUDO_RANDOM',
pseudoRandom: () => {
return {
type: actions.PSEUDO_RANDOM,
payload: { }
}
}
// ... inside the smart contract
if (action.type === actions.PSEUDO_RANDOM) {
const seed = state.seed + state.times
const prng = seedrandom(seed)
const prNumber = Math.floor(prng() * 100)
state = state.set('number', prNumber)
state = state.set('times', state.times + 1)
return state
}
// ... dispatching the action
const pseudoRandomAction = actions.pseudoRandom()
chain.dispatch(pseudoRandomAction)Here are some questions that may help when faced with non-determinism:
-
Do you really need that UUID as a key for your items or can you store them in an array?
-
Could you use a nonce instead?
-
Does the data you are storing in a file truly need to be on file or can it be loaded on the chain and used that way?
Ultimately, the decision will be based on the requirements of the project but how you handle it will make all the difference in a well written Interbit application.
|
Caution
|
Incomplete Content: Since this documentation was written a new
feature was implemented.
|