Browse Source

Merge branch 'master' into multiproxy

master
Con Kolivas 9 years ago
parent
commit
18efa70a60
  1. 39
      pool/email.php
  2. 22
      pool/inc.php
  3. 111
      pool/page.php
  4. 130
      pool/page_2fa.php
  5. 86
      pool/page_blocks.php
  6. 11
      pool/page_payments.php
  7. 9
      pool/page_reg.php
  8. 2
      pool/page_settings.php
  9. 3
      sql/ckdb.sql
  10. 25
      sql/v1.0.1-v1.0.2.sql
  11. 15
      src/ckdb.c
  12. 104
      src/ckdb.h
  13. 4
      src/ckdb_btc.c
  14. 134
      src/ckdb_cmd.c
  15. 71
      src/ckdb_crypt.c
  16. 100
      src/ckdb_data.c
  17. 255
      src/ckdb_dbio.c

39
pool/email.php

@ -172,6 +172,45 @@ function passChanged($to, $whoip, $emailinfo)
return sendnoheader($to, "Password Change", $message, $emailinfo);
}
#
function twofaSetup($to, $whoip, $emailinfo)
{
global $eol;
if (!isset($emailinfo['KWebURL']))
return false;
$web = $emailinfo['KWebURL'];
$ret = emailEnd('2fa change', $whoip, $emailinfo);
if ($ret === false)
return false;
$message = "2FA is ready to be tested.$eol";
$message = "It will be enabled once you test it.$eol$eol";
$message .= $ret;
return sendnoheader($to, "2FA is Ready to be Enabled", $message, $emailinfo);
}
#
function twofaEnabled($to, $whoip, $emailinfo)
{
global $eol;
if (!isset($emailinfo['KWebURL']))
return false;
$web = $emailinfo['KWebURL'];
$ret = emailEnd('2fa change', $whoip, $emailinfo);
if ($ret === false)
return false;
$message = "2FA is enabled on your account.$eol$eol";
$message .= $ret;
return sendnoheader($to, "2FA is Enabled", $message, $emailinfo);
}
#
# getOpts required for email
# If they aren't all setup in the DB then email functions will return false
function emailOptList()

22
pool/inc.php

@ -29,7 +29,9 @@ function gfi(c){gle(c);gst(c)}
function gbd(c){gbe(c,0,0);gln(c,1,0);gln(c,1,1);gln(c,0,1);gle(c);gfl(c);gst(c)}
function ggr(c,xs,ys,yt,xn,x0,x1,y0,y1,ar,nx,vx,vy,av,w,cols){gtso(c,xs,ys);gss(c,'black');glw(c,1.5);gbe(c,0,1);gln(c,0,0);gln(c,1,0);gst(c);glw(c,0.2);var hi=c['ctx'].measureText('M').width, wi=c['ctx'].measureText('1').width;for(var i=0;i<11;i++){var y=i/10.0;gbe(c,-0.01,y);gln(c,1,y);gst(c);var t=''+(((y1-y0)*i/10+y0).toFixed(2));gfz(c,0,y,-wi,0,t,'black','end')}gfz(c,gx0(c),0.55,wi,0,yt,'#0080ff','left');var m=Math.round(0.5+xn/20.0);for(var i=0;i<xn;i++){var n=ar[nx+i];var x=ar[vx+i];var xo=(x-x0)/(x1-x0);if(c['skey'] && (i<(xn-1)) && (i%m) == 0){gbe(c,xo,0);gln(c,xo,-0.01);gst(c);gfz(c,xo,0,0,-hi*1.5,n,'#00a050','center')}if(c['slines']){gbe(c,xo,0);gln(c,xo,1);gst(c)}}var xhr=3600+x1-(x1%3600);gss(c,'brown');if(c['tkey'] || c['tlines']){var hlv=c['hln'][c['hl']];hrs=c['hrs'][c['hr']]*3600/hlv;var l=0;tpos=2.7;if(c['over']){tpos=1.5}for(var i=xhr;i>=x0;i-=hrs){var n=dfmt(c,i);var xo=(i-x0)/(x1-x0);if(xo<=1 && c['tkey'] && ((l%hlv)==0)){gbe(c,xo,0);gln(c,xo,-0.02);gst(c);gfz(c,xo,0,0,-hi*tpos,n,'brown','center')}if(xo<=1 && c['tlines']){gbe(c,xo,0);gln(c,xo,1);gst(c)}l++}}glw(c,1);if(c['smooth']){for(var j=1;j<w.length;j++){var f=1;gss(c,cols[j-1]);var xa=0,ya=0,xb=0,yb=0;for(var i=0;i<xn;i++){var x=ar[vx+i];var y=ar[w[j]+vy+i];var xo=(x-x0)/(x1-x0);var yo=(y-y0)/(y1-y0);if(f==1){gbe(c,xo,yo);f=0;xb=xo;yb=yo}else{gct(c,(xa+xb)/2,(ya+yb)/2,xb,yb,(xb+xo)/2,(yb+yo)/2)}xa=xb;ya=yb;xb=xo;yb=yo}gct(c,(xa+xb)/2,(ya+yb)/2,xo,yo,xo,yo);gst(c)}}else{for(var j=1;j<w.length;j++){var f=1;gss(c,cols[j-1]);for(var i=0;i<xn;i++){var x=ar[vx+i];var y=ar[w[j]+vy+i];var xo=(x-x0)/(x1-x0);var yo=(y-y0)/(y1-y0);if(f==1){gbe(c,xo,yo);f=0}else{gln(c,xo,yo)}}gst(c)}}glw(c,1);for(var j=1;j<w.length;j++){if(av[j-1]>0){gss(c,'red');var y=(av[j-1]-y0)/(y1-y0);gbe(c,0,y);gln(c,1,y);gst(c);var t=''+av[j-1].toFixed(2)+'av';gfz(c,1,y,1,0,t,cols[j-1],'left')}}if(c['tkey']){var col,hrl=c['hrs'].length;for(var i=0;i<hrl;i++){if(c['hr']==i){col='red'}else{col='black'}gfz(c,1,0,c['xo']-c['pxe'],hi*(i+1)*2,''+c['hrs'][i],col,'end')}for(var i=0;i<c['hln'].length;i++){if(c['hl']==i){col='red'}else{col='black'}gfz(c,1,0,c['xo']-c['pxe'],hi*(i+2+hrl)*2,''+c['hrs'][i],col,'end')}}}
function sn(i,shi){if(shi.indexOf(' Shift ')<0){return ''+(i%10)}else{return shi.replace(/.* ([a-z])[a-z]*$/,'$1')}}
function gc(c){var div=document.getElementById('can0');while (div.firstChild){div.removeChild(div.firstChild)}c['can']=document.createElement('canvas');c['can'].id='can';c['wx']=window.innerWidth;c['wy']=window.innerHeight;c['xm']=Math.max(Math.round(c['wx']*0.9+0.5),400);c['ym']=Math.max(Math.round(c['wy']*0.8+0.5),400);if(c['ym']>c['xm']){c['ym']=c['xm']}c['xo']=0.0;c['yo']=0.0;c['ctx']=c['can'].getContext('2d');c['ctx'].canvas.width=c['xm']+1;c['ctx'].canvas.height=c['ym']+1;div.appendChild(c['can']);c['pxe']=Math.max(Math.round(c['xm']/250),1)}
function gc2(c){var div=document.getElementById('can0');while (div.firstChild){div.removeChild(div.firstChild)}c['can']=document.createElement('canvas');c['can'].id='can';c['xo']=0.0;c['yo']=0.0;c['ctx']=c['can'].getContext('2d');c['ctx'].canvas.width=c['xm']+1;c['ctx'].canvas.height=c['ym']+1;div.appendChild(c['can']);c['pxe']=Math.max(Math.round(c['xm']/250),1)}
function gc(c){c['wx']=window.innerWidth;c['wy']=window.innerHeight;c['xm']=Math.max(Math.round(c['wx']*0.9+0.5),400);c['ym']=Math.max(Math.round(c['wy']*0.8+0.5),400);if(c['ym']>c['xm']){c['ym']=c['xm']}gc2(c)}
function gcxy(c,xm,ym){c['wx']=window.innerWidth;c['wy']=window.innerHeight;c['xm']=Math.min(Math.round(c['wx']*0.95),xm);c['ym']=Math.min(Math.round(c['wy']*0.95),ym);gc2(c)}
function opts(t,i){var e=document.getElementById(i);if(t.checked){e.style.visibility='visible'}else{e.style.visibility='hidden'}}
function ghrs(c){c['hrs']=[1,2,3,4,6,8,12,24,48];c['hln']=[1,2,3,4,6]}
function ghg(c,dx){var tl=dx/(gchx(c,1)/50)/3600;for(var j=c['hrs'].length-1;j>=0;j--){if(tl<c['hrs'][j]){c['hr']=j}else{break}}if(tl<0.5){var tb=1/tl;for(var k=0;k<c['hln'].length;k++){if(c['hln'][k]<tb){c['hl']=k}else{break}}}else{c['hl']=1}}
@ -73,7 +75,7 @@ function jst(){var e=document.getElementById('jst');if(e){e.style.visibility='hi
return $h;
}
#
function HeadCSS($iCrap = false)
function HeadCSS()
{
$h = "input[type=checkbox] {vertical-align:-2px;}
form {display:inline-block;}
@ -104,15 +106,10 @@ input.tiny {width:0px;height:0px;margin:0px;padding:0px;outline:none;border:0px;
#n42 td.navboxr {float:right;}
#n42 td.nav {position:relative;}
#n42 td.ts {border-width:1px;border-color:#0022ee;border-style:solid none none none;}
";
if (!$iCrap)
{
$h .= "#n42 div.sub {left:0px;z-index:42;position:absolute;visibility:hidden;}
#n42 div.sub {left:0px;z-index:42;position:absolute;visibility:hidden;}
#n42 td.nav:hover {background:#0099ee;}
#n42 td.nav:hover div.sub {background:#0077ee;visibility:visible;}
";
}
$h .= "h1 {margin-top:20px;float:middle;font-size:20px;}
h1 {margin-top:20px;float:middle;font-size:20px;}
.foot, .push {height:50px;}
.title {background-color:#909090;}
.even {background-color:#cccccc;}
@ -148,4 +145,11 @@ function sotc(cn,d){var ws=gcn(cn);if(ws==''){ws=d}sotn(cn,ws)}
return $s;
}
#
function QRJS()
{
$q = "function qr(tw,fa,qrx,qry,qrd){if(hasCan()){gcxy(c,qrx*4,qry*4);gfs(c,'white');gss(c,'white');gbd(c);gfs(c,'black');gss(c,'black');for(var y=0;y<qry;y++){var x=0,b=0;for(var j=0;j<qrx;j+=4){var n=qrd[y].substr(b,1).charCodeAt(0)-97;for(k=0;k<4;k++){if(n & (1<<k)){gbe(c,x/qrx,1-(y/qry));gln(c,(x+1)/qrx,1-(y/qry));gln(c,(x+1)/qrx,1-((y+1)/qry));gln(c,x/qrx,1-((y+1)/qry));gle(c);gfl(c)}x++}b++}}}}
";
return $q;
}
#
?>

111
pool/page.php

@ -51,25 +51,59 @@ function addCSS($css)
$page_css .= $css;
}
#
global $added_gbase;
$added_gbase = false;
function addGBase()
{
$g = GBaseJS();
addScript($g);
global $added_gbase;
if ($added_gbase == false)
{
$added_gbase = true;
$g = GBaseJS();
addScript($g);
}
}
#
global $added_tips;
$added_tips = false;
function addTips()
{
$t = TipsJS();
addScript($t);
$tcss = TipsCSS();
addCSS($tcss);
global $added_tips;
if ($added_tips == false)
{
$added_tips = true;
$t = TipsJS();
addScript($t);
$tcss = TipsCSS();
addCSS($tcss);
}
}
#
global $added_sort;
$added_sort = false;
function addSort()
{
$s = SortJS();
addScript($s);
global $added_sort;
if ($added_sort == false)
{
$added_sort = true;
$s = SortJS();
addScript($s);
}
}
#
global $added_qr;
$added_qr = false;
function addQR()
{
global $added_qr;
if ($added_qr == false)
{
$added_qr = true;
addGBase();
$q = QRJS();
addScript($q);
}
}
#
function makeURL($page)
@ -119,20 +153,10 @@ function trm_force($html)
return dotrm($html, false);
}
#
function isCrap()
{
if (isset($_SERVER['HTTP_USER_AGENT']))
return strpos($_SERVER['HTTP_USER_AGENT'],'iP');
else
return false;
}
#
function pghead($css_marker, $script_marker, $name)
{
global $page_title;
$iCrap = isCrap();
$head = "<!DOCTYPE html>\n";
$head .= "<html><head><title>$page_title$name</title>";
@ -144,7 +168,7 @@ function pghead($css_marker, $script_marker, $name)
$head .= HeadJS();
$head .= "\n</script>\n";
$head .= "<style type='text/css'>\n";
$head .= HeadCSS($iCrap);
$head .= HeadCSS();
$head .= "\n$css_marker\n</style>\n";
$head .= '<meta name="robots" content="noindex">';
@ -410,26 +434,23 @@ function pgtop($info, $dotop, $user, $douser)
if ($who == false)
{
$top .= '<table cellpadding=0 cellspacing=0 border=0><tr><td>';
$top .= '<a href=https://' . $_SERVER['SERVER_NAME'];
$top .= '/index.php?Register=1>Login<br>Register</a>';
$top .= '<a href="https://' . $_SERVER['SERVER_NAME'];
$top .= '/index.php?Register=1">Login<br>Register</a>';
$top .= '</td></tr></table>';
}
else
{
$extra = '';
$first = substr($who, 0, 1);
if (($first == '1' || $first == '3') && strlen($who) > 12)
if (strlen($who) > 12)
{
$who = substr($who, 0, 11);
$who = substr($who, 0, 12);
$extra = '&#133;';
}
$top .= "
<span class=topwho>".htmlspecialchars($who)."$extra&nbsp;</span><br>
<span class=topdes>Hash&nbsp;Rate:</span>
<span class=topdat>$uhr$u1hr</span><br>";
$top .= makeForm('')."
<input type=submit name=Logout value=Logout>
</form>";
$top .= "<span class=topwho>".htmlspecialchars($who)."$extra&nbsp;</span>";
$top .= makeForm('');
$top .= "<input type=submit name=Logout value=Logout></form>";
$top .= "<br><span class=topdes>Hash&nbsp;Rate:</span>";
$top .= "<span class=topdat>$uhr$u1hr</span><br>";
}
$top .= '</span>';
@ -445,8 +466,6 @@ function pgtop($info, $dotop, $user, $douser)
#
function pgmenu($menus)
{
$iCrap = isCrap();
$ret = "\n<table cellpadding=0 cellspacing=0 border=0 width=100% id=n42>";
$ret .= '<tr><td width=100%>';
$ret .= '<table cellpadding=0 cellspacing=0 border=0 width=100%>';
@ -462,35 +481,27 @@ function pgmenu($menus)
$side = 'r';
continue;
}
if ($iCrap)
$ret .= "<td class=navbox$side><table cellpadding=0 cellspacing=0 border=0>";
$first = true;
foreach ($submenus as $submenu => $item)
{
foreach ($submenus as $submenu => $item)
$ret .= "<td class=nav>".makeLink($item)."$submenu</a></td>";
}
else
{
$ret .= "<td class=navbox$side><table cellpadding=0 cellspacing=0 border=0>";
$first = true;
foreach ($submenus as $submenu => $item)
{
if ($first == true)
{
$first = false;
if ($submenu == $menu)
{
$ret .= "<tr><td class=nav>".makeLink($item)."$menu</a>";
$ret .= "<tr><td class=nav onclick=''>".makeLink($item)."$menu</a>";
$ret .= '<div class=sub><table cellpadding=0 cellspacing=0 border=0 width=100%>';
continue;
}
$ret .= "<tr><td class=nav><a>$menu</a>";
$ret .= "<tr><td class=nav onclick=''><a>$menu</a>";
$ret .= '<div class=sub><table cellpadding=0 cellspacing=0 border=0 width=100%>';
}
$ret .= "<tr><td class=ts>".makeLink($item,'class=as')."$submenu</a></td></tr>";
}
if ($first == false)
$ret .= '</table></div></td></tr></table>';
$ret .= '</td>';
}
if ($first == false)
$ret .= '</table></div></td></tr></table>';
$ret .= '</td>';
}
$ret .= "</tr></table></td></tr></table>\n";
return $ret;

130
pool/page_2fa.php

@ -1,7 +1,20 @@
<?php
#
include_once('email.php');
#
function app_txt($ones)
{
$app = "The free and recommended $ones that ";
$app .= "have been tested here are:<br><span class=hil>";
$app .= "Android: Google Play '<b>FreeOTP Authenticator</b>' by Red Hat<br>";
$app .= "Apple: App Store '<b>OTP Auth</b>' by Roland Moers</span><br><br>";
return $app;
}
#
function set_2fa($data, $user, $tfa, $ans, $err)
{
$draw = false;
$pg = '<h1>Two Factor Authentication Settings</h1>';
if ($err !== null and $err != '')
@ -17,12 +30,10 @@ function set_2fa($data, $user, $tfa, $ans, $err)
{
case '':
$pg .= '<tr class=dl><td>';
$pg .= "You don't have 2FA setup yet<br><br>";
$pg .= "You don't have Two Factor Authentication (2FA) setup yet<br><br>";
$pg .= 'To use 2FA you need an App on your phone/tablet<br>';
$pg .= 'The free and recommended ones that have been tested here are:<br><br>';
$pg .= "Android: Google Play 'FreeOTP Authenticator' by Red Hat<br>";
$pg .= "Apple: App Store 'OTP Auth' by Roland Moers<br><br>";
$pg .= 'Click here to start setting up 2FA: ';
$pg .= app_txt('ones');
$pg .= 'Click here to begin the setup process for 2FA: ';
$pg .= '<input type=submit name=Setup value=Setup>';
$pg .= '</td></tr>';
break;
@ -39,6 +50,8 @@ function set_2fa($data, $user, $tfa, $ans, $err)
$sfaurl = 'otpauth://'.$ans['2fa_auth'].'/'.$ans['2fa_issuer'].
':'.htmlspecialchars($who).'?secret='.$ans['2fa_key'].
'&algorithm='.$ans['2fa_hash'].'&issuer='.$ans['2fa_issuer'];
$draw = true;
addQR();
}
else
{
@ -46,11 +59,25 @@ function set_2fa($data, $user, $tfa, $ans, $err)
$sfainfo = 'unavailable';
$sfaurl = 'unavailable';
}
$pg .= "Your 2FA Secret Key is: $key<br>";
$pg .= "Your <span class=urg>2FA Secret Key</span> is: $key<br>";
$pg .= "2FA Settings are $sfainfo<br><br>";
$pg .= "2FA URL is <a href='$sfaurl'>Click</a><br><br>";
$pg .= '2FA Value: <input name=Value value="" size=10> ';
$pg .= '<input type=submit name=Test value=Test>';
$pg .= "To setup 2FA in your App: <a href='$sfaurl'>Click here</a><br>";
$pg .= "or scan the qrcode/barcode below with your App:<br><br>";
$pg .= '<div id=can0><canvas id=can width=1 height=1>';
$pg .= 'A qrcode will show here if your browser supports html5/canvas';
$pg .= "</canvas></div><br>";
$pg .= 'Then enter your App 2FA Value: <input name=Value value="" size=10> ';
$pg .= '<input type=submit name=Test value=Test></td></tr>';
$pg .= '<tr class=dl><td>';
$pg .= app_txt('2FA apps');
$pg .= '<span class=urg>N.B.</span> if you wish to setup 2FA on more than one device,<br>';
$pg .= 'you should setup all devices before testing one of them.<br>';
$pg .= 'If you have an old <span class=urg>2FA Secret Key</span> in your device for this web site,<br>';
$pg .= 'delete it before scanning in the new <span class=urg>2FA Secret Key</span>.<br><br>';
$pg .= '<span class=urg>WARNING:</span> if you lose your 2FA device you will need to know<br>';
$pg .= 'the <span class=urg>2FA Secret Key</span> to manually setup a new device,<br>';
$pg .= 'so your should copy it and store it somewhere securely.<br>';
$pg .= 'For security reasons, the site will not show you an active <span class=urg>2FA Secret Key</span>.<br>';
$pg .= '</td></tr>';
break;
case 'ok':
@ -60,16 +87,61 @@ function set_2fa($data, $user, $tfa, $ans, $err)
$pg .= 'Current 2FA Value: <input name=Value value="" size=10> ';
$pg .= '<input type=submit name=New value=New><span class=st1>*</span><br><br>';
$pg .= '<span class=st1>*</span>WARNING: replacing the Secret Key will disable 2FA<br>';
$pg .= 'until you successfully test the new key.<br><br>';
$pg .= 'until you successfully test the new key,<br>';
$pg .= 'thus getting a new key is effectively the same as disabling 2FA.<br><br>';
$pg .= '</td></tr>';
break;
}
$pg .= '</table></form>';
$pg .= '</center></td></tr>';
$pg .= '<tr class=dl><td>';
$pg .= '2FA means that you need 2 codes to login to your account.<br>';
$pg .= 'You will also need the 2FA code to modify any important settings in your account.<br>';
$pg .= 'The 1st code is your current password.<br>';
$pg .= 'The 2nd code is a number that your 2FA device will generate each time.<br>';
$pg .= 'Your 2FA device would be, for example, your phone or tablet.<br><br>';
$pg .= 'Each time you need a 2FA code, you use your device to generate a number<br>';
$pg .= 'that you type into the "<span class=st1>*</span>2nd Authentication:" field on any page that has it.<br><br>';
$pg .= '<b>IMPORTANT:</b> the TOTP algorithm uses the time on your device,<br>';
$pg .= "so it is important that your device's clock is accurate within a few seconds.<br><br>";
$pg .= '<b>IMPORTANT:</b> you enter the value from your App at the time you submit data.<br>';
$pg .= "The value is valid only once for a maximum of 30 seconds.<br>";
$pg .= "In both the Apps it has a 'dial' that shows the 30 seconds running out.<br>";
$pg .= "If you are close to running out, you can wait for the 30 seconds to run out<br>";
$pg .= "and then enter the new value it will come up with.<br>";
$pg .= "The pool checks your value using the time at the pool when you submit the data,<br>";
$pg .= "it doesn't matter when you loaded the web page,<br>";
$pg .= "it only matters when you clicked on the web page button to send the data to the pool.<br><br>";
$pg .= '<span class=urg>WARNING:</span> once you have successfully tested and enabled 2FA,<br>';
$pg .= 'you will be unable to access or even reset your account without 2FA.<br>';
$pg .= 'There is no option to recover your 2FA from the web site,<br>';
$pg .= 'and you must know your 2FA code in order to be able to disable 2FA.<br><br>';
$pg .= '<span class=urg>WARNING:</span> it is important to <b>not</b> store your login password in your 2FA device.<br>';
$pg .= 'These 2 together will give full access to your account.';
$pg .= '</td></tr>';
$pg .= '</table>';
if ($draw !== false)
{
$qr = shell_exec("../pool/myqr.sh '$sfaurl'");
if ($qr !== null and strlen($qr) > 30)
{
$pg .= "<script type='text/javascript'>\n";
$pg .= "${qr}qr(tw,fa,qrx,qry,qrd);</script>\n";
if (strpos($qr, 'var tw=1,fa=0,qrx=') === false)
error_log("QR error for '$user' res='$qr'");
}
else
{
if ($qr === null)
$qr = 'null';
error_log("QR failed for '$user' res='$qr'");
}
}
return $pg;
}
#
@ -77,23 +149,30 @@ function do2fa($data, $user)
{
$err = '';
$setup = getparam('Setup', false);
$testemail = false;
if ($setup === 'Setup')
{
// rand() included as part of the entropy
$ans = get2fa($user, 'setup', rand(1073741824,2147483647), 0);
$testemail = true;
}
else
{
$value = getparam('Value', false);
$test = getparam('Test', false);
if ($test === 'Test' and $value !== null)
{
$ans = get2fa($user, 'test', 0, $value);
$testemail = true;
}
else
{
$nw = getparam('New', false);
if ($nw === 'New' and $value !== null)
{
$ans = get2fa($user, 'new', rand(1073741824,2147483647), $value);
$testemail = true;
}
else
$ans = get2fa($user, '', 0, 0);
}
@ -104,6 +183,31 @@ function do2fa($data, $user)
{
if (isset($ans['2fa_error']))
$err = $ans['2fa_error'];
if ($testemail and $err == '')
{
$ans2 = userSettings($user);
if ($ans2['STATUS'] != 'ok')
dbdown(); // Should be no other reason?
if (!isset($ans2['email']))
$err = 'An error occurred, check your details below';
else
{
$email = $ans2['email'];
$emailinfo = getOpts($user, emailOptList());
if ($emailinfo['STATUS'] != 'ok')
$err = 'An error occurred, check your details below';
else
{
if ($setup === 'Setup')
twofaSetup($email, zeip(), $emailinfo);
else if ($test === 'Test')
twofaEnabled($email, zeip(), $emailinfo);
else if ($nw === 'New')
twofaSetup($email, zeip(), $emailinfo);
}
}
}
}
if (!isset($ans['2fa_status']))
$tfa = null;

86
pool/page_blocks.php

@ -1,5 +1,36 @@
<?php
#
function erlcolour($erl)
{
if ($erl <= 0.5)
{
$grn = (-0.3 - log10($erl)) * 383;
if ($grn < 0)
$grn = 0;
if ($grn > 255)
$grn = 255;
if ($grn > 190)
$fg = 'blue';
else
$fg = 'white';
$bg = sprintf("#00%02x00", $grn);
}
else # ($erl > 0.5)
{
$red = (-0.3 - log10(1.0 - $erl)) * 255;
if ($red < 0)
$red = 0;
if ($red > 255)
$red = 255;
$fg = 'white';
$bg = sprintf("#%02x0000", $red);
}
return array($fg, $bg);
}
#
function pctcolour($pct)
{
if ($pct == 100)
@ -79,14 +110,19 @@ function doblocks($data, $user)
$desc = $ans['s_desc:'.$i];
$diff = number_format(100 * $ans['s_diffratio:'.$i], 2);
$mean = number_format(100 * $ans['s_diffmean:'.$i], 2);
$cdferl = number_format($ans['s_cdferl:'.$i], 4);
$cdferl = $ans['s_cdferl:'.$i];
list($fg, $bg) = erlcolour($cdferl);
$cdferldsp = "<font color=$fg>".number_format($cdferl, 4).'</font>';
$bg = " bgcolor=$bg";
$luck = number_format(100 * $ans['s_luck:'.$i], 2);
$pg .= "<tr class=$row>";
$pg .= "<td class=dl>$desc Blocks</td>";
$pg .= "<td class=dr>$diff%</td>";
$pg .= "<td class=dr>$mean%</td>";
$pg .= "<td class=dr>$cdferl</td>";
$pg .= "<td class=dr$bg>$cdferldsp</td>";
$pg .= "<td class=dr>$luck%</td>";
$pg .= "</tr>\n";
}
@ -137,11 +173,13 @@ function doblocks($data, $user)
$pg .= "<td class=dr>Diff</td>";
$pg .= "<td class=dr>Diff%</td>";
$pg .= "<td class=dr>CDF</td>";
$pg .= "<td class=dr>B</td>";
$pg .= "</tr>\n";
}
$blktot = 0;
$nettot = 0;
$i = 0;
$cnt = 0;
$orph = false;
$csv = "Sequence,Height,Status,Timestamp,DiffAcc,NetDiff,Hash\n";
if ($ans['STATUS'] == 'ok')
@ -158,28 +196,55 @@ function doblocks($data, $user)
$hifld = "$blink$hi>$hi</a>";
$ex = '';
$conf = $ans['confirmed:'.$i];
$stat = $ans['status:'.$i];
if ($stat == 'Orphan')
$inf = $ans['info:'.$i];
$tt = '';
if ($conf == 'O' or $conf == 'R')
{
$ex = 's';
$orph = true;
$seq = '';
$nn = $cnt;
if ($conf == 'R')
{
addTips();
$in = explode(':', $inf, 2);
if (trim($in[0]) != '')
$stat = trim($in[0]);
if (count($in) < 2 or trim($in[1]) == '')
{
$tip = 'Share diff was VERY close<br>';
$tip .= 'so we tested it,<br>';
$tip .= "but it wasn't worthy<br>";
}
else
$tip = str_replace('+', '<br>', trim($in[1]));
$tt = "<span class=q onclick='tip(\"btip$i\",6000)'>";
$tt .= '?</span><span class=tip0>';
$tt .= "<span class=notip id=btip$i>";
$tt .= "$tip</span></span>";
}
}
else
{
$seq = $ans['seq:'.$i];
if ($stat == '1-Confirm')
$nn = ++$cnt;
}
if ($conf == '1')
{
if (isset($data['info']['lastheight']))
{
$conf = 1 + $data['info']['lastheight'] - $hi;
$stat = '+'.$conf.' Confirms';
$confn = 1 + $data['info']['lastheight'] - $hi;
$stat = '+'.$confn.' Confirms';
}
else
$stat = 'Conf';
}
$stara = '';
if ($stat == 'Orphan')
if ($conf == 'O' or $conf == 'R')
$stara = '<span class=st1>*</span>';
if (isset($ans['statsconf:'.$i]))
@ -207,7 +272,7 @@ function doblocks($data, $user)
$bpct = "<font color=$fg>$approx".number_format($pct, 3).'%</font>';
$bg = " bgcolor=$bg";
$blktot += $diffacc;
if ($stat != 'Orphan')
if ($conf != 'O' and $conf != 'R')
$nettot += $netdiff;
$cdfdsp = number_format($cdf, 3);
@ -228,10 +293,11 @@ function doblocks($data, $user)
$pg .= "<td class=dl$ex>".htmlspecialchars($ans['workername:'.$i]).'</td>';
$pg .= "<td class=dr$ex>".btcfmt($ans['reward:'.$i]).'</td>';
$pg .= "<td class=dl$ex>".utcd($ans['firstcreatedate:'.$i]).'</td>';
$pg .= "<td class=dr$ex>$stat</td>";
$pg .= "<td class=dr$ex>$tt$stat</td>";
$pg .= "<td class=dr>$stara$approx$acc</td>";
$pg .= "<td class=dr$bg>$bpct</td>";
$pg .= "<td class=dr>$cdfdsp</td>";
$pg .= "<td class=dr>$nn</td>";
$pg .= "</tr>\n";
}
else
@ -259,7 +325,7 @@ function doblocks($data, $user)
else
$pg .= '8';
$pg .= ' class=dc><font size=-1><span class=st1>*</span>';
$pg .= "Orphans count as shares but not as a block in calculations";
$pg .= 'Orphans/Rejects count as shares but not as a block in calculations';
$pg .= '</font></td></tr>';
}
$pg .= "</table>\n";

11
pool/page_payments.php

@ -7,14 +7,17 @@ function sortheight($a, $b)
#
function dopayments($data, $user)
{
$bc = 'https://blockchain.info/address/';
$btc = 'https://www.blocktrail.com/BTC/address/';
$btcn = 'blocktrail';
$addr1 = '1KzFJddTvK9TQWsmWFKYJ9fRx9QeSATyrT';
$addr2 = '16dRhawxuR3BmdmkzdzUdgEfGAQszgmtbc';
$addr3 = '1N6LrEDiHuFwSyJYj2GedZM2FGk7kkLjn';
$pg = '<h1>Payments</h1>';
$pg .= 'The payment transactions on blockchain are here:';
$pg .= " <a href='$bc$addr1' target=_blank>BTCa</a> and";
$pg .= " <a href='$bc$addr2' target=_blank>BTCb</a><br>";
$pg .= "The payment transactions on $btcn are here:";
$pg .= " <a href='$btc$addr1' target=_blank>BTCa</a>,";
$pg .= " <a href='$btc$addr2' target=_blank>BTCb</a> and";
$pg .= " <a href='$btc$addr3' target=_blank>BTCc</a><br>";
$pg .= "The payments below don't yet show when they have been sent.<br><br>";
$ans = getPayments($user);

9
pool/page_reg.php

@ -15,7 +15,14 @@ function doregres($data, $u)
else
$mail = '';
$pg = '<br><br><h1>Choose one:</h1>';
$pg = makeForm('')."<br>
<table cellpadding=0 cellspacing=0 border=0><tr>
<td>User:</td><td><input type=text name=User size=10 value=''></td>
<td>&nbsp;Pass:</td><td><input type=password name=Pass size=10 value=''></td>
<td>&nbsp;<input type=submit name=Login value=Login></td>
</tr></table></form>";
$pg .= '<br><h1>or choose one:</h1>';
$pg .= '<table cellpadding=5 cellspacing=0 border=1><tr><td class=dc>';

2
pool/page_settings.php

@ -218,7 +218,7 @@ function dosettings($data, $user)
$old = $_SESSION['old_set_email'];
else
$old = null;
# emailAddressChanged($email, zeip(), $emailinfo, $old);
emailAddressChanged($email, zeip(), $emailinfo, $old);
break;
case 'Address':
payoutAddressChanged($email, zeip(), $emailinfo);

3
sql/ckdb.sql

@ -336,6 +336,7 @@ CREATE TABLE blocks (
nonce character varying(64) NOT NULL,
reward bigint NOT NULL, -- satoshis
confirmed char DEFAULT '' NOT NULL,
info character varying(64) DEFAULT ''::character varying NOT NULL,
diffacc float DEFAULT 0 NOT NULL,
diffinv float DEFAULT 0 NOT NULL,
shareacc float DEFAULT 0 NOT NULL,
@ -463,4 +464,4 @@ CREATE TABLE version (
PRIMARY KEY (vlock)
);
insert into version (vlock,version) values (1,'1.0.1');
insert into version (vlock,version) values (1,'1.0.2');

25
sql/v1.0.1-v1.0.2.sql

@ -0,0 +1,25 @@
SET SESSION AUTHORIZATION 'postgres';
BEGIN transaction;
DO $$
DECLARE ver TEXT;
BEGIN
UPDATE version set version='1.0.2' where vlock=1 and version='1.0.1';
IF found THEN
RETURN;
END IF;
SELECT version into ver from version
WHERE vlock=1;
RAISE EXCEPTION 'Wrong DB version - expect "1.0.1" - found "%"', ver;
END $$;
ALTER TABLE ONLY blocks
ADD COLUMN info character varying(64) DEFAULT ''::character varying NOT NULL;
END transaction;

15
src/ckdb.c

@ -165,6 +165,8 @@ const char *hashpatt = "^[A-Fa-f0-9]*$";
* and with a simple test must be ADDR_MIN_LEN to ADDR_MAX_LEN (ckdb.h)
* bitcoind is used to fully validate them when required */
const char *addrpatt = "^[13][A-HJ-NP-Za-km-z1-9]*$";
// Strings in socket transfer: space to '~' excluding '='
const char *strpatt = "^[ -<>-~]*$";
// So the records below have the same 'name' as the klist
const char Transfer[] = "Transfer";
@ -423,6 +425,7 @@ const char *blocks_new = "New";
const char *blocks_confirm = "1-Confirm";
const char *blocks_42 = "Matured";
const char *blocks_orphan = "Orphan";
const char *blocks_reject = "Unworthy";
const char *blocks_unknown = "?Unknown?";
K_TREE *blocks_root;
@ -1320,7 +1323,9 @@ static void dealloc_storage()
FREE_ALL(auths);
FREE_TREE(payouts_id);
FREE_ALL(payouts);
FREE_TREE(payouts);
FREE_STORE_DATA(payouts);
FREE_LIST_DATA(payouts);
FREE_ALL(miningpayouts);
FREE_ALL(blocks);
@ -1400,7 +1405,9 @@ static void dealloc_storage()
FREE_ALL(useratts);
FREE_TREE(userid);
FREE_ALL(users);
FREE_TREE(users);
FREE_STORE_DATA(users);
FREE_LIST_DATA(users);
LOGWARNING("%s() transfer/heartbeatqueue/workqueue ...", __func__);
@ -4676,7 +4683,7 @@ static void *listener(void *arg)
LOGEMERG("ABORTING");
everyone_die = true;
}
return NULL;
goto sayonara;
}
if (!everyone_die) {
@ -4785,6 +4792,8 @@ static void *listener(void *arg)
}
}
sayonara:
listener_using_data = false;
if (conn)

104
src/ckdb.h

@ -54,8 +54,8 @@
*/
#define DB_VLOCK "1"
#define DB_VERSION "1.0.1"
#define CKDB_VERSION DB_VERSION"-1.200"
#define DB_VERSION "1.0.2"
#define CKDB_VERSION DB_VERSION"-1.222"
#define WHERE_FFL " - from %s %s() line %d"
#define WHERE_FFL_HERE __FILE__, __func__, __LINE__
@ -67,13 +67,6 @@
#define STRINT(x) STRINT2(x)
#define STRINT2(x) #x
#define FREENULL(mem) do { \
if (mem) { \
free(mem); \
mem = NULL; \
} \
} while (0)
// So they can fit into a 1 byte flag field
#define TRUE_STR "Y"
#define FALSE_STR "N"
@ -105,6 +98,13 @@ extern int switch_state;
#define BLANK " "
extern char *EMPTY;
#define FREENULL(mem) do { \
if ((mem) && (void *)(mem) != (void *)EMPTY) { \
free(mem); \
mem = NULL; \
} \
} while (0)
// To ensure there's space for the ticker
#define TICK_PREFIX " "
@ -115,6 +115,7 @@ extern const char *idpatt;
extern const char *intpatt;
extern const char *hashpatt;
extern const char *addrpatt;
extern const char *strpatt;
/* If a trimmed username is like an address but this many or more characters,
* disallow it */
@ -450,17 +451,21 @@ enum cmd_values {
} while (0)
#define LIST_MEM_ADD(_list, _fld) do { \
size_t __siz; \
__siz = strlen(_fld) + 1; \
LIST_MEM_ADD_SIZ(_list, __siz); \
if ((_fld) && (_fld) != EMPTY) { \
size_t __siz; \
__siz = strlen(_fld) + 1; \
LIST_MEM_ADD_SIZ(_list, __siz); \
} \
} while (0)
#define LIST_MEM_SUB(_list, _fld) do { \
size_t __siz; \
__siz = strlen(_fld) + 1; \
if (__siz % MEMBASE) \
__siz += MEMBASE - (__siz % MEMBASE); \
_list->ram -= (int)__siz; \
if ((_fld) && (_fld) != EMPTY) { \
size_t __siz; \
__siz = strlen(_fld) + 1; \
if (__siz % MEMBASE) \
__siz += MEMBASE - (__siz % MEMBASE); \
_list->ram -= (int)__siz; \
} \
} while (0)
#define SET_POINTER(_list, _fld, _val, _def) do { \
@ -479,11 +484,28 @@ enum cmd_values {
LIST_MEM_ADD(_list, _val); \
_fld = strdup(_val); \
if (!(_fld)) \
quithere(1, "malloc OOM"); \
quithere(1, "strdup OOM"); \
} \
} \
} while (0)
#define DUP_POINTER(_list, _fld, _val) do { \
if ((_fld) && ((_fld) != EMPTY)) { \
if (_list) \
LIST_MEM_SUB(_list, _fld); \
free(_fld); \
} \
if (!(_val) || !(*(_val))) \
(_fld) = EMPTY; \
else { \
if (_list) \
LIST_MEM_ADD(_list, _val); \
_fld = strdup(_val); \
if (!(_fld)) \
quithere(1, "strdup OOM"); \
} \
} while (0)
#define SET_CREATEBY(_list, _fld, _val) SET_POINTER(_list, _fld, _val, by_default)
#define SET_CREATECODE(_list, _fld, _val) SET_POINTER(_list, _fld, _val, EMPTY)
#define SET_CREATEINET(_list, _fld, _val) SET_POINTER(_list, _fld, _val, inet_default)
@ -1021,6 +1043,7 @@ typedef struct users {
char *userdata;
int64_t databits; // non-DB field, Bitmask of userdata content
int64_t userbits; // Bitmask of user attributes
int32_t lastvalue; // non-DB field
HISTORYDATECONTROLFIELDS;
} USERS;
@ -1440,6 +1463,8 @@ typedef struct blocks {
char nonce[TXT_SML+1];
int64_t reward;
char confirmed[TXT_FLAG+1];
// block Short:Description to use vs default for 'R' in page_blocks.php
char info[TXT_SML+1];
double diffacc;
double diffinv;
double shareacc;
@ -1487,6 +1512,15 @@ typedef struct blocks {
#define BLOCKS_42_VALUE 101
#define BLOCKS_ORPHAN 'O'
#define BLOCKS_ORPHAN_STR "O"
#define BLOCKS_REJECT 'R'
#define BLOCKS_REJECT_STR "R"
#define BLOCKS_N_C_STR BLOCKS_NEW_STR " or " BLOCKS_CONFIRM_STR
#define BLOCKS_N_C_O_STR BLOCKS_NEW_STR ", " BLOCKS_CONFIRM_STR " or " \
BLOCKS_ORPHAN_STR
#define BLOCKS_N_C_O_R_STR BLOCKS_NEW_STR ", " BLOCKS_CONFIRM_STR ", " \
BLOCKS_ORPHAN_STR " or " BLOCKS_REJECT_STR
/* Block height difference required before checking if it's orphaned
* TODO: add a cmd_blockstatus option to un-orphan a block */
#define BLOCKS_ORPHAN_CHECK 1
@ -1500,6 +1534,7 @@ extern const char *blocks_new;
extern const char *blocks_confirm;
extern const char *blocks_42;
extern const char *blocks_orphan;
extern const char *blocks_reject;
extern const char *blocks_unknown;
#define KANO -27972
@ -1572,6 +1607,10 @@ extern cklock_t process_pplns_lock;
#define PAYOUTS_ORPHAN 'O'
#define PAYOUTS_ORPHAN_STR "O"
#define PAYORPHAN(_status) ((_status)[0] == PAYOUTS_ORPHAN)
// A rejected payout must be ignored
#define PAYOUTS_REJECT 'R'
#define PAYOUTS_REJECT_STR "R"
#define PAYREJECT(_status) ((_status)[0] == PAYOUTS_REJECT)
// Default number of shifts (payouts) to display on web
#define SHIFTS_DEFAULT 99
@ -1972,12 +2011,19 @@ extern const char *marktype_shift_end_skip;
#define MARK_USED_STR "u"
#define MUSED(_status) (tolower((_status)[0]) == MARK_USED)
enum info_type {
INFO_NEW,
INFO_ORPHAN,
INFO_REJECT
};
// USERINFO from various incoming data
typedef struct userinfo {
int64_t userid;
char username[TXT_BIG+1];
int blocks;
int orphans; // How many blocks are orphans
int rejects; // How many blocks are rejects
tv_t last_block;
// For all time
double diffacc;
@ -2028,9 +2074,13 @@ extern void sequence_report(bool lock);
#define REWARDOVERRIDE "MinerReward"
// Data free functions (first)
#define FREE_ITEM(item) do { } while(0)
// TODO: make a macro for all other to use above macro
extern void free_msgline_data(K_ITEM *item, bool t_lock, bool t_cull);
extern void free_users_data(K_ITEM *item);
extern void free_workinfo_data(K_ITEM *item);
extern void free_sharesummary_data(K_ITEM *item);
extern void free_payouts_data(K_ITEM *item);
extern void free_optioncontrol_data(K_ITEM *item);
extern void free_markersummary_data(K_ITEM *item);
extern void free_workmarkers_data(K_ITEM *item);
@ -2038,6 +2088,12 @@ extern void free_marks_data(K_ITEM *item);
#define free_seqset_data(_item) _free_seqset_data(_item, false)
extern void _free_seqset_data(K_ITEM *item, bool lock);
// Data copy functions
#define COPY_DATA(_new, _old) memcpy(_new, _old, sizeof(*(_new)))
extern void copy_users(USERS *newu, USERS *oldu);
#define copy_blocks(_newb, _oldb) COPY_DATA(_newb, _oldb)
#define safe_text(_txt) _safe_text(_txt, true)
#define safe_text_nonull(_txt) _safe_text(_txt, false)
extern char *_safe_text(char *txt, bool shownull);
@ -2270,7 +2326,7 @@ extern K_ITEM *find_markersummary_userid(int64_t userid, char *workername,
_find_markersummary(_markerid, 0, KANO, EMPTY, true)
#define POOL_MS(_row) do { \
(_row)->userid = KANO; \
(_row)->workername = strdup(EMPTY); \
(_row)->workername = EMPTY; \
} while (0)
extern K_ITEM *_find_markersummary(int64_t markerid, int64_t workinfoid,
int64_t userid, char *workername, bool pool);
@ -2303,7 +2359,7 @@ extern K_ITEM *_find_create_userinfo(int64_t userid, bool lock, WHERE_FFL_ARGS);
extern void _userinfo_update(SHARES *shares, SHARESUMMARY *sharesummary,
MARKERSUMMARY *markersummary, bool ss_sub, bool lock);
#define userinfo_block(_blocks, _isnew) _userinfo_block(_blocks, _isnew, true)
extern void _userinfo_block(BLOCKS *blocks, bool isnew, bool lock);
extern void _userinfo_block(BLOCKS *blocks, enum info_type isnew, bool lock);
// ***
// *** PostgreSQL functions ckdb_dbio.c
@ -2436,9 +2492,9 @@ extern bool blocks_stats(PGconn *conn, int32_t height, char *blockhash,
double shareinv, int64_t elapsed,
char *by, char *code, char *inet, tv_t *cd);
extern bool blocks_add(PGconn *conn, char *height, char *blockhash,
char *confirmed, char *workinfoid, char *username,
char *workername, char *clientid, char *enonce1,
char *nonce2, char *nonce, char *reward,
char *confirmed, char *info, char *workinfoid,
char *username, char *workername, char *clientid,
char *enonce1, char *nonce2, char *nonce, char *reward,
char *by, char *code, char *inet, tv_t *cd,
bool igndup, char *id, K_TREE *trf_root);
extern bool blocks_fill(PGconn *conn);
@ -2551,5 +2607,7 @@ extern K_ITEM *gen_2fa_key(K_ITEM *old_u_item, int32_t entropy, char *by,
extern bool check_2fa(USERS *users, int32_t value);
extern bool tst_2fa(K_ITEM *old_u_item, int32_t value, char *by, char *code,
char *inet, tv_t *cd, K_TREE *trf_root);
extern K_ITEM *remove_2fa(K_ITEM *old_u_item, int32_t value, char *by,
char *code, char *inet, tv_t *cd, K_TREE *trf_root);
#endif

4
src/ckdb_btc.c

@ -355,7 +355,7 @@ void btc_blockstatus(BLOCKS *blocks)
ok = blocks_add(NULL, height_str,
blocks->blockhash,
BLOCKS_ORPHAN_STR,
BLOCKS_ORPHAN_STR, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY,
by_default, (char *)__func__, inet_default,
@ -378,7 +378,7 @@ void btc_blockstatus(BLOCKS *blocks)
ok = blocks_add(NULL, height_str,
blocks->blockhash,
BLOCKS_42_STR,
BLOCKS_42_STR, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY,
by_default, (char *)__func__, inet_default,

134
src/ckdb_cmd.c

@ -325,6 +325,24 @@ static char *cmd_2fa(__maybe_unused PGconn *conn, char *cmd, char *id,
DATA_USERS(users, u_item);
}
}
} else if (strcmp(action, "remove") == 0) {
// Can't remove if 2FA isn't already present
if (!(users->databits & (USER_TOTPAUTH | USER_TEST2FA)))
goto dame;
value = (int32_t)atoi(transfer_data(i_value));
if (!check_2fa(users, value)) {
sfa_error = "Invalid code";
// Report sfa_error to web
ok = true;
} else {
u_new = remove_2fa(u_item, value, by, code,
inet, now, trf_root);
if (u_new) {
ok = true;
sfa_status = EMPTY;
key = false;
}
}
}
if (key) {
char *keystr, *issuer = "Kano";
@ -1132,7 +1150,8 @@ redo:
while (b_item) {
DATA_BLOCKS(blocks, b_item);
if (CURRENT(&(blocks->expirydate))) {
if (blocks->confirmed[0] != BLOCKS_ORPHAN)
if (blocks->confirmed[0] != BLOCKS_ORPHAN &&
blocks->confirmed[0] != BLOCKS_REJECT)
tot++;
}
b_item = next_in_ktree(ctx);
@ -1149,10 +1168,14 @@ redo:
copy_tv(&first_cd, &(blocks->createdate));
}
if (CURRENT(&(blocks->expirydate))) {
if (blocks->confirmed[0] == BLOCKS_ORPHAN) {
if (blocks->confirmed[0] == BLOCKS_ORPHAN ||
blocks->confirmed[0] == BLOCKS_REJECT) {
snprintf(tmp, sizeof(tmp),
"seq:%d=o%c",
rows, FLDSEP);
"seq:%d=%c%c",
rows,
blocks->confirmed[0] == BLOCKS_ORPHAN ?
'o' : 'r',
FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
} else {
snprintf(tmp, sizeof(tmp),
@ -1191,10 +1214,16 @@ redo:
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp),
"status:%d=%s%c", rows,
"confirmed:%d=%s%cstatus:%d=%s%c", rows,
blocks->confirmed, FLDSEP, rows,
blocks_confirmed(blocks->confirmed), FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp),
"info:%d=%s%c", rows,
blocks->info, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp),
"statsconf:%d=%s%c", rows,
blocks->statsconfirmed, FLDSEP);
@ -1248,7 +1277,8 @@ redo:
while (b_item) {
DATA_BLOCKS(blocks, b_item);
if (CURRENT(&(blocks->expirydate)) &&
blocks->confirmed[0] != BLOCKS_ORPHAN) {
blocks->confirmed[0] != BLOCKS_ORPHAN &&
blocks->confirmed[0] != BLOCKS_REJECT) {
desc = NULL;
if (seq == 1) {
snprintf(desc_buf, sizeof(desc_buf),
@ -1314,8 +1344,9 @@ redo:
"rows=%d%cflds=%s%c",
rows, FLDSEP,
"seq,height,blockhash,nonce,reward,workername,first"CDTRF","
CDTRF",status,statsconf,diffacc,diffinv,shareacc,"
"shareinv,elapsed,netdiff,diffratio,cdf,luck", FLDSEP);
CDTRF",confirmed,status,info,statsconf,diffacc,diffinv,"
"shareacc,shareinv,elapsed,netdiff,diffratio,cdf,luck",
FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "arn=%s%carp=%s", "Blocks,BlockStats", FLDSEP, ",s");
@ -1329,13 +1360,13 @@ static char *cmd_blockstatus(__maybe_unused PGconn *conn, char *cmd, char *id,
tv_t *now, char *by, char *code, char *inet,
__maybe_unused tv_t *cd, K_TREE *trf_root)
{
K_ITEM *i_height, *i_blockhash, *i_action;
K_ITEM *i_height, *i_blockhash, *i_action, *i_info;
char reply[1024] = "";
size_t siz = sizeof(reply);
K_ITEM *b_item;
BLOCKS *blocks;
int32_t height;
char *action;
char *action, *info, *tmp;
bool ok = false;
LOGDEBUG("%s(): cmd '%s'", __func__, cmd);
@ -1368,13 +1399,57 @@ static char *cmd_blockstatus(__maybe_unused PGconn *conn, char *cmd, char *id,
DATA_BLOCKS(blocks, b_item);
// Default to previous value
info = blocks->info;
if (strcasecmp(action, "orphan") == 0) {
switch (blocks->confirmed[0]) {
case BLOCKS_NEW:
case BLOCKS_CONFIRM:
ok = blocks_add(conn, transfer_data(i_height),
blocks->blockhash,
BLOCKS_ORPHAN_STR,
BLOCKS_ORPHAN_STR, info,
EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY,
by, code, inet, now, false, id,
trf_root);
if (!ok) {
snprintf(reply, siz,
"DBE.action '%s'",
action);
LOGERR("%s.%s", id, reply);
return strdup(reply);
}
// TODO: reset the share counter?
break;
default:
snprintf(reply, siz,
"ERR.invalid action '%.*s%s' for block state '%s'",
CMD_SIZ, action,
(strlen(action) > CMD_SIZ) ? "..." : "",
blocks_confirmed(blocks->confirmed));
LOGERR("%s.%s", id, reply);
return strdup(reply);
}
} else if (strcasecmp(action, "reject") == 0) {
i_info = require_name(trf_root, "info", 0, (char *)strpatt,
reply, siz);
if (!i_info)
return strdup(reply);
tmp = transfer_data(i_info);
/* Override if not empty
* Thus you can't blank it out if current has a value */
if (tmp && *tmp)
info = tmp;
switch (blocks->confirmed[0]) {
case BLOCKS_NEW:
case BLOCKS_CONFIRM:
case BLOCKS_ORPHAN:
case BLOCKS_REJECT:
ok = blocks_add(conn, transfer_data(i_height),
blocks->blockhash,
BLOCKS_REJECT_STR, info,
EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY,
by, code, inet, now, false, id,
@ -1403,7 +1478,7 @@ static char *cmd_blockstatus(__maybe_unused PGconn *conn, char *cmd, char *id,
case BLOCKS_NEW:
ok = blocks_add(conn, transfer_data(i_height),
blocks->blockhash,
BLOCKS_CONFIRM_STR,
BLOCKS_CONFIRM_STR, info,
EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY,
by, code, inet, now, false, id,
@ -2596,6 +2671,7 @@ static char *cmd_blocks_do(PGconn *conn, char *cmd, char *id, char *by,
ok = blocks_add(conn, transfer_data(i_height),
transfer_data(i_blockhash),
transfer_data(i_confirmed),
EMPTY,
transfer_data(i_workinfoid),
transfer_data(i_username),
transfer_data(i_workername),
@ -2612,6 +2688,7 @@ static char *cmd_blocks_do(PGconn *conn, char *cmd, char *id, char *by,
ok = blocks_add(conn, transfer_data(i_height),
transfer_data(i_blockhash),
transfer_data(i_confirmed),
EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY,
by, code, inet, cd, igndup, id,
@ -3794,9 +3871,8 @@ static char *cmd_setopts(PGconn *conn, char *cmd, char *id,
gotvalue = false;
}
if (strcmp(dot, "value") == 0) {
optioncontrol->optionvalue = strdup(data);
if (!(optioncontrol->optionvalue))
quithere(1, "malloc (%d) OOM", (int)strlen(data));
DUP_POINTER(optioncontrol_free,
optioncontrol->optionvalue, data);
gotvalue = true;
} else if (strcmp(dot, "date") == 0) {
att_to_date(&(optioncontrol->activationdate), data, now);
@ -3977,6 +4053,7 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id,
block_extra = "Can't be paid out yet";
break;
case BLOCKS_ORPHAN:
case BLOCKS_REJECT:
block_extra = "Can't be paid out";
break;
default:
@ -4428,6 +4505,7 @@ static char *cmd_pplns2(__maybe_unused PGconn *conn, char *cmd, char *id,
block_extra = "Can't be paid out yet";
break;
case BLOCKS_ORPHAN:
case BLOCKS_REJECT:
block_extra = "Can't be paid out";
break;
default:
@ -4694,7 +4772,7 @@ static char *cmd_payouts(PGconn *conn, char *cmd, char *id, tv_t *now,
payouts2->diffused = payouts->diffused;
payouts2->shareacc = payouts->shareacc;
copy_tv(&(payouts2->lastshareacc), &(payouts->lastshareacc));
payouts2->stats = strdup(payouts->stats);
DUP_POINTER(payouts_free, payouts2->stats, payouts->stats);
ok = payouts_add(conn, true, p2_item, &old_p2_item,
by, code, inet, now, NULL, false);
@ -4709,12 +4787,14 @@ static char *cmd_payouts(PGconn *conn, char *cmd, char *id, tv_t *now,
"%"PRId32"/%s",
payoutid, old_payouts2->status, payouts2->status,
payouts2->height, payouts2->blockhash);
} else if (strcasecmp(action, "orphan") == 0) {
} else if (strcasecmp(action, "orphan") == 0 ||
strcasecmp(action, "reject") == 0) {
/* Change the status of a generated payout to orphaned
* or rejected
* Require payoutid
* Use this if the orphan process didn't automatically
* update a generated payout to orphaned
* TODO: get orphaned blocks to automatically do this */
* Use this if the orphan or reject process didn't
* automatically update a generated payout
* TODO: get orphaned and rejected blocks to automatically do this */
i_payoutid = require_name(trf_root, "payoutid", 1,
(char *)intpatt, reply, siz);
if (!i_payoutid)
@ -4753,12 +4833,15 @@ static char *cmd_payouts(PGconn *conn, char *cmd, char *id, tv_t *now,
payouts2->workinfoidstart = payouts->workinfoidstart;
payouts2->workinfoidend = payouts->workinfoidend;
payouts2->elapsed = payouts->elapsed;
STRNCPY(payouts2->status, PAYOUTS_ORPHAN_STR);
if (strcasecmp(action, "orphan") == 0)
STRNCPY(payouts2->status, PAYOUTS_ORPHAN_STR);
else
STRNCPY(payouts2->status, PAYOUTS_REJECT_STR);
payouts2->diffwanted = payouts->diffwanted;
payouts2->diffused = payouts->diffused;
payouts2->shareacc = payouts->shareacc;
copy_tv(&(payouts2->lastshareacc), &(payouts->lastshareacc));
payouts2->stats = strdup(payouts->stats);
DUP_POINTER(payouts_free, payouts2->stats, payouts->stats);
ok = payouts_add(conn, true, p2_item, &old_p2_item,
by, code, inet, now, NULL, false);
@ -5410,8 +5493,7 @@ static char *cmd_stats(__maybe_unused PGconn *conn, char *cmd, char *id,
APPEND_REALLOC_INIT(buf, off, len);
APPEND_REALLOC(buf, off, len, "ok.");
// Doesn't include blob memory
// - average transactiontree length of ~119k I have is ~28k (>3.3GB)
// FYI average transactiontree length of the ~119k I have is ~28k (>3.3GB)
#define USEINFO(_obj, _stores, _trees) \
klist = _obj ## _free; \
ram = sizeof(K_LIST) + _stores * sizeof(K_STORE) + \
@ -6166,7 +6248,9 @@ static char *cmd_userinfo(__maybe_unused PGconn *conn, char *cmd, char *id,
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "blocks:%d=%d%c", rows,
userinfo->blocks - userinfo->orphans, FLDSEP);
userinfo->blocks -
(userinfo->orphans + userinfo->rejects),
FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "orphans:%d=%d%c", rows,

71
src/ckdb_crypt.c

@ -117,12 +117,7 @@ K_ITEM *gen_2fa_key(K_ITEM *old_u_item, int32_t entropy, char *by, char *code,
u_item = k_unlink_head(users_free);
K_WUNLOCK(users_free);
DATA_USERS(users, u_item);
memcpy(users, old_users, sizeof(*users));
if (users->userdata != EMPTY) {
users->userdata = strdup(users->userdata);
if (!users->userdata)
quithere(1, "strdup OOM");
}
copy_users(users, old_users);
users_userdata_add_bin(users, USER_TOTPAUTH_NAME,
USER_TOTPAUTH, key, sizeof(key));
users_userdata_add_txt(users, USER_TEST2FA_NAME,
@ -198,15 +193,23 @@ bool check_2fa(USERS *users, int32_t value)
otp %= 1000000;
LOGDEBUG("%s() '%s/%s offset=%d otp=%"PRId32" value=%"PRId32,
LOGDEBUG("%s() '%s/%s offset=%d otp=%"PRId32" value=%"PRId32
" lastvalue=%"PRId32,
__func__, st = safe_text_nonull(users->username),
USER_TOTPAUTH_NAME, offset, otp, value);
USER_TOTPAUTH_NAME, offset, otp, value, users->lastvalue);
FREENULL(st);
FREENULL(hash);
if (otp == value)
/* Disallow 0 since that's the default value
* If it is 0, that means wait another TOTPAUTH_TIME and try again
* 0 is only one in a million tests for all users
* For security reasons, we can't allow using the same value twice,
* N.B. a ckdb restart will forget lastvalue, but a restart should
* take long enough to resolve that issue */
if (otp == value && otp != 0 && otp != users->lastvalue) {
users->lastvalue = otp;
return true;
else
} else
return false;
}
@ -224,12 +227,7 @@ bool tst_2fa(K_ITEM *old_u_item, int32_t value, char *by, char *code,
u_item = k_unlink_head(users_free);
K_WUNLOCK(users_free);
DATA_USERS(users, u_item);
memcpy(users, old_users, sizeof(*users));
if (users->userdata != EMPTY) {
users->userdata = strdup(users->userdata);
if (!users->userdata)
quithere(1, "strdup OOM");
}
copy_users(users, old_users);
users_userdata_del(users, USER_TEST2FA_NAME, USER_TEST2FA);
ok = users_replace(NULL, u_item, old_u_item, by, code, inet, cd,
trf_root);
@ -237,3 +235,44 @@ bool tst_2fa(K_ITEM *old_u_item, int32_t value, char *by, char *code,
}
return ok;
}
K_ITEM *remove_2fa(K_ITEM *old_u_item, int32_t value, char *by, char *code,
char *inet, tv_t *cd, K_TREE *trf_root)
{
K_ITEM *u_item = NULL;
USERS *old_users, *users;
bool ok, did = false;
DATA_USERS(old_users, old_u_item);
ok = check_2fa(old_users, value);
if (ok) {
K_WLOCK(users_free);
u_item = k_unlink_head(users_free);
K_WUNLOCK(users_free);
DATA_USERS(users, u_item);
copy_users(users, old_users);
if (users->databits & USER_TEST2FA) {
users_userdata_del(users, USER_TEST2FA_NAME, USER_TEST2FA);
did = true;
}
if (users->databits & USER_TOTPAUTH) {
users_userdata_del(users, USER_TOTPAUTH_NAME, USER_TOTPAUTH);
did = true;
}
if (did) {
ok = users_replace(NULL, u_item, old_u_item, by, code, inet, cd,
trf_root);
if (!ok) {
// u_item was cleaned up in user_replace()
u_item = NULL;
}
} else {
K_WLOCK(users_free);
free_users_data(u_item);
k_add_head(users_free, u_item);
K_WUNLOCK(users_free);
u_item = NULL;
}
}
return u_item;
}

100
src/ckdb_data.c

@ -44,15 +44,33 @@ void free_msgline_data(K_ITEM *item, bool t_lock, bool t_cull)
FREENULL(msgline->msg);
}
void free_users_data(K_ITEM *item)
{
USERS *users;
DATA_USERS(users, item);
LIST_MEM_SUB(users_free, users->userdata);
FREENULL(users->userdata);
}
void free_workinfo_data(K_ITEM *item)
{
WORKINFO *workinfo;
DATA_WORKINFO(workinfo, item);
if (workinfo->transactiontree)
FREENULL(workinfo->transactiontree);
if (workinfo->merklehash)
FREENULL(workinfo->merklehash);
LIST_MEM_SUB(workinfo_free, workinfo->transactiontree);
FREENULL(workinfo->transactiontree);
LIST_MEM_SUB(workinfo_free, workinfo->merklehash);
FREENULL(workinfo->merklehash);
}
void free_payouts_data(K_ITEM *item)
{
PAYOUTS *payouts;
DATA_PAYOUTS(payouts, item);
LIST_MEM_SUB(payouts_free, payouts->stats);
FREENULL(payouts->stats);
}
void free_sharesummary_data(K_ITEM *item)
@ -60,10 +78,8 @@ void free_sharesummary_data(K_ITEM *item)
SHARESUMMARY *sharesummary;
DATA_SHARESUMMARY(sharesummary, item);
if (sharesummary->workername) {
LIST_MEM_SUB(sharesummary_free, sharesummary->workername);
FREENULL(sharesummary->workername);
}
LIST_MEM_SUB(sharesummary_free, sharesummary->workername);
FREENULL(sharesummary->workername);
SET_CREATEBY(sharesummary_free, sharesummary->createby, EMPTY);
SET_CREATECODE(sharesummary_free, sharesummary->createcode, EMPTY);
SET_CREATEINET(sharesummary_free, sharesummary->createinet, EMPTY);
@ -77,8 +93,8 @@ void free_optioncontrol_data(K_ITEM *item)
OPTIONCONTROL *optioncontrol;
DATA_OPTIONCONTROL(optioncontrol, item);
if (optioncontrol->optionvalue)
FREENULL(optioncontrol->optionvalue);
LIST_MEM_SUB(optioncontrol_free, optioncontrol->optionvalue);
FREENULL(optioncontrol->optionvalue);
}
void free_markersummary_data(K_ITEM *item)
@ -86,8 +102,8 @@ void free_markersummary_data(K_ITEM *item)
MARKERSUMMARY *markersummary;
DATA_MARKERSUMMARY(markersummary, item);
if (markersummary->workername)
FREENULL(markersummary->workername);
LIST_MEM_SUB(markersummary_free, markersummary->workername);
FREENULL(markersummary->workername);
SET_CREATEBY(markersummary_free, markersummary->createby, EMPTY);
SET_CREATECODE(markersummary_free, markersummary->createcode, EMPTY);
SET_CREATEINET(markersummary_free, markersummary->createinet, EMPTY);
@ -101,10 +117,10 @@ void free_workmarkers_data(K_ITEM *item)
WORKMARKERS *workmarkers;
DATA_WORKMARKERS(workmarkers, item);
if (workmarkers->poolinstance)
FREENULL(workmarkers->poolinstance);
if (workmarkers->description)
FREENULL(workmarkers->description);
LIST_MEM_SUB(workmarkers_free, workmarkers->poolinstance);
FREENULL(workmarkers->poolinstance);
LIST_MEM_SUB(workmarkers_free, workmarkers->description);
FREENULL(workmarkers->description);
}
void free_marks_data(K_ITEM *item)
@ -112,12 +128,12 @@ void free_marks_data(K_ITEM *item)
MARKS *marks;
DATA_MARKS(marks, item);
if (marks->poolinstance && marks->poolinstance != EMPTY)
FREENULL(marks->poolinstance);
if (marks->description && marks->description != EMPTY)
FREENULL(marks->description);
if (marks->extra && marks->extra != EMPTY)
FREENULL(marks->extra);
LIST_MEM_SUB(marks_free, marks->poolinstance);
FREENULL(marks->poolinstance);
LIST_MEM_SUB(marks_free, marks->description);
FREENULL(marks->description);
LIST_MEM_SUB(marks_free, marks->extra);
FREENULL(marks->extra);
}
void _free_seqset_data(K_ITEM *item, bool lock)
@ -145,6 +161,16 @@ void _free_seqset_data(K_ITEM *item, bool lock)
}
}
/* Data copy functions (added here as needed)
All pointers need to initialised since DUP_POINTER will free them */
void copy_users(USERS *newu, USERS *oldu)
{
memcpy(newu, oldu, sizeof(*newu));
newu->userdata = NULL;
DUP_POINTER(users_free, newu->userdata, oldu->userdata);
}
// Clear text printable version of txt up to first '\0'
char *_safe_text(char *txt, bool shownull)
{
@ -2629,6 +2655,8 @@ const char *blocks_confirmed(char *confirmed)
return blocks_42;
case BLOCKS_ORPHAN:
return blocks_orphan;
case BLOCKS_REJECT:
return blocks_reject;
}
return blocks_unknown;
}
@ -2869,7 +2897,8 @@ bool check_update_blocks_stats(tv_t *stats)
DATA_BLOCKS(blocks, b_item);
if (CURRENT(&(blocks->expirydate))) {
pending += blocks->diffacc;
if (blocks->confirmed[0] == BLOCKS_ORPHAN)
if (blocks->confirmed[0] == BLOCKS_ORPHAN ||
blocks->confirmed[0] == BLOCKS_REJECT)
blocks->diffcalc = 0.0;
else {
blocks->diffcalc = pending;
@ -2918,10 +2947,11 @@ bool check_update_blocks_stats(tv_t *stats)
else
blocks->blockluck = 1.0 / blocks->blockdiffratio;
/* Orphans are treated as +diffacc but no block
/* Orphans/Rejects are treated as +diffacc but no block
* i.e. they simply add shares to the later block
* and have running stats set to zero */
if (blocks->confirmed[0] == BLOCKS_ORPHAN) {
if (blocks->confirmed[0] == BLOCKS_ORPHAN ||
blocks->confirmed[0] == BLOCKS_REJECT) {
blocks->diffratio = 0.0;
blocks->diffmean = 0.0;
blocks->cdferl = 0.0;
@ -3311,6 +3341,7 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd)
switch (blocks->confirmed[0]) {
case BLOCKS_NEW:
case BLOCKS_ORPHAN:
case BLOCKS_REJECT:
LOGERR("%s(): can't process block %"PRId32"/%"
PRId64"/%s/%"PRId64" status: %s/%s",
__func__, blocks->height, blocks->workinfoid,
@ -3656,7 +3687,7 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd)
diff_times, FLDSEP, diff_add, FLDSEP, total_share_count,
FLDSEP, ss_count, FLDSEP, wm_count, FLDSEP, ms_count,
FLDSEP, cd_buf);
payouts->stats = buf;
DUP_POINTER(payouts_free, payouts->stats, &buf[0]);
conned = CKPQConn(&conn);
begun = CKPQBegin(conn);
@ -3870,9 +3901,6 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd)
ss_count, wm_count, ms_count, usercount, diff_times,
diff_add, cd_buf);
// convert the stack memory to heap memeory
payouts->stats = strdup(payouts->stats);
K_WLOCK(payouts_free);
p2_item = k_unlink_head(payouts_free);
K_WUNLOCK(payouts_free);
@ -3890,7 +3918,7 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd)
payouts2->diffused = payouts->diffused;
payouts2->shareacc = payouts->shareacc;
copy_tv(&(payouts2->lastshareacc), &(payouts->lastshareacc));
payouts2->stats = strdup(payouts->stats);
DUP_POINTER(payouts_free, payouts2->stats, payouts->stats);
setnow(&now);
/* N.B. the PROCESSING payouts could have expirydate = createdate
@ -3918,6 +3946,7 @@ shazbot:
if (p_item) {
K_WLOCK(payouts_free);
free_payouts_data(p_item);
k_add_head(payouts_free, p_item);
K_WUNLOCK(payouts_free);
}
@ -4867,8 +4896,8 @@ void _userinfo_update(SHARES *shares, SHARESUMMARY *sharesummary,
}
}
// N.B. good blocks = blocks - orphans
void _userinfo_block(BLOCKS *blocks, bool isnew, bool lock)
// N.B. good blocks = blocks - (orphans + rejects)
void _userinfo_block(BLOCKS *blocks, enum info_type isnew, bool lock)
{
USERINFO *row;
K_ITEM *item;
@ -4877,11 +4906,14 @@ void _userinfo_block(BLOCKS *blocks, bool isnew, bool lock)
DATA_USERINFO(row, item);
if (lock)
K_WLOCK(userinfo_free);
if (isnew) {
if (isnew == INFO_NEW) {
row->blocks++;
copy_tv(&(row->last_block), &(blocks->createdate));
} else
} else if (isnew == INFO_ORPHAN)
row->orphans++;
else if (isnew == INFO_REJECT)
row->rejects++;
if (lock)
K_WUNLOCK(userinfo_free);
}

255
src/ckdb_dbio.c

@ -181,6 +181,7 @@ char *pqerrmsg(PGconn *conn)
#define PQPARAM17 PQPARAM16 ",$17"
#define PQPARAM18 PQPARAM16 ",$17,$18"
#define PQPARAM22 PQPARAM16 ",$17,$18,$19,$20,$21,$22"
#define PQPARAM23 PQPARAM16 ",$17,$18,$19,$20,$21,$22,$23"
#define PQPARAM26 PQPARAM22 ",$23,$24,$25,$26"
#define PQPARAM27 PQPARAM26 ",$27"
@ -415,7 +416,7 @@ bool users_update(PGconn *conn, K_ITEM *u_item, char *oldhash,
K_WUNLOCK(users_free);
DATA_USERS(row, item);
memcpy(row, users, sizeof(*row));
copy_users(row, users);
// Update each one supplied
if (hash) {
@ -428,11 +429,6 @@ bool users_update(PGconn *conn, K_ITEM *u_item, char *oldhash,
STRNCPY(row->emailaddress, email);
if (status)
STRNCPY(row->status, status);
if (row->userdata != EMPTY) {
row->userdata = strdup(users->userdata);
if (!row->userdata)
quithere(1, "strdup OOM");
}
HISTORYDATEINIT(row, cd, by, code, inet);
HISTORYDATETRANSFER(trf_root, row);
@ -514,8 +510,7 @@ unparam:
K_WLOCK(users_free);
if (!ok) {
if (row->userdata != EMPTY)
FREENULL(row->userdata);
free_users_data(item);
k_add_head(users_free, item);
} else {
users_root = remove_from_ktree(users_root, u_item, cmp_users);
@ -649,9 +644,10 @@ unparam:
free(params[n]);
unitem:
K_WLOCK(users_free);
if (!ok)
if (!ok) {
free_users_data(item);
k_add_head(users_free, item);
else {
} else {
users_root = add_to_ktree(users_root, item, cmp_users);
userid_root = add_to_ktree(userid_root, item, cmp_userid);
k_add_head(users_store, item);
@ -761,8 +757,7 @@ unparam:
K_WLOCK(users_free);
if (!ok) {
// cleanup done here
if (users->userdata != EMPTY)
FREENULL(users->userdata);
free_users_data(u_item);
k_add_head(users_free, u_item);
} else {
users_root = remove_from_ktree(users_root, old_u_item, cmp_users);
@ -892,8 +887,10 @@ bool users_fill(PGconn *conn)
userid_root = add_to_ktree(userid_root, item, cmp_userid);
k_add_head(users_store, item);
}
if (!ok)
if (!ok) {
free_users_data(item);
k_add_head(users_free, item);
}
K_WUNLOCK(users_free);
PQclear(res);
@ -1429,7 +1426,7 @@ bool workers_update(PGconn *conn, K_ITEM *item, char *difficultydefault,
WORKERS *row;
char *upd, *ins;
bool ok = false;
char *params[6 + HISTORYDATECOUNT];
char *params[7 + HISTORYDATECOUNT];
int n, par = 0;
int32_t diffdef;
char idlenot;
@ -2341,7 +2338,7 @@ K_ITEM *optioncontrol_item_add(PGconn *conn, K_ITEM *oc_item, tv_t *cd, bool beg
K_TREE_CTX ctx[1];
PGresult *res;
K_ITEM *old_item, look;
OPTIONCONTROL *row, *optioncontrol;
OPTIONCONTROL *row;
char *upd, *ins;
bool ok = false;
char *params[4 + HISTORYDATECOUNT];
@ -2444,16 +2441,15 @@ nostart:
K_WLOCK(optioncontrol_free);
if (!ok) {
// Cleanup item passed in
FREENULL(row->optionvalue);
free_optioncontrol_data(oc_item);
k_add_head(optioncontrol_free, oc_item);
} else {
// Discard old
if (old_item) {
DATA_OPTIONCONTROL(optioncontrol, old_item);
optioncontrol_root = remove_from_ktree(optioncontrol_root, old_item,
cmp_optioncontrol);
k_unlink_item(optioncontrol_store, old_item);
FREENULL(optioncontrol->optionvalue);
free_optioncontrol_data(old_item);
k_add_head(optioncontrol_free, old_item);
}
optioncontrol_root = add_to_ktree(optioncontrol_root, oc_item, cmp_optioncontrol);
@ -2600,7 +2596,7 @@ bool optioncontrol_fill(PGconn *conn)
}
}
if (!ok) {
FREENULL(row->optionvalue);
free_optioncontrol_data(item);
k_add_head(optioncontrol_free, item);
}
@ -2648,14 +2644,8 @@ int64_t workinfo_add(PGconn *conn, char *workinfoidstr, char *poolinstance,
TXT_TO_BIGINT("workinfoid", workinfoidstr, row->workinfoid);
STRNCPY(row->poolinstance, poolinstance);
row->transactiontree = strdup(transactiontree);
if (!(row->transactiontree))
quithere(1, "malloc (%d) OOM", (int)strlen(transactiontree));
LIST_MEM_ADD(workinfo_free, row->transactiontree);
row->merklehash = strdup(merklehash);
if (!(row->merklehash))
quithere(1, "malloc (%d) OOM", (int)strlen(merklehash));
LIST_MEM_ADD(workinfo_free, row->merklehash);
DUP_POINTER(workinfo_free, row->transactiontree, transactiontree);
DUP_POINTER(workinfo_free, row->merklehash, merklehash);
STRNCPY(row->prevhash, prevhash);
STRNCPY(row->coinbase1, coinbase1);
STRNCPY(row->coinbase2, coinbase2);
@ -2670,11 +2660,8 @@ int64_t workinfo_add(PGconn *conn, char *workinfoidstr, char *poolinstance,
K_WLOCK(workinfo_free);
if (find_in_ktree(workinfo_root, item, cmp_workinfo, ctx)) {
LIST_MEM_SUB(workinfo_free, row->transactiontree);
FREENULL(row->transactiontree);
LIST_MEM_SUB(workinfo_free, row->merklehash);
FREENULL(row->merklehash);
workinfoid = row->workinfoid;
free_workinfo_data(item);
k_add_head(workinfo_free, item);
K_WUNLOCK(workinfo_free);
@ -2735,19 +2722,12 @@ unparam:
K_WLOCK(workinfo_free);
if (workinfoid == -1) {
LIST_MEM_SUB(workinfo_free, row->transactiontree);
FREENULL(row->transactiontree);
LIST_MEM_SUB(workinfo_free, row->merklehash);
FREENULL(row->merklehash);
free_workinfo_data(item);
k_add_head(workinfo_free, item);
} else {
if (row->transactiontree && *(row->transactiontree)) {
// Not currently needed in RAM
LIST_MEM_SUB(workinfo_free, row->transactiontree);
free(row->transactiontree);
row->transactiontree = strdup(EMPTY);
LIST_MEM_ADD(workinfo_free, row->transactiontree);
}
// Not currently needed in RAM
LIST_MEM_SUB(workinfo_free, row->transactiontree);
FREENULL(row->transactiontree);
hex2bin(ndiffbin, row->bits, 4);
current_ndiff = diff_from_nbits(ndiffbin);
@ -2870,9 +2850,9 @@ bool workinfo_fill(PGconn *conn)
if (!ok)
break;
TXT_TO_BLOB("transactiontree", field, row->transactiontree);
*/
row->transactiontree = strdup(EMPTY);
LIST_MEM_ADD(workinfo_free, row->transactiontree);
*/
row->transactiontree = EMPTY;
PQ_GET_FLD(res, i, "merklehash", field, ok);
if (!ok)
@ -2940,8 +2920,7 @@ bool workinfo_fill(PGconn *conn)
tick();
}
if (!ok) {
//FREENULL(row->transactiontree);
FREENULL(row->merklehash);
free_workinfo_data(item);
k_add_head(workinfo_free, item);
}
@ -3690,9 +3669,11 @@ bool sharesummaries_to_markersummaries(PGconn *conn, WORKMARKERS *workmarkers,
bzero(markersummary, sizeof(*markersummary));
markersummary->markerid = workmarkers->markerid;
markersummary->userid = sharesummary->userid;
markersummary->workername = strdup(sharesummary->workername);
LIST_MEM_ADD(markersummary_free, markersummary->workername);
ms_root = add_to_ktree(ms_root, ms_item, cmp_markersummary);
DUP_POINTER(markersummary_free,
markersummary->workername,
sharesummary->workername);
ms_root = add_to_ktree(ms_root, ms_item,
cmp_markersummary);
LOGDEBUG("%s() new ms %"PRId64"/%"PRId64"/%s",
shortname, markersummary->markerid,
@ -3830,7 +3811,6 @@ flail:
bzero(p_markersummary, sizeof(*p_markersummary));
p_markersummary->markerid = markersummary->markerid;
POOL_MS(p_markersummary);
LIST_MEM_ADD(markersummary_free, p_markersummary->workername);
markersummary_pool_root = add_to_ktree(markersummary_pool_root,
p_ms_item,
cmp_markersummary);
@ -4075,8 +4055,8 @@ bool _sharesummary_update(SHARES *s_row, SHAREERRORS *e_row, K_ITEM *ss_item,
DATA_SHARESUMMARY(row, item);
bzero(row, sizeof(*row));
row->userid = userid;
row->workername = strdup(workername);
LIST_MEM_ADD(sharesummary_free, row->workername);
DUP_POINTER(sharesummary_free, row->workername,
workername);
row->workinfoid = workinfoid;
}
@ -4146,7 +4126,6 @@ bool _sharesummary_update(SHARES *s_row, SHAREERRORS *e_row, K_ITEM *ss_item,
DATA_SHARESUMMARY(p_row, p_item);
bzero(p_row, sizeof(*p_row));
POOL_SS(p_row);
LIST_MEM_ADD(sharesummary_free, p_row->workername);
p_row->workinfoid = workinfoid;
}
@ -4214,7 +4193,7 @@ bool blocks_stats(PGconn *conn, int32_t height, char *blockhash,
K_WUNLOCK(blocks_free);
DATA_BLOCKS(row, b_item);
memcpy(row, oldblocks, sizeof(*row));
copy_blocks(row, oldblocks);
row->diffacc = diffacc;
row->diffinv = diffinv;
row->shareacc = shareacc;
@ -4326,9 +4305,9 @@ unparam:
}
bool blocks_add(PGconn *conn, char *height, char *blockhash,
char *confirmed, char *workinfoid, char *username,
char *workername, char *clientid, char *enonce1,
char *nonce2, char *nonce, char *reward,
char *confirmed, char *info, char *workinfoid,
char *username, char *workername, char *clientid,
char *enonce1, char *nonce2, char *nonce, char *reward,
char *by, char *code, char *inet, tv_t *cd,
bool igndup, char *id, K_TREE *trf_root)
{
@ -4342,11 +4321,10 @@ bool blocks_add(PGconn *conn, char *height, char *blockhash,
BLOCKS *row, *oldblocks;
USERS *users;
char *upd, *ins;
char *params[17 + HISTORYDATECOUNT];
char *params[18 + HISTORYDATECOUNT];
bool ok = false, update_old = false;
int n, par = 0;
char want = '?';
char *st = NULL;
char *want = NULL, *st = NULL;
LOGDEBUG("%s(): add", __func__);
@ -4398,6 +4376,7 @@ bool blocks_add(PGconn *conn, char *height, char *blockhash,
}
STRNCPY(row->confirmed, confirmed);
STRNCPY(row->info, info);
TXT_TO_BIGINT("workinfoid", workinfoid, row->workinfoid);
STRNCPY(row->workername, workername);
TXT_TO_INT("clientid", clientid, row->clientid);
@ -4428,6 +4407,7 @@ bool blocks_add(PGconn *conn, char *height, char *blockhash,
params[par++] = str_to_buf(row->nonce, NULL, 0);
params[par++] = bigint_to_buf(row->reward, NULL, 0);
params[par++] = str_to_buf(row->confirmed, NULL, 0);
params[par++] = str_to_buf(row->info, NULL, 0);
params[par++] = double_to_buf(row->diffacc, NULL, 0);
params[par++] = double_to_buf(row->diffinv, NULL, 0);
params[par++] = double_to_buf(row->shareacc, NULL, 0);
@ -4440,9 +4420,9 @@ bool blocks_add(PGconn *conn, char *height, char *blockhash,
ins = "insert into blocks "
"(height,blockhash,workinfoid,userid,workername,"
"clientid,enonce1,nonce2,nonce,reward,confirmed,"
"diffacc,diffinv,shareacc,shareinv,elapsed,"
"info,diffacc,diffinv,shareacc,shareinv,elapsed,"
"statsconfirmed"
HISTORYDATECONTROL ") values (" PQPARAM22 ")";
HISTORYDATECONTROL ") values (" PQPARAM23 ")";
if (conn == NULL) {
conn = dbconnect();
@ -4458,10 +4438,11 @@ bool blocks_add(PGconn *conn, char *height, char *blockhash,
}
// We didn't use a Begin
ok = true;
userinfo_block(row, true);
userinfo_block(row, INFO_NEW);
goto unparam;
break;
case BLOCKS_ORPHAN:
case BLOCKS_REJECT:
case BLOCKS_42:
// These shouldn't be possible until startup completes
if (!startup_complete) {
@ -4473,7 +4454,6 @@ bool blocks_add(PGconn *conn, char *height, char *blockhash,
height, hash_dsp, cd_buf);
goto flail;
}
want = BLOCKS_CONFIRM;
case BLOCKS_CONFIRM:
if (!old_b_item) {
tv_to_buf(cd, cd_buf, sizeof(cd_buf));
@ -4482,16 +4462,37 @@ bool blocks_add(PGconn *conn, char *height, char *blockhash,
height, hash_dsp, cd_buf);
goto flail;
}
if (confirmed[0] == BLOCKS_CONFIRM)
want = BLOCKS_NEW;
if (oldblocks->confirmed[0] != want) {
switch (confirmed[0]) {
case BLOCKS_CONFIRM:
if (oldblocks->confirmed[0] != BLOCKS_NEW)
want = BLOCKS_NEW_STR;
break;
case BLOCKS_42:
if (oldblocks->confirmed[0] != BLOCKS_CONFIRM)
want = BLOCKS_CONFIRM_STR;
break;
case BLOCKS_ORPHAN:
if (oldblocks->confirmed[0] != BLOCKS_NEW &&
oldblocks->confirmed[0] != BLOCKS_CONFIRM)
want = BLOCKS_N_C_STR;
break;
case BLOCKS_REJECT:
if (oldblocks->confirmed[0] != BLOCKS_NEW &&
oldblocks->confirmed[0] != BLOCKS_CONFIRM &&
oldblocks->confirmed[0] != BLOCKS_ORPHAN &&
oldblocks->confirmed[0] != BLOCKS_REJECT)
want = BLOCKS_N_C_O_R_STR;
break;
}
if (want) {
// No mismatch messages during startup
if (startup_complete) {
tv_to_buf(cd, cd_buf, sizeof(cd_buf));
LOGERR("%s(): New Status: %s requires Status: %c. "
"Ignored: Status: %s, Block: %s/...%s/%s",
LOGERR("%s(): New Status: (%s)%s requires Status: %s. "
"Ignored: Status: (%s)%s, Block: %s/...%s/%s",
__func__,
blocks_confirmed(confirmed), want,
confirmed, blocks_confirmed(confirmed),
want, oldblocks->confirmed,
blocks_confirmed(oldblocks->confirmed),
height, hash_dsp, cd_buf);
}
@ -4511,8 +4512,10 @@ bool blocks_add(PGconn *conn, char *height, char *blockhash,
}
// New is mostly a copy of the old
memcpy(row, oldblocks, sizeof(*row));
copy_blocks(row, oldblocks);
STRNCPY(row->confirmed, confirmed);
if (info && *info)
STRNCPY(row->info, info);
if (confirmed[0] == BLOCKS_CONFIRM) {
row->diffacc = pool.diffacc;
row->diffinv = pool.diffinv;
@ -4546,6 +4549,7 @@ bool blocks_add(PGconn *conn, char *height, char *blockhash,
params[par++] = str_to_buf(row->blockhash, NULL, 0);
params[par++] = tv_to_buf(cd, NULL, 0);
params[par++] = str_to_buf(row->confirmed, NULL, 0);
params[par++] = str_to_buf(row->info, NULL, 0);
if (confirmed[0] == BLOCKS_CONFIRM) {
params[par++] = double_to_buf(row->diffacc, NULL, 0);
@ -4553,34 +4557,34 @@ bool blocks_add(PGconn *conn, char *height, char *blockhash,
params[par++] = double_to_buf(row->shareacc, NULL, 0);
params[par++] = double_to_buf(row->shareinv, NULL, 0);
HISTORYDATEPARAMS(params, par, row);
PARCHKVAL(par, 7 + HISTORYDATECOUNT, params); // 12 as per ins
PARCHKVAL(par, 8 + HISTORYDATECOUNT, params); // 13 as per ins
ins = "insert into blocks "
"(height,blockhash,workinfoid,userid,workername,"
"clientid,enonce1,nonce2,nonce,reward,confirmed,"
"diffacc,diffinv,shareacc,shareinv,elapsed,"
"info,diffacc,diffinv,shareacc,shareinv,elapsed,"
"statsconfirmed"
HISTORYDATECONTROL ") select "
"height,blockhash,workinfoid,userid,workername,"
"clientid,enonce1,nonce2,nonce,reward,"
"$3,$4,$5,$6,$7,elapsed,statsconfirmed,"
"$8,$9,$10,$11,$12 from blocks where "
"$3,$4,$5,$6,$7,$8,elapsed,statsconfirmed,"
"$9,$10,$11,$12,$13 from blocks where "
"blockhash=$1 and "EDDB"=$2";
} else {
HISTORYDATEPARAMS(params, par, row);
PARCHKVAL(par, 3 + HISTORYDATECOUNT, params); // 8 as per ins
PARCHKVAL(par, 4 + HISTORYDATECOUNT, params); // 9 as per ins
ins = "insert into blocks "
"(height,blockhash,workinfoid,userid,workername,"
"clientid,enonce1,nonce2,nonce,reward,confirmed,"
"diffacc,diffinv,shareacc,shareinv,elapsed,"
"info,diffacc,diffinv,shareacc,shareinv,elapsed,"
"statsconfirmed"
HISTORYDATECONTROL ") select "
"height,blockhash,workinfoid,userid,workername,"
"clientid,enonce1,nonce2,nonce,reward,"
"$3,diffacc,diffinv,shareacc,shareinv,elapsed,"
"$3,$4,diffacc,diffinv,shareacc,shareinv,elapsed,"
"statsconfirmed,"
"$4,$5,$6,$7,$8 from blocks where "
"$5,$6,$7,$8,$9 from blocks where "
"blockhash=$1 and "EDDB"=$2";
}
@ -4594,7 +4598,9 @@ bool blocks_add(PGconn *conn, char *height, char *blockhash,
update_old = true;
if (confirmed[0] == BLOCKS_ORPHAN)
userinfo_block(row, false);
userinfo_block(row, INFO_ORPHAN);
else if (confirmed[0] == BLOCKS_REJECT)
userinfo_block(row, INFO_REJECT);
break;
default:
LOGERR("%s(): %s.failed.invalid confirm='%s'",
@ -4684,6 +4690,7 @@ flail:
}
break;
case BLOCKS_ORPHAN:
case BLOCKS_REJECT:
case BLOCKS_42:
default:
blk = false;
@ -4709,14 +4716,14 @@ bool blocks_fill(PGconn *conn)
BLOCKS *row;
char *field;
char *sel;
int fields = 17;
int fields = 18;
bool ok;
LOGDEBUG("%s(): select", __func__);
sel = "select "
"height,blockhash,workinfoid,userid,workername,"
"clientid,enonce1,nonce2,nonce,reward,confirmed,"
"clientid,enonce1,nonce2,nonce,reward,confirmed,info,"
"diffacc,diffinv,shareacc,shareinv,elapsed,statsconfirmed"
HISTORYDATECONTROL
" from blocks";
@ -4805,6 +4812,11 @@ bool blocks_fill(PGconn *conn)
break;
TXT_TO_STR("confirmed", field, row->confirmed);
PQ_GET_FLD(res, i, "info", field, ok);
if (!ok)
break;
TXT_TO_STR("info", field, row->info);
PQ_GET_FLD(res, i, "diffacc", field, ok);
if (!ok)
break;
@ -4851,9 +4863,11 @@ bool blocks_fill(PGconn *conn)
}
if (CURRENT(&(row->expirydate))) {
_userinfo_block(row, true, false);
_userinfo_block(row, INFO_NEW, false);
if (row->confirmed[0] == BLOCKS_ORPHAN)
_userinfo_block(row, false, false);
_userinfo_block(row, INFO_ORPHAN, false);
else if (row->confirmed[0] == BLOCKS_REJECT)
_userinfo_block(row, INFO_REJECT, false);
}
}
if (!ok)
@ -5097,6 +5111,7 @@ void payouts_add_ram(bool ok, K_ITEM *p_item, K_ITEM *old_p_item, tv_t *cd)
K_WLOCK(payouts_free);
if (!ok) {
// Cleanup for the calling function
free_payouts_data(p_item);
k_add_head(payouts_free, p_item);
} else {
if (old_p_item) {
@ -5601,7 +5616,7 @@ bool payouts_fill(PGconn *conn)
tick();
}
if (!ok) {
FREENULL(row->stats);
free_payouts_data(item);
k_add_head(payouts_free, item);
}
@ -6425,7 +6440,6 @@ bool markersummary_fill(PGconn *conn)
bzero(p_row, sizeof(*p_row));
p_row->markerid = row->markerid;
POOL_MS(p_row);
LIST_MEM_ADD(markersummary_free, p_row->workername);
markersummary_pool_root = add_to_ktree(markersummary_pool_root,
p_item,
cmp_markersummary);
@ -6448,7 +6462,7 @@ bool markersummary_fill(PGconn *conn)
tick();
}
if (!ok) {
FREENULL(row->workername);
free_markersummary_data(item);
k_add_head(markersummary_free, item);
}
@ -6605,12 +6619,10 @@ bool _workmarkers_process(PGconn *conn, bool already, bool add,
}
}
row->poolinstance = strdup(poolinstance);
LIST_MEM_ADD(workmarkers_free, poolinstance);
DUP_POINTER(workmarkers_free, row->poolinstance, poolinstance);
row->workinfoidend = workinfoidend;
row->workinfoidstart = workinfoidstart;
row->description = strdup(description);
LIST_MEM_ADD(workmarkers_free, description);
DUP_POINTER(workmarkers_free, row->description, description);
STRNCPY(row->status, status);
HISTORYDATEINIT(row, cd, by, code, inet);
HISTORYDATETRANSFER(trf_root, row);
@ -6658,23 +6670,7 @@ unparam:
K_WLOCK(workmarkers_free);
if (!ok) {
if (wm_item) {
DATA_WORKMARKERS(row, wm_item);
if (row->poolinstance) {
if (row->poolinstance != EMPTY) {
LIST_MEM_SUB(workmarkers_free,
row->poolinstance);
free(row->poolinstance);
}
row->poolinstance = NULL;
}
if (row->description) {
if (row->description != EMPTY) {
LIST_MEM_SUB(workmarkers_free,
row->description);
free(row->description);
}
row->description = NULL;
}
free_workmarkers_data(wm_item);
k_add_head(workmarkers_free, wm_item);
}
}
@ -6820,8 +6816,10 @@ bool workmarkers_fill(PGconn *conn)
tick();
}
if (!ok)
if (!ok) {
free_workmarkers_data(item);
k_add_head(workmarkers_free, item);
}
K_WUNLOCK(workmarkers_free);
PQclear(res);
@ -6920,13 +6918,10 @@ bool _marks_process(PGconn *conn, bool add, char *poolinstance,
K_WUNLOCK(marks_free);
DATA_MARKS(row, m_item);
bzero(row, sizeof(*row));
row->poolinstance = strdup(poolinstance);
LIST_MEM_ADD(marks_free, poolinstance);
DUP_POINTER(marks_free, row->poolinstance, poolinstance);
row->workinfoid = workinfoid;
row->description = strdup(description);
LIST_MEM_ADD(marks_free, description);
row->extra = strdup(extra);
LIST_MEM_ADD(marks_free, extra);
DUP_POINTER(marks_free, row->description, description);
DUP_POINTER(marks_free, row->extra, extra);
STRNCPY(row->marktype, marktype);
STRNCPY(row->status, status);
HISTORYDATEINIT(row, cd, by, code, inet);
@ -6991,32 +6986,10 @@ unparam:
K_WLOCK(marks_free);
if (!ok) {
if (m_item) {
DATA_MARKS(row, m_item);
if (row->poolinstance) {
if (row->poolinstance != EMPTY) {
LIST_MEM_SUB(marks_free, row->poolinstance);
free(row->poolinstance);
}
row->poolinstance = NULL;
}
if (row->description) {
if (row->description != EMPTY) {
LIST_MEM_SUB(marks_free, row->description);
free(row->description);
}
row->description = NULL;
}
if (row->extra) {
if (row->extra != EMPTY) {
LIST_MEM_SUB(marks_free, row->extra);
free(row->extra);
}
row->extra = NULL;
}
free_marks_data(m_item);
k_add_head(marks_free, m_item);
}
}
else {
} else {
if (old_m_item) {
marks_root = remove_from_ktree(marks_root, old_m_item, cmp_marks);
copy_tv(&(oldmarks->expirydate), cd);
@ -7123,8 +7096,10 @@ bool marks_fill(PGconn *conn)
tick();
}
if (!ok)
if (!ok) {
free_marks_data(item);
k_add_head(marks_free, item);
}
K_WUNLOCK(marks_free);
PQclear(res);

Loading…
Cancel
Save