From 53473691ecedb8f43286612ccc19d86c7ed98314 Mon Sep 17 00:00:00 2001 From: jl777 Date: Tue, 19 Jan 2016 22:02:21 -0300 Subject: [PATCH] pin --- InstantDEX/InstantDEX.c | 2 +- InstantDEX/exchange_trades.h | 2 +- InstantDEX/exchangeparse.h | 2 +- InstantDEX/exchanges/bitfinex.c | 2 +- InstantDEX/exchanges/bitstamp.c | 2 +- InstantDEX/exchanges/bittrex.c | 2 +- InstantDEX/exchanges/btc38.c | 2 +- InstantDEX/exchanges/btce.c | 2 +- InstantDEX/exchanges/coinbase.c | 2 +- InstantDEX/exchanges/huobi.c | 2 +- InstantDEX/exchanges/lakebtc.c | 2 +- InstantDEX/exchanges/okcoin.c | 2 +- InstantDEX/exchanges/poloniex.c | 2 +- InstantDEX/exchanges/quadriga.c | 2 +- InstantDEX/orderbooks.h | 2 +- crypto777/OS_nonportable.c | 2 +- crypto777/OS_portable.c | 2 +- crypto777/OS_portable.h | 4 +- crypto777/OS_time.c | 2 +- crypto777/SaM.c | 2 +- crypto777/bitcoind_RPC.c | 31 +- crypto777/cJSON.c | 2 +- crypto777/curve25519.c | 2 +- crypto777/iguana_OS.c | 2 +- crypto777/iguana_serdes.c | 2 +- crypto777/iguana_utils.c | 2 +- crypto777/ramcoder.c | 2 +- crypto777/tweetnacl.c | 5 + iguana/SuperNET.c | 478 ++++++++++- iguana/SuperNET.h | 3 +- iguana/cards777.c | 526 ++++++++++++ iguana/iguana.sources | 2 +- iguana/iguana777.c | 2 +- iguana/iguana777.h | 3 +- iguana/iguana_accept.c | 2 +- iguana/iguana_bitmap.c | 2 +- iguana/iguana_blocks.c | 2 +- iguana/iguana_bundles.c | 2 +- iguana/iguana_chains.c | 2 +- iguana/iguana_html.c | 2 +- iguana/iguana_init.c | 2 +- iguana/iguana_json.c | 155 +--- iguana/iguana_msg.c | 2 +- iguana/iguana_peers.c | 2 +- iguana/iguana_pubkeys.c | 2 +- iguana/iguana_ramchain.c | 2 +- iguana/iguana_recv.c | 2 +- iguana/iguana_rpc.c | 2 +- iguana/iguana_tx.c | 2 +- iguana/iguana_wallet.c | 2 +- iguana/main.c | 3 +- iguana/pangea777.h | 189 ++++ iguana/pangea_api.c | 594 +++++++++++++ iguana/pangea_fsm.c | 1420 +++++++++++++++++++++++++++++++ iguana/pangea_funds.c | 970 +++++++++++++++++++++ iguana/pangea_init.c | 487 +++++++++++ iguana/pangea_network.c | 435 ++++++++++ iguana/poker.c | 644 ++++++++++++++ iguana/ramchain_api.c | 2 +- includes/iguana_api.h | 2 +- includes/iguana_apideclares.h | 52 +- includes/iguana_apidefs.h | 8 + includes/iguana_apiundefs.h | 6 + includes/tweetnacl.h | 3 + 64 files changed, 5877 insertions(+), 227 deletions(-) create mode 100755 iguana/cards777.c create mode 100755 iguana/pangea777.h create mode 100755 iguana/pangea_api.c create mode 100755 iguana/pangea_fsm.c create mode 100755 iguana/pangea_funds.c create mode 100755 iguana/pangea_init.c create mode 100755 iguana/pangea_network.c create mode 100755 iguana/poker.c diff --git a/InstantDEX/InstantDEX.c b/InstantDEX/InstantDEX.c index 4828f96d4..49282dcbf 100755 --- a/InstantDEX/InstantDEX.c +++ b/InstantDEX/InstantDEX.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/InstantDEX/exchange_trades.h b/InstantDEX/exchange_trades.h index a84785b34..f1e750ec4 100755 --- a/InstantDEX/exchange_trades.h +++ b/InstantDEX/exchange_trades.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/InstantDEX/exchangeparse.h b/InstantDEX/exchangeparse.h index 1e301cdb2..1f1193867 100755 --- a/InstantDEX/exchangeparse.h +++ b/InstantDEX/exchangeparse.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/InstantDEX/exchanges/bitfinex.c b/InstantDEX/exchanges/bitfinex.c index 7eb43cf1d..2cbcf7f55 100755 --- a/InstantDEX/exchanges/bitfinex.c +++ b/InstantDEX/exchanges/bitfinex.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/InstantDEX/exchanges/bitstamp.c b/InstantDEX/exchanges/bitstamp.c index e27700153..be7f6f10c 100755 --- a/InstantDEX/exchanges/bitstamp.c +++ b/InstantDEX/exchanges/bitstamp.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/InstantDEX/exchanges/bittrex.c b/InstantDEX/exchanges/bittrex.c index 807f69566..ce6ad3695 100755 --- a/InstantDEX/exchanges/bittrex.c +++ b/InstantDEX/exchanges/bittrex.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/InstantDEX/exchanges/btc38.c b/InstantDEX/exchanges/btc38.c index 9dabb495a..a9dd3c38b 100755 --- a/InstantDEX/exchanges/btc38.c +++ b/InstantDEX/exchanges/btc38.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/InstantDEX/exchanges/btce.c b/InstantDEX/exchanges/btce.c index 6ef9adeb8..6454439e6 100755 --- a/InstantDEX/exchanges/btce.c +++ b/InstantDEX/exchanges/btce.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/InstantDEX/exchanges/coinbase.c b/InstantDEX/exchanges/coinbase.c index 65d07c382..b9ac404bf 100755 --- a/InstantDEX/exchanges/coinbase.c +++ b/InstantDEX/exchanges/coinbase.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/InstantDEX/exchanges/huobi.c b/InstantDEX/exchanges/huobi.c index 5e8b856f2..6918ccd37 100755 --- a/InstantDEX/exchanges/huobi.c +++ b/InstantDEX/exchanges/huobi.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/InstantDEX/exchanges/lakebtc.c b/InstantDEX/exchanges/lakebtc.c index 3c45366e2..2b9bf7e31 100755 --- a/InstantDEX/exchanges/lakebtc.c +++ b/InstantDEX/exchanges/lakebtc.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/InstantDEX/exchanges/okcoin.c b/InstantDEX/exchanges/okcoin.c index 5b3376abc..9d49d85d2 100755 --- a/InstantDEX/exchanges/okcoin.c +++ b/InstantDEX/exchanges/okcoin.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/InstantDEX/exchanges/poloniex.c b/InstantDEX/exchanges/poloniex.c index da01fc290..1ecc10a87 100755 --- a/InstantDEX/exchanges/poloniex.c +++ b/InstantDEX/exchanges/poloniex.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/InstantDEX/exchanges/quadriga.c b/InstantDEX/exchanges/quadriga.c index 8d5716e3d..c320f759d 100755 --- a/InstantDEX/exchanges/quadriga.c +++ b/InstantDEX/exchanges/quadriga.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/InstantDEX/orderbooks.h b/InstantDEX/orderbooks.h index cfd2c51b4..e669f6410 100755 --- a/InstantDEX/orderbooks.h +++ b/InstantDEX/orderbooks.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/crypto777/OS_nonportable.c b/crypto777/OS_nonportable.c index 4fab475d4..42cabd876 100755 --- a/crypto777/OS_nonportable.c +++ b/crypto777/OS_nonportable.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/crypto777/OS_portable.c b/crypto777/OS_portable.c index 5b3db5c1a..5c3d879bc 100755 --- a/crypto777/OS_portable.c +++ b/crypto777/OS_portable.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/crypto777/OS_portable.h b/crypto777/OS_portable.h index 45cb63a89..d92b66ca4 100755 --- a/crypto777/OS_portable.h +++ b/crypto777/OS_portable.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -243,6 +243,7 @@ void reverse_hexstr(char *str); int32_t init_hexbytes_noT(char *hexbytes,uint8_t *message,long len); uint16_t parse_ipaddr(char *ipaddr,char *ip_port); int32_t bitweight(uint64_t x); +unsigned char _decode_hex(char *hex); long _stripwhite(char *buf,int accept); int32_t is_DST(int32_t datenum); @@ -335,6 +336,7 @@ int32_t btc_priv2pub(uint8_t pubkey[33],uint8_t privkey[32]); extern char *Iguana_validcommands[]; extern bits256 GENESIS_PUBKEY,GENESIS_PRIVKEY; +extern char NXTAPIURL[]; #endif diff --git a/crypto777/OS_time.c b/crypto777/OS_time.c index 49113bff9..c685a38cd 100755 --- a/crypto777/OS_time.c +++ b/crypto777/OS_time.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/crypto777/SaM.c b/crypto777/SaM.c index cf6b66dea..0f5d42a75 100755 --- a/crypto777/SaM.c +++ b/crypto777/SaM.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/crypto777/bitcoind_RPC.c b/crypto777/bitcoind_RPC.c index 2e38a5884..e64521a40 100755 --- a/crypto777/bitcoind_RPC.c +++ b/crypto777/bitcoind_RPC.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -18,6 +18,7 @@ #include #include +#define issue_curl(cmdstr) bitcoind_RPC(0,"curl",cmdstr,0,0,0) // return data from the server struct return_string { @@ -339,3 +340,31 @@ void curlhandle_free(void *curlhandle) { curl_easy_cleanup(curlhandle); } + +bits256 issue_getpubkey(int32_t *haspubkeyp,char *acct) +{ + cJSON *json; bits256 pubkey; char cmd[4096],*jsonstr; struct destbuf pubkeystr; + sprintf(cmd,"%s?requestType=getAccountPublicKey&account=%s",NXTAPIURL,acct); + jsonstr = issue_curl(cmd); + pubkeystr.buf[0] = 0; + if ( haspubkeyp != 0 ) + *haspubkeyp = 0; + memset(&pubkey,0,sizeof(pubkey)); + if ( jsonstr != 0 ) + { + printf("PUBKEYRPC.(%s)\n",jsonstr); + if ( (json = cJSON_Parse(jsonstr)) != 0 ) + { + copy_cJSON(&pubkeystr,cJSON_GetObjectItem(json,"publicKey")); + free_json(json); + if ( strlen(pubkeystr.buf) == sizeof(pubkey)*2 ) + { + if ( haspubkeyp != 0 ) + *haspubkeyp = 1; + decode_hex(pubkey.bytes,sizeof(pubkey),pubkeystr.buf); + } + } + free(jsonstr); + } + return(pubkey); +} diff --git a/crypto777/cJSON.c b/crypto777/cJSON.c index dd5dfef24..960250d72 100755 --- a/crypto777/cJSON.c +++ b/crypto777/cJSON.c @@ -616,7 +616,7 @@ void cJSON_Minify(char *json) // the following written by jl777 /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/crypto777/curve25519.c b/crypto777/curve25519.c index 914e315ed..080bc72fd 100755 --- a/crypto777/curve25519.c +++ b/crypto777/curve25519.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/crypto777/iguana_OS.c b/crypto777/iguana_OS.c index 74566a50f..03d524ce9 100755 --- a/crypto777/iguana_OS.c +++ b/crypto777/iguana_OS.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/crypto777/iguana_serdes.c b/crypto777/iguana_serdes.c index 6e4628e0c..38aad09a7 100755 --- a/crypto777/iguana_serdes.c +++ b/crypto777/iguana_serdes.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/crypto777/iguana_utils.c b/crypto777/iguana_utils.c index e2ec96f91..461425b88 100755 --- a/crypto777/iguana_utils.c +++ b/crypto777/iguana_utils.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/crypto777/ramcoder.c b/crypto777/ramcoder.c index 9e6d876c3..d495914de 100755 --- a/crypto777/ramcoder.c +++ b/crypto777/ramcoder.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/crypto777/tweetnacl.c b/crypto777/tweetnacl.c index a143a1444..cd750b477 100755 --- a/crypto777/tweetnacl.c +++ b/crypto777/tweetnacl.c @@ -456,6 +456,11 @@ int crypto_box_keypair(u8 *y,u8 *x) return crypto_scalarmult_base(y,x); } +int crypto_box_priv2pub(u8 *y,u8 *x) +{ + return crypto_scalarmult_base(y,x); +} + int crypto_box_beforenm(u8 *k,const u8 *y,const u8 *x) { u8 s[32]; diff --git a/iguana/SuperNET.c b/iguana/SuperNET.c index 98608f54e..0a972ccf3 100644 --- a/iguana/SuperNET.c +++ b/iguana/SuperNET.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -134,6 +134,24 @@ int32_t SuperNET_serialize(int32_t reverse,bits256 *senderpubp,uint64_t *senderb return((int32_t)extra); } +int32_t SuperNET_decode(uint64_t *senderbitsp,bits256 *sigp,uint32_t *timestampp,uint64_t *destbitsp,uint8_t *str,uint8_t *cipher,int32_t *lenp,uint8_t *myprivkey) +{ + bits256 srcpubkey; uint8_t *nonce; int i,hdrlen,err=0,len = *lenp; + hdrlen = SuperNET_serialize(1,&srcpubkey,senderbitsp,sigp,timestampp,destbitsp,cipher); + cipher += hdrlen, len -= hdrlen; + if ( *destbitsp != 0 && *senderbitsp != 0 ) + { + nonce = cipher; + cipher += crypto_box_NONCEBYTES, len -= crypto_box_NONCEBYTES; + printf("decode ptr.%p[%d]\n",cipher,len); + err = crypto_box_open((uint8_t *)str,cipher,len,nonce,srcpubkey.bytes,myprivkey); + for (i=0; i %llu)\n",newlen,(long long)senderbits,(long long)destbits); } } - } - else printf("%llu: SuperNET_decrypt skip: decode_cipher error len.%d -> newlen.%d\n",(long long)acct777_nxt64bits(mypub),len,newlen); + } else printf("%llu: SuperNET_decrypt skip: decode_cipher error len.%d -> newlen.%d\n",(long long)acct777_nxt64bits(mypub),len,newlen); free(buf); return(newlen); } @@ -270,7 +281,7 @@ int32_t SuperNET_sendmsg(struct supernet_info *myinfo,struct iguana_info *coin,s destbits = 0; destpub = GENESIS_PUBKEY; } - //printf("hostnet777_sendmsg dest.%llu destpub.%llx priv.%llx pub.%llx\n",(long long)destbits,(long long)destpub.txid,(long long)mypriv.txid,(long long)mypub.txid); + printf("SuperNET_sendmsg dest.%llu destpub.%llx priv.%llx pub.%llx\n",(long long)destbits,(long long)destpub.txid,(long long)mypriv.txid,(long long)mypub.txid); memset(&sig,0,sizeof(sig)); if ( mypub.txid == 0 || mypriv.txid == 0 ) mypriv = curve25519_keypair(&mypub), sig.timestamp = (uint32_t)time(NULL); @@ -323,7 +334,7 @@ int32_t SuperNET_json2bits(char *myipaddr,bits256 persistent_priv,bits256 persis checkc = SuperNET_checkc(persistent_priv,destpub,tag); len += iguana_rwnum(1,&serialized[len],sizeof(checkc),&checkc); agent = jstr(json,"agent"), method = jstr(json,"method"); - if ( strcmp(agent,"SuperNET") == 0 && strcmp(method,"json2bits") == 0 ) + if ( agent != 0 && method != 0 && strcmp(agent,"SuperNET") == 0 && strcmp(method,"json2bits") == 0 ) { agent = jstr(json,"destagent"); method = jstr(json,"destmethod"); @@ -346,9 +357,9 @@ int32_t SuperNET_json2bits(char *myipaddr,bits256 persistent_priv,bits256 persis } crc = calc_crc32(0,&serialized[sizeof(crc)],len - sizeof(crc)); iguana_rwnum(1,serialized,sizeof(crc),&crc); - int32_t i; for (i=0; i dest.%x myip.%x senderpub.%llx tag.%llu\n",destipbits,myipbits,(long long)senderpub.txid,(long long)tag); - int32_t i; for (i=0; i= 0 ) { jaddstr(json,"agent",agent); @@ -419,7 +430,7 @@ int32_t iguana_send_supernet(struct iguana_info *coin,struct iguana_peer *addr,c space = malloc(sizeof(struct iguana_msghdr) + IGUANA_MAXPACKETSIZE); datalen = SuperNET_json2bits(myinfo->ipaddr,myinfo->persistent_priv,myinfo->myaddr.persistent,&serialized[sizeof(struct iguana_msghdr)],IGUANA_MAXPACKETSIZE,addr->ipaddr,addr->pubkey,json); printf("SUPERSEND.(%s) -> (%s) delaymillis.%d datalen.%d\n",jsonstr,addr->ipaddr,delaymillis,datalen); - if ( 0 ) + if ( 1 ) qlen = iguana_queue_send(coin,addr,delaymillis,serialized,"SuperNET",datalen,0,0); else qlen = SuperNET_sendmsg(myinfo,coin,addr,addr->pubkey,myinfo->privkey,myinfo->myaddr.pubkey,serialized,datalen,space,delaymillis); free(serialized); @@ -659,3 +670,410 @@ char *SuperNET_p2p(struct iguana_info *coin,struct iguana_peer *addr,int32_t *de free(space); return(retstr); } + +cJSON *SuperNET_peerarray(struct iguana_info *coin,int32_t max,int32_t supernetflag) +{ + int32_t i,r,j,n = 0; struct iguana_peer *addr; cJSON *array = cJSON_CreateArray(); + r = rand(); + for (j=0; jpeers.active[i]; + if ( addr->usock >= 0 && supernetflag == (addr->supernet != 0) ) + { + jaddistr(array,addr->ipaddr); + if ( ++n >= max ) + break; + } + } + if ( n == 0 ) + { + free_json(array); + return(0); + } + return(array); +} + +int32_t SuperNET_coinpeers(struct iguana_info *coin,cJSON *SNjson,cJSON *rawjson,int32_t max) +{ + cJSON *array,*item; + if ( (array= SuperNET_peerarray(coin,max,1)) != 0 ) + { + max -= cJSON_GetArraySize(array); + item = cJSON_CreateObject(); + jaddstr(item,"coin",coin->symbol); + jadd(item,"peers",array); + jaddi(SNjson,item); + } + if ( max > 0 && (array= SuperNET_peerarray(coin,max,0)) != 0 ) + { + max -= cJSON_GetArraySize(array); + item = cJSON_CreateObject(); + jaddstr(item,"coin",coin->symbol); + jadd(item,"peers",array); + jaddi(rawjson,item); + } + return(max); +} + +void SuperNET_parsepeers(struct supernet_info *myinfo,cJSON *array,int32_t n,int32_t supernetflag) +{ + int32_t i,j,m; cJSON *coinarray,*item; char *symbol,*ipaddr; struct iguana_info *ptr; + if ( array != 0 && n > 0 ) + { + for (i=0; i>1; + if ( len < crypto_box_NONCEBYTES ) + return(clonestr("{\"error\":\"cipher is too short\"}")); + if ( len > sizeof(space) ) + { + cipher = calloc(1,len); + message = calloc(1,len); + } + else cipher = space, message = space2; + decode_hex(cipher,len,cipherstr); + origptr = cipher; + if ( bits256_nonz(srcpubkey) == 0 ) + { + memcpy(srcpubkey.bytes,cipher,sizeof(srcpubkey)); + //char str[65]; printf("use attached pubkey.(%s)\n",bits256_str(str,srcpubkey)); + cipher += sizeof(srcpubkey); + len -= sizeof(srcpubkey); + } + nonce = cipher; + cipher += crypto_box_NONCEBYTES, len -= crypto_box_NONCEBYTES; + if ( (deciphered= _SuperNET_decipher(nonce,cipher,message,len,srcpubkey,privkey)) != 0 ) + { + len -= crypto_box_ZEROBYTES; + deciphered[len] = 0; + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","deciphered message"); + jaddstr(retjson,"message",(char *)deciphered); + retstr = jprint(retjson,1); + } else retstr = clonestr("{\"error\":\"couldnt decipher message\"}"); + if ( origptr != space ) + free(origptr); + if ( message != space2 ) + free(message); + return(retstr); +} + +TWOHASHES_AND_STRING(SuperNET,cipher,privkey,destpubkey,message) +{ + bits256 mypubkey; uint8_t *buf,*nonce,*cipher,*origptr,space[8192],space2[sizeof(space)]; + cJSON *retjson; char *retstr,*hexstr; int32_t onetimeflag=0,allocsize,len; + len = (int32_t)strlen(message); + allocsize = (len + crypto_box_NONCEBYTES + crypto_box_ZEROBYTES); + if ( bits256_nonz(destpubkey) == 0 ) + { + destpubkey = GENESIS_PUBKEY; + onetimeflag = 2; // prevent any possible leakage of privkey by using known destpub + } + if ( bits256_nonz(privkey) == 0 ) + onetimeflag = 1; + if ( onetimeflag != 0 ) + { + crypto_box_keypair(mypubkey.bytes,privkey.bytes); + allocsize += sizeof(bits256); + } + if ( allocsize > sizeof(space) ) + { + buf = calloc(1,allocsize); + cipher = calloc(1,allocsize); + } else buf = space, cipher = space2; + origptr = nonce = cipher; + if ( onetimeflag != 0 ) + { + memcpy(cipher,mypubkey.bytes,sizeof(mypubkey)); + nonce = &cipher[sizeof(mypubkey)]; + } + OS_randombytes(nonce,crypto_box_NONCEBYTES); + cipher = &nonce[crypto_box_NONCEBYTES]; + _SuperNET_cipher(nonce,cipher,(void *)message,len,destpubkey,privkey,buf); + if ( buf != space ) + free(buf); + if ( allocsize > sizeof(space)/2 ) + hexstr = calloc(1,(allocsize<<1)+1); + else hexstr = (void *)space; + init_hexbytes_noT(hexstr,origptr,allocsize); + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","ciphered message"); + jaddstr(retjson,"message",message); + jaddstr(retjson,"cipher",hexstr); + init_hexbytes_noT(hexstr,nonce,crypto_box_NONCEBYTES); + jaddstr(retjson,"nonce",hexstr); + if ( onetimeflag != 0 ) + { + jaddbits256(retjson,"onetime_privkey",privkey); + jaddbits256(retjson,"onetime_pubkey",mypubkey); + if ( onetimeflag == 2 ) + jaddstr(retjson,"warning","onetime keypair was used to broadcast"); + } + retstr = jprint(retjson,1); + if ( hexstr != (void *)space ) + free(hexstr); + if ( origptr != space2 ) + free(origptr); + return(retstr); +} + +bits256 SuperNET_pindecipher(IGUANA_ARGS,char *pin,char *privcipher) +{ + cJSON *testjson; char *mstr,*cstr; bits256 privkey,pinpriv,pinpub; + conv_NXTpassword(pinpriv.bytes,pinpub.bytes,(uint8_t *)pin,(int32_t)strlen(pin)); + if ( (cstr= SuperNET_decipher(IGUANA_CALLARGS,pinpriv,pinpub,privcipher)) != 0 ) + { + if ( (testjson= cJSON_Parse(cstr)) != 0 ) + { + if ( (mstr= jstr(testjson,"message")) != 0 && strlen(mstr) == sizeof(bits256)*2 ) + { + decode_hex(privkey.bytes,sizeof(privkey),mstr); + } //else jaddstr(retjson,"error","invalid return from deciphering privcipher"); + free_json(testjson); + } + free(cstr); + } //else jaddstr(retjson,"error","null return from deciphering privcipher"); + return(privkey); +} + +THREE_STRINGS(SuperNET,rosetta,passphrase,pin,showprivkey) +{ + uint8_t rmd160[20],pub[33],flag = 0; uint64_t nxt64bits; bits256 check,privkey,pubkey,pinpriv,pinpub; + char str2[41],wifbuf[64],addr[64],str[128],privcipher[512],*privcipherstr,*cstr; cJSON *retjson; + nxt64bits = conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); + if ( showprivkey != 0 && strcmp(showprivkey,"yes") == 0 ) + flag = 1; + privcipher[0] = 0; + conv_NXTpassword(pinpriv.bytes,pinpub.bytes,(uint8_t *)pin,(int32_t)strlen(pin)); + if ( (cstr= SuperNET_cipher(IGUANA_CALLARGS,pinpriv,pinpub,bits256_str(str,privkey))) != 0 ) + { + if ( (retjson= cJSON_Parse(cstr)) != 0 ) + { + if ( (privcipherstr= jstr(retjson,"cipher")) != 0 ) + strcpy(privcipher,privcipherstr); + free_json(retjson); + } + free(cstr); + } + retjson = cJSON_CreateObject(); + jaddstr(retjson,"privcipher",privcipher); + jaddbits256(retjson,"pubkey",pubkey); + RS_encode(str,nxt64bits); + jaddstr(retjson,"RS",str); + jadd64bits(retjson,"NXT",nxt64bits); + btc_priv2pub(pub,privkey.bytes); + init_hexbytes_noT(str,pub,33); + jaddstr(retjson,"btcpubkey",str); + calc_OP_HASH160(str2,rmd160,str); + jaddstr(retjson,"rmd160",str2); + if ( btc_coinaddr(addr,0,str) == 0 ) + { + jaddstr(retjson,"BTC",addr); + btc_priv2wip(wifbuf,privkey.bytes,0x80); + if ( flag != 0 ) + jaddstr(retjson,"BTCwif",wifbuf); + } + if ( btc_coinaddr(addr,60,str) == 0 ) + { + jaddstr(retjson,"BTCD",addr); + btc_priv2wip(wifbuf,privkey.bytes,0xbc); + if ( flag != 0 ) + jaddstr(retjson,"BTCDwif",wifbuf); + } + if ( flag != 0 ) + jaddbits256(retjson,"privkey",privkey); + check = SuperNET_pindecipher(IGUANA_CALLARGS,pin,privcipher); + if ( memcmp(check.bytes,privkey.bytes,sizeof(check)) != 0 ) + { + jaddbits256(retjson,"deciphered",check); + jaddstr(retjson,"error","cant recreate privkey from (pin + privcipher)"); + } + else if ( flag != 0 ) + jaddbits256(retjson,"deciphered",check); + if ( jobj(retjson,"error") == 0 ) + jaddstr(retjson,"result","use pin and privcipher to access wallet"); + return(jprint(retjson,1)); +} + +STRING_ARG(SuperNET,broadcastcipher,message) +{ + bits256 zero; + memset(zero.bytes,0,sizeof(zero)); + return(SuperNET_cipher(IGUANA_CALLARGS,zero,zero,message)); +} + +STRING_ARG(SuperNET,broadcastdecipher,message) +{ + bits256 zero; + memset(zero.bytes,0,sizeof(zero)); + return(SuperNET_decipher(IGUANA_CALLARGS,zero,zero,message)); +} + +HASH_AND_STRING(SuperNET,multicastcipher,pubkey,message) +{ + bits256 zero; + memset(zero.bytes,0,sizeof(zero)); + return(SuperNET_cipher(IGUANA_CALLARGS,zero,pubkey,message)); +} + +HASH_AND_STRING(SuperNET,multicastdecipher,privkey,cipherstr) +{ + bits256 zero; + memset(zero.bytes,0,sizeof(zero)); + return(SuperNET_decipher(IGUANA_CALLARGS,privkey,zero,cipherstr)); +} + +ZERO_ARGS(SuperNET,stop) +{ + if ( remoteaddr == 0 || strncmp(remoteaddr,"127.0.0.1",strlen("127.0.0.1")) == 0 ) + { + iguana_exit(); + return(clonestr("{\"result\":\"exit started\"}")); + } else return(clonestr("{\"error\":\"cant do a remote stop of this node\"}")); +} + +TWO_ARRAYS(SuperNET,mypeers,supernet,rawpeers) +{ + SuperNET_parsepeers(myinfo,supernet,cJSON_GetArraySize(supernet),1); + SuperNET_parsepeers(myinfo,rawpeers,cJSON_GetArraySize(rawpeers),0); + return(clonestr("{\"result\":\"peers parsed\"}")); +} + +STRING_ARG(SuperNET,getpeers,activecoin) +{ + int32_t i,max = 64; + cJSON *SNjson,*rawjson,*retjson = cJSON_CreateObject(); + SNjson = cJSON_CreateArray(); + rawjson = cJSON_CreateArray(); + if ( coin != 0 ) + max = SuperNET_coinpeers(coin,SNjson,rawjson,max); + else + { + for (i=0; i0; i++) + if ( Coins[i] != 0 ) + max = SuperNET_coinpeers(Coins[i],SNjson,rawjson,max); + } + if ( max != 64 ) + { + jaddstr(retjson,"agent","SuperNET"); + jaddstr(retjson,"method","mypeers"); + jadd(retjson,"supernet",SNjson); + jadd(retjson,"rawpeers",rawjson); + } + else + { + jaddstr(retjson,"error","no peers"); + free_json(SNjson); + free_json(rawjson); + } + return(jprint(retjson,1)); +} + +TWOSTRINGS_AND_HASH_AND_TWOINTS(SuperNET,DHT,hexmsg,destip,destpub,maxdelay,broadcast) +{ + if ( remoteaddr != 0 ) + return(clonestr("{\"error\":\"cant remote DHT\"}")); + else if ( is_hexstr(hexmsg,(int32_t)strlen(hexmsg)) <= 0 ) + return(clonestr("{\"error\":\"message must be in hex\"}")); + return(SuperNET_DHTencode(myinfo,destip,destpub,hexmsg,maxdelay,broadcast)); +} + +HASH_AND_STRING(SuperNET,saveconf,wallethash,confjsonstr) +{ + return(clonestr("{\"result\":\"saveconf here\"}")); +} + +HASH_ARRAY_STRING(SuperNET,layer,mypriv,otherpubs,str) +{ + return(clonestr("{\"result\":\"layer encrypt here\"}")); +} + +THREE_STRINGS(SuperNET,announce,category,subcategory,message) +{ + cJSON *argjson = cJSON_CreateObject(); int32_t len; char *hexmsg=0,*retstr = 0; + //SuperNET_ann(myinfo,category,subcategory,message); + if ( remoteaddr == 0 ) + { + len = (int32_t)strlen(message); + if ( is_hexstr(message,len) == 0 ) + { + } + else hexmsg = message; + retstr = SuperNET_DHTsend(myinfo,GENESIS_PUBKEY,hexmsg,0,1); + if ( hexmsg != message) + free(hexmsg); + } + return(jprint(argjson,1)); +} + +THREE_STRINGS(SuperNET,survey,category,subcategory,message) +{ + return(clonestr("{\"result\":\"layer encrypt here\"}")); +} +#include "../includes/iguana_apiundefs.h" diff --git a/iguana/SuperNET.h b/iguana/SuperNET.h index cf43992e8..9dd89f62a 100644 --- a/iguana/SuperNET.h +++ b/iguana/SuperNET.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -118,6 +118,7 @@ char *SuperNET_DHTsend(struct supernet_info *myinfo,bits256 routehash,char *hexm uint16_t SuperNET_API2num(char *agent,char *method); int32_t SuperNET_num2API(char *agent,char *method,uint16_t num); bits256 SuperNET_sharedseed(bits256 privkey,bits256 otherpub); +int32_t SuperNET_decrypt(bits256 *senderpubp,uint64_t *senderbitsp,uint32_t *timestampp,bits256 mypriv,bits256 mypub,uint8_t *dest,int32_t maxlen,uint8_t *src,int32_t len); int32_t SuperNET_str2hex(uint8_t *hex,char *str); void SuperNET_hex2str(char *str,uint8_t *hex,int32_t len); diff --git a/iguana/cards777.c b/iguana/cards777.c new file mode 100755 index 000000000..2a87b70cd --- /dev/null +++ b/iguana/cards777.c @@ -0,0 +1,526 @@ +/****************************************************************************** + * Copyright © 2014-2016 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. * + * * + ******************************************************************************/ +#include "pangea777.h" + +bits256 cards777_initcrypt(bits256 data,bits256 privkey,bits256 pubkey,int32_t invert) +{ + bits256 hash; + hash = curve25519_shared(privkey,pubkey); + if ( invert != 0 ) + hash = crecip_donna(hash); + return(fmul_donna(data,hash)); +} + +bits256 cards777_cardpriv(bits256 playerpriv,bits256 *cardpubs,int32_t numcards,bits256 cipher) +{ + bits256 cardpriv,checkpub; int32_t i; + for (i=0; i= 0 && destplayer != slot ) + printf(">>>>>>>>>>>> ERROR "); + if ( Debuglevel > 2 ) + printf("slot.%d B DECODED cardi.%d destplayer.%d cardpriv.[%d]\n",slot,cardi,destplayer,cardpriv.bytes[1]); + *cardprivp = cardpriv; + return(cardpriv.bytes[1]); + } + memset(cardprivp,0,sizeof(*cardprivp)); + return(-1); +} + +int32_t cards777_validate(bits256 cardpriv,bits256 final,bits256 *cardpubs,int32_t numcards,bits256 *audit,int32_t numplayers,bits256 playerpub) +{ + int32_t i; bits256 val,checkcard,ver; + val = final; + for (i=numplayers-1; i>0; i--) + { + val = fmul_donna(audit[i],val); + //if ( memcmp(tmp.bytes,audit[i-1].bytes,sizeof(tmp)) != 0 ) + // printf("cards777_validate: mismatched audit[%d] %llx vs %llx %llx\n",i-1,(long long)tmp.txid,(long long)audit[i-1].txid,(long long)audit[i].txid); + } + checkcard = val;//fcontract(val); + if ( memcmp(checkcard.bytes,audit[0].bytes,sizeof(checkcard)) != 0 ) + { + printf("cards777_validate: checkcard not validated %llx vs %llx numplayers.%d\n",(long long)checkcard.txid,(long long)audit[0].txid,numplayers); + return(-1); + } + ver = cards777_initcrypt(cardpriv,cardpriv,playerpub,0); + if ( memcmp(checkcard.bytes,ver.bytes,sizeof(checkcard)) != 0 ) + { + printf("cards777_validate: ver not validated %llx vs %llx\n",(long long)checkcard.txid,(long long)ver.txid); + return(-1); + } + return(cardpriv.bytes[1]); +} + +int32_t cards777_shuffle(bits256 *shuffled,bits256 *cards,int32_t numcards,int32_t N) +{ + int32_t i,j,pos,nonz,permi[CARDS777_MAXCARDS],desti[CARDS777_MAXCARDS]; uint8_t x; uint64_t mask; + memset(desti,0,sizeof(desti)); + for (i=0; i 2 ) + printf("%d ",permi[i]); + mask |= (1LL << permi[i]); + for (j=0; j 2 ) + printf("shuffled mask.%llx err.%llx\n",(long long)mask,(long long)(mask ^ ((1LL< %llx}.%d ",(long long)incards[nonz].txid,(long long)layered[nonz].txid,nonz); + } + //printf("card.%d\n",i); + } +} + +int32_t cards777_calcmofn(uint8_t *allshares,uint8_t *myshares[],uint8_t *sharenrs,int32_t M,bits256 *xoverz,int32_t numcards,int32_t N) +{ + int32_t size,j; + size = N * sizeof(bits256) * numcards; + calc_shares(allshares,(void *)xoverz,size,size,M,N,sharenrs); // PM &allshares[playerj * size] to playerJ + for (j=0; j 2 ) + printf("card777_initdeck unit.%llx\n",(long long)prod.txid); + nonz = 0; + while ( mask != (1LL << numcards)-1 ) + { + privkey = curve25519_keypair(&pubkey); + buf[0] = 0; + if ( (i=privkey.bytes[1]) < numcards && ((1LL << i) & mask) == 0 ) + { + mask |= (1LL << i); + cardpubs[num] = pubkey; + if ( playerprivs != 0 ) + sprintf(buf+strlen(buf),"%llx.",(long long)privkey.txid); + for (j=0; j %llx] ",(long long)cards[nonz].txid,(long long)curve25519_shared(playerprivs[j],pubkey).txid,(long long)cards777_initcrypt(cards[nonz],playerprivs[j],pubkey,1).txid); + } + vcalc_sha256(0,hash.bytes,pubkey.bytes,sizeof(pubkey)); + hash.bytes[0] &= 0xf8, hash.bytes[31] &= 0x7f, hash.bytes[31] |= 64; + prod = fmul_donna(prod,hash); + //printf("(%s) num.%d [%llx] %d prod.%llx\n",buf,num,(long long)mask ^ ((1LL << numcards)-1),i,(long long)prod.txid); + num++; + } + } + if ( playerprivs != 0 ) + printf("\n%llx %llx playerprivs\n",(long long)playerprivs[0].txid,(long long)playerprivs[1].txid); + if ( 0 && Debuglevel > 2 ) + { + for (i=0; ihand.sharenrs,dp->N); + if ( (nrs= jstr(json,"sharenrs")) != 0 ) + decode_hex(dp->hand.sharenrs,(int32_t)strlen(nrs)>>1,nrs); + }*/ + int32_t i,j,m,size; uint8_t *recover,*testshares[CARDS777_MAXPLAYERS],testnrs[255]; + size = N * sizeof(bits256) * numcards; + for (j=0; j<1; j++) + { + memset(testnrs,0,sizeof(testnrs)); + memset(testshares,0,sizeof(testshares)); + m = (rand() % N) + 1; + if ( m < M ) + m = M; + if ( init_sharenrs(testnrs,sharenrs,m,N) < 0 ) + { + printf("iter.%d error init_sharenrs(m.%d of n.%d)\n",j,m,N); + return(0); + } + for (i=0; ibytes,0,sizeof(*seedp)); + for (i=0; i %llx\n",i,(long long)cipher.txid); + return(cipher); + } + } + if ( i == numcards ) + { + printf("decryption error %llx: destplayer.%d no match\n",(long long)cipher.txid,destplayer); + memset(cipher.bytes,0,sizeof(cipher)); + //cipher = cards777_cardpriv(playerpriv,cardpubs,numcards,cipher); + } + return(cipher); +} + +struct cards777_privdata *cards777_allocpriv(int32_t numcards,int32_t N) +{ + struct cards777_privdata *priv; + if ( (priv= calloc(1,sizeof(*priv) + sizeof(bits256) * (2*((N * numcards * N) + (N * numcards))))) == 0 ) + { + printf("cards777_allocpriv: unexpected out of memory error\n"); + return(0); + } + priv->audits = &priv->data[0]; + priv->outcards = &priv->audits[N * numcards * N]; + priv->xoverz = &priv->outcards[N * numcards]; + priv->allshares = (void *)&priv->xoverz[N * numcards]; // N*numcards*N + return(priv); +} + +struct cards777_pubdata *cards777_allocpub(int32_t M,int32_t numcards,int32_t N) +{ + struct cards777_pubdata *dp; + if ( (dp= calloc(1,sizeof(*dp) + sizeof(bits256) * ((numcards + 1) + (N * numcards)))) == 0 ) + { + printf("cards777_allocpub: unexpected out of memory error\n"); + return(0); + } + dp->M = M, dp->N = N, dp->numcards = numcards; + dp->hand.cardpubs = &dp->data[0]; + dp->hand.final = &dp->hand.cardpubs[numcards + 1]; + return(dp); +} + +#ifdef notyet +int32_t cards777_testinit(struct hostnet777_server *srv,int32_t M,struct hostnet777_client **clients,int32_t N,int32_t numcards) +{ + //static int64_t balances[9]; + int32_t i; uint8_t sharenrs[255]; //,destplayer,cardibits256 *ciphers,cardpriv,card; uint64_t mask = 0; + struct cards777_pubdata *dp; //struct cards777_privdata *priv; struct pangea_info *sp; + if ( srv->num != N ) + { + printf("srv->num.%d != N.%d\n",srv->num,N); + return(-1); + } + memset(sharenrs,0,sizeof(sharenrs)); + init_sharenrs(sharenrs,0,N,N); // this needs to be done to start a hand + for (i=0; iclients[i].pubdata = cards777_allocpub(M,numcards,N); + //sp = dp->table; + memcpy(dp->hand.sharenrs,sharenrs,dp->N); + /*for (j=0; jplayerpubs[j] = srv->clients[j].pubkey; + for (j=0; jbalances[j] = &balances[j]; + }*/ + printf("deprecated, need to init sp->\n"); + //priv = srv->clients[i].privdata = cards777_allocpriv(numcards,N); + //priv->privkey = (i == 0) ? srv->H.privkey : clients[i]->H.privkey; + /*if ( i == 0 ) + dp->checkprod = cards777_initdeck(priv->outcards,dp->cardpubs,numcards,N,dp->playerpubs), refdp = dp; + else memcpy(dp->cardpubs,refdp->cardpubs,sizeof(*dp->cardpubs) * numcards);*/ + } + return(0); + /*priv = srv->clients[0].privdata; + ciphers = priv->outcards; + for (i=1; iclients[i].pubdata; + priv = srv->clients[i].privdata; + cards777_encode(priv->outcards,priv->xoverz,priv->allshares,priv->myshares,dp->sharenrs,dp->M,ciphers,dp->numcards,dp->N); + ciphers = priv->outcards; + } + for (cardi=0; cardinumcards; cardi++) + { + for (destplayer=0; destplayerN; destplayer++) + { + priv = srv->clients[dp->N - 1].privdata; + card = priv->outcards[cardi*dp->N + destplayer]; + for (i=N-1; i>=0; i--) + { + j = (i > 0) ? i : destplayer; + //printf("cardi.%d destplayer.%d i.%d j.%d\n",cardi,destplayer,i,j); + dp = srv->clients[j].pubdata; + priv = srv->clients[j].privdata; + cardpriv = cards777_cardpriv(priv->privkey,dp->cardpubs,dp->numcards,card); + if ( cardpriv.txid != 0 ) + { + mask |= (1LL << cardpriv.bytes[1]); + if ( destplayer != j ) + printf(">>>>>>>>>>>> ERROR "); + printf("i.%d j.%d A DECODED cardi.%d destplayer.%d cardpriv.[%d] mask.%llx\n",i,j,cardi,destplayer,cardpriv.bytes[1],(long long)mask); + break; + } + card = cards777_decode(priv->xoverz,destplayer,card,priv->outcards,dp->numcards,dp->N); + cardpriv = cards777_cardpriv(priv->privkey,dp->cardpubs,dp->numcards,card); + if ( cardpriv.txid != 0 ) + { + mask |= (1LL << cardpriv.bytes[1]); + if ( destplayer != j ) + printf(">>>>>>>>>>>> ERROR "); + printf("i.%d j.%d B DECODED cardi.%d destplayer.%d cardpriv.[%d] mask.%llx\n",i,j,cardi,destplayer,cardpriv.bytes[1],(long long)mask); + break; + } + } + } + printf("cardi.%d\n\n",cardi); + }*/ + return(0); +} + +void cards777_initid(struct hostnet777_id *id,bits256 pubkey,struct cards777_pubdata *dp,struct cards777_privdata *priv) +{ + id->pubkey = pubkey; + id->nxt64bits = acct777_nxt64bits(pubkey); + id->pubdata = dp; + id->privdata = priv; + id->pmsock = -1; +} + +void cards777_test() +{ + int32_t i,j,vals[52][52]; bits256 keypairs[52][2],otherpairs[52][2],matrix[52][52]; char buf[512]; + FILE *fp; + if ( (fp= fopen("/persistent/test","rb")) != 0 ) + { + if ( fread(buf,6,1,fp) <= 0 ) + printf("read error for /persistent/test\n"); + buf[6] = 0; + printf("test exists (%s)\n",buf); + fclose(fp); + } else printf("testfile not present\n"); + for (i=0; i<52; i++) + keypairs[i][0] = curve25519_keypair(&keypairs[i][1]); + for (j=0; j<52; j++) + otherpairs[j][0] = curve25519_keypair(&otherpairs[j][1]); + bits256 zmone;zmone = crecip_donna(keypairs[0][0]); + printf("DEBUG.%d %llx vs %llx | %llx -> %llx/%llx\n",Debuglevel,(long long)keypairs[0][0].txid,(long long)fcontract(fexpand(keypairs[0][0])).txid,(long long)zmone.txid,(long long)fexpand(fmul_donna(keypairs[0][0],zmone)).txid,(long long)fmul(fexpand(keypairs[0][0]),fexpand(zmone)).txid); + for (i=0; i<52; i++) + {break; + buf[0] = 0; + for (j=0; j<52; j++) + { + matrix[i][j] = fmul_donna(keypairs[j][1],otherpairs[i][1]); + vals[i][j] = matrix[i][j].bytes[1] % 52; + sprintf(buf+strlen(buf),"%d ",vals[i][j]); + } + printf("%s\n",buf); + } + struct hostnet777_server *srv; int32_t M,N = 9; //struct hostnet777_client **clients; + struct cards777_pubdata *dp; struct cards777_privdata *priv; + bits256 checkprod,cards[52],playerpubs[9],playerprivs[9]; + //clients = calloc(N+1,sizeof(*clients)); + if ( (srv= hostnet777_server(keypairs[0][0],keypairs[0][1],0,0,0,N)) == 0 ) + { + printf("cant create hostnet777 server\n"); + return; + } + M = (N >> 1) + 1; + for (i=0; iclients[i],keypairs[i][1],cards777_allocpub(M,52,N),cards777_allocpriv(52,N)); + playerprivs[i] = keypairs[i][0]; + playerpubs[i] = keypairs[i][1]; + if ( i == 0 ) + { + srv->H.privkey = keypairs[i][0]; + srv->H.pubkey = keypairs[i][1]; + } + else + { + } + } + dp = srv->clients[0].pubdata; + dp->N = N; dp->M = M; dp->numcards = 52; + checkprod = cards777_initdeck(cards,dp->hand.cardpubs,52,N,playerpubs,0); + printf("deck initialzed %llx\n",(long long)checkprod.txid); + uint8_t sharenrs[255]; uint64_t mask = 0; int32_t cardi,destplayer; + bits256 card,cardpriv,seed,*ciphers = cards; + for (i=1; iclients[i].pubdata; + dp->N = N; dp->M = M; dp->numcards = 52; + priv = srv->clients[i].privdata; + cards777_encode(priv->outcards,priv->xoverz,priv->allshares,priv->myshares,sharenrs,dp->M,ciphers,dp->numcards,dp->N); + ciphers = priv->outcards; + } + printf("deck encrypted\n"); + for (cardi=0; cardinumcards; cardi++) + { + for (destplayer=0; destplayerN; destplayer++) + { + priv = srv->clients[dp->N - 1].privdata; + card = priv->outcards[cardi*dp->N + destplayer]; + for (i=N-1; i>=0; i--) + { + j = (i > 0) ? i : destplayer; + //printf("cardi.%d destplayer.%d i.%d j.%d\n",cardi,destplayer,i,j); + dp = srv->clients[j].pubdata; + priv = srv->clients[j].privdata; + cardpriv = cards777_cardpriv(keypairs[j][0],dp->hand.cardpubs,dp->numcards,card); + if ( cardpriv.txid != 0 ) + { + mask |= (1LL << cardpriv.bytes[1]); + if ( destplayer != j ) + printf(">>>>>>>>>>>> ERROR "); + printf("i.%d j.%d A DECODED cardi.%d destplayer.%d cardpriv.[%d] mask.%llx\n",i,j,cardi,destplayer,cardpriv.bytes[1],(long long)mask); + break; + } + card = cards777_decode(&seed,priv->xoverz,destplayer,card,priv->outcards,dp->numcards,dp->N); + cardpriv = cards777_cardpriv(keypairs[j][0],dp->hand.cardpubs,dp->numcards,card); + if ( cardpriv.txid != 0 ) + { + mask |= (1LL << cardpriv.bytes[1]); + if ( destplayer != j ) + printf(">>>>>>>>>>>> ERROR "); + printf("i.%d j.%d B DECODED cardi.%d destplayer.%d cardpriv.[%d] mask.%llx\n",i,j,cardi,destplayer,cardpriv.bytes[1],(long long)mask); + break; + } + } + } + printf("cardi.%d\n\n",cardi); + break; + } +} + +#endif diff --git a/iguana/iguana.sources b/iguana/iguana.sources index be771a6b5..997a6ff72 100755 --- a/iguana/iguana.sources +++ b/iguana/iguana.sources @@ -1,3 +1,3 @@ #iguana_html.c -SOURCES := SuperNET.c ramchain_api.c iguana_tx.c iguana_wallet.c iguana_pubkeys.c iguana_recv.c iguana_bundles.c iguana_msg.c iguana_rpc.c iguana777.c iguana_chains.c iguana_peers.c iguana_accept.c iguana_bitmap.c iguana_init.c iguana_ramchain.c iguana_blocks.c iguana_json.c main.c +SOURCES := SuperNET.c pangea_api.c pangea_fsm.c pangea_network.c pangea_init.c poker.c ramchain_api.c iguana_tx.c iguana_wallet.c iguana_pubkeys.c iguana_recv.c iguana_bundles.c iguana_msg.c iguana_rpc.c iguana777.c iguana_chains.c iguana_peers.c iguana_accept.c iguana_bitmap.c iguana_init.c iguana_ramchain.c iguana_blocks.c iguana_json.c main.c diff --git a/iguana/iguana777.c b/iguana/iguana777.c index 5e47b4783..8a7e3d8ba 100755 --- a/iguana/iguana777.c +++ b/iguana/iguana777.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/iguana/iguana777.h b/iguana/iguana777.h index db2642340..e440a47a7 100755 --- a/iguana/iguana777.h +++ b/iguana/iguana777.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -695,6 +695,7 @@ int32_t iguana_pendingaccept(struct iguana_info *coin); char *iguana_blockingjsonstr(struct supernet_info *myinfo,char *jsonstr,uint64_t tag,int32_t maxmillis,char *remoteaddr); void iguana_iAkill(struct iguana_info *coin,struct iguana_peer *addr,int32_t markflag); cJSON *SuperNET_bits2json(bits256 mypriv,bits256 mypub,struct iguana_peer *addr,uint8_t *serialized,uint8_t *space,int32_t datalen,int32_t iscompressed); +int32_t SuperNET_sendmsg(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_peer *addr,bits256 destpub,bits256 mypriv,bits256 mypub,uint8_t *msg,int32_t len,uint8_t *data,int32_t delaymillis); extern queue_t bundlesQ; diff --git a/iguana/iguana_accept.c b/iguana/iguana_accept.c index 4991eb1f3..6cf5f4932 100755 --- a/iguana/iguana_accept.c +++ b/iguana/iguana_accept.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/iguana/iguana_bitmap.c b/iguana/iguana_bitmap.c index 678af8bd2..c5b5212fe 100755 --- a/iguana/iguana_bitmap.c +++ b/iguana/iguana_bitmap.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/iguana/iguana_blocks.c b/iguana/iguana_blocks.c index b56a74790..13f1390e8 100755 --- a/iguana/iguana_blocks.c +++ b/iguana/iguana_blocks.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/iguana/iguana_bundles.c b/iguana/iguana_bundles.c index 79cb92831..984d4e47c 100755 --- a/iguana/iguana_bundles.c +++ b/iguana/iguana_bundles.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/iguana/iguana_chains.c b/iguana/iguana_chains.c index 2896dd0c5..a70648810 100755 --- a/iguana/iguana_chains.c +++ b/iguana/iguana_chains.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/iguana/iguana_html.c b/iguana/iguana_html.c index b384bc327..724b0f565 100755 --- a/iguana/iguana_html.c +++ b/iguana/iguana_html.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/iguana/iguana_init.c b/iguana/iguana_init.c index 3fd3c0186..ff9ee214e 100755 --- a/iguana/iguana_init.c +++ b/iguana/iguana_init.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/iguana/iguana_json.c b/iguana/iguana_json.c index f808e2591..48577f115 100755 --- a/iguana/iguana_json.c +++ b/iguana/iguana_json.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -99,9 +99,11 @@ cJSON *SuperNET_helpjson() #define IGUANA_HELP_III(agent,name,val,val2,val3) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#val,"int"),helpitem(#val2,"int"),helpitem(#val3,"int"))) #define IGUANA_HELP_IAS(agent,name,val,obj,str) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#val,"int"),helpitem(#obj,"array"),helpitem(#str,"string"))) +#define IGUANA_HELP_64A(agent,name,j64,obj) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#j64,"u64bits"),helpitem(#obj,"array"))) #define IGUANA_HELP_AA(agent,name,obj,obj2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#obj,"array"),helpitem(#obj2,"array"))) #define IGUANA_HELP_D(agent,name,amount) array = helpjson(IGUANA_ARGS,#agent,#name,helparray(cJSON_CreateArray(),helpitem(#amount,"float"))) +#define IGUANA_HELP_H(agent,name,hash) array = helpjson(IGUANA_ARGS,#agent,#name,helparray(cJSON_CreateArray(),helpitem(#hash,"hash"))) #define IGUANA_HELP_HI(agent,name,hash,val) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#hash,"hash"),helpitem(#val,"int"))) #define IGUANA_HELP_HS(agent,name,hash,str) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#hash,"hash"),helpitem(#str,"str"))) #define IGUANA_HELP_HII(agent,name,hash,val,val2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#hash,"hash"),helpitem(#val,"int"),helpitem(#val2,"int"))) @@ -143,9 +145,10 @@ cJSON *SuperNET_helpjson() #define THREE_INTS IGUANA_HELP_III #define TWOHASHES_AND_STRING IGUANA_HELP_HHS #define HASH_ARRAY_STRING IGUANA_HELP_HAS +#define U64_AND_ARRAY IGUANA_HELP_64A +#define HASH_ARG IGUANA_HELP_H #include "../includes/iguana_apideclares.h" -#undef IGUANA_ARGS #include "../includes/iguana_apiundefs.h" if ( array != 0 ) @@ -318,133 +321,8 @@ cJSON *iguana_peersjson(struct iguana_info *coin,int32_t addronly) else return(array); } -cJSON *SuperNET_peerarray(struct iguana_info *coin,int32_t max,int32_t supernetflag) -{ - int32_t i,r,j,n = 0; struct iguana_peer *addr; cJSON *array = cJSON_CreateArray(); - r = rand(); - for (j=0; jpeers.active[i]; - if ( addr->usock >= 0 && supernetflag == (addr->supernet != 0) ) - { - jaddistr(array,addr->ipaddr); - if ( ++n >= max ) - break; - } - } - if ( n == 0 ) - { - free_json(array); - return(0); - } - return(array); -} - -int32_t SuperNET_coinpeers(struct iguana_info *coin,cJSON *SNjson,cJSON *rawjson,int32_t max) -{ - cJSON *array,*item; - if ( (array= SuperNET_peerarray(coin,max,1)) != 0 ) - { - max -= cJSON_GetArraySize(array); - item = cJSON_CreateObject(); - jaddstr(item,"coin",coin->symbol); - jadd(item,"peers",array); - jaddi(SNjson,item); - } - if ( max > 0 && (array= SuperNET_peerarray(coin,max,0)) != 0 ) - { - max -= cJSON_GetArraySize(array); - item = cJSON_CreateObject(); - jaddstr(item,"coin",coin->symbol); - jadd(item,"peers",array); - jaddi(rawjson,item); - } - return(max); -} - -void SuperNET_parsepeers(struct supernet_info *myinfo,cJSON *array,int32_t n,int32_t supernetflag) -{ - int32_t i,j,m; cJSON *coinarray,*item; char *symbol,*ipaddr; struct iguana_info *ptr; - if ( array != 0 && n > 0 ) - { - for (i=0; i0; i++) - if ( Coins[i] != 0 ) - max = SuperNET_coinpeers(Coins[i],SNjson,rawjson,max); - } - if ( max != 64 ) - { - jaddstr(retjson,"agent","SuperNET"); - jaddstr(retjson,"method","mypeers"); - jadd(retjson,"supernet",SNjson); - jadd(retjson,"rawpeers",rawjson); - } - else - { - jaddstr(retjson,"error","no peers"); - free_json(SNjson); - free_json(rawjson); - } - return(jprint(retjson,1)); -} - STRING_ARG(iguana,peers,activecoin) { if ( coin != 0 ) @@ -670,22 +548,7 @@ TWO_STRINGS(SuperNET,html,agentform,htmlfile) fclose(fp); return(jprint(retjson,1)); } - -ZERO_ARGS(SuperNET,saveconf) -{ - return(clonestr("{\"result\":\"saveconf here\"}")); -} - -HASH_ARRAY_STRING(SuperNET,layer,mypriv,otherpubs,str) -{ - return(clonestr("{\"result\":\"layer encrypt here\"}")); -} - -HASH_AND_STRING(SuperNET,sharepersistent,persistentpub,destip) -{ - return(clonestr("{\"result\":\"share persistent here\"}")); -} - + #undef IGUANA_ARGS #include "../includes/iguana_apiundefs.h" @@ -720,10 +583,12 @@ char *SuperNET_parser(struct supernet_info *myinfo,char *agent,char *method,cJSO #define IGUANA_DISPATCH_IA(agent,name,val,array) else if ( strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,juint(json,#val),jobj(json,#array))) #define IGUANA_DISPATCH_IAS(agent,name,val,array,str) else if ( strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,juint(json,#val),jobj(json,#array),jstr(json,#str))) +#define IGUANA_DISPATCH_64A(agent,name,j64,array) else if ( strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,j64bits(json,#j64),jobj(json,#array))) #define IGUANA_DISPATCH_AA(agent,name,array,array2) else if ( strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jobj(json,#array),jobj(json,#array2))) #define IGUANA_DISPATCH_D(agent,name,amount) else if ( strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jdouble(json,#amount))) +#define IGUANA_DISPATCH_H(agent,name,hash) else if ( strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jbits256(json,#hash))) #define IGUANA_DISPATCH_HI(agent,name,hash,val) else if ( strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jbits256(json,#hash),juint(json,#val))) #define IGUANA_DISPATCH_HS(agent,name,hash,str) else if ( strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jbits256(json,#hash),jstr(json,#str))) #define IGUANA_DISPATCH_HII(agent,name,hash,val,val2) else if ( strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jbits256(json,#hash),juint(json,#val),juint(json,#val2))) @@ -765,9 +630,11 @@ char *SuperNET_parser(struct supernet_info *myinfo,char *agent,char *method,cJSO #define THREE_INTS IGUANA_DISPATCH_III #define TWOHASHES_AND_STRING IGUANA_DISPATCH_HHS #define HASH_ARRAY_STRING IGUANA_DISPATCH_HAS +#define U64_AND_ARRAY IGUANA_DISPATCH_64A +#define HASH_ARG IGUANA_DISPATCH_H #include "../includes/iguana_apideclares.h" -#undef IGUANA_ARGS +//#undef IGUANA_ARGS #include "../includes/iguana_apiundefs.h" diff --git a/iguana/iguana_msg.c b/iguana/iguana_msg.c index 8bb17fb85..4f0b2d57f 100755 --- a/iguana/iguana_msg.c +++ b/iguana/iguana_msg.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/iguana/iguana_peers.c b/iguana/iguana_peers.c index 3794915f7..c8618be08 100755 --- a/iguana/iguana_peers.c +++ b/iguana/iguana_peers.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/iguana/iguana_pubkeys.c b/iguana/iguana_pubkeys.c index fee631f65..07afb5c69 100755 --- a/iguana/iguana_pubkeys.c +++ b/iguana/iguana_pubkeys.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/iguana/iguana_ramchain.c b/iguana/iguana_ramchain.c index c9f039dde..df3944bcf 100755 --- a/iguana/iguana_ramchain.c +++ b/iguana/iguana_ramchain.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/iguana/iguana_recv.c b/iguana/iguana_recv.c index 58227478a..6d90ef280 100755 --- a/iguana/iguana_recv.c +++ b/iguana/iguana_recv.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/iguana/iguana_rpc.c b/iguana/iguana_rpc.c index d9e0d4c03..d671c5b30 100755 --- a/iguana/iguana_rpc.c +++ b/iguana/iguana_rpc.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/iguana/iguana_tx.c b/iguana/iguana_tx.c index 37cb08734..15367377f 100755 --- a/iguana/iguana_tx.c +++ b/iguana/iguana_tx.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/iguana/iguana_wallet.c b/iguana/iguana_wallet.c index c05a9ca06..5b2f2b508 100755 --- a/iguana/iguana_wallet.c +++ b/iguana/iguana_wallet.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/iguana/main.c b/iguana/main.c index d898ba652..0a2389cc5 100644 --- a/iguana/main.c +++ b/iguana/main.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -31,6 +31,7 @@ char *Iguana_validcommands[] = "version", "verack", "getaddr", "addr", "inv", "getdata", "notfound", "getblocks", "getheaders", "headers", "tx", "block", "mempool", "ping", "pong", "reject", "filterload", "filteradd", "filterclear", "merkleblock", "alert", "" }; +int32_t Showmode,Autofold,PANGEA_MAXTHREADS = 1; struct iguana_info *Coins[IGUANA_MAXCOINS]; int32_t USE_JAY,FIRST_EXTERNAL,IGUANA_disableNXT,Debuglevel; diff --git a/iguana/pangea777.h b/iguana/pangea777.h new file mode 100755 index 000000000..1cf964c98 --- /dev/null +++ b/iguana/pangea777.h @@ -0,0 +1,189 @@ +/****************************************************************************** + * Copyright © 2014-2016 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. * + * * + ******************************************************************************/ + +#ifndef PANGEA777_H +#define PANGEA777_H +#include "iguana777.h" + +#define TEST_TRANSPORT "http://" + +#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 + +#define CARDS777_MAXCARDS 52 +#define CARDS777_MAXPLAYERS 9 +#define CARDS777_FOLD -1 +#define CARDS777_START 1 +#define CARDS777_ANTE 2 +#define CARDS777_SMALLBLIND 3 +#define CARDS777_BIGBLIND 4 +#define CARDS777_CHECK 5 +#define CARDS777_CALL 6 +#define CARDS777_BET 7 +#define CARDS777_RAISE 8 +#define CARDS777_FULLRAISE 9 +#define CARDS777_SENTCARDS 10 +#define CARDS777_ALLIN 11 +#define CARDS777_FACEUP 12 +#define CARDS777_WINNINGS 13 +#define CARDS777_RAKES 14 +#define CARDS777_CHANGES 15 +#define CARDS777_SNAPSHOT 16 + +struct cards777_handinfo +{ + bits256 checkprod,*cardpubs,*final,community256[5],cards[CARDS777_MAXPLAYERS][2]; + uint64_t othercardpubs[CARDS777_MAXPLAYERS]; + int64_t havemasks[CARDS777_MAXPLAYERS],betsize,hostrake,pangearake,lastraise,bets[CARDS777_MAXPLAYERS],snapshot[CARDS777_MAXPLAYERS+1],won[CARDS777_MAXPLAYERS]; + uint32_t starttime,handmask,lastbettor,startdecktime,betstarted,finished,encodestarted; + uint32_t cardi,userinput_starttime,handranks[CARDS777_MAXPLAYERS]; + int8_t betstatus[CARDS777_MAXPLAYERS],actions[CARDS777_MAXPLAYERS],turnis[CARDS777_MAXPLAYERS]; + uint8_t numactions,undergun,community[5],sharenrs[CARDS777_MAXPLAYERS][255],hands[CARDS777_MAXPLAYERS][7]; +}; + +struct cards777_pubdata +{ + int64_t snapshot[CARDS777_MAXPLAYERS]; + uint64_t maxrake,hostrake,bigblind,ante,pangearake,summaries,mismatches; + uint32_t button,readymask,numhands,rakemillis,minbuyin,maxbuyin,summarysize; + void *table; struct cards777_handinfo hand; + char newhand[65536],coinstr[16]; uint8_t M,N,numcards,summary[65536]; bits256 data[]; +}; + +struct cards777_privdata +{ + bits256 holecards[2],*audits,*outcards,*xoverz; + //,*reconstructed[CARDS777_MAXPLAYERS],*mofn[CARDS777_MAXPLAYERS][CARDS777_MAXPLAYERS]; + uint8_t *myshares[CARDS777_MAXPLAYERS],*allshares,hole[2],cardis[2],automuck,autofold; + bits256 data[]; +}; + +extern int32_t Debuglevel; +bits256 xoverz_donna(bits256 a); +bits256 crecip_donna(bits256 a); +bits256 fmul_donna(bits256 a,bits256 b); + +void calc_shares(unsigned char *shares,unsigned char *secret,int32_t size,int32_t width,int32_t M,int32_t N,unsigned char *sharenrs); +int32_t init_sharenrs(unsigned char sharenrs[255],unsigned char *orig,int32_t m,int32_t n); + +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 pangeanet777_endpoint { char endpoint[128],transport[16],ipaddr[64]; uint16_t port; }; +struct pangeanet777_id { bits256 pubkey; uint64_t nxt64bits; void *privdata,*pubdata; int32_t pmsock; uint32_t lastcontact; }; +union pangeanet777 { struct pangeanet777_server *server; struct pangeanet777_client *client; }; +struct pangeanet777_hdr +{ + queue_t Q; bits256 privkey,pubkey; + void *privdata,*pubdata; uint64_t nxt64bits;//,recvhashes[64]; + void (*pollfunc)(union pangeanet777 *hn); + uint32_t lastping; int32_t slot,done,state,ind; +}; + +struct pangeanet777_client { struct pangeanet777_hdr H; int32_t subsock; struct pangeanet777_id my; uint64_t balance,tableid; }; + +struct pangeanet777_server +{ + struct pangeanet777_hdr H; + int32_t num,max,pubsock; struct pangeanet777_endpoint ep; //queue_t mailboxQ[CARDS777_MAXPLAYERS]; + struct pangeanet777_id clients[]; +}; + +struct pangea_thread +{ + union pangeanet777 hn; uint64_t nxt64bits; int32_t threadid,ishost,M,N,numcards; +} *THREADS[_PANGEA_MAXTHREADS]; + +int32_t SuperNET_copybits(int32_t reverse,uint8_t *dest,uint8_t *src,int32_t len); + +int32_t cardstr(char *cardstr,uint8_t card); +uint32_t set_handstr(char *handstr,uint8_t cards[7],int32_t verbose); + +struct cards777_pubdata *cards777_allocpub(int32_t M,int32_t numcards,int32_t N); +struct cards777_privdata *cards777_allocpriv(int32_t numcards,int32_t N); +bits256 cards777_initdeck(bits256 *cards,bits256 *cardpubs,int32_t numcards,int32_t N,bits256 *playerpubs,bits256 *playerprivs); +bits256 cards777_pubkeys(bits256 *pubkeys,int32_t numcards,bits256 cmppubkey); +int32_t cards777_checkcard(bits256 *cardprivp,int32_t cardi,int32_t slot,int32_t destplayer,bits256 playerpriv,bits256 *cardpubs,int32_t numcards,bits256 card); +int32_t cards777_validate(bits256 cardpriv,bits256 final,bits256 *cardpubs,int32_t numcards,bits256 *audit,int32_t numplayers,bits256 playerpub); +bits256 cards777_decode(bits256 *seedp,bits256 *xoverz,int32_t destplayer,bits256 cipher,bits256 *outcards,int32_t numcards,int32_t N); +uint8_t *cards777_encode(bits256 *encoded,bits256 *xoverz,uint8_t *allshares,uint8_t *myshares[],uint8_t sharenrs[255],int32_t M,bits256 *ciphers,int32_t numcards,int32_t N); + +int32_t pangea_search(struct pangea_info *sp,uint64_t nxt64bits); +int32_t pangea_tableaddr(struct cards777_pubdata *dp,uint64_t destbits); +struct pangea_info *pangea_find64(uint64_t tableid,uint64_t nxt64bits); +struct pangea_info *pangea_find(uint64_t tableid,int32_t threadid); +int32_t pangea_neworder(struct cards777_pubdata *dp,struct pangea_info *sp,uint64_t *active,int32_t numactive); + +cJSON *pangea_tablestatus(struct pangea_info *sp); +void pangea_summary(union pangeanet777 *hn,struct cards777_pubdata *dp,uint8_t type,void *arg0,int32_t size0,void *arg1,int32_t size1); +void pangea_startbets(union pangeanet777 *hn,struct cards777_pubdata *dp,int32_t cardi); +void pangea_checkantes(union pangeanet777 *hn,struct cards777_pubdata *dp); +uint64_t pangea_bot(union pangeanet777 *hn,struct cards777_pubdata *dp,int32_t turni,int32_t cardi,uint64_t betsize); +char *pangea_dispsummary(struct pangea_info *sp,int32_t verbose,uint8_t *summary,int32_t summarysize,uint64_t tableid,int32_t handid,int32_t numplayers); +char *_pangea_input(uint64_t my64bits,uint64_t tableid,cJSON *json); +void pangea_finish(union pangeanet777 *hn,struct cards777_pubdata *dp); +void pangea_serverstate(union pangeanet777 *hn,struct cards777_pubdata *dp,struct cards777_privdata *priv); + +int32_t pangea_anotherhand(void *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); +void pangea_buyins(uint32_t *minbuyinp,uint32_t *maxbuyinp); +int32_t pangea_sidepots(int32_t dispflag,uint64_t sidepots[CARDS777_MAXPLAYERS][CARDS777_MAXPLAYERS],struct cards777_pubdata *dp,int64_t *bets); +int64_t pangea_splitpot(int64_t *won,uint64_t *pangearakep,uint64_t sidepot[CARDS777_MAXPLAYERS],union pangeanet777 *hn,int32_t rakemillis); +int32_t pangea_actives(int32_t *activej,struct cards777_pubdata *dp); +int32_t pangea_bet(union pangeanet777 *hn,struct cards777_pubdata *dp,int32_t player,int64_t bet,int32_t action); +uint64_t pangea_winnings(int32_t player,uint64_t *pangearakep,uint64_t *hostrakep,uint64_t total,int32_t numwinners,int32_t rakemillis,uint64_t maxrake); +int32_t _pangea_addfunds(union pangeanet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t senderind); +void _pangea_chat(uint64_t senderbits,void *buf,int32_t len,int32_t senderind); + +void pangea_sendcmd(char *hex,union pangeanet777 *hn,char *cmdstr,int32_t destplayer,uint8_t *data,int32_t datalen,int32_t cardi,int32_t turni); +int32_t pangea_slotA(struct pangea_info *sp); +int32_t pangea_slotB(struct pangea_info *sp); +int32_t pangea_slot(struct pangea_info *sp,int32_t ind); +int32_t pangea_ind(struct pangea_info *sp,int32_t slot); +int32_t pangea_slot(struct pangea_info *sp,int32_t ind); +int32_t pangea_poll(uint64_t *senderbitsp,uint32_t *timestampp,union pangeanet777 *hn); + +int32_t pangeanet777_register(struct pangeanet777_server *srv,bits256 clientpub,int32_t slot); +struct pangeanet777_client *pangeanet777_client(bits256 privkey,bits256 pubkey,char *srvendpoint,int32_t slot); +struct pangeanet777_server *pangeanet777_server(bits256 srvprivkey,bits256 srvpubkey,char *transport,char *ipaddr,uint16_t port,int32_t maxclients); +int32_t pangeanet777_idle(union pangeanet777 *hn); +void pangeanet777_msg(uint64_t destbits,bits256 destpub,union pangeanet777 *src,int32_t blindflag,char *jsonstr,int32_t len); +struct pangea_info *pangea_threadtables(int32_t *nump,int32_t threadid,uint64_t tableid); + +extern int32_t Debuglevel,PANGEA_MAXTHREADS,Showmode,Autofold; +bits256 issue_getpubkey(int32_t *haspubkeyp,char *acct); + +#endif diff --git a/iguana/pangea_api.c b/iguana/pangea_api.c new file mode 100755 index 000000000..3337da6f1 --- /dev/null +++ b/iguana/pangea_api.c @@ -0,0 +1,594 @@ +/****************************************************************************** + * Copyright © 2014-2016 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. * + * * + ******************************************************************************/ + +#include "pangea777.h" + +void pangea_sendcmd(char *hex,union pangeanet777 *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\",\"turni\":%d,\"myslot\":%d,\"myind\":%d,\"cardi\":%d,\"dest\":%d,\"sender\":\"%llu\",\"timestamp\":\"%lu\",\"n\":%u,%s\"data\":\"",cmdstr,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; + PNACL_message("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 ) + { + PNACL_message("error creating json\n"); + return; + } + free_json(json); + hexlen = (int32_t)strlen(hex)+1; + //PNACL_message("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)); + //PNACL_message("T%d broadcasts %d\n",hn->client->H.slot,hexlen); + } + else + { + destpub = sp->playerpubs[pangea_slot(sp,destplayer)]; + destbits = acct777_nxt64bits(destpub); + //PNACL_message("T%d sends %d to dest.%d\n",hn->client->H.slot,hexlen,destplayer); + } + pangeanet777_msg(destbits,destpub,hn,blindflag,hex,hexlen); +} + +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; inumaddrs; 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 supernet_info *plugin) +{ + int32_t i,n,m,pinggap = 1; uint64_t senderbits; uint32_t timestamp; struct pangea_thread *tp; union pangeanet777 *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; + //PNACL_message("pangea idle player.%d\n",hn->client->H.slot); + if ( hn->client->H.done == 0 ) + { + n++; + if ( pangeanet777_idle(hn) != 0 ) + m++; + pangea_poll(&senderbits,×tamp,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 ) + { + PNACL_message("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 ) + usleep(3000); + } + //for (i=0; i<_PANGEA_MAXTHREADS; i++) + // if ( THREADS[i] != 0 && Pangea_waiting != 0 ) + // pangea_userpoll(&THREADS[i]->hn); + 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); + PNACL_message("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 + { + PNACL_message("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; inumaddrs; 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\"}")); +} + +void _pangea_chat(uint64_t senderbits,void *buf,int32_t len,int32_t senderind) +{ + PNACL_message(">>>>>>>>>>> CHAT FROM.%d %llu: (%s)\n",senderind,(long long)senderbits,(char *)buf); +} + +/*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; + PNACL_message("inside rosetta\n"); + if ( (coin= jstr(json,"coin")) != 0 ) + { + if ( (wipstr= jstr(json,"wif")) != 0 || (wipstr= jstr(json,"wip")) != 0 ) + { + PNACL_message("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); + PNACL_message("pubkey.%s\n",pubkeystr); + retjson = cJSON_CreateObject(); + jaddstr(retjson,"btcpubkey",pubkeystr); + for (i=0; inxt64bits,*(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); + } + +int32_t pangea_unzbuf(uint8_t *buf,char *hexstr,int32_t len) +{ + int32_t i,j,len2; + for (len2=i=0; iclient->H.pubdata, sp = dp->table; + priv = hn->client->H.privdata; + if ( hn == 0 || hn->client == 0 || dp == 0 || priv == 0 ) + { + if ( Debuglevel > 2 ) + PNACL_message("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 ) + { + PNACL_message("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); + //PNACL_message("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 ) + { + PNACL_message("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 ) + { + PNACL_message("len too big for pangea_poll\n"); + goto cleanup; + } + decode_hex(buf,len,hexstr); + } else if ( hexstr != 0 ) + PNACL_message("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,"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_bypass(uint64_t my64bits,uint8_t myprivkey[32],cJSON *json) +{ + char *methodstr,*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); + } + return(retstr); +} + +#include "../includes/iguana_apidefs.h" + +INT_AND_ARRAY(pangea,newhand,senderind,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + +INT_AND_ARRAY(pangea,ping,senderind,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + +INT_AND_ARRAY(pangea,gotdeck,senderind,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + +INT_AND_ARRAY(pangea,ready,senderind,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + +INT_AND_ARRAY(pangea,encoded,senderind,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + +INT_AND_ARRAY(pangea,final,senderind,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + +INT_AND_ARRAY(pangea,addedfunds,senderind,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + +INT_AND_ARRAY(pangea,preflop,senderind,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + +INT_AND_ARRAY(pangea,decoded,senderind,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + +INT_AND_ARRAY(pangea,card,senderind,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + +INT_AND_ARRAY(pangea,facedown,senderind,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + +INT_AND_ARRAY(pangea,faceup,senderind,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + +INT_AND_ARRAY(pangea,turn,senderind,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + +INT_AND_ARRAY(pangea,confirmturn,senderind,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + +INT_AND_ARRAY(pangea,chat,senderind,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + +INT_AND_ARRAY(pangea,action,senderind,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + +INT_AND_ARRAY(pangea,showdown,senderind,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + +INT_AND_ARRAY(pangea,handsummary,senderind,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + + +//U64_AND_ARRAY(pangea,turn,tableid,args); +U64_AND_ARRAY(pangea,status,tableid,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + +U64_AND_ARRAY(pangea,mode,tableid,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + +U64_AND_ARRAY(pangea,buyin,tableid,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} + +U64_AND_ARRAY(pangea,history,tableid,args) +{ + cJSON *retjson = cJSON_CreateObject(); + return(jprint(retjson,1)); +} +#undef IGUANA_ARGS + +#include "../includes/iguana_apiundefs.h" diff --git a/iguana/pangea_fsm.c b/iguana/pangea_fsm.c new file mode 100755 index 000000000..16f09c357 --- /dev/null +++ b/iguana/pangea_fsm.c @@ -0,0 +1,1420 @@ +/****************************************************************************** + * Copyright © 2014-2016 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. * + * * + ******************************************************************************/ + +#include "pangea777.h" + + +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 + { + PNACL_message("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 + { + PNACL_message("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] ) + { + PNACL_message("pangea_neworder: neworder requires host nodeA to be first active node\n"); + return(-1); + } + slots[0] = 0; + for (i=1; inumaddrs); + return(-1); + } + } + for (i=0; iactive[i] = active[i]; + //PNACL_message("%llu ",(long long)sp->active[i]); + } + sp->numactive = dp->N = numactive; + dp->M = (numactive >> 1) + 1; + sp->myind = pangea_ind(sp,sp->myslot); + //PNACL_message("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; inumactive; i++) + { + if ( sp->active[i] == nxt64bits ) + continue; + active[n++] = sp->active[i]; + } + if ( n != sp->numactive-1 ) + PNACL_message("pangea_inactivate: cant find %llu\n",(long long)nxt64bits); + PNACL_message("T%d inactivate %llu n.%d\n",sp->myslot,(long long)nxt64bits,n); + pangea_neworder(dp,sp,active,n); + return(n); +} + +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 pangeanet777 *hn,struct cards777_pubdata *dp) +{ + int32_t hexlen; bits256 destpub; + hexlen = (int32_t)strlen(dp->newhand)+1; + memset(destpub.bytes,0,sizeof(destpub)); + pangeanet777_msg(0,destpub,hn,0,dp->newhand,hexlen); + dp->hand.startdecktime = (uint32_t)time(NULL); + PNACL_message("pangea_sendnewdeck new deck at %u\n",dp->hand.startdecktime); +} + +int32_t pangea_newdeck(union pangeanet777 *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; iN; i++) + { + if ( sp->balances[pangea_slot(sp,i)] <= 0 ) + removelist[m++] = sp->addrs[pangea_slot(sp,i)]; + } + if ( 0 && m > 0 ) + { + for (i=0; itable,0,0); + array = cJSON_CreateArray(); + for (i=0; iN; 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\",\"active\":%s,\"sender\":\"%llu\",\"timestamp\":\"%lu\",\"n\":%u,\"data\":\"","newhand",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); + PNACL_message("host sends NEWDECK checkprod.%llx numhands.%d\n",(long long)dp->hand.checkprod.txid,dp->numhands); + return(0); +} + +int32_t pangea_anotherhand(void *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; inumaddrs; i++) + { + total += sp->balances[i]; + PNACL_message("(p%d %.8f) ",i,dstr(sp->balances[i])); + if ( sp->balances[i] != 0 ) + { + if ( activej < 0 ) + activej = i; + n++; + } + } + PNACL_message("balances %.8f [%.8f]\n",dstr(total),dstr(total + dp->hostrake + dp->pangearake)); + if ( n == 1 ) + { + PNACL_message("Only player.%d left with %.8f | get sigs and cashout after numhands.%d\n",activej,dstr(sp->balances[pangea_slot(sp,activej)]),dp->numhands); + sleep(60); + return(1); + } + else + { + if ( sleepflag != 0 ) + sleep(sleepflag); + //dp->hand.betstarted = 0; + pangea_newdeck(hn); + if ( sleepflag != 0 ) + sleep(sleepflag); + } + return(n); +} + +int32_t _pangea_newhand(union pangeanet777 *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) ) + { + PNACL_message("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 ) + { + //PNACL_message("T%d (%s)\n",sp->myslot,jprint(array,0)); + for (i=0; itable,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)); + PNACL_message("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 pangeanet777 *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; iN; i++) + { + if ( dp->hand.othercardpubs[i] != dp->hand.checkprod.txid ) + break; + } + if ( i == dp->N ) + { + if ( PANGEA_PAUSE > 0 ) + sleep(PANGEA_PAUSE); + dp->hand.encodestarted = (uint32_t)time(NULL); + PNACL_message("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 pangeanet777 *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; iN; i++) + { + slot = pangea_slot(sp,i); + total += sp->balances[slot]; + PNACL_message("(p%d %.8f) ",i,dstr(sp->balances[slot])); + } + PNACL_message("balances %.8f [%.8f] | ",dstr(total),dstr(total + dp->hostrake + dp->pangearake)); + PNACL_message("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 pangeanet777 *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; int32_t i,slot,retval = -1; struct iguana_info *coin = 0; + slot = pangea_slot(sp,senderind); + dp->readymask |= (1 << slot); + if ( (coin= iguana_coinfind(dp->coinstr)) != 0 ) + addrtype = coin->chain->pubval;//coin777_addrtype(&p2shtype,dp->coinstr); + else return(-1); + 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; iN; 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; iN; i++) + pubkeys[i] = sp->btcpubkeys[pangea_slot(sp,i)]; + retval = create_MofN(coin->chain->p2shval,sp->redeemScript,sp->scriptPubKey,sp->multisigaddr,pubkeys,dp->M,dp->N); + PNACL_message("retval.%d scriptPubKey.(%s) multisigaddr.(%s) redeemScript.(%s)\n",retval,sp->scriptPubKey,sp->multisigaddr,sp->redeemScript); + } + PNACL_message("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); + 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; itable; + if ( data == 0 || datalen != sizeof(bits256)*dp->N ) + { + PNACL_message("pangea_card invalid datalen.%d vs %ld\n",datalen,(long)sizeof(bits256)*dp->N); + return(-1); + } + //PNACL_message("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); + //PNACL_message("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 ) + PNACL_message("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]); + PNACL_message(">>>>>>>>>> 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 ) + PNACL_message("player.%d decoded cardi.%d card.[%02d] but it doesnt validate\n",hn->client->H.slot,cardi,card); + } else PNACL_message("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 pangeanet777 *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 ) + { + PNACL_message("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 ) + { + PNACL_message("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)); + //PNACL_message("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 ) + PNACL_message("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); + //PNACL_message("-> 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>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; itable; + if ( data == 0 || datalen != (2 * dp->N) * (dp->N * dp->N * sizeof(bits256)) || (hex= malloc(maxlen)) == 0 ) + { + PNACL_message("pangea_preflop invalid datalen.%d vs %ld\n",datalen,(long)(2 * dp->N) * (dp->N * dp->N * sizeof(bits256))); + return(-1); + } + //PNACL_message("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; inumcards*dp->N; i++) + // PNACL_message("%llx ",(long long)priv->outcards[i].txid); + //PNACL_message("player.%d outcards\n",hn->client->H.slot); + for (cardi=0; cardiN*2; cardi++) + for (destplayer=0; destplayerN; 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 ) + PNACL_message("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); + } + //PNACL_message("issue preflop\n"); + if ( (zbuf= calloc(1,datalen*2+1)) != 0 ) + { + //init_hexbytes_noT(zbuf,priv->audits[0].bytes,datalen); + //PNACL_message("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 ( calc_crc32(0,(void *)hex,datalen) != calc_crc32(0,priv->audits[0].bytes,datalen) ) + { + PNACL_message("zbuf error len2.%d vs datalen.%d crcs %u vs %u\n%s\n",len2,datalen,calc_crc32(0,(void *)hex,datalen),calc_crc32(0,priv->audits[0].bytes,datalen),hex); + getchar(); + } + } + } + //PNACL_message("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 + { + //PNACL_message("sendout cards\n"); + for (iter=cardi=0; iter<2; iter++) + for (i=0; iN; i++,cardi++) + { + destplayer = (dp->button + i) % dp->N; + pangea_rwaudit(0,audit,priv->audits,cardi,destplayer,dp->N); + //PNACL_message("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); + //PNACL_message("[%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 pangeanet777 *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) ) + { + PNACL_message("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; inumcards*dp->N; i++) + // PNACL_message("%llx ",(long long)priv->outcards[i].txid); + PNACL_message("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 ) + { + //PNACL_message("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; iN; i++,cardi++) + for (destplayer=0; destplayerN; 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); + } + PNACL_message("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 pangeanet777 *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) ) + { + PNACL_message("pangea_final invalid datalen.%d vs %ld\n",datalen,(long)((dp->numcards * dp->N) * sizeof(bits256))); + return(-1); + } + if ( Debuglevel > 2 ) + PNACL_message("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 pangeanet777 *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) ) + { + PNACL_message("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; iN; i++) + { + if ( Debuglevel > 2 ) + PNACL_message("%llx ",(long long)dp->hand.havemasks[i]); + if ( bitweight(dp->hand.havemasks[i]) == 2 ) + n++; + } + if ( Debuglevel > 2 ) + PNACL_message(" | 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); + PNACL_message("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 pangeanet777 *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) ) + { + PNACL_message("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); + PNACL_message("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); + } + //PNACL_message("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; iN; i++) + dp->hand.hands[i][cardi - dp->N*2] = data[1]; + memcpy(dp->hand.community256[cardi - dp->N*2].bytes,data,sizeof(bits256)); + + //PNACL_message("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); + //PNACL_message("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 PNACL_message("dont start bets %d\n",cardi+1); + } + else + { + //PNACL_message("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); +} + +int32_t _pangea_turn(union pangeanet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t senderind) +{ + int32_t turni,cardi,i; char hex[2048]; uint64_t betsize = 0; struct pangea_info *sp = dp->table; + turni = juint(json,"turni"); + cardi = juint(json,"cardi"); + if ( Debuglevel > 2 ) + printf("P%d: got turn.%d from %d | cardi.%d summary[%d] crc.%u\n",hn->server->H.slot,turni,senderind,cardi,dp->summarysize,calc_crc32(0,dp->summary,dp->summarysize)); + dp->hand.turnis[senderind] = turni; + if ( senderind == 0 && sp != 0 ) + { + dp->hand.cardi = cardi; + dp->hand.betstarted = 1; + dp->hand.undergun = turni; + if ( hn->client->H.slot != pangea_slotA(dp->table) ) + { + pangea_checkantes(hn,dp); + memcpy(dp->hand.snapshot,dp->hand.bets,dp->N*sizeof(uint64_t)); + for (i=0; iN; i++) + if ( dp->hand.bets[i] > betsize ) + betsize = dp->hand.bets[i]; + dp->hand.snapshot[dp->N] = betsize; + //printf("player.%d sends confirmturn.%d\n",hn->client->H.slot,turni); + pangea_sendcmd(hex,hn,"confirmturn",-1,(void *)dp->hand.snapshot,sizeof(uint64_t)*(dp->N+1),cardi,turni); + } + } + return(0); +} + +int32_t _pangea_confirmturn(union pangeanet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t senderind) +{ + uint32_t starttime; int32_t i,turni,cardi; uint64_t betsize=0,amount=0; struct pangea_info *sp=0; char hex[1024]; + if ( data == 0 ) + { + printf("pangea_turn: null data\n"); + return(-1); + } + turni = juint(json,"turni"); + cardi = juint(json,"cardi"); + //printf("got confirmturn.%d cardi.%d sender.%d\n",turni,cardi,senderind); + //if ( datalen == sizeof(betsize) ) + // memcpy(&betsize,data,sizeof(betsize)); + starttime = dp->hand.starttime; + if ( (sp= dp->table) != 0 ) + { + if ( senderind == 0 && hn->client->H.slot != pangea_slotA(dp->table) ) + { + dp->hand.undergun = turni; + dp->hand.cardi = cardi; + memcpy(dp->hand.snapshot,data,(dp->N+1)*sizeof(uint64_t)); + for (betsize=i=0; iN; i++) + if ( dp->hand.bets[i] > betsize ) + betsize = dp->hand.bets[i]; + if ( betsize != dp->hand.snapshot[dp->N] ) + printf("T%d ERROR BETSIZE MISMATCH: %.8f vs %.8f\n",sp->myslot,dstr(betsize),dstr(dp->hand.snapshot[dp->N])); + dp->hand.betsize = betsize; + } + dp->hand.turnis[senderind] = turni; + for (i=0; iN; i++) + { + //printf("[i%d %d] ",i,dp->turnis[i]); + if ( dp->hand.turnis[i] != turni ) + break; + } + //printf("sp.%p vs turni.%d cardi.%d hand.cardi %d\n",sp,turni,cardi,dp->hand.cardi); + if ( hn->client->H.slot == pangea_slotA(dp->table) && i == dp->N ) + { + for (betsize=i=0; iN; i++) + if ( dp->hand.bets[i] > betsize ) + betsize = dp->hand.bets[i]; + dp->hand.betsize = dp->hand.snapshot[dp->N] = betsize; + //if ( Debuglevel > 2 ) + printf("player.%d sends confirmturn.%d cardi.%d betsize %.0f\n",hn->client->H.slot,dp->hand.undergun,dp->hand.cardi,dstr(betsize)); + if ( senderind != 0 ) + pangea_sendcmd(hex,hn,"confirmturn",-1,(void *)dp->hand.snapshot,sizeof(uint64_t)*(dp->N+1),dp->hand.cardi,dp->hand.undergun); + } + if ( senderind == 0 && (turni= dp->hand.undergun) == pangea_ind(dp->table,hn->client->H.slot) ) + { + if ( dp->hand.betsize != betsize ) + printf("P%d: pangea_turn warning hand.betsize %.8f != betsize %.8f\n",hn->client->H.slot,dstr(dp->hand.betsize),dstr(betsize)); + if ( sp->isbot[hn->client->H.slot] != 0 ) + pangea_bot(hn,dp,turni,cardi,betsize); + else if ( dp->hand.betstatus[pangea_ind(dp->table,hn->client->H.slot)] == CARDS777_FOLD || dp->hand.betstatus[pangea_ind(dp->table,hn->client->H.slot)] == CARDS777_ALLIN ) + pangea_sendcmd(hex,hn,"action",-1,(void *)&amount,sizeof(amount),cardi,0); + else if ( priv->autofold != 0 ) + pangea_sendcmd(hex,hn,"action",-1,(void *)&amount,sizeof(amount),cardi,0); + else + { + dp->hand.userinput_starttime = (uint32_t)time(NULL); + dp->hand.cardi = cardi; + dp->hand.betsize = betsize; + fprintf(stderr,"Waiting for user input cardi.%d: ",cardi); + } + if ( hn->client->H.slot == pangea_slotA(dp->table) ) + { + char *str = jprint(pangea_tablestatus(sp),1); + printf("%s\n",str); + free(str); + } + //pangea_statusprint(dp,priv,pangea_ind(dp->table,hn->client->H.slot)); + } + } + return(0); +} + +void pangea_sendsummary(union pangeanet777 *hn,struct cards777_pubdata *dp,struct cards777_privdata *priv) +{ + char *hex; + if ( (hex= malloc(dp->summarysize*2 + 4096)) != 0 ) + { + pangea_sendcmd(hex,hn,"summary",-1,dp->summary,dp->summarysize,0,0); + free(hex); + } +} + +int32_t _pangea_gotsummary(union pangeanet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t senderind) +{ + char *otherhist,*handhist = 0; int32_t matched = 0; struct pangea_info *sp = dp->table; + if ( Debuglevel > 2 ) // ordering changes crc + printf("player.%d [%d]: got summary.%d from %d memcmp.%d\n",hn->client->H.slot,dp->summarysize,datalen,senderind,memcmp(data,dp->summary,datalen)); + if ( datalen == dp->summarysize ) + { + if ( memcmp(dp->summary,data,datalen) == 0 ) + { + //printf("P%d: matched senderind.%d\n",hn->client->H.slot,senderind); + matched = 1; + } + else + { + if ( (handhist= pangea_dispsummary(sp,1,dp->summary,dp->summarysize,sp->tableid,dp->numhands-1,dp->N)) != 0 ) + { + if ( (otherhist= pangea_dispsummary(sp,1,data,datalen,sp->tableid,dp->numhands-1,dp->N)) != 0 ) + { + if ( strcmp(handhist,otherhist) == 0 ) + { + //printf("P%d: matched B senderind.%d\n",hn->client->H.slot,senderind); + matched = 1; + } + else printf("\n[%s] MISMATCHED vs \n[%s]\n",handhist,otherhist); + free(otherhist); + } else printf("error getting otherhist\n"); + free(handhist); + } else printf("error getting handhist\n"); + } + } + if ( matched != 0 ) + dp->summaries |= (1LL << senderind); + else + { + //printf("P%d: MISMATCHED senderind.%d\n",hn->client->H.slot,senderind); + dp->mismatches |= (1LL << senderind); + } + if ( senderind == 0 && hn->client->H.slot != pangea_slotA(dp->table) ) + pangea_sendsummary(hn,dp,priv); + if ( (dp->mismatches | dp->summaries) == (1LL << dp->N)-1 ) + { + if ( Debuglevel > 2 ) + printf("P%d: hand summary matches.%llx errors.%llx | size.%d\n",hn->client->H.slot,(long long)dp->summaries,(long long)dp->mismatches,dp->summarysize); + //if ( handhist == 0 && (handhist= pangea_dispsummary(sp,1,dp->summary,dp->summarysize,sp->tableid,dp->numhands-1,dp->N)) != 0 ) + // printf("HAND.(%s)\n",handhist), free(handhist); + if ( hn->server->H.slot == 0 ) + { + dp->mismatches = dp->summaries = 0; + pangea_anotherhand(hn,dp,3); + } + } + return(0); +} + +void pangea_finish(union pangeanet777 *hn,struct cards777_pubdata *dp) +{ + int32_t j,n,r,norake = 0; uint64_t sidepots[CARDS777_MAXPLAYERS][CARDS777_MAXPLAYERS],list[CARDS777_MAXPLAYERS],pangearake,rake; int64_t balances[CARDS777_MAXPLAYERS]; + uint32_t changes; uint16_t busted,rebuy; struct pangea_info *sp = dp->table; + if ( dp->hand.finished == 0 ) + { + memset(sidepots,0,sizeof(sidepots)); + n = pangea_sidepots(1,sidepots,dp,dp->hand.bets); + if ( dp->hand.community[0] == 0xff ) + norake = 1; + for (pangearake=rake=j=0; jhand.won,&pangearake,sidepots[j],hn,norake == 0 ? dp->rakemillis : 0); + dp->hostrake += rake; + dp->pangearake += pangearake; + dp->hand.hostrake = rake; + dp->hand.pangearake = pangearake; + dp->hand.finished = (uint32_t)time(NULL); + for (j=busted=rebuy=r=0; jN; j++) + { + balances[j] = sp->balances[pangea_slot(sp,j)]; + //balances[j] += dp->hand.won[j]; + //sp->balances[pangea_slot(sp,j)] = balances[j]; + if ( dp->snapshot[pangea_slot(sp,j)] > 0 && balances[j] <= 0 ) + { + busted |= (1 << j); + list[r++] = sp->active[j]; + } + else if ( dp->snapshot[pangea_slot(sp,j)] <= 0 && balances[j] > 0 ) + rebuy |= (1 << j); + } + changes = (((uint32_t)rebuy<<20) | ((uint32_t)busted<<4) | (dp->N&0xf)); + pangea_summary(hn,dp,CARDS777_CHANGES,(void *)&changes,sizeof(changes),(void *)balances,sizeof(uint64_t)*dp->N); + pangea_summary(hn,dp,CARDS777_RAKES,(void *)&rake,sizeof(rake),(void *)&pangearake,sizeof(pangearake)); + if ( hn->client->H.slot == pangea_slotA(dp->table) ) + { + char *sumstr,*statstr; + statstr = jprint(pangea_tablestatus(dp->table),1); + sumstr = pangea_dispsummary(dp->table,1,dp->summary,dp->summarysize,0,dp->numhands-1,dp->N); + printf("%s\n\n%s",statstr,sumstr); + free(statstr), free(sumstr); + pangea_sendsummary(hn,dp,hn->client->H.privdata); + } + if ( 0 && busted != 0 ) + { + for (j=0; jactive[0] ) + { + pangea_inactivate(dp,sp,list[j]); + printf("T%d: INACTIVATE.[%d] %llu\n",sp->myslot,j,(long long)list[j]); + } + } + } + } +} + +int32_t pangea_lastman(union pangeanet777 *hn,struct cards777_pubdata *dp,struct cards777_privdata *priv) +{ + int32_t activej = -1; char hex[1024]; + if ( dp->hand.betstarted != 0 && pangea_actives(&activej,dp) <= 1 ) + { + if ( dp->hand.finished != 0 ) + { + printf("DUPLICATE LASTMAN!\n"); + return(1); + } + if ( 0 && hn->server->H.slot == activej && priv->automuck == 0 ) + { + pangea_sendcmd(hex,hn,"faceup",-1,priv->holecards[0].bytes,sizeof(priv->holecards[0]),priv->cardis[0],priv->cardis[0] != 0xff); + pangea_sendcmd(hex,hn,"faceup",-1,priv->holecards[1].bytes,sizeof(priv->holecards[1]),priv->cardis[1],priv->cardis[1] != 0xff); + } + pangea_finish(hn,dp); + return(1); + } + return(0); +} + +void pangea_startbets(union pangeanet777 *hn,struct cards777_pubdata *dp,int32_t cardi) +{ + uint32_t now,i; char hex[1024]; + sleep(3); + if ( dp->hand.betstarted == 0 ) + { + dp->hand.betstarted = 1; + } else dp->hand.betstarted++; + dp->hand.numactions = 0; + dp->hand.cardi = cardi; + now = (uint32_t)time(NULL); + memset(dp->hand.actions,0,sizeof(dp->hand.actions)); + memset(dp->hand.turnis,0xff,sizeof(dp->hand.turnis)); + dp->hand.undergun = ((dp->button + 3) % dp->N); + if ( cardi > dp->N*2 ) + { + for (i=0; iN; i++) + dp->hand.snapshot[i] = dp->hand.bets[i]; + } + else pangea_checkantes(hn,dp); + dp->hand.snapshot[dp->N] = dp->hand.betsize; + printf("STARTBETS.%d cardi.%d numactions.%d undergun.%d betsize %.8f dp->N %d\n",dp->hand.betstarted,cardi,dp->hand.numactions,dp->hand.undergun,dstr(dp->hand.betsize),dp->N); + pangea_sendcmd(hex,hn,"turn",-1,(void *)dp->hand.snapshot,sizeof(uint64_t)*(dp->N+1),cardi,dp->hand.undergun); + /*for (i=0; iN; i++) + { + j = (dp->hand.undergun + i) % dp->N; + if ( dp->hand.betstatus[j] != CARDS777_FOLD && dp->hand.betstatus[j] != CARDS777_ALLIN ) + break; + dp->hand.numactions++; + } + if ( i != dp->N ) + { + dp->hand.undergun = j; + pangea_sendcmd(hex,hn,"turn",-1,(void *)dp->hand.snapshot,sizeof(uint64_t)*(dp->N+1),cardi,dp->hand.undergun); + } + else if ( pangea_lastman(hn,dp,hn->client->H.privdata) > 0 ) + { + pangea_sendsummary(hn,dp,hn->client->H.privdata); + return; + } else printf("UNEXPECTED condition missing lastman\n");*/ +} + +int32_t _pangea_action(union pangeanet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t senderind) +{ + uint32_t now; int32_t action,cardi,i,j,destplayer = 0; bits256 audit[CARDS777_MAXPLAYERS]; char hex[1024]; uint8_t tmp; uint64_t amount = 0; + action = juint(json,"turni"); + cardi = juint(json,"cardi"); + memcpy(&amount,data,sizeof(amount)); + if ( cardi < 2*dp->N ) + { + char *str = jprint(json,0); + printf("pangea_action: illegal cardi.%d: (%s)\n",cardi,str); + free(str); + } + if ( senderind != dp->hand.undergun ) + { + printf("T%d: out of turn action.%d by player.%d (undergun.%d) cardi.%d amount %.8f\n",hn->client->H.slot,action,senderind,dp->hand.undergun,cardi,dstr(amount)); + return(-1); + } + tmp = senderind; + pangea_bet(hn,dp,senderind,amount,CARDS777_CHECK); + dp->hand.actions[senderind] = action; + dp->hand.undergun = (dp->hand.undergun + 1) % dp->N; + dp->hand.numactions++; + if ( Debuglevel > 2 )//|| hn->client->H.slot == 0 ) + printf("player.%d: got action.%d cardi.%d senderind.%d -> undergun.%d numactions.%d\n",hn->client->H.slot,action,cardi,senderind,dp->hand.undergun,dp->hand.numactions); + if ( pangea_lastman(hn,dp,priv) > 0 ) + return(0); + if ( hn->client->H.slot == pangea_slotA(dp->table) ) + { + now = (uint32_t)time(NULL); + for (i=j=0; iN; i++) + { + j = (dp->hand.undergun + i) % dp->N; + if ( dp->hand.betstatus[j] == CARDS777_FOLD || dp->hand.betstatus[j] == CARDS777_ALLIN ) + { + dp->hand.actions[j] = dp->hand.betstatus[j]; + //printf("skip player.%d\n",j); + dp->hand.numactions++; + } else break; + } + dp->hand.undergun = j; + if ( dp->hand.numactions < dp->N ) + { + //printf("T%d: senderind.%d i.%d j.%d -> undergun.%d numactions.%d\n",hn->client->H.slot,senderind,i,j,dp->hand.undergun,dp->hand.numactions); + //if ( senderind != 0 ) + pangea_sendcmd(hex,hn,"turn",-1,(void *)dp->hand.snapshot,sizeof(uint64_t)*(dp->N+1),dp->hand.cardi,dp->hand.undergun); + } + else + { + for (i=0; i<5; i++) + { + if ( dp->hand.community[i] == 0xff ) + break; + printf("%02x ",dp->hand.community[i]); + } + printf("COMMUNITY\n"); + if ( i == 0 ) + { + if ( dp->hand.cardi != dp->N * 2 ) + printf("cardi mismatch %d != %d\n",dp->hand.cardi,dp->N * 2); + cardi = dp->hand.cardi; + printf("decode flop\n"); + for (i=0; i<3; i++,cardi++) + { + memset(audit,0,sizeof(audit)); + audit[0] = dp->hand.final[cardi*dp->N + destplayer]; + pangea_sendcmd(hex,hn,"decoded",-1,audit[0].bytes,sizeof(bits256)*dp->N,cardi,dp->N-1); + } + } + else if ( i == 3 ) + { + if ( dp->hand.cardi != dp->N * 2+3 ) + printf("cardi mismatch %d != %d\n",dp->hand.cardi,dp->N * 2 + 3); + cardi = dp->hand.cardi; + printf("decode turn\n"); + memset(audit,0,sizeof(audit)); + audit[0] = dp->hand.final[cardi*dp->N + destplayer]; + pangea_sendcmd(hex,hn,"decoded",-1,audit[0].bytes,sizeof(bits256)*dp->N,cardi,dp->N-1); + //pangea_sendcmd(hex,hn,"decoded",-1,dp->hand.final[cardi*dp->N + destplayer].bytes,sizeof(dp->hand.final[cardi*dp->N + destplayer]),cardi,dp->N-1); + } + else if ( i == 4 ) + { + printf("decode river\n"); + if ( dp->hand.cardi != dp->N * 2+4 ) + printf("cardi mismatch %d != %d\n",dp->hand.cardi,dp->N * 2+4); + cardi = dp->hand.cardi; + memset(audit,0,sizeof(audit)); + audit[0] = dp->hand.final[cardi*dp->N + destplayer]; + pangea_sendcmd(hex,hn,"decoded",-1,audit[0].bytes,sizeof(bits256)*dp->N,cardi,dp->N-1); + //pangea_sendcmd(hex,hn,"decoded",-1,dp->hand.final[cardi*dp->N + destplayer].bytes,sizeof(dp->hand.final[cardi*dp->N + destplayer]),cardi,dp->N-1); + } + else + { + cardi = dp->N * 2 + 5; + if ( dp->hand.cardi != dp->N * 2+5 ) + printf("cardi mismatch %d != %d\n",dp->hand.cardi,dp->N * 2+5); + for (i=0; iN; i++) + { + j = (dp->hand.lastbettor + i) % dp->N; + if ( dp->hand.betstatus[j] != CARDS777_FOLD ) + break; + } + dp->hand.undergun = j; + printf("sent showdown request for undergun.%d\n",j); + pangea_sendcmd(hex,hn,"showdown",-1,(void *)&dp->hand.betsize,sizeof(dp->hand.betsize),cardi,dp->hand.undergun); + } + } + } + if ( Debuglevel > 2 )// || hn->client->H.slot == 0 ) + { + char *str = jprint(pangea_tablestatus(dp->table),1); + printf("player.%d got pangea_action.%d for player.%d action.%d amount %.8f | numactions.%d\n%s\n",hn->client->H.slot,cardi,senderind,action,dstr(amount),dp->hand.numactions,str); + free(str); + } + return(0); +} + +int32_t pangea_myrank(struct cards777_pubdata *dp,int32_t senderind) +{ + int32_t i; uint32_t myrank = dp->hand.handranks[senderind]; + for (i=0; iN; i++) + if ( i != senderind && dp->hand.handranks[i] > myrank ) + return(-1); + return(myrank != 0); +} + +int32_t _pangea_showdown(union pangeanet777 *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 i,turni,cardi; uint64_t amount = 0; + turni = juint(json,"turni"); + cardi = juint(json,"cardi"); + if ( Debuglevel > 2 ) + printf("P%d: showdown from sender.%d\n",hn->client->H.slot,senderind); + if ( dp->hand.betstatus[pangea_ind(dp->table,hn->client->H.slot)] != CARDS777_FOLD && ((priv->automuck == 0 && dp->hand.actions[pangea_ind(dp->table,hn->client->H.slot)] != CARDS777_SENTCARDS) || (turni == pangea_ind(dp->table,hn->client->H.slot) && dp->hand.lastbettor == pangea_ind(dp->table,hn->client->H.slot))) ) + { + if ( priv->automuck != 0 && pangea_myrank(dp,pangea_ind(dp->table,hn->client->H.slot)) < 0 ) + pangea_sendcmd(hex,hn,"action",-1,(void *)&amount,sizeof(amount),cardi,CARDS777_FOLD); + else + { + pangea_sendcmd(hex,hn,"faceup",-1,priv->holecards[0].bytes,sizeof(priv->holecards[0]),priv->cardis[0],pangea_ind(dp->table,hn->client->H.slot)); + pangea_sendcmd(hex,hn,"faceup",-1,priv->holecards[1].bytes,sizeof(priv->holecards[1]),priv->cardis[1],pangea_ind(dp->table,hn->client->H.slot)); + dp->hand.actions[pangea_ind(dp->table,hn->client->H.slot)] = CARDS777_SENTCARDS; + } + } + if ( pangea_lastman(hn,dp,priv) > 0 ) + return(0); + if ( hn->client->H.slot == pangea_slotA(dp->table) && senderind != 0 ) + { + for (i=0; iN; i++) + { + dp->hand.undergun = (dp->hand.undergun + 1) % dp->N; + if ( dp->hand.undergun == dp->hand.lastbettor ) + { + printf("all players queried with showdown handmask.%x finished.%u\n",dp->hand.handmask,dp->hand.finished); + return(0); + } + if ( dp->hand.betstatus[dp->hand.undergun] != CARDS777_FOLD ) + break; + } + printf("senderind.%d host sends showdown for undergun.%d\n",senderind,dp->hand.undergun); + pangea_sendcmd(hex,hn,"showdown",-1,(void *)&dp->hand.betsize,sizeof(dp->hand.betsize),cardi,dp->hand.undergun); + } + return(0); +} + +char *_pangea_input(uint64_t my64bits,uint64_t tableid,cJSON *json) +{ + char *actionstr; uint64_t sum,amount=0; int32_t action=0,num,threadid; struct pangea_info *sp; struct cards777_pubdata *dp; char hex[4096]; + threadid = juint(json,"threadid"); + if ( (sp= pangea_threadtables(&num,threadid,tableid)) == 0 ) + return(clonestr("{\"error\":\"you are not playing on any tables\"}")); + if ( 0 && num != 1 ) + return(clonestr("{\"error\":\"more than one active table\"}")); + else if ( (dp= sp->dp) == 0 ) + return(clonestr("{\"error\":\"no pubdata ptr for table\"}")); + else if ( dp->hand.undergun != pangea_ind(sp,sp->myslot) || dp->hand.betsize == 0 ) + { + printf("undergun.%d threadid.%d myind.%d\n",dp->hand.undergun,sp->tp->threadid,pangea_ind(sp,sp->myslot)); + return(clonestr("{\"error\":\"not your turn\"}")); + } + else if ( (actionstr= jstr(json,"action")) == 0 ) + return(clonestr("{\"error\":\"on action specified\"}")); + else + { + if ( strcmp(actionstr,"check") == 0 || strcmp(actionstr,"call") == 0 || strcmp(actionstr,"bet") == 0 || strcmp(actionstr,"raise") == 0 || strcmp(actionstr,"allin") == 0 || strcmp(actionstr,"fold") == 0 ) + { + sum = dp->hand.bets[pangea_ind(sp,sp->myslot)]; + if ( strcmp(actionstr,"allin") == 0 ) + amount = sp->balances[sp->myslot], action = CARDS777_ALLIN; + else if ( strcmp(actionstr,"bet") == 0 ) + amount = j64bits(json,"amount"), action = 1; + else + { + if ( dp->hand.betsize == sum ) + { + if ( strcmp(actionstr,"check") == 0 || strcmp(actionstr,"call") == 0 ) + action = 0; + else if ( strcmp(actionstr,"raise") == 0 ) + { + action = 1; + if ( (amount= dp->hand.lastraise) < j64bits(json,"amount") ) + amount = j64bits(json,"amount"); + } + else printf("unsupported userinput command.(%s)\n",actionstr); + } + else + { + if ( strcmp(actionstr,"check") == 0 || strcmp(actionstr,"call") == 0 ) + action = 1, amount = (dp->hand.betsize - sum); + else if ( strcmp(actionstr,"raise") == 0 ) + { + action = 2; + amount = (dp->hand.betsize - sum); + if ( amount < dp->hand.lastraise ) + amount = dp->hand.lastraise; + if ( j64bits(json,"amount") > amount ) + amount = j64bits(json,"amount"); + } + else if ( strcmp(actionstr,"fold") == 0 ) + action = 0; + else printf("unsupported userinput command.(%s)\n",actionstr); + } + } + if ( amount > sp->balances[sp->myslot] ) + amount = sp->balances[sp->myslot], action = CARDS777_ALLIN; + pangea_sendcmd(hex,&sp->tp->hn,"action",-1,(void *)&amount,sizeof(amount),dp->hand.cardi,action); + printf("ACTION.(%s)\n",hex); + return(clonestr("{\"result\":\"action submitted\"}")); + } + else return(clonestr("{\"error\":\"illegal action specified, must be: check, call, bet, raise, fold or allin\"}")); + } +} + +int32_t _pangea_ping(union pangeanet777 *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; ihand.community[i] = juint(jitem(array,i),0); + }*/ + } + //PNACL_message("player.%d GOTPING.(%s) %llx\n",hn->client->H.slot,jprint(json,0),(long long)dp->othercardpubs[senderind]); + return(0); +} + +void p_angea_chat(uint64_t senderbits,void *buf,int32_t len,int32_t senderind) +{ + PNACL_message(">>>>>>>>>>> CHAT FROM.%d %llu: (%s)\n",senderind,(long long)senderbits,(char *)buf); +} + +int32_t pangea_poll(uint64_t *senderbitsp,uint32_t *timestampp,union pangeanet777 *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 ) + PNACL_message("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 ) + { + PNACL_message("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); + //PNACL_message("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 ) + { + PNACL_message("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 ) + { + PNACL_message("len too big for pangea_poll\n"); + goto cleanup; + } + decode_hex(buf,len,hexstr); + } else if ( hexstr != 0 ) + PNACL_message("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,"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); +} + +void pangea_serverstate(union pangeanet777 *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 ) + { + PNACL_message("HANDGAP\n"); + pangea_anotherhand(hn,dp,3); + } + if ( dp->hand.betstarted == 0 && dp->newhand[0] == 0 ) + { + static uint32_t disptime; + for (i=n=0; iN; i++) + { + if ( Debuglevel > 2 ) + PNACL_message("%llx ",(long long)dp->hand.havemasks[i]); + if ( bitweight(dp->hand.havemasks[i]) == 2 ) + n++; + } + if ( n < dp->N ) + { + for (i=0; iN; 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 ) + { + PNACL_message("send newdeck len.%ld\n",(long)strlen(dp->newhand)); + pangea_newdeck(hn); + PNACL_message("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; jN; j++) + PNACL_message("%.8f ",dstr(sp->balances[pangea_slot(sp,i)])); + PNACL_message("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_idle(struct supernet_info *plugin) +{ + int32_t i,n,m,pinggap = 1; uint64_t senderbits; uint32_t timestamp; struct pangea_thread *tp; union pangeanet777 *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; + //PNACL_message("pangea idle player.%d\n",hn->client->H.slot); + if ( hn->client->H.done == 0 ) + { + n++; + if ( pangeanet777_idle(hn) != 0 ) + m++; + pangea_poll(&senderbits,×tamp,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 ) + { + PNACL_message("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 ) + usleep(3000); + } + //for (i=0; i<_PANGEA_MAXTHREADS; i++) + // if ( THREADS[i] != 0 && Pangea_waiting != 0 ) + // pangea_userpoll(&THREADS[i]->hn); + return(0); +} diff --git a/iguana/pangea_funds.c b/iguana/pangea_funds.c new file mode 100755 index 000000000..52cd1732b --- /dev/null +++ b/iguana/pangea_funds.c @@ -0,0 +1,970 @@ +/****************************************************************************** + * Copyright © 2014-2016 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. * + * * + ******************************************************************************/ + +#include "pangea777.h" + +char *pangea_typestr(uint8_t type) +{ + static char err[64]; + switch ( type ) + { + case 0xff: return("fold"); + case CARDS777_START: return("start"); + case CARDS777_ANTE: return("ante"); + case CARDS777_SMALLBLIND: return("smallblind"); + case CARDS777_BIGBLIND: return("bigblind"); + case CARDS777_CHECK: return("check"); + case CARDS777_CALL: return("call"); + case CARDS777_BET: return("bet"); + case CARDS777_RAISE: return("raise"); + case CARDS777_FULLRAISE: return("fullraise"); + case CARDS777_SENTCARDS: return("sentcards"); + case CARDS777_ALLIN: return("allin"); + case CARDS777_FACEUP: return("faceup"); + case CARDS777_WINNINGS: return("won"); + case CARDS777_RAKES: return("rakes"); + case CARDS777_CHANGES: return("changes"); + case CARDS777_SNAPSHOT: return("snapshot"); + } + sprintf(err,"unknown type.%d",type); + return(err); +} + +cJSON *pangea_handitem(int32_t *cardip,cJSON **pitemp,uint8_t type,uint64_t valA,uint64_t *bits64p,bits256 card,int32_t numplayers) +{ + int32_t cardi,n,i,rebuy,busted; char str[128],hexstr[65],cardpubs[(CARDS777_MAXCARDS+1)*64+1]; cJSON *item,*array,*pitem = 0; + item = cJSON_CreateObject(); + *cardip = -1; + switch ( type ) + { + case CARDS777_START: + jaddnum(item,"handid",valA); + init_hexbytes_noT(cardpubs,(void *)bits64p,(int32_t)((CARDS777_MAXCARDS+1) * sizeof(bits256))); + jaddstr(item,"cardpubs",cardpubs); + break; + case CARDS777_RAKES: + jaddnum(item,"hostrake",dstr(valA)); + jaddnum(item,"pangearake",dstr(*bits64p)); + break; + case CARDS777_SNAPSHOT: + jaddnum(item,"handid",valA); + array = cJSON_CreateArray(); + for (i=0; i>4) & 0xffff); + rebuy = (int32_t)((valA>>20) & 0xffff); + if ( busted != 0 ) + jaddnum(item,"busted",busted); + if ( rebuy != 0 ) + jaddnum(item,"rebuy",rebuy); + array = cJSON_CreateArray(); + for (i=0; i= 0 && valA < numplayers ) + jaddnum(item,"player",valA); + jaddnum(item,"won",dstr(*bits64p)); + if ( pitem == 0 ) + pitem = cJSON_CreateObject(); + jaddnum(pitem,"won",dstr(*bits64p)); + break; + case CARDS777_FACEUP: + *cardip = cardi = (int32_t)(valA >> 8); + if ( cardi >= 0 && cardi < 52 ) + jaddnum(item,"cardi",cardi); + else printf("illegal cardi.%d valA.%llu\n",cardi,(long long)valA); + valA &= 0xff; + if ( (int32_t)valA >= 0 && valA < numplayers ) + jaddnum(item,"player",valA); + else if ( valA == 0xff ) + jaddnum(item,"community",cardi - numplayers*2); + cardstr(str,card.bytes[1]); + jaddnum(item,str,card.bytes[1]); + init_hexbytes_noT(hexstr,card.bytes,sizeof(card)); + jaddstr(item,"privkey",hexstr); + break; + default: + if ( (int32_t)valA >= 0 && valA < numplayers ) + jaddnum(item,"player",valA); + jaddstr(item,"action",pangea_typestr(type)); + if ( pitem == 0 ) + pitem = cJSON_CreateObject(); + if ( *bits64p != 0 ) + { + jaddnum(item,"bet",dstr(*bits64p)); + jaddnum(pitem,pangea_typestr(type),dstr(*bits64p)); + } + else jaddstr(pitem,"action",pangea_typestr(type)); + break; + } + *pitemp = pitem; + return(item); +} + +int32_t pangea_parsesummary(uint8_t *typep,uint64_t *valAp,uint64_t *bits64p,bits256 *cardp,uint8_t *summary,int32_t len) +{ + int32_t handid; uint16_t cardi_player; uint32_t changes=0; uint8_t player; + *bits64p = 0; + memset(cardp,0,sizeof(*cardp)); + len += SuperNET_copybits(1,&summary[len],(void *)typep,sizeof(*typep)); + if ( *typep == 0 ) + { + printf("len.%d type.%d [%d]\n",len,*typep,summary[len-1]); + return(-1); + } + if ( *typep == CARDS777_START || *typep == CARDS777_SNAPSHOT ) + len += SuperNET_copybits(1,&summary[len],(void *)&handid,sizeof(handid)), *valAp = handid; + else if ( *typep == CARDS777_CHANGES ) + len += SuperNET_copybits(1,&summary[len],(void *)&changes,sizeof(changes)), *valAp = changes; + else if ( *typep == CARDS777_RAKES ) + len += SuperNET_copybits(1,&summary[len],(void *)valAp,sizeof(*valAp)); + else if ( *typep == CARDS777_FACEUP ) + len += SuperNET_copybits(1,&summary[len],(void *)&cardi_player,sizeof(cardi_player)), *valAp = cardi_player; + else len += SuperNET_copybits(1,&summary[len],(void *)&player,sizeof(player)), *valAp = player; + if ( *typep == CARDS777_FACEUP ) + len += SuperNET_copybits(1,&summary[len],cardp->bytes,sizeof(*cardp)); + else if ( *typep == CARDS777_START ) + len += SuperNET_copybits(1,&summary[len],(void *)bits64p,sizeof(bits256)*(CARDS777_MAXCARDS+1)); + else if ( *typep == CARDS777_SNAPSHOT ) + len += SuperNET_copybits(1,&summary[len],(void *)bits64p,sizeof(*bits64p) * CARDS777_MAXPLAYERS); + else if ( *typep == CARDS777_CHANGES ) + len += SuperNET_copybits(1,&summary[len],(void *)bits64p,sizeof(*bits64p) * (changes & 0xf)); + else len += SuperNET_copybits(1,&summary[len],(void *)bits64p,sizeof(*bits64p)); + return(len); +} + +void pangea_summary(union pangeanet777 *hn,struct cards777_pubdata *dp,uint8_t type,void *arg0,int32_t size0,void *arg1,int32_t size1) +{ + uint64_t valA,bits64[CARDS777_MAXPLAYERS + (CARDS777_MAXCARDS+1)*4]; bits256 card; uint8_t checktype; char *str; + cJSON *item,*pitem; int32_t len,cardi,startlen = dp->summarysize; + if ( type == 0 ) + { + printf("type.0\n"); getchar(); + } + //printf("summarysize.%d type.%d [%02x %02x]\n",dp->summarysize,type,*(uint8_t *)arg0,*(uint8_t *)arg1); + dp->summarysize += SuperNET_copybits(0,&dp->summary[dp->summarysize],(void *)&type,sizeof(type)); + //printf("-> %d\n",dp->summary[dp->summarysize-1]); + dp->summarysize += SuperNET_copybits(0,&dp->summary[dp->summarysize],arg0,size0); + dp->summarysize += SuperNET_copybits(0,&dp->summary[dp->summarysize],arg1,size1); + //printf("startlen.%d summarysize.%d\n",startlen,dp->summarysize); + len = pangea_parsesummary(&checktype,&valA,bits64,&card,dp->summary,startlen); + if ( len != dp->summarysize || checktype != type || memcmp(&valA,arg0,size0) != 0 ) + printf("pangea_summary parse error [%d] (%d vs %d) || (%d vs %d).%d || cmp.%d size0.%d size1.%d\n",startlen,len,dp->summarysize,checktype,type,dp->summary[startlen],memcmp(&valA,arg0,size0),size0,size1); + if ( card.txid != 0 && memcmp(card.bytes,arg1,sizeof(card)) != 0 ) + printf("pangea_summary: parse error card mismatch %llx != %llx\n",(long long)card.txid,*(long long *)arg1); + else if ( card.txid == 0 && memcmp(arg1,bits64,size1) != 0 ) + printf("pangea_summary: parse error bits64 %llx != %llx\n",(long long)bits64[0],*(long long *)arg0); + if ( 1 && hn->client->H.slot == pangea_slotA(dp->table) ) + { + if ( (item= pangea_handitem(&cardi,&pitem,type,valA,bits64,card,dp->N)) != 0 ) + { + str = jprint(item,1); + printf("ITEM.(%s)\n",str); + free(str); + } + if ( pitem != 0 ) + { + str = jprint(pitem,1); + printf("PITEM.(%s)\n",str); + free(str); + } + } + if ( Debuglevel > 2 )//|| hn->client->H.slot == pangea_slotA(dp->table) ) + printf("pangea_summary.%d %d | summarysize.%d crc.%u\n",type,*(uint8_t *)arg0,dp->summarysize,calc_crc32(0,dp->summary,dp->summarysize)); +} + +char *pangea_dispsummary(struct pangea_info *sp,int32_t verbose,uint8_t *summary,int32_t summarysize,uint64_t tableid,int32_t handid,int32_t numplayers) +{ + int32_t i,cardi,n = 0,len = 0; uint8_t type; uint64_t valA,bits64[CARDS777_MAXPLAYERS + (CARDS777_MAXCARDS+1)*4]; bits256 card; + cJSON *item,*json,*all,*cardis[52],*players[CARDS777_MAXPLAYERS],*pitem,*array = cJSON_CreateArray(); + all = cJSON_CreateArray(); + memset(cardis,0,sizeof(cardis)); + memset(players,0,sizeof(players)); + for (i=0; i= 0 && cardi < 52 ) + { + //printf("cardis[%d] <- %p\n",cardi,item); + cardis[cardi] = item; + } + else jaddi(array,item); + item = 0; + } + if ( pitem != 0 ) + { + jaddnum(pitem,"n",n), n++; + if ( (int32_t)valA >= 0 && valA < numplayers ) + jaddi(players[valA],pitem); + else free_json(pitem), printf("illegal player.%llu\n",(long long)valA); + pitem = 0; + } + } + for (i=0; inumactive; i++) + // jaddi64bits(array,sp->active[i]); + //jadd(json,"active",array); + for (i=0; inumactive; i++) + printf("%llu ",(long long)sp->active[i]); + printf("sp->numactive[%d]\n",sp->numactive); + } + jaddnum(json,"size",summarysize); + jaddnum(json,"handid",handid); + //jaddnum(json,"crc",_crc32(0,summary,summarysize)); + jadd(json,"hand",array); + array = cJSON_CreateArray(); + for (i=0; i<52; i++) + if ( cardis[i] != 0 ) + jaddi(array,cardis[i]); + jadd(json,"cards",array); + //jadd(json,"players",all); + return(jprint(json,1)); + } +} + +void pangea_fold(union pangeanet777 *hn,struct cards777_pubdata *dp,int32_t player) +{ + uint8_t tmp; + //printf("player.%d folded\n",player); //getchar(); + dp->hand.handmask |= (1 << player); + dp->hand.betstatus[player] = CARDS777_FOLD; + dp->hand.actions[player] = CARDS777_FOLD; + tmp = player; + pangea_summary(hn,dp,CARDS777_FOLD,&tmp,sizeof(tmp),(void *)&dp->hand.bets[player],sizeof(dp->hand.bets[player])); +} + +uint64_t pangea_totalbet(struct cards777_pubdata *dp) +{ + int32_t j; uint64_t total; + for (total=j=0; jN; j++) + total += dp->hand.bets[j]; + return(total); +} + +int32_t pangea_actives(int32_t *activej,struct cards777_pubdata *dp) +{ + int32_t i,n; + *activej = -1; + for (i=n=0; iN; i++) + { + if ( dp->hand.betstatus[i] != CARDS777_FOLD ) + { + if ( *activej < 0 ) + *activej = i; + n++; + } + } + return(n); +} + +struct pangea_info *pangea_usertables(int32_t *nump,uint64_t my64bits,uint64_t tableid) +{ + int32_t i,j,num = 0; struct pangea_info *sp,*retsp = 0; + *nump = 0; + for (i=0; inumaddrs; j++) + if ( sp->addrs[j] == my64bits && (tableid == 0 || sp->tableid == tableid) ) + { + if ( num++ == 0 ) + { + retsp = sp; + break; + } + } + } + } + *nump = num; + return(retsp); +} + +struct pangea_info *pangea_threadtables(int32_t *nump,int32_t threadid,uint64_t tableid) +{ + int32_t i,j,num = 0; struct pangea_info *sp,*retsp = 0; + *nump = 0; + for (i=0; inumaddrs; j++) + if ( sp->tp != 0 && sp->tp->threadid == threadid && (tableid == 0 || sp->tableid == tableid) ) + { + if ( num++ == 0 ) + { + retsp = sp; + break; + } + } + } + } + *nump = num; + return(retsp); +} + +int32_t pangea_bet(union pangeanet777 *hn,struct cards777_pubdata *dp,int32_t player,int64_t bet,int32_t action) +{ + uint64_t sum; uint8_t tmp; struct pangea_info *sp = dp->table; + player %= dp->N; + if ( Debuglevel > 2 ) + printf("player.%d PANGEA_BET[%d] <- %.8f\n",hn->client->H.slot,player,dstr(bet)); + if ( dp->hand.betstatus[player] == CARDS777_ALLIN ) + return(CARDS777_ALLIN); + else if ( dp->hand.betstatus[player] == CARDS777_FOLD ) + return(CARDS777_FOLD); + if ( bet > 0 && bet >= sp->balances[pangea_slot(sp,player)] ) + { + bet = sp->balances[pangea_slot(sp,player)]; + dp->hand.betstatus[player] = action = CARDS777_ALLIN; + } + else + { + if ( bet > dp->hand.betsize && bet > dp->hand.lastraise && bet < (dp->hand.lastraise<<1) ) + { + printf("pangea_bet %.8f not double %.8f, clip to lastraise\n",dstr(bet),dstr(dp->hand.lastraise)); + bet = dp->hand.lastraise; + action = CARDS777_RAISE; + } + } + sum = dp->hand.bets[player]; + if ( sum+bet < dp->hand.betsize && action != CARDS777_ALLIN ) + { + pangea_fold(hn,dp,player); + action = CARDS777_FOLD; + tmp = player; + if ( Debuglevel > 2 ) + printf("player.%d betsize %.8f < hand.betsize %.8f FOLD\n",player,dstr(bet),dstr(dp->hand.betsize)); + return(action); + } + else if ( bet >= 2*dp->hand.lastraise ) + { + dp->hand.lastraise = bet; + dp->hand.numactions = 0; + if ( action == CARDS777_CHECK ) + { + action = CARDS777_FULLRAISE; // allows all players to check/bet again + if ( Debuglevel > 2 ) + printf("FULLRAISE by player.%d\n",player); + } + } + sum += bet; + if ( sum > dp->hand.betsize ) + { + dp->hand.numactions = 0; + dp->hand.betsize = sum, dp->hand.lastbettor = player; + if ( sum > dp->hand.lastraise && action == CARDS777_ALLIN ) + dp->hand.lastraise = sum; + else if ( action == CARDS777_CHECK ) + action = CARDS777_BET; + } + if ( bet > 0 && action == CARDS777_CHECK ) + action = CARDS777_CALL; + tmp = player; + pangea_summary(hn,dp,action,&tmp,sizeof(tmp),(void *)&bet,sizeof(bet)); + sp->balances[pangea_slot(sp,player)] -= bet, dp->hand.bets[pangea_slot(sp,player)] += bet; + if ( Debuglevel > 2 ) + printf("player.%d: player.%d BET %f -> balances %f bets %f\n",hn->client->H.slot,player,dstr(bet),dstr(sp->balances[pangea_slot(sp,player)]),dstr(dp->hand.bets[player])); + return(action); +} + +void pangea_antes(union pangeanet777 *hn,struct cards777_pubdata *dp) +{ + int32_t i,j,n,actives[CARDS777_MAXPLAYERS]; uint64_t threshold; int32_t handid; struct pangea_info *sp = dp->table; + for (i=0; inumaddrs; i++) + dp->snapshot[i] = sp->balances[i]; + handid = dp->numhands - 1; + pangea_summary(hn,dp,CARDS777_SNAPSHOT,(void *)&handid,sizeof(handid),(void *)dp->snapshot,sizeof(uint64_t)*CARDS777_MAXPLAYERS); + for (i=0; iN; i++) + if ( sp->balances[pangea_slot(sp,i)] <= 0 ) + pangea_fold(hn,dp,i); + if ( dp->ante != 0 ) + { + for (i=0; iN; i++) + { + if ( i != dp->button && i != (dp->button+1) % dp->N ) + { + if ( sp->balances[pangea_slot(sp,i)] < dp->ante ) + pangea_fold(hn,dp,i); + else pangea_bet(hn,dp,i,dp->ante,CARDS777_ANTE); + } + } + } + memset(actives,0,sizeof(actives)); + for (i=n=0; iN; i++) + { + j = (1 + dp->button + i) % dp->N; + if ( n == 0 ) + threshold = (dp->bigblind >> 1) - 1; + else if ( n == 1 ) + threshold = dp->bigblind - 1; + else threshold = 0; + if ( sp->balances[pangea_slot(sp,j)] > threshold ) + { + //printf("active[%d] <- %d\n",n,j); + actives[n++] = j; + } + else pangea_fold(hn,dp,j); + } + if ( n < 2 ) + { + printf("pangea_antes not enough players n.%d\n",n); + } + else + { + pangea_bet(hn,dp,actives[0],(dp->bigblind>>1),CARDS777_SMALLBLIND); + dp->button = (actives[0] + dp->N - 1) % dp->N; + pangea_bet(hn,dp,actives[1],dp->bigblind,CARDS777_BIGBLIND); + + } + /*for (i=0; iN; i++) + { + j = (1 + dp->button + i) % dp->N; + if ( dp->balances[j] < (dp->bigblind >> 1) ) + pangea_fold(hn,dp,j); + else + { + smallblindi = j; + pangea_bet(hn,dp,smallblindi,(dp->bigblind>>1),CARDS777_SMALLBLIND); + break; + } + } + for (i=0; iN; i++) + { + j = (1 + smallblindi + i) % dp->N; + if ( dp->balances[j] < dp->bigblind ) + pangea_fold(hn,dp,j); + else + { + pangea_bet(hn,dp,j,dp->bigblind,CARDS777_BIGBLIND); + break; + } + }*/ + if ( 0 ) + { + for (i=0; iN; i++) + printf("%.8f ",dstr(dp->hand.bets[i])); + printf("antes\n"); + } +} + +void pangea_checkantes(union pangeanet777 *hn,struct cards777_pubdata *dp) +{ + int32_t i; + for (i=0; iN; i++) + { + //printf("%.8f ",dstr(dp->balances[i])); + if ( dp->hand.bets[i] != 0 ) + break; + } + if ( i == dp->N && dp->hand.checkprod.txid != 0 ) + { + for (i=0; iN; i++) + if ( dp->hand.bets[i] != 0 ) + break; + if ( i == dp->N ) + { + //printf("i.%d vs N.%d call antes\n",i,dp->N); + pangea_antes(hn,dp); + } else printf("bets i.%d\n",i); + } +} + +/*int32_t pangea_cashout(union pangeanet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t senderind) +{ + return(0); +}*/ + +int32_t _pangea_addfunds(union pangeanet777 *hn,cJSON *json,struct cards777_pubdata *dp,struct cards777_privdata *priv,uint8_t *data,int32_t datalen,int32_t senderind) +{ + char *txidstr,*destaddr; uint32_t vout; int32_t slot; uint64_t amount = 0; struct pangea_info *sp = dp->table; + slot = pangea_slot(sp,senderind); + if ( datalen == sizeof(amount) ) + memcpy(&amount,data,sizeof(amount)); + else + { + if ( (json= cJSON_Parse((void *)data)) != 0 ) + { + amount = j64bits(json,"amount"); + txidstr = jstr(json,"txidstr"); + destaddr = jstr(json,"msigaddr"); + vout = juint(json,"vout"); + if ( txidstr != 0 && destaddr != 0 && amount > 0 && strcmp(destaddr,sp->multisigaddr) == 0 ) + { + // of course need to verify on blockchain + strcpy(sp->buyintxids[slot],txidstr); + sp->buyinvouts[slot] = vout; + sp->buyinamounts[slot] = amount; + } + free_json(json); + } + } + if ( sp->balances[slot] == 0 ) + sp->balances[slot] = amount; + pangea_checkantes(hn,dp); + printf("slot.%d: addfunds.%d <- %.8f total %.8f\n",hn->client->H.slot,senderind,dstr(amount),dstr(sp->balances[senderind])); + return(0); +} + +uint64_t pangea_winnings(int32_t player,uint64_t *pangearakep,uint64_t *hostrakep,uint64_t total,int32_t numwinners,int32_t rakemillis,uint64_t maxrake) +{ + uint64_t split,pangearake,rake; + if ( numwinners > 0 ) + { + split = (total * (1000 - rakemillis)) / (1000 * numwinners); + pangearake = (total - split*numwinners); + if ( pangearake > maxrake ) + { + pangearake = maxrake; + split = (total - pangearake) / numwinners; + pangearake = (total - split*numwinners); + } + } + else + { + split = 0; + pangearake = total; + } + if ( rakemillis > PANGEA_MINRAKE_MILLIS ) + { + rake = (pangearake * (rakemillis - PANGEA_MINRAKE_MILLIS)) / rakemillis; + pangearake -= rake; + } + else rake = 0; + *hostrakep = rake; + *pangearakep = pangearake; + printf("\nP%d: rakemillis.%d total %.8f split %.8f rake %.8f pangearake %.8f\n",player,rakemillis,dstr(total),dstr(split),dstr(rake),dstr(pangearake)); + return(split); +} + +int32_t pangea_sidepots(int32_t dispflag,uint64_t sidepots[CARDS777_MAXPLAYERS][CARDS777_MAXPLAYERS],struct cards777_pubdata *dp,int64_t *bets) +{ + int32_t i,j,nonz,n = 0; uint64_t bet,minbet = 0; + memset(sidepots,0,sizeof(uint64_t)*CARDS777_MAXPLAYERS*CARDS777_MAXPLAYERS); + for (j=0; jN; j++) + sidepots[0][j] = bets[j]; + nonz = 1; + while ( nonz > 0 ) + { + for (minbet=j=0; jN; j++) + { + if ( (bet= sidepots[n][j]) != 0 ) + { + if ( dp->hand.betstatus[j] != CARDS777_FOLD ) + { + if ( minbet == 0 || bet < minbet ) + minbet = bet; + } + } + } + for (j=nonz=0; jN; j++) + { + if ( sidepots[n][j] > minbet && dp->hand.betstatus[j] != CARDS777_FOLD ) + nonz++; + } + if ( nonz > 0 ) + { + for (j=0; jN; j++) + { + if ( sidepots[n][j] > minbet ) + { + sidepots[n+1][j] = (sidepots[n][j] - minbet); + sidepots[n][j] = minbet; + } + } + } + if ( ++n >= dp->N ) + break; + } + if ( dispflag != 0 ) + { + for (i=0; iN; j++) + printf("%.8f ",dstr(sidepots[i][j])); + printf("sidepot.%d of %d\n",i,n); + } + } + return(n); +} + +int64_t pangea_splitpot(int64_t *won,uint64_t *pangearakep,uint64_t sidepot[CARDS777_MAXPLAYERS],union pangeanet777 *hn,int32_t rakemillis) +{ + int32_t winners[CARDS777_MAXPLAYERS],j,n,numwinners = 0; uint32_t bestrank,rank; uint8_t tmp; struct pangea_info *sp; + uint64_t total = 0,bet,split,maxrake,rake=0,pangearake=0; char handstr[128],besthandstr[128]; struct cards777_pubdata *dp; + dp = hn->client->H.pubdata, sp = dp->table; + bestrank = 0; + besthandstr[0] = 0; + for (j=n=0; jN; j++) + { + if ( (bet= sidepot[j]) != 0 ) + { + total += bet; + if ( dp->hand.betstatus[j] != CARDS777_FOLD ) + { + if ( dp->hand.handranks[j] > bestrank ) + { + bestrank = dp->hand.handranks[j]; + set_handstr(besthandstr,dp->hand.hands[j],0); + //printf("set besthandstr.(%s)\n",besthandstr); + } + } + } + } + for (j=0; jN; j++) + { + if ( dp->hand.betstatus[j] != CARDS777_FOLD && sidepot[j] > 0 ) + { + if ( dp->hand.handranks[j] == bestrank ) + winners[numwinners++] = j; + rank = set_handstr(handstr,dp->hand.hands[j],0); + if ( handstr[strlen(handstr)-1] == ' ' ) + handstr[strlen(handstr)-1] = 0; + //if ( hn->server->H.slot == 0 ) + printf("(p%d %14s)",j,handstr[0]!=' '?handstr:handstr+1); + //printf("(%2d %2d).%d ",dp->hands[j][5],dp->hands[j][6],(int32_t)dp->balances[j]); + } + } + if ( numwinners == 0 ) + printf("pangea_splitpot error: numwinners.0\n"); + else + { + uint64_t maxrakes[CARDS777_MAXPLAYERS+1] = { 0, 0, 1, 2, 2, 3, 3, 3, 3, 3 }; // 2players 1BB, 3-4players, 2BB, 5+players 3BB + for (j=n=0; jN; j++) + if ( dp->hand.bets[j] > 0 ) + n++; + if ( (maxrake= maxrakes[n] * dp->bigblind) > dp->maxrake ) + { + maxrake = dp->maxrake; + if ( strcmp(dp->coinstr,"BTC") == 0 && maxrake < PANGEA_BTCMAXRAKE ) + maxrake = PANGEA_BTCMAXRAKE; + else if ( maxrake < PANGEA_MAXRAKE ) + maxrake = PANGEA_MAXRAKE; + } + split = pangea_winnings(pangea_ind(dp->table,hn->client->H.slot),&pangearake,&rake,total,numwinners,rakemillis,maxrake); + (*pangearakep) += pangearake; + for (j=0; jbalances[pangea_slot(sp,winners[j])] += split; + won[winners[j]] += split; + } + if ( split*numwinners + rake + pangearake != total ) + printf("pangea_split total error %.8f != split %.8f numwinners %d rake %.8f pangearake %.8f\n",dstr(total),dstr(split),numwinners,dstr(rake),dstr(pangearake)); + //if ( hn->server->H.slot == 0 ) + { + printf(" total %.8f split %.8f rake %.8f Prake %.8f hand.(%s) N%d winners ",dstr(total),dstr(split),dstr(rake),dstr(pangearake),besthandstr,dp->numhands); + for (j=0; jtable; + sum = dp->hand.bets[pangea_ind(dp->table,hn->client->H.slot)]; + action = 0; + n = pangea_actives(&activej,dp); + if ( (r = (rand() % 100)) < 1 ) + amount = sp->balances[hn->client->H.slot], action = CARDS777_ALLIN; + else + { + if ( betsize == sum ) + { + if ( r < 100/n ) + { + amount = dp->hand.lastraise; + action = 1; + if ( (rand() % 100) < 10 ) + amount <<= 1; + } + } + else if ( betsize > sum ) + { + amount = (betsize - sum); + total = pangea_totalbet(dp); + threshold = (300 * amount)/(1 + total); + n++; + if ( r/n > threshold ) + { + action = 1; + if ( r/n > 3*threshold && amount < dp->hand.lastraise*2 ) + amount = dp->hand.lastraise * 2, action = 2; + //else if ( r/n > 10*threshold ) + // amount = dp->balances[pangea_ind(dp->table,hn->client->H.slot)], action = CARDS777_ALLIN; + } + else if ( amount < sum/10 || amount <= SATOSHIDEN ) + action = CARDS777_CALL; + else + { + //printf("amount %.8f, sum %.8f, betsize %.8f\n",dstr(amount),dstr(sum),dstr(betsize)); + action = CARDS777_FOLD, amount = 0; + } + } + else printf("pangea_turn error betsize %.8f vs sum %.8f | slot.%d ind.%d\n",dstr(betsize),dstr(sum),hn->client->H.slot,pangea_ind(dp->table,hn->client->H.slot)); + if ( amount > sp->balances[hn->client->H.slot] ) + amount = sp->balances[hn->client->H.slot], action = CARDS777_ALLIN; + } + pangea_sendcmd(hex,hn,"action",-1,(void *)&amount,sizeof(amount),cardi,action); + printf("playerbot.%d got pangea_turn.%d for player.%d action.%d bet %.8f\n",hn->client->H.slot,cardi,turni,action,dstr(amount)); + return(amount); +} + +cJSON *pangea_handjson(struct cards777_handinfo *hand,uint8_t *holecards,int32_t isbot) +{ + int32_t i,card; char cardAstr[8],cardBstr[8],pairstr[18],cstr[128]; cJSON *array,*json = cJSON_CreateObject(); + array = cJSON_CreateArray(); + cstr[0] = 0; + for (i=0; i<5; i++) + { + if ( (card= hand->community[i]) != 0xff ) + { + jaddinum(array,card); + cardstr(&cstr[strlen(cstr)],card); + strcat(cstr," "); + } + } + jaddstr(json,"community",cstr); + jadd(json,"cards",array); + if ( (card= holecards[0]) != 0xff ) + { + jaddnum(json,"cardA",card); + cardstr(cardAstr,holecards[0]); + } else cardAstr[0] = 0; + if ( (card= holecards[1]) != 0xff ) + { + jaddnum(json,"cardB",card); + cardstr(cardBstr,holecards[1]); + } else cardBstr[0] = 0; + sprintf(pairstr,"%s %s",cardAstr,cardBstr); + jaddstr(json,"holecards",pairstr); + jaddnum(json,"betsize",dstr(hand->betsize)); + jaddnum(json,"lastraise",dstr(hand->lastraise)); + jaddnum(json,"lastbettor",hand->lastbettor); + jaddnum(json,"numactions",hand->numactions); + jaddnum(json,"undergun",hand->undergun); + jaddnum(json,"isbot",isbot); + jaddnum(json,"cardi",hand->cardi); + return(json); +} + +char *pangea_statusstr(int32_t status) +{ + if ( status == CARDS777_FOLD ) + return("folded"); + else if ( status == CARDS777_ALLIN ) + return("ALLin"); + else return("active"); +} + +int32_t pangea_countdown(struct cards777_pubdata *dp,int32_t player) +{ + if ( dp->hand.undergun == player && dp->hand.userinput_starttime != 0 ) + return((int32_t)(dp->hand.userinput_starttime + PANGEA_USERTIMEOUT - time(NULL))); + else return(-1); +} + +cJSON *pangea_tablestatus(struct pangea_info *sp) +{ + uint64_t sidepots[CARDS777_MAXPLAYERS][CARDS777_MAXPLAYERS],totals[CARDS777_MAXPLAYERS],sum; char *handhist; + int32_t i,n,j,countdown,iter; int64_t total; struct cards777_pubdata *dp; cJSON *bets,*item,*array,*json = cJSON_CreateObject(); + jadd64bits(json,"tableid",sp->tableid); + jadd64bits(json,"myslot",sp->myslot); + jadd64bits(json,"myind",pangea_ind(sp,sp->myslot)); + dp = sp->dp; + jaddstr(json,"tablemsig",sp->multisigaddr); + jaddnum(json,"minbuyin",dp->minbuyin); + jaddnum(json,"maxbuyin",dp->maxbuyin); + jaddnum(json,"button",dp->button); + jaddnum(json,"M",dp->M); + jaddnum(json,"N",dp->N); + jaddnum(json,"numcards",dp->numcards); + jaddnum(json,"numhands",dp->numhands); + jaddnum(json,"rake",(double)dp->rakemillis/10.); + jaddnum(json,"maxrake",dstr(dp->maxrake)); + jaddnum(json,"hostrake",dstr(dp->hostrake)); + jaddnum(json,"pangearake",dstr(dp->pangearake)); + jaddnum(json,"bigblind",dstr(dp->bigblind)); + jaddnum(json,"ante",dstr(dp->ante)); + array = cJSON_CreateArray(); + for (i=0; iN; i++) + jaddi64bits(array,sp->active[i]); + jadd(json,"addrs",array); + array = cJSON_CreateArray(); + for (i=0; iN; i++) + jaddinum(array,dp->hand.turnis[i]); + jadd(json,"turns",array); + array = cJSON_CreateArray(); + for (i=0; inumaddrs; i++) + jaddinum(array,dstr(sp->balances[i])); + jadd(json,"balances",array); + array = cJSON_CreateArray(); + for (i=0; iN; i++) + jaddinum(array,dstr(dp->hand.snapshot[i])); + jadd(json,"snapshot",array); + array = cJSON_CreateArray(); + for (i=0; iN; i++) + jaddistr(array,pangea_statusstr(dp->hand.betstatus[i])); + jadd(json,"status",array); + bets = cJSON_CreateArray(); + for (total=i=0; iN; i++) + { + total += dp->hand.bets[i]; + jaddinum(bets,dstr(dp->hand.bets[i])); + } + jadd(json,"bets",bets); + jaddnum(json,"totalbets",dstr(total)); + for (iter=0; iter<2; iter++) + if ( (n= pangea_sidepots(0,sidepots,dp,iter == 0 ? dp->hand.snapshot : dp->hand.bets)) > 0 && n < dp->N ) + { + array = cJSON_CreateArray(); + for (i=0; iN; j++) + jaddinum(item,dstr(sidepots[i][j])), sum += sidepots[i][j]; + totals[i] = sum; + jaddi(array,item); + } + jadd(json,iter == 0 ? "pots" : "RTpots",array); + item = cJSON_CreateArray(); + for (sum=i=0; ipriv != 0 ) + { + jadd64bits(json,"automuck",sp->priv->automuck); + jadd64bits(json,"autofold",sp->priv->autofold); + jadd(json,"hand",pangea_handjson(&dp->hand,sp->priv->hole,sp->isbot[sp->myslot])); + } + if ( (handhist= pangea_dispsummary(sp,0,dp->summary,dp->summarysize,sp->tableid,dp->numhands-1,dp->N)) != 0 ) + { + if ( (item= cJSON_Parse(handhist)) != 0 ) + jadd(json,"actions",item); + free(handhist); + } + if ( (countdown= pangea_countdown(dp,pangea_ind(sp,sp->myslot))) >= 0 ) + jaddnum(json,"timeleft",countdown); + if ( dp->hand.finished != 0 ) + { + item = cJSON_CreateObject(); + jaddnum(item,"hostrake",dstr(dp->hand.hostrake)); + jaddnum(item,"pangearake",dstr(dp->hand.pangearake)); + array = cJSON_CreateArray(); + for (i=0; iN; i++) + jaddinum(array,dstr(dp->hand.won[i])); + jadd(item,"won",array); + jadd(json,"summary",item); + } + return(json); +} + +void pangea_playerprint(struct cards777_pubdata *dp,int32_t i,int32_t myind) +{ + int32_t countdown; char str[8]; struct pangea_info *sp = dp->table; + if ( (countdown= pangea_countdown(dp,i)) >= 0 ) + sprintf(str,"%2d",countdown); + else str[0] = 0; + printf("%d: %6s %12.8f %2s | %12.8f %s\n",i,pangea_statusstr(dp->hand.betstatus[i]),dstr(dp->hand.bets[i]),str,dstr(sp->balances[pangea_slot(sp,i)]),i == myind ? "<<<<<<<<<<<": ""); +} + +void pangea_statusprint(struct cards777_pubdata *dp,struct cards777_privdata *priv,int32_t myind) +{ + int32_t i; char handstr[64]; uint8_t hand[7]; + for (i=0; iN; i++) + pangea_playerprint(dp,i,myind); + handstr[0] = 0; + if ( dp->hand.community[0] != dp->hand.community[1] ) + { + for (i=0; i<5; i++) + if ( (hand[i]= dp->hand.community[i]) == 0xff ) + break; + if ( i == 5 ) + { + if ( (hand[5]= priv->hole[0]) != 0xff && (hand[6]= priv->hole[1]) != 0xff ) + set_handstr(handstr,hand,1); + } + } + printf("%s\n",handstr); +} + +/* + if ( hn->server->H.slot == 0 ) +{ + char *pangea_cashout(char *coinstr,int32_t oldtx_format,uint64_t values[],char *txidstrs[],int32_t vouts[],int32_t numinputs,char *destaddrs[],char *destscripts[],uint64_t outputs[],int32_t n,char *scriptPubKey,char *redeemScript,char *wip,uint64_t txfee,char sigs[][256],int32_t numplayers,uint8_t *privkey,int32_t privkeyind,char *othersignedtx); + uint64_t values[1],txfee; char *othersignedtx,*rawtx,*txidstrs[1],*destaddrs[1],*destscripts[1],sigs[CARDS777_MAXPLAYERS][256]; int32_t vouts[1]; uint64_t outputs[1]; + if ( strcmp(dp->coinstr,"BTC") == 0 ) + { + txfee = SATOSHIDEN/10000; + values[0] = SATOSHIDEN / 5000, txidstrs[0] = "94cb2925d802c6c3695f0765767d892e13bd90ca256cc08ed5d85fd737bcc848", vouts[0] = 0; + outputs[0] = SATOSHIDEN / 5000 - txfee; + } + else + { + txfee = SATOSHIDEN/1000; + values[0] = SATOSHIDEN, txidstrs[0] = "af980e0cf15c028d571767935e9e78ff0ad3068ff1a2ae2ca62c723a75ed8a80", vouts[0] = 1; + outputs[0] = SATOSHIDEN - txfee; + } + destaddrs[0] = dp->multisigaddr, destscripts[0] = dp->scriptPubKey; + memset(sigs,0,sizeof(sigs)); + othersignedtx = 0; + for (i=0; iN; i++) + { + rawtx = pangea_cashout(dp->coinstr,strcmp(dp->coinstr,"BTC") == 0,values,txidstrs,vouts,1,destaddrs,destscripts,outputs,1,dp->scriptPubKey,dp->redeemScript,priv->wipstr,txfee,sigs,dp->N,THREADS[i]->hn.client->H.privkey.bytes,i,othersignedtx); + if ( othersignedtx != 0 ) + free(othersignedtx); + othersignedtx = rawtx; + } +} +*/ diff --git a/iguana/pangea_init.c b/iguana/pangea_init.c new file mode 100755 index 000000000..38be79c48 --- /dev/null +++ b/iguana/pangea_init.c @@ -0,0 +1,487 @@ +/****************************************************************************** + * Copyright © 2014-2016 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. * + * * + ******************************************************************************/ + +#include "pangea777.h" + +void pangea_buyins(uint32_t *minbuyinp,uint32_t *maxbuyinp) +{ + if ( *minbuyinp == 0 && *maxbuyinp == 0 ) + { + *minbuyinp = 100; + *maxbuyinp = 1000; + } + else + { + PNACL_message("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; + PNACL_message("(%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; struct iguana_info *coin; + if ( createdflagp != 0 ) + *createdflagp = 0; + for (i=0; inxt64bits ) + break; + } + if ( i == numaddrs ) + { + PNACL_message("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 ) + { + PNACL_message("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; jbalances[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 ) + { + PNACL_message("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); + if ( (coin= iguana_coinfind(base)) != 0 ) + { + sp->addrtype = coin->chain->pubval;//coin777_addrtype(&sp->p2shtype,base); + sp->wiftype = coin->chain->wipval;//coin777_wiftype(base); + } + btc_priv2wip(sp->wipstr,tp->hn.client->H.privkey.bytes,sp->wiftype); + strcpy(sp->btcpubkeys[sp->myslot],sp->btcpubkeystr); + PNACL_message("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; itableid == TABLES[i]->tableid && tp->threadid == TABLES[i]->tp->threadid ) + { + PNACL_message("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; inumcards; i++) + for (j=0; jN; 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 %s) ",(long long)playerpubs[i].txid,hexstr); + jaddistr(array,hexstr); + } + //PNACL_message("playerpubs\n"); + return(array); +} + +cJSON *pangea_cardpubs(struct cards777_pubdata *dp) +{ + int32_t i; char hexstr[65]; cJSON *array = cJSON_CreateArray(); + for (i=0; inumcards; 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 CARDS777_MAXPLAYERS ) + { + PNACL_message("no address or illegal num.%d\n",num); + return(clonestr("{\"error\":\"no addrs or illegal numplayers\"}")); + } + for (i=0; ihn.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 ) + { + PNACL_message("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= pangeanet777_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 ) + { + PNACL_message("no balances or illegal num.%d\n",num); + return(clonestr("{\"error\":\"no balances or illegal numplayers\"}")); + } + for (i=0; idp; 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 ) + { + PNACL_message("no address or illegal num.%d\n",num); + return(clonestr("{\"error\":\"no addrs or illegal numplayers\"}")); + } + for (i=0; iplayerpubs[i].bytes,sizeof(bits256),hexstr); + PNACL_message("set playerpubs.(%s) %llx\n",hexstr,(long long)sp->playerpubs[i].txid); + if ( sp->playerpubs[i].txid == 0 ) + { + PNACL_message("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 supernet_info *plugin,int32_t maxplayers) +{ + /* struct pangea_thread *tp; struct pangeanet777_server *srv; + PANGEA_MAXTHREADS = 1; + THREADS[0] = tp = calloc(1,sizeof(*THREADS[0])); + if ( tp == 0 ) + { + PNACL_message("pangea_threadinit: unexpected out of memory\n"); + return(0); + } + tp->nxt64bits = plugin->nxt64bits; + if ( (srv= pangeanet777_server(*(bits256 *)plugin->mypriv,*(bits256 *)plugin->mypub,plugin->transport,plugin->ipaddr,plugin->pangeaport,9)) == 0 ) + PNACL_message("cant create pangeanet777 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);*/ + return(0); +} + +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}",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); //\"pluginrequest\":\"SuperNET\", + PNACL_message("START.(%s)\n",retbuf); + //dp->pmworks |= (1 << sp->myind); + free(addrstr), free(ciphers), free(playerpubs), free(isbotstr);// free(balancestr); +} + +int32_t pangea_start(struct supernet_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; + struct pangea_info *sp; cJSON *bids,*walletitem,*item; struct iguana_info *coin; + memset(addrs,0,sizeof(addrs)); + PNACL_message("pangea_start rakemillis.%d\n",hostrake); + //memset(balances,0,sizeof(balances)); + pangea_buyins(&minbuyin,&maxbuyin); + if ( hostrake < 0 || hostrake > PANGEA_MAX_HOSTRAKE ) + { + PNACL_message("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\"}"); + PNACL_message("%s\n",retbuf); + return(-1); + } + } + PNACL_message("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\"}"); + PNACL_message("%s\n",retbuf); + return(-1); + } + if ( (coin= iguana_coinfind(base)) != 0 ) + addrtype = coin->chain->pubval;//coin777_addrtype(&p2shtype,base); + if ( (bids= jarray(&n,json,"bids")) != 0 ) + { + PNACL_message("numbids.%d\n",n); + for (i=num=0; inxt64bits ) + myind = num; + PNACL_message("%llu ",(long long)addrs[num]); + num++; + } + } + else PNACL_message("%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.); + } + } + } + PNACL_message("(%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)); + PNACL_message("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]; + } + PNACL_message("pangea numplayers.%d\n",num); + if ( (sp= pangea_create(tp,&createdflag,base,timestamp,addrs,num,bigblind,ante,isbot,minbuyin,maxbuyin,hostrake)) == 0 ) + { + PNACL_message("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); + } + PNACL_message("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; + PNACL_message("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; jN; 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= pangeanet777_register(THREADS[0]->hn.server,sp->playerpubs[j],-1)) != j ) + PNACL_message("unexpected register slot.%d for j.%d\n",slot,j); + } + //PNACL_message("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); +} diff --git a/iguana/pangea_network.c b/iguana/pangea_network.c new file mode 100755 index 000000000..7cb79dc4b --- /dev/null +++ b/iguana/pangea_network.c @@ -0,0 +1,435 @@ +/****************************************************************************** + * Copyright © 2014-2016 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. * + * * + ******************************************************************************/ + +#include "pangea777.h" + +struct pangeanet777_id *pangeanet777_find(struct pangeanet777_server *srv,bits256 senderpub) +{ + int32_t i; uint64_t senderbits = acct777_nxt64bits(senderpub); + if ( srv->num > 0 ) + { + for (i=0; imax; i++) + if ( srv->clients[i].nxt64bits == senderbits ) + return(&srv->clients[i]); + } + return(0); +} + +void pangeanet777_lastcontact(struct pangeanet777_server *srv,bits256 senderpub) +{ + struct pangeanet777_id *ptr; + if ( (ptr= pangeanet777_find(srv,senderpub)) != 0 ) + ptr->lastcontact = (uint32_t)time(NULL); +} + +void pangeanet777_processmsg(uint64_t *destbitsp,bits256 *senderpubp,queue_t *Q,bits256 mypriv,bits256 mypub,uint8_t *msg,int32_t origlen,int32_t pmflag) +{ + char *jsonstr = 0; bits256 sig; uint32_t timestamp; int32_t len; uint64_t senderbits; uint8_t *ptr=0; cJSON *json; long extra; + extra = sizeof(*senderpubp) + sizeof(*destbitsp) + sizeof(sig) + sizeof(senderbits) + sizeof(timestamp); + if ( (len= origlen) > extra ) + { + //printf("got msglen.%d\n",origlen); + if ( (ptr= malloc(len*4 + 8192 + sizeof(struct queueitem) - extra)) == 0 ) + { + printf("hostnet777_processmsg cant alloc queueitem\n"); + return; + } + if ( (len= SuperNET_decrypt(senderpubp,&senderbits,×tamp,mypriv,mypub,&ptr[sizeof(struct queueitem)],len*4,msg,len)) > 1 && len < len*4 ) + { + jsonstr = (char *)&ptr[sizeof(struct queueitem)]; + if ( (json= cJSON_Parse(jsonstr)) != 0 ) + { + //printf("now.%lld vs millitime.%lld lag.%lld\n",(long long)now,(long long)millitime,(long long)(millitime - now)); + if ( pmflag != 0 && juint(json,"timestamp") != timestamp && juint(json,"timestamp")+1 != timestamp ) + printf("msg.(%s) timestamp.%u mismatch | now.%ld\n",jsonstr,timestamp,(long)time(NULL)); + else if ( pmflag != 0 && j64bits(json,"sender") != senderbits ) + printf("msg.(%ld) sender.%llu mismatch vs json.%llu\n",(long)strlen(jsonstr),(long long)senderbits,(long long)j64bits(json,"sender")); + else + { + //printf("%llu: QUEUE msg.%d\n",(long long)acct777_nxt64bits(mypub),len); + //if ( hostnet777_hashes(recvhashes,64,ptr,len) < 0 ) + queue_enqueue("host777",Q,(void *)ptr,0); + ptr = 0; + } + free_json(json); + } else printf("parse error.(%s)\n",jsonstr); + } else printf("decrypt error len.%d origlen.%d\n",len,origlen); + } else printf("origlen.%d\n",origlen); + if ( ptr != 0 ) + free(ptr); +} + +int32_t pangeanet777_idle(union pangeanet777 *hn) +{ + int32_t len,slot,sock,n = 0; bits256 senderpub,mypriv,mypub; uint64_t destbits; uint8_t *msg; + long extra = sizeof(bits256)+sizeof(uint64_t); + if ( (slot= hn->client->H.slot) != 0 ) + { + mypriv = hn->client->H.privkey, mypub = hn->client->H.pubkey; + if ( (sock= hn->client->subsock) >= 0 && (len= nn_recv(sock,&msg,NN_MSG,0)) > extra ) + { + SuperNET_copybits(1,msg,(void *)&destbits,sizeof(uint64_t)); + //printf("client got pub len.%d\n",len); + if ( destbits == 0 || destbits == hn->client->H.nxt64bits ) + pangeanet777_processmsg(&destbits,&senderpub,&hn->client->H.Q,mypriv,mypub,msg,len,0), n++; + nn_freemsg(msg); + } else if ( hn->client->H.pollfunc != 0 ) + (*hn->client->H.pollfunc)(hn); + } + else + { + //printf("server idle %.0f\n",milliseconds()); + mypriv = hn->server->H.privkey, mypub = hn->server->H.pubkey; + for (slot=1; slotserver->num; slot++) + { + //printf("check ind.%d %.0f\n",ind,milliseconds()); + if ( (sock= hn->server->clients[slot].pmsock) >= 0 && (len= nn_recv(sock,&msg,NN_MSG,0)) > extra ) + { + //printf("server got pm[%d] %d\n",slot,len); + SuperNET_copybits(1,msg,(void *)&destbits,sizeof(uint64_t)); + if ( destbits == 0 || destbits == hn->server->H.nxt64bits ) + { + pangeanet777_processmsg(&destbits,&senderpub,&hn->server->H.Q,mypriv,mypub,msg,len,1); + pangeanet777_lastcontact(hn->server,senderpub); + } + printf("pangeanet777_idle: do the send here\n"); + //pangeanet777_send(hn->server->pubsock,msg,len); + nn_freemsg(msg); + } + } + if ( hn->server->H.pollfunc != 0 ) + (*hn->server->H.pollfunc)(hn); + } + return(n); +} + +int32_t pangeanet777_replace(struct pangeanet777_server *srv,bits256 clientpub,int32_t slot) +{ + char endpoint[128],buf[128]; uint64_t nxt64bits = acct777_nxt64bits(clientpub); + sprintf(endpoint,"%s://%s:%u",srv->ep.transport,srv->ep.ipaddr,srv->ep.port + slot + 1); + //sprintf(buf,"%s://127.0.0.1:%u",srv->ep.transport,srv->ep.port + slot + 1); + strcpy(buf,endpoint); + if ( srv->clients[slot].pmsock < 0 ) + { + printf("pangeanet777_replace deal with getting new socket here\n"); + //srv->clients[slot].pmsock = nn_createsocket(buf,1,"NN_PULL",NN_PULL,srv->ep.port + slot + 1,10,10); + } + printf("NN_PULL.%d for slot.%d\n",srv->clients[slot].pmsock,slot); + srv->clients[slot].pubkey = clientpub; + srv->clients[slot].nxt64bits = nxt64bits; + srv->clients[slot].lastcontact = (uint32_t)time(NULL); + return(srv->clients[slot].pmsock); +} + +int32_t pangeanet777_register(struct pangeanet777_server *srv,bits256 clientpub,int32_t slot) +{ + int32_t i,n; struct pangeanet777_id *ptr; + if ( slot < 0 ) + { + if ( (ptr= pangeanet777_find(srv,clientpub)) != 0 ) + { + slot = (int32_t)(((long)ptr - (long)srv->clients) / sizeof(*srv->clients)); + //printf("pangea_register: deregister slot.%d\n",slot); + if ( ptr->pmsock >= 0 ) + nn_shutdown(ptr->pmsock,0); + memset(ptr,0,sizeof(*ptr)); + ptr->pmsock = -1; + srv->num--; + return(-1); + } + for (slot=1; slotmax; slot++) + if ( srv->clients[slot].nxt64bits == 0 ) + break; + } + if ( srv->num >= srv->max ) + { + printf("pangea_register: cant register anymore num.%d vs max.%d\n",srv->num,srv->max); + return(-1); + } + if ( (ptr= pangeanet777_find(srv,clientpub)) != 0 ) + { + printf("pangea_register: cant register duplicate %llu\n",(long long)acct777_nxt64bits(clientpub)); + return((int32_t)(((long)ptr - (long)srv->clients) / sizeof(*srv->clients))); + } + if ( slot != srv->num ) + { + printf("pangea_register: cant register slot.%d vs num.%d vs max.%d\n",slot,srv->num,srv->max); + return(-1); + } + pangeanet777_replace(srv,clientpub,slot); + srv->num++; + for (i=n=0; imax; i++) + if ( srv->clients[i].nxt64bits != 0 ) + n++; + if ( n != srv->num ) + { + printf("mismatched nonz nxt64bits n.%d vs %d\n",n,srv->num); + srv->num = n; + } + return(slot); +} + +struct pangeanet777_client *pangeanet777_client(bits256 privkey,bits256 pubkey,char *srvendpoint,int32_t slot) +{ + char endbuf[128],endbuf2[128]; uint16_t port; struct pangeanet777_client *ptr; + ptr = calloc(1,sizeof(*ptr)); + ptr->H.slot = slot; + ptr->H.privkey = privkey, ptr->H.pubkey = ptr->my.pubkey = pubkey; + ptr->H.nxt64bits = ptr->my.nxt64bits = acct777_nxt64bits(pubkey); + ptr->my.lastcontact = (uint32_t)time(NULL); + strcpy(endbuf,srvendpoint); + endbuf[strlen(endbuf)-4] = 0; + port = atoi(&srvendpoint[strlen(endbuf)]); + sprintf(endbuf2,"%s%u",endbuf,port + 1 + slot); + printf("pangeanet777_client: deal with creating connections here\n"); + //ptr->my.pmsock = nn_createsocket(endbuf2,0,"NN_PUSH",NN_PUSH,0,10,100); + printf("NN_PUSH %d from (%s) port.%d\n",ptr->my.pmsock,endbuf2,port+1+slot); + sprintf(endbuf2,"%s%u",endbuf,port); + //ptr->subsock = nn_createsocket(endbuf2,0,"NN_SUB",NN_SUB,0,10,100); + printf("SUB %d from (%s) port.%d\n",ptr->subsock,endbuf2,port); + nn_setsockopt(ptr->subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); + //sprintf(endbuf2,"%s%u",endbuf,port); + //ptr->pushsock = nn_createsocket(endbuf2,0,"NN_PUSH",NN_PUSH,0,10,1); + //printf("PUSH %d to (%s)\n",ptr->pushsock,endbuf2); + return(ptr); +} + +void pangeanet777_freeclient(struct pangeanet777_client *client) +{ + client->H.done = 1; + if ( client->subsock >= 0 ) + nn_shutdown(client->subsock,0); + //if ( client->pushsock >= 0 ) + // nn_shutdown(client->pushsock,0); + if ( client->my.pmsock >= 0 ) + nn_shutdown(client->my.pmsock,0); +} + +void pangeanet777_freeserver(struct pangeanet777_server *srv) +{ + int32_t ind; + srv->H.done = 1; + //if ( srv->pullsock >= 0 ) + // nn_shutdown(srv->pullsock,0); + if ( srv->pubsock >= 0 ) + nn_shutdown(srv->pubsock,0); + for (ind=1; indmax; ind++) + { + if ( srv->clients[ind].pmsock >= 0 ) + nn_shutdown(srv->clients[ind].pmsock,0); + } +} + +struct pangeanet777_server *pangeanet777_server(bits256 srvprivkey,bits256 srvpubkey,char *transport,char *ipaddr,uint16_t port,int32_t maxclients) +{ + struct pangeanet777_server *srv; int32_t i; struct pangeanet777_endpoint *ep; char buf[128]; + srv = calloc(1,sizeof(*srv) + maxclients*sizeof(struct pangeanet777_id)); + srv->max = maxclients; + ep = &srv->ep; + if ( (ep->port= port) == 0 ) + ep->port = port = 8000 + (rand() % 1000); + if ( transport == 0 || transport[0] == 0 ) + transport = TEST_TRANSPORT; + if ( ipaddr == 0 || ipaddr[0] == 0 ) + ipaddr = "127.0.0.1"; + strcpy(ep->transport,transport), strcpy(ep->ipaddr,ipaddr); + for (i=0; iclients[i].pmsock = -1; + srv->H.privkey = srvprivkey; + srv->H.pubkey = srv->clients[0].pubkey = srvpubkey; + srv->H.nxt64bits = srv->clients[0].nxt64bits = acct777_nxt64bits(srvpubkey); + sprintf(ep->endpoint,"%s://%s:%u",transport,ipaddr,port); + if ( strcmp(transport,"tcpmux") == 0 ) + strcat(ep->endpoint,"/pangea"); + //sprintf(buf,"%s://127.0.0.1:%u",transport,port); + strcpy(buf,ep->endpoint); + printf("pangeanet777_server: create socket here\n"); + //srv->pubsock = nn_createsocket(buf,1,"NN_PUB",NN_PUB,port,10,100); + printf("PUB.%d to (%s) pangeaport.%d\n",srv->pubsock,ep->endpoint,port); + srv->num = 1; + return(srv); +} + +void *pangeanet777_idler(union pangeanet777 *ptr) +{ + while ( ptr->client->H.done == 0 ) + { + if ( pangeanet777_idle(ptr) == 0 ) + usleep(1000); + } + //printf("pangea_idler ind.%d done\n",ptr->client->H.slot); + sleep(1); + free(ptr); + return(0); +} + +int32_t SuperNET_sendmsg(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_peer *addr,bits256 destpub,bits256 mypriv,bits256 mypub,uint8_t *msg,int32_t len,uint8_t *data,int32_t delaymillis); + +#define pangeanet777_broadcast(mypriv,mypub,msg,len) SuperNET_sendmsg(myinfo,coin,addr,zeropoint,mypriv,mypub,msg,len,space,0) +#define pangeanet777_blindcast(msg,len) SuperNET_sendmsg(myinfo,coin,addr,zeropoint,zeropoint,zeropoint,msg,len,space,0) +#define pangeanet777_signedPM(destpub,mypriv,mypub,msg,len) SuperNET_sendmsg(myinfo,coin,addr,destpub,mypriv,mypub,msg,len,space,0) +#define pangeanet777_blindPM(destpub,msg,len) SuperNET_sendmsg(myinfo,coin,addr,destpub,zeropoint,zeropoint,msg,len,space,0) +void pangeanet777_msg(uint64_t destbits,bits256 destpub,union pangeanet777 *src,int32_t blindflag,char *jsonstr,int32_t len) +{ + static bits256 zeropoint; + struct supernet_info *myinfo = SuperNET_MYINFO(0); uint8_t *space; + struct iguana_peer *addr = 0; struct iguana_info *coin = iguana_coinfind("BTCD"); + if ( destbits == 0 ) + { + //printf(">>>>>>>>> blind.%d broadcast from %llu, len.%d\n",blindflag,(long long)src->client->H.nxt64bits,len); + space = calloc(1,IGUANA_MAXPACKETSIZE); + if ( blindflag != 0 ) + pangeanet777_blindcast((uint8_t *)jsonstr,len); + else pangeanet777_broadcast(src->client->H.privkey,src->client->H.pubkey,(uint8_t *)jsonstr,len); + free(space); + if ( src->server->H.slot == 0 ) + queue_enqueue("loopback",&src->client->H.Q,queueitem(jsonstr),1); + } + else if ( destbits != src->client->H.nxt64bits ) + { + //printf(">>>>>>>>> blind.%d PM from %llu to %llu\n",blindflag,(long long)src->client->H.nxt64bits,(long long)destbits); + space = calloc(1,IGUANA_MAXPACKETSIZE); + if ( blindflag != 0 ) + pangeanet777_blindPM(destpub,(uint8_t *)jsonstr,len); + else pangeanet777_signedPM(destpub,src->client->H.privkey,src->client->H.pubkey,(uint8_t *)jsonstr,len); + free(space); + } + else queue_enqueue("loopback",&src->client->H.Q,queueitem(jsonstr),1); +} + +int32_t pangea_search(struct pangea_info *sp,uint64_t nxt64bits) +{ + int32_t i; + for (i=0; inumactive; i++) + if ( sp->active[i] == nxt64bits ) + return(i); + for (i=0; inumactive; i++) + PNACL_message("%llu ",(long long)sp->active[i]); + PNACL_message("active[]\n"); + for (i=0; inumaddrs; i++) + PNACL_message("%llu ",(long long)sp->addrs[i]); + PNACL_message("addrs[]\n"); + PNACL_message("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; inumaddrs; i++) + if ( sp->addrs[i] == destbits ) + return(i); + } + return(-1); +} + +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; inumaddrs; i++) + { + if ( sp->addrs[i] == nxt64bits ) + { + PNACL_message("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 ) + { + PNACL_message("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 ) + { + pangeanet777_replace(sp->tp->hn.server,clientpub,openslot); + for (i=0; inumactive; i++) + isbot[i] = sp->isbot[i]; + pangea_create_newtable(retbuf,sp,dp,isbot); + pangeanet777_msg(nxt64bits,clientpub,&sp->tp->hn,0,retbuf,(int32_t)strlen(retbuf)+1); + free(retbuf); + } + } + pangea_neworder(dp,sp,0,0); + return(n); +} + +bits256 pangea_destpub(uint64_t destbits) +{ + int32_t i,haspubkey; bits256 destpub; char destNXT[64]; + memset(destpub.bytes,0,sizeof(destpub)); + for (i=0; itp->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; itableid && (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; itableid) && TABLES[i]->tp != 0 ) + { + for (j=0; jnumaddrs; 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; itableid); + free(sp); +} + diff --git a/iguana/poker.c b/iguana/poker.c new file mode 100755 index 000000000..61980b11c --- /dev/null +++ b/iguana/poker.c @@ -0,0 +1,644 @@ +// from http://www.azillionmonkeys.com/qed/poker.zip +// shamelessly copied from azillionmonkeys. getting millions of evals per second! + +#include +#include +#include +#include +#include +#include + +#define CLUB_SUIT (1) +#define DIAMOND_SUIT (2) +#define HEART_SUIT (4) +#define SPADE_SUIT (8) + +#define RANK_SHL (27) +#define SUBR_SHL (13) +#define SUBR_SHLMASK ((1<> 8) & 0x3F00; + i = ((i * (1 + 64 + 4096 + 262144)) >> 24) | s; +#endif + + f[0] = f[1] = f[2] = f[3] = 0; + cc[0] = cc[1] = cc[2] = cc[3] = 4; + + i = CardSuitIdx[h[0]]; + f[i] = c[0]; cc[i]--; + + i = CardSuitIdx[h[1]]; + f[i] |= c[1]; cc[i]--; + + i = CardSuitIdx[h[2]]; + f[i] |= c[2]; cc[i]--; + + i = CardSuitIdx[h[3]]; + f[i] |= c[3]; cc[i]--; + + i = CardSuitIdx[h[4]]; + f[i] |= c[4]; cc[i]--; + + i = CardSuitIdx[h[5]]; + f[i] |= c[5]; cc[i]--; + + i = CardSuitIdx[h[6]]; + f[i] |= c[6]; cc[i]--; + + // If any of the counts goes below 0, then that suit has at least 5 cards in it. + + if (((cc[0] | cc[1]) | (cc[2] | cc[3])) < 0) { + + // Map the negative count (of which there is at most 1) to the suit index. + + s = (((cc[0] & 8) | (cc[1] & 16)) | ((cc[2] & 32) | (cc[3] & 64))) >> 3; + s = LG2TAB[s]; + + // Work out the top 5 cards, so that the proper flush is also known ... + + t = f[s]; + while (cc[s] < -1) { + t &= t - 1; // Rip off last bit. + cc[s]++; + } + + // ... but also keep the low part so that all straight flushes can still be tested for. + + return f[s] | (t << SUBR_SHL); + } + // 0 -> indicates there is no flush in the hand. + return 0; +} + +#define SevenCardDrawFlushScore(f) (FLUSH_SCORE + ((f) >> SUBR_SHL)) + +u32 SevenCardDrawScore (const u8 * h) +{ + u32 c[7],f, t, s, u, v,m1, m2, m3, m4; + c[0] = CardMask[h[0]]; + c[1] = CardMask[h[1]]; + c[2] = CardMask[h[2]]; + c[3] = CardMask[h[3]]; + c[4] = CardMask[h[4]]; + c[5] = CardMask[h[5]]; + c[6] = CardMask[h[6]]; + // Work out flush mask always, since its only redundant in the case of a full house or 4 of a kind. + f = SevenCardDrawFlush (h, c); + // t is the full card mask + t = ((c[0] | c[1]) | (c[2] | c[3])) | (c[4] | c[5] | c[6]); + // If 7 cards are found in a row ... + s = t & (t - 1); + v = s ^ t; + u = (v << 7) - 1; + u &= ~(u >> 7); + // ... then work out the possible straight flush/bicycle, straight, and flush possibilities. + if ((u & t) == u) { + if (f) { + // Intersect the flush mask with the straight mask to try to figure out if we have a straight flush. + s = f & u; + u = s & (s - 1); + u ^= s; + u = (u << 7) - 1; + u &= ~(u >> 5); + t = u >> 1; + v = u >> 2; + if ((u & s) == u) return STRAIGHT_FLUSH_SCORE + u; + if ((t & s) == t) return STRAIGHT_FLUSH_SCORE + t; + if ((v & s) == v) return STRAIGHT_FLUSH_SCORE + v; + // Deal with possible bicycle/wheel 5,4,3,2,Ace straight flush + if ((0x100F & f) == 0x100F) + return STRAIGHT_FLUSH_SCORE + 0xF; + return SevenCardDrawFlushScore (f); + } + u &= ~(u >> 5); + return STRAIGHT_SCORE + u; + } + // If at most 6 cards are found in a row ... + u = (v << 6) - 1; + u &= ~(u >> 6); + if ((u & t) != u) { + u = s & (s - 1); + u ^= s; + u = (u << 6) - 1; + u &= ~(u >> 6); + } + // ... then work out the possible straight flush/bicycle, straight, and flush possibilities. + if ((u & t) == u) { + if (f) { + s = f & u; + u = s & (s - 1); + u ^= s; + u = (u << 6) - 1; + u &= ~(u >> 5); + t = u >> 1; + if ((u & s) == u) return STRAIGHT_FLUSH_SCORE + u; + if ((t & s) == t) return STRAIGHT_FLUSH_SCORE + t; + // Deal with possible bicycle/wheel 5,4,3,2,Ace straight flush + if ((0x100F & f) == 0x100F) + return STRAIGHT_FLUSH_SCORE + 0xF; + return SevenCardDrawFlushScore (f); + } + u &= ~(u >> 5); + return STRAIGHT_SCORE + u; + } + // If at most 5 cards are found in a row ... + u = (v << 5) - 1; + u &= ~(u >> 5); + if ((u & t) != u) { + v = s; + s = s & (s - 1); + v ^= s; + u = (v << 5) - 1; + u &= ~(u >> 5); + if ((u & t) != u) { + u = s & (s - 1); + s ^= u; + u = (s << 5) - 1; + u &= ~(u >> 5); + } + } + // ... then work out the possible straight flush/bicycle, straight, and flush possibilities. + if ((u & t) == u) { + if (f) { + s = f & u; + u = s & (s - 1); + u ^= s; + u = (u << 5) - 1; + u &= ~(u >> 5); + if ((u & s) == u) { + return STRAIGHT_FLUSH_SCORE + u; + } + // Deal with possible bicycle/wheel 5,4,3,2,Ace straight flush + if ((0x100F & f) == 0x100F) + return STRAIGHT_FLUSH_SCORE + 0xF; + return SevenCardDrawFlushScore (f); + } + u &= ~(u >> 5); + return STRAIGHT_SCORE + u; + } + // Deal with the bicycle/wheel 5,4,3,2,Ace straight + if ((0x100F & t) == 0x100F) { + if (f) + { + if ((0x100F & f) == 0x100F) + return STRAIGHT_FLUSH_SCORE + 0xF; + return SevenCardDrawFlushScore (f); + } + return STRAIGHT_SCORE + 0xF; + } + /* + // m1 = c0 | ... | c4 + // m2 = (c0 & c1) | ((c0|c1) & c2) | ((c0|c1|c2) & c3) | ((c0|c1|c2|c3) & c4) + // m3 = mask of 3 or 4 of a kind. + // m4 = mask of 4 of a kind. + */ + + m1 = c[0] | c[1]; + m2 = c[1] & c[0]; + + m3 = c[2] & m2; + m2 |= c[2] & m1; + m1 |= c[2]; + + m4 = c[3] & m3; + m3 |= c[3] & m2; + m2 |= c[3] & m1; + m1 |= c[3]; + + m4 |= c[4] & m3; + m3 |= c[4] & m2; + m2 |= c[4] & m1; + m1 |= c[4]; + + m4 |= c[5] & m3; + m3 |= c[5] & m2; + m2 |= c[5] & m1; + m1 |= c[5]; + + m4 |= c[6] & m3; + m3 |= c[6] & m2; + m2 |= c[6] & m1; + m1 |= c[6]; + // Make sure the m1 is just the mask of singleton cards. + m1 &= ~m2; + // No 3 or 4 of a kinds. + if (m3 == 0) { + if (f) { + return SevenCardDrawFlushScore (f); + } + if (m2) { + s = m2 & (m2 - 1); + if (s == 0) { + t = m1 & (m1 - 1); + t &= (t - 1); + return TWO_KIND_SCORE + (m2 << SUBR_SHL) + t; + } + v = m1; + t = s & (s - 1); + if (t) { + v |= m2 ^ s; + m2 = s; + } else { + v &= (v - 1); + } + v &= (v - 1); + return TWO_PAIR_SCORE + (m2 << SUBR_SHL) + v; + } + // Nothing -- just remove the two low cards. + m1 &= (m1 - 1); + m1 &= (m1 - 1); + return m1; + } + // 4 of a kind. + if (m4) { + m1 |= (m2 & ~m4); + while ((m2 = (m1 & (m1 - 1))) != 0) { + m1 = m2; + } + return FOUR_KIND_SCORE + (m4 << SUBR_SHL) + m1; + } + // 3 of a kind, but no other pair in the hand + if ((m2 & ~m3) == 0) { + t = m3 & (m3 - 1); + // Two 3 of a kinds => Full House + if (t) + return FULL_HOUSE_SCORE + (t << SUBR_SHL) + (m3 ^ t); + if (f) + return SevenCardDrawFlushScore (f); + // Just remove the two low cards, and score this as 3 of a kind. + m1 &= (m1 - 1); + m1 &= (m1 - 1); + return THREE_KIND_SCORE + (m3 << SUBR_SHL) + m1; + } + // 3 of a kind and a seperate 2 of a kind (full house.) + m2 &= ~m3; + t = m2 & (m2 - 1); + // If there are two 2 pairs in the hand, then pick the higher pair + if (!t) t = m2; + return FULL_HOUSE_SCORE + (m3 << SUBR_SHL) + t; +} + +// Just a brute force 7 card draw ranking by picking each of the possible two cards to be skipped, and finding the score which is highest amongst the 21 possible 5 card sub-hands. +u32 SevenCardDrawScoreSlow (const u8 * h) { +s32 i, j, k; +u32 r, m; +u8 h2[5]; + + m = 0; + for (i=0; i < 6; i++) { + for (k=0; k < i; k++) { + h2[k] = h[k]; + } + for (j=i+1; j < 7; j++) { + for (k=i+1; k < j; k++) { + h2[k-1] = h[k]; + } + for (k=j+1; k < 7; k++) { + h2[k-2] = h[k]; + } + r = FiveCardDrawScore (h2); + if (r > m) m = r; + } + } + return m; +} + +// A correctly distributed (ignoring the problem of using "rand() % x") reshuffling of your cards. +static void Shuffle (CardPileType * c) +{ + int32_t i, j, k; u8 t; + for (i = 0; i < (c->len - 1); i++) + { + k = (RAND_MAX / (c->len - i)) * (c->len - i); + do { + j = rand (); + } while (j >= k); + j = i + (j % (c->len - i)); + t = c->entry[i]; + c->entry[i] = c->entry[j]; + c->entry[j] = t; + } +} + +static int32_t Deal (CardPileType * h, CardPileType * d, int32_t n) +{ + int32_t i; + for (i=0; i < n && d->len > 0; i++) + { + d->len--; + h->entry[ h->len ] = d->entry[ d->len ]; + h->len++; + } + return i; +} + +static void InitDeck (CardPileType * deck) +{ + u8 i; + deck->len = 52; + for (i=0; i < 52; i++) deck->entry[i] = i; +} + +static void DisplayCard (u8 c, char out[]) +{ + // char suitdisp[9] = { 0, 5, 4, 0, 3, 0, 0, 0, 6 }; + static char suitdisp[9] = { 0, 'c', 'd', 0, 'h', 0, 0, 0, 's' }; + char s[4]; + s[0] = " 1 "[CardValue[c]]; + s[1] = "234567890JQKA"[CardValue[c]]; + s[2] = suitdisp[CardSuit[c]]; + s[3] = '\0'; + strcat (out, " "); + strcat (out, s); +} + +void DisplayHand5 (const CardPileType * h) { + char out[128]; + int i; + + out[0] = '\0'; + for (i=0; i < 5; i++) DisplayCard (h->entry[i], out); + sprintf (out + strlen (out), " => %08X\n", (int)FiveCardDrawScore (&h->entry[0])); + printf ("%s", out); +} + +void set_cardstr(char *cardstr,uint32_t c) +{ + /*static char suitdisp[9] = { 0, 'c', 'd', 0, 'h', 0, 0, 0, 's' }; + cardstr[0] = " 1 "[CardValue[c % 13]]; + cardstr[1] = "234567890JQKA"[CardValue[c % 13]]; + cardstr[2] = suitdisp[CardSuit[c]]; + cardstr[3] = '\0';*/ + + int32_t i,j=0; + c >>= 1; + for (i=12; i>=0; i--) + if ( ((1 << i) & c) != 0 ) + { + cardstr[j++] = " 1 "[i]; + cardstr[j++] = "234567890JQKA"[i]; + cardstr[j++] = ' '; + } + cardstr[j++] = 0; +} + +uint32_t set_handstr(char *handstr,uint8_t cards[7],int32_t verbose) +{ + char cardstr[32],cardstr2[32],*kickerstr,*str; uint32_t score,i; + handstr[0] = 0; + if ( cards == 0 ) + { + handstr[0] = 0; + printf("set_handstr: null cards??\n"); + return(0); + } + for (i=0; i<7; i++) + if ( cards[i] < 0 || cards[i] >= 52 ) + { + //printf("illegal card[%d] %d\n",i,cards[i]); + return(0); + } + score = SevenCardDrawScore (&cards[0]); + set_cardstr(cardstr,(score>>SUBR_SHL) & SUBR_SHLMASK); + set_cardstr(cardstr2,score & SUBR_SHLMASK); + kickerstr = kickerstrs[(score>>RANK_SHL)&15]; + str = handstrs[(score>>RANK_SHL)&15]; + if ( verbose != 0 ) + { + if ( strcmp(kickerstr,"high") == 0 ) + sprintf(handstr,"%c%c high %s",cardstr2[0],cardstr2[1],str); + else if ( strcmp(str,"full house") == 0 ) + sprintf(handstr,"%c%c full of %c%c",cardstr[0],cardstr[1],cardstr2[0],cardstr2[1]); + else if ( strcmp(str,"three of a kind") == 0 ) + sprintf(handstr,"set of %c%c with kickers %c%c %c%c",cardstr[0],cardstr[1],cardstr2[0],cardstr2[1],cardstr2[3],cardstr2[4]); + else if ( strcmp(str,"two pair") == 0 ) + sprintf(handstr,"two pair %c%c and %c%c with %c%c kicker",cardstr[0],cardstr[1],cardstr[3],cardstr[4],cardstr2[0],cardstr2[1]); + else if ( strcmp(str,"one pair") == 0 ) + sprintf(handstr,"pair of %c%c with %c%c kicker",cardstr[0],cardstr[1],cardstr2[0],cardstr2[1]); + else sprintf(handstr,"%s %s %s %s",str,cardstr,kickerstr,cardstr2); + } + else + { + if ( strcmp(kickerstr,"high") == 0 ) + sprintf(handstr,"%c%c high %s",cardstr2[0],cardstr2[1],str); + else if ( strcmp(str,"full house") == 0 ) + sprintf(handstr,"fullhouse %c%c %c%c",cardstr[0],cardstr[1],cardstr2[0],cardstr2[1]); + else if ( strcmp(str,"three of a kind") == 0 ) + sprintf(handstr,"trip %c%c",cardstr[0],cardstr[1]); + else if ( strcmp(str,"two pair") == 0 ) + sprintf(handstr,"two pairs %c%c %c%c",cardstr[0],cardstr[1],cardstr[3],cardstr[4]); + else if ( strcmp(str,"one pair") == 0 ) + sprintf(handstr,"pair %c%c",cardstr[0],cardstr[1]); + else sprintf(handstr,"%s",cardstr2); + } + return(score); +} + +void DisplayHand7(char *handstr,uint8_t *cards) +{ + uint32_t x,y; int32_t i; char out[512]; + out[0] = '\0'; + for (i=0; i<7; i++) + DisplayCard (cards[i], out); + x = SevenCardDrawScore (cards); + y = SevenCardDrawScoreSlow (cards); + set_handstr(handstr,cards,1); + if ( x != y ) + fprintf(stderr,"Error slow score %08x vs fast score %08x???\n",y,x); + sprintf (out + strlen (out), " => %08x %6d %6d -> (%s)",x,(x>>SUBR_SHL)&SUBR_SHLMASK,x&SUBR_SHLMASK,handstr); + printf("%s\n",out); +} + +void poker_test() +{ + char *_mbstr(double n); + CardPileType Deck,Hands[1000]; uint32_t c,starttime,score; uint64_t total,counter; char handstr[512]; uint8_t *cards; + //srand (0); + InitDeck (&Deck); + Shuffle (&Deck); + for (c=0; c<(sizeof(Hands)/sizeof(*Hands)); c++) + { + Deal (&Hands[c],&Deck,7); + DisplayHand7(handstr,Hands[c].entry); + Deal (&Deck,&Hands[c],7); + Shuffle(&Deck); + } + starttime = (uint32_t)time(NULL); +#ifndef _WIN32 + while ( (uint32_t)time(NULL) == starttime ) + usleep(100); + total = counter = 0; + while ( (uint32_t)time(NULL) < starttime+11 ) + { + for (c=0; c<1000; c++,counter++) + { + cards = Hands[c % (sizeof(Hands)/sizeof(*Hands))].entry; + score = SevenCardDrawScore(cards); + total += score; + } + } + char *mbstr(char *str,double val); + char str[65]; printf("counter.%llu %s in 10 seconds: ave score %llx\n",(long long)counter,mbstr(str,counter),(long long)(total/counter)); +#endif +} diff --git a/iguana/ramchain_api.c b/iguana/ramchain_api.c index 112f951d6..9f2a2abac 100755 --- a/iguana/ramchain_api.c +++ b/iguana/ramchain_api.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/includes/iguana_api.h b/includes/iguana_api.h index 104070971..4d20d5bff 100755 --- a/includes/iguana_api.h +++ b/includes/iguana_api.h @@ -18,7 +18,7 @@ #include "../includes/iguana_apidefs.h" #include "../includes/iguana_apideclares.h" -#undef IGUANA_ARGS +//#undef IGUANA_ARGS #include "../includes/iguana_apiundefs.h" diff --git a/includes/iguana_apideclares.h b/includes/iguana_apideclares.h index f6457b1c9..a7d97f884 100755 --- a/includes/iguana_apideclares.h +++ b/includes/iguana_apideclares.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -13,17 +13,61 @@ * * ******************************************************************************/ -ZERO_ARGS(SuperNET,saveconf); ZERO_ARGS(SuperNET,help); TWO_STRINGS(SuperNET,html,agentform,htmlfile); STRING_ARG(SuperNET,bitcoinrpc,setcoin); -TWOSTRINGS_AND_HASH_AND_TWOINTS(SuperNET,DHT,message,destip,destpub,maxdelay,broadcast); +TWOSTRINGS_AND_HASH_AND_TWOINTS(SuperNET,DHT,hexmsg,destip,destpub,maxdelay,broadcast); + +THREE_STRINGS(SuperNET,rosetta,passphrase,pin,showprivkey); +ZERO_ARGS(SuperNET,keypair); +HASH_ARG(SuperNET,priv2pub,privkey); + +TWOHASHES_AND_STRING(SuperNET,cipher,privkey,destpubkey,message); +TWOHASHES_AND_STRING(SuperNET,decipher,privkey,srcpubkey,cipherstr); + +STRING_ARG(SuperNET,broadcastcipher,message); +STRING_ARG(SuperNET,broadcastdecipher,message); + +HASH_AND_STRING(SuperNET,multicastcipher,pubkey,message); +HASH_AND_STRING(SuperNET,multicastdecipher,privkey,cipherstr); + +ZERO_ARGS(SuperNET,keypair); +HASH_ARG(SuperNET,priv2pub,privkey); + +THREE_STRINGS(SuperNET,announce,category,subcategory,message); +THREE_STRINGS(SuperNET,survey,category,subcategory,message); + STRING_ARG(SuperNET,getpeers,activecoin); TWO_ARRAYS(SuperNET,mypeers,supernet,rawpeers); ZERO_ARGS(SuperNET,stop); -HASH_AND_STRING(SuperNET,sharepersistent,persistentpub,destip); +HASH_AND_STRING(SuperNET,saveconf,wallethash,confjsonstr); HASH_ARRAY_STRING(SuperNET,layer,mypriv,otherpubs,str); +INT_AND_ARRAY(pangea,newhand,senderind,args); +INT_AND_ARRAY(pangea,ping,senderind,args); +INT_AND_ARRAY(pangea,gotdeck,senderind,args); +INT_AND_ARRAY(pangea,ready,senderind,args); +INT_AND_ARRAY(pangea,encoded,senderind,args); +INT_AND_ARRAY(pangea,final,senderind,args); +INT_AND_ARRAY(pangea,addedfunds,senderind,args); +INT_AND_ARRAY(pangea,preflop,senderind,args); +INT_AND_ARRAY(pangea,decoded,senderind,args); +INT_AND_ARRAY(pangea,card,senderind,args); +INT_AND_ARRAY(pangea,facedown,senderind,args); +INT_AND_ARRAY(pangea,faceup,senderind,args); +INT_AND_ARRAY(pangea,turn,senderind,args); +INT_AND_ARRAY(pangea,confirmturn,senderind,args); +INT_AND_ARRAY(pangea,chat,senderind,args); +INT_AND_ARRAY(pangea,action,senderind,args); +INT_AND_ARRAY(pangea,showdown,senderind,args); +INT_AND_ARRAY(pangea,handsummary,senderind,args); + +//U64_AND_ARRAY(pangea,turn,tableid,args); +U64_AND_ARRAY(pangea,status,tableid,args); +U64_AND_ARRAY(pangea,mode,tableid,args); +U64_AND_ARRAY(pangea,buyin,tableid,args); +U64_AND_ARRAY(pangea,history,tableid,args); + STRING_ARG(iguana,peers,activecoin); STRING_AND_INT(iguana,maxpeers,activecoin,max); STRING_ARG(iguana,getconnectioncount,activecoin); diff --git a/includes/iguana_apidefs.h b/includes/iguana_apidefs.h index 32e039a7b..681a65cde 100755 --- a/includes/iguana_apidefs.h +++ b/includes/iguana_apidefs.h @@ -1,4 +1,5 @@ +#define IGUANA_CALLARGS myinfo,coin,json,remoteaddr #define IGUANA_ARGS struct supernet_info *myinfo,struct iguana_info *coin,cJSON *json,char *remoteaddr #define IGUANA_CFUNC0(agent,name) char *agent ## _ ## name(IGUANA_ARGS) #define IGUANA_CFUNC_S(agent,name,str) char *agent ## _ ## name(IGUANA_ARGS,char *str) @@ -6,6 +7,10 @@ #define IGUANA_CFUNC_SA(agent,name,str,array) char *agent ## _ ## name(IGUANA_ARGS,char *str,cJSON *array) #define IGUANA_CFUNC_AA(agent,name,array,array2) char *agent ## _ ## name(IGUANA_ARGS,cJSON *array,cJSON *array2) #define IGUANA_CFUNC_SAA(agent,name,str,array,array2) char *agent ## _ ## name(IGUANA_ARGS,char *str,cJSON *array,cJSON *array2) + +#define IGUANA_CFUNC_64A(agent,name,j64,array) char *agent ## _ ## name(IGUANA_ARGS,uint64_t j64,cJSON *array) + + #define IGUANA_CFUNC_IA(agent,name,val,array) char *agent ## _ ## name(IGUANA_ARGS,int32_t val,cJSON *array) #define IGUANA_CFUNC_IAS(agent,name,val,array,str) char *agent ## _ ## name(IGUANA_ARGS,int32_t val,cJSON *array,char *str) #define IGUANA_CFUNC_II(agent,name,val,val2) char *agent ## _ ## name(IGUANA_ARGS,int32_t val,int32_t val2) @@ -21,6 +26,7 @@ #define IGUANA_CFUNC_SI(agent,name,str,val) char *agent ## _ ## name(IGUANA_ARGS,char *str,int32_t val) #define IGUANA_CFUNC_SII(agent,name,str,val,val2) char *agent ## _ ## name(IGUANA_ARGS,char *str,int32_t val,int32_t val2) #define IGUANA_CFUNC_HI(agent,name,hash,val) char *agent ## _ ## name(IGUANA_ARGS,bits256 hash,int32_t val) +#define IGUANA_CFUNC_H(agent,name,hash) char *agent ## _ ## name(IGUANA_ARGS,bits256 hash) #define IGUANA_CFUNC_HS(agent,name,hash,str) char *agent ## _ ## name(IGUANA_ARGS,bits256 hash,char *str) #define IGUANA_CFUNC_HHS(agent,name,hash,hash2,str) char *agent ## _ ## name(IGUANA_ARGS,bits256 hash,bits256 hash2,char *str) #define IGUANA_CFUNC_HAS(agent,name,hash,array,str) char *agent ## _ ## name(IGUANA_ARGS,bits256 hash,cJSON *array,char *str) @@ -61,3 +67,5 @@ #define TWOSTRINGS_AND_HASH_AND_TWOINTS IGUANA_CFUNC_SSHII #define THREE_INTS IGUANA_CFUNC_III #define HASH_ARRAY_STRING IGUANA_CFUNC_HAS +#define U64_AND_ARRAY IGUANA_CFUNC_64A +#define HASH_ARG IGUANA_CFUNC_H \ No newline at end of file diff --git a/includes/iguana_apiundefs.h b/includes/iguana_apiundefs.h index 9d0a14cb2..09e509d67 100755 --- a/includes/iguana_apiundefs.h +++ b/includes/iguana_apiundefs.h @@ -28,3 +28,9 @@ #undef TWOSTRINGS_AND_HASH_AND_TWOINTS #undef TWOHASHES_AND_STRING #undef HASH_ARRAY_STRING +#undef U64_AND_ARRAY +#undef HASH_ARG + +#undef IGUANA_ARGS +#undef IGUANA_CALLARGS + diff --git a/includes/tweetnacl.h b/includes/tweetnacl.h index 2771b886d..ce0fa9bcb 100755 --- a/includes/tweetnacl.h +++ b/includes/tweetnacl.h @@ -22,6 +22,7 @@ extern int crypto_auth_hmacsha512256_tweet_verify(const unsigned char *,const un #define crypto_box crypto_box_curve25519xsalsa20poly1305 #define crypto_box_open crypto_box_curve25519xsalsa20poly1305_open #define crypto_box_keypair crypto_box_curve25519xsalsa20poly1305_keypair +#define crypto_box_priv2pub crypto_box_curve25519xsalsa20poly1305_priv2pub #define crypto_box_beforenm crypto_box_curve25519xsalsa20poly1305_beforenm #define crypto_box_afternm crypto_box_curve25519xsalsa20poly1305_afternm #define crypto_box_open_afternm crypto_box_curve25519xsalsa20poly1305_open_afternm @@ -42,6 +43,7 @@ extern int crypto_auth_hmacsha512256_tweet_verify(const unsigned char *,const un extern int crypto_box_curve25519xsalsa20poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *,const unsigned char *); extern int crypto_box_curve25519xsalsa20poly1305_tweet_open(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *,const unsigned char *); extern int crypto_box_curve25519xsalsa20poly1305_tweet_keypair(unsigned char *,unsigned char *); +extern int crypto_box_curve25519xsalsa20poly1305_tweet_priv2pub(unsigned char *,unsigned char *); extern int crypto_box_curve25519xsalsa20poly1305_tweet_beforenm(unsigned char *,const unsigned char *,const unsigned char *); extern int crypto_box_curve25519xsalsa20poly1305_tweet_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); extern int crypto_box_curve25519xsalsa20poly1305_tweet_open_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); @@ -49,6 +51,7 @@ extern int crypto_box_curve25519xsalsa20poly1305_tweet_open_afternm(unsigned cha #define crypto_box_curve25519xsalsa20poly1305 crypto_box_curve25519xsalsa20poly1305_tweet #define crypto_box_curve25519xsalsa20poly1305_open crypto_box_curve25519xsalsa20poly1305_tweet_open #define crypto_box_curve25519xsalsa20poly1305_keypair crypto_box_curve25519xsalsa20poly1305_tweet_keypair +#define crypto_box_curve25519xsalsa20poly1305_priv2pub crypto_box_curve25519xsalsa20poly1305_tweet_priv2pub #define crypto_box_curve25519xsalsa20poly1305_beforenm crypto_box_curve25519xsalsa20poly1305_tweet_beforenm #define crypto_box_curve25519xsalsa20poly1305_afternm crypto_box_curve25519xsalsa20poly1305_tweet_afternm #define crypto_box_curve25519xsalsa20poly1305_open_afternm crypto_box_curve25519xsalsa20poly1305_tweet_open_afternm