Created
January 26, 2014 12:55
-
-
Save ProTip/8632276 to your computer and use it in GitHub Desktop.
This file contains 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
// level1 project main.go | |
package main | |
import ( | |
"crypto/sha1" | |
//"fmt" | |
"bytes" | |
"encoding/binary" | |
"encoding/hex" | |
"fmt" | |
"io" | |
"log" | |
"os" | |
"os/exec" | |
//"reflect" | |
"strconv" | |
"time" | |
//"unsafe" | |
"math/rand" | |
"runtime" | |
) | |
type miner_message struct { | |
mined bool | |
commit_message []byte | |
} | |
func main() { | |
os.Chdir("/home/gzapp/projects/stripe-cft3/level1/level1") | |
max_procs := 4 | |
max_miners := 8 | |
runtime.GOMAXPROCS(max_procs) | |
log.SetOutput(os.Stderr) | |
git_tree := git_write_tree() | |
git_parent := git_parnet() | |
time := timestamp() | |
difficulty := get_difficulty() | |
//fmt.Println("Git tree is: ", string(git_tree)) | |
//fmt.Println("Git parent is: ", string(git_parent)) | |
//fmt.Println("Difficulty is: ", string(difficulty)) | |
//fmt.Println("Timestamp is: ", string(time)) | |
c1 := make(chan miner_message) | |
for i := 0; i < max_miners; i++ { | |
commit_message := construct_commit(git_tree, git_parent, time) | |
go find_coin(commit_message, difficulty, c1) | |
} | |
for i := 0; i < max_miners; i++ { | |
resp := <-c1 | |
if resp.mined == true { | |
fmt.Println(string(resp.commit_message)) | |
os.Exit(0) | |
} | |
} | |
os.Exit(1) | |
} | |
func find_coin(commit_message []byte, difficulty []byte, c chan miner_message) { | |
rng_source := rand.NewSource(time.Now().UnixNano()) | |
rng := rand.New(rng_source) | |
local_diff := make([]byte, len(difficulty), len(difficulty)) | |
start_nounce := uint64(rng.Int63()) | |
end_nounce := start_nounce + 1000000 | |
log.Println("Staring at nounce: ", start_nounce) | |
log.Println("Ending at nounce: ", end_nounce) | |
for i := start_nounce; i < end_nounce; i++ { | |
nounce_message(commit_message, uint64(i)) | |
//fmt.Println(string(commit_message)) | |
sum := git_commit_hash(commit_message) | |
//fmt.Println(string(commit_message)) | |
if compare(sum, local_diff) == -1 { | |
resp := miner_message{true, commit_message} | |
c <- resp | |
return | |
} | |
} | |
resp := miner_message{false, nil} | |
c <- resp | |
return | |
} | |
func compare(sum []byte, diff []byte) int { | |
//fmt.Println("Comparing sum: ", sum, " to difficulty: ", diff) | |
return bytes.Compare(sum, diff) | |
} | |
func git_commit_hash(message []byte) []byte { | |
commit := construct_commit_hash(message) | |
commit_reader := bytes.NewReader(commit) | |
h := sha1.New() | |
io.Copy(h, commit_reader) | |
sum := h.Sum(nil) | |
return sum[:] | |
} | |
func construct_commit_hash(message []byte) []byte { | |
var commit bytes.Buffer | |
length := len(message) | |
commit.Write([]byte("commit ")) | |
commit.WriteString(strconv.Itoa(length + 1)) | |
commit.WriteByte(byte(0x00)) | |
commit.Write(message) | |
commit.WriteByte(byte('\n')) | |
return commit.Bytes() | |
} | |
func nounce_message(message []byte, nounce uint64) { | |
nounce_slice := message[len(message)-16:] | |
b := [8]byte{} | |
binary.BigEndian.PutUint64(b[:], nounce) | |
hex.Encode(nounce_slice, b[:]) | |
} | |
func construct_commit(tree []byte, parent []byte, time []byte) []byte { | |
var message bytes.Buffer | |
message.Write([]byte("tree ")) | |
message.Write(tree[:len(tree)-1]) | |
message.Write([]byte("\n")) | |
message.Write([]byte("parent ")) | |
message.Write(parent[:len(parent)-1]) | |
message.Write([]byte("\n")) | |
message.Write([]byte("author ProTip user <greg.zapp@gmail.com> ")) | |
message.Write(time[:len(time)-1]) | |
message.Write([]byte("+0000\n")) | |
message.Write([]byte("committer ProTip user <greg.zapp@gmail.com> ")) | |
message.Write(time[:len(time)-1]) | |
message.Write([]byte("+0000\n\n")) | |
message.Write([]byte("Give me a Gitcoin\n\n")) | |
message.Write([]byte("0000000000000000")) | |
return message.Bytes() | |
} | |
func timestamp() []byte { | |
cmd := exec.Command("date", "+%s") | |
out, err := cmd.Output() | |
if err != nil { | |
panic(err.Error()) | |
} | |
return out | |
} | |
func get_difficulty() []byte { | |
cmd := exec.Command("cat", "difficulty.txt") | |
out, err := cmd.Output() | |
if err != nil { | |
panic(err.Error()) | |
} | |
zeros := []byte("0000000000000000000000000000000000000000") | |
difficulty := out[:len(out)-1] | |
difficulty_slice := zeros[:len(out)-1] | |
copy(difficulty_slice, difficulty) | |
var diff_binary = make([]byte, 40, 40) | |
hex.Decode(diff_binary, zeros) | |
return diff_binary | |
} | |
func git_parnet() []byte { | |
cmd := exec.Command("git", "rev-parse", "HEAD") | |
out, err := cmd.Output() | |
if err != nil { | |
panic(err.Error()) | |
} | |
return out | |
} | |
func git_write_tree() []byte { | |
cmd := exec.Command("git", "write-tree") | |
out, err := cmd.Output() | |
if err != nil { | |
panic(err.Error()) | |
} | |
return out | |
} | |
func trace(s string) (string, time.Time) { | |
log.Println("START:", s) | |
return s, time.Now() | |
} | |
func un(s string, startTime time.Time) { | |
endTime := time.Now() | |
log.Println(" END:", s, "ElapsedTime in seconds:", endTime.Sub(startTime)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment