Last active
October 31, 2017 13:54
-
-
Save ohac/d2375c17f55f0f81e051af824acd2c86 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
worker_all.js | |
foo.html | |
foo.js | |
foo.wasm |
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
#!/bin/bash | |
emcc foo.c -O3 -s WASM=1 -s EXPORTED_FUNCTIONS="['_sha256d_str']" -o foo.html |
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
0.0.0.0:8080 { | |
root ./ | |
proxy /proxy localhost:8088 { | |
websocket | |
max_fails 1 | |
} | |
ext .html | |
} |
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
#!/bin/bash | |
cat em.js foo.js worker.js > worker_all.js |
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
var Module = { | |
print: function() { | |
return function(text) { | |
if (arguments.length > 1) { | |
text = Array.prototype.slice.call(arguments).join(' '); | |
} | |
console.log(text); | |
}; | |
}, | |
printErr: function(text) { | |
if (arguments.length > 1) { | |
text = Array.prototype.slice.call(arguments).join(' '); | |
} | |
console.error(text); | |
}, | |
}; |
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
const char* sha256d_str(const char *datastr) { | |
static char rv[64 + 1]; | |
#if 0 | |
unsigned char buff[256]; // TODO | |
unsigned char buff2[32]; | |
size_t len = strlen(datastr) / 2; | |
hex2bin(buff, datastr, len); | |
sha256d(buff2, buff, len); | |
bin2hex(rv, buff2, 32); | |
#else | |
rv[0] = 'a'; | |
rv[1] = 0; | |
#endif | |
return rv; | |
} |
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
<!doctype html> | |
<html lang="en"> | |
<head> | |
<title>Web Miner</title> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | |
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous"> | |
</head> | |
<body> | |
<main role="main" class="container"> | |
<h1>Web Miner</h1> | |
<div class="form-group"> | |
<label for="host">Hostname</label> | |
<input id="host" type="text" class="form-control" placeholder="Hostname" aria-label="Hostname" aria-describedby="basic-addon1"> | |
</div> | |
<div class="form-group"> | |
<label for="port">Port number</label> | |
<input id="port" type="text" class="form-control" placeholder="Port number" aria-label="Port number" aria-describedby="basic-addon1"> | |
</div> | |
<div class="form-group"> | |
<label for="username">Username</label> | |
<input id="username" type="text" class="form-control" placeholder="Username" aria-label="Username" aria-describedby="basic-addon1"> | |
</div> | |
<div class="form-group"> | |
<label for="password">Password</label> | |
<input type="password" class="form-control" id="password" placeholder="Password"> | |
</div> | |
<div class="form-group"> | |
<label for="algo">Algorithm</label> | |
<select id="algo" class="form-control"> | |
<option>yescrypt</option> | |
</select> | |
</div> | |
<div class="form-group"> | |
<label for="threads">Threads</label> | |
<select id="threads" class="form-control"> | |
<option>1</option> | |
<option>2</option> | |
<option>3</option> | |
<option>4</option> | |
<option>5</option> | |
<option>6</option> | |
<option>7</option> | |
<option>8</option> | |
</select> | |
</div> | |
<div class="form-group"> | |
<button id="start" type="button" class="btn btn-primary">Start</button> | |
</div> | |
<div id="connected" class="alert alert-info" role="alert" style="display: none"> | |
Connected | |
</div> | |
<div id="disconnected" class="alert alert-danger" role="alert" style="display: none"> | |
Disconnected | |
</div> | |
<div id="message" class="alert alert-info" role="alert" style="display: none"> | |
Got message | |
</div> | |
<div id="error" class="alert alert-danger" role="alert" style="display: none"> | |
Error | |
</div> | |
<div id="result"></div> | |
</main> | |
<script src="//code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js" integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh" crossorigin="anonymous"></script> | |
<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js" integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ" crossorigin="anonymous"></script> | |
<script src="/miner.js" type="text/javascript"></script> | |
</body> | |
</html> |
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
$(function(){ | |
if (true) { // debug code | |
var worker = new Worker('worker_all.js'); | |
worker.onmessage = function(e) { | |
var result = e.data; | |
console.log('recv from worker: ' + result); | |
} | |
setTimeout(function(){ | |
var work = {}; | |
work['jobid'] = '7b61'; | |
work['clean'] = false; | |
work['prevhash'] = '1e924c35bc128651ad5618755c3ce078' + | |
'e20896b652575e3411106f740000000b'; | |
work['diff'] = 0.2; | |
work['coinb1'] = '010000000100000000000000000000000000000000000000' + | |
'00000000000000000000000000ffffffff270332c80f062f' + | |
'503253482f04d7e2f55908'; | |
work['coinb2'] = '0d2f6e6f64655374726174756d2f0000000001806e877401' + | |
'0000001976a9143321f2d17da1a0f064ccaa8fea08d50b46' + | |
'c38ed888ac00000000'; | |
work['xnonce1'] = '07ffb0ec'; | |
work['merkles'] = []; | |
work['version'] = '00000002'; | |
work['nbits'] = '1d1c8031'; | |
work['xnonce2len'] = 4; | |
work['xnonce2'] = '00000000'; | |
work['ntime'] = '59f5e2d7'; | |
work['nonce'] = 0x1b00; // expected nonce: 0x1b8a | |
worker.postMessage(work); | |
}, 1000); // wait for main of foo.c | |
} | |
$('#start').click(function(){ | |
var auth = false; | |
const workers = []; | |
var ws = new WebSocket('ws://localhost:8080/proxy'); | |
ws.onopen = function(ev) { | |
console.log('open'); | |
$('.alert').hide(); | |
$('#connected').show(); | |
var msg = {"id": 0, "method": "proxy.connect", "params": []}; | |
msg.params[0] = $('#host').val(); | |
msg.params[1] = $('#port').val(); | |
ws.send(JSON.stringify(msg) + "\n"); | |
auth = false; | |
msg = {"id": 1, "method": "mining.subscribe", "params": []}; | |
var user_agent = 'webminer/0.1'; | |
var session_id = null; | |
msg.params[0] = user_agent; | |
if (session_id) { | |
msg.params[1] = session_id; | |
} | |
ws.send(JSON.stringify(msg) + "\n"); | |
}; | |
ws.onclose = function(ev) { | |
console.log('close'); | |
$('.alert').hide(); | |
$('#disconnected').show(); | |
}; | |
var work = {}; | |
ws.onmessage = function(ev) { | |
console.log('message: ' + ev.data); | |
$('.alert').hide(); | |
$('#message').show(); | |
var doauth = false; | |
var json = JSON.parse(ev.data); | |
var result = json.result; | |
if (result) { | |
var res0 = result[0]; | |
if (json.id == 1) { | |
// for bunnymining.work | |
var res00 = res0[0]; | |
if (res00 == 'mining.notify') { | |
var sessionid = res0[1]; | |
var xnonce1 = result[1]; | |
var xnonce2len = result[2]; | |
work['sessionid'] = sessionid; | |
work['xnonce1'] = xnonce1; | |
work['xnonce2len'] = xnonce2len; | |
console.log('mining.mining.notify 1: ' + work); | |
doauth = true; | |
} | |
// for jp.lapool.me | |
var res000 = res00[0]; | |
if (res000 == 'mining.set_difficulty') { | |
var xnonce1 = result[1]; | |
var xnonce2len = result[2]; | |
work['xnonce1'] = xnonce1; | |
work['xnonce2len'] = xnonce2len; | |
console.log('mining.mining.notify 1: ' + work); | |
doauth = true; | |
} | |
} | |
} | |
if (json.id == 4) { | |
console.log('yay!?'); | |
} | |
var method = json.method; | |
var params = json.params; | |
if (json.id == null) { | |
if (method == 'mining.set_difficulty') { | |
var diff = params[0]; | |
console.log('mining.set_difficulty: ' + diff); | |
work['diff'] = diff; | |
} | |
else if (method == 'mining.notify') { | |
work['jobid'] = params[0]; | |
work['prevhash'] = params[1]; | |
work['coinb1'] = params[2]; | |
work['coinb2'] = params[3]; | |
work['merkles'] = params[4]; | |
work['version'] = params[5]; | |
work['nbits'] = params[6]; | |
work['ntime'] = params[7]; | |
work['clean'] = params[8]; | |
console.log('mining.notify 2: ' + work); | |
for (var i = 0; i < $('#threads').val(); i++) { | |
var worker = workers[i]; | |
if (worker) { | |
worker.terminate(); | |
} | |
worker = new Worker('worker_all.js'); | |
workers[i] = worker; | |
worker.onmessage = function(e) { | |
var result = e.data; | |
console.log('recv from worker: ' + result); | |
var xnonce2 = result[0]; | |
var nonce = result[1]; | |
var username = $('#username').val(); | |
var msg = {"id": 4, "method": "mining.submit", | |
"params": [username, work.jobid, xnonce2, work.ntime, nonce] | |
}; | |
ws.send(JSON.stringify(msg) + "\n"); | |
work['nonce'] = parseInt(nonce, 16) + 1; | |
console.log('restart nonce', work['nonce']); | |
worker.postMessage($.extend({}, work)); | |
} | |
} | |
setTimeout(function(){ | |
for (var i = 0; i < $('#threads').val(); i++) { | |
work['nonce'] = 0x10000000 * i; | |
console.log('start nonce', work['nonce']); | |
worker.postMessage($.extend({}, work)); | |
} | |
}, 100); // TODO wait for main of foo.c | |
} | |
} | |
if (!auth && doauth) { | |
auth = true; | |
msg = {"id": 2, "method": "mining.authorize", "params": []}; | |
msg.params[0] = $('#username').val(); | |
msg.params[1] = $('#password').val(); | |
ws.send(JSON.stringify(msg) + "\n"); | |
} | |
}; | |
ws.onerror = function(ev) { | |
console.log('error'); | |
$('.alert').hide(); | |
$('#error').show(); | |
for (var i = 0; i < workers.length; i++) { | |
var worker = workers[i]; | |
if (worker) { | |
worker.postMessage('stop'); | |
workers[i] = null; | |
} | |
} | |
}; | |
return false; | |
}); | |
}); |
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
var miner = function(work){ | |
var sha256d_str2 = Module.cwrap('sha256d_str2', 'string', | |
['string', 'string', 'string', 'string', 'string']); | |
var miner_thread2 = Module.cwrap('miner_thread2', 'string', | |
['string', 'string', 'number']); | |
console.log('worker: running'); | |
if (work.jobid) { | |
var xnonce2 = ''; | |
for (var i = 0; i < work.xnonce2len; i++) { | |
xnonce2 += '00'; | |
} | |
var merklestr = ''; | |
for (var i = 0; i < work.merkles.length; i++) { | |
merklestr += work.merkles[i]; | |
} | |
var merkleroot = sha256d_str2( | |
work.coinb1, | |
work.xnonce1, | |
xnonce2, | |
work.coinb2, | |
merklestr); | |
console.log('worker: merkleroot = ' + merkleroot); | |
// work.sessionid | |
// work.diff | |
// work.jobid | |
// work.clean | |
var nonce = '00000000'; | |
var blockheader0 = | |
work.version + | |
work.prevhash + | |
merkleroot + | |
work.ntime + | |
work.nbits; | |
var blockheader = blockheader0 + nonce; | |
console.log('worker: blockheader = ' + blockheader); | |
var nonce_and_hash = miner_thread2(blockheader, work.diff.toString(), | |
work.nonce); | |
console.log('worker: found? ' + nonce_and_hash); | |
postMessage([xnonce2, nonce_and_hash.split(',')[0]]); | |
} | |
}; | |
self.addEventListener('message', (message) => { | |
var data = message.data; | |
console.log(data); | |
if (data == 'stop') { | |
console.log('worker: stop'); | |
self.close(); | |
} | |
var doit = false; | |
if (data == 'debug') { doit = true; } | |
if (data.jobid) { doit = true; } | |
if (doit) { | |
miner(data); | |
} | |
}); |
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
package main | |
import ( | |
"bufio" | |
"encoding/json" | |
"flag" | |
"fmt" | |
"github.com/gorilla/websocket" | |
"log" | |
"net" | |
"net/http" | |
) | |
var upgrader = websocket.Upgrader{ | |
CheckOrigin: func(r *http.Request) bool { | |
return true | |
}, | |
} | |
type Command struct { | |
Id int `json:"id"` | |
Method string `json:"method"` | |
Params []string `json:"params"` | |
} | |
func proxysender(c *websocket.Conn, conn *net.TCPConn, cmdq chan string) { | |
mt := websocket.TextMessage | |
for { | |
cmd := <-cmdq | |
fmt.Println("get from command queue:", cmd) | |
if cmd == "stop" { | |
break | |
} | |
err := c.WriteMessage(mt, []byte(cmd)) | |
if err != nil { | |
fmt.Println("ws:", err) | |
break | |
} | |
var command Command | |
json.Unmarshal([]byte(cmd), &command) | |
method := command.Method | |
if method == "mining.subscribe" || method == "mining.authorize" || method == "mining.submit" { | |
fmt.Println("write to pool:", cmd) | |
conn.Write([]byte(cmd)) | |
} | |
} | |
conn.Close() | |
} | |
func proxyreceiver(conn *net.TCPConn, cmdq chan string) { | |
scanner := bufio.NewScanner(conn) | |
for scanner.Scan() { | |
t := scanner.Text() | |
fmt.Println("from pool:", t) | |
cmdq <- t | |
} | |
if err := scanner.Err(); err != nil { | |
fmt.Println("from pool:", err) | |
return | |
} | |
cmdq <- "stop" | |
} | |
func proxyconnect(host, port string) (conn *net.TCPConn) { | |
dest, err := net.ResolveTCPAddr("tcp", host+":"+port) | |
if err != nil { | |
fmt.Println("resolve:", err) | |
return | |
} | |
src := new(net.TCPAddr) | |
var err2 error | |
conn, err2 = net.DialTCP("tcp", src, dest) | |
if err2 != nil { | |
fmt.Println("dial:", err2) | |
return | |
} | |
fmt.Println("dial ok!") | |
return | |
} | |
func proxymain(w http.ResponseWriter, r *http.Request) { | |
c, err := upgrader.Upgrade(w, r, nil) | |
if err != nil { | |
log.Print("upgrade:", err) | |
return | |
} | |
defer c.Close() | |
cmdq := make(chan string, 10) | |
for { | |
_, jsonstr, err := c.ReadMessage() | |
if err != nil { | |
log.Println("read:", err) | |
cmdq <- "stop" | |
break | |
} | |
log.Printf("recv: %s", jsonstr) | |
var command Command | |
json.Unmarshal(jsonstr, &command) | |
fmt.Println(command) | |
if command.Method == "proxy.connect" && len(command.Params) == 2 { | |
host := command.Params[0] | |
port := command.Params[1] | |
conn := proxyconnect(host, port) | |
if conn != nil { | |
go proxysender(c, conn, cmdq) | |
go proxyreceiver(conn, cmdq) | |
} | |
} else { | |
cmdq <- string(jsonstr) | |
} | |
} | |
} | |
func main() { | |
flag.Parse() | |
log.SetFlags(0) | |
http.HandleFunc("/proxy", proxymain) | |
addr := flag.String("addr", "localhost:8088", "http service address") | |
log.Fatal(http.ListenAndServe(*addr, nil)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment