Created
October 29, 2020 18:45
-
-
Save SergioDemianLerner/480b5d880134f4863196af9c43ae4b6e to your computer and use it in GitHub Desktop.
CryptoRandomBridge
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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