Anavrins

Kminer

Feb 23rd, 2016 (edited)
182
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.01 KB | None | 0 0
  1. -- In-game KristMiner
  2. -- By Anavrins
  3. -- Disclaimer: This is a proof of concept ONLY
  4. -- This is the fastest in-game krist miner out there, and will lag your ComputerCraft instance
  5. -- Do not run on online servers!
  6.  
  7. local args = {...}
  8. local address = args[1]
  9. if not address then print("Usage: kmine <address>") return end
  10.  
  11. local nodeurl = "https://krist.ceriat.net"
  12. local work
  13. local block
  14. local balance
  15. local solved = 0
  16. local nonce = 0
  17. local rate = 0
  18.  
  19. local clock = os.clock
  20. local tonum = tonumber
  21.  
  22. -- JSON (Compacted) By ElvishJerricco
  23. local json = loadstring([[local a={["\n"]="\\n",["\r"]="\\r",["\t"]="\\t",["\b"]="\\b",["\f"]="\\f",["\""]="\\\"",["\\"]="\\\\"}local function b(t)local c=0;for d,e in pairs(t)do if type(d)~="number"then return false elseif d>c then c=d end end;return c==#t end;local f={['\n']=true,['\r']=true,['\t']=true,[' ']=true,[',']=true,[':']=true}function removeWhite(g)while f[g:sub(1,1)]do g=g:sub(2)end;return g end;local h={}for d,e in pairs(a)do h[e]=d end;function parseBoolean(g)if g:sub(1,4)=="true"then return true,removeWhite(g:sub(5))else return false,removeWhite(g:sub(6))end end;function parseNull(g)return nil,removeWhite(g:sub(5))end;local i={['e']=true,['E']=true,['+']=true,['-']=true,['.']=true}function parseNumber(g)local j=1;while i[g:sub(j,j)]or tonumber(g:sub(j,j))do j=j+1 end;local k=tonumber(g:sub(1,j-1))g=removeWhite(g:sub(j))return k,g end;function parseString(g)g=g:sub(2)local l=""while g:sub(1,1)~="\""do local m=g:sub(1,1)g=g:sub(2)assert(m~="\n","Unclosed string")if m=="\\"then local n=g:sub(1,1)g=g:sub(2)m=assert(h[m..n],"Invalid escape character")end;l=l..m end;return l,removeWhite(g:sub(2))end;function parseArray(g)g=removeWhite(g:sub(2))local k={}local j=1;while g:sub(1,1)~="]"do local e=nil;e,g=parseValue(g)k[j]=e;j=j+1;g=removeWhite(g)end;g=removeWhite(g:sub(2))return k,g end;function parseObject(g)g=removeWhite(g:sub(2))local k={}while g:sub(1,1)~="}"do local d,e=nil,nil;d,e,g=parseMember(g)k[d]=e;g=removeWhite(g)end;g=removeWhite(g:sub(2))return k,g end;function parseMember(g)local d=nil;d,g=parseValue(g)local k=nil;k,g=parseValue(g)return d,k,g end;function parseValue(g)local o=g:sub(1,1)if o=="{"then return parseObject(g)elseif o=="["then return parseArray(g)elseif tonumber(o)~=nil or i[o]then return parseNumber(g)elseif g:sub(1,4)=="true"or g:sub(1,5)=="false"then return parseBoolean(g)elseif o=="\""then return parseString(g)elseif g:sub(1,4)=="null"then return parseNull(g)end;return nil end;return{decode=function(g)g=removeWhite(g)t=parseValue(g)return t end}]])()
  24.  
  25. -- SHA256 (Compacted) By Anavrins
  26. local sha256 = loadstring([[local a=2^32;local b=bit32 and bit32.band or bit.band;local c=bit32 and bit32.bnot or bit.bnot;local d=bit32 and bit32.bxor or bit.bxor;local e=bit32 and bit32.lshift or bit.blshift;local f=unpack;local function g(h,i)local j=h/2^i;local k=j%1;return j-k+k*a end;local function l(m,n)local j=m/2^n;return j-j%1 end;local o={0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19}local p={0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2}local function q(r)local s,t=0,0;if 0xFFFFFFFF-s<r then t=t+1;s=r-(0xFFFFFFFF-s)-1 else s=s+r end;return t,s end;local function u(v,w)return e(v[w]or 0,24)+e(v[w+1]or 0,16)+e(v[w+2]or 0,8)+(v[w+3]or 0)end;local function x(y)local z=#y;local A={}y[#y+1]=0x80;while#y%64~=56 do y[#y+1]=0 end;local B=math.ceil(#y/64)for w=1,B do A[w]={}for C=1,16 do A[w][C]=u(y,1+(w-1)*64+(C-1)*4)end end;A[B][15],A[B][16]=q(z*8)return A end;local function D(E,F)for C=17,64 do local G=E[C-15]local H=d(d(g(E[C-15],7),g(E[C-15],18)),l(E[C-15],3))local I=d(d(g(E[C-2],17),g(E[C-2],19)),l(E[C-2],10))E[C]=(E[C-16]+H+E[C-7]+I)%a end;local J,i,K,L,M,k,N,O=f(F)for C=1,64 do local P=d(d(g(M,6),g(M,11)),g(M,25))local Q=d(b(M,k),b(c(M),N))local R=(O+P+Q+p[C]+E[C])%a;local S=d(d(g(J,2),g(J,13)),g(J,22))local T=d(d(b(J,i),b(J,K)),b(i,K))local U=(S+T)%a;O,N,k,M,L,K,i,J=N,k,M,(L+R)%a,K,i,J,(R+U)%a end;F[1]=(F[1]+J)%a;F[2]=(F[2]+i)%a;F[3]=(F[3]+K)%a;F[4]=(F[4]+L)%a;F[5]=(F[5]+M)%a;F[6]=(F[6]+k)%a;F[7]=(F[7]+N)%a;F[8]=(F[8]+O)%a;return F end;return{digest=function(y)y=x({y:byte(1,-1)})local F={f(o)}for w=1,#y do F=D(y[w],F)end;return("%08x"):rep(8):format(unpack(F))end}]])()
  27.  
  28. local function toBase(num, base)
  29.     local char = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-:+=^!/*?&<>()[]{}@%$#"
  30.     local ret = ""
  31.     base = base or 36
  32.     while num ~= 0 do
  33.         local i = num % base
  34.         ret = char:sub(i+1,i+1) .. ret
  35.         num = math.floor(num/base)
  36.     end
  37.     return ret
  38. end
  39.  
  40. local function getJSONPage(url, options, post)
  41.     local res
  42.     if type(post) == "table" then
  43.         local postdata = ""
  44.         for k, v in pairs(post) do
  45.             postdata = postdata..k.."="..textutils.urlEncode(v).."&"
  46.         end
  47.         res = http.post(url..options, postdata:sub(1, -2))
  48.     else
  49.         res = http.get(url..options)
  50.     end
  51.  
  52.     if not res then error("Error: Node Offline", 0) end
  53.     local ret = json.decode(res.readAll())
  54.     return ret
  55. end
  56.  
  57. local function getWork()
  58.     local res = getJSONPage(nodeurl, "/work")
  59.     return res.ok and res.work or nil
  60.     -- return 0x0007FFFFFFFF -- For testing purpose, you will only get invalid blocks though
  61. end
  62.  
  63. local function getLastBlock()
  64.     local res = getJSONPage(nodeurl, "/blocks/last")
  65.     return res.ok and res.block.short_hash, res.block.address or nil
  66. end
  67.  
  68. local function getBalance()
  69.     local res = getJSONPage(nodeurl, "/addresses/"..address)
  70.     if res.error then error(res.error, 0) end
  71.     return res.ok and res.address.balance or nil
  72. end
  73.  
  74. local function submitBlock(nonce)
  75.     local postdata = {
  76.         address = address,
  77.         nonce = nonce,
  78.     }
  79.     local res = getJSONPage(nodeurl, "/submit", postdata)
  80.     if res.ok then
  81.         return res.success
  82.     end
  83. end
  84.  
  85. local function printHeader(str, ny)
  86.     local w, h = term.getSize()
  87.     local x, y = term.getCursorPos()
  88.     term.setCursorPos(math.ceil(w/2) - math.floor(#str/2), ny or 1)
  89.     term.clearLine()
  90.     term.write(str)
  91.     term.setCursorPos(x, y)
  92. end
  93.  
  94. local function log(text, color)
  95.     term.setTextColor(color or colors.white)
  96.     print(text)
  97.     term.setTextColor(colors.yellow)
  98.     printHeader(("Work: %s | Block: %s"):format(work, block), 1)
  99.     printHeader(("Balance: %s"):format(balance), 2)
  100. end
  101.  
  102. term.clear()
  103. term.setCursorPos(1,1)
  104. print("Connecting to node...")
  105. balance = getBalance()
  106. block = getLastBlock()
  107. work = getWork()
  108. local timer = clock()
  109. local timer2 = clock()
  110.  
  111. term.setCursorPos(1, 3)
  112. local function miner()
  113.     while true do
  114.         local nonceStr = toBase(nonce, 85)
  115.         local hash = sha256.digest(address..block..nonceStr)
  116.         local subhash = hash:sub(1, 12)
  117.         if tonum(subhash, 16) < work then
  118.             log(subhash.." found! nonce: "..nonceStr, colors.cyan)
  119.             solved = solved + 1
  120.             local ok = submitBlock(nonceStr)
  121.             log(ok and "Accepted" or "Invalid", ok and colors.lime or colors.red)
  122.         end
  123.  
  124.         if clock() > timer + 1 then
  125.             log(("%s H/s Solved: %s"):format(nonce-rate, solved))
  126.             timer = clock()
  127.             rate = nonce
  128.             os.queueEvent("")
  129.             os.pullEvent("")
  130.         end
  131.         nonce = nonce+1
  132.     end
  133. end
  134. local function updatework()
  135.     while true do
  136.         sleep(5)
  137.         timer2 = clock()
  138.         local newblock, lastaddr = getLastBlock()
  139.         local newwork = getWork()
  140.         balance = getBalance()
  141.         if newwork ~= work then
  142.             work = newwork
  143.             log("Block mined by "..lastaddr, colors.orange)
  144.             log("New work: "..work, colors.orange)
  145.         end
  146.         if newblock ~= block then
  147.             block = newblock
  148.             log("New block: "..block, colors.orange)
  149.         end
  150.     end
  151. end
  152. parallel.waitForAny(miner, updatework)
Advertisement
Add Comment
Please, Sign In to add comment