I'd heard of the previous rounds of Stripe's Capture The Flag coding competition but hadn't actually looked into them in detail, but a friend of mine was giving this round a go and so I decided to play along. I had no vision of winning, so to keep the effort time-boxed I went for the minimalist solution that I could envision to each problem. I only made it to level 3 then stalled out, mostly because I'm unfamiliar with Scala and thus implementing my envisioned solution would have required a significant amount of time. I also wasted a significant chunk of time on level 1 (probably more than equal to the time spent coding all the other levels) trying to pull off what I assumed was an invited hack before trying a straightforward solution. Overall I found it a lot of fun and would encourage anyone interested in software to give it a go next time.
level 0
In this level we're given a short ruby script that "highlights" (by adding angle brackets) all of the words in an input text which aren't found in a dictionary. The script works but is slow, as it simply reads the dictionary into an array and does a naive search of that array for each word in the input. My solution was trivial, simply read the dictionary into a hash, and check for a key. Could have just been two changed lines if I bothered to try to remember a terser array to hash technique.
path = ARGV.length > 0 ? ARGV[0] : '/usr/share/dict/words' -entries = File.read(path).split("\n") +entries = {} +File.readlines(path).each do |entry| + entries[entry.chomp] = true +end contents = $stdin.read output = contents.gsub(/[^ \n]+/) do |word| - if entries.include?(word.downcase) + if entries.has_key? word.downcase word else "<#{word}>" end end print output
Result scored 117/50 required points.
level 1
On this level I wasted a bunch of time trying a hack rather than coding a solution. The task is to submit a git commit with a hash "lexicographically less than the value contained in the repository's difficulty.txt file". The fact that difficulty.txt was a local file rather than some constant or stored on a server seemed to me to be asking for a hack like submitting a difficulty.txt file with a value like "ffffff" in it. Could not make that work, but would be interested to hear from anyone who did. After giving up on the hack it took about 5 minutes on Google and Stack Overflow to find this utility:
beautify_git_hash: Beautify the Git commit hash! This is a little useless toy inspired by BitCoin's "proof of work" concept. It enables you to modify your Git commit to enforce a certain prefix on the Git commit hash.
I cloned this into my project and tested it by hand to see that it worked. Since this beautifies un-pushed commits via an amend, I changed prepare_index()
in miner
to do a commit instead of an add, then simply replaced default implementations solve
routine with a call to beautify_git_hash.
High level loop didn't change at all, so here's the guts of my code:
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" >> LEDG git commit LEDGER.txt -m 'Give me a Gitcoin' } solve() { fix=`../beautify_git_hash.py 000000` bash -c "$fix" }
I fired up the miner and in a couple minutes I'd mined a gitcoin, which gave me a result of 50/50. Didn't
have to improve performance of the beautify_git_hash
script at all so credit for this win
goes to the original author, Volker Grabcsch.
level 2
Hey, finally a node level, how exciting! Well, not really, this turned out to be just a rehash of the
level 0. In this level we have to create a proxy that can blacklist attackers based on ip. A full
implementation is provided with one key function missing: currently_blacklisted(ip)
.
The obvious implementation proved good enough, with a couple quick tests to figure out the right constant to use to detect a "bad" number of requests.
var blacklist = {}; function currently_blacklisted(ip) { if (!(ip in blacklist)) blacklist[ip] = 0; blacklist[ip] += 1; return blacklist[ip] > 4; }
This got me a result of 95/85. I actually spent a little more time on this later and was able to get higher scores during local testing, but never got a positive score on submitting them, so I suspect something was borked in the test environment.