@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
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
289
src/cc/games/prices.c
Normal 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
281
src/cc/games/prices.cpp
Normal 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
208
src/cc/games/prices.h
Normal 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
904
src/cc/games/tetris.c
Normal 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
87
src/cc/games/tetris.cpp
Normal 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
208
src/cc/games/tetris.h
Normal 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
|
||||
|
||||
2419
src/cc/gamescc.cpp
2419
src/cc/gamescc.cpp
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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
8
src/cc/makeprices
Executable 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 ..
|
||||
|
||||
|
||||
@@ -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 ..
|
||||
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -451,4 +451,3 @@ std::string PricesFinish(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
2411
src/cc/tetris.cpp
2411
src/cc/tetris.cpp
File diff suppressed because it is too large
Load Diff
27
src/gui/komodoku/README.md
Normal file
27
src/gui/komodoku/README.md
Normal file
@@ -0,0 +1,27 @@
|
||||
About
|
||||
-----
|
||||
Komodo SudokuCC GUI
|
||||
|
||||
Just solve Sudoku and earn SUDOKU coins!
|
||||
|
||||

|
||||
|
||||
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
BIN
src/gui/komodoku/Roboto-Light.ttf
Executable file
Binary file not shown.
362
src/gui/komodoku/Sudoku.py
Normal file
362
src/gui/komodoku/Sudoku.py
Normal 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()
|
||||
BIN
src/gui/komodoku/background.png
Normal file
BIN
src/gui/komodoku/background.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 301 KiB |
BIN
src/gui/komodoku/board.png
Normal file
BIN
src/gui/komodoku/board.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
41
src/gui/komodoku/sudoku_kmdlib.py
Normal file
41
src/gui/komodoku/sudoku_kmdlib.py
Normal 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))))
|
||||
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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[];
|
||||
|
||||
@@ -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)));
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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","");
|
||||
|
||||
18
src/main.cpp
18
src/main.cpp
@@ -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");
|
||||
|
||||
@@ -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
21
src/tui/LICENSE
Normal 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
58
src/tui/README.md
Normal 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`
|
||||
|
||||

|
||||
|
||||
# TUI for OraclesCC
|
||||
|
||||
Have files uploader/downloader functionality - also there is a AWS branch for AWS certificates uploading demonstration
|
||||
|
||||
`python3 oracles_cc_tui.py`
|
||||
|
||||

|
||||
|
||||
# TUI for GatewaysCC
|
||||
|
||||

|
||||
|
||||
`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`
|
||||
|
||||

|
||||
|
||||
# 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
39
src/tui/lib/logo.txt
Normal 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
129
src/tui/lib/rpclib.py
Normal 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
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
8
src/tui/requirements.txt
Normal 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
67
src/tui/tui_assets.py
Executable 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()
|
||||
|
||||
67
src/tui/tui_gateways_creation.py
Executable file
67
src/tui/tui_gateways_creation.py
Executable 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
96
src/tui/tui_gateways_usage.py
Executable 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
68
src/tui/tui_marmara.py
Executable 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
67
src/tui/tui_oracles.py
Executable 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
116
src/tui/tui_rogue.py
Executable 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
96
src/tui/tui_tetris.py
Executable 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()
|
||||
Reference in New Issue
Block a user