You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2133 lines
91 KiB

9 years ago
/******************************************************************************
* Copyright © 2014-2015 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#ifdef later
#define BUNDLED
#define PLUGINSTR "pangea"
#define PLUGNAME(NAME) pangea ## NAME
#define STRUCTNAME struct PLUGNAME(_info)
#define STRINGIFY(NAME) #NAME
#define PLUGIN_EXTRASIZE sizeof(STRUCTNAME)
#include <time.h>
#define DEFINES_ONLY
//#include "../../utils/huffstream.c"
#include "../../common/hostnet777.c"
#include "../../includes/cJSON.h"
#include "../../agents/plugin777.c"
#undef DEFINES_ONLY
#include "../InstantDEX/InstantDEX_quote.h"
#include "../includes/curve25519.h"
#define _PANGEA_MAXTHREADS 9
#define PANGEA_MINRAKE_MILLIS 5
#define PANGEA_USERTIMEOUT 60
#define PANGEA_MAX_HOSTRAKE 5
#define PANGEA_BTCMAXRAKE (SATOSHIDEN / 100)
#define PANGEA_MAXRAKE (3 * SATOSHIDEN)
#define PANGEA_HANDGAP 30
#define PANGEA_PAUSE 5
struct pangea_info
{
uint32_t timestamp,numaddrs,minbuyin,maxbuyin;
int64_t balances[CARDS777_MAXPLAYERS]; uint8_t isbot[CARDS777_MAXPLAYERS]; bits256 playerpubs[CARDS777_MAXPLAYERS];
uint64_t basebits,bigblind,ante,addrs[CARDS777_MAXPLAYERS],active[CARDS777_MAXPLAYERS],tableid;
char btcpubkeystr[67],wipstr[64],coinstr[16],multisigaddr[64],scriptPubKey[128],redeemScript[4096];
uint8_t addrtype,p2shtype,wiftype,btcpub[33];
int32_t myslot,myind,numactive,buyinvouts[CARDS777_MAXPLAYERS]; uint64_t buyinamounts[CARDS777_MAXPLAYERS];
char buyintxids[CARDS777_MAXPLAYERS][128],coinaddrs[CARDS777_MAXPLAYERS][67],btcpubkeys[CARDS777_MAXPLAYERS][67];
struct pangea_thread *tp; struct cards777_privdata *priv; struct cards777_pubdata *dp;
} *TABLES[100];
//./BitcoinDarkd SuperNET '{"agent":"InstantDEX","method":"orderbook","exchange":"active","base":"NXT","rel":"BTC"}'
// ./SNapi "{\"agent\":\"InstantDEX\",\"method\":\"orderbook\",\"exchange\":\"pangea\",\"base\":\"NXT\"}"
// ./SNapi "{\"agent\":\"InstantDEX\",\"method\":\"placebid\",\"exchange\":\"pangea\",\"base\":\"NXT\"}"
struct pangea_thread
{
union hostnet777 hn; uint64_t nxt64bits; int32_t threadid,ishost,M,N,numcards;
} *THREADS[_PANGEA_MAXTHREADS];
int32_t PANGEA_MAXTHREADS = 0;
int32_t Showmode,Autofold;
//uint64_t Pangea_waiting,Pangea_userinput_betsize; uint32_t Pangea_userinput_starttime; int32_t Pangea_userinput_cardi; char Pangea_userinput[128];
char *clonestr(char *);
uint64_t stringbits(char *str);
uint32_t set_handstr(char *handstr,uint8_t cards[7],int32_t verbose);
int32_t cardstr(char *cardstr,uint8_t card);
int32_t init_hexbytes_noT(char *hexbytes,uint8_t *message,long len);
bits256 issue_getpubkey(int32_t *haspubkeyp,char *acct);
uint64_t set_account_NXTSECRET(void *myprivkey,void *mypubkey,char *NXTacct,char *NXTaddr,char *secret,int32_t max,cJSON *argjson,char *coinstr,char *serverport,char *userpass);
int32_t pangea_anotherhand(union hostnet777 *hn,struct cards777_pubdata *dp,int32_t sleepflag);
void pangea_clearhand(struct cards777_pubdata *dp,struct cards777_handinfo *hand,struct cards777_privdata *priv);
void pangea_create_newtable(char *retbuf,struct pangea_info *sp,struct cards777_pubdata *dp,uint64_t *isbot);
#define PANGEA_COMMANDS "start", "newtable", "status", "turn"
char *PLUGNAME(_methods)[] = { PANGEA_COMMANDS };
char *PLUGNAME(_pubmethods)[] = { PANGEA_COMMANDS };
char *PLUGNAME(_authmethods)[] = { PANGEA_COMMANDS };
uint64_t PLUGNAME(_register)(struct plugin_info *plugin,STRUCTNAME *data,cJSON *argjson)
{
uint64_t disableflags = 0;
return(disableflags); // set bits corresponding to array position in _methods[]
}
int32_t PLUGNAME(_shutdown)(struct plugin_info *plugin,int32_t retcode)
{
if ( retcode == 0 ) // this means parent process died, otherwise _process_json returned negative value
{
}
return(retcode);
}
int32_t pangea_search(struct pangea_info *sp,uint64_t nxt64bits)
{
int32_t i;
for (i=0; i<sp->numactive; i++)
if ( sp->active[i] == nxt64bits )
return(i);
for (i=0; i<sp->numactive; i++)
PostMessage("%llu ",(long long)sp->active[i]);
PostMessage("active[]\n");
for (i=0; i<sp->numaddrs; i++)
PostMessage("%llu ",(long long)sp->addrs[i]);
PostMessage("addrs[]\n");
PostMessage("pangea_search: slot.%d ind.%d cant find %llu in active[%d]\n",sp->myslot,sp->myind,(long long)nxt64bits,sp->numactive);
return(-1);
}
int32_t pangea_tableaddr(struct cards777_pubdata *dp,uint64_t destbits)
{
int32_t i; struct pangea_info *sp;
if ( dp != 0 && (sp= dp->table) != 0 )
{
for (i=0; i<sp->numaddrs; i++)
if ( sp->addrs[i] == destbits )
return(i);
}
return(-1);
}
int32_t pangea_slotA(struct pangea_info *sp)
{
return(0);
}
int32_t pangea_slotB(struct pangea_info *sp)
{
uint64_t nxt64bits;
nxt64bits = sp->active[1];
return(pangea_search(sp,nxt64bits));
}
int32_t pangea_slot(struct pangea_info *sp,int32_t ind)
{
return(pangea_tableaddr(sp->dp,sp->active[ind]));
}
int32_t pangea_ind(struct pangea_info *sp,int32_t slot)
{
return(pangea_search(sp,sp->addrs[slot]));
}
int32_t pangea_lastnode(struct pangea_info *sp)
{
return(pangea_search(sp,sp->active[sp->numactive-1]));
}
int32_t pangea_nextnode(struct pangea_info *sp)
{
if ( sp->myind < sp->numactive-1 )
return(sp->myind + 1);
else
{
PostMessage("pangea_nextnode: no next node from last node slot.%d ind.%d of numaddrs.%d numactive.%d\n",sp->myslot,sp->myind,sp->numaddrs,sp->numactive);
return(-1);
}
}
int32_t pangea_prevnode(struct pangea_info *sp)
{
if ( sp->myind > 0 )
return(sp->myind - 1);
else
{
PostMessage("pangea_prevnode: no prev node from node slot %d, ind.%d\n",sp->myslot,sp->myind);
return(-1);
}
}
int32_t pangea_neworder(struct cards777_pubdata *dp,struct pangea_info *sp,uint64_t *active,int32_t numactive)
{
int32_t slots[CARDS777_MAXPLAYERS],i;
if ( active == 0 )
active = sp->active, numactive = sp->numactive;
memset(slots,0,sizeof(slots));
if ( active[0] != sp->addrs[0] )
{
PostMessage("pangea_neworder: neworder requires host nodeA to be first active node\n");
return(-1);
}
slots[0] = 0;
for (i=1; i<numactive; i++)
{
if ( (slots[i]= pangea_tableaddr(dp,active[i])) < 0 )
{
PostMessage("cant find %llu in addrs[%d]\n",(long long)active[i],sp->numaddrs);
return(-1);
}
}
for (i=0; i<numactive; i++)
{
sp->active[i] = active[i];
//PostMessage("%llu ",(long long)sp->active[i]);
}
sp->numactive = dp->N = numactive;
dp->M = (numactive >> 1) + 1;
sp->myind = pangea_ind(sp,sp->myslot);
//PostMessage("T%d neworder.%d -> M.%d N.%d ind.%d\n",sp->myslot,sp->numactive,dp->M,dp->N,sp->myind);
return(numactive);
}
int32_t pangea_inactivate(struct cards777_pubdata *dp,struct pangea_info *sp,uint64_t nxt64bits)
{
int32_t i,n; uint64_t active[CARDS777_MAXPLAYERS];
for (i=n=0; i<sp->numactive; i++)
{
if ( sp->active[i] == nxt64bits )
continue;
active[n++] = sp->active[i];
}
if ( n != sp->numactive-1 )
PostMessage("pangea_inactivate: cant find %llu\n",(long long)nxt64bits);
PostMessage("T%d inactivate %llu n.%d\n",sp->myslot,(long long)nxt64bits,n);
pangea_neworder(dp,sp,active,n);
return(n);
}
int32_t pangea_addplayer(struct cards777_pubdata *dp,struct pangea_info *sp,bits256 clientpub)
{
int32_t i,n,openslot = -1; uint64_t nxt64bits = acct777_nxt64bits(clientpub);
for (i=n=0; i<sp->numaddrs; i++)
{
if ( sp->addrs[i] == nxt64bits )
{
PostMessage("pangea_addplayer: player %llu already in addrs[%d]\n",(long long)nxt64bits,i);
return(-1);
}
if ( sp->balances[i] <= 0 )
openslot = i;
}
if ( openslot < 0 || sp->numactive >= sp->numaddrs-1 )
{
PostMessage("pangea_addplayer: no room to add %llu\n",(long long)nxt64bits);
return(-1);
}
dp->readymask &= ~(1 << openslot);
sp->addrs[openslot] = nxt64bits;
sp->playerpubs[openslot] = clientpub;
sp->active[sp->numactive++] = nxt64bits;
if ( sp->myslot == 0 )
{
uint64_t isbot[CARDS777_MAXPLAYERS]; char *retbuf = malloc(65536);
if ( retbuf != 0 )
{
hostnet777_replace(sp->tp->hn.server,clientpub,openslot);
for (i=0; i<sp->numactive; i++)
isbot[i] = sp->isbot[i];
pangea_create_newtable(retbuf,sp,dp,isbot);
hostnet777_msg(nxt64bits,clientpub,&sp->tp->hn,0,retbuf,(int32_t)strlen(retbuf)+1);
free(retbuf);
}
}
pangea_neworder(dp,sp,0,0);
return(n);
}
void pangea_sendcmd(char *hex,union hostnet777 *hn,char *cmdstr,int32_t destplayer,uint8_t *data,int32_t datalen,int32_t cardi,int32_t turni)
{
int32_t n,hexlen,blindflag = 0; uint64_t destbits; bits256 destpub; cJSON *json; char hoststr[1024]; struct pangea_info *sp;
struct cards777_pubdata *dp = hn->client->H.pubdata;
hoststr[0] = 0;
sp = dp->table;
sprintf(hex,"{\"cmd\":\"%s\",\"millitime\":\"%lld\",\"turni\":%d,\"myslot\":%d,\"myind\":%d,\"cardi\":%d,\"dest\":%d,\"sender\":\"%llu\",\"timestamp\":\"%lu\",\"n\":%u,%s\"data\":\"",cmdstr,(long long)hostnet777_convmT(&hn->client->H.mT,0),turni,hn->client->H.slot,pangea_ind(dp->table,hn->client->H.slot),cardi,destplayer,(long long)hn->client->H.nxt64bits,(long)time(NULL),datalen,hoststr);
n = (int32_t)strlen(hex);
if ( strcmp(cmdstr,"preflop") == 0 )
{
memcpy(&hex[n],data,datalen+1);
hexlen = (int32_t)strlen(hex)+1;
PostMessage("P%d HEX.[] hexlen.%d n.%d\n",hn->server->H.slot,hexlen,datalen);
}
else if ( data != 0 && datalen != 0 )
init_hexbytes_noT(&hex[n],data,datalen);
strcat(hex,"\"}");
if ( (json= cJSON_Parse(hex)) == 0 )
{
PostMessage("error creating json\n");
return;
}
free_json(json);
hexlen = (int32_t)strlen(hex)+1;
//PostMessage("HEX.[%s] hexlen.%d n.%d\n",hex,hexlen,datalen);
if ( destplayer < 0 )//|| ((1LL << destplayer) & dp->pmworks) == 0 )
{
destbits = 0;
memset(destpub.bytes,0,sizeof(destpub));
//PostMessage("T%d broadcasts %d\n",hn->client->H.slot,hexlen);
}
else
{
destpub = sp->playerpubs[pangea_slot(sp,destplayer)];
destbits = acct777_nxt64bits(destpub);
//PostMessage("T%d sends %d to dest.%d\n",hn->client->H.slot,hexlen,destplayer);
}
hostnet777_msg(destbits,destpub,hn,blindflag,hex,hexlen);
}
#include "pangeafunds.c"
bits256 pangea_destpub(uint64_t destbits)
{
int32_t i,haspubkey; bits256 destpub; char destNXT[64];
memset(destpub.bytes,0,sizeof(destpub));
for (i=0; i<sizeof(TABLES)/sizeof(*TABLES); i++)
if ( TABLES[i] != 0 && TABLES[i]->tp->nxt64bits == destbits )
{
destpub = TABLES[i]->tp->hn.client->H.pubkey;
break;
}
if ( i == sizeof(TABLES)/sizeof(*TABLES) )
{
expand_nxt64bits(destNXT,destbits);
destpub = issue_getpubkey(&haspubkey,destNXT);
}
return(destpub);
}
struct pangea_info *pangea_find(uint64_t tableid,int32_t threadid)
{
int32_t i;
for (i=0; i<sizeof(TABLES)/sizeof(*TABLES); i++)
if ( TABLES[i] != 0 && tableid == TABLES[i]->tableid && (threadid < 0 || TABLES[i]->tp->threadid == threadid) )
return(TABLES[i]);
return(0);
}
struct pangea_info *pangea_find64(uint64_t tableid,uint64_t nxt64bits)
{
int32_t i,j;
for (i=0; i<sizeof(TABLES)/sizeof(*TABLES); i++)
{
if ( TABLES[i] != 0 && (tableid == 0 || tableid == TABLES[i]->tableid) && TABLES[i]->tp != 0 )
{
for (j=0; j<TABLES[i]->numaddrs; j++)
{
if ( TABLES[i]->addrs[j] == nxt64bits )
return(TABLES[i]);
}
}
}
return(0);
}
void pangea_free(struct pangea_info *sp)
{
int32_t i;
for (i=0; i<sizeof(TABLES)/sizeof(*TABLES); i++)
if ( TABLES[i] == sp )
{
TABLES[i] = 0;
break;
}
PostMessage("PANGEA PURGE %llu\n",(long long)sp->tableid);
free(sp);
}
void pangea_clearhand(struct cards777_pubdata *dp,struct cards777_handinfo *hand,struct cards777_privdata *priv)
{
bits256 *final,*cardpubs; int32_t i;
final = hand->final, cardpubs = hand->cardpubs;
memset(hand,0,sizeof(*hand));
hand->final = final, hand->cardpubs = cardpubs;
memset(final,0,sizeof(*final) * dp->N * dp->numcards);
memset(cardpubs,0,sizeof(*cardpubs) * (1 + dp->numcards));
for (i=0; i<5; i++)
hand->community[i] = 0xff;
memset(hand->hands,0xff,sizeof(hand->hands));
priv->hole[0] = priv->hole[1] = priv->cardis[0] = priv->cardis[1] = 0xff;
memset(priv->holecards,0,sizeof(priv->holecards));
}
void pangea_sendnewdeck(union hostnet777 *hn,struct cards777_pubdata *dp)
{
int32_t hexlen; bits256 destpub;
hexlen = (int32_t)strlen(dp->newhand)+1;
memset(destpub.bytes,0,sizeof(destpub));
hostnet777_msg(0,destpub,hn,0,dp->newhand,hexlen);
dp->hand.startdecktime = (uint32_t)time(NULL);
PostMessage("pangea_sendnewdeck new deck at %u\n",dp->hand.startdecktime);
}
int32_t pangea_newdeck(union hostnet777 *src)
{
uint8_t data[(CARDS777_MAXCARDS + 1) * sizeof(bits256)]; struct cards777_pubdata *dp; struct cards777_privdata *priv; int32_t i,n,m,len;
bits256 playerpubs[CARDS777_MAXPLAYERS]; struct pangea_info *sp; uint64_t removelist[CARDS777_MAXPLAYERS]; cJSON *array; char *str;
dp = src->client->H.pubdata, sp = dp->table;
priv = src->client->H.privdata;
pangea_clearhand(dp,&dp->hand,priv);
for (i=m=0; i<dp->N; i++)
{
if ( sp->balances[pangea_slot(sp,i)] <= 0 )
removelist[m++] = sp->addrs[pangea_slot(sp,i)];
}
if ( 0 && m > 0 )
{
for (i=0; i<m; i++)
pangea_inactivate(dp,sp,removelist[i]);
}
pangea_neworder(dp,dp->table,0,0);
array = cJSON_CreateArray();
for (i=0; i<dp->N; i++)
{
playerpubs[i] = sp->playerpubs[pangea_slot(sp,i)];
jaddi64bits(array,sp->active[i]);
}
str = jprint(array,1);
dp->hand.checkprod = dp->hand.cardpubs[dp->numcards] = cards777_initdeck(priv->outcards,dp->hand.cardpubs,dp->numcards,dp->N,playerpubs,0);
len = (dp->numcards + 1) * sizeof(bits256);
sprintf(dp->newhand,"{\"cmd\":\"%s\",\"millitime\":\"%lld\",\"active\":%s,\"sender\":\"%llu\",\"timestamp\":\"%lu\",\"n\":%u,\"data\":\"","newhand",(long long)hostnet777_convmT(&src->server->H.mT,0),str,(long long)src->client->H.nxt64bits,(long)time(NULL),len);
free(str);
n = (int32_t)strlen(dp->newhand);
memcpy(data,dp->hand.cardpubs,len);
init_hexbytes_noT(&dp->newhand[n],data,len);
strcat(dp->newhand,"\"}");
pangea_sendnewdeck(src,dp);
PostMessage("host sends NEWDECK checkprod.%llx numhands.%d\n",(long long)dp->hand.checkprod.txid,dp->numhands);
return(0);
}
int32_t pangea_anotherhand(union hostnet777 *hn,struct cards777_pubdata *dp,int32_t sleepflag)
{
int32_t i,n,activej = -1; uint64_t total = 0; struct pangea_info *sp = dp->table;
for (i=n=0; i<sp->numaddrs; i++)
{
total += sp->balances[i];
PostMessage("(p%d %.8f) ",i,dstr(sp->balances[i]));
if ( sp->balances[i] != 0 )
{
if ( activej < 0 )
activej = i;
n++;
}
}
PostMessage("balances %.8f [%.8f]\n",dstr(total),dstr(total + dp->hostrake + dp->pangearake));
if ( n == 1 )
{
PostMessage("Only player.%d left with %.8f | get sigs and cashout after numhands.%d\n",activej,dstr(sp->balances[pangea_slot(sp,activej)]),dp->numhands);
msleep(60000);
return(1);
}
else
{
if ( sleepflag != 0 )
msleep(sleepflag * 1000);
//dp->hand.betstarted = 0;
pangea_newdeck(hn);
if ( sleepflag != 0 )
msleep(sleepflag * 1000);
}
return(n);
}
int32_t pangea_newhand(union hostnet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t senderind)
{
char hex[1024]; int32_t handid,m,i; uint64_t active[CARDS777_MAXPLAYERS]; cJSON *array; struct pangea_info *sp = dp->table;
if ( data == 0 || datalen != (dp->numcards + 1) * sizeof(bits256) )
{
PostMessage("pangea_newhand invalid datalen.%d vs %ld\n",datalen,(long)((dp->numcards + 1) * sizeof(bits256)));
return(-1);
}
if ( hn->server->H.slot != 0 )
{
pangea_clearhand(dp,&dp->hand,priv);
if ( (array= jarray(&m,json,"active")) != 0 )
{
//PostMessage("T%d (%s)\n",sp->myslot,jprint(array,0));
for (i=0; i<m; i++)
active[i] = j64bits(jitem(array,i),0);
pangea_neworder(dp,dp->table,active,m);
} else pangea_neworder(dp,dp->table,0,0);
}
dp->button = (dp->numhands++ % dp->N);
memcpy(dp->hand.cardpubs,data,(dp->numcards + 1) * sizeof(bits256));
PostMessage("player.%d NEWHAND.%llx received numhands.%d button.%d cardi.%d | dp->N %d\n",hn->client->H.slot,(long long)dp->hand.cardpubs[dp->numcards].txid,dp->numhands,dp->button,dp->hand.cardi,dp->N);
dp->hand.checkprod = cards777_pubkeys(dp->hand.cardpubs,dp->numcards,dp->hand.cardpubs[dp->numcards]);
memset(dp->summary,0,sizeof(dp->summary));
dp->summaries = dp->mismatches = dp->summarysize = 0;
handid = dp->numhands - 1;
if ( sp->myind >= 0 )
{
pangea_summary(hn,dp,CARDS777_START,&handid,sizeof(handid),dp->hand.cardpubs[0].bytes,sizeof(bits256)*(dp->numcards+1));
pangea_sendcmd(hex,hn,"gotdeck",-1,dp->hand.checkprod.bytes,sizeof(uint64_t),dp->hand.cardi,dp->hand.userinput_starttime);
}
return(0);
}
void pangea_checkstart(union hostnet777 *hn,struct cards777_pubdata *dp,struct cards777_privdata *priv)
{
int32_t i;
if ( dp->hand.checkprod.txid != 0 && dp->newhand[0] != 0 && dp->hand.encodestarted == 0 )
{
for (i=0; i<dp->N; i++)
{
if ( dp->hand.othercardpubs[i] != dp->hand.checkprod.txid )
break;
}
if ( i == dp->N )
{
if ( PANGEA_PAUSE > 0 )
msleep(PANGEA_PAUSE * 1000);
dp->hand.encodestarted = (uint32_t)time(NULL);
PostMessage("SERVERSTATE issues encoded %llx\n",(long long)dp->hand.checkprod.txid);
pangea_sendcmd(dp->newhand,hn,"encoded",pangea_slotB(dp->table),priv->outcards[0].bytes,sizeof(bits256)*dp->N*dp->numcards,dp->N*dp->numcards,-1);
}
}
}
int32_t pangea_gotdeck(union hostnet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t senderind)
{
int32_t i,slot; uint64_t total = 0; struct pangea_info *sp = dp->table;
dp->hand.othercardpubs[senderind] = *(uint64_t *)data;
if ( Debuglevel > 2 )
{
for (i=0; i<dp->N; i++)
{
slot = pangea_slot(sp,i);
total += sp->balances[slot];
PostMessage("(p%d %.8f) ",i,dstr(sp->balances[slot]));
}
PostMessage("balances %.8f [%.8f] | ",dstr(total),dstr(total + dp->hostrake + dp->pangearake));
PostMessage("player.%d pangea_gotdeck from P.%d otherpubs.%llx\n",hn->client->H.slot,senderind,(long long)dp->hand.othercardpubs[senderind]);
}
pangea_checkstart(hn,dp,priv);
return(0);
}
int32_t pangea_ready(union hostnet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t senderind)
{
int32_t create_MofN(uint8_t addrtype,char *redeemScript,char *scriptPubKey,char *p2shaddr,char *pubkeys[],int32_t M,int32_t N);
char hex[4096],hexstr[67],*pubkeys[CARDS777_MAXPLAYERS]; struct pangea_info *sp = dp->table;
uint8_t addrtype,p2shtype; int32_t i,slot,retval = -1;
slot = pangea_slot(sp,senderind);
dp->readymask |= (1 << slot);
addrtype = coin777_addrtype(&p2shtype,dp->coinstr);
if ( datalen == 33 )
{
init_hexbytes_noT(hexstr,data,datalen);
strcpy(sp->btcpubkeys[slot],hexstr);
btc_coinaddr(sp->coinaddrs[slot],addrtype,hexstr);
}
else hexstr[0] = 0;
for (i=0; i<dp->N; i++)
if ( GETBIT(&dp->readymask,i) == 0 )
break;
if ( i == dp->N )//dp->readymask == ((1 << dp->N) - 1) )
{
if ( hn->server->H.slot == pangea_slotA(sp) && senderind != 0 )
pangea_sendcmd(hex,hn,"ready",-1,sp->btcpub,sizeof(sp->btcpub),0,0);
for (i=0; i<dp->N; i++)
pubkeys[i] = sp->btcpubkeys[pangea_slot(sp,i)];
retval = create_MofN(p2shtype,sp->redeemScript,sp->scriptPubKey,sp->multisigaddr,pubkeys,dp->M,dp->N);
PostMessage("retval.%d scriptPubKey.(%s) multisigaddr.(%s) redeemScript.(%s)\n",retval,sp->scriptPubKey,sp->multisigaddr,sp->redeemScript);
}
PostMessage("player.%d got ready from senderind.%d slot.%d readymask.%x btcpubkey.(%s) (%s) wip.(%s)\n",hn->client->H.slot,senderind,slot,dp->readymask,hexstr,sp->coinaddrs[slot],sp->wipstr);
/*if ( 0 && hn->client->H.slot == pangea_slotA(dp->table) )
{
if ( (dp->pmworks & (1 << senderind)) == 0 )
{
PostMessage("send pmtest from %d to %d\n",hn->client->H.slot,senderind);
pangea_sendcmd(hex,hn,"pmtest",-1,dp->hand.checkprod.bytes,sizeof(uint64_t),-1,-1);
pangea_sendcmd(hex,hn,"pmtest",senderind,dp->hand.checkprod.bytes,sizeof(uint64_t),-1,senderind);
}
}*/
return(0);
}
void pangea_rwaudit(int32_t saveflag,bits256 *audit,bits256 *audits,int32_t cardi,int32_t destplayer,int32_t N)
{
int32_t i;
audits = &audits[(cardi * N + destplayer) * N];
if ( saveflag != 0 )
{
for (i=0; i<N; i++)
audits[i] = audit[i];
}
else
{
for (i=0; i<N; i++)
audit[i] = audits[i];
}
}
int32_t pangea_card(union hostnet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t cardi,int32_t senderind)
{
int32_t destplayer,card,selector,validcard = -1; bits256 cardpriv,audit[CARDS777_MAXPLAYERS]; char hex[1024],cardAstr[8],cardBstr[8]; struct pangea_info *sp = dp->table;
if ( data == 0 || datalen != sizeof(bits256)*dp->N )
{
PostMessage("pangea_card invalid datalen.%d vs %ld\n",datalen,(long)sizeof(bits256)*dp->N);
return(-1);
}
//PostMessage("pangea_card priv.%llx\n",(long long)hn->client->H.privkey.txid);
destplayer = juint(json,"dest");
pangea_rwaudit(1,(void *)data,priv->audits,cardi,destplayer,dp->N);
pangea_rwaudit(0,audit,priv->audits,cardi,destplayer,dp->N);
//PostMessage("card.%d destplayer.%d [%llx]\n",cardi,destplayer,(long long)audit[0].txid);
if ( (card= cards777_checkcard(&cardpriv,cardi,pangea_ind(dp->table,hn->client->H.slot),destplayer,hn->client->H.privkey,dp->hand.cardpubs,dp->numcards,audit[0])) >= 0 )
{
destplayer = pangea_ind(dp->table,hn->client->H.slot);
if ( Debuglevel > 2 )
PostMessage("player.%d got card.[%d]\n",hn->client->H.slot,card);
//memcpy(&priv->incards[cardi*dp->N + destplayer],cardpriv.bytes,sizeof(bits256));
selector = (cardi / dp->N);
priv->holecards[selector] = cardpriv;
priv->cardis[selector] = cardi;
dp->hand.hands[destplayer][5 + selector] = priv->hole[selector] = cardpriv.bytes[1];
validcard = 1;
cardAstr[0] = cardBstr[0] = 0;
if ( priv->hole[0] != 0xff )
cardstr(cardAstr,priv->hole[0]);
if ( priv->hole[1] != 0xff )
cardstr(cardBstr,priv->hole[1]);
PostMessage(">>>>>>>>>> dest.%d priv.%p holecards[%02d] cardi.%d / dp->N %d (%02d %02d) -> (%s %s)\n",destplayer,priv,priv->hole[cardi / dp->N],cardi,dp->N,priv->hole[0],priv->hole[1],cardAstr,cardBstr);
if ( cards777_validate(cardpriv,dp->hand.final[cardi*dp->N + destplayer],dp->hand.cardpubs,dp->numcards,audit,dp->N,sp->playerpubs[hn->client->H.slot]) < 0 )
PostMessage("player.%d decoded cardi.%d card.[%02d] but it doesnt validate\n",hn->client->H.slot,cardi,card);
} else PostMessage("ERROR player.%d got no card %llx\n",hn->client->H.slot,*(long long *)data);
if ( cardi < dp->N*2 )
pangea_sendcmd(hex,hn,"facedown",-1,(void *)&cardi,sizeof(cardi),cardi,validcard);
else pangea_sendcmd(hex,hn,"faceup",-1,cardpriv.bytes,sizeof(cardpriv),cardi,0xff);
return(0);
}
int32_t pangea_decoded(union hostnet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t senderind)
{
int32_t cardi,destplayer,card,turni; bits256 cardpriv,audit[CARDS777_MAXPLAYERS]; char hex[1024]; struct pangea_info *sp = dp->table;
if ( data == 0 || datalen != sizeof(bits256)*dp->N )
{
PostMessage("pangea_decoded invalid datalen.%d vs %ld\n",datalen,(long)sizeof(bits256));
return(-1);
}
cardi = juint(json,"cardi");
turni = juint(json,"turni");
if ( cardi < dp->N*2 || cardi >= dp->N*2 + 5 )
{
PostMessage("pangea_decoded invalid cardi.%d\n",cardi);
return(-1);
}
destplayer = pangea_ind(dp->table,0);
pangea_rwaudit(1,(void *)data,priv->audits,cardi,destplayer,dp->N);
pangea_rwaudit(0,audit,priv->audits,cardi,destplayer,dp->N);
//memcpy(&priv->incards[cardi*dp->N + destplayer],data,sizeof(bits256));
if ( turni == pangea_ind(dp->table,hn->client->H.slot) )
{
if ( hn->client->H.slot != pangea_slotA(dp->table) )
{
audit[0] = cards777_decode(&audit[sp->myind],priv->xoverz,destplayer,audit[0],priv->outcards,dp->numcards,dp->N);
pangea_rwaudit(1,audit,priv->audits,cardi,destplayer,dp->N);
pangea_sendcmd(hex,hn,"decoded",-1,audit[0].bytes,sizeof(bits256)*dp->N,cardi,pangea_prevnode(dp->table));
//PostMessage("player.%d decoded cardi.%d %llx -> %llx\n",hn->client->H.slot,cardi,(long long)priv->incards[cardi*dp->N + destplayer].txid,(long long)decoded.txid);
}
else
{
if ( (card= cards777_checkcard(&cardpriv,cardi,pangea_ind(dp->table,hn->client->H.slot),pangea_ind(dp->table,hn->client->H.slot),hn->client->H.privkey,dp->hand.cardpubs,dp->numcards,audit[0])) >= 0 )
{
if ( cards777_validate(cardpriv,dp->hand.final[cardi*dp->N + destplayer],dp->hand.cardpubs,dp->numcards,audit,dp->N,sp->playerpubs[hn->client->H.slot]) < 0 )
PostMessage("player.%d decoded cardi.%d card.[%d] but it doesnt validate\n",hn->client->H.slot,cardi,card);
pangea_sendcmd(hex,hn,"faceup",-1,cardpriv.bytes,sizeof(cardpriv),cardi,cardpriv.txid!=0?0xff:-1);
//PostMessage("-> FACEUP.(%s)\n",hex);
}
}
}
return(0);
}
int32_t pangea_zbuf(char *zbuf,uint8_t *data,int32_t datalen)
{
int i,j,n = 0;
for (i=0; i<datalen; i++)
{
if ( data[i] != 0 )
{
zbuf[n++] = hexbyte((data[i]>>4) & 0xf);
zbuf[n++] = hexbyte(data[i] & 0xf);
}
else
{
for (j=1; j<16; j++)
if ( data[i+j] != 0 )
break;
i += (j - 1);
zbuf[n++] = 'Z';
zbuf[n++] = 'A'+j;
}
}
zbuf[n] = 0;
return(n);
}
int32_t pangea_unzbuf(uint8_t *buf,char *hexstr,int32_t len)
{
int32_t i,j,len2;
for (len2=i=0; i<len; i+=2)
{
if ( hexstr[i] == 'Z' )
{
for (j=0; j<hexstr[i+1]-'A'; j++)
buf[len2++] = 0;
}
else buf[len2++] = _decode_hex(&hexstr[i]);
}
//char *tmp = calloc(1,len*2+1);
//init_hexbytes_noT(tmp,buf,len2);
//PostMessage("zlen %d to len2 %d\n",len,len2);
//free(tmp);
return(len2);
}
int32_t pangea_preflop(union hostnet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t senderind)
{
char *hex,*zbuf; int32_t i,card,len,iter,cardi,destplayer,maxlen = (int32_t)(2 * CARDS777_MAXPLAYERS * CARDS777_MAXPLAYERS * CARDS777_MAXCARDS * sizeof(bits256));
bits256 cardpriv,audit[CARDS777_MAXPLAYERS]; struct pangea_info *sp = dp->table;
if ( data == 0 || datalen != (2 * dp->N) * (dp->N * dp->N * sizeof(bits256)) || (hex= malloc(maxlen)) == 0 )
{
PostMessage("pangea_preflop invalid datalen.%d vs %ld\n",datalen,(long)(2 * dp->N) * (dp->N * dp->N * sizeof(bits256)));
return(-1);
}
//PostMessage("preflop player.%d\n",hn->client->H.slot);
//memcpy(priv->incards,data,datalen);
memcpy(priv->audits,data,datalen);
if ( hn->client->H.slot != pangea_slotA(dp->table) && hn->client->H.slot != pangea_slotB(dp->table) )
{
//for (i=0; i<dp->numcards*dp->N; i++)
// PostMessage("%llx ",(long long)priv->outcards[i].txid);
//PostMessage("player.%d outcards\n",hn->client->H.slot);
for (cardi=0; cardi<dp->N*2; cardi++)
for (destplayer=0; destplayer<dp->N; destplayer++)
{
pangea_rwaudit(0,audit,priv->audits,cardi,destplayer,dp->N);
if ( 0 && (card= cards777_checkcard(&cardpriv,cardi,pangea_ind(dp->table,hn->client->H.slot),destplayer,hn->client->H.privkey,dp->hand.cardpubs,dp->numcards,audit[0])) >= 0 )
PostMessage("ERROR: unexpected decode player.%d got card.[%d]\n",hn->client->H.slot,card);
audit[0] = cards777_decode(&audit[sp->myind],priv->xoverz,destplayer,audit[0],priv->outcards,dp->numcards,dp->N);
pangea_rwaudit(1,audit,priv->audits,cardi,destplayer,dp->N);
}
//PostMessage("issue preflop\n");
if ( (zbuf= calloc(1,datalen*2+1)) != 0 )
{
//init_hexbytes_noT(zbuf,priv->audits[0].bytes,datalen);
//PostMessage("STARTZBUF.(%s)\n",zbuf);
len = pangea_zbuf(zbuf,priv->audits[0].bytes,datalen);
{
int32_t len2;
len2 = pangea_unzbuf((void *)hex,zbuf,len);
if ( len2 != datalen || memcmp(hex,priv->audits[0].bytes,datalen) != 0 )
{
if ( _crc32(0,(void *)hex,datalen) != _crc32(0,priv->audits[0].bytes,datalen) )
{
PostMessage("zbuf error len2.%d vs datalen.%d crcs %u vs %u\n%s\n",len2,datalen,_crc32(0,(void *)hex,datalen),_crc32(0,priv->audits[0].bytes,datalen),hex);
getchar();
}
}
}
//PostMessage("datalen.%d -> len.%d zbuf %ld\n",datalen,len,(long)strlen(zbuf));
pangea_sendcmd(hex,hn,"preflop",pangea_prevnode(dp->table),(void *)zbuf,len,dp->N * 2 * dp->N,-1);
free(zbuf);
}
}
else
{
//PostMessage("sendout cards\n");
for (iter=cardi=0; iter<2; iter++)
for (i=0; i<dp->N; i++,cardi++)
{
destplayer = (dp->button + i) % dp->N;
pangea_rwaudit(0,audit,priv->audits,cardi,destplayer,dp->N);
//PostMessage("audit[0] %llx -> ",(long long)audit[0].txid);
audit[0] = cards777_decode(&audit[sp->myind],priv->xoverz,destplayer,audit[0],priv->outcards,dp->numcards,dp->N);
pangea_rwaudit(1,audit,priv->audits,cardi,destplayer,dp->N);
//PostMessage("[%llx + %llx] ",*(long long *)&audit[0],(long long)&audit[pangea_ind(dp->table,hn->client->H.slot)]);
if ( destplayer == pangea_ind(dp->table,hn->client->H.slot) )
pangea_card(hn,json,dp,priv,audit[0].bytes,sizeof(bits256)*dp->N,cardi,destplayer);
else pangea_sendcmd(hex,hn,"card",destplayer,audit[0].bytes,sizeof(bits256)*dp->N,cardi,-1);
}
}
free(hex);
return(0);
}
int32_t pangea_encoded(union hostnet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t senderind)
{
char *hex; bits256 audit[CARDS777_MAXPLAYERS]; int32_t i,iter,cardi,destplayer; struct pangea_info *sp = dp->table;
if ( data == 0 || datalen != (dp->numcards * dp->N) * sizeof(bits256) )
{
PostMessage("pangea_encode invalid datalen.%d vs %ld\n",datalen,(long)((dp->numcards * dp->N) * sizeof(bits256)));
return(-1);
}
cards777_encode(priv->outcards,priv->xoverz,priv->allshares,priv->myshares,dp->hand.sharenrs[pangea_ind(dp->table,hn->client->H.slot)],dp->M,(void *)data,dp->numcards,dp->N);
//int32_t i; for (i=0; i<dp->numcards*dp->N; i++)
// PostMessage("%llx ",(long long)priv->outcards[i].txid);
PostMessage("player.%d ind.%d encodes into %p %llx -> %llx next.%d dp->N %d\n",hn->client->H.slot,pangea_ind(sp,hn->client->H.slot),priv->outcards,(long long)*(uint64_t *)data,(long long)priv->outcards[0].txid,pangea_nextnode(sp),dp->N);
if ( pangea_ind(sp,hn->client->H.slot) > 0 && (hex= malloc(65536)) != 0 )
{
if ( pangea_ind(sp,hn->client->H.slot) < sp->numactive-1 )
{
//PostMessage("send encoded\n");
pangea_sendcmd(hex,hn,"encoded",pangea_nextnode(sp),priv->outcards[0].bytes,datalen,dp->N*dp->numcards,-1);
}
else
{
memcpy(dp->hand.final,priv->outcards,sizeof(bits256)*dp->N*dp->numcards);
pangea_sendcmd(hex,hn,"final",-1,priv->outcards[0].bytes,datalen,dp->N*dp->numcards,-1);
for (iter=cardi=0; iter<2; iter++)
for (i=0; i<dp->N; i++,cardi++)
for (destplayer=0; destplayer<dp->N; destplayer++)
{
pangea_rwaudit(0,audit,priv->audits,cardi,destplayer,dp->N);
audit[0] = dp->hand.final[cardi*dp->N + destplayer];
pangea_rwaudit(1,audit,priv->audits,cardi,destplayer,dp->N);
}
PostMessage("call preflop %ld\n",(long)((2 * dp->N) * (dp->N * dp->N * sizeof(bits256))));
pangea_preflop(hn,json,dp,priv,priv->audits[0].bytes,(2 * dp->N) * (dp->N * dp->N * sizeof(bits256)),pangea_ind(sp,hn->client->H.slot));
}
free(hex);
}
return(0);
}
int32_t pangea_final(union hostnet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t senderind)
{
if ( data == 0 || datalen != (dp->numcards * dp->N) * sizeof(bits256) )
{
PostMessage("pangea_final invalid datalen.%d vs %ld\n",datalen,(long)((dp->numcards * dp->N) * sizeof(bits256)));
return(-1);
}
if ( Debuglevel > 2 )
PostMessage("player.%d final into %p\n",hn->client->H.slot,priv->outcards);
memcpy(dp->hand.final,data,sizeof(bits256) * dp->N * dp->numcards);
return(0);
}
int32_t pangea_facedown(union hostnet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t cardi,int32_t senderind)
{
int32_t i,validcard,n = 0;
if ( data == 0 || datalen != sizeof(int32_t) )
{
PostMessage("pangea_facedown invalid datalen.%d vs %ld\n",datalen,(long)sizeof(bits256));
return(-1);
}
validcard = juint(json,"turni");
if ( validcard > 0 )
dp->hand.havemasks[senderind] |= (1LL << cardi);
for (i=0; i<dp->N; i++)
{
if ( Debuglevel > 2 )
PostMessage("%llx ",(long long)dp->hand.havemasks[i]);
if ( bitweight(dp->hand.havemasks[i]) == 2 )
n++;
}
if ( Debuglevel > 2 )
PostMessage(" | player.%d sees that destplayer.%d got cardi.%d valid.%d | %llx | n.%d\n",hn->client->H.slot,senderind,cardi,validcard,(long long)dp->hand.havemasks[senderind],n);
if ( hn->client->H.slot == pangea_slotA(dp->table) && n == dp->N )
pangea_startbets(hn,dp,dp->N*2);
return(0);
}
uint32_t pangea_rank(struct cards777_pubdata *dp,int32_t senderind)
{
int32_t i; char handstr[128];
if ( dp->hand.handranks[senderind] != 0 )
return(dp->hand.handranks[senderind]);
for (i=0; i<7; i++)
{
if ( i < 5 )
dp->hand.hands[senderind][i] = dp->hand.community[i];
if ( dp->hand.hands[senderind][i] == 0xff )
break;
}
if ( i == 7 )
{
dp->hand.handranks[senderind] = set_handstr(handstr,dp->hand.hands[senderind],0);
dp->hand.handmask |= (1 << senderind);
PostMessage("sender.%d (%s) rank.%x handmask.%x\n",senderind,handstr,dp->hand.handranks[senderind],dp->hand.handmask);
}
return(dp->hand.handranks[senderind]);
}
int32_t pangea_faceup(union hostnet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t senderind)
{
int32_t cardi,validcard,i; char hexstr[65]; uint16_t tmp;
if ( data == 0 || datalen != sizeof(bits256) )
{
PostMessage("pangea_faceup invalid datalen.%d vs %ld\n",datalen,(long)((dp->numcards + 1) * sizeof(bits256)));
return(-1);
}
init_hexbytes_noT(hexstr,data,sizeof(bits256));
cardi = juint(json,"cardi");
validcard = ((int32_t)juint(json,"turni")) >= 0;
if ( Debuglevel > 2 || hn->client->H.slot == pangea_slotA(dp->table) )
{
char *str = jprint(json,0);
PostMessage("from.%d -> player.%d COMMUNITY.[%d] (%s) cardi.%d valid.%d (%s)\n",senderind,hn->client->H.slot,data[1],hexstr,cardi,validcard,str);
free(str);
}
//PostMessage("got FACEUP.(%s)\n",jprint(json,0));
if ( validcard > 0 )
{
tmp = (cardi << 8);
tmp |= (juint(json,"turni") & 0xff);
pangea_summary(hn,dp,CARDS777_FACEUP,&tmp,sizeof(tmp),data,sizeof(bits256));
if ( cardi >= dp->N*2 && cardi < dp->N*2+5 )
{
dp->hand.community[cardi - dp->N*2] = data[1];
for (i=0; i<dp->N; i++)
dp->hand.hands[i][cardi - dp->N*2] = data[1];
memcpy(dp->hand.community256[cardi - dp->N*2].bytes,data,sizeof(bits256));
//PostMessage("set community[%d] <- %d\n",cardi - dp->N*2,data[1]);
if ( senderind == pangea_ind(dp->table,hn->client->H.slot) )
pangea_rank(dp,senderind);
//PostMessage("calc rank\n");
if ( hn->client->H.slot == pangea_slotA(dp->table) && cardi >= dp->N*2+2 && cardi < dp->N*2+5 )
pangea_startbets(hn,dp,cardi+1);
//else PostMessage("dont start bets %d\n",cardi+1);
}
else
{
//PostMessage("valid.%d cardi.%d vs N.%d\n",validcard,cardi,dp->N);
if ( cardi < dp->N*2 )
{
memcpy(dp->hand.cards[senderind][cardi/dp->N].bytes,data,sizeof(bits256));
dp->hand.hands[senderind][5 + cardi/dp->N] = data[1];
pangea_rank(dp,senderind);
}
}
}
return(0);
}
void pangea_serverstate(union hostnet777 *hn,struct cards777_pubdata *dp,struct cards777_privdata *priv)
{
int32_t i,j,n; struct pangea_info *sp = dp->table;
if ( dp->hand.finished != 0 && time(NULL) > dp->hand.finished+PANGEA_HANDGAP )
{
PostMessage("HANDGAP\n");
pangea_anotherhand(hn,dp,3);
}
if ( dp->hand.betstarted == 0 && dp->newhand[0] == 0 )
{
static uint32_t disptime;
for (i=n=0; i<dp->N; i++)
{
if ( Debuglevel > 2 )
PostMessage("%llx ",(long long)dp->hand.havemasks[i]);
if ( bitweight(dp->hand.havemasks[i]) == 2 )
n++;
}
if ( n < dp->N )
{
for (i=0; i<dp->N; i++)
{
if ( sp->balances[pangea_slot(sp,i)] < dp->minbuyin*dp->bigblind || sp->balances[pangea_slot(sp,i)] > dp->maxbuyin*dp->bigblind )
break;
}
if ( i == dp->N && dp->numhands < 2 )
{
if ( time(NULL) > dp->hand.startdecktime+60 )
{
PostMessage("send newdeck len.%ld\n",(long)strlen(dp->newhand));
pangea_newdeck(hn);
PostMessage("sent newdeck %ld\n",(long)strlen(dp->newhand));
}
}
else if ( disptime != time(NULL) && (time(NULL) % 60) == 0 )
{
disptime = (uint32_t)time(NULL);
for (j=0; j<dp->N; j++)
PostMessage("%.8f ",dstr(sp->balances[pangea_slot(sp,i)]));
PostMessage("no buyin for %d (%.8f %.8f)\n",i,dstr(dp->minbuyin*dp->bigblind),dstr(dp->maxbuyin*dp->bigblind));
}
}
}
else pangea_checkstart(hn,dp,priv);
}
/*int32_t pangea_pmtest(union hostnet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t senderind)
{
int32_t turni,cardi; char hex[2048];
cardi = juint(json,"cardi");
turni = juint(json,"turni");
if ( senderind >= 0 && senderind < dp->N )
{
if ( cardi < 0 )
{
if ( turni >= 0 )
dp->pmviaworks |= (1 << senderind);
else dp->broadcastworks |= (1 << senderind);
}
else
{
if ( turni >= 0 )
dp->pmworks |= (1 << senderind);
else dp->pmviaworks |= (1 << senderind);
}
if ( dp->pmworks != ((1 << dp->N) - 1) )
{
//PostMessage("PMworks: %x %x %x\n",dp->pmworks,dp->pmviaworks,dp->broadcastworks);
}
}
//PostMessage("got pmtest.%d from %d cardi.%d\n",turni,senderind,cardi);
if ( hn->client->H.slot == 0 )
{
if ( dp->pmworks == ((1 << dp->N) - 1) )
{
//PostMessage("all pms work\n");
}
}
else
{
if ( dp->pmworks != ((1 << dp->N) - 1) )
{
pangea_sendcmd(hex,hn,"pmtest",senderind,dp->hand.checkprod.bytes,sizeof(uint64_t),senderind,turni);
pangea_sendcmd(hex,hn,"pmtest",-1,dp->hand.checkprod.bytes,sizeof(uint64_t),-1,turni);
}
}
return(0);
}*/
int32_t pangea_ping(union hostnet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t senderind)
{
dp->hand.othercardpubs[senderind] = *(uint64_t *)data;
if ( senderind == 0 )
{
/*dp->hand.undergun = juint(json,"turni");
dp->hand.cardi = juint(json,"cardi");
if ( (array= jarray(&n,json,"community")) != 0 )
{
for (i=0; i<n; i++)
dp->hand.community[i] = juint(jitem(array,i),0);
}*/
}
//PostMessage("player.%d GOTPING.(%s) %llx\n",hn->client->H.slot,jprint(json,0),(long long)dp->othercardpubs[senderind]);
return(0);
}
void pangea_chat(uint64_t senderbits,void *buf,int32_t len,int32_t senderind)
{
PostMessage(">>>>>>>>>>> CHAT FROM.%d %llu: (%s)\n",senderind,(long long)senderbits,(char *)buf);
}
int32_t pangea_poll(uint64_t *senderbitsp,uint32_t *timestampp,union hostnet777 *hn)
{
char *jsonstr,*hexstr,*cmdstr; cJSON *json; struct cards777_privdata *priv; struct cards777_pubdata *dp; struct pangea_info *sp;
int32_t len,senderind,maxlen; uint8_t *buf;
*senderbitsp = 0;
dp = hn->client->H.pubdata, sp = dp->table;
priv = hn->client->H.privdata;
if ( hn == 0 || hn->client == 0 || dp == 0 || priv == 0 )
{
if ( Debuglevel > 2 )
PostMessage("pangea_poll: null hn.%p %p dp.%p priv.%p\n",hn,hn!=0?hn->client:0,dp,priv);
return(-1);
}
maxlen = (int32_t)(sizeof(bits256) * dp->N*dp->N*dp->numcards);
if ( (buf= malloc(maxlen)) == 0 )
{
PostMessage("pangea_poll: null buf\n");
return(-1);
}
if ( dp != 0 && priv != 0 && (jsonstr= queue_dequeue(&hn->client->H.Q,1)) != 0 )
{
//pangea_neworder(dp,dp->table,0,0);
//PostMessage("player.%d GOT.(%s)\n",hn->client->H.slot,jsonstr);
if ( (json= cJSON_Parse(jsonstr)) != 0 )
{
*senderbitsp = j64bits(json,"sender");
if ( (senderind= juint(json,"myind")) < 0 || senderind >= dp->N )
{
PostMessage("pangea_poll: illegal senderind.%d cardi.%d turni.%d (%s)\n",senderind,juint(json,"cardi"),juint(json,"turni"),jsonstr);
goto cleanup;
}
*timestampp = juint(json,"timestamp");
hn->client->H.state = juint(json,"state");
len = juint(json,"n");
cmdstr = jstr(json,"cmd");
if ( sp->myind < 0 )
{
// check for reactivation command
goto cleanup;
}
if ( cmdstr != 0 && strcmp(cmdstr,"preflop") == 0 )
{
if ( (hexstr= jstr(json,"data")) != 0 )
len = pangea_unzbuf(buf,hexstr,len);
}
else if ( (hexstr= jstr(json,"data")) != 0 && strlen(hexstr) == (len<<1) )
{
if ( len > maxlen )
{
PostMessage("len too big for pangea_poll\n");
goto cleanup;
}
decode_hex(buf,len,hexstr);
} else if ( hexstr != 0 )
PostMessage("len.%d vs hexlen.%ld (%s)\n",len,(long)(strlen(hexstr)>>1),hexstr);
if ( cmdstr != 0 )
{
if ( strcmp(cmdstr,"newhand") == 0 )
pangea_newhand(hn,json,dp,priv,buf,len,senderind);
else if ( strcmp(cmdstr,"ping") == 0 )
pangea_ping(hn,json,dp,priv,buf,len,senderind);
//else if ( strcmp(cmdstr,"pmtest") == 0 )
// pangea_pmtest(hn,json,dp,priv,buf,len,senderind);
else if ( strcmp(cmdstr,"gotdeck") == 0 )
pangea_gotdeck(hn,json,dp,priv,buf,len,senderind);
else if ( strcmp(cmdstr,"ready") == 0 )
pangea_ready(hn,json,dp,priv,buf,len,senderind);
else if ( strcmp(cmdstr,"encoded") == 0 )
pangea_encoded(hn,json,dp,priv,buf,len,senderind);
else if ( strcmp(cmdstr,"final") == 0 )
pangea_final(hn,json,dp,priv,buf,len,senderind);
else if ( strcmp(cmdstr,"addfunds") == 0 )
pangea_addfunds(hn,json,dp,priv,buf,len,senderind);
else if ( strcmp(cmdstr,"preflop") == 0 )
pangea_preflop(hn,json,dp,priv,buf,len,senderind);
else if ( strcmp(cmdstr,"decoded") == 0 )
pangea_decoded(hn,json,dp,priv,buf,len,senderind);
else if ( strcmp(cmdstr,"card") == 0 )
pangea_card(hn,json,dp,priv,buf,len,juint(json,"cardi"),senderind);
else if ( strcmp(cmdstr,"facedown") == 0 )
pangea_facedown(hn,json,dp,priv,buf,len,juint(json,"cardi"),senderind);
else if ( strcmp(cmdstr,"faceup") == 0 )
pangea_faceup(hn,json,dp,priv,buf,len,senderind);
else if ( strcmp(cmdstr,"turn") == 0 )
pangea_turn(hn,json,dp,priv,buf,len,senderind);
else if ( strcmp(cmdstr,"confirmturn") == 0 )
pangea_confirmturn(hn,json,dp,priv,buf,len,senderind);
else if ( strcmp(cmdstr,"chat") == 0 )
pangea_chat(*senderbitsp,buf,len,senderind);
else if ( strcmp(cmdstr,"action") == 0 )
pangea_action(hn,json,dp,priv,buf,len,senderind);
else if ( strcmp(cmdstr,"showdown") == 0 )
pangea_showdown(hn,json,dp,priv,buf,len,senderind);
else if ( strcmp(cmdstr,"summary") == 0 )
pangea_gotsummary(hn,json,dp,priv,buf,len,senderind);
}
cleanup:
free_json(json);
}
free_queueitem(jsonstr);
}
free(buf);
return(hn->client->H.state);
}
char *pangea_status(uint64_t my64bits,uint64_t tableid,cJSON *json)
{
int32_t i,j,threadid = juint(json,"threadid"); struct pangea_info *sp; cJSON *item,*array=0,*retjson = 0;
if ( tableid != 0 )
{
if ( (sp= pangea_find(tableid,threadid)) != 0 )
{
if ( (item= pangea_tablestatus(sp)) != 0 )
{
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jadd(retjson,"table",item);
return(jprint(retjson,1));
}
}
}
else
{
for (i=0; i<sizeof(TABLES)/sizeof(*TABLES); i++)
{
if ( (sp= TABLES[i]) != 0 )
{
for (j=0; j<sp->numaddrs; j++)
if ( sp->addrs[j] == my64bits )
{
if ( (item= pangea_tablestatus(sp)) != 0 )
{
if ( array == 0 )
array = cJSON_CreateArray();
jaddi(array,item);
}
break;
}
}
}
}
retjson = cJSON_CreateObject();
if ( array == 0 )
jaddstr(retjson,"error","no table status");
else
{
jaddstr(retjson,"result","success");
jadd(retjson,"tables",array);
}
jadd64bits(retjson,"nxtaddr",my64bits);
return(jprint(retjson,1));
}
int32_t pangea_idle(struct plugin_info *plugin)
{
int32_t i,n,m,pinggap = 1; uint64_t senderbits; uint32_t timestamp; struct pangea_thread *tp; union hostnet777 *hn;
struct cards777_pubdata *dp; char hex[1024];
while ( 1 )
{
for (i=n=m=0; i<_PANGEA_MAXTHREADS; i++)
{
if ( (tp= THREADS[i]) != 0 )
{
hn = &tp->hn;
//PostMessage("pangea idle player.%d\n",hn->client->H.slot);
if ( hn->client->H.done == 0 )
{
n++;
if ( hostnet777_idle(hn) != 0 )
m++;
pangea_poll(&senderbits,&timestamp,hn);
dp = hn->client->H.pubdata;
if ( dp != 0 && hn->client->H.slot == pangea_slotA(dp->table) )
pinggap = 1;
if ( hn->client != 0 && dp != 0 )
{
if ( time(NULL) > hn->client->H.lastping + pinggap )
{
if ( 0 && (dp= hn->client->H.pubdata) != 0 )
{
pangea_sendcmd(hex,hn,"ping",-1,dp->hand.checkprod.bytes,sizeof(uint64_t),dp->hand.cardi,dp->hand.undergun);
hn->client->H.lastping = (uint32_t)time(NULL);
}
}
if ( dp->hand.handmask == ((1 << dp->N) - 1) && dp->hand.finished == 0 )//&& dp->hand.pangearake == 0 )
{
PostMessage("P%d: all players folded or showed cards at %ld | rakemillis %d\n",hn->client->H.slot,(long)time(NULL),dp->rakemillis);
pangea_finish(hn,dp);
}
if ( hn->client->H.slot == pangea_slotA(dp->table) )
pangea_serverstate(hn,dp,hn->server->H.privdata);
}
}
}
}
if ( n == 0 )
break;
if ( m == 0 )
msleep(3);
}
//for (i=0; i<_PANGEA_MAXTHREADS; i++)
// if ( THREADS[i] != 0 && Pangea_waiting != 0 )
// pangea_userpoll(&THREADS[i]->hn);
return(0);
}
void pangea_buyins(uint32_t *minbuyinp,uint32_t *maxbuyinp)
{
if ( *minbuyinp == 0 && *maxbuyinp == 0 )
{
*minbuyinp = 100;
*maxbuyinp = 1000;
}
else
{
PostMessage("minbuyin.%d maxbuyin.%d -> ",*minbuyinp,*maxbuyinp);
if ( *minbuyinp < 20 )
*minbuyinp = 20;
if ( *maxbuyinp < *minbuyinp )
*maxbuyinp = (*minbuyinp * 4);
if ( *maxbuyinp > 1000 )
*maxbuyinp = 1000;
if ( *minbuyinp > *maxbuyinp )
*minbuyinp = *maxbuyinp;
PostMessage("(%d %d)\n",*minbuyinp,*maxbuyinp);
}
}
struct pangea_info *pangea_create(struct pangea_thread *tp,int32_t *createdflagp,char *base,uint32_t timestamp,uint64_t *addrs,int32_t numaddrs,uint64_t bigblind,uint64_t ante,uint64_t *isbot,uint32_t minbuyin,uint32_t maxbuyin,int32_t hostrake)
{
struct pangea_info *sp = 0; bits256 hash; int32_t i,j,numcards,firstslot = -1; struct cards777_privdata *priv; struct cards777_pubdata *dp;
if ( createdflagp != 0 )
*createdflagp = 0;
for (i=0; i<numaddrs; i++)
PostMessage("%llu ",(long long)addrs[i]);
PostMessage("pangea_create numaddrs.%d\n",numaddrs);
for (i=0; i<numaddrs; i++)
{
if ( addrs[i] == tp->nxt64bits )
break;
}
if ( i == numaddrs )
{
PostMessage("this node not in addrs\n");
return(0);
}
if ( numaddrs > 0 && (sp= calloc(1,sizeof(*sp))) != 0 )
{
sp->tp = tp;
numcards = CARDS777_MAXCARDS;
pangea_buyins(&minbuyin,&maxbuyin);
tp->numcards = numcards, tp->N = numaddrs;
sp->numactive = numaddrs;
sp->dp = dp = cards777_allocpub((numaddrs >> 1) + 1,numcards,numaddrs);
dp->minbuyin = minbuyin, dp->maxbuyin = maxbuyin;
sp->minbuyin = minbuyin, sp->maxbuyin = maxbuyin;
dp->rakemillis = hostrake;
if ( dp->rakemillis > PANGEA_MAX_HOSTRAKE )
dp->rakemillis = PANGEA_MAX_HOSTRAKE;
dp->rakemillis += PANGEA_MINRAKE_MILLIS;
if ( dp == 0 )
{
PostMessage("pangea_create: unexpected out of memory pub\n");
return(0);
}
for (j=0; j<5; j++)
dp->hand.community[j] = 0xff;
memcpy(sp->addrs,addrs,numaddrs * sizeof(sp->addrs[0]));
for (j=0; j<numaddrs; j++)
{
//if ( balances != 0 )
// dp->balances[j] = balances[j];
//else dp->balances[j] = 100;
if ( isbot != 0 )
sp->isbot[j] = isbot[j];
sp->active[j] = addrs[j];
}
sp->priv = priv = cards777_allocpriv(numcards,numaddrs);
priv->hole[0] = priv->hole[1] = 0xff;
if ( priv == 0 )
{
PostMessage("pangea_create: unexpected out of memory priv\n");
return(0);
}
priv->automuck = Showmode;
priv->autofold = Autofold;
btc_priv2pub(sp->btcpub,tp->hn.client->H.privkey.bytes);
init_hexbytes_noT(sp->btcpubkeystr,sp->btcpub,33);
strcpy(sp->coinstr,base);
strcpy(dp->coinstr,base);
sp->addrtype = coin777_addrtype(&sp->p2shtype,base);
sp->wiftype = coin777_wiftype(base);
btc_priv2wip(sp->wipstr,tp->hn.client->H.privkey.bytes,sp->wiftype);
strcpy(sp->btcpubkeys[sp->myslot],sp->btcpubkeystr);
PostMessage("T%d: Automuck.%d Autofold.%d rakemillis.%d btcpubkey.(%s) (%s) addrtype.%02x p2sh.%02x wif.%02x\n",tp->hn.client->H.slot,priv->automuck,priv->autofold,dp->rakemillis,sp->btcpubkeystr,dp->coinstr,sp->addrtype,sp->p2shtype,sp->wiftype);
if ( (sp->timestamp= timestamp) == 0 )
sp->timestamp = (uint32_t)time(NULL);
sp->numaddrs = sp->numactive = numaddrs;
sp->basebits = stringbits(base);
sp->bigblind = dp->bigblind = bigblind, sp->ante = dp->ante = ante;
vcalc_sha256(0,hash.bytes,(uint8_t *)sp,numaddrs * sizeof(sp->addrs[0]) + 4*sizeof(uint32_t) + 3*sizeof(uint64_t));
sp->tableid = hash.txid;
for (i=0; i<sizeof(TABLES)/sizeof(*TABLES); i++)
{
if ( TABLES[i] != 0 )
{
if ( sp->tableid == TABLES[i]->tableid && tp->threadid == TABLES[i]->tp->threadid )
{
PostMessage("tableid %llu already exists!\n",(long long)sp->tableid);
free(sp);
return(TABLES[i]);
}
}
else if ( firstslot < 0 )
firstslot = i;
}
TABLES[firstslot] = sp;
if ( createdflagp != 0 )
*createdflagp = 1;
}
return(sp);
}
cJSON *pangea_ciphersjson(struct cards777_pubdata *dp,struct cards777_privdata *priv)
{
int32_t i,j,nonz = 0; char hexstr[65]; cJSON *array = cJSON_CreateArray();
for (i=0; i<dp->numcards; i++)
for (j=0; j<dp->N; j++,nonz++)
{
init_hexbytes_noT(hexstr,priv->outcards[nonz].bytes,sizeof(bits256));
jaddistr(array,hexstr);
}
return(array);
}
cJSON *pangea_playerpubs(bits256 *playerpubs,int32_t num)
{
int32_t i; char hexstr[65]; cJSON *array = cJSON_CreateArray();
for (i=0; i<num; i++)
{
init_hexbytes_noT(hexstr,playerpubs[i].bytes,sizeof(bits256));
//PostMessage("(%llx-> %s) ",(long long)playerpubs[i].txid,hexstr);
jaddistr(array,hexstr);
}
//PostMessage("playerpubs\n");
return(array);
}
cJSON *pangea_cardpubs(struct cards777_pubdata *dp)
{
int32_t i; char hexstr[65]; cJSON *array = cJSON_CreateArray();
for (i=0; i<dp->numcards; i++)
{
init_hexbytes_noT(hexstr,dp->hand.cardpubs[i].bytes,sizeof(bits256));
jaddistr(array,hexstr);
}
init_hexbytes_noT(hexstr,dp->hand.checkprod.bytes,sizeof(bits256));
jaddistr(array,hexstr);
return(array);
}
cJSON *pangea_sharenrs(uint8_t *sharenrs,int32_t n)
{
int32_t i; cJSON *array = cJSON_CreateArray();
for (i=0; i<n; i++)
jaddinum(array,sharenrs[i]);
return(array);
}
char *pangea_newtable(int32_t threadid,cJSON *json,uint64_t my64bits,bits256 privkey,bits256 pubkey,char *transport,char *ipaddr,uint16_t port,uint32_t minbuyin,uint32_t maxbuyin,int32_t hostrake)
{
int32_t createdflag,num,i,myind= -1; uint64_t tableid,addrs[CARDS777_MAXPLAYERS],isbot[CARDS777_MAXPLAYERS];
struct pangea_info *sp; cJSON *array; struct pangea_thread *tp=0; char *base,*str,*hexstr,*endpoint,hex[1024]; uint32_t timestamp;
struct cards777_pubdata *dp; struct hostnet777_server *srv=0;
str = jprint(json,0);
PostMessage("T%d NEWTABLE.(%s)\n",threadid,str);
free(str);
if ( (tableid= j64bits(json,"tableid")) != 0 && (base= jstr(json,"base")) != 0 && (timestamp= juint(json,"timestamp")) != 0 )
{
if ( (array= jarray(&num,json,"addrs")) == 0 || num < 2 || num > CARDS777_MAXPLAYERS )
{
PostMessage("no address or illegal num.%d\n",num);
return(clonestr("{\"error\":\"no addrs or illegal numplayers\"}"));
}
for (i=0; i<num; i++)
{
addrs[i] = j64bits(jitem(array,i),0);
if ( addrs[i] == my64bits )
{
threadid = myind = i;
if ( (tp= THREADS[threadid]) == 0 )
{
THREADS[threadid] = tp = calloc(1,sizeof(*THREADS[threadid]));
if ( i == 0 )
{
if ( (srv= hostnet777_server(privkey,pubkey,transport,ipaddr,port,num)) == 0 )
PostMessage("cant create hostnet777 server\n");
else
{
tp->hn.server = srv;
memcpy(srv->H.privkey.bytes,privkey.bytes,sizeof(bits256));
memcpy(srv->H.pubkey.bytes,pubkey.bytes,sizeof(bits256));
}
}
else
{
PANGEA_MAXTHREADS = 1;
if ( (endpoint= jstr(json,"pangea_endpoint")) != 0 )
{
if ( strncmp(endpoint,"tcp://127.0.0.1",strlen("tcp://127.0.0.1")) == 0 || strncmp(endpoint,"ws://127.0.0.1",strlen("ws://127.0.0.1")) == 0 )
{
PostMessage("ILLEGAL pangea_endpoint.(%s)\n",endpoint);
return(clonestr("{\"error\":\"contact pangea host and tell them to add myipaddr to their SuperNET.conf\"}"));
}
if ( (tp->hn.client= hostnet777_client(privkey,pubkey,endpoint,i)) == 0 )
{
memcpy(tp->hn.client->H.privkey.bytes,privkey.bytes,sizeof(bits256));
memcpy(tp->hn.client->H.pubkey.bytes,pubkey.bytes,sizeof(bits256));
}
}
}
tp->nxt64bits = my64bits;
}
}
}
if ( myind < 0 )
return(clonestr("{\"error\":\"this table is not for me\"}"));
/*if ( (array= jarray(&num,json,"balances")) == 0 )
{
PostMessage("no balances or illegal num.%d\n",num);
return(clonestr("{\"error\":\"no balances or illegal numplayers\"}"));
}
for (i=0; i<num; i++)
balances[i] = j64bits(jitem(array,i),0);*/
if ( (array= jarray(&num,json,"isbot")) != 0 )
{
for (i=0; i<num; i++)
isbot[i] = j64bits(jitem(array,i),0);
}
else memset(isbot,0,sizeof(isbot));
PostMessage("call pangea_create\n");
if ( (sp= pangea_create(tp,&createdflag,base,timestamp,addrs,num,j64bits(json,"bigblind"),j64bits(json,"ante"),isbot,minbuyin,maxbuyin,hostrake)) == 0 )
{
PostMessage("cant create table.(%s) numaddrs.%d\n",base,num);
return(clonestr("{\"error\":\"cant create table\"}"));
}
PostMessage("back from pangea_create\n");
dp = sp->dp; sp->myslot = sp->myind = myind;
dp->table = sp;
tp->numcards = dp->numcards, tp->N = dp->N, tp->M = dp->M;
if ( threadid == 0 )
{
tp->hn.server->clients[0].pubdata = dp;
tp->hn.server->clients[0].privdata = sp->priv;
tp->hn.server->H.pubdata = dp;
tp->hn.server->H.privdata = sp->priv;
}
else
{
tp->hn.client->my.pubdata = dp;
tp->hn.client->my.privdata = sp->priv;
tp->hn.client->H.pubdata = dp;
tp->hn.client->H.privdata = sp->priv;
if ( THREADS[0] != 0 )
{
THREADS[0]->hn.server->clients[threadid].pubdata = dp;
THREADS[0]->hn.server->clients[threadid].privdata = sp->priv;
}
}
if ( (array= jarray(&num,json,"playerpubs")) == 0 || num < 2 || num > CARDS777_MAXPLAYERS )
{
PostMessage("no address or illegal num.%d\n",num);
return(clonestr("{\"error\":\"no addrs or illegal numplayers\"}"));
}
for (i=0; i<num; i++)
{
hexstr = jstr(jitem(array,i),0);
decode_hex(sp->playerpubs[i].bytes,sizeof(bits256),hexstr);
PostMessage("set playerpubs.(%s) %llx\n",hexstr,(long long)sp->playerpubs[i].txid);
if ( sp->playerpubs[i].txid == 0 )
{
PostMessage("player.%d has no NXT pubkey\n",i);
return(clonestr("{\"error\":\"not all players have published NXT pubkeys\"}"));
}
}
if ( myind >= 0 && createdflag != 0 && addrs[myind] == tp->nxt64bits )
{
memcpy(sp->addrs,addrs,sizeof(*addrs) * dp->N);
dp->readymask |= (1 << sp->myslot);
pangea_sendcmd(hex,&tp->hn,"ready",-1,sp->btcpub,sizeof(sp->btcpub),0,0);
return(clonestr("{\"result\":\"newtable created\"}"));
}
else if ( createdflag == 0 )
{
if ( sp->addrs[0] == tp->nxt64bits )
return(clonestr("{\"result\":\"this is my table\"}"));
else return(clonestr("{\"result\":\"table already exists\"}"));
}
}
return(clonestr("{\"error\":\"no tableid\"}"));
}
struct pangea_thread *pangea_threadinit(struct plugin_info *plugin,int32_t maxplayers)
{
struct pangea_thread *tp; struct hostnet777_server *srv;
PANGEA_MAXTHREADS = 1;
THREADS[0] = tp = calloc(1,sizeof(*THREADS[0]));
if ( tp == 0 )
{
PostMessage("pangea_threadinit: unexpected out of memory\n");
return(0);
}
tp->nxt64bits = plugin->nxt64bits;
if ( (srv= hostnet777_server(*(bits256 *)plugin->mypriv,*(bits256 *)plugin->mypub,plugin->transport,plugin->ipaddr,plugin->pangeaport,9)) == 0 )
PostMessage("cant create hostnet777 server\n");
else
{
tp->hn.server = srv;
memcpy(srv->H.privkey.bytes,plugin->mypriv,sizeof(bits256));
memcpy(srv->H.pubkey.bytes,plugin->mypub,sizeof(bits256));
}
return(tp);
}
void pangea_create_newtable(char *retbuf,struct pangea_info *sp,struct cards777_pubdata *dp,uint64_t *isbot)
{
char *addrstr,*ciphers,*playerpubs,*isbotstr;
isbotstr = jprint(addrs_jsonarray(isbot,dp->N),1);
//balancestr = jprint(addrs_jsonarray(balances,num),1);
addrstr = jprint(addrs_jsonarray(sp->addrs,dp->N),1);
ciphers = jprint(pangea_ciphersjson(dp,sp->priv),1);
playerpubs = jprint(pangea_playerpubs(sp->playerpubs,dp->N),1);
dp->readymask |= (1 << sp->myslot);
sprintf(retbuf,"{\"cmd\":\"newtable\",\"broadcast\":\"allnodes\",\"myind\":%d,\"pangea_endpoint\":\"%s\",\"plugin\":\"relay\",\"destplugin\":\"pangea\",\"method\":\"busdata\",\"submethod\":\"newtable\",\"my64bits\":\"%llu\",\"tableid\":\"%llu\",\"timestamp\":%u,\"M\":%d,\"N\":%d,\"base\":\"%s\",\"bigblind\":\"%llu\",\"minbuyin\":\"%d\",\"maxbuyin\":\"%u\",\"rakemillis\":\"%u\",\"ante\":\"%llu\",\"playerpubs\":%s,\"addrs\":%s,\"isbot\":%s,\"millitime\":\"%lld\"}",sp->myslot,sp->tp->hn.server->ep.endpoint,(long long)sp->tp->nxt64bits,(long long)sp->tableid,sp->timestamp,dp->M,dp->N,sp->coinstr,(long long)sp->bigblind,dp->minbuyin,dp->maxbuyin,dp->rakemillis,(long long)sp->ante,playerpubs,addrstr,isbotstr,(long long)hostnet777_convmT(&sp->tp->hn.server->H.mT,0)); //\"pluginrequest\":\"SuperNET\",
PostMessage("START.(%s)\n",retbuf);
//dp->pmworks |= (1 << sp->myind);
free(addrstr), free(ciphers), free(playerpubs), free(isbotstr);// free(balancestr);
}
int32_t pangea_start(struct plugin_info *plugin,char *retbuf,char *base,uint32_t timestamp,uint64_t bigblind,uint64_t ante,int32_t hostrake,int32_t maxplayers,uint32_t minbuyin,uint32_t maxbuyin,cJSON *json)
{
char destNXT[64]; struct pangea_thread *tp; struct cards777_pubdata *dp;
int32_t createdflag,addrtype,haspubkey,i,j,slot,n,myind=-1,r,num=0,threadid=0; uint64_t addrs[512],isbot[512],tmp;
uint8_t p2shtype; struct pangea_info *sp; cJSON *bids,*walletitem,*item;
memset(addrs,0,sizeof(addrs));
PostMessage("pangea_start rakemillis.%d\n",hostrake);
//memset(balances,0,sizeof(balances));
pangea_buyins(&minbuyin,&maxbuyin);
if ( hostrake < 0 || hostrake > PANGEA_MAX_HOSTRAKE )
{
PostMessage("illegal hostrake.%d\n",hostrake);
strcpy(retbuf,"{\"error\":\"illegal hostrake\"}");
return(-1);
}
if ( bigblind == 0 )
bigblind = SATOSHIDEN;
if ( (tp= THREADS[threadid]) == 0 )
{
pangea_threadinit(plugin,maxplayers);
if ( (tp=THREADS[0]) == 0 )
{
strcpy(retbuf,"{\"error\":\"uinitialized threadid\"}");
PostMessage("%s\n",retbuf);
return(-1);
}
}
PostMessage("mynxt64bits.%llu base.(%s) maxplayers.%d minbuyin.%u maxbuyin.%u\n",(long long)tp->nxt64bits,base,maxplayers,minbuyin,maxbuyin);
if ( base == 0 || base[0] == 0 || maxplayers < 2 || maxplayers > CARDS777_MAXPLAYERS )
{
sprintf(retbuf,"{\"error\":\"bad params\"}");
PostMessage("%s\n",retbuf);
return(-1);
}
addrtype = coin777_addrtype(&p2shtype,base);
if ( (bids= jarray(&n,json,"bids")) != 0 )
{
PostMessage("numbids.%d\n",n);
for (i=num=0; i<n; i++)
{
item = jitem(bids,i);
if ( (addrs[num]= j64bits(item,"offerNXT")) != 0 && (walletitem= jobj(item,"wallet")) != 0 )
{
if ( j64bits(walletitem,"bigblind") == bigblind && j64bits(walletitem,"ante") == ante && juint(walletitem,"rakemillis") == hostrake )
{
//balances[num] = j64bits(walletitem,"balance");
isbot[num] = juint(walletitem,"isbot");
PostMessage("(i.%d %llu) ",i,(long long)addrs[num]);//,dstr(balances[num]));
for (j=0; j<num; j++)
if ( addrs[j] == addrs[num] )
break;
if ( j == num )
{
if ( addrs[num] == tp->nxt64bits )
myind = num;
PostMessage("%llu ",(long long)addrs[num]);
num++;
}
}
else PostMessage("%d: %llu mismatched walletitem bigblind %.8f ante %.8f rake %.1f%%\n",i,(long long)addrs[num],dstr(j64bits(walletitem,"bigblind")),dstr(j64bits(walletitem,"ante")),(double)juint(walletitem,"rakemillis")/10.);
}
}
}
PostMessage("(%llu) pangea_start(%s) threadid.%d myind.%d num.%d maxplayers.%d\n",(long long)tp->nxt64bits,base,tp->threadid,myind,num,maxplayers);
if ( (i= myind) > 0 )
{
addrs[i] = addrs[0];
addrs[0] = tp->nxt64bits;
//tmp = balances[i];
//balances[i] = balances[0];
//balances[0] = tmp;
tmp = isbot[i];
isbot[i] = isbot[0];
isbot[0] = tmp;
i = 0;
strcpy(retbuf,"{\"error\":\"host needs to be locally started and the first entry in addrs\"}");
return(-1);
}
while ( num > maxplayers )
{
r = (rand() % (num-1));
PostMessage("swap out %d of %d\n",r+1,num);
num--;
isbot[r + 1] = isbot[num];
//balances[r + 1] = balances[num];
addrs[r + 1] = addrs[num];
}
PostMessage("pangea numplayers.%d\n",num);
if ( (sp= pangea_create(tp,&createdflag,base,timestamp,addrs,num,bigblind,ante,isbot,minbuyin,maxbuyin,hostrake)) == 0 )
{
PostMessage("cant create table.(%s) numaddrs.%d\n",base,num);
strcpy(retbuf,"{\"error\":\"cant create table, make sure all players have published NXT pubkeys\"}");
return(-1);
}
PostMessage("back from pangea_create\n");
dp = sp->dp, dp->table = sp;
sp->myslot = sp->myind = myind;
if ( createdflag != 0 && myind == 0 && addrs[myind] == tp->nxt64bits )
{
tp->numcards = dp->numcards, tp->N = dp->N, tp->M = dp->M;
PostMessage("myind.%d: hostrake.%d\n",myind,dp->rakemillis);
dp->minbuyin = minbuyin, dp->maxbuyin = maxbuyin;
tp->hn.server->clients[myind].pubdata = dp;
tp->hn.server->clients[myind].privdata = sp->priv;
tp->hn.server->H.pubdata = dp;
tp->hn.server->H.privdata = sp->priv;
for (j=0; j<dp->N; j++)
{
if ( THREADS[j] != 0 )
sp->playerpubs[j] = THREADS[j]->hn.client->H.pubkey;
else
{
expand_nxt64bits(destNXT,addrs[j]);
sp->playerpubs[j] = issue_getpubkey(&haspubkey,destNXT);
if ( (slot= hostnet777_register(THREADS[0]->hn.server,sp->playerpubs[j],-1)) != j )
PostMessage("unexpected register slot.%d for j.%d\n",slot,j);
}
//PostMessage("thread[%d] pub.%llx priv.%llx\n",j,(long long)dp->playerpubs[j].txid,(long long)THREADS[j]->hn.client->H.privkey.txid);
}
pangea_create_newtable(retbuf,sp,dp,isbot);
#ifdef BUNDLED
if ( 1 )
{
char *busdata_sync(uint32_t *noncep,char *jsonstr,char *broadcastmode,char *destNXTaddr);
char *str; uint32_t nonce;
if ( (str= busdata_sync(&nonce,retbuf,"allnodes",0)) != 0 )
free(str);
}
#endif
}
return(0);
}
char *pangea_history(uint64_t my64bits,uint64_t tableid,cJSON *json)
{
struct pangea_info *sp;
if ( (sp= pangea_find64(tableid,my64bits)) != 0 && sp->dp != 0 )
{
if ( jobj(json,"handid") == 0 )
return(pangea_dispsummary(sp,juint(json,"verbose"),sp->dp->summary,sp->dp->summarysize,tableid,sp->dp->numhands-1,sp->dp->N));
else return(pangea_dispsummary(sp,juint(json,"verbose"),sp->dp->summary,sp->dp->summarysize,tableid,juint(json,"handid"),sp->dp->N));
}
return(clonestr("{\"error\":\"cant find tableid\"}"));
}
char *pangea_buyin(uint64_t my64bits,uint64_t tableid,cJSON *json)
{
struct pangea_info *sp; uint32_t buyin,vout; uint64_t amount = 0; char hex[1024],jsonstr[1024],*txidstr,*destaddr;
if ( (sp= pangea_find64(tableid,my64bits)) != 0 && sp->dp != 0 && sp->tp != 0 && (amount= j64bits(json,"amount")) != 0 )
{
buyin = (uint32_t)(amount / sp->dp->bigblind);
PostMessage("buyin.%u amount %.8f -> %.8f\n",buyin,dstr(amount),dstr(buyin * sp->bigblind));
if ( buyin >= sp->dp->minbuyin && buyin <= sp->dp->maxbuyin )
{
sp->balances[pangea_ind(sp,sp->myslot)] = amount;
if ( (txidstr= jstr(json,"txidstr")) != 0 && (destaddr= jstr(json,"msigaddr")) != 0 && strcmp(destaddr,sp->multisigaddr) == 0 )
{
vout = juint(json,"vout");
sprintf(jsonstr,"{\"txid\":\"%s\",\"vout\":%u,\"msig\":\"%s\",\"amount\":%.8f}",txidstr,vout,sp->multisigaddr,dstr(amount));
pangea_sendcmd(hex,&sp->tp->hn,"addfunds",-1,(void *)jsonstr,(int32_t)strlen(jsonstr)+1,pangea_ind(sp,sp->myslot),-1);
} else pangea_sendcmd(hex,&sp->tp->hn,"addfunds",-1,(void *)&amount,sizeof(amount),pangea_ind(sp,sp->myslot),-1);
//pangea_sendcmd(hex,&sp->tp->hn,"addfunds",0,(void *)&amount,sizeof(amount),pangea_ind(sp,sp->myslot),-1);
return(clonestr("{\"result\":\"buyin sent\"}"));
}
else
{
PostMessage("buyin.%d vs (%d %d)\n",buyin,sp->dp->minbuyin,sp->dp->maxbuyin);
return(clonestr("{\"error\":\"buyin too small or too big\"}"));
}
}
return(clonestr("{\"error\":\"cant buyin unless you are part of the table\"}"));
}
char *pangea_mode(uint64_t my64bits,uint64_t tableid,cJSON *json)
{
struct pangea_info *sp; char *chatstr,hex[8192]; int32_t i; uint64_t pm;
if ( jobj(json,"automuck") != 0 )
{
if ( tableid == 0 )
Showmode = juint(json,"automuck");
else if ( (sp= pangea_find64(tableid,my64bits)) != 0 && sp->priv != 0 )
sp->priv->automuck = juint(json,"automuck");
else return(clonestr("{\"error\":\"automuck not tableid or sp->priv\"}"));
return(clonestr("{\"result\":\"set automuck mode\"}"));
}
else if ( jobj(json,"autofold") != 0 )
{
if ( tableid == 0 )
Autofold = juint(json,"autofold");
else if ( (sp= pangea_find64(tableid,my64bits)) != 0 && sp->priv != 0 )
sp->priv->autofold = juint(json,"autofold");
else return(clonestr("{\"error\":\"autofold not tableid or sp->priv\"}"));
return(clonestr("{\"result\":\"set autofold mode\"}"));
}
else if ( (sp= pangea_find64(tableid,my64bits)) != 0 && (chatstr= jstr(json,"chat")) != 0 && strlen(chatstr) < 256 )
{
if ( 0 && (pm= j64bits(json,"pm")) != 0 )
{
for (i=0; i<sp->numaddrs; i++)
if ( sp->addrs[i] == pm )
break;
if ( i == sp->numaddrs )
return(clonestr("{\"error\":\"specified pm destination not at table\"}"));
} else i = -1;
pangea_sendcmd(hex,&sp->tp->hn,"chat",i,(void *)chatstr,(int32_t)strlen(chatstr)+1,pangea_ind(sp,sp->myslot),-1);
return(clonestr("{\"result\":\"chat message sent\"}"));
}
return(clonestr("{\"error\":\"unknown pangea mode\"}"));
}
char *pangea_univ(uint8_t *mypriv,cJSON *json)
{
char *addrtypes[][3] = { {"BTC","0","80"}, {"LTC","48"}, {"BTCD","60","bc"}, {"DOGE","30"}, {"VRC","70"}, {"OPAL","115"}, {"BITS","25"} };
char *wipstr,*coin,*coinaddr,pubkeystr[67],rsaddr[64],destaddr[64],wifbuf[128]; uint8_t priv[32],pub[33],addrtype; int32_t i;
uint64_t nxt64bits; cJSON *retjson,*item;
PostMessage("inside rosetta\n");
if ( (coin= jstr(json,"coin")) != 0 )
{
if ( (wipstr= jstr(json,"wif")) != 0 || (wipstr= jstr(json,"wip")) != 0 )
{
PostMessage("got wip.(%s)\n",wipstr);
btc_wip2priv(priv,wipstr);
}
else if ( (coinaddr= jstr(json,"addr")) != 0 )
{
if ( getprivkey(priv,coin,coinaddr) < 0 )
return(clonestr("{\"error\":\"cant get privkey\"}"));
}
} else memcpy(priv,mypriv,sizeof(priv));
btc_priv2pub(pub,priv);
init_hexbytes_noT(pubkeystr,pub,33);
PostMessage("pubkey.%s\n",pubkeystr);
retjson = cJSON_CreateObject();
jaddstr(retjson,"btcpubkey",pubkeystr);
for (i=0; i<sizeof(addrtypes)/sizeof(*addrtypes); i++)
{
if ( btc_coinaddr(destaddr,atoi(addrtypes[i][1]),pubkeystr) == 0 )
{
item = cJSON_CreateObject();
jaddstr(item,"addr",destaddr);
if ( addrtypes[i][2] != 0 )
{
decode_hex(&addrtype,1,addrtypes[i][2]);
btc_priv2wip(wifbuf,priv,addrtype);
jaddstr(item,"wif",wifbuf);
}
jadd(retjson,addrtypes[i][0],item);
}
}
nxt64bits = nxt_priv2addr(rsaddr,pubkeystr,priv);
item = cJSON_CreateObject();
jaddstr(item,"addressRS",rsaddr);
jadd64bits(item,"address",nxt64bits);
jaddstr(item,"pubkey",pubkeystr);
jadd(retjson,"NXT",item);
return(jprint(retjson,1));
}
void pangea_test(struct plugin_info *plugin)//,int32_t numthreads,int64_t bigblind,int64_t ante,int32_t rakemillis)
{
char retbuf[65536]; bits256 privkey,pubkey; int32_t i,slot,threadid; struct pangea_thread *tp; struct hostnet777_client **clients;
struct hostnet777_server *srv=0; cJSON *item,*bids,*walletitem,*testjson = cJSON_CreateObject();
//msleep(5000);
int32_t numthreads; int64_t bigblind,ante; int32_t rakemillis;
numthreads = 9; bigblind = SATOSHIDEN; ante = 0*SATOSHIDEN/10; rakemillis = PANGEA_MAX_HOSTRAKE;
//plugin->sleepmillis = 1;
//if ( PANGEA_MAXTHREADS > 1 && PANGEA_MAXTHREADS <= 9 )
// numthreads = PANGEA_MAXTHREADS;
//else
PostMessage("pangeatest\n");
if ( PANGEA_MAXTHREADS == 0 )
PANGEA_MAXTHREADS = numthreads;
else numthreads = PANGEA_MAXTHREADS;
if ( plugin->transport[0] == 0 )
strcpy(plugin->transport,TEST_TRANSPORT);
if ( plugin->ipaddr[0] == 0 )
strcpy(plugin->ipaddr,"127.0.0.1");
if ( plugin->pangeaport == 0 )
plugin->pangeaport = 12343;
PostMessage("pangea numthreads.%d\n",numthreads);
if ( (clients= calloc(numthreads,sizeof(*clients))) == 0 )
{
PostMessage("pangea_test: unexpected out of mem\n");
return;
}
for (threadid=0; threadid<PANGEA_MAXTHREADS; threadid++)
{
if ( (tp= calloc(1,sizeof(*THREADS[threadid]))) == 0 )
{
PostMessage("pangea_test: unexpected out of mem\n");
free(clients);
return;
}
tp->threadid = threadid;
if ( threadid != 0 )
{
char hexstr[65]; uint32_t tmp = threadid + 4;
tp->nxt64bits = conv_NXTpassword(privkey.bytes,pubkey.bytes,(void *)&tmp,sizeof(tmp));
init_hexbytes_noT(hexstr,pubkey.bytes,sizeof(pubkey));
printf("NXT.%llu pubkey.%s\n",(long long)tp->nxt64bits,hexstr);
}
else
{
tp->nxt64bits = plugin->nxt64bits;
memcpy(privkey.bytes,plugin->mypriv,32);
memcpy(pubkey.bytes,plugin->mypub,32);
}
if ( threadid == 0 )
{
if ( (srv= hostnet777_server(privkey,pubkey,0,0,0,numthreads)) == 0 )
{
PostMessage("cant create hostnet777 server\n");
free(tp);
return;
}
tp->hn.server = srv;
clients[0] = (void *)srv;
slot = threadid;
// srv->H.privkey = privkey, srv->H.pubkey = pubkey;
}
else
{
if ( (slot= hostnet777_register(srv,pubkey,-1)) >= 0 && slot == threadid )
{
if ( (clients[threadid]= hostnet777_client(privkey,pubkey,srv->ep.endpoint,slot)) == 0 )
PostMessage("error creating clients[%d]\n",threadid);
else
{
tp->hn.client = clients[threadid];
//tp->hn.client->H.privkey = privkey, tp->hn.client->H.pubkey = pubkey;
//if ( portable_thread_create((void *)hostnet777_idler,hn) == 0 )
// PostMessage("error launching clients[%d] thread\n",threadid);
}
} else PostMessage("error slot.%d != threadid.%d\n",slot,threadid);
}
if ( clients[threadid] != 0 )
PostMessage("%llu: slot.%d client.%p -> %llu pubkey.%llx/%llx privkey.%llx/%llx\n",(long long)tp->nxt64bits,slot,clients[threadid],(long long)clients[threadid]->H.nxt64bits,(long long)clients[threadid]->H.pubkey.txid,(long long)pubkey.txid,(long long)clients[threadid]->H.privkey.txid,(long long)privkey.txid);
THREADS[threadid] = tp;
}
bids = cJSON_CreateArray();
PostMessage("numthreads.%d notabot.%d\n",numthreads,plugin->notabot);//, getchar();
for (i=0; i<numthreads; i++)
{
item = cJSON_CreateObject();
walletitem = cJSON_CreateObject();
if ( plugin->notabot != numthreads )
{
if ( i != plugin->notabot )
jaddnum(walletitem,"isbot",1);
}
jadd64bits(walletitem,"bigblind",bigblind);
jadd64bits(walletitem,"ante",ante);
jaddnum(walletitem,"rakemillis",rakemillis);
//jadd64bits(walletitem,"balance",bigblind * 100);
jadd64bits(item,"offerNXT",THREADS[i]->nxt64bits);
jadd(item,"wallet",walletitem);
jaddi(bids,item);
}
jadd(testjson,"bids",bids);
jadd64bits(testjson,"offerNXT",THREADS[0]->nxt64bits);
jadd64bits(testjson,"bigblind",bigblind);
jadd64bits(testjson,"ante",ante);
jaddnum(testjson,"rakemillis",rakemillis);
PostMessage("TEST.(%s)\n",jprint(testjson,0));
pangea_start(plugin,retbuf,"BTCD",0,bigblind,ante,rakemillis,i,0,0,testjson);
free_json(testjson);
testjson = cJSON_Parse(retbuf);
//PostMessage("BROADCAST.(%s)\n",retbuf);
for (threadid=1; threadid<numthreads; threadid++)
pangea_newtable(threadid,testjson,THREADS[threadid]->nxt64bits,THREADS[threadid]->hn.client->H.privkey,THREADS[threadid]->hn.client->H.pubkey,0,0,0,0,0,rakemillis);
for (threadid=0; threadid<numthreads; threadid++)
{
int32_t j; struct cards777_pubdata *dp; struct pangea_info *sp;
tp = THREADS[threadid];
dp = tp->hn.client->H.pubdata;
if ( (sp= dp->table) == 0 )
PostMessage("pangea_test: null table\n");
for (j=0; j<numthreads; j++)
sp->balances[j] = 1000 * SATOSHIDEN;
PostMessage("T%d: set balances sp.%p\n",threadid,sp);
}
//for (threadid=0; threadid<numthreads; threadid++)
// if ( portable_thread_create((void *)hostnet777_idler,&THREADS[threadid]->hn) == 0 )
// PostMessage("error launching server thread\n");
//tp = THREADS[0];
//pangea_newdeck(&tp->hn);
free(clients);
}
int32_t PLUGNAME(_process_json)(char *forwarder,char *sender,int32_t valid,struct plugin_info *plugin,uint64_t tag,char *retbuf,int32_t maxlen,char *jsonstr,cJSON *json,int32_t initflag,char *tokenstr)
{
char *resultstr,*methodstr,*base,*retstr = 0; int32_t maxplayers,tmp; cJSON *argjson;
retbuf[0] = 0;
PostMessage("<<<<<<<<<<<< INSIDE PANGEA! process %s (%s) forwarder.(%s) sender.(%s)\n",plugin->name,jsonstr,forwarder,sender);
if ( initflag > 0 )
{
randombytes((uint8_t *)&tmp,sizeof(tmp)), srand(tmp);
uint64_t conv_NXTpassword(unsigned char *mysecret,unsigned char *mypublic,uint8_t *pass,int32_t passlen);
//PANGEA.readyflag = 1;
plugin->sleepmillis = 10;
plugin->allowremote = 1;
argjson = cJSON_Parse(jsonstr);
plugin->nxt64bits = set_account_NXTSECRET(plugin->mypriv,plugin->mypub,plugin->NXTACCT,plugin->NXTADDR,plugin->NXTACCTSECRET,sizeof(plugin->NXTACCTSECRET),argjson,0,0,0);
free_json(argjson);
PostMessage("(%s) pangea.my64bits %llu ipaddr.%s mypriv.%02x mypub.%02x\n",jprint(json,0),(long long)plugin->nxt64bits,plugin->ipaddr,plugin->mypriv[0],plugin->mypub[0]);
PANGEA_MAXTHREADS = juint(json,"pangeatest");
plugin->notabot = juint(json,"notabot");
if ( PANGEA_MAXTHREADS != 0 )
{
PostMessage("notabot.%d launch pangea_test\n",plugin->notabot);
//pangea_test(plugin);
portable_thread_create((void *)pangea_test,plugin);//,9,SATOSHIDEN,SATOSHIDEN/10,10);
}
PostMessage("initialized PANGEA\n");
if ( 0 )
{
int32_t i; char str[8];
for (i=0; i<52; i++)
{
cardstr(str,i);
PostMessage("(%d %s) ",i,str);
}
PostMessage("cards\n");
}
}
else
{
if ( plugin_result(retbuf,json,tag) > 0 )
return((int32_t)strlen(retbuf));
methodstr = jstr(json,"method");
resultstr = jstr(json,"result");
if ( methodstr == 0 || methodstr[0] == 0 )
{
PostMessage("(%s) has not method\n",jsonstr);
return(0);
}
else if ( resultstr != 0 && strcmp(resultstr,"registered") == 0 )
{
plugin->registered = 1;
strcpy(retbuf,"{\"result\":\"activated\"}");
}
else if ( strcmp(methodstr,"newtable") == 0 )
retstr = pangea_newtable(juint(json,"threadid"),json,plugin->nxt64bits,*(bits256 *)plugin->mypriv,*(bits256 *)plugin->mypub,plugin->transport,plugin->ipaddr,plugin->pangeaport,juint(json,"minbuyin"),juint(json,"maxbuyin"),juint(json,"rakemillis"));
else if ( sender == 0 || sender[0] == 0 )
{
if ( strcmp(methodstr,"start") == 0 )
{
strcpy(retbuf,"{\"result\":\"start issued\"}");
if ( (base= jstr(json,"base")) != 0 )
{
if ( (maxplayers= juint(json,"maxplayers")) < 2 )
maxplayers = 2;
else if ( maxplayers > CARDS777_MAXPLAYERS )
maxplayers = CARDS777_MAXPLAYERS;
if ( jstr(json,"resubmit") == 0 )
sprintf(retbuf,"{\"resubmit\":[{\"method\":\"start\"}, {\"bigblind\":\"%llu\"}, {\"ante\":\"%llu\"}, {\"rakemillis\":\"%u\"}, {\"maxplayers\":%d}, {\"minbuyin\":%d}, {\"maxbuyin\":%d}],\"pluginrequest\":\"SuperNET\",\"plugin\":\"InstantDEX\",\"method\":\"orderbook\",\"base\":\"%s\",\"exchange\":\"pangea\",\"allfields\":1}",(long long)j64bits(json,"bigblind"),(long long)j64bits(json,"ante"),juint(json,"rakemillis"),maxplayers,juint(json,"minbuyin"),juint(json,"maxbuyin"),jstr(json,"base")!=0?jstr(json,"base"):"BTCD");
else if ( pangea_start(plugin,retbuf,base,0,j64bits(json,"bigblind"),j64bits(json,"ante"),juint(json,"rakemillis"),maxplayers,juint(json,"minbuyin"),juint(json,"maxbuyin"),json) < 0 )
;
} else strcpy(retbuf,"{\"error\":\"no base specified\"}");
}
else if ( strcmp(methodstr,"status") == 0 )
retstr = pangea_status(plugin->nxt64bits,j64bits(json,"tableid"),json);
}
//else if ( strcmp(methodstr,"turn") == 0 )
// retstr = pangea_input(plugin->nxt64bits,j64bits(json,"tableid"),json);
}
return(plugin_copyretstr(retbuf,maxlen,retstr));
}
char *Pangea_bypass(uint64_t my64bits,uint8_t myprivkey[32],cJSON *json)
{
char *methodstr,*passphrase,*retstr = 0;
if ( (methodstr= jstr(json,"method")) != 0 )
{
if ( strcmp(methodstr,"turn") == 0 )
retstr = pangea_input(my64bits,j64bits(json,"tableid"),json);
else if ( strcmp(methodstr,"status") == 0 )
retstr = pangea_status(my64bits,j64bits(json,"tableid"),json);
else if ( strcmp(methodstr,"mode") == 0 )
retstr = pangea_mode(my64bits,j64bits(json,"tableid"),json);
else if ( strcmp(methodstr,"rosetta") == 0 )
retstr = pangea_univ(myprivkey,json);
else if ( strcmp(methodstr,"buyin") == 0 )
retstr = pangea_buyin(my64bits,j64bits(json,"tableid"),json);
else if ( strcmp(methodstr,"history") == 0 )
retstr = pangea_history(my64bits,j64bits(json,"tableid"),json);
else if ( strcmp(methodstr,"rates") == 0 )
retstr = peggyrates(0,jstr(json,"name"));
else if ( strcmp(methodstr,"pangeatest") == 0 )
{
int32_t n;
n = juint(json,"numplayers");
if ( n >= 2 && n <= 9 )
retstr = SuperNET_setconf(methodstr,n);
else return(clonestr("{\"error\":\"invalid numplayers\"}"));
}
else if ( strcmp(methodstr,"changenum") == 0 )
{
char *fieldstr;
if ( (fieldstr= jstr(json,"fieldname")) != 0 )
retstr = SuperNET_setconf(fieldstr,juint(json,"val"));
else return(clonestr("{\"error\":\"no fieldname\"}"));
}
else if ( strcmp(methodstr,"changefield") == 0 )
{
char *fieldstr;
if ( (fieldstr= jstr(json,"fieldname")) != 0 )
retstr = SuperNET_setconfstr(fieldstr,jstr(json,"valstr"));
else return(clonestr("{\"error\":\"no fieldname\"}"));
}
else if ( strcmp(methodstr,"notabot") == 0 )
{
int32_t n;
n = juint(json,"val");
if ( n == 0 || n == -1 )
retstr = SuperNET_setconf(methodstr,n);
else return(clonestr("{\"error\":\"invalid notabot\"}"));
}
else if ( strcmp(methodstr,"clearconf") == 0 )
{
if ( SuperNET_saveconf("{\"secret\":\"randvals\"}") == 0 )
return(clonestr("{\"result\":\"SuperNET.conf restored to defaults\"}"));
else return(clonestr("{\"error\":\"SuperNET.conf couldnt be cleared\"}"));
}
else if ( strcmp(methodstr,"secret") == 0 && (passphrase= jstr(json,"passphrase")) != 0 )
{
char buf[1024],rsaddr[64]; uint64_t nxt64bits; bits256 pubkey,privkey;
sprintf(buf,"{\"secret\":\"%s\"}",passphrase);
if ( SuperNET_saveconf(buf) == 0 )
{
nxt64bits = conv_NXTpassword(privkey.bytes,pubkey.bytes,(void *)passphrase,(int32_t)strlen(passphrase));
RS_encode(rsaddr,nxt64bits);
sprintf(buf,"{\"result\":\"success\",\"NXT\":\"%llu\",\"RS\":\"%s\"}",(long long)nxt64bits,rsaddr);
return(clonestr(buf));
}
else return(clonestr("{\"error\":\"couldnt sent new passphrase\"}"));
}
}
// ./BitcoinDarkd SuperNET '{"agent":"pangea","method":"pangeatest","numplayers":2}'
// ./BitcoinDarkd SuperNET '{"agent":"pangea","method":"notabot","val":-1}'
// ./BitcoinDarkd SuperNET '{"agent":"pangea","method":"clearconf"}'
// ./BitcoinDarkd SuperNET '{"agent":"pangea","method":"secret","passphrase":"password"}'
return(retstr);
}
#endif