Skip to content

Instantly share code, notes, and snippets.

@gtfierro
Last active January 4, 2016 07:09
Show Gist options
  • Save gtfierro/8587176 to your computer and use it in GitHub Desktop.
Save gtfierro/8587176 to your computer and use it in GitHub Desktop.
GITCOIN
#!/bin/bash
set -eu
if [ "$#" != 2 ]; then
echo >&2 "Usage: $0 <clone_url> <public_username>
A VERY SLOW mining implementation. This should give you an idea of
where to start, but it probably won't successfully mine you any
Gitcoins.
Arguments:
<clone_url> is the string you'd pass to git clone (i.e.
something of the form username@hostname:path)
<public_username> is the public username provided to you in
the CTF web interface."
exit 1
fi
export clone_spec=$1
export public_username=$2
start=0
prepare_index() {
perl -i -pe 's/($ENV{public_username}: )(\d+)/$1 . ($2+1)/e' LEDGER.txt
grep -q "$public_username" LEDGER.txt || echo "$public_username: 1" >> LEDGER.txt
git add LEDGER.txt
}
solve() {
# Brute force until you find something that's lexicographically
# small than $difficulty.
difficulty=$(cat difficulty.txt)
# Create a Git tree object reflecting our current working
# directory
tree=$(git write-tree)
parent=$(git rev-parse HEAD)
timestamp=$(date +%s)
echo "Tree" $tree
echo "Parent" $parent
echo "Timestamp" $timestamp
#while let counter=counter+1; do
printbody="tree $tree
parent $parent
author CTF user <me@example.com> $timestamp +0000
committer CTF user <me@example.com> $timestamp +0000
Give me a Gitcoin
"
printf "$printbody" > in.com
counter=$(/Users/gabe/src/stripe-ctf/level1/sha1 1000000000)
echo "counter" $counter
body="tree $tree
parent $parent
author CTF user <me@example.com> $timestamp +0000
committer CTF user <me@example.com> $timestamp +0000
Give me a Gitcoin
$counter"
# See http://git-scm.com/book/en/Git-Internals-Git-Objects for
# details on Git objects.
sha1=$(git hash-object -t commit --stdin <<< "$body")
echo "computed sha1" $sha1
if [ "$sha1" "<" "$difficulty" ]; then
echo
echo "Mined a Gitcoin with commit: $sha1"
git hash-object -t commit --stdin -w <<< "$body" > /dev/null
git reset --hard "$sha1" > /dev/null
git push origin master --force
fi
#done
}
reset() {
git fetch origin master >/dev/null 2>/dev/null
git reset --hard origin/master >/dev/null
}
# Set up repo
local_path=./${clone_spec##*:}
if [ -d "$local_path" ]; then
echo "Using existing repository at $local_path"
cd "$local_path"
else
echo "Cloning repository to $local_path"
git clone "$clone_spec" "$local_path"
cd "$local_path"
fi
while true; do
prepare_index
solve
if git push origin master --force ; then
echo "Success :)"
break
else
echo "Starting over :("
reset
fi
done
git fetch && git reset --hard origin/master
cp ../miner .
cd ..
go build sha1.go
cd -
cp ../sha1 .
rm -rf level1
time ./miner <clone url> <username>
# Replace these! put run.sh in your initial cloned level1 repo
# put miner and sha1.go in the directory above, e.g.
# /blah/blah/blah/projectdirectory <- miner and sha1.go here
# /blah/blah/blah/projectdirectory/level1 <- run.sh here
package main
import (
"crypto/sha1"
//"github.com/jgrahamc/go-openssl/sha1"
"encoding/hex"
"io/ioutil"
"flag"
"fmt"
"os"
"runtime"
"strconv"
"sync"
"bytes"
_ "time"
)
var wg sync.WaitGroup
func testhash(body string, counter int) {
filecontents, _ := ioutil.ReadFile("in.com")
fmt.Println(filecontents)
hasher := sha1.New()
newbody := body + strconv.Itoa(counter) + "\n"
bytebody := bytes.Replace([]byte(newbody), []byte{92, 110}, []byte{10}, -1)
fmt.Fprintf(hasher, "commit %d\x00", len(bytebody))
fmt.Println(bytebody)
fmt.Println(string(bytebody))
fmt.Println(newbody)
hasher.Write([]byte(bytebody))
sum := hasher.Sum(nil)
myhash := hex.EncodeToString(sum[:])
fmt.Println("hash:", myhash)
}
func makehash(counter int, difficulty string) bool {
hasher := sha1.New()
//newbody := fmt.Sprintf(body, counter)
//fmt.Println(body)
body, _ := ioutil.ReadFile("in.com")
newbody := string(body) + strconv.Itoa(counter) + "\n"
bytebody := bytes.Replace([]byte(newbody), []byte{92, 110}, []byte{10}, -1)
fmt.Fprintf(hasher, "commit %d\x00", len(bytebody))
hasher.Write([]byte(bytebody))
sum := hasher.Sum(nil)
myhash := hex.EncodeToString(sum[:])
if myhash < difficulty {
fmt.Fprintln(os.Stderr, string(bytebody))
fmt.Fprintln(os.Stderr, "Hash from go:", myhash)
return true
}
return false
}
func runbetter(total int) {
counterchan := make(chan int)
for i := 0; i < 4*runtime.NumCPU(); i++ {
go func() {
defer wg.Done()
for {
counter, more := <-counterchan
if !more {
break
}
if makehash(counter, "000001") {
fmt.Println(counter)
os.Exit(0)
}
}
}()
}
for i := 0; i < total; i++ {
counterchan <- i
}
close(counterchan)
wg.Wait()
}
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
flag.Parse()
total, _ := strconv.Atoi(flag.Arg(0))
wg.Add(4*runtime.NumCPU())
runbetter(total)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment