Merge pull request #1370 from jl777/jl777

Jl777
This commit is contained in:
jl777
2019-04-01 05:37:22 -11:00
committed by GitHub
48 changed files with 7424 additions and 4611 deletions

View File

@@ -59,13 +59,16 @@ static bool fDaemon;
#include "komodo_defs.h"
#define KOMODO_ASSETCHAIN_MAXLEN 65
extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
extern uint32_t ASSETCHAINS_BLOCKTIME;
extern uint64_t ASSETCHAINS_CBOPRET;
void komodo_passport_iteration();
uint64_t komodo_interestsum();
int32_t komodo_longestchain();
void komodo_cbopretupdate();
void WaitForShutdown(boost::thread_group* threadGroup)
{
bool fShutdown = ShutdownRequested();
int32_t i; bool fShutdown = ShutdownRequested();
// Tell the main threads to shutdown.
while (!fShutdown)
{
@@ -73,13 +76,27 @@ void WaitForShutdown(boost::thread_group* threadGroup)
if ( ASSETCHAINS_SYMBOL[0] == 0 )
{
komodo_passport_iteration();
MilliSleep(10000);
for (i=0; i<10; i++)
{
fShutdown = ShutdownRequested();
if ( fShutdown != 0 )
break;
MilliSleep(1000);
}
}
else
{
//komodo_interestsum();
//komodo_longestchain();
MilliSleep(20000);
if ( ASSETCHAINS_CBOPRET != 0 )
komodo_cbopretupdate();
for (i=0; i<=ASSETCHAINS_BLOCKTIME/5; i++)
{
fShutdown = ShutdownRequested();
if ( fShutdown != 0 )
break;
MilliSleep(1000);
}
}
fShutdown = ShutdownRequested();
}

View File

@@ -197,6 +197,7 @@ int64_t IsTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *c
bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx);
void komodo_sendmessage(int32_t minpeers,int32_t maxpeers,const char *message,std::vector<uint8_t> payload);
int32_t payments_parsehexdata(std::vector<uint8_t> &hexdata,cJSON *item,int32_t len);
int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex);
CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector<uint8_t> origpubkey, std::string name, std::string description, vscript_t vopretNonfungible);
CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector<uint8_t> origpubkey, std::string name, std::string description, std::vector<std::pair<uint8_t, vscript_t>> oprets);
@@ -247,6 +248,7 @@ void CCaddrTokens1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, c
int32_t CClib_initcp(struct CCcontract_info *cp,uint8_t evalcode);
bool IsCCInput(CScript const& scriptSig);
bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_t blocktime);
int32_t unstringbits(char *buf,uint64_t bits);
uint64_t stringbits(char *str);
uint256 revuint256(uint256 txid);

View File

@@ -168,6 +168,18 @@ bool IsCCInput(CScript const& scriptSig)
return true;
}
bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_t blocktime)
{
int64_t interest; uint64_t valuein;
CCoinsViewCache &view = *pcoinsTip;
valuein = view.GetValueIn(height,&interest,tx,blocktime);
if ( valuein-tx.GetValueOut() > txfee )
{
//fprintf(stderr, "txfee.%li vs txfee.%li\n", valuein-tx.GetValueOut(), txfee);
return false;
}
return true;
}
// set additional 'unspendable' addr
void CCaddr2set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr)
@@ -668,4 +680,4 @@ bool CClib_Dispatch(const CC *cond,Eval *eval,std::vector<uint8_t> paramsNull,co
return(false); //eval->Invalid("error in CClib_validate");
}
return eval->Invalid("cclib CC must have evalcode between 16 and 127");
}
}

View File

@@ -52,6 +52,8 @@ std::string MYCCLIBNAME = (char *)"sudoku";
void komodo_netevent(std::vector<uint8_t> payload) {}
#endif
extern std::string MYCCLIBNAME;
char *CClib_name() { return((char *)MYCCLIBNAME.c_str()); }
struct CClib_rpcinfo
@@ -691,8 +693,8 @@ int32_t cclib_parsehash(uint8_t *hash32,cJSON *item,int32_t len)
#include "customcc.cpp"
#elif BUILD_GAMESCC
#include "gamescc.cpp"
#include "rogue/cursesd.c"
#include "gamescc.cpp"
#else
#include "sudoku.cpp"

1119
src/cc/dapps/dappstd.c Normal file

File diff suppressed because it is too large Load Diff

289
src/cc/games/prices.c Normal file
View File

@@ -0,0 +1,289 @@
#include "prices.h"
#include <time.h>
#include <unistd.h>
#ifdef BUILD_GAMESCC
#include "../rogue/cursesd.h"
#else
#include <curses.h>
#endif
#define SATOSHIDEN ((uint64_t)100000000L)
#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"prices",cmdstr,0,0,0)
extern int64_t Net_change,Betsize;
int random_tetromino(struct games_state *rs)
{
rs->seed = _games_rngnext(rs->seed);
return(rs->seed % NUM_TETROMINOS);
}
int32_t pricesdata(struct games_player *P,void *ptr)
{
tetris_game *tg = (tetris_game *)ptr;
P->gold = tg->points;
P->dungeonlevel = tg->level;
//fprintf(stderr,"score.%d level.%d\n",tg->points,tg->level);
return(0);
}
void sleep_milli(int milliseconds)
{
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = milliseconds * 1000 * 1000;
nanosleep(&ts, NULL);
}
struct games_state globalR;
extern char Gametxidstr[];
int32_t issue_games_events(struct games_state *rs,char *gametxidstr,uint32_t eventid,gamesevent c);
uint64_t get_btcusd();
int32_t issue_bet(struct games_state *rs,int64_t x,int64_t betsize);
void *gamesiterate(struct games_state *rs)
{
bool running = true; uint32_t eventid = 0; int64_t price;
if ( rs->guiflag != 0 || rs->sleeptime != 0 )
{
initscr(); // initialize curses
cbreak(); // pass key presses to program, but not signals
noecho(); // don't echo key presses to screen
timeout(0);
}
while ( running != 0 )
{
//running = tg_tick(rs,tg,move);
if ( rs->guiflag != 0 || rs->sleeptime != 0 )
{
}
if ( rs->guiflag != 0 )
{
#ifdef STANDALONE
price = get_btcusd();
//fprintf(stderr,"%llu -> t%u %.4f\n",(long long)price,(uint32_t)(price >> 32),(double)(price & 0xffffffff)/10000);
//issue_games_events(rs,Gametxidstr,eventid,price);
issue_bet(rs,price,Betsize);
eventid++;
doupdate();
sleep(10);
switch ( getch() )
{
case '+': Net_change++; break;
case '-': Net_change--; break;
case '0': Net_change = 0; break;
case '$': Betsize = SATOSHIDEN; break;
case '^': Betsize += (Betsize >> 3); break;
case '/': Betsize -= (Betsize >> 3); break;
}
/*if ( (counter++ % 10) == 0 )
doupdate();
c = games_readevent(rs);
if ( c <= 0x7f || skipcount == 0x3fff )
{
if ( skipcount > 0 )
issue_games_events(rs,Gametxidstr,eventid-skipcount,skipcount | 0x4000);
if ( c <= 0x7f )
issue_games_events(rs,Gametxidstr,eventid,c);
if ( tg->level != prevlevel )
{
flushkeystrokes(rs,0);
prevlevel = tg->level;
}
skipcount = 0;
} else skipcount++;*/
#endif
}
else
{
if ( rs->replaydone != 0 )
break;
if ( rs->sleeptime != 0 )
{
sleep_milli(1);
}
/*if ( skipcount == 0 )
{
c = games_readevent(rs);
//fprintf(stderr,"%04x score.%d level.%d\n",c,tg->points,tg->level);
if ( (c & 0x4000) == 0x4000 )
{
skipcount = (c & 0x3fff);
c = 'S';
}
}
if ( skipcount > 0 )
skipcount--;*/
}
eventid++;
}
return(0);
}
#ifdef STANDALONE
#include <ncurses.h>
#include "dapps/dappstd.c"
int64_t Net_change,Betsize = SATOSHIDEN;
char *send_curl(char *url,char *fname)
{
char *retstr;
retstr = issue_curl(url);
return(retstr);
}
cJSON *get_urljson(char *url,char *fname)
{
char *jsonstr; cJSON *json = 0;
if ( (jsonstr= send_curl(url,fname)) != 0 )
{
//printf("(%s) -> (%s)\n",url,jsonstr);
json = cJSON_Parse(jsonstr);
free(jsonstr);
}
return(json);
}
//////////////////////////////////////////////
// start of dapp
//////////////////////////////////////////////
uint64_t get_btcusd()
{
cJSON *pjson,*bpi,*usd; char str[512]; uint64_t x,newprice,mult,btcusd = 0;
if ( (pjson= get_urljson((char *)"http://api.coindesk.com/v1/bpi/currentprice.json",(char *)"/tmp/oraclefeed.json")) != 0 )
{
if ( (bpi= jobj(pjson,(char *)"bpi")) != 0 && (usd= jobj(bpi,(char *)"USD")) != 0 )
{
btcusd = jdouble(usd,(char *)"rate_float") * SATOSHIDEN;
mult = 10000 + Net_change*10;
newprice = (btcusd * mult) / 10000;
x = ((uint64_t)time(NULL) << 32) | ((newprice / 10000) & 0xffffffff);
sprintf(str,"BTC/USD %.4f -> Betsize %.8f (^ / to change) && %.4f Net %.1f%% [+ - to change]\n",dstr(btcusd),dstr(Betsize),dstr(newprice),(double)100*(mult-10000)/10000);
mvaddstr(0, 0, str);
clrtoeol();
doupdate();
}
free_json(pjson);
}
return(x);
}
char *clonestr(char *str)
{
char *clone; int32_t len;
if ( str == 0 || str[0] == 0 )
{
printf("warning cloning nullstr.%p\n",str);
#ifdef __APPLE__
while ( 1 ) sleep(1);
#endif
str = (char *)"<nullstr>";
}
len = strlen(str);
clone = (char *)calloc(1,len+16);
strcpy(clone,str);
return(clone);
}
int32_t issue_games_events(struct games_state *rs,char *gametxidstr,uint32_t eventid,gamesevent c)
{
static FILE *fp;
char params[512],*retstr; cJSON *retjson,*resobj; int32_t retval = -1;
if ( fp == 0 )
fp = fopen("events.log","wb");
rs->buffered[rs->num++] = c;
if ( 1 )
{
if ( sizeof(c) == 1 )
sprintf(params,"[\"events\",\"17\",\"[%%22%02x%%22,%%22%s%%22,%u]\"]",(uint8_t)c&0xff,gametxidstr,eventid);
else if ( sizeof(c) == 2 )
sprintf(params,"[\"events\",\"17\",\"[%%22%04x%%22,%%22%s%%22,%u]\"]",(uint16_t)c&0xffff,gametxidstr,eventid);
else if ( sizeof(c) == 4 )
sprintf(params,"[\"events\",\"17\",\"[%%22%08x%%22,%%22%s%%22,%u]\"]",(uint32_t)c&0xffffffff,gametxidstr,eventid);
else if ( sizeof(c) == 8 )
sprintf(params,"[\"events\",\"17\",\"[%%22%016llx%%22,%%22%s%%22,%u]\"]",(long long)c,gametxidstr,eventid);
if ( (retstr= komodo_issuemethod(USERPASS,(char *)"cclib",params,GAMES_PORT)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (resobj= jobj(retjson,(char *)"result")) != 0 )
{
retval = 0;
if ( fp != 0 )
{
fprintf(fp,"%s\n",jprint(resobj,0));
fflush(fp);
}
}
free_json(retjson);
} else fprintf(fp,"error parsing %s\n",retstr);
free(retstr);
} else fprintf(fp,"error issuing method %s\n",params);
return(retval);
} else return(0);
}
int32_t issue_bet(struct games_state *rs,int64_t x,int64_t betsize)
{
char params[512],hexstr[64],*retstr; cJSON *retjson,*resobj; int32_t i,retval = -1;
memset(hexstr,0,sizeof(hexstr));
for (i=0; i<8; i++)
{
sprintf(&hexstr[i<<1],"%02x",(uint8_t)(x & 0xff));
x >>= 8;
}
sprintf(params,"[\"bet\",\"17\",\"[%.8f,%%22%s%%22]\"]",dstr(betsize),hexstr);
if ( (retstr= komodo_issuemethod(USERPASS,(char *)"cclib",params,GAMES_PORT)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (resobj= jobj(retjson,(char *)"result")) != 0 )
{
retval = 0;
//fprintf(stderr,"%s\n",jprint(resobj,0));
}
free_json(retjson);
}
free(retstr);
}
return(retval);
}
int prices(int argc, char **argv)
{
struct games_state *rs = &globalR;
int32_t c,skipcount=0; uint32_t eventid = 0;
memset(rs,0,sizeof(*rs));
rs->guiflag = 1;
rs->sleeptime = 1; // non-zero to allow refresh()
if ( argc >= 2 && strlen(argv[2]) == 64 )
{
#ifdef _WIN32
#ifdef _MSC_VER
rs->origseed = _strtoui64(argv[1], NULL, 10);
#else
rs->origseed = atol(argv[1]); // windows, but not MSVC
#endif // _MSC_VER
#else
rs->origseed = atol(argv[1]); // non-windows
#endif // _WIN32
rs->seed = rs->origseed;
if ( argc >= 3 )
{
strcpy(Gametxidstr,argv[2]);
fprintf(stderr,"setplayerdata %s\n",Gametxidstr);
if ( games_setplayerdata(rs,Gametxidstr) < 0 )
{
fprintf(stderr,"invalid gametxid, or already started\n");
return(-1);
}
}
} else rs->seed = 777;
gamesiterate(rs);
//gamesbailout(rs);
return 0;
}
#endif

281
src/cc/games/prices.cpp Normal file
View File

@@ -0,0 +1,281 @@
/******************************************************************************
* Copyright © 2014-2019 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. *
* *
******************************************************************************/
std::string MYCCLIBNAME = (char *)"prices";
#define PRICES_BETPERIOD 3
UniValue games_rawtxresult(UniValue &result,std::string rawtx,int32_t broadcastflag);
extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33];
#define bstr(x) ((double)((uint32_t)x) / 10000.)
struct prices_bar
{
uint64_t open,high,low,close,sum;
int32_t num;
};
int32_t prices_barupdate(struct prices_bar *bar,uint64_t pricebits)
{
uint32_t uprice,timestamp;
timestamp = (uint32_t)(pricebits >> 32);
uprice = (uint32_t)pricebits;
bar->sum += uprice, bar->num++;
if ( bar->open == 0 )
bar->open = bar->high = bar->low = pricebits;
if ( uprice > (uint32_t)bar->high )
bar->high = pricebits;
else if ( uprice < (uint32_t)bar->low )
bar->low = pricebits;
bar->close = pricebits;
return(0);
}
int64_t prices_bardist(struct prices_bar *bar,uint32_t aveprice,uint64_t pricebits)
{
int64_t a,dist = 0;
if ( aveprice != 0 )
{
a = (pricebits & 0xffffffff);
dist = (a - aveprice);
dist *= dist;
//fprintf(stderr,"dist.%lld (u %u - ave %u) %d\n",(long long)dist,uprice,aveprice,uprice-aveprice);
}
return(dist);
}
void prices_bardisp(struct prices_bar *bar)
{
if ( bar->num == 0 )
fprintf(stderr,"BAR null\n");
else fprintf(stderr,"BAR ave %.4f (O %.4f, H %.4f, L %.4f, C %.4f)\n",bstr(bar->sum/bar->num),bstr(bar->open),bstr(bar->high),bstr(bar->low),bstr(bar->close));
}
int64_t prices_blockinfo(int32_t height,char *acaddr)
{
std::vector<uint8_t> vopret; CBlockIndex *pindex; CBlock block; CTransaction tx,vintx; uint64_t pricebits; char destaddr[64]; uint32_t aveprice=0,timestamp,uprice; uint256 hashBlock; int64_t dist,mindist=(1LL<<60),prizefund = 0; int32_t mini=-1,i,n,vini,numvouts,iter; struct prices_bar refbar;
if ( (pindex= komodo_chainactive(height)) != 0 )
{
if ( komodo_blockload(block,pindex) == 0 )
{
n = block.vtx.size();
vini = 0;
memset(&refbar,0,sizeof(refbar));
for (iter=0; iter<2; iter++)
{
for (i=0; i<n; i++)
{
tx = block.vtx[i];
if ( myGetTransaction(tx.vin[vini].prevout.hash,vintx,hashBlock) == 0 )
continue;
else if ( tx.vin[vini].prevout.n >= vintx.vout.size() || Getscriptaddress(destaddr,vintx.vout[tx.vin[vini].prevout.n].scriptPubKey) == 0 )
continue;
else if ( (numvouts= tx.vout.size()) > 1 && tx.vout[numvouts-1].scriptPubKey[0] == 0x6a )
{
GetOpReturnData(tx.vout[numvouts-1].scriptPubKey,vopret);
if ( vopret.size() == 8 )
{
E_UNMARSHAL(vopret,ss >> pricebits);
timestamp = (uint32_t)(pricebits >> 32);
uprice = (uint32_t)pricebits;
if ( iter == 0 )
{
prizefund += tx.vout[0].nValue;
if ( strcmp(acaddr,destaddr) == 0 )
{
//fprintf(stderr,"REF ");
prices_barupdate(&refbar,pricebits);
}
}
else if ( strcmp(acaddr,destaddr) != 0 )
{
dist = prices_bardist(&refbar,aveprice,pricebits);
if ( dist < mindist )
{
mindist = dist;
mini = i;
}
fprintf(stderr,"mini.%d i.%d %.8f t%u %.4f v.%d %s lag.%d i.%d dist.%lld\n",mini,i,(double)tx.vout[0].nValue/COIN,timestamp,(double)uprice/10000,numvouts,destaddr,(int32_t)(pindex->nTime-timestamp),iter,(long long)dist);
}
} else return(-3);
}
}
if ( iter == 0 )
{
prices_bardisp(&refbar);
if ( refbar.num != 0 )
aveprice = (uint32_t)refbar.sum / refbar.num;
}
}
return(prizefund);
} else return(-2);
} else return(-1);
}
UniValue games_settle(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
UniValue result(UniValue::VOBJ); char acaddr[64]; CPubKey acpk,mypk,gamespk; int64_t prizefund = 0; int32_t height,nextheight = komodo_nextheight();
if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] == 0 )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error"," no -ac_pubkey for price reference"));
return(result);
}
mypk = pubkey2pk(Mypubkey());
gamespk = GetUnspendable(cp,0);
acpk = buf2pk(ASSETCHAINS_OVERRIDE_PUBKEY33);
Getscriptaddress(acaddr,CScript() << ParseHex(HexStr(acpk)) << OP_CHECKSIG);
if ( params != 0 && cJSON_GetArraySize(params) == 1 )
{
height = juint(jitem(params,0),0);
result.push_back(Pair("height",(int64_t)height));
if ( (prizefund= prices_blockinfo(height,acaddr)) < 0 )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("errorcode",prizefund));
result.push_back(Pair("error","blockinfo error"));
}
else
{
// display bets
if ( height <= nextheight-PRICES_BETPERIOD )
{
// settle bets by first nonzero reference bar
}
result.push_back(Pair("prizefund",ValueFromAmount(prizefund)));
result.push_back(Pair("result","success"));
}
}
else
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","couldnt parse"));
}
return(result);
}
UniValue games_bet(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
UniValue result(UniValue::VOBJ); std::string rawtx; int64_t amount,inputsum; uint64_t price; CPubKey gamespk,mypk,acpk;
if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] == 0 )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error"," no -ac_pubkey for price reference"));
return(result);
}
mypk = pubkey2pk(Mypubkey());
gamespk = GetUnspendable(cp,0);
acpk = buf2pk(ASSETCHAINS_OVERRIDE_PUBKEY33);
if ( params != 0 && cJSON_GetArraySize(params) == 2 )
{
amount = jdouble(jitem(params,0),0) * COIN + 0.0000000049;
if ( cclib_parsehash((uint8_t *)&price,jitem(params,1),8) < 0 )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","couldnt parsehash"));
return(result);
}
if ( mypk == acpk )
{
amount = 0; // i am the reference price feed
//fprintf(stderr,"i am the reference\n");
}
//fprintf(stderr,"amount %llu price %llx\n",(long long)amount,(long long)price);
if ( (inputsum= AddNormalinputs(mtx,mypk,amount+GAMES_TXFEE,64)) >= amount+GAMES_TXFEE )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,gamespk));
rawtx = FinalizeCCTx(0,cp,mtx,mypk,GAMES_TXFEE,CScript() << OP_RETURN << price);
return(games_rawtxresult(result,rawtx,1));
}
else
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","not enough funds"));
}
}
else
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","couldnt parse"));
}
return(result);
}
void prices_update(uint32_t timestamp,uint32_t uprice,int32_t ismine)
{
//fprintf(stderr,"%s t%u %.4f %16llx\n",ismine!=0?"mine":"ext ",timestamp,(double)uprice/10000,(long long)((uint64_t)timestamp<<32) | uprice);
}
// game specific code for daemon
void games_packitemstr(char *packitemstr,struct games_packitem *item)
{
strcpy(packitemstr,"");
}
int64_t games_cashout(struct games_player *P)
{
int32_t dungeonlevel = P->dungeonlevel; int64_t mult=1000,cashout = 0;
cashout = (uint64_t)P->gold * mult * dungeonlevel * dungeonlevel;
return(cashout);
}
void pricesplayerjson(UniValue &obj,struct games_player *P)
{
obj.push_back(Pair("packsize",(int64_t)P->packsize));
obj.push_back(Pair("hitpoints",(int64_t)P->hitpoints));
obj.push_back(Pair("strength",(int64_t)(P->strength&0xffff)));
obj.push_back(Pair("maxstrength",(int64_t)(P->strength>>16)));
obj.push_back(Pair("level",(int64_t)P->level));
obj.push_back(Pair("experience",(int64_t)P->experience));
obj.push_back(Pair("dungeonlevel",(int64_t)P->dungeonlevel));
}
int32_t disp_gamesplayer(char *str,struct games_player *P)
{
str[0] = 0;
//if ( P->gold <= 0 )//|| P->hitpoints <= 0 || (P->strength&0xffff) <= 0 || P->level <= 0 || P->experience <= 0 || P->dungeonlevel <= 0 )
// return(-1);
sprintf(str," <- playerdata: gold.%d hp.%d strength.%d/%d level.%d exp.%d dl.%d",P->gold,P->hitpoints,P->strength&0xffff,P->strength>>16,P->level,P->experience,P->dungeonlevel);
return(0);
}
int32_t games_payloadrecv(CPubKey pk,uint32_t timestamp,std::vector<uint8_t> payload)
{
uint256 gametxid; int32_t i,len; char str[67]; int64_t price; uint32_t eventid = 0;
if ( (len= payload.size()) > 36 )
{
len -= 36;
for (i=0; i<32; i++)
((uint8_t *)&gametxid)[i] = payload[len+i];
eventid = (uint32_t)payload[len+32];
eventid |= (uint32_t)payload[len+33] << 8;
eventid |= (uint32_t)payload[len+34] << 16;
eventid |= (uint32_t)payload[len+35] << 24;
for (i=0; i<len&&i<sizeof(price); i++)
((uint8_t *)&price)[7-i] = payload[i];
prices_update((uint32_t)(price >> 32),(uint32_t)(price & 0xffffffff),pk == pubkey2pk(Mypubkey()));
//fprintf(stderr,"%llu -> t%u %.4f ",(long long)price,(uint32_t)(price >> 32),(double)(price & 0xffffffff)/10000);
//fprintf(stderr," got payload, from %s %s/e%d\n",pubkey33_str(str,(uint8_t *)&pk),gametxid.GetHex().c_str(),eventid);
return(0);
} else return(-1);
}
bool games_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx)
{
return(true);
}

208
src/cc/games/prices.h Normal file
View File

@@ -0,0 +1,208 @@
#ifndef H_PRICES_H
#define H_PRICES_H
/***************************************************************************/
/** https://github.com/brenns10/tetris
@file main.c
@author Stephen Brennan
@date Created Wednesday, 10 June 2015
@brief Main program for tetris.
@copyright Copyright (c) 2015, Stephen Brennan. Released under the Revised
BSD License. See LICENSE.txt for details.
*******************************************************************************/
/*
Convert a tetromino type to its corresponding cell.
*/
#define TYPE_TO_CELL(x) ((x)+1)
/*
Strings for how you would print a tetris board.
*/
#define TC_EMPTY_STR " "
#define TC_BLOCK_STR "\u2588"
/*
Questions about a tetris cell.
*/
#define TC_IS_EMPTY(x) ((x) == TC_EMPTY)
#define TC_IS_FILLED(x) (!TC_IS_EMPTY(x))
/*
How many cells in a tetromino?
*/
#define TETRIS 4
/*
How many tetrominos?
*/
#define NUM_TETROMINOS 7
/*
How many orientations of a tetromino?
*/
#define NUM_ORIENTATIONS 4
/*
Level constants.
*/
#define MAX_LEVEL 19
#define LINES_PER_LEVEL 10
/*
A "cell" is a 1x1 block within a tetris board.
*/
typedef enum {
TC_EMPTY, TC_CELLI, TC_CELLJ, TC_CELLL, TC_CELLO, TC_CELLS, TC_CELLT, TC_CELLZ
} tetris_cell;
/*
A "type" is a type/shape of a tetromino. Not including orientation.
*/
typedef enum {
TET_I, TET_J, TET_L, TET_O, TET_S, TET_T, TET_Z
} tetris_type;
/*
A row,column pair. Negative numbers allowed, because we need them for
offsets.
*/
typedef struct {
int row;
int col;
} tetris_location;
/*
A "block" is a struct that contains information about a tetromino.
Specifically, what type it is, what orientation it has, and where it is.
*/
typedef struct {
int typ;
int ori;
tetris_location loc;
} tetris_block;
/*
All possible moves to give as input to the game.
*/
typedef enum {
TM_LEFT, TM_RIGHT, TM_CLOCK, TM_COUNTER, TM_DROP, TM_HOLD, TM_NONE
} tetris_move;
/*
A game object!
*/
typedef struct {
/*
Game board stuff:
*/
int rows;
int cols;
/*
Scoring information:
*/
int points;
int level;
/*
Falling block is the one currently going down. Next block is the one that
will be falling after this one. Stored is the block that you can swap out.
*/
tetris_block falling;
tetris_block next;
tetris_block stored;
/*
Number of game ticks until the block will move down.
*/
int ticks_till_gravity;
/*
Number of lines until you advance to the next level.
*/
int lines_remaining;
char board[];
} tetris_game;
/*
This array stores all necessary information about the cells that are filled by
each tetromino. The first index is the type of the tetromino (i.e. shape,
e.g. I, J, Z, etc.). The next index is the orientation (0-3). The final
array contains 4 tetris_location objects, each mapping to an offset from a
point on the upper left that is the tetromino "origin".
*/
extern const tetris_location TETROMINOS[NUM_TETROMINOS][NUM_ORIENTATIONS][TETRIS];
/*
This array tells you how many ticks per gravity by level. Decreases as level
increases, to add difficulty.
*/
extern const int GRAVITY_LEVEL[MAX_LEVEL+1];
// Data structure manipulation.
void tg_init(tetris_game *obj, int rows, int cols);
tetris_game *tg_create(struct games_state *rs,int rows, int cols);
void tg_destroy(tetris_game *obj);
void tg_delete(tetris_game *obj);
tetris_game *tg_load(FILE *f);
void tg_save(tetris_game *obj, FILE *f);
// Public methods not related to memory:
char tg_get(tetris_game *obj, int row, int col);
bool tg_check(tetris_game *obj, int row, int col);
bool tg_tick(struct games_state *rs,tetris_game *obj, tetris_move move);
void tg_print(tetris_game *obj, FILE *f);
/******************************************************************************
* Copyright © 2014-2019 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. *
* *
******************************************************************************/
#define GAMENAME "prices" // name of executable
#define GAMEMAIN prices // main program of game
#define GAMEPLAYERJSON pricesplayerjson // displays game specific json
#define GAMEDATA pricesdata // extracts data from game specific variables into games_state
#define CHAINNAME "PRICES" // -ac_name=
typedef uint64_t gamesevent; // can be 8, 16, 32, or 64 bits
#define MAXPACK 23
struct games_packitem
{
int32_t type,launch,count,which,hplus,dplus,arm,flags,group;
char damage[8],hurldmg[8];
};
struct games_player
{
int32_t gold,hitpoints,strength,level,experience,packsize,dungeonlevel,amulet;
struct games_packitem gamespack[MAXPACK];
};
struct games_state
{
uint64_t seed,origseed;
char *keystrokeshex;
uint32_t needflush,replaydone;
int32_t numkeys,ind,num,guiflag,counter,sleeptime,playersize,restoring,lastnum;
FILE *logfp;
struct games_player P;
gamesevent buffered[5000],*keystrokes;
uint8_t playerdata[8192];
};
extern struct games_state globalR;
void *gamesiterate(struct games_state *rs);
int32_t flushkeystrokes(struct games_state *rs,int32_t waitflag);
void games_packitemstr(char *packitemstr,struct games_packitem *item);
uint64_t _games_rngnext(uint64_t initseed);
int32_t games_replay2(uint8_t *newdata,uint64_t seed,gamesevent *keystrokes,int32_t num,struct games_player *player,int32_t sleepmillis);
gamesevent games_revendian(gamesevent revx);
int32_t disp_gamesplayer(char *str,struct games_player *P);
#endif

904
src/cc/games/tetris.c Normal file
View File

@@ -0,0 +1,904 @@
#include "tetris.h"
/*
In order to port a game into gamesCC, the RNG needs to be seeded with the gametxid seed, also events needs to be broadcast using issue_games_events. Also the game engine needs to be daemonized, preferably by putting all globals into a single data structure.
also, the standalone game needs to support argv of seed gametxid, along with replay args
*/
int random_tetromino(struct games_state *rs)
{
rs->seed = _games_rngnext(rs->seed);
return(rs->seed % NUM_TETROMINOS);
}
int32_t tetrisdata(struct games_player *P,void *ptr)
{
tetris_game *tg = (tetris_game *)ptr;
P->gold = tg->points;
P->dungeonlevel = tg->level;
//fprintf(stderr,"score.%d level.%d\n",tg->points,tg->level);
return(0);
}
/***************************************************************************/
/** https://github.com/brenns10/tetris
@file main.c
@author Stephen Brennan
@date Created Wednesday, 10 June 2015
@brief Main program for tetris.
@copyright Copyright (c) 2015, Stephen Brennan. Released under the Revised
BSD License. See LICENSE.txt for details.
*******************************************************************************/
#include <stdio.h> // for FILE
#include <stdbool.h> // for bool
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#include <string.h>
#ifdef BUILD_GAMESCC
#include "../rogue/cursesd.h"
#else
#include <curses.h>
#endif
#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
/*******************************************************************************
Array Definitions
*******************************************************************************/
const tetris_location TETROMINOS[NUM_TETROMINOS][NUM_ORIENTATIONS][TETRIS] =
{
// I
{{{1, 0}, {1, 1}, {1, 2}, {1, 3}},
{{0, 2}, {1, 2}, {2, 2}, {3, 2}},
{{3, 0}, {3, 1}, {3, 2}, {3, 3}},
{{0, 1}, {1, 1}, {2, 1}, {3, 1}}},
// J
{{{0, 0}, {1, 0}, {1, 1}, {1, 2}},
{{0, 1}, {0, 2}, {1, 1}, {2, 1}},
{{1, 0}, {1, 1}, {1, 2}, {2, 2}},
{{0, 1}, {1, 1}, {2, 0}, {2, 1}}},
// L
{{{0, 2}, {1, 0}, {1, 1}, {1, 2}},
{{0, 1}, {1, 1}, {2, 1}, {2, 2}},
{{1, 0}, {1, 1}, {1, 2}, {2, 0}},
{{0, 0}, {0, 1}, {1, 1}, {2, 1}}},
// O
{{{0, 1}, {0, 2}, {1, 1}, {1, 2}},
{{0, 1}, {0, 2}, {1, 1}, {1, 2}},
{{0, 1}, {0, 2}, {1, 1}, {1, 2}},
{{0, 1}, {0, 2}, {1, 1}, {1, 2}}},
// S
{{{0, 1}, {0, 2}, {1, 0}, {1, 1}},
{{0, 1}, {1, 1}, {1, 2}, {2, 2}},
{{1, 1}, {1, 2}, {2, 0}, {2, 1}},
{{0, 0}, {1, 0}, {1, 1}, {2, 1}}},
// T
{{{0, 1}, {1, 0}, {1, 1}, {1, 2}},
{{0, 1}, {1, 1}, {1, 2}, {2, 1}},
{{1, 0}, {1, 1}, {1, 2}, {2, 1}},
{{0, 1}, {1, 0}, {1, 1}, {2, 1}}},
// Z
{{{0, 0}, {0, 1}, {1, 1}, {1, 2}},
{{0, 2}, {1, 1}, {1, 2}, {2, 1}},
{{1, 0}, {1, 1}, {2, 1}, {2, 2}},
{{0, 1}, {1, 0}, {1, 1}, {2, 0}}},
};
const int GRAVITY_LEVEL[MAX_LEVEL+1] = {
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
50, 48, 46, 44, 42, 40, 38, 36, 34, 32,
//10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
30, 28, 26, 24, 22, 20, 16, 12, 8, 4
};
/*******************************************************************************
Helper Functions for Blocks
*******************************************************************************/
void sleep_milli(int milliseconds)
{
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = milliseconds * 1000 * 1000;
nanosleep(&ts, NULL);
}
/*
Return the block at the given row and column.
*/
char tg_get(tetris_game *obj, int row, int column)
{
return obj->board[obj->cols * row + column];
}
/*
Set the block at the given row and column.
*/
static void tg_set(tetris_game *obj, int row, int column, char value)
{
obj->board[obj->cols * row + column] = value;
}
/*
Check whether a row and column are in bounds.
*/
bool tg_check(tetris_game *obj, int row, int col)
{
return 0 <= row && row < obj->rows && 0 <= col && col < obj->cols;
}
/*
Place a block onto the board.
*/
static void tg_put(tetris_game *obj, tetris_block block)
{
int i;
for (i = 0; i < TETRIS; i++) {
tetris_location cell = TETROMINOS[block.typ][block.ori][i];
tg_set(obj, block.loc.row + cell.row, block.loc.col + cell.col,
TYPE_TO_CELL(block.typ));
}
}
/*
Clear a block out of the board.
*/
static void tg_remove(tetris_game *obj, tetris_block block)
{
int i;
for (i = 0; i < TETRIS; i++) {
tetris_location cell = TETROMINOS[block.typ][block.ori][i];
tg_set(obj, block.loc.row + cell.row, block.loc.col + cell.col, TC_EMPTY);
}
}
/*
Check if a block can be placed on the board.
*/
static bool tg_fits(tetris_game *obj, tetris_block block)
{
int i, r, c;
for (i = 0; i < TETRIS; i++) {
tetris_location cell = TETROMINOS[block.typ][block.ori][i];
r = block.loc.row + cell.row;
c = block.loc.col + cell.col;
if (!tg_check(obj, r, c) || TC_IS_FILLED(tg_get(obj, r, c))) {
return false;
}
}
return true;
}
/*
Create a new falling block and populate the next falling block with a random
one.
*/
static void tg_new_falling(struct games_state *rs,tetris_game *obj)
{
// Put in a new falling tetromino.
obj->falling = obj->next;
obj->next.typ = random_tetromino(rs);
obj->next.ori = 0;
obj->next.loc.row = 0;
obj->next.loc.col = obj->cols/2 - 2;
}
/*******************************************************************************
Game Turn Helpers
*******************************************************************************/
/*
Tick gravity, and move the block down if gravity should act.
*/
static void tg_do_gravity_tick(struct games_state *rs,tetris_game *obj)
{
obj->ticks_till_gravity--;
if (obj->ticks_till_gravity <= 0) {
tg_remove(obj, obj->falling);
obj->falling.loc.row++;
if (tg_fits(obj, obj->falling)) {
obj->ticks_till_gravity = GRAVITY_LEVEL[obj->level];
} else {
obj->falling.loc.row--;
tg_put(obj, obj->falling);
tg_new_falling(rs,obj);
}
tg_put(obj, obj->falling);
}
}
/*
Move the falling tetris block left (-1) or right (+1).
*/
static void tg_move(tetris_game *obj, int direction)
{
tg_remove(obj, obj->falling);
obj->falling.loc.col += direction;
if (!tg_fits(obj, obj->falling)) {
obj->falling.loc.col -= direction;
}
tg_put(obj, obj->falling);
}
/*
Send the falling tetris block to the bottom.
*/
static void tg_down(struct games_state *rs,tetris_game *obj)
{
tg_remove(obj, obj->falling);
while (tg_fits(obj, obj->falling)) {
obj->falling.loc.row++;
}
obj->falling.loc.row--;
tg_put(obj, obj->falling);
tg_new_falling(rs,obj);
}
/*
Rotate the falling block in either direction (+/-1).
*/
static void tg_rotate(tetris_game *obj, int direction)
{
tg_remove(obj, obj->falling);
while (true) {
obj->falling.ori = (obj->falling.ori + direction) % NUM_ORIENTATIONS;
// If the new orientation fits, we're done.
if (tg_fits(obj, obj->falling))
break;
// Otherwise, try moving left to make it fit.
obj->falling.loc.col--;
if (tg_fits(obj, obj->falling))
break;
// Finally, try moving right to make it fit.
obj->falling.loc.col += 2;
if (tg_fits(obj, obj->falling))
break;
// Put it back in its original location and try the next orientation.
obj->falling.loc.col--;
// Worst case, we come back to the original orientation and it fits, so this
// loop will terminate.
}
tg_put(obj, obj->falling);
}
/*
Swap the falling block with the block in the hold buffer.
*/
static void tg_hold(struct games_state *rs,tetris_game *obj)
{
tg_remove(obj, obj->falling);
if (obj->stored.typ == -1) {
obj->stored = obj->falling;
tg_new_falling(rs,obj);
} else {
int typ = obj->falling.typ, ori = obj->falling.ori;
obj->falling.typ = obj->stored.typ;
obj->falling.ori = obj->stored.ori;
obj->stored.typ = typ;
obj->stored.ori = ori;
while (!tg_fits(obj, obj->falling)) {
obj->falling.loc.row--;
if (tg_fits(obj, obj->falling)) {
break;
}
obj->falling.loc.col--;
if (tg_fits(obj, obj->falling)) {
break;
}
obj->falling.loc.col += 2;
}
}
tg_put(obj, obj->falling);
}
/*
Perform the action specified by the move.
*/
static void tg_handle_move(struct games_state *rs,tetris_game *obj, tetris_move move)
{
switch (move) {
case TM_LEFT:
//fprintf(stderr,"LEFT ");
tg_move(obj, -1);
break;
case TM_RIGHT:
//fprintf(stderr,"RIGHT ");
tg_move(obj, 1);
break;
case TM_DROP:
tg_down(rs,obj);
break;
case TM_CLOCK:
tg_rotate(obj, 1);
break;
case TM_COUNTER:
tg_rotate(obj, -1);
break;
case TM_HOLD:
tg_hold(rs,obj);
break;
default:
// pass
break;
}
}
/*
Return true if line i is full.
*/
static bool tg_line_full(tetris_game *obj, int i)
{
int j;
for (j = 0; j < obj->cols; j++) {
if (TC_IS_EMPTY(tg_get(obj, i, j)))
return false;
}
return true;
}
/*
Shift every row above r down one.
*/
static void tg_shift_lines(tetris_game *obj, int r)
{
int i, j;
for (i = r-1; i >= 0; i--) {
for (j = 0; j < obj->cols; j++) {
tg_set(obj, i+1, j, tg_get(obj, i, j));
tg_set(obj, i, j, TC_EMPTY);
}
}
}
/*
Find rows that are filled, remove them, shift, and return the number of
cleared rows.
*/
static int tg_check_lines(tetris_game *obj)
{
int i, nlines = 0;
tg_remove(obj, obj->falling); // don't want to mess up falling block
for (i = obj->rows-1; i >= 0; i--) {
if (tg_line_full(obj, i)) {
tg_shift_lines(obj, i);
i++; // do this line over again since they're shifted
nlines++;
}
}
tg_put(obj, obj->falling); // replace
return nlines;
}
/*
Adjust the score for the game, given how many lines were just cleared.
*/
static void tg_adjust_score(tetris_game *obj, int lines_cleared)
{
static int line_multiplier[] = {0, 40, 100, 300, 1200};
obj->points += line_multiplier[lines_cleared] * (obj->level + 1);
if (lines_cleared >= obj->lines_remaining) {
obj->level = MIN(MAX_LEVEL, obj->level + 1);
lines_cleared -= obj->lines_remaining;
obj->lines_remaining = LINES_PER_LEVEL - lines_cleared;
} else {
obj->lines_remaining -= lines_cleared;
}
}
/*
Return true if the game is over.
*/
static bool tg_game_over(tetris_game *obj)
{
int i, j;
bool over = false;
tg_remove(obj, obj->falling);
for (i = 0; i < 2; i++) {
for (j = 0; j < obj->cols; j++) {
if (TC_IS_FILLED(tg_get(obj, i, j))) {
over = true;
}
}
}
tg_put(obj, obj->falling);
return over;
}
/*******************************************************************************
Main Public Functions
*******************************************************************************/
/*
Do a single game tick: process gravity, user input, and score. Return true if
the game is still running, false if it is over.
*/
bool tg_tick(struct games_state *rs,tetris_game *obj, tetris_move move)
{
int lines_cleared;
// Handle gravity.
tg_do_gravity_tick(rs,obj);
// Handle input.
tg_handle_move(rs,obj, move);
// Check for cleared lines
lines_cleared = tg_check_lines(obj);
tg_adjust_score(obj, lines_cleared);
// Return whether the game will continue (NOT whether it's over)
return !tg_game_over(obj);
}
void tg_init(struct games_state *rs,tetris_game *obj, int rows, int cols)
{
// Initialization logic
obj->rows = rows;
obj->cols = cols;
//obj->board = (char *)malloc(rows * cols);
memset(obj->board, TC_EMPTY, rows * cols);
obj->points = 0;
obj->level = 0;
obj->ticks_till_gravity = GRAVITY_LEVEL[obj->level];
obj->lines_remaining = LINES_PER_LEVEL;
//srand(time(NULL));
tg_new_falling(rs,obj);
tg_new_falling(rs,obj);
obj->stored.typ = -1;
obj->stored.ori = 0;
obj->stored.loc.row = 0;
obj->next.loc.col = obj->cols/2 - 2;
//printf("%d", obj->falling.loc.col);
}
tetris_game *tg_create(struct games_state *rs,int rows, int cols)
{
tetris_game *obj = (tetris_game *)malloc(sizeof(tetris_game) + rows*cols);
tg_init(rs,obj, rows, cols);
return obj;
}
/*void tg_destroy(tetris_game *obj)
{
// Cleanup logic
free(obj->board);
}*/
void tg_delete(tetris_game *obj) {
//tg_destroy(obj);
free(obj);
}
/*
Load a game from a file.
tetris_game *tg_load(FILE *f)
{
tetris_game *obj = (tetris_game *)malloc(sizeof(tetris_game));
if (fread(obj, sizeof(tetris_game), 1, f) != 1 )
{
fprintf(stderr,"read game error\n");
free(obj);
obj = 0;
}
else
{
obj->board = (char *)malloc(obj->rows * obj->cols);
if (fread(obj->board, sizeof(char), obj->rows * obj->cols, f) != obj->rows * obj->cols )
{
fprintf(stderr,"fread error\n");
free(obj->board);
free(obj);
obj = 0;
}
}
return obj;
}*/
/*
Save a game to a file.
void tg_save(tetris_game *obj, FILE *f)
{
if (fwrite(obj, sizeof(tetris_game), 1, f) != 1 )
fprintf(stderr,"error writing tetrisgame\n");
else if (fwrite(obj->board, sizeof(char), obj->rows * obj->cols, f) != obj->rows * obj->cols )
fprintf(stderr,"error writing board\n");
}*/
/*
Print a game board to a file. Really just for early debugging.
*/
void tg_print(tetris_game *obj, FILE *f) {
int i, j;
for (i = 0; i < obj->rows; i++) {
for (j = 0; j < obj->cols; j++) {
if (TC_IS_EMPTY(tg_get(obj, i, j))) {
fputs(TC_EMPTY_STR, f);
} else {
fputs(TC_BLOCK_STR, f);
}
}
fputc('\n', f);
}
}
/*
2 columns per cell makes the game much nicer.
*/
#define COLS_PER_CELL 2
/*
Macro to print a cell of a specific type to a window.
*/
#define ADD_BLOCK(w,x) waddch((w),' '|A_REVERSE|COLOR_PAIR(x)); \
waddch((w),' '|A_REVERSE|COLOR_PAIR(x))
#define ADD_EMPTY(w) waddch((w), ' '); waddch((w), ' ')
/*
Print the tetris board onto the ncurses window.
*/
void display_board(WINDOW *w, tetris_game *obj)
{
int i, j;
box(w, 0, 0);
for (i = 0; i < obj->rows; i++) {
wmove(w, 1 + i, 1);
for (j = 0; j < obj->cols; j++) {
if (TC_IS_FILLED(tg_get(obj, i, j))) {
ADD_BLOCK(w,tg_get(obj, i, j));
} else {
ADD_EMPTY(w);
}
}
}
wnoutrefresh(w);
}
/*
Display a tetris piece in a dedicated window.
*/
void display_piece(WINDOW *w, tetris_block block)
{
int b;
tetris_location c;
wclear(w);
box(w, 0, 0);
if (block.typ == -1) {
wnoutrefresh(w);
return;
}
for (b = 0; b < TETRIS; b++) {
c = TETROMINOS[block.typ][block.ori][b];
wmove(w, c.row + 1, c.col * COLS_PER_CELL + 1);
ADD_BLOCK(w, TYPE_TO_CELL(block.typ));
}
wnoutrefresh(w);
}
/*
Display score information in a dedicated window.
*/
void display_score(WINDOW *w, tetris_game *tg)
{
wclear(w);
box(w, 0, 0);
wprintw(w, (char *)"Score\n%d\n", tg->points);
wprintw(w, (char *)"Level\n%d\n", tg->level);
wprintw(w, (char *)"Lines\n%d\n", tg->lines_remaining);
wnoutrefresh(w);
}
/*
Save and exit the game.
void save(tetris_game *game, WINDOW *w)
{
FILE *f;
wclear(w);
box(w, 0, 0); // return the border
wmove(w, 1, 1);
wprintw(w, (char *)"Save and exit? [Y/n] ");
wrefresh(w);
timeout(-1);
if (getch() == 'n') {
timeout(0);
return;
}
f = fopen("tetris.save", "w");
tg_save(game, f);
fclose(f);
tg_delete(game);
endwin();
fprintf(stderr,"Game saved to \"tetris.save\".\n");
fprintf(stderr,"Resume by passing the filename as an argument to this program.\n");
exit(EXIT_SUCCESS);
}*/
/*
Do the NCURSES initialization steps for color blocks.
*/
void init_colors(void)
{
start_color();
//init_color(COLOR_ORANGE, 1000, 647, 0);
init_pair(TC_CELLI, COLOR_CYAN, COLOR_BLACK);
init_pair(TC_CELLJ, COLOR_BLUE, COLOR_BLACK);
init_pair(TC_CELLL, COLOR_WHITE, COLOR_BLACK);
init_pair(TC_CELLO, COLOR_YELLOW, COLOR_BLACK);
init_pair(TC_CELLS, COLOR_GREEN, COLOR_BLACK);
init_pair(TC_CELLT, COLOR_MAGENTA, COLOR_BLACK);
init_pair(TC_CELLZ, COLOR_RED, COLOR_BLACK);
}
struct games_state globalR;
extern char Gametxidstr[];
int32_t issue_games_events(struct games_state *rs,char *gametxidstr,uint32_t eventid,gamesevent c);
gamesevent games_readevent(struct games_state *rs);
void *gamesiterate(struct games_state *rs)
{
uint32_t counter = 0; bool running = true; tetris_move move = TM_NONE;
gamesevent c; uint16_t skipcount=0; int32_t prevlevel; uint32_t eventid = 0; tetris_game *tg;
WINDOW *board, *next, *hold, *score;
if ( rs->guiflag != 0 || rs->sleeptime != 0 )
{
// NCURSES initialization:
initscr(); // initialize curses
cbreak(); // pass key presses to program, but not signals
noecho(); // don't echo key presses to screen
keypad(stdscr, TRUE); // allow arrow keys
timeout(0); // no blocking on getch()
curs_set(0); // set the cursor to invisible
init_colors(); // setup tetris colors
}
tg = tg_create(rs,22, 10);
prevlevel = tg->level;
// Create windows for each section of the interface.
board = newwin(tg->rows + 2, 2 * tg->cols + 2, 0, 0);
next = newwin(6, 10, 0, 2 * (tg->cols + 1) + 1);
hold = newwin(6, 10, 7, 2 * (tg->cols + 1) + 1);
score = newwin(6, 10, 14, 2 * (tg->cols + 1 ) + 1);
while ( running != 0 )
{
running = tg_tick(rs,tg,move);
if ( 1 && (rs->guiflag != 0 || rs->sleeptime != 0) )
{
display_board(board,tg);
display_piece(next,tg->next);
display_piece(hold,tg->stored);
display_score(score,tg);
}
if ( rs->guiflag != 0 )
{
#ifdef STANDALONE
sleep_milli(15);
if ( (counter++ % 10) == 0 )
doupdate();
c = games_readevent(rs);
if ( c <= 0x7f || skipcount == 0x3fff )
{
if ( skipcount > 0 )
issue_games_events(rs,Gametxidstr,eventid-skipcount,skipcount | 0x4000);
if ( c <= 0x7f )
issue_games_events(rs,Gametxidstr,eventid,c);
if ( tg->level != prevlevel )
{
flushkeystrokes(rs,0);
prevlevel = tg->level;
}
skipcount = 0;
} else skipcount++;
#endif
}
else
{
if ( rs->replaydone != 0 )
break;
if ( rs->sleeptime != 0 )
{
sleep_milli(1);
if ( (counter++ % 20) == 0 )
doupdate();
}
if ( skipcount == 0 )
{
c = games_readevent(rs);
//fprintf(stderr,"%04x score.%d level.%d\n",c,tg->points,tg->level);
if ( (c & 0x4000) == 0x4000 )
{
skipcount = (c & 0x3fff);
c = 'S';
}
}
if ( skipcount > 0 )
skipcount--;
}
eventid++;
switch ( c )
{
case 'h':
move = TM_LEFT;
break;
case 'l':
move = TM_RIGHT;
break;
case 'k':
move = TM_CLOCK;
break;
case 'j':
move = TM_DROP;
break;
case 'q':
running = false;
move = TM_NONE;
break;
/*case 'p':
wclear(board);
box(board, 0, 0);
wmove(board, tg->rows/2, (tg->cols*COLS_PER_CELL-6)/2);
wprintw(board, "PAUSED");
wrefresh(board);
timeout(-1);
getch();
timeout(0);
move = TM_NONE;
break;
case 's':
save(tg, board);
move = TM_NONE;
break;*/
case ' ':
move = TM_HOLD;
break;
default:
move = TM_NONE;
}
}
return(tg);
}
#ifdef STANDALONE
/*
Main tetris game!
*/
#include "dapps/dappstd.c"
char *clonestr(char *str)
{
char *clone; int32_t len;
if ( str == 0 || str[0] == 0 )
{
printf("warning cloning nullstr.%p\n",str);
#ifdef __APPLE__
while ( 1 ) sleep(1);
#endif
str = (char *)"<nullstr>";
}
len = strlen(str);
clone = (char *)calloc(1,len+16);
strcpy(clone,str);
return(clone);
}
int32_t issue_games_events(struct games_state *rs,char *gametxidstr,uint32_t eventid,gamesevent c)
{
static FILE *fp;
char params[512],*retstr; cJSON *retjson,*resobj; int32_t retval = -1;
if ( fp == 0 )
fp = fopen("events.log","wb");
rs->buffered[rs->num++] = c;
if ( 0 )
{
if ( sizeof(c) == 1 )
sprintf(params,"[\"events\",\"17\",\"[%%22%02x%%22,%%22%s%%22,%u]\"]",(uint8_t)c&0xff,gametxidstr,eventid);
else if ( sizeof(c) == 2 )
sprintf(params,"[\"events\",\"17\",\"[%%22%04x%%22,%%22%s%%22,%u]\"]",(uint16_t)c&0xffff,gametxidstr,eventid);
else if ( sizeof(c) == 4 )
sprintf(params,"[\"events\",\"17\",\"[%%22%08x%%22,%%22%s%%22,%u]\"]",(uint32_t)c&0xffffffff,gametxidstr,eventid);
else if ( sizeof(c) == 8 )
sprintf(params,"[\"events\",\"17\",\"[%%22%016llx%%22,%%22%s%%22,%u]\"]",(long long)c,gametxidstr,eventid);
if ( (retstr= komodo_issuemethod(USERPASS,(char *)"cclib",params,GAMES_PORT)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (resobj= jobj(retjson,(char *)"result")) != 0 )
{
retval = 0;
if ( fp != 0 )
{
fprintf(fp,"%s\n",jprint(resobj,0));
fflush(fp);
}
}
free_json(retjson);
} else fprintf(fp,"error parsing %s\n",retstr);
free(retstr);
} else fprintf(fp,"error issuing method %s\n",params);
return(retval);
} else return(0);
}
int tetris(int argc, char **argv)
{
struct games_state *rs = &globalR;
int32_t c,skipcount=0; uint32_t eventid = 0; tetris_game *tg = 0;
memset(rs,0,sizeof(*rs));
rs->guiflag = 1;
rs->sleeptime = 1; // non-zero to allow refresh()
if ( argc >= 2 && strlen(argv[2]) == 64 )
{
#ifdef _WIN32
#ifdef _MSC_VER
rs->origseed = _strtoui64(argv[1], NULL, 10);
#else
rs->origseed = atol(argv[1]); // windows, but not MSVC
#endif // _MSC_VER
#else
rs->origseed = atol(argv[1]); // non-windows
#endif // _WIN32
rs->seed = rs->origseed;
if ( argc >= 3 )
{
strcpy(Gametxidstr,argv[2]);
fprintf(stderr,"setplayerdata %s\n",Gametxidstr);
if ( games_setplayerdata(rs,Gametxidstr) < 0 )
{
fprintf(stderr,"invalid gametxid, or already started\n");
return(-1);
}
}
} else rs->seed = 777;
/* Load file if given a filename.
if (argc >= 2) {
FILE *f = fopen(argv[1], "r");
if (f == NULL) {
perror("tetris");
exit(EXIT_FAILURE);
}
tg = tg_load(f);
fclose(f);
} else {
// Otherwise create new game.
tg = tg_create(rs,22, 10);
}*/
// Game loop
tg = (tetris_game *)gamesiterate(rs);
gamesbailout(rs);
// Deinitialize NCurses
wclear(stdscr);
endwin();
// Output ending message.
printf("Game over!\n");
printf("You finished with %d points on level %d.\n", tg->points, tg->level);
// Deinitialize Tetris
tg_delete(tg);
return 0;
}
#endif

87
src/cc/games/tetris.cpp Normal file
View File

@@ -0,0 +1,87 @@
/******************************************************************************
* Copyright © 2014-2019 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. *
* *
******************************************************************************/
std::string MYCCLIBNAME = (char *)"gamescc";
// game specific code for daemon
void games_packitemstr(char *packitemstr,struct games_packitem *item)
{
strcpy(packitemstr,"");
}
int64_t games_cashout(struct games_player *P)
{
int32_t dungeonlevel = P->dungeonlevel; int64_t mult=10000,cashout = 0;
cashout = (uint64_t)P->gold * mult;
return(cashout);
}
void tetrisplayerjson(UniValue &obj,struct games_player *P)
{
obj.push_back(Pair("packsize",(int64_t)P->packsize));
obj.push_back(Pair("hitpoints",(int64_t)P->hitpoints));
obj.push_back(Pair("strength",(int64_t)(P->strength&0xffff)));
obj.push_back(Pair("maxstrength",(int64_t)(P->strength>>16)));
obj.push_back(Pair("level",(int64_t)P->level));
obj.push_back(Pair("experience",(int64_t)P->experience));
obj.push_back(Pair("dungeonlevel",(int64_t)P->dungeonlevel));
}
int32_t disp_gamesplayer(char *str,struct games_player *P)
{
str[0] = 0;
//if ( P->gold <= 0 )//|| P->hitpoints <= 0 || (P->strength&0xffff) <= 0 || P->level <= 0 || P->experience <= 0 || P->dungeonlevel <= 0 )
// return(-1);
sprintf(str," <- playerdata: gold.%d hp.%d strength.%d/%d level.%d exp.%d dl.%d",P->gold,P->hitpoints,P->strength&0xffff,P->strength>>16,P->level,P->experience,P->dungeonlevel);
return(0);
}
int32_t games_payloadrecv(CPubKey pk,uint32_t timestamp,std::vector<uint8_t> payload)
{
uint256 gametxid; int32_t i,len; char str[67]; uint32_t eventid = 0;
if ( (len= payload.size()) > 36 )
{
len -= 36;
for (i=0; i<32; i++)
((uint8_t *)&gametxid)[i] = payload[len+i];
eventid = (uint32_t)payload[len+32];
eventid |= (uint32_t)payload[len+33] << 8;
eventid |= (uint32_t)payload[len+34] << 16;
eventid |= (uint32_t)payload[len+35] << 24;
//for (i=0; i<len; i++)
// fprintf(stderr,"%02x",payload[i]);
//fprintf(stderr," got payload, from %s %s/e%d\n",pubkey33_str(str,(uint8_t *)&pk),gametxid.GetHex().c_str(),eventid);
return(0);
} else return(-1);
}
UniValue games_bet(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
UniValue result;
return(result);
}
UniValue games_settle(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
UniValue result;
return(result);
}
bool games_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx)
{
return(true);
}

208
src/cc/games/tetris.h Normal file
View File

@@ -0,0 +1,208 @@
#ifndef H_TETRIS_H
#define H_TETRIS_H
/***************************************************************************/
/** https://github.com/brenns10/tetris
@file main.c
@author Stephen Brennan
@date Created Wednesday, 10 June 2015
@brief Main program for tetris.
@copyright Copyright (c) 2015, Stephen Brennan. Released under the Revised
BSD License. See LICENSE.txt for details.
*******************************************************************************/
/*
Convert a tetromino type to its corresponding cell.
*/
#define TYPE_TO_CELL(x) ((x)+1)
/*
Strings for how you would print a tetris board.
*/
#define TC_EMPTY_STR " "
#define TC_BLOCK_STR "\u2588"
/*
Questions about a tetris cell.
*/
#define TC_IS_EMPTY(x) ((x) == TC_EMPTY)
#define TC_IS_FILLED(x) (!TC_IS_EMPTY(x))
/*
How many cells in a tetromino?
*/
#define TETRIS 4
/*
How many tetrominos?
*/
#define NUM_TETROMINOS 7
/*
How many orientations of a tetromino?
*/
#define NUM_ORIENTATIONS 4
/*
Level constants.
*/
#define MAX_LEVEL 19
#define LINES_PER_LEVEL 10
/*
A "cell" is a 1x1 block within a tetris board.
*/
typedef enum {
TC_EMPTY, TC_CELLI, TC_CELLJ, TC_CELLL, TC_CELLO, TC_CELLS, TC_CELLT, TC_CELLZ
} tetris_cell;
/*
A "type" is a type/shape of a tetromino. Not including orientation.
*/
typedef enum {
TET_I, TET_J, TET_L, TET_O, TET_S, TET_T, TET_Z
} tetris_type;
/*
A row,column pair. Negative numbers allowed, because we need them for
offsets.
*/
typedef struct {
int row;
int col;
} tetris_location;
/*
A "block" is a struct that contains information about a tetromino.
Specifically, what type it is, what orientation it has, and where it is.
*/
typedef struct {
int typ;
int ori;
tetris_location loc;
} tetris_block;
/*
All possible moves to give as input to the game.
*/
typedef enum {
TM_LEFT, TM_RIGHT, TM_CLOCK, TM_COUNTER, TM_DROP, TM_HOLD, TM_NONE
} tetris_move;
/*
A game object!
*/
typedef struct {
/*
Game board stuff:
*/
int rows;
int cols;
/*
Scoring information:
*/
int points;
int level;
/*
Falling block is the one currently going down. Next block is the one that
will be falling after this one. Stored is the block that you can swap out.
*/
tetris_block falling;
tetris_block next;
tetris_block stored;
/*
Number of game ticks until the block will move down.
*/
int ticks_till_gravity;
/*
Number of lines until you advance to the next level.
*/
int lines_remaining;
char board[];
} tetris_game;
/*
This array stores all necessary information about the cells that are filled by
each tetromino. The first index is the type of the tetromino (i.e. shape,
e.g. I, J, Z, etc.). The next index is the orientation (0-3). The final
array contains 4 tetris_location objects, each mapping to an offset from a
point on the upper left that is the tetromino "origin".
*/
extern const tetris_location TETROMINOS[NUM_TETROMINOS][NUM_ORIENTATIONS][TETRIS];
/*
This array tells you how many ticks per gravity by level. Decreases as level
increases, to add difficulty.
*/
extern const int GRAVITY_LEVEL[MAX_LEVEL+1];
// Data structure manipulation.
void tg_init(tetris_game *obj, int rows, int cols);
tetris_game *tg_create(struct games_state *rs,int rows, int cols);
void tg_destroy(tetris_game *obj);
void tg_delete(tetris_game *obj);
tetris_game *tg_load(FILE *f);
void tg_save(tetris_game *obj, FILE *f);
// Public methods not related to memory:
char tg_get(tetris_game *obj, int row, int col);
bool tg_check(tetris_game *obj, int row, int col);
bool tg_tick(struct games_state *rs,tetris_game *obj, tetris_move move);
void tg_print(tetris_game *obj, FILE *f);
/******************************************************************************
* Copyright © 2014-2019 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. *
* *
******************************************************************************/
#define GAMENAME "tetris" // name of executable
#define GAMEMAIN tetris // main program of game
#define GAMEPLAYERJSON tetrisplayerjson // displays game specific json
#define GAMEDATA tetrisdata // extracts data from game specific variables into games_state
#define CHAINNAME "GTEST" // -ac_name=
typedef uint16_t gamesevent; // can be 8, 16, 32, or 64 bits
#define MAXPACK 23
struct games_packitem
{
int32_t type,launch,count,which,hplus,dplus,arm,flags,group;
char damage[8],hurldmg[8];
};
struct games_player
{
int32_t gold,hitpoints,strength,level,experience,packsize,dungeonlevel,amulet;
struct games_packitem gamespack[MAXPACK];
};
struct games_state
{
uint64_t seed,origseed;
char *keystrokeshex;
uint32_t needflush,replaydone;
int32_t numkeys,ind,num,guiflag,counter,sleeptime,playersize,restoring,lastnum;
FILE *logfp;
struct games_player P;
gamesevent buffered[5000],*keystrokes;
uint8_t playerdata[8192];
};
extern struct games_state globalR;
void *gamesiterate(struct games_state *rs);
int32_t flushkeystrokes(struct games_state *rs,int32_t waitflag);
void games_packitemstr(char *packitemstr,struct games_packitem *item);
uint64_t _games_rngnext(uint64_t initseed);
int32_t games_replay2(uint8_t *newdata,uint64_t seed,gamesevent *keystrokes,int32_t num,struct games_player *player,int32_t sleepmillis);
gamesevent games_revendian(gamesevent revx);
int32_t disp_gamesplayer(char *str,struct games_player *P);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,9 @@
#include <stdint.h>
#include <stdio.h>
#define GAMES_RNGMULT 11109
#define GAMES_RNGOFFSET 13849
#define GAMES_MAXRNGS 10000
#ifndef STANDALONE
@@ -12,7 +15,6 @@ extern CWallet* pwalletMain;
#include "CCinclude.h"
#include "secp256k1.h"
std::string MYCCLIBNAME = (char *)"gamescc";
#define EVAL_GAMES (EVAL_FAUCET2+1)
#define GAMES_TXFEE 10000
@@ -20,20 +22,17 @@ std::string MYCCLIBNAME = (char *)"gamescc";
#define GAMES_MAXKEYSTROKESGAP 60
#define GAMES_MAXPLAYERS 64
#define GAMES_REGISTRATIONSIZE (100 * 10000)
#define GAMES_REGISTRATION 5
#define GAMES_REGISTRATION 1
#define GAMES_RNGMULT 11109
#define GAMES_RNGOFFSET 13849
#define GAMES_MAXRNGS 10000
#define MYCCNAME "games"
std::string Games_pname;
#define GAMENAME "sudoku"
#define RPC_FUNCS \
{ (char *)MYCCNAME, (char *)"rng", (char *)"hash,playerid", 1, 2, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"rngnext", (char *)"seed", 1, 1, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"fund", (char *)"amount", 1, 1, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"players", (char *)"no params", 0, 0, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"games", (char *)"no params", 0, 0, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"pending", (char *)"no params", 0, 0, ' ', EVAL_GAMES }, \
@@ -42,14 +41,18 @@ std::string Games_pname;
{ (char *)MYCCNAME, (char *)"playerinfo", (char *)"playertxid", 1, 1, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"gameinfo", (char *)"gametxid", 1, 1, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"keystrokes", (char *)"txid,hexstr", 2, 2, 'K', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"finish", (char *)"gametxid", 1, 1, 'Q', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"bailout", (char *)"gametxid", 1, 1, 'Q', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"highlander", (char *)"gametxid", 1, 1, 'H', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"events", (char *)"eventshex [gametxid [eventid]]", 1, 3, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"extract", (char *)"gametxid [pubkey]", 1, 2, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"bet", (char *)"amount hexstr", 2, 2, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"settle", (char *)"height", 1, 1, ' ', EVAL_GAMES }, \
{ (char *)MYCCNAME, (char *)"register", (char *)"gametxid [playertxid]", 1, 2, 'R', EVAL_GAMES },
bool games_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx);
UniValue games_rng(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_rngnext(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_fund(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_players(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_games(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_pending(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
@@ -58,10 +61,13 @@ UniValue games_newgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_playerinfo(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_gameinfo(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_keystrokes(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_finish(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_bailout(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_highlander(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_events(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_extract(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_register(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_bet(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue games_settle(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
#define CUSTOM_DISPATCH \
if ( cp->evalcode == EVAL_GAMES ) \
@@ -92,45 +98,23 @@ if ( cp->evalcode == EVAL_GAMES ) \
return(games_keystrokes(txfee,cp,params)); \
else if ( strcmp(method,"extract") == 0 ) \
return(games_extract(txfee,cp,params)); \
else if ( strcmp(method,"finish") == 0 ) \
return(games_finish(txfee,cp,params)); \
else if ( strcmp(method,"bailout") == 0 ) \
return(games_bailout(txfee,cp,params)); \
else if ( strcmp(method,"highlander") == 0 ) \
return(games_highlander(txfee,cp,params)); \
else if ( strcmp(method,"fund") == 0 ) \
return(games_fund(txfee,cp,params)); \
else if ( strcmp(method,"bet") == 0 ) \
return(games_bet(txfee,cp,params)); \
else if ( strcmp(method,"settle") == 0 ) \
return(games_settle(txfee,cp,params)); \
else \
{ \
result.push_back(Pair("result","error")); \
result.push_back(Pair("error","invalid gamescc method")); \
result.push_back(Pair("method",method)); \
return(result); \
} \
}
#endif
#define MAXPACK 23
struct games_packitem
{
int32_t type,launch,count,which,hplus,dplus,arm,flags,group;
char damage[8],hurldmg[8];
};
struct games_player
{
int32_t gold,hitpoints,strength,level,experience,packsize,dungeonlevel,amulet;
struct games_packitem gamespack[MAXPACK];
};
struct games_state
{
uint64_t seed;
char *keystrokes,*keystrokeshex;
uint32_t needflush,replaydone;
int32_t numkeys,ind,num,guiflag,counter,sleeptime,playersize,restoring,lastnum;
FILE *logfp;
struct games_player P;
char buffered[10000];
uint8_t playerdata[10000];
};
int32_t games_replay2(uint8_t *newdata,uint64_t seed,char *keystrokes,int32_t num,struct games_player *player,int32_t sleepmillis);
void games_packitemstr(char *packitemstr,struct games_packitem *item);
#endif

View File

@@ -1,2 +1,19 @@
#!/bin/sh
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o ../libcc.so cclib.cpp
rm *.so rogue/rogue games/tetris games/prices
echo rogue
make -f Makefile_rogue
./makerogue
echo sudoku/musig/dilithium
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o sudokucc.so cclib.cpp
echo games tetris
./maketetris
echo games prices
./makeprices
echo customcc stub
gcc -O3 -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o customcc.so cclib.cpp

8
src/cc/makeprices Executable file
View File

@@ -0,0 +1,8 @@
echo pricescc.so
gcc -O3 -DBUILD_GAMESCC -DBUILD_PRICES -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o pricescc.so cclib.cpp
echo prices
cd games
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -DSTANDALONE -DBUILD_PRICES ../gamescc.cpp -lncurses -lcurl -o prices
cd ..

View File

@@ -1,2 +1,7 @@
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -DSTANDALONE gamescc.cpp -lncurses -lcurl -o tetris
echo gamescc.so with tetris
gcc -O3 -DBUILD_GAMESCC -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o gamescc.so cclib.cpp
echo tetris dapp
cd games
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -DSTANDALONE ../gamescc.cpp -lncurses -lcurl -o tetris
cd ..

View File

@@ -192,7 +192,9 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
if ( tmptx.vout.size() > 0 && DecodePaymentsOpRet(tmptx.vout[tmptx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,totalallocations,txidoprets) != 0 )
{
if ( lockedblocks < 0 || minrelease < 0 || totalallocations <= 0 || txidoprets.size() < 2 )
return(eval->Invalid("negative values"));
return(eval->Invalid("negative values"));
if ( !CheckTxFee(tx, PAYMENTS_TXFEE, chainActive.LastTip()->GetHeight(), chainActive.LastTip()->nTime) )
return eval->Invalid("txfee is too high");
Paymentspk = GetUnspendable(cp,0);
//fprintf(stderr, "lockedblocks.%i minrelease.%i totalallocations.%i txidopret1.%s txidopret2.%s\n",lockedblocks, minrelease, totalallocations, txidoprets[0].ToString().c_str(), txidoprets[1].ToString().c_str() );
@@ -281,7 +283,7 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
fprintf(stderr, "vin.%i is not a payments CC vout: txid.%s\n", i, txin.GetHash().ToString().c_str());
return(eval->Invalid("vin is not paymentsCC type"));
} //else fprintf(stderr, "vin.%i opret type txid.%s\n", i, txin.GetHash().ToString().c_str());
}
}
// check the chain depth vs locked blcoks requirement.
CBlockIndex* pblockindex = mapBlockIndex[blockhash];
if ( pblockindex->GetHeight() > ht-lockedblocks )

View File

@@ -451,4 +451,3 @@ std::string PricesFinish(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,
}

View File

@@ -197,9 +197,6 @@ bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t
uint256 txid,fundingtxid,hashBlock,vinfundingtxid; uint64_t vinsbits,sbits,APR,minseconds,maxseconds,mindeposit,amount,reward,txfee=10000; int32_t numvins,numvouts,preventCCvins,preventCCvouts,i; uint8_t funcid; CScript scriptPubKey; CTransaction fundingTx,vinTx;
numvins = tx.vin.size();
numvouts = tx.vout.size();
int64_t interest; uint64_t valuein;
CCoinsViewCache &view = *pcoinsTip;
valuein = view.GetValueIn(chainActive.LastTip()->GetHeight(),&interest,tx,chainActive.LastTip()->nTime);
preventCCvins = preventCCvouts = -1;
if ( numvouts < 1 )
return eval->Invalid("no vouts");
@@ -258,20 +255,22 @@ bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t
if ( (*cp->ismyvin)(tx.vin[i].scriptSig) == 0 )
return eval->Invalid("unexpected normal vin for unlock");
}
if ( valuein-tx.GetValueOut() > txfee )
if ( !CheckTxFee(tx, txfee, chainActive.LastTip()->GetHeight(), chainActive.LastTip()->nTime) )
return eval->Invalid("txfee is too high");
reward = RewardsCalc(amount,tx.vin[0].prevout.hash,APR,minseconds,maxseconds,mindeposit);
if ( numvins == 1 && tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 )
{
fprintf(stderr, "valueout.%li vs valuein.%li txfee.%li\n", tx.GetValueOut(), valuein, txfee);
return eval->Invalid("alright is stealing your money");
}
if ( numvouts == 2 && numvins == 1 )
{
if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() != 0 )
return eval->Invalid("unlock recover tx vout.0 is not normal output");
if ( reward == 0 )
return eval->Invalid("unlock recover no rewards");
else if ( tx.vout[1].nValue != 10000 )
return eval->Invalid("wrong marker vour value");
else if ( tx.vout[1].scriptPubKey != tx.vout[0].scriptPubKey )
return eval->Invalid("unlock recover tx vout.1 mismatched scriptPubKey");
else if ( tx.vout[0].scriptPubKey != vinTx.vout[1].scriptPubKey )
return eval->Invalid("unlock recover tx vout.0 mismatched scriptPubKey");
else if ( tx.vout[0].nValue > vinTx.vout[0].nValue )
return eval->Invalid("unlock recover tx vout.0 mismatched amounts");
else if ( tx.vout[1].nValue > 0 )
else if ( tx.vout[2].nValue > 0 )
return eval->Invalid("unlock recover tx vout.1 nonz amount");
else return(true);
}
@@ -689,8 +688,7 @@ std::string RewardsUnlock(uint64_t txfee,char *planstr,uint256 fundingtxid,uint2
}
else
{
firstmtx.vout.push_back(CTxOut(amount-txfee,scriptPubKey));
//CCerror = "cant find enough rewards inputs";
firstmtx.vout.push_back(CTxOut(amount-txfee*2,scriptPubKey));
fprintf(stderr,"not enough rewards funds to payout %.8f, recover mode tx\n",(double)(reward+txfee)/COIN);
return(FinalizeCCTx(-1LL,cp,firstmtx,mypk,txfee,EncodeRewardsOpRet('U',sbits,fundingtxid)));
}

View File

@@ -16,6 +16,13 @@
#ifndef H_CURSESD_H
#define H_CURSESD_H
#define KEY_OFFSET 0x100
#define KEY_DOWN (KEY_OFFSET + 0x02) /* Down arrow key */
#define KEY_UP (KEY_OFFSET + 0x03) /* Up arrow key */
#define KEY_LEFT (KEY_OFFSET + 0x04) /* Left arrow key */
#define KEY_RIGHT (KEY_OFFSET + 0x05) /* Right arrow key */
#define COLOR_BLACK 0
#ifdef PDC_RGB /* RGB */
@@ -168,6 +175,8 @@ char *unctrl(char c);
#define leaveok(win,bf) 0
#define halfdelay(x) 0
#define nocbreak() 0
#define cbreak() 0
#define curs_set(x) 0
// for tetris
#define init_pair(a,b,c) 0

View File

@@ -283,6 +283,24 @@ int32_t rogue_iamregistered(int32_t maxplayers,uint256 gametxid,CTransaction tx,
return(0);
}
int64_t rogue_buyins(uint256 gametxid,int32_t maxplayers)
{
int32_t i,vout; uint256 spenttxid,hashBlock; CTransaction spenttx; int64_t buyins = 0;
for (i=0; i<maxplayers; i++)
{
vout = i+1;
if ( myIsutxo_spent(spenttxid,gametxid,vout) >= 0 )
{
if ( myGetTransaction(spenttxid,spenttx,hashBlock) != 0 && spenttx.vout.size() > 0 )
{
if ( spenttx.vout[0].nValue > ROGUE_REGISTRATIONSIZE )
buyins += (spenttx.vout[0].nValue - ROGUE_REGISTRATIONSIZE);
} //else fprintf(stderr,"cant find spenttxid.%s\n",spenttxid.GetHex().c_str());
} //else fprintf(stderr,"vout %d is unspent\n",vout);
}
return(buyins);
}
int32_t rogue_isvalidgame(struct CCcontract_info *cp,int32_t &gameheight,CTransaction &tx,int64_t &buyin,int32_t &maxplayers,uint256 txid,int32_t unspentv0)
{
uint256 hashBlock; int32_t i,numvouts; char coinaddr[64]; CPubKey roguepk; uint64_t txfee = 10000;
@@ -690,6 +708,7 @@ uint64_t rogue_gamefields(UniValue &obj,int64_t maxplayers,int64_t buyin,uint256
obj.push_back(Pair("alive",rogue_playersalive(openslots,numplayers,gametxid,maxplayers,ht,tx)));
obj.push_back(Pair("openslots",openslots));
obj.push_back(Pair("numplayers",numplayers));
obj.push_back(Pair("buyins",ValueFromAmount(rogue_buyins(gametxid,maxplayers))));
}
obj.push_back(Pair("maxplayers",maxplayers));
obj.push_back(Pair("buyin",ValueFromAmount(buyin)));
@@ -1093,6 +1112,20 @@ UniValue rogue_extract(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
return(result);
}
int64_t rogue_cashout(struct rogue_player *P)
{
int32_t dungeonlevel; int64_t cashout,mult = 10;
if ( P->amulet != 0 )
mult *= 5;
dungeonlevel = P->dungeonlevel;
if ( P->amulet != 0 && dungeonlevel < 26 )
dungeonlevel = 26;
if ( dungeonlevel > 42 )
dungeonlevel = 42;
cashout = (uint64_t)P->gold * P->gold * mult * dungeonlevel;
return(cashout);
}
int32_t rogue_playerdata_validate(int64_t *cashoutp,uint256 &playertxid,struct CCcontract_info *cp,std::vector<uint8_t> playerdata,uint256 gametxid,CPubKey pk)
{
static uint32_t good,bad; static uint256 prevgame;
@@ -1105,17 +1138,9 @@ int32_t rogue_playerdata_validate(int64_t *cashoutp,uint256 &playertxid,struct C
free(keystrokes);
sprintf(fname,"rogue.%llu.pack",(long long)seed);
remove(fname);
for (i=0; i<newdata.size(); i++)
((uint8_t *)&P)[i] = newdata[i];
if ( P.amulet != 0 )
mult *= 5;
dungeonlevel = P.dungeonlevel;
if ( P.amulet != 0 && dungeonlevel < 26 )
dungeonlevel = 26;
if ( dungeonlevel > 42 )
dungeonlevel = 42;
*cashoutp = (uint64_t)P.gold * P.gold * mult * dungeonlevel;
*cashoutp = rogue_cashout(&P);
if ( newdata == playerdata )
{
if ( gametxid != prevgame )
@@ -1206,16 +1231,10 @@ UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
result.push_back(Pair("name","rogue"));
result.push_back(Pair("method",method));
result.push_back(Pair("myrogueaddr",myrogueaddr));
mult = 10; //100000;
if ( strcmp(method,"bailout") == 0 )
{
funcid = 'Q';
mult = 10; //100000;
}
else
{
funcid = 'H';
mult = 20; //200000;
}
else funcid = 'H';
if ( params != 0 && (n= cJSON_GetArraySize(params)) > 0 )
{
if ( n > 0 )
@@ -1264,13 +1283,10 @@ UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
cpTokens = CCinit(&tokensC, EVAL_TOKENS);
mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, txfee, GetUnspendable(cpTokens,NULL))); // marker to token cc addr, burnable and validated
mtx.vout.push_back(MakeTokensCC1vout(cp->evalcode,1,mypk));
if ( P.amulet != 0 )
mult *= 5;
dungeonlevel = P.dungeonlevel;
if ( P.amulet != 0 && dungeonlevel < 26 )
dungeonlevel = 26;
cashout = (uint64_t)P.gold * P.gold * mult * dungeonlevel;
cashout = rogue_cashout(&P);
fprintf(stderr,"\nextracted $$$gold.%d -> %.8f ROGUE hp.%d strength.%d/%d level.%d exp.%d dl.%d n.%d amulet.%d\n",P.gold,(double)cashout/COIN,P.hitpoints,P.strength&0xffff,P.strength>>16,P.level,P.experience,P.dungeonlevel,n,P.amulet);
if ( komodo_nextheight() > 77777 && cashout > ROGUE_MAXCASHOUT )
cashout = ROGUE_MAXCASHOUT;
if ( funcid == 'H' && maxplayers > 1 )
{
if ( P.amulet == 0 )
@@ -1280,12 +1296,11 @@ UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
else if ( rogue_playersalive(tmp,tmp,gametxid,maxplayers,gameheight,gametx) > 1 )
return(cclib_error(result,"highlander must be a winner or last one standing"));
}
cashout *= 2;
cashout += numplayers * buyin;
}
if ( cashout > 0 )
{
if ( komodo_nextheight() > 77777 && cashout > ROGUE_MAXCASHOUT )
cashout = ROGUE_MAXCASHOUT;
if ( (inputsum= AddCClibInputs(cp,mtx,roguepk,cashout,60,cp->unspendableCCaddr)) > cashout )
CCchange = (inputsum - cashout);
else fprintf(stderr,"couldnt find enough utxos\n");
@@ -1326,12 +1341,12 @@ UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
UniValue rogue_bailout(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
return(rogue_finishgame(txfee,cp,params,"bailout"));
return(rogue_finishgame(txfee,cp,params,(char *)"bailout"));
}
UniValue rogue_highlander(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
return(rogue_finishgame(txfee,cp,params,"highlander"));
return(rogue_finishgame(txfee,cp,params,(char *)"highlander"));
}
UniValue rogue_gameinfo(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
@@ -1506,7 +1521,7 @@ bool rogue_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const C
if ( (numvouts= tx.vout.size()) > 1 )
{
txid = tx.GetHash();
if ( txid == Parseuint256("1ae04dc0c5f2fca2053819a3a1b2efe5d355c34f58d6f16d59e5e2573e7baf7f") ) // osx rogue chain ht.50902
if ( txid == Parseuint256("1ae04dc0c5f2fca2053819a3a1b2efe5d355c34f58d6f16d59e5e2573e7baf7f") || txid == Parseuint256("2a34b36cc1292aecfaabdad79b42cab9989fa6dcc87ac8ca88aa6162dab1e2c4") ) // osx rogue chain ht.50902, 69522
enabled = 0;
scriptPubKey = tx.vout[numvouts-1].scriptPubKey;
GetOpReturnData(scriptPubKey,vopret);
@@ -1598,13 +1613,13 @@ bool rogue_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const C
if ( enabled != 0 )
return eval->Invalid("mismatched playerdata");
}
if ( height > 777777 && cashout > ROGUE_MAXCASHOUT )
cashout = ROGUE_MAXCASHOUT;
if ( funcid == 'H' )
{
cashout *= 2;
//cashout += numplayers * buyin;
cashout += rogue_buyins(gametxid,maxplayers);
}
if ( height > 777777 && cashout > ROGUE_MAXCASHOUT )
cashout = ROGUE_MAXCASHOUT;
sprintf(cashstr,"tokentx.(%c) decoded.%d ht.%d txid.%s %.8f vs vout2 %.8f",tokentx,decoded,height,txid.GetHex().c_str(),(double)cashout/COIN,(double)tx.vout[2].nValue/COIN);
if ( strcmp(laststr,cashstr) != 0 )
{

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
About
-----
Komodo SudokuCC GUI
Just solve Sudoku and earn SUDOKU coins!
![alt text](https://i.imgur.com/std99XW.png)
To run you need up and running SUDOKU chain daemon built from latest https://github.com/jl777/komodo/tree/FSM and started with valid for your wallet pubkey in `-pubkey=` param.
SUDOKU chain params:
```./komodod -ac_name=SUDOKU -ac_supply=1000000 -pubkey=<yourpubkey> -addnode=5.9.102.210 -gen -genproclimit=1 -ac_cclib=sudoku -ac_perc=10000000 -ac_reward=100000000 -ac_cc=60000 -ac_script=2ea22c80203d1579313abe7d8ea85f48c65ea66fc512c878c0d0e6f6d54036669de940febf8103120c008203000401cc &```
1) install dependencies:
```
$ sudo apt-get install python-pygame libgnutls28-dev
$ pip install requests wheel slick-bitcoinrpc pygame
```
2) and then start:
```
$ git clone https://github.com/tonymorony/Komodoku
$ cd Komodoku
$ python Sudoku.py
```

BIN
src/gui/komodoku/Roboto-Light.ttf Executable file

Binary file not shown.

362
src/gui/komodoku/Sudoku.py Normal file
View File

@@ -0,0 +1,362 @@
#!/usr/bin/env python
# Copyright (C) 2010 Paul Bourke <pauldbourke@gmail.com>
# Copyright (C) 2019 Anton Lysakov <tlysakov@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import pygame
import sys
import random
import sudoku_kmdlib
import time
class PyGameBoard():
"""Represents the game's frontend using pygame"""
def __init__(self, engine, windowSize, gridValues, timestampValues):
pygame.init()
pygame.display.set_caption('Sudoku')
self.__engine = engine
self.__gridValues = gridValues
self.__timestampValues = timestampValues
self.__screen = pygame.display.set_mode(windowSize)
background = pygame.image.load(sys.path[0] + '/background.png').convert()
board = pygame.image.load(sys.path[0] + '/board.png')
boardX = boardY = 10
self.__screen.blit(background, (0, 0))
self.__screen.blit(board, (boardX, boardY))
self.__tiles = self.__createTiles(boardX, boardY)
self.__drawUI()
self.__draw()
def __draw(self):
"""Handles events and updates display buffer"""
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.MOUSEBUTTONUP and event.button == 1:
self.__handleMouse(event.pos)
elif (event.type == pygame.KEYUP):
self.__handleKeyboard(event.key)
pygame.display.flip()
def __drawUI(self):
'''Draws the text buttons along the right panel'''
font = pygame.font.Font(sys.path[0] + '/Roboto-Light.ttf', 28)
font.set_underline(True)
self.__titleText = font.render('Sudoku', 1, (0, 0, 0))
self.__titleTextRect = self.__titleText.get_rect()
self.__titleTextRect.centerx = 445
self.__titleTextRect.centery = 30
self.__screen.blit(self.__titleText, self.__titleTextRect)
font = pygame.font.Font(sys.path[0] + '/Roboto-Light.ttf', 14)
self.__titleText = font.render('TonyL 2019', 1, (0, 0, 0))
self.__titleTextRect = self.__titleText.get_rect()
self.__titleTextRect.centerx = 445
self.__titleTextRect.centery = 55
self.__screen.blit(self.__titleText, self.__titleTextRect)
font = pygame.font.Font(sys.path[0] + '/Roboto-Light.ttf', 24)
self.__newGameText = font.render('-New Game-', 1, (0, 0, 0))
self.__newGameTextRect = self.__newGameText.get_rect()
self.__newGameTextRect.centerx = 495
self.__newGameTextRect.centery = 180
self.__screen.blit(self.__newGameText, self.__newGameTextRect)
self.__solveText = font.render('-Check Balance-', 1, (0, 0, 0))
self.__solveTextRect = self.__solveText.get_rect()
self.__solveTextRect.centerx = 495
self.__solveTextRect.centery = 220
self.__screen.blit(self.__solveText, self.__solveTextRect)
font = pygame.font.Font(sys.path[0] + '/Roboto-Light.ttf', 24)
self.__checkText = font.render('-Check Solution-', 1, (0, 0, 0))
self.__checkTextRect = self.__checkText.get_rect()
self.__checkTextRect.centerx = 495
self.__checkTextRect.centery = 260
self.__screen.blit(self.__checkText, self.__checkTextRect)
def __handleKeyboard(self, key):
"""Get key pressed and update the game board"""
validKeys = {pygame.K_0: "0", pygame.K_1: "1", pygame.K_2: "2",
pygame.K_3: "3", pygame.K_4: "4", pygame.K_5: "5",
pygame.K_6: "6", pygame.K_7: "7", pygame.K_8: "8",
pygame.K_9: "9", pygame.K_BACKSPACE: "", pygame.K_DELETE: ""}
if key == pygame.K_ESCAPE:
sys.exit()
elif key in validKeys:
i = self.__currentTile.getGridLoc()[0]
j = self.__currentTile.getGridLoc()[1]
cell_num = 9 * i + (j + 1)
self.__currentTile.setFontColor(pygame.color.THECOLORS['blue'])
self.__currentTile.updateValue(validKeys[key])
self.__gridValues[i][j] = self.__currentTile.getValue()
self.__timestampValues[cell_num] = int(round(time.time()))
def __handleMouse(self, (x, y)):
for row in self.__tiles:
for tile in row:
if tile.getRect().collidepoint(x, y):
if not tile.isReadOnly():
tile.highlight(pygame.color.THECOLORS['lightyellow'])
if self.__currentTile.isCorrect():
self.__currentTile.unhighlight()
else:
self.__currentTile.highlight((255, 164, 164))
self.__currentTile = tile
if self.__newGameTextRect.collidepoint(x, y):
self.__engine.startNewGame()
elif self.__solveTextRect.collidepoint(x, y):
self.__engine.getSolution()
elif self.__checkTextRect.collidepoint(x, y):
ret = self.__engine.checkSolution(self.__gridValues, self.__timestampValues)
def __updateBoard(self, gridValues):
for i in range(9):
for j in range(9):
self.__tiles[i][j].updateValue(gridValues[i][j])
def __unhightlightBoard(self):
for i in range(9):
for j in range(9):
self.__tiles[i][j].unhighlight()
def __createTiles(self, initX=0, initY=0):
"""Set up a list of tiles corresponding to the grid, along with
each ones location coordinates on the board"""
square_size = 40
tiles = list()
x = y = 0
for i in range(0, 9):
row = list()
for j in range(0, 9):
if j in (0, 1, 2):
x = (j * 41) + (initX + 2)
if j in (3, 4, 5):
x = (j * 41) + (initX + 6)
if j in (6, 7, 8):
x = (j * 41) + (initX + 10)
if i in (0, 1, 2):
y = (i * 41) + (initY + 2)
if i in (3, 4, 5):
y = (i * 41) + (initY + 6)
if i in (6, 7, 8):
y = (i * 41) + (initY + 10)
tile = Tile(self.__gridValues[i][j], (x, y), (i, j), square_size)
row.append(tile)
tiles.append(row)
self.__currentTile = tiles[0][0]
return tiles
class Tile():
"""Represents a graphical tile on the board"""
def __init__(self, value, coords, gridLoc, size):
xpos = coords[0]
ypos = coords[1]
self.__fontColor = pygame.color.THECOLORS["black"]
self.__readOnly = False
self.__colorSquare = pygame.Surface((size, size)).convert()
self.__colorSquare.fill(pygame.color.THECOLORS['white'], None, pygame.BLEND_RGB_ADD)
self.__colorSquareRect = self.__colorSquare.get_rect()
self.__colorSquareRect = self.__colorSquareRect.move(xpos + 1, ypos + 1)
self.__value = value
self.__gridLoc = gridLoc
self.__screen = pygame.display.get_surface()
self.__rect = pygame.Rect(xpos, ypos, size, size)
self.__isCorrect = True
if self.__value is not '-':
self.__readOnly = True
self.__draw()
def updateValue(self, value):
self.__value = value
self.__draw()
def isCorrect(self):
return self.__isCorrect
def setCorrect(self, isCorrect):
self.__isCorrect = isCorrect
def setFontColor(self, fontColor):
self.__fontColor = fontColor
def getValue(self):
return self.__value
def getRect(self):
return self.__rect
def getGridLoc(self):
return self.__gridLoc
def isReadOnly(self):
return self.__readOnly
def highlight(self, color):
if self.__readOnly is True:
return
self.__colorSquare.fill(color)
self.__draw()
def unhighlight(self):
self.__colorSquare.fill((255, 225, 255), None, pygame.BLEND_RGB_ADD)
self.__draw()
def __draw(self):
value = self.__value
if self.__value == '-':
value = ''
font = pygame.font.Font(sys.path[0] + '/Roboto-Light.ttf', 24)
text = font.render(str(value), 1, self.__fontColor)
textpos = text.get_rect()
textpos.centerx = self.__rect.centerx
textpos.centery = self.__rect.centery
self.__screen.blit(self.__colorSquare, self.__colorSquareRect)
self.__screen.blit(text, textpos)
class Sudoku:
"""Represents the game's backend and logic"""
def __init__(self, puzzleFile, rpc_connection):
self.__puzzleFile = puzzleFile
self.__rpc_connection = rpc_connection
self.startNewGame()
def startNewGame(self):
self.__linePuzzle = self.__loadPuzzle(self.__puzzleFile)
gridValues = self.lineToGrid(self.__linePuzzle)
# prefill 0 timestamps for already known numbers
timestampValues = self.prefill_timestamps(gridValues)
board = PyGameBoard(self, (600, 400), gridValues, timestampValues)
board.setValues(gridValues)
def __loadPuzzle(self, listName):
self.__chosen_puzzle = random.choice(listName)
puzzle = self.__rpc_connection.cclib("txidinfo", "17", '"%22' + self.__chosen_puzzle + '%22"')["unsolved"]
print "Puzzle ID: " + self.__chosen_puzzle
print "Reward amount: " + str(self.__rpc_connection.cclib("txidinfo", "17", '"%22' + self.__chosen_puzzle + '%22"')["amount"])
ret = []
linePuzzle = str(puzzle)
for i in linePuzzle:
ret.append(i)
return ret
def gridToLine(self, grid):
linePuzzle = ''
for i in range(9):
for j in range(9):
linePuzzle += grid[i][j]
return linePuzzle
def lineToGrid(self, linePuzzle):
assert (len(linePuzzle) == 81)
grid = []
for i in xrange(0, 81, 9):
grid.append(linePuzzle[i:i + 9])
return grid
def getSolution(self):
balance = self.__rpc_connection.cclibaddress("17")["mybalance"]
print "Your balance: " + str(balance)
def __solve(self, linePuzzle):
linePuzzle = ''.join(linePuzzle)
i = linePuzzle.find('-')
if i == -1:
return linePuzzle
excluded_numbers = set()
for j in range(81):
if self.sameRow(i, j) or self.sameCol(i, j) or self.sameBlock(i, j):
excluded_numbers.add(linePuzzle[j])
for m in '123456789':
if m not in excluded_numbers:
funcRet = self.__solve(linePuzzle[:i] + m + linePuzzle[i + 1:])
if funcRet is not None:
return funcRet
def prefill_timestamps(self, grid):
timestamps = {}
for i in range(9):
for j in range(9):
if grid[i][j] != '-':
cell_num = 9 * i + ( j + 1 )
timestamps[cell_num] = 0
return timestamps
def sameRow(self, i, j):
return (i / 9 == j / 9)
def sameCol(self, i, j):
return (i - j) % 9 == 0
def sameBlock(self, i, j):
return (i / 27 == j / 27 and i % 9 / 3 == j % 9 / 3)
def checkSolution(self, attemptGrid, timestampValues):
# [%22<txid>%22,%22<solution>%22,t0,t1,t2,...]
attemptLine = self.gridToLine(attemptGrid)
#print attemptLine
#print timestampValues
timestampsline = ""
for timestamp in timestampValues.values():
timestampsline += ","
timestampsline += str(timestamp)
arg_line = "[%22"+self.__chosen_puzzle+"%22,%22"+attemptLine+"%22"+timestampsline+"]"
print arg_line
try:
solution_info = self.__rpc_connection.cclib("solution", "17", '"' + arg_line + '"')
print solution_info
solution_txid = self.__rpc_connection.sendrawtransaction(solution_info["hex"])
print "Solution accepted!"
print solution_txid
except Exception as e:
print(e)
print(solution_info)
solution_txid = 'error'
return solution_txid
def main():
while True:
# Assetchain hardcoded here
chain = 'SUDOKU'
try:
print 'Welcome to the Komodo SudokuCC'
rpc_connection = sudoku_kmdlib.def_credentials(chain)
pending_puzzles = rpc_connection.cclib("pending", "17")["pending"]
puzzle_list = []
for puzzle in pending_puzzles:
puzzle_list.append(puzzle["txid"])
except Exception as e:
#print rpc_connection
print e
print 'Cant connect to SUDOKU Daemon! Please re-check if it up'
sys.exit()
else:
print 'Succesfully connected!\n'
break
newGame = Sudoku(puzzle_list, rpc_connection)
if __name__ == '__main__':
main()

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 KiB

BIN
src/gui/komodoku/board.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@@ -0,0 +1,41 @@
import platform
import os
import re
import random
from slickrpc import Proxy
# define function that fetchs rpc creds from .conf
def def_credentials(chain):
rpcport ='';
operating_system = platform.system()
if operating_system == 'Darwin':
ac_dir = os.environ['HOME'] + '/Library/Application Support/Komodo'
elif operating_system == 'Linux':
ac_dir = os.environ['HOME'] + '/.komodo'
elif operating_system == 'Windows':
ac_dir = '%s/komodo/' % os.environ['APPDATA']
if chain == 'KMD':
coin_config_file = str(ac_dir + '/komodo.conf')
else:
coin_config_file = str(ac_dir + '/' + chain + '/' + chain + '.conf')
with open(coin_config_file, 'r') as f:
for line in f:
l = line.rstrip()
if re.search('rpcuser', l):
rpcuser = l.replace('rpcuser=', '')
elif re.search('rpcpassword', l):
rpcpassword = l.replace('rpcpassword=', '')
elif re.search('rpcport', l):
rpcport = l.replace('rpcport=', '')
if len(rpcport) == 0:
if chain == 'KMD':
rpcport = 7771
else:
print("rpcport not in conf file, exiting")
print("check "+coin_config_file)
exit(1)
return(Proxy("http://%s:%s@127.0.0.1:%d"%(rpcuser, rpcpassword, int(rpcport))))

View File

@@ -201,6 +201,9 @@ try_again:
curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback
curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL, 1L); // supposed to fix "Alarm clock" and long jump crash
curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback
//curl_easy_setopt(curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
//curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, 2);
if ( strncmp(url,"https",5) == 0 )
{
curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0);
@@ -247,13 +250,13 @@ try_again:
numretries++;
if ( specialcase != 0 )
{
printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res);
fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res);
free(s.ptr);
return(0);
}
else if ( numretries >= 1 )
{
//printf("Maximum number of retries exceeded!\n");
fprintf(stderr,"Maximum number of retries exceeded!\n");
free(s.ptr);
return(0);
}
@@ -1234,7 +1237,7 @@ uint64_t komodo_commission(const CBlock *pblock,int32_t height)
n = pblock->vtx[i].vout.size();
for (j=0; j<n; j++)
{
if ( height > 100000 && ASSETCHAINS_STAKED != 0 && txn_count > 1 && i == txn_count-1 && j == n-1 )
if ( height > 150000 && ASSETCHAINS_STAKED != 0 && txn_count > 1 && i == txn_count-1 && j == n-1 )
break;
//fprintf(stderr,"(%d %.8f).%d ",i,dstr(pblock->vtx[i].vout[j].nValue),j);
if ( i != 0 || j != 1 )

View File

@@ -50,7 +50,7 @@ extern uint64_t ASSETCHAINS_TIMELOCKGTE;
extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH,ASSETCHAINS_EQUIHASH,KOMODO_INITDONE;
extern int32_t KOMODO_MININGTHREADS,KOMODO_LONGESTCHAIN,ASSETCHAINS_SEED,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,KOMODO_ON_DEMAND,KOMODO_PASSPORT_INITDONE,ASSETCHAINS_STAKED;
extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_LASTERA;
extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_LASTERA,ASSETCHAINS_CBOPRET;
extern bool VERUS_MINTBLOCKS;
extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[];
extern const char *ASSETCHAINS_ALGORITHMS[];

View File

@@ -1547,3 +1547,547 @@ void komodo_passport_iteration()
printf("READY for %s RPC calls at %u! done PASSPORT %s refid.%d\n",ASSETCHAINS_SYMBOL,(uint32_t)time(NULL),ASSETCHAINS_SYMBOL,refid);
}
}
extern std::vector<uint8_t> Mineropret; // opreturn data set by the data gathering code
#define PRICES_MAXCHANGE (COIN / 100) // maximum acceptable change, set at 1%
#define PRICES_SIZEBIT0 (sizeof(uint32_t) * 4) // 4 uint32_t unixtimestamp, BTCUSD, BTCGBP and BTCEUR
// komodo_heightpricebits() extracts the price data in the coinbase for nHeight
int32_t komodo_heightpricebits(uint32_t prevbits[4],int32_t nHeight)
{
CBlockIndex *pindex; CBlock block; CTransaction tx; int32_t numvouts; std::vector<uint8_t> vopret;
if ( (pindex= komodo_chainactive(nHeight)) != 0 )
{
if ( komodo_blockload(block,pindex) == 0 )
{
tx = block.vtx[0];
numvouts = (int32_t)tx.vout.size();
GetOpReturnData(tx.vout[numvouts-1].scriptPubKey,vopret);
if ( vopret.size() >= PRICES_SIZEBIT0 )
{
memcpy(prevbits,vopret.data(),vopret.size());
return(0);
}
}
}
fprintf(stderr,"couldnt get pricebits for %d\n",nHeight);
return(-1);
}
/*
komodo_pricenew() is passed in a reference price, the change tolerance and the proposed price. it needs to return a clipped price if it is too big and also set a flag if it is at or above the limit
*/
uint32_t komodo_pricenew(char *maxflagp,uint32_t price,uint32_t refprice,int64_t tolerance)
{
uint64_t highprice,lowprice;
if ( refprice < 2 )
return(0);
highprice = ((uint64_t)refprice * (COIN + tolerance)) / COIN; // calc highest acceptable price
lowprice = ((uint64_t)refprice * (COIN - tolerance)) / COIN; // and lowest
if ( highprice == refprice )
highprice++;
if ( lowprice == refprice )
lowprice--;
if ( price >= highprice )
{
fprintf(stderr,"high %u vs h%llu l%llu tolerance.%llu\n",price,(long long)highprice,(long long)lowprice,(long long)tolerance);
if ( price > highprice ) // return non-zero only if we violate the tolerance
{
*maxflagp = 2;
return(highprice);
}
*maxflagp = 1;
}
else if ( price <= lowprice )
{
//fprintf(stderr,"low %u vs h%llu l%llu tolerance.%llu\n",price,(long long)highprice,(long long)lowprice,(long long)tolerance);
if ( price < lowprice )
{
*maxflagp = -2;
return(lowprice);
}
*maxflagp = -1;
}
return(0);
}
// komodo_pricecmp() returns -1 if any of the prices are beyond the tolerance
int32_t komodo_pricecmp(int32_t nHeight,int32_t n,char *maxflags,uint32_t *pricebitsA,uint32_t *pricebitsB,int64_t tolerance)
{
int32_t i; uint32_t newprice;
for (i=1; i<n; i++)
{
if ( (newprice= komodo_pricenew(&maxflags[i],pricebitsA[i],pricebitsB[i],tolerance)) != 0 )
{
fprintf(stderr,"ht.%d i.%d/%d %u vs %u -> newprice.%u out of tolerance maxflag.%d\n",nHeight,i,n,pricebitsB[i],pricebitsA[i],newprice,maxflags[i]);
return(-1);
}
}
return(0);
}
// komodo_priceclamp() clamps any price that is beyond tolerance
int32_t komodo_priceclamp(int32_t n,uint32_t *pricebits,uint32_t *refprices,int64_t tolerance)
{
int32_t i; uint32_t newprice; char maxflags[2048];
memset(maxflags,0,sizeof(maxflags));
for (i=1; i<n; i++)
{
if ( (newprice= komodo_pricenew(&maxflags[i],pricebits[i],refprices[i],tolerance)) != 0 )
{
fprintf(stderr,"priceclamped[%d of %d] %u vs %u -> %u\n",i,n,refprices[i],pricebits[i],newprice);
pricebits[i] = newprice;
}
}
return(0);
}
// komodo_mineropret() returns a valid pricedata to add to the coinbase opreturn for nHeight
CScript komodo_mineropret(int32_t nHeight)
{
CScript opret; char maxflags[2048]; uint32_t pricebits[2048],prevbits[2048]; int32_t maxflag,i,n,numzero=0;
if ( Mineropret.size() >= PRICES_SIZEBIT0 )
{
n = (int32_t)(Mineropret.size() / sizeof(uint32_t));
numzero = 1;
while ( numzero > 0 )
{
memcpy(pricebits,Mineropret.data(),Mineropret.size());
for (i=numzero=0; i<n; i++)
if ( pricebits[i] == 0 )
numzero++;
if ( numzero != 0 )
fprintf(stderr,"numzero.%d\n",numzero);
}
if ( komodo_heightpricebits(prevbits,nHeight-1) == 0 )
{
memcpy(pricebits,Mineropret.data(),Mineropret.size());
memset(maxflags,0,sizeof(maxflags));
if ( komodo_pricecmp(0,n,maxflags,pricebits,prevbits,PRICES_MAXCHANGE) < 0 )
{
// if the new prices are outside tolerance, update Mineropret with clamped prices
komodo_priceclamp(n,pricebits,prevbits,PRICES_MAXCHANGE);
fprintf(stderr,"update Mineropret to clamped prices\n");
memcpy(Mineropret.data(),pricebits,Mineropret.size());
}
}
int32_t i;
for (i=0; i<Mineropret.size(); i++)
fprintf(stderr,"%02x",Mineropret[i]);
fprintf(stderr," <- Mineropret\n");
return(opret << OP_RETURN << Mineropret);
}
return(opret);
}
/*
komodo_opretvalidate() is the entire price validation!
it prints out some useful info for debugging, like the lag from current time and prev block and the prices encoded in the opreturn.
The only way komodo_opretvalidate() doesnt return an error is if maxflag is set or it is within tolerance of both the prior block and the local data. The local data validation only happens if it is a recent block and not a block from the past as the local node is only getting the current price data.
*/
// reconsiderblock 002aca768b09dfcf36bd934ab34b23983148b116e12cb0b6e1a3f895d1db63aa
// and
// reconsiderblock 0034cf582018eacc0b4ae001491ce460113514cb1a3f217567ef4a2207de361a
// reconsiderbloc 000abf51c023b64af327c50c1b060797b8cb281c696d30ab92fd002a8b8c9aea
// are needed to sync past initial blocks with different data set
// pass in blockhash and nTime, latch if it is rejected due to local price, then if localprice changes in a way that would validate then issue reconsiderblock
// add rpc call for extracting rawprices
int32_t komodo_opretvalidate(int32_t nHeight,CScript scriptPubKey)
{
std::vector<uint8_t> vopret; char maxflags[2048]; double btcusd,btcgbp,btceur; uint32_t localbits[2048],pricebits[2048],prevbits[2048],newprice; int32_t i,maxflag,lag,lag2,n; uint32_t now = (uint32_t)time(NULL);
if ( ASSETCHAINS_CBOPRET != 0 && nHeight > 0 )
{
GetOpReturnData(scriptPubKey,vopret);
if ( vopret.size() >= PRICES_SIZEBIT0 )
{
n = (int32_t)(vopret.size() / sizeof(uint32_t));
memcpy(pricebits,vopret.data(),Mineropret.size());
memset(maxflags,0,sizeof(maxflags));
if ( nHeight > 1 )
{
lag = (int32_t)(now - pricebits[0]);
lag2 = (int32_t)(komodo_heightstamp(nHeight-1) - pricebits[0]);
if ( lag < -60 ) // avoid data from future
{
fprintf(stderr,"now.%u htstamp.%u - pricebits[0] %u -> lag.%d\n",now,komodo_heightstamp(nHeight-1),pricebits[0],lag2);
return(-1);
}
// else need to check against current blocktime to prevent pricebits[0] games
btcusd = (double)pricebits[1]/10000;
btcgbp = (double)pricebits[2]/10000;
btceur = (double)pricebits[3]/10000;
fprintf(stderr,"ht.%d: lag.%d %.4f USD, %.4f GBP, %.4f EUR, GBPUSD %.6f, EURUSD %.6f, EURGBP %.6f [%d]\n",nHeight,lag,btcusd,btcgbp,btceur,btcusd/btcgbp,btcusd/btceur,btcgbp/btceur,lag2);
if ( komodo_heightpricebits(prevbits,nHeight-1) == 0 )
{
if ( nHeight < 500 )
{
for (i=0; i<n; i++)
if ( pricebits[i] == 0 )
pricebits[i] = prevbits[i];
}
if ( komodo_pricecmp(nHeight,n,maxflags,pricebits,prevbits,PRICES_MAXCHANGE) < 0 )
{
for (i=1; i<n; i++)
fprintf(stderr,"%.4f ",(double)prevbits[i]/10000);
fprintf(stderr," oldprices.%d\n",nHeight);
for (i=1; i<n; i++)
fprintf(stderr,"%.4f ",(double)pricebits[i]/10000);
fprintf(stderr," newprices.%d\n",nHeight);
fprintf(stderr,"vs prev maxflag.%d cmp error\n",maxflag);
return(-1);
} // else this is the good case we hope to happen
} else return(-1);
if ( lag < ASSETCHAINS_BLOCKTIME && Mineropret.size() >= PRICES_SIZEBIT0 )
{
memcpy(localbits,Mineropret.data(),Mineropret.size());
if ( nHeight < 500 )
{
for (i=0; i<n; i++)
if ( localbits[i] == 0 )
localbits[i] = prevbits[i];
}
for (i=1; i<n; i++)
{
if ( (maxflag= maxflags[i]) != 0 )
{
// make sure local price is moving in right direction
fprintf(stderr,"maxflag.%d i.%d localbits.%u vs pricebits.%u prevbits.%u\n",maxflag,i,localbits[i],pricebits[i],prevbits[i]);
if ( maxflag > 0 && localbits[i] < prevbits[i] )
return(-1);
else if ( maxflag < 0 && localbits[i] > prevbits[i] )
return(-1);
}
}
}
}
return(0);
} else fprintf(stderr,"wrong size %d vs %d, scriptPubKey size %d [%02x]\n",(int32_t)vopret.size(),(int32_t)Mineropret.size(),(int32_t)scriptPubKey.size(),scriptPubKey[0]);
return(-1);
}
return(0);
}
char *nonportable_path(char *str)
{
int32_t i;
for (i=0; str[i]!=0; i++)
if ( str[i] == '/' )
str[i] = '\\';
return(str);
}
char *portable_path(char *str)
{
#ifdef _WIN32
return(nonportable_path(str));
#else
#ifdef __PNACL
/*int32_t i,n;
if ( str[0] == '/' )
return(str);
else
{
n = (int32_t)strlen(str);
for (i=n; i>0; i--)
str[i] = str[i-1];
str[0] = '/';
str[n+1] = 0;
}*/
#endif
return(str);
#endif
}
void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep)
{
FILE *fp;
long filesize,buflen = *allocsizep;
uint8_t *buf = *bufp;
*lenp = 0;
if ( (fp= fopen(portable_path(fname),"rb")) != 0 )
{
fseek(fp,0,SEEK_END);
filesize = ftell(fp);
if ( filesize == 0 )
{
fclose(fp);
*lenp = 0;
//printf("loadfile null size.(%s)\n",fname);
return(0);
}
if ( filesize > buflen )
{
*allocsizep = filesize;
*bufp = buf = (uint8_t *)realloc(buf,(long)*allocsizep+64);
}
rewind(fp);
if ( buf == 0 )
printf("Null buf ???\n");
else
{
if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize )
printf("error reading filesize.%ld\n",(long)filesize);
buf[filesize] = 0;
}
fclose(fp);
*lenp = filesize;
//printf("loaded.(%s)\n",buf);
} //else printf("OS_loadfile couldnt load.(%s)\n",fname);
return(buf);
}
void *filestr(long *allocsizep,char *_fname)
{
long filesize = 0; char *fname,*buf = 0; void *retptr;
*allocsizep = 0;
fname = (char *)malloc(strlen(_fname)+1);
strcpy(fname,_fname);
retptr = loadfile(fname,(uint8_t **)&buf,&filesize,allocsizep);
free(fname);
return(retptr);
}
cJSON *send_curl(char *url,char *fname)
{
long fsize; char curlstr[1024],*jsonstr; cJSON *json=0;
sprintf(curlstr,"wget -q \"%s\" -O %s",url,fname);
if ( system(curlstr) == 0 )
{
if ( (jsonstr= (char *)filestr((long *)&fsize,fname)) != 0 )
{
json = cJSON_Parse(jsonstr);
free(jsonstr);
}
}
return(json);
}
// get_urljson just returns the JSON returned by the URL using issue_curl
#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"CBCOINBASE",cmdstr,0,0,0)
const char *Cryptos[] = { "KMD", "ETH", "LTC", "BCHABC", "XMR", "IOTA", "DASH", "XEM", "ZEC", "WAVES", "RVN", "LSK", "DCR", "BTS", "ICX", "HOT", "STEEM", "ENJ", "STRAT" };
const char *Forex[] =
{ "BGN","NZD","ILS","RUB","CAD","PHP","CHF","AUD","JPY","TRY","HKD","MYR","HRK","CZK","IDR","DKK","NOK","HUF","GBP","MXN","THB","ISK","ZAR","BRL","SGD","PLN","INR","KRW","RON","CNY","SEK","EUR"
};
/*
const char *Techstocks[] =
{ "AAPL","ADBE","ADSK","AKAM","AMD","AMZN","ATVI","BB","CDW","CRM","CSCO","CYBR","DBX","EA","FB","GDDY","GOOG","GRMN","GSAT","HPQ","IBM","INFY","INTC","INTU","JNPR","MSFT","MSI","MU","MXL","NATI","NCR","NFLX","NTAP","NVDA","ORCL","PANW","PYPL","QCOM","RHT","S","SHOP","SNAP","SPOT","SYMC","SYNA","T","TRIP","TWTR","TXN","VMW","VOD","VRSN","VZ","WDC","XRX","YELP","YNDX","ZEN"
};
const char *Metals[] = { "XAU", "XAG", "XPT", "XPD", };
const char *Markets[] = { "DJIA", "SPX", "NDX", "VIX" };
*/
cJSON *get_urljson(char *url)
{
char *jsonstr; cJSON *json = 0;
if ( (jsonstr= issue_curl(url)) != 0 )
{
//fprintf(stderr,"(%s) -> (%s)\n",url,jsonstr);
json = cJSON_Parse(jsonstr);
free(jsonstr);
}
return(json);
}
uint32_t get_stockprice(const char *symbol)
{
char url[512]; cJSON *json,*obj; uint32_t high,low,price = 0;
sprintf(url,"https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=%s&interval=15min&apikey=%s",symbol,NOTARY_PUBKEY.data()+50);
if ( (json= get_urljson(url)) != 0 )
{
if ( (obj= jobj(json,(char *)"Time Series (15min)")) != 0 )
{
high = jdouble(jitem(obj,0),(char *)"2. high")*10000 + 0.000049;
low = jdouble(jitem(obj,0),(char *)"3. low")*10000 + 0.000049;
price = (high + low) / 2;
}
free_json(json);
}
return(price);
}
uint32_t get_dailyfx(uint32_t *prices)
{
//{"base":"USD","rates":{"BGN":1.74344803,"NZD":1.471652701,"ILS":3.6329113924,"RUB":65.1997682296,"CAD":1.3430201462,"USD":1.0,"PHP":52.8641469068,"CHF":0.9970582992,"AUD":1.4129078267,"JPY":110.6792654662,"TRY":5.6523444464,"HKD":7.8499732573,"MYR":4.0824567659,"HRK":6.6232840078,"CZK":22.9862720628,"IDR":14267.4986628633,"DKK":6.6551078624,"NOK":8.6806917454,"HUF":285.131039401,"GBP":0.7626582278,"MXN":19.4183455161,"THB":31.8702085933,"ISK":122.5708682475,"ZAR":14.7033339276,"BRL":3.9750401141,"SGD":1.3573720806,"PLN":3.8286682118,"INR":69.33187734,"KRW":1139.1602781244,"RON":4.2423783206,"CNY":6.7387234801,"SEK":9.3385630237,"EUR":0.8914244963},"date":"2019-03-28"}
char url[512],*datestr; cJSON *json,*rates; int32_t i; uint32_t datenum=0,price = 0;
sprintf(url,"https://api.openrates.io/latest?base=USD");
if ( (json= send_curl(url,(char *)"dailyfx")) != 0 )
{
if ( (rates= jobj(json,(char *)"rates")) != 0 )
{
for (i=0; i<sizeof(Forex)/sizeof(*Forex); i++)
{
price = jdouble(rates,(char *)Forex[i]) * 10000 + 0.000049;
fprintf(stderr,"(%s %.4f) ",Forex[i],(double)price/10000);
prices[i] = price;
}
}
if ( (datestr= jstr(json,(char *)"date")) != 0 )
fprintf(stderr,"(%s)",datestr);
fprintf(stderr,"\n");
free_json(json);
}
return(datenum);
}
uint32_t get_binanceprice(const char *symbol)
{
char url[512]; cJSON *json; uint32_t price = 0;
sprintf(url,"https://api.binance.com/api/v1/ticker/price?symbol=%sBTC",symbol);
if ( (json= send_curl(url,(char *)"bnbprice")) != 0 )
{
price = jdouble(json,(char *)"price")*SATOSHIDEN + 0.0000000049;
free_json(json);
}
usleep(100000);
return(price);
}
int32_t get_cryptoprices(uint32_t *prices,const char *list[],int32_t n)
{
int32_t i,errs=0; uint32_t price;
for (i=0; i<n; i++)
{
if ( (price= get_binanceprice(list[i])) == 0 )
errs++;
fprintf(stderr,"(%s %.8f) ",list[i],(double)price/SATOSHIDEN);
prices[i] = price;
}
fprintf(stderr," errs.%d\n",errs);
return(-errs);
}
uint32_t get_currencyprice(const char *symbol)
{
char url[512]; cJSON *json,*obj; uint32_t price = 0;
sprintf(url,"https://www.alphavantage.co/query?function=CURRENCY_EXCHANGE_RATE&from_currency=%s&to_currency=USD&apikey=%s",symbol,NOTARY_PUBKEY.data()+50);
if ( (json= send_curl(url,(char *)"curldata")) != 0 )//get_urljson(url)) != 0 )
{
if ( (obj= jobj(jitem(json,0),0)) != 0 )
price = jdouble(obj,(char *)"5. Exchange Rate")*10000 + 0.000049;
free_json(json);
}
return(price);
}
int32_t get_stocks(const char *list[],int32_t n)
{
int32_t i,errs=0; uint32_t price;
for (i=0; i<n; i++)
{
if ( (price= get_stockprice(list[i])) == 0 )
errs++;
else fprintf(stderr,"(%s %.4f) ",list[i],(double)price/10000);
}
fprintf(stderr," errs.%d\n",errs);
return(-errs);
}
// parse the coindesk specific data. yes, if this changes, it will require an update. However, regardless if the format from the data source changes, then the code that extracts it must be changed. One way to mitigate this is to have a large variety of data sources so that there is only a very remote chance that all of them are not available. Certainly the data gathering needs to be made more robust, but it doesnt really affect the proof of concept for the decentralized trustless oracle. The trustlessness is achieved by having all nodes get the oracle data.
int32_t get_btcusd(uint32_t pricebits[4])
{
cJSON *pjson,*bpi,*obj; char str[512]; double dbtcgbp,dbtcusd,dbtceur; uint64_t btcusd = 0,btcgbp = 0,btceur = 0;
if ( (pjson= get_urljson((char *)"http://api.coindesk.com/v1/bpi/currentprice.json")) != 0 )
{
if ( (bpi= jobj(pjson,(char *)"bpi")) != 0 )
{
pricebits[0] = (uint32_t)time(NULL);
if ( (obj= jobj(bpi,(char *)"USD")) != 0 )
{
btcusd = jdouble(obj,(char *)"rate_float") * SATOSHIDEN;
pricebits[1] = ((btcusd / 10000) & 0xffffffff);
}
if ( (obj= jobj(bpi,(char *)"GBP")) != 0 )
{
btcgbp = jdouble(obj,(char *)"rate_float") * SATOSHIDEN;
pricebits[2] = ((btcgbp / 10000) & 0xffffffff);
}
if ( (obj= jobj(bpi,(char *)"EUR")) != 0 )
{
btceur = jdouble(obj,(char *)"rate_float") * SATOSHIDEN;
pricebits[3] = ((btceur / 10000) & 0xffffffff);
}
}
free_json(pjson);
dbtcusd = (double)pricebits[1]/10000;
dbtcgbp = (double)pricebits[2]/10000;
dbtceur = (double)pricebits[3]/10000;
fprintf(stderr,"BTC/USD %.4f, BTC/GBP %.4f, BTC/EUR %.4f GBPUSD %.6f, EURUSD %.6f EURGBP %.6f\n",dbtcusd,dbtcgbp,dbtceur,dbtcusd/dbtcgbp,dbtcusd/dbtceur,dbtcgbp/dbtceur);
return(0);
}
return(-1);
}
// komodo_cbopretupdate() obtains the external price data and encodes it into Mineropret, which will then be used by the miner and validation
// save history, use new data to approve past rejection, where is the auto-reconsiderblock?
// 51% correlation, smoothing
void komodo_cbopretupdate()
{
static uint32_t lasttime,lastcrypto,lastbtc;
static uint32_t pricebits[4],cryptoprices[sizeof(Cryptos)/sizeof(*Cryptos)],forexprices[sizeof(Forex)/sizeof(*Forex)];
int32_t size; uint32_t now = (uint32_t)time(NULL);
if ( (ASSETCHAINS_CBOPRET & 1) != 0 )
{
if ( komodo_nextheight() > 333 )
ASSETCHAINS_CBOPRET = 7;
size = PRICES_SIZEBIT0;
if ( (ASSETCHAINS_CBOPRET & 2) != 0 )
size += sizeof(forexprices);
if ( (ASSETCHAINS_CBOPRET & 4) != 0 )
size += sizeof(cryptoprices);
if ( Mineropret.size() < size )
Mineropret.resize(size);
size = PRICES_SIZEBIT0;
if ( now > lastbtc+120 && get_btcusd(pricebits) == 0 )
{
memcpy(Mineropret.data(),pricebits,PRICES_SIZEBIT0);
lastbtc = (uint32_t)time(NULL);
}
if ( (ASSETCHAINS_CBOPRET & 2) != 0 )
{
if ( now > lasttime+3600*5 || forexprices[0] == 0 )
{
get_dailyfx(forexprices);
memcpy(&Mineropret.data()[size],forexprices,sizeof(forexprices));
lasttime = (uint32_t)time(NULL);
}
size += sizeof(forexprices);
}
if ( (ASSETCHAINS_CBOPRET & 4) != 0 )
{
if ( now > lastcrypto+100 )
{
get_cryptoprices(cryptoprices,Cryptos,(int32_t)(sizeof(Cryptos)/sizeof(*Cryptos)));
memcpy(&Mineropret.data()[size],cryptoprices,sizeof(cryptoprices));
lastcrypto = (uint32_t)time(NULL);
}
size += sizeof(cryptoprices);
}
//int32_t i; for (i=0; i<Mineropret.size(); i++)
// fprintf(stderr,"%02x",Mineropret[i]);
//fprintf(stderr," <- set Mineropret[%d]\n",(int32_t)Mineropret.size());
/*
if ( (ASSETCHAINS_CBOPRET & 4) != 0 )
{
get_currencies(Metals,(int32_t)(sizeof(Metals)/sizeof(*Metals)));
}
if ( (ASSETCHAINS_CBOPRET & 32) != 0 )
{
get_stocks(Markets,(int32_t)(sizeof(Markets)/sizeof(*Markets)));
}
if ( (ASSETCHAINS_CBOPRET & 64) != 0 )
{
get_stocks(Techstocks,(int32_t)(sizeof(Techstocks)/sizeof(*Techstocks)));
}*/
}
}

View File

@@ -50,6 +50,7 @@ int32_t KOMODO_INSYNC,KOMODO_LASTMINED,prevKOMODO_LASTMINED,KOMODO_CCACTIVATE,JU
std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY,ASSETCHAINS_SCRIPTPUB,NOTARY_ADDRESS,WHITELIST_ADDRESS,ASSETCHAINS_SELFIMPORT,ASSETCHAINS_CCLIB;
uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEYHASH[20],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW,NUM_NOTARIES,ASSETCHAINS_MARMARA;
bool VERUS_MINTBLOCKS;
std::vector<uint8_t> Mineropret;
char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],ASSETCHAINS_USERPASS[4096],NOTARYADDRS[64][36];
uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,ASSETCHAINS_BEAMPORT,ASSETCHAINS_CODAPORT;
@@ -66,7 +67,7 @@ int64_t MAX_MONEY = 200000000 * 100000000LL;
// spec will use an op_return with CLTV at front and anything after |OP_RETURN|PUSH of rest|OPRETTYPE_TIMELOCK|script|
#define _ASSETCHAINS_TIMELOCKOFF 0xffffffffffffffff
uint64_t ASSETCHAINS_TIMELOCKGTE = _ASSETCHAINS_TIMELOCKOFF;
uint64_t ASSETCHAINS_TIMEUNLOCKFROM = 0, ASSETCHAINS_TIMEUNLOCKTO = 0;
uint64_t ASSETCHAINS_TIMEUNLOCKFROM = 0, ASSETCHAINS_TIMEUNLOCKTO = 0,ASSETCHAINS_CBOPRET=0;
uint64_t ASSETCHAINS_LASTERA = 1;
uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_DECAY[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS];

View File

@@ -1664,11 +1664,12 @@ uint64_t komodo_ac_block_subsidy(int nHeight)
}
extern int64_t MAX_MONEY;
void komodo_cbopretupdate();
void komodo_args(char *argv0)
{
extern const char *Notaries_elected1[][2];
std::string name,addn; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[8192],disablebits[32],*extraptr=0; FILE *fp; uint64_t val; uint16_t port; int32_t i,nonz=0,baseid,len,n,extralen = 0; uint64_t ccenables[256];
std::string name,addn,hexstr; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[8192],disablebits[32],*extraptr=0; FILE *fp; uint64_t val; uint16_t port; int32_t i,nonz=0,baseid,len,n,extralen = 0; uint64_t ccenables[256];
IS_KOMODO_NOTARY = GetBoolArg("-notary", false);
IS_STAKED_NOTARY = GetArg("-stakednotary", -1);
if ( IS_STAKED_NOTARY != -1 && IS_KOMODO_NOTARY == true ) {
@@ -1810,6 +1811,16 @@ void komodo_args(char *argv0)
ASSETCHAINS_BEAMPORT = GetArg("-ac_beam",0);
ASSETCHAINS_CODAPORT = GetArg("-ac_coda",0);
ASSETCHAINS_MARMARA = GetArg("-ac_marmara",0);
ASSETCHAINS_CBOPRET = GetArg("-ac_cbopret",0);
hexstr = GetArg("-ac_mineropret","");
if ( hexstr.size() != 0 )
{
Mineropret.resize(hexstr.size()/2);
decode_hex(Mineropret.data(),hexstr.size()/2,(char *)hexstr.c_str());
for (i=0; i<Mineropret.size(); i++)
fprintf(stderr,"%02x",Mineropret[i]);
fprintf(stderr," Mineropret\n");
}
if ( ASSETCHAINS_COMMISSION != 0 && ASSETCHAINS_FOUNDERS_REWARD != 0 )
{
fprintf(stderr,"cannot use founders reward and commission on the same chain.\n");
@@ -1948,7 +1959,7 @@ void komodo_args(char *argv0)
fprintf(stderr,"-ac_script and -ac_marmara are mutually exclusive\n");
exit(0);
}
if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1 || ASSETCHAINS_SELFIMPORT.size() > 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF|| ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LWMAPOS != 0 || ASSETCHAINS_LASTERA > 0 || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 || ASSETCHAINS_MARMARA != 0 || nonz > 0 || ASSETCHAINS_CCLIB.size() > 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 || ASSETCHAINS_NOTARY_PAY[0] != 0 || ASSETCHAINS_BLOCKTIME != 60 )
if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1 || ASSETCHAINS_SELFIMPORT.size() > 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF|| ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LWMAPOS != 0 || ASSETCHAINS_LASTERA > 0 || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 || ASSETCHAINS_MARMARA != 0 || nonz > 0 || ASSETCHAINS_CCLIB.size() > 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 || ASSETCHAINS_NOTARY_PAY[0] != 0 || ASSETCHAINS_BLOCKTIME != 60 || ASSETCHAINS_CBOPRET != 0 || Mineropret.size() != 0 )
{
fprintf(stderr,"perc %.4f%% ac_pub=[%02x%02x%02x...] acsize.%d\n",dstr(ASSETCHAINS_COMMISSION)*100,ASSETCHAINS_OVERRIDE_PUBKEY33[0],ASSETCHAINS_OVERRIDE_PUBKEY33[1],ASSETCHAINS_OVERRIDE_PUBKEY33[2],(int32_t)ASSETCHAINS_SCRIPTPUB.size());
extraptr = extrabuf;
@@ -2048,6 +2059,17 @@ void komodo_args(char *argv0)
}
if ( ASSETCHAINS_BLOCKTIME != 60 )
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_BLOCKTIME),(void *)&ASSETCHAINS_BLOCKTIME);
if ( Mineropret.size() != 0 )
{
for (i=0; i<Mineropret.size(); i++)
extraptr[extralen++] = Mineropret[i];
}
if ( ASSETCHAINS_CBOPRET != 0 )
{
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_CBOPRET),(void *)&ASSETCHAINS_CBOPRET);
komodo_cbopretupdate(); // will set Mineropret
fprintf(stderr,"This blockchain uses data produced from CoinDesk Bitcoin Price Index\n");
}
}
addn = GetArg("-seednode","");

View File

@@ -1014,6 +1014,15 @@ bool ContextualCheckCoinbaseTransaction(const CTransaction& tx, const int nHeigh
}
return(false);
}
else if ( ASSETCHAINS_MARMARA != 0 && nHeight > 0 && (nHeight & 1) == 0 )
{
}
else if ( ASSETCHAINS_CBOPRET != 0 && nHeight > 0 && tx.vout.size() > 0 )
{
if ( komodo_opretvalidate(nHeight,tx.vout[tx.vout.size()-1].scriptPubKey) < 0 )
return(false);
}
return(true);
}
@@ -4111,7 +4120,14 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
GetMainSignals().BlockChecked(*pblock, state);
if (!rv) {
if (state.IsInvalid())
{
InvalidBlockFound(pindexNew, state);
/*if ( ASSETCHAINS_CBOPRET != 0 )
{
pindexNew->nStatus &= ~BLOCK_FAILED_MASK;
fprintf(stderr,"reconsiderblock %d\n",(int32_t)pindexNew->GetHeight());
}*/
}
return error("ConnectTip(): ConnectBlock %s failed", pindexNew->GetBlockHash().ToString());
}
mapBlockSource.erase(pindexNew->GetBlockHash());
@@ -5202,7 +5218,7 @@ bool AcceptBlockHeader(int32_t *futureblockp,const CBlockHeader& block, CValidat
miSelf->second = pindex = AddToBlockIndex(block);
if (ppindex)
*ppindex = pindex;
if ( pindex != 0 && pindex->nStatus & BLOCK_FAILED_MASK )
if ( pindex != 0 && (pindex->nStatus & BLOCK_FAILED_MASK) != 0 )
{
if ( ASSETCHAINS_CC == 0 )//&& (ASSETCHAINS_PRIVATE == 0 || KOMODO_INSYNC >= Params().GetConsensus().vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight) )
return state.Invalid(error("%s: block is marked invalid", __func__), 0, "duplicate");

View File

@@ -155,6 +155,7 @@ CScript MarmaraCoinbaseOpret(uint8_t funcid,int32_t height,CPubKey pk);
uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector<int8_t> &NotarisationNotaries, uint32_t timestamp, int32_t height, uint8_t *script, int32_t len);
int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
int32_t komodo_getnotarizedheight(uint32_t timestamp,int32_t height, uint8_t *script, int32_t len);
CScript komodo_mineropret(int32_t nHeight);
CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32_t gpucount, bool isStake)
{
@@ -723,7 +724,14 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
fprintf(stderr, "Created notary payment coinbase totalsat.%lu\n",totalsats);
} else fprintf(stderr, "vout 2 of notarisation is not OP_RETURN scriptlen.%i\n", scriptlen);
}
if ( ASSETCHAINS_CBOPRET != 0 )
{
int32_t numv = (int32_t)txNew.vout.size();
txNew.vout.resize(numv+1);
txNew.vout[numv].nValue = 0;
txNew.vout[numv].scriptPubKey = komodo_mineropret(nHeight);
//printf("autocreate commision/cbopret.%lld vout[%d]\n",(long long)ASSETCHAINS_CBOPRET,(int32_t)txNew.vout.size());
}
pblock->vtx[0] = txNew;
pblocktemplate->vTxFees[0] = -nFees;
@@ -941,6 +949,7 @@ void komodo_sendmessage(int32_t minpeers,int32_t maxpeers,const char *message,st
continue;
if ( numsent < minpeers || (rand() % 10) == 0 )
{
//fprintf(stderr,"pushmessage\n");
pnode->PushMessage(message,payload);
if ( numsent++ > maxpeers )
break;

21
src/tui/LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Anton Lysakov
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

58
src/tui/README.md Normal file
View File

@@ -0,0 +1,58 @@
# Komodo Cryptoconditons Terminal User Interfaces (aka TUIs)
These tools creating for demonstration and partial automation of Komodo cryptoconditions modules testing. (RogueCC game, AssetsCC, OraclesCC, GatewaysCC, MarmaraCC, ...)
Developer installation (on Ubuntu 18.04) :
Python3 required for execution:
* `sudo apt-get install python3.6 python3-pip libgnutls28-dev`
pip packages needed:
* `pip3 install setuptools wheel slick-bitcoinrpc`
* or `pip3 install -r requirements.txt`
Starting:
# TUI for RogueCC
If you're looking for player 3 in 1 (daemon + game + TUI) multiOS bundle - please check `releases` of this repo.
`python3 rogue_tui.py`
![alt text](https://i.imgur.com/gkcxMGt.png)
# TUI for OraclesCC
Have files uploader/downloader functionality - also there is a AWS branch for AWS certificates uploading demonstration
`python3 oracles_cc_tui.py`
![alt text](https://i.imgur.com/tfHwRqc.png)
# TUI for GatewaysCC
![alt text](https://i.imgur.com/c8DPfpp.png)
`python3 gateways_creation_tui.py`
`python3 gateways_usage_tui.py`
At the moment raw version of manual gateway how-to guide can be found here: https://docs.komodoplatform.com/cc/contracts/gateways/scenarios/tutorial.html I advice to read it before you start use this tool to understand the flow.
# TUI for MarmaraCC
`python3 marmara_tui.py`
![alt text](https://i.imgur.com/uonMWHl.png)
# TUI for AssetsCC (not much finished)
`python3 assets_cc_tui.py`
Before execution be sure than daemon for needed AC up.

39
src/tui/lib/logo.txt Normal file
View File

@@ -0,0 +1,39 @@
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0xlc:ldOKNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0xo:,........';lxOXNMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMWNKkoc,..................':ox0XWMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMWNKkdc;............................,:ok0NWMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMWNKOdl;'.....................................,cdkKNWMMMMMMMMMMMMMM
MMMMMMMMMMMMMW0c'..............................................';kNMMMMMMMMMMMMM
MMMMMMMMMMMMMK:......................';:c:'......................,kWMMMMMMMMMMMM
MMMMMMMMMMMMXl...................;cdkKNWWNXOdl;'..................;OWMMMMMMMMMMM
MMMMMMMMMMMNo...............,cok0XWMMMMMMMMMMWNKkdc;'..............:KMMMMMMMMMMM
MMMMMMMMMMWx'...........;ox0XWMMMMMMMMMMMMMMMMMMMMWNKko:............lXMMMMMMMMMM
MMMMMMMMMWk,...........lXWMMMMMMMMMMMMWWWWMMMMMMMMMMMMMNx'...........oNMMMMMMMMM
MMMMMMMMW0;...........cKMMMMMMMMMWNXOdl::cdkKNWMMMMMMMMMNo...........'xWMMMMMMMM
MMMMMMMMKc...........;0WMMMMMWN0xl:,........';ldOXWMMMMMMXl...........,OWMMMMMMM
MMMMMMMXl...........,kWMMMMMMKl..................;OWMMMMMMK:...........;0MMMMMMM
MMMMMMNd...........'xNMMMMMMXl....................:0WMMMMMWO;...........cKMMMMMM
MMMMMNx'...........oNMMMMMMNd......................cKMMMMMMWk'...........lXMMMMM
MMMMWO,...........lXMMMMMMWx'.......................oXMMMMMMNd'...........dNMMMM
MMMMXc...........,OWMMMMMMK:........................,kWMMMMMMKc...........;0MMMM
MMMMWx'...........oXMMMMMMNd........................cKMMMMMMWk,...........lXMMMM
MMMMMNd...........'dNMMMMMMXl......................:0MMMMMMWO;...........cKMMMMM
MMMMMMXl...........,kWMMMMMMKc....................,OWMMMMMM0:...........;0MMMMMM
MMMMMMMKc...........;OWMMMMMW0:..................,kWMMMMMMXc...........,OWMMMMMM
MMMMMMMM0;...........:KMMMMMMWKko:,..........';lx0WMMMMMMNo...........'xWMMMMMMM
MMMMMMMMWk,...........lXMMMMMMMMWWXOxl:,,;cdOKNWMMMMMMMMNx'...........dNMMMMMMMM
MMMMMMMMMWx'...........dNMMMMMMMMMMMMWNXXNWMMMMMMMMMMMMWk,...........lXMMMMMMMMM
MMMMMMMMMMNo............cx0XWMMMMMMMMMMMMMMMMMMMMMMWN0kl,...........cKMMMMMMMMMM
MMMMMMMMMMMXl..............,:ok0XWMMMMMMMMMMMMWNKkdc;..............;0WMMMMMMMMMM
MMMMMMMMMMMMK:..................,cokKNWMMWNKOdl;'.................,kWMMMMMMMMMMM
MMMMMMMMMMMMWO;......................;cool;'.....................'xNMMMMMMMMMMMM
MMMMMMMMMMMMMWk;................................................'dNMMMMMMMMMMMMM
MMMMMMMMMMMMMMWXOxl;'.......................................,cdkKWMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMWNKOdc;..............................,cok0NWMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMWNKkoc,....................,:ox0XWMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0ko:,..........':lx0XWMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0xl:,,;ldOKNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNNXNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM

129
src/tui/lib/rpclib.py Normal file
View File

@@ -0,0 +1,129 @@
import http
from slickrpc import Proxy
# RPC connection
def rpc_connect(rpc_user, rpc_password, port):
try:
rpc_connection = Proxy("http://%s:%s@127.0.0.1:%d"%(rpc_user, rpc_password, port))
except Exception:
raise Exception("Connection error! Probably no daemon on selected port.")
return rpc_connection
# Non CC calls
def getinfo(rpc_connection):
try:
getinfo = rpc_connection.getinfo()
except Exception:
raise Exception("Connection error!")
return getinfo
def sendrawtransaction(rpc_connection, hex):
tx_id = rpc_connection.sendrawtransaction(hex)
return tx_id
def gettransaction(rpc_connection, tx_id):
transaction_info = rpc_connection.gettransaction(tx_id)
return transaction_info
def getrawtransaction(rpc_connection, tx_id):
rawtransaction = rpc_connection.getrawtransaction(tx_id)
return rawtransaction
def getbalance(rpc_connection):
balance = rpc_connection.getbalance()
return balance
# Token CC calls
def token_create(rpc_connection, name, supply, description):
token_hex = rpc_connection.tokencreate(name, supply, description)
return token_hex
def token_info(rpc_connection, token_id):
token_info = rpc_connection.tokeninfo(token_id)
return token_info
#TODO: have to add option with pubkey input
def token_balance(rpc_connection, token_id):
token_balance = rpc_connection.tokenbalance(token_id)
return token_balance
def token_list(rpc_connection):
token_list = rpc_connection.tokenlist()
return token_list
def token_convert(rpc_connection, evalcode, token_id, pubkey, supply):
token_convert_hex = rpc_connection.tokenconvert(evalcode, token_id, pubkey, supply)
return token_convert_hex
def get_rawmempool(rpc_connection):
mempool = rpc_connection.getrawmempool()
return mempool
# Oracle CC calls
def oracles_create(rpc_connection, name, description, data_type):
oracles_hex = rpc_connection.oraclescreate(name, description, data_type)
return oracles_hex
def oracles_register(rpc_connection, oracle_id, data_fee):
oracles_register_hex = rpc_connection.oraclesregister(oracle_id, data_fee)
return oracles_register_hex
def oracles_subscribe(rpc_connection, oracle_id, publisher_id, data_fee):
oracles_subscribe_hex = rpc_connection.oraclessubscribe(oracle_id, publisher_id, data_fee)
return oracles_subscribe_hex
def oracles_info(rpc_connection, oracle_id):
oracles_info = rpc_connection.oraclesinfo(oracle_id)
return oracles_info
def oracles_data(rpc_connection, oracle_id, hex_string):
oracles_data = rpc_connection.oraclesdata(oracle_id, hex_string)
return oracles_data
def oracles_list(rpc_connection):
oracles_list = rpc_connection.oracleslist()
return oracles_list
def oracles_samples(rpc_connection, oracletxid, batonutxo, num):
oracles_sample = rpc_connection.oraclessamples(oracletxid, batonutxo, num)
return oracles_sample
# Gateways CC calls
# Arguments changing dynamically depends of M N, so supposed to wrap it this way
# token_id, oracle_id, coin_name, token_supply, M, N + pubkeys for each N
def gateways_bind(rpc_connection, *args):
gateways_bind_hex = rpc_connection.gatewaysbind(*args)
return gateways_bind_hex
def gateways_deposit(rpc_connection, gateway_id, height, coin_name,\
coin_txid, claim_vout, deposit_hex, proof, dest_pub, amount):
gateways_deposit_hex = rpc_connection.gatewaysdeposit(gateway_id, height, coin_name,\
coin_txid, claim_vout, deposit_hex, proof, dest_pub, amount)
return gateways_deposit_hex
def gateways_claim(rpc_connection, gateway_id, coin_name, deposit_txid, dest_pub, amount):
gateways_claim_hex = rpc_connection.gatewaysclaim(gateway_id, coin_name, deposit_txid, dest_pub, amount)
return gateways_claim_hex
def gateways_withdraw(rpc_connection, gateway_id, coin_name, withdraw_pub, amount):
gateways_withdraw_hex = rpc_connection.gatewayswithdraw(gateway_id, coin_name, withdraw_pub, amount)
return gateways_withdraw_hex

1974
src/tui/lib/tuilib.py Executable file

File diff suppressed because it is too large Load Diff

8
src/tui/requirements.txt Normal file
View File

@@ -0,0 +1,8 @@
configobj==5.0.6
pip==9.0.1
pycurl==7.43.0.2
setuptools==39.0.1
six==1.12.0
slick-bitcoinrpc==0.1.4
ujson==1.35
wheel==0.32.3

67
src/tui/tui_assets.py Executable file
View File

@@ -0,0 +1,67 @@
#!/usr/bin/env python3
from lib import rpclib, tuilib
import os
import time
header = "\
___ _ _____ \n\
/ _ \ | | / __ \\\n\
/ /_\ \ ___ ___ ___ | |_ ___ | / \/\n\
| _ |/ __|/ __| / _ \| __|/ __|| | \n\
| | | |\__ \\\__ \| __/| |_ \__ \| \__/\\\n\
\_| |_/|___/|___/ \___| \__||___/ \____/\n"
menuItems = [
{"Check current connection": tuilib.getinfo_tui},
{"Check mempool": tuilib.print_mempool},
{"Print tokens list": tuilib.print_tokens_list},
{"Check my tokens balances" : tuilib.print_tokens_balances},
# transfer tokens (pre-print tokens balances)
{"Create token": tuilib.token_create_tui},
# trading zone - pre-print token orders - possible to open order or fill existing one
{"Exit": exit}
]
def main():
while True:
os.system('clear')
print(tuilib.colorize(header, 'pink'))
print(tuilib.colorize('CLI version 0.2 by Anton Lysakov\n', 'green'))
for item in menuItems:
print(tuilib.colorize("[" + str(menuItems.index(item)) + "] ", 'blue') + list(item.keys())[0])
choice = input(">> ")
try:
if int(choice) < 0:
raise ValueError
# Call the matching function
if list(menuItems[int(choice)].keys())[0] == "Exit":
list(menuItems[int(choice)].values())[0]()
else:
list(menuItems[int(choice)].values())[0](rpc_connection)
except (ValueError, IndexError):
pass
if __name__ == "__main__":
while True:
try:
print(tuilib.colorize("Welcome to the GatewaysCC TUI!\n"
"Please provide asset chain RPC connection details for initialization", "blue"))
rpc_connection = tuilib.rpc_connection_tui()
rpclib.getinfo(rpc_connection)
except Exception:
print(tuilib.colorize("Cant connect to RPC! Please re-check credentials.", "pink"))
else:
print(tuilib.colorize("Succesfully connected!\n", "green"))
with (open("lib/logo.txt", "r")) as logo:
for line in logo:
print(line, end='')
time.sleep(0.04)
print("\n")
break
main()

View File

@@ -0,0 +1,67 @@
#!/usr/bin/env python3
from lib import rpclib, tuilib
import os
import time
header = "\
_____ _ _____ _____ \n\
| __ \ | | / __ \/ __ \\\n\
| | \/ __ _| |_ _____ ____ _ _ _ ___| / \/| / \/\n\
| | __ / _` | __/ _ \ \ /\ / / _` | | | / __| | | | \n\
| |_\ \ (_| | || __/\ V V / (_| | |_| \__ \ \__/\| \__/\\\n\
\____/\__,_|\__\___| \_/\_/ \__,_|\__, |___/\____/ \____/\n\
__/ | \n\
|___/ \n"
menuItems = [
{"Check current connection": tuilib.getinfo_tui},
{"Check mempool": tuilib.print_mempool},
{"Create token": tuilib.token_create_tui},
{"Create oracle": tuilib.oracle_create_tui},
{"Register as publisher for oracle": tuilib.oracle_register_tui},
{"Subscribe on oracle (+UTXO generator)": tuilib.oracle_subscription_utxogen},
{"Bind Gateway": tuilib.gateways_bind_tui},
{"Exit": exit}
]
def main():
while True:
os.system('clear')
print(tuilib.colorize(header, 'pink'))
print(tuilib.colorize('CLI version 0.2\n', 'green'))
for item in menuItems:
print(tuilib.colorize("[" + str(menuItems.index(item)) + "] ", 'blue') + list(item.keys())[0])
choice = input(">> ")
try:
if int(choice) < 0:
raise ValueError
# Call the matching function
if list(menuItems[int(choice)].keys())[0] == "Exit":
list(menuItems[int(choice)].values())[0]()
else:
list(menuItems[int(choice)].values())[0](rpc_connection)
except (ValueError, IndexError):
pass
if __name__ == "__main__":
while True:
try:
print(tuilib.colorize("Welcome to the GatewaysCC TUI!\n"
"Please provide asset chain RPC connection details for initialization", "blue"))
rpc_connection = tuilib.rpc_connection_tui()
rpclib.getinfo(rpc_connection)
except Exception:
print(tuilib.colorize("Cant connect to RPC! Please re-check credentials.", "pink"))
else:
print(tuilib.colorize("Succesfully connected!\n", "green"))
with (open("lib/logo.txt", "r")) as logo:
for line in logo:
print(line, end='')
time.sleep(0.04)
print("\n")
break
main()

96
src/tui/tui_gateways_usage.py Executable file
View File

@@ -0,0 +1,96 @@
#!/usr/bin/env python3
from lib import rpclib, tuilib
import os, time
header = "\
_____ _ _____ _____ \n\
| __ \ | | / __ \/ __ \\\n\
| | \/ __ _| |_ _____ ____ _ _ _ ___| / \/| / \/\n\
| | __ / _` | __/ _ \ \ /\ / / _` | | | / __| | | | \n\
| |_\ \ (_| | || __/\ V V / (_| | |_| \__ \ \__/\| \__/\\\n\
\____/\__,_|\__\___| \_/\_/ \__,_|\__, |___/\____/ \____/\n\
__/ | \n\
|___/ \n"
menuItems = [
{"Check connection to assetchain": tuilib.getinfo_tui},
{"Check assetchain mempool": tuilib.print_mempool},
{"Check connection to KMD": tuilib.getinfo_tui},
{"Connect to KMD daemon": tuilib.rpc_kmd_connection_tui},
{"Send KMD gateway deposit transaction": tuilib.gateways_send_kmd},
{"Execute gateways deposit": tuilib.gateways_deposit_tui},
{"Execute gateways claim": tuilib.gateways_claim_tui},
{"Execute gateways withdrawal": tuilib.gateways_withdrawal_tui},
{"Exit": exit}
]
def main():
while True:
os.system('clear')
print(tuilib.colorize(header, 'pink'))
print(tuilib.colorize('CLI version 0.2\n', 'green'))
for item in menuItems:
print(tuilib.colorize("[" + str(menuItems.index(item)) + "] ", 'blue') + list(item.keys())[0])
choice = input(">> ")
try:
if int(choice) < 0:
raise ValueError
# Call the matching function
if list(menuItems[int(choice)].keys())[0] == "Exit":
list(menuItems[int(choice)].values())[0]()
# We have to call KMD specific functions with connection to KMD daemon
elif list(menuItems[int(choice)].keys())[0] == "Connect to KMD daemon":
rpc_connection_kmd = list(menuItems[int(choice)].values())[0]()
elif list(menuItems[int(choice)].keys())[0] == "Check connection to KMD":
while True:
try:
list(menuItems[int(choice)].values())[0](rpc_connection_kmd)
break
except Exception as e:
print("Please connect to KMD daemon first!")
input("Press [Enter] to continue...")
break
elif list(menuItems[int(choice)].keys())[0] == "Send KMD gateway deposit transaction":
while True:
try:
list(menuItems[int(choice)].values())[0](rpc_connection_kmd)
break
except Exception as e:
print(e)
print("Please connect to KMD daemon first!")
input("Press [Enter] to continue...")
break
elif list(menuItems[int(choice)].keys())[0] == "Execute gateways deposit":
while True:
try:
list(menuItems[int(choice)].values())[0](rpc_connection, rpc_connection_kmd)
break
except Exception as e:
print(e)
print("Please connect to KMD daemon first!")
input("Press [Enter] to continue...")
break
else:
list(menuItems[int(choice)].values())[0](rpc_connection)
except (ValueError, IndexError):
pass
if __name__ == "__main__":
while True:
try:
print(tuilib.colorize("Welcome to the GatewaysCC TUI!\nPlease provide RPC connection details for initialization", "blue"))
rpc_connection = tuilib.rpc_connection_tui()
rpclib.getinfo(rpc_connection)
except Exception:
print(tuilib.colorize("Cant connect to RPC! Please re-check credentials.", "pink"))
else:
print(tuilib.colorize("Succesfully connected!\n", "green"))
with (open("lib/logo.txt", "r")) as logo:
for line in logo:
print(line, end='')
time.sleep(0.04)
print("\n")
break
main()

68
src/tui/tui_marmara.py Executable file
View File

@@ -0,0 +1,68 @@
#!/usr/bin/env python3
from lib import rpclib, tuilib
import os
import time
header = "\
___ ___ _____ _ _ _____ \n\
| \/ | |_ _| | | |_ _|\n\
| . . | __ _ _ __ _ __ ___ __ _ _ __ __ _ | | | | | | | |\n\
| |\/| |/ _` | '__| '_ ` _ \ / _` | '__/ _` | | | | | | | | |\n\
| | | | (_| | | | | | | | | (_| | | | (_| | | | | |_| |_| |_\n\
\_| |_/\__,_|_| |_| |_| |_|\__,_|_| \__,_| \_/ \___/ \___/\n"
menuItems = [
{"Check current connection": tuilib.getinfo_tui},
{"Check mempool": tuilib.print_mempool},
{"Check MARMARA info": tuilib.marmara_info_tui},
{"Lock funds for MARMARA": tuilib.marmara_lock_tui},
{"Request MARMARA cheque": tuilib.marmara_receive_tui},
{"Issue MARMARA cheque": tuilib.marmara_issue_tui},
{"Check credit loop status": tuilib.marmara_creditloop_tui},
{"Settle MARMARA loop": tuilib.marmara_settlement_tui},
{"Exit": exit}
]
def main():
while True:
os.system('clear')
print(tuilib.colorize(header, 'pink'))
print(tuilib.colorize('CLI version 0.1\n', 'green'))
for item in menuItems:
print(tuilib.colorize("[" + str(menuItems.index(item)) + "] ", 'blue') + list(item.keys())[0])
choice = input(">> ")
try:
if int(choice) < 0:
raise ValueError
# Call the matching function
if list(menuItems[int(choice)].keys())[0] == "Exit":
list(menuItems[int(choice)].values())[0]()
else:
list(menuItems[int(choice)].values())[0](rpc_connection)
except (ValueError, IndexError):
pass
if __name__ == "__main__":
while True:
chain = input("Input assetchain name (-ac_name= value) you want to work with: ")
try:
print(tuilib.colorize("Welcome to the MarmaraCC TUI!\n"
"Please provide asset chain RPC connection details for initialization", "blue"))
rpc_connection = tuilib.def_credentials(chain)
rpclib.getinfo(rpc_connection)
except Exception:
print(tuilib.colorize("Cant connect to RPC! Please re-check credentials.", "pink"))
else:
print(tuilib.colorize("Succesfully connected!\n", "green"))
with (open("lib/logo.txt", "r")) as logo:
for line in logo:
print(line, end='')
time.sleep(0.04)
print("\n")
break
main()

67
src/tui/tui_oracles.py Executable file
View File

@@ -0,0 +1,67 @@
#!/usr/bin/env python3
from lib import rpclib, tuilib
import os
import time
header = "\
_____ _ _____ _____ \n\
| _ | | | / __ \/ __ \\\n\
| | | | _ __ __ _ ___ | | ___ ___ | / \/| / \/\n\
| | | || '__| / _` | / __|| | / _ \/ __|| | | |\n\
\ \_/ /| | | (_| || (__ | || __/\__ \| \__/\| \__/\\\n\
\___/ |_| \__,_| \___||_| \___||___/ \____/ \____/\n"
menuItems = [
# TODO: Have to implement here native oracle file uploader / reader, should be dope
# TODO: data publisher / converter for different types
{"Check current connection": tuilib.getinfo_tui},
{"Check mempool": tuilib.print_mempool},
{"Create oracle": tuilib.oracle_create_tui},
{"Register as publisher for oracle": tuilib.oracle_register_tui},
{"Subscribe on oracle (+UTXO generator)": tuilib.oracle_subscription_utxogen},
{"Upload file to oracle": tuilib.convert_file_oracle_D},
{"Display list of files uploaded to this AC": tuilib.display_files_list},
{"Download files from oracle": tuilib.files_downloader},
{"Exit": exit}
]
def main():
while True:
os.system('clear')
print(tuilib.colorize(header, 'pink'))
print(tuilib.colorize('CLI version 0.2 by Anton Lysakov\n', 'green'))
for item in menuItems:
print(tuilib.colorize("[" + str(menuItems.index(item)) + "] ", 'blue') + list(item.keys())[0])
choice = input(">> ")
try:
if int(choice) < 0:
raise ValueError
# Call the matching function
if list(menuItems[int(choice)].keys())[0] == "Exit":
list(menuItems[int(choice)].values())[0]()
else:
list(menuItems[int(choice)].values())[0](rpc_connection)
except (ValueError, IndexError):
pass
if __name__ == "__main__":
while True:
try:
print(tuilib.colorize("Welcome to the GatewaysCC TUI!\n"
"Please provide asset chain RPC connection details for initialization", "blue"))
rpc_connection = tuilib.rpc_connection_tui()
rpclib.getinfo(rpc_connection)
except Exception:
print(tuilib.colorize("Cant connect to RPC! Please re-check credentials.", "pink"))
else:
print(tuilib.colorize("Succesfully connected!\n", "green"))
with (open("lib/logo.txt", "r")) as logo:
for line in logo:
print(line, end='')
time.sleep(0.04)
print("\n")
break
main()

116
src/tui/tui_rogue.py Executable file
View File

@@ -0,0 +1,116 @@
#!/usr/bin/env python3
from lib import rpclib, tuilib
import os
import time
import sys
import platform
header = "\
______ _____ _____ \n\
| ___ \ / __ \/ __ \\\n\
| |_/ /___ __ _ _ _ ___| / \/| / \/\n\
| // _ \ / _` | | | |/ _ \ | | |\n\
| |\ \ (_) | (_| | |_| | __/ \__/\| \__/\\\n\
\_| \_\___/ \__, |\__,_|\___|\____/ \____/\n\
__/ |\n\
|___/\n"
menuItems = [
{"Check current connection": tuilib.getinfo_tui},
{"Check mempool": tuilib.print_mempool},
{"Check my warriors list": tuilib.print_players_list},
{"Transfer warrior to other pubkey": tuilib.warrior_trasnfer},
{"TOP-20 ROGUE Warriors": tuilib.top_warriors_rating},
{"Set warriors name": tuilib.set_warriors_name},
{"Start singleplayer training game (creating, registering and starting game)": tuilib.rogue_newgame_singleplayer},
{"Create multiplayer game": tuilib.rogue_newgame_multiplayer},
{"Join (register) multiplayer game": tuilib.rogue_join_multiplayer_game},
{"Check my multiplayer games status / start": tuilib.play_multiplayer_game},
{"Check if somebody wants to buy your warrior (incoming bids)": tuilib.print_icoming_bids},
{"Place order to sell warrior": tuilib.sell_warrior},
{"Place order to buy someones warrior": tuilib.place_bid_on_warriror},
{"Check if somebody selling warrior": tuilib.find_warriors_asks},
{"Check / cancel my warriors trade orders": tuilib.warriors_orders_check},
# {"Manually exit the game (bailout)": "test"},
# {"Manually claim ROGUE coins for game (highlander)": "test"},
{"Exit": tuilib.exit}
]
def main():
while True:
operating_system = platform.system()
if operating_system != 'Win64' and operating_system != 'Windows':
os.system('clear')
else:
os.system('cls')
print(tuilib.colorize(header, 'pink'))
print(tuilib.colorize('TUI v0.0.3\n', 'green'))
menu_items_counter = 0
for item in menuItems:
if menu_items_counter == 0:
print("\nUtility:\n")
menu_items_counter = menu_items_counter + 1
print(tuilib.colorize("[" + str(menuItems.index(item)) + "] ", 'blue') + list(item.keys())[0])
if menu_items_counter == 6:
print("\nNew singleplayer game:\n")
if menu_items_counter == 7:
print("\nMultiplayer games:\n")
if menu_items_counter == 10:
print("\nDEX features:\n")
choice = input(">> ")
try:
if int(choice) < 0:
raise ValueError
# Call the matching function
if list(menuItems[int(choice)].keys())[0] == "Exit":
list(menuItems[int(choice)].values())[0]()
else:
list(menuItems[int(choice)].values())[0](rpc_connection)
except (ValueError, IndexError):
pass
if __name__ == "__main__":
while True:
chain = "ROGUE"
try:
print(tuilib.colorize("Welcome to the RogueCC TUI!\n"
"Please provide asset chain RPC connection details for initialization", "blue"))
rpc_connection = tuilib.def_credentials(chain)
rpclib.getinfo(rpc_connection)
# waiting until chain is in sync
while True:
have_blocks = rpclib.getinfo(rpc_connection)["blocks"]
longest_chain = rpclib.getinfo(rpc_connection)["longestchain"]
if have_blocks != longest_chain:
print(tuilib.colorize("ROGUE not synced yet.", "red"))
print("Have " + str(have_blocks) + " from " + str(longest_chain) + " blocks")
time.sleep(5)
else:
print(tuilib.colorize("Chain is synced!", "green"))
break
# checking if pubkey is set and set valid if not
info = rpclib.getinfo(rpc_connection)
if "pubkey" in info.keys():
print("Pubkey is already set")
else:
valid_address = rpc_connection.getaccountaddress("")
valid_pubkey = rpc_connection.validateaddress(valid_address)["pubkey"]
rpc_connection.setpubkey(valid_pubkey)
print(tuilib.colorize("Pubkey is succesfully set!", "green"))
# copy ROGUE config to current daemon directory if it's not here
tuilib.check_if_config_is_here(rpc_connection, "ROGUE")
except Exception:
print(tuilib.colorize("Cant connect to ROGUE daemon RPC! Please check if daemon is up.", "pink"))
tuilib.exit()
else:
print(tuilib.colorize("Succesfully connected!\n", "green"))
with (open("lib/logo.txt", "r")) as logo:
for line in logo:
print(line, end='')
time.sleep(0.04)
print("\n")
break
main()

96
src/tui/tui_tetris.py Executable file
View File

@@ -0,0 +1,96 @@
#!/usr/bin/env python3
from lib import rpclib, tuilib
import os
import time
import sys
import platform
header = "\
_____ _ _ ______\n\
|_ _| | | (_) | _ \n\
| | ___| |_ _ __ _ ___| | | |__ _ _ __ _ __\n\
| |/ _ \ __| '__| / __| | | / _` | '_ \| '_ \\\n\
| | __/ |_| | | \__ \ |/ / (_| | |_) | |_) |\n\
\_/\___|\__|_| |_|___/___/ \__,_| .__/| .__/\n\
| | | |\n\
|_| |_|"
menuItems = [
{"Check current connection": tuilib.getinfo_tui},
{"Check mempool": tuilib.print_mempool},
{"Start singleplayer tetris game (creating, registering and starting game)": tuilib.rogue_newgame_singleplayer},
{"Exit": tuilib.exit}
]
def main():
while True:
operating_system = platform.system()
if operating_system != 'Win64' and operating_system != 'Windows':
os.system('clear')
else:
os.system('cls')
print(tuilib.colorize(header, 'pink'))
print(tuilib.colorize('TUI v0.0.3\n', 'green'))
menu_items_counter = 0
for item in menuItems:
print(tuilib.colorize("[" + str(menuItems.index(item)) + "] ", 'blue') + list(item.keys())[0])
choice = input(">> ")
try:
if int(choice) < 0:
raise ValueError
# Call the matching function
if list(menuItems[int(choice)].keys())[0] == "Exit":
list(menuItems[int(choice)].values())[0]()
elif list(menuItems[int(choice)].keys())[0] == "Start singleplayer tetris game (creating, registering and starting game)":
list(menuItems[int(choice)].values())[0](rpc_connection, False)
else:
list(menuItems[int(choice)].values())[0](rpc_connection)
except (ValueError, IndexError):
pass
if __name__ == "__main__":
while True:
chain = "GTEST"
try:
print(tuilib.colorize("Welcome to the Tetris TUI!\n"
"Please provide asset chain RPC connection details for initialization", "blue"))
rpc_connection = tuilib.def_credentials(chain)
rpclib.getinfo(rpc_connection)
# waiting until chain is in sync
while True:
have_blocks = rpclib.getinfo(rpc_connection)["blocks"]
longest_chain = rpclib.getinfo(rpc_connection)["longestchain"]
if have_blocks != longest_chain:
print(tuilib.colorize("GTEST not synced yet.", "red"))
print("Have " + str(have_blocks) + " from " + str(longest_chain) + " blocks")
time.sleep(5)
else:
print(tuilib.colorize("Chain is synced!", "green"))
break
# checking if pubkey is set and set valid if not
info = rpclib.getinfo(rpc_connection)
if "pubkey" in info.keys():
print("Pubkey is already set")
else:
valid_address = rpc_connection.getaccountaddress("")
valid_pubkey = rpc_connection.validateaddress(valid_address)["pubkey"]
rpc_connection.setpubkey(valid_pubkey)
print(tuilib.colorize("Pubkey is succesfully set!", "green"))
# copy ROGUE config to current daemon directory if it's not here
tuilib.check_if_config_is_here(rpc_connection, "GTEST")
except Exception:
print(tuilib.colorize("Cant connect to GTEST daemon RPC! Please check if daemon is up.", "pink"))
tuilib.exit()
else:
print(tuilib.colorize("Succesfully connected!\n", "green"))
with (open("lib/logo.txt", "r")) as logo:
for line in logo:
print(line, end='')
time.sleep(0.04)
print("\n")
break
main()