At this point in our contracts, we have been working with pseudo-randomness. Our keccak256 function was a great way to get started learning about how to create smart contracts. However, as we mentioned earlier, you can run into some major issues when creating smart contracts that rely on pseudo-randomness. Everything that is part of the on-chain mechanism is deterministic by design, including our hashing function.
When we tried to get random DNA from a string, we know that the DNA we are going to get is going to be the same every single time. This means, that our randomness creation function isn't actually random! We also can't rely on someone being honest when they input a "string" into this function.
uint(keccak256(abi.encodePacked(_str)))
So how can we fix this? Well, a naive approach is to use globally available variables like msg.sender, block.difficulty, and block.timestamp. You might see references that try to get random numbers like so:
uint(keccak256(abi.encodePacked(msg.sender, block.difficulty, block.timestamp)));
In this example, the developers try to mix up all these globally available variables to make it harder to predict the number. However, even these numbers have predictability:
msg.sender is known by the senderblock.difficulty is directly influenced by the minersblock.timestamp is predictableSo now it should be clear that everything inside the blockchain is deterministic and can lead to exploits if we try to use randomness from inside the blockchain. So how can we get randomness from outside the blockchain? You guessed it, with a Chainlink Oracle!
Let's take a look back at our good friend the zombie code, where we gave our zombie some pseudo-random DNA, and let's try to fix it. This time though, we will use the secure randomness of the Chainlink Verifiable Randomness Function (Chainlink VRF).
Chainlink VRF is a way to get randomness from outside the blockchain, but in a proven cryptographic manner. This is important because we always want our logic to be truly incorruptible. Another naive attempt at getting randomness outside the blockchain would be to use an off-chain API call to a service that returns a random number. But if that services goes down, is bribed, hacked, or otherwise, you could potentially be getting back a corrupt random number. Chainlink VRF includes on-chain verification contracts that cryptographically prove that the random number the contract is getting is really random.

Now, this is where we will be introduced to the basic request model of working with oracles.
The first step is when a smart contract (called the "callee contract") makes a "request" to a Chainlink node which is comprised of a smart contract and the corresponding off-chain node. When it receives the request, the smart contract emits a specific event that the corresponding Chainlink node is subscribed to/looking for. This happens in one transaction.
The Chainlink oracle will then process the request (be it randomness, a data request, etc), and return the data/computation back to the callee contract, or a contract that will in turn send the response to the callee contract. This "middle" contract is often referred to as the "oracle contract". This return process happens in a second separate transaction, so in total the basic request model is a two transaction event, and therefore, will take at the very minimum two blocks to complete.