Skip to content

Instantly share code, notes, and snippets.

@SergioDemianLerner
Created October 29, 2020 18:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SergioDemianLerner/480b5d880134f4863196af9c43ae4b6e to your computer and use it in GitHub Desktop.
Save SergioDemianLerner/480b5d880134f4863196af9c43ae4b6e to your computer and use it in GitHub Desktop.
CryptoRandomBridge
pragma solidity >=0.4.0 <0.7.0;
abstract contract IBridgePrecompiledContract {
function getBtcBlockchainBlockHashAtDepth(int256 depth) public virtual view returns (bytes memory hash);
function getBtcBlockchainBestChainHeight() public virtual view returns (int height);
}
contract CryptoRandomBridge {
IBridgePrecompiledContract bridge =
IBridgePrecompiledContract(0x0000000000000000000000000000000001000006);
bool waitForRandom;
uint deadline;
function debug_queryLastBtcBlockHash() public view returns (bytes32) {
return bitcoinHeaderHash(0);
}
function isRandomValueReady() public view returns (bool) {
if (!waitForRandom)
return false;
// Assure the deadline block has been mined, and it has 6
// confirmations
return uint(bridge.getBtcBlockchainBestChainHeight())>=deadline+6;
}
function getRandomValue() public returns (bytes32) {
require(isRandomValueReady());
waitForRandom = false;
return bitcoinHeaderHash(deadline);
}
function startWaitForRandomValue() public {
// Here we must make sure that the block is "live", meanining that the attacker
// is not blocking the blocks to enter the bridge.
// For that to happen we should query the last block timestamp.
// Sadly the bridge does not have a method to return a Bitcoin header
// given its hash, or the last block header.
// It may be added in the Iris network upgrade.
uint lastBitcoinBlockTimestamp = getLastBitcoinBlockTimestamp();
if (lastBitcoinBlockTimestamp<block.timestamp-3600)
return; // no random number can be chosen now.
// Wait approximately one hour
deadline = uint(bridge.getBtcBlockchainBestChainHeight())+6;
waitForRandom = true;
}
function bitcoinHeaderHash(uint depth) public view returns (bytes32) {
bytes32 x = bytesToBytes32(bridge.getBtcBlockchainBlockHashAtDepth(int(depth)));
return x;
}
function getLastBitcoinBlockTimestamp() private view returns (uint) {
// This is mock code. In the future, if the bridge contract implements
// a method getBtcBlockchainBlockHeaderAtDepth()
// then we can grab the timestamp block that Bitcoin header.
return block.timestamp;
}
function bytesToBytes32(bytes memory source) private pure returns (bytes32 result) {
if (source.length == 0) {
return 0x0;
}
assembly {
result := mload(add(source, 32))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment