Skip to content

Instantly share code, notes, and snippets.

Created June 20, 2016 19:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save anonymous/0a3b2af1710cbc96d8f4b7a95f9fb2a0 to your computer and use it in GitHub Desktop.
Save anonymous/0a3b2af1710cbc96d8f4b7a95f9fb2a0 to your computer and use it in GitHub Desktop.
Created using browser-solidity: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://ethereum.github.io/browser-solidity/#version=soljson-latest.js&optimize=undefined&gist=
contract fakeRelay {
bytes header;
function fakeRelay(bytes head){
header = head;
}
function getBlockHeader(uint) constant returns (bytes){
return header;
}
function getFeeAmount(uint) returns (uint) {
return 0;
}
}
import "./fake.sol";
contract BTCRelay {
function getBlockHeader(uint blockHash) returns (byte[112]);
function getLastBlockHeight() returns (uint);
function getBlockchainHead() returns (uint);
function getFeeAmount(uint blockHash) returns (uint);
}
contract BlockhashFetch {
BTCRelay relay;
mapping(uint => uint) blockHashes;
function BlockhashFetch(address _relay){
relay = BTCRelay(_relay);
}
function getPrevHash(uint prevHash) returns (bytes32 hash){
//uint fee = relay.getFeeAmount(prevHash);
bytes4 sig = bytes4(sha3("getBlockHeader(int256)"));
bytes[128] memory header;
address r = address(relay);
bytes32 temp;
assembly {
mstore(0,mload(sig))
mstore(4,prevHash)
call(1000000, r, 0, 0, 0x24, add(header,0x20), 128)
//mstore(header, 80)
temp := mload(add(header,0x44))
}
/*
for(uint i; i<32; i++){
hash = hash | bytes32(uint(temp[i]) * (0x100**i));
}
*/
return temp;
}
}
library ProofLib {
struct Proof {
address defender;
address challenger;
bytes32 lVal;
bytes32 rVal;
uint lIndex;
uint rIndex;
uint roundTime;
uint lastRound;
bytes32 currentVal;
//TODO: Implement non-participation resilliancy
}
function newChallenge(Proof storage self, address _defender, address _challenger, bytes32 seed, bytes32 result, uint difficulty, uint time) {
self.defender = _defender;
self.challenger = _challenger;
self.lVal = seed;
self.rVal = result;
self.lIndex = 0;
self.rIndex = difficulty;
self.roundTime = time;
self.lastRound = block.number;
}
function challenge(Proof storage self, bool correct) {
if (self.currentVal == 0 || msg.sender != self.challenger) throw;
if (correct) {
self.lIndex = (self.lIndex + self.rIndex) / 2;
self.lVal = self.currentVal;
} else {
self.rIndex = (self.lIndex + self.rIndex) / 2;
self.rVal = self.currentVal;
}
self.currentVal = 0;
}
function respond(Proof storage self, bytes32 hash) {
if (self.currentVal != 0 || msg.sender != self.defender) throw;
self.currentVal = hash;
}
function finalize(Proof storage self) returns(bool confirmed) { //returns true if challenge successfully disproves proposal
if (self.rIndex - self.lIndex <= 3) {
bytes32 hash = self.lVal;
for (uint i; i < self.rIndex - self.lIndex; i++) {
hash = sha3(hash);
}
if (hash == self.rVal) {
return false;
} else {
return true;
}
} else throw;
}
function getProof(Proof storage self) constant returns(uint,uint,bytes32,bytes32,bytes32){
return (self.lIndex, self.rIndex, self.lVal, self.currentVal, self.rVal);
}
function test() returns(uint){
return 5;
}
}
import "ProofLib.sol";
contract RanDAOPlus {
using ProofLib for ProofLib.Proof;
//EVENTS FOR DEBUGGING ONLY
uint constant timeout = 10;
uint constant difficultyTarget = 6;
uint constant proofRoundTime = 5;
uint difficulty;
mapping(uint => bytes32) finalizedRandomNumbers; //Maps block numbers to random numbers: One random number is generated per block
struct Proposal {
uint block;
bytes32 proposal;
uint deposit;
address depositor;
mapping(address => ProofLib.Proof) challenges;
bool disproven;
}
struct PendingBlock {
uint blockNumber;
uint difficulty;
uint depositLimit;
mapping(bytes32 => uint) depositTotals;
mapping(address => Proposal) proposals;
mapping(bytes32 => uint) submissionTimes;
bytes32 topProposal;
uint timer;
}
mapping(uint => PendingBlock) pending;
function submitProposal(uint blockNum, bytes32 proposal) {
if (finalizedRandomNumbers[blockNum] != 0 || pending[blockNum].blockNumber == 0) throw;
Proposal prop = pending[blockNum].proposals[msg.sender];
prop.block = blockNum;
prop.proposal = proposal;
prop.deposit = msg.value;
prop.depositor = msg.sender;
pending[blockNum].depositTotals[proposal] += msg.value;
if (pending[blockNum].depositTotals[proposal] > pending[blockNum].depositTotals[pending[blockNum].topProposal] && pending[blockNum].depositTotals[proposal] > pending[blockNum].depositLimit) {
pending[blockNum].topProposal = proposal;
pending[blockNum].timer = blockNum + timeout;
}
if (pending[blockNum].submissionTimes[proposal] == 0) {
pending[blockNum].submissionTimes[proposal] = block.number;
}
}
function newChallenge(uint blockNum, address defender) {
ProofLib.Proof proof = pending[blockNum].proposals[defender].challenges[msg.sender];
proof.newChallenge(defender, msg.sender, block.blockhash(blockNum), pending[blockNum].proposals[defender].proposal, pending[blockNum].difficulty, proofRoundTime);
pending[blockNum].depositTotals[pending[blockNum].proposals[defender].proposal] -= pending[blockNum].proposals[defender].deposit;
}
function challenge(uint block, address defender, bool correct) {
pending[block].proposals[defender].challenges[msg.sender].challenge(correct);
}
function respond(uint block, address challenger, bytes32 response) {
pending[block].proposals[msg.sender].challenges[challenger].respond(response);
}
function finalize(uint blockNum, address defender, address challenger) {
ProofLib.Proof proof = pending[blockNum].proposals[defender].challenges[challenger];
bool challengeSuccessful = proof.finalize();
distributeRewards(proof, challengeSuccessful, blockNum);
delete pending[blockNum].proposals[defender].challenges[challenger];
}
function distributeRewards(ProofLib.Proof proof, bool challengeSuccessful, uint blockNum) private { //Make sure loopback attacks not possible
if (challengeSuccessful) {
proof.challenger.send(pending[blockNum].proposals[proof.defender].deposit * 2);
pending[blockNum].proposals[proof.defender].disproven = true;
} else {
proof.defender.send(pending[blockNum].proposals[proof.defender].deposit);
}
}
function challengeTimeout(uint blockNum, bool isDefender, address opponent) {
ProofLib.Proof proof;
if (isDefender) {
proof = pending[blockNum].proposals[msg.sender].challenges[opponent];
} else {
proof = pending[blockNum].proposals[opponent].challenges[msg.sender];
}
if (proof.roundTime + proof.lastRound < block.number) {
if (proof.currentVal == 0) {
distributeRewards(proof, true, blockNum);
} else {
distributeRewards(proof, false, blockNum);
}
}
}
function finalizeNumber(uint blockNum) {
if (pending[blockNum].topProposal != 0 && pending[blockNum].timer <= block.number) {
finalizedRandomNumbers[blockNum] = pending[blockNum].topProposal;
adjustDifficulty(blockNum - pending[blockNum].submissionTimes[pending[blockNum].topProposal]);
delete pending[blockNum];
}
}
function adjustDifficulty(uint blocksToVerify) {
difficulty = difficultyTarget / blocksToVerify * difficulty; //TODO: Simulate network difficulty adjustment -- optimise algo
}
function sha(bytes32 seed) constant returns(bytes32){
return sha3(seed);
}
function getProof(uint blockNum, address defender, address challenger) constant returns (uint,uint,bytes32,bytes32,bytes32){
return pending[blockNum].proposals[defender].challenges[challenger].getProof();
}
function test() returns (uint){
return ProofLib.test();
}
function blocknum() constant returns(uint,bytes32){
return (block.number,block.blockhash(block.number-1));
}
}
library TestLib {
function test() constant returns (uint){
return 3;
}
}
contract Test1 {
function add(int a, int b) returns(int){ //Simply add the two arguments and return
return a+b;
}
function() returns (int){ //If the function signature doesn't check out, return -1
return -1;
}
}
contract Test2 {
Test1 test1;
function Test2(){ //Constructor function
test1 = new Test1(); //Create new "Test1" function
}
function test(int a, int b) constant returns (int c){
address addr = address(test1); //Place the test1 address on the stack
bytes4 sig = bytes4(sha3("add(int256,int256)")); //Function signature
assembly {
let x := mload(0x40) //Find empty storage location using "free memory pointer"
mstore(x,sig) //Place signature at begining of empty storage
mstore(add(x,0x04),a) //Place first argument directly next to signature
mstore(add(x,0x24),b) //Place second argument next to first, padded to 32 bytes
call(5000, addr, 0, //Issue call, providing 5k gas and 0 value to "addr"
x, 0x44, add(x,0x80), 0x20) //Inputs start at location "x" and are 68 bytes long, outputs start 128 bytes after x, and are 32 bytes long
c := mload(add(x,0x80)) //Assign output value to c
mstore(0x40,add(x,0x100)) // Set storage pointer to empty space
}
}
function test2(int a, int b) constant returns(int c){ //Make sure the Test1 function works properly
return test1.add(a,b); // (It does)
}
}
contract hashTest{
byte[] test;
function extract (uint i, bytes blockHeader) returns(bytes32 blockhash){
bytes32 hash;
hash = blockHeader[i];
return hash;
}
function swap(bytes32 header) returns (bytes32 hash){
for(uint i; i<32; i++){
hash = hash | bytes32(uint(header[i]) * (0x100**i));
}
}
function slice(bytes header) returns(bytes32 hash){
for(uint i = 4; i<36 ; i++){
hash = hash | bytes32(uint(header[i]) * (0x100**(i-4)));
}
}
function echo (bytes a) constant returns (bytes32 x){
assembly {
x := mload(add(a,0x24))
}
}
function sha(bytes32 a) constant returns (bytes32 b){
return sha3(a);
}
}
contract BTCRelay {
function getBlockHeader(uint blockHash) returns (byte[112]);
function getLastBlockHeight() returns (uint);
function getBlockchainHead() returns (uint);
function getFeeAmount(uint blockHash) returns (uint);
}
contract fetch{
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment