Skip to content

Instantly share code, notes, and snippets.

@ProTip
Created January 26, 2014 12:55
Show Gist options
  • Save ProTip/8632276 to your computer and use it in GitHub Desktop.
Save ProTip/8632276 to your computer and use it in GitHub Desktop.
// 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