From 7524c64024bf625ffc06bcfd804a1f520c840f18 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 19:06:09 -0400 Subject: [PATCH 01/31] Our intrepid warrior gazed at his Dragon and both knew what was needed --- src/cc/CCinclude.h | 4 +- src/cc/crypto777/OS_portable.h | 42 ++++----- src/cc/includes/curve25519.h | 4 +- src/cc/oracles.cpp | 14 +-- src/komodo.h | 26 +++--- src/komodo_ccdata.h | 16 ++-- src/komodo_defs.h | 4 +- src/komodo_gateway.h | 12 +-- src/komodo_kv.h | 8 +- src/komodo_nSPV.h | 160 ++++++++++++++++----------------- src/komodo_nSPV_fullnode.h | 54 +++++------ src/komodo_nSPV_superlite.h | 50 +++++------ src/komodo_pax.h | 18 ++-- src/komodo_port.c | 14 +-- src/komodo_utils.h | 60 ++++++------- src/notaries_staked.h | 4 +- src/rpc/misc.cpp | 10 +-- src/rpc/server.cpp | 2 +- src/rpc/server.h | 2 +- src/wallet/rpcwallet.cpp | 16 ++-- 20 files changed, 260 insertions(+), 260 deletions(-) diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 1d28e2cc9..7535f881e 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -309,8 +309,8 @@ int32_t myGet_mempool_txs(std::vector &txs,uint8_t evalcode,uint8_ /// \endcond /// \cond INTERNAL -int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); -int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp); +int32_t dragon_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); +int32_t dragon_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp); /// \endcond CScript GetScriptForMultisig(int nRequired, const std::vector& keys); diff --git a/src/cc/crypto777/OS_portable.h b/src/cc/crypto777/OS_portable.h index e0b185cbc..9599ebcfe 100755 --- a/src/cc/crypto777/OS_portable.h +++ b/src/cc/crypto777/OS_portable.h @@ -15,7 +15,7 @@ #ifndef OS_PORTABLEH #define OS_PORTABLEH -// iguana_OS has functions that invoke system calls. Whenever possible stdio and similar functions are use and most functions are fully portable and in this file. For things that require OS specific, the call is routed to iguana_OS_portable_* Usually, all but one OS can be handled with the same code, so iguana_OS_portable.c has most of this shared logic and an #ifdef iguana_OS_nonportable.c +// dragon_OS has functions that invoke system calls. Whenever possible stdio and similar functions are use and most functions are fully portable and in this file. For things that require OS specific, the call is routed to dragon_OS_portable_* Usually, all but one OS can be handled with the same code, so dragon_OS_portable.c has most of this shared logic and an #ifdef dragon_OS_nonportable.c #ifdef __APPLE__ //#define LIQUIDITY_PROVIDER 1 @@ -279,19 +279,19 @@ void *queue_clone(queue_t *clone,queue_t *queue,int32_t size); int32_t queue_size(queue_t *queue); char *mbstr(char *str,double n); -void iguana_memreset(struct OS_memspace *mem); -void iguana_mempurge(struct OS_memspace *mem); -void *iguana_meminit(struct OS_memspace *mem,char *name,void *ptr,int64_t totalsize,int32_t threadsafe); -void *iguana_memalloc(struct OS_memspace *mem,long size,int32_t clearflag); -int64_t iguana_memfree(struct OS_memspace *mem,void *ptr,int32_t size); +void dragon_memreset(struct OS_memspace *mem); +void dragon_mempurge(struct OS_memspace *mem); +void *dragon_meminit(struct OS_memspace *mem,char *name,void *ptr,int64_t totalsize,int32_t threadsafe); +void *dragon_memalloc(struct OS_memspace *mem,long size,int32_t clearflag); +int64_t dragon_memfree(struct OS_memspace *mem,void *ptr,int32_t size); // generic functions -bits256 iguana_merkle(char *symbol,bits256 *tree,int32_t txn_count); +bits256 dragon_merkle(char *symbol,bits256 *tree,int32_t txn_count); bits256 bits256_calctxid(char *symbol,uint8_t *serialized,int32_t len); int32_t unhex(char c); void touppercase(char *str); uint32_t is_ipaddr(char *str); -void iguana_bitmap(char *space,int32_t max,char *name); +void dragon_bitmap(char *space,int32_t max,char *name); double _pairaved(double valA,double valB); int32_t unstringbits(char *buf,uint64_t bits); uint64_t stringbits(char *str); @@ -383,26 +383,26 @@ void expand_ipbits(char *ipaddr,uint64_t ipbits); void escape_code(char *escaped,char *str); void SaM_PrepareIndices(void); -// iguana_serdes.c +// dragon_serdes.c #ifndef IGUANA_LOG2PACKETSIZE #define IGUANA_LOG2PACKETSIZE 22 #endif #ifndef IGUANA_MAXPACKETSIZE #define IGUANA_MAXPACKETSIZE (1 << IGUANA_LOG2PACKETSIZE) #endif -struct iguana_msghdr { uint8_t netmagic[4]; char command[12]; uint8_t serdatalen[4],hash[4]; } PACKED; +struct dragon_msghdr { uint8_t netmagic[4]; char command[12]; uint8_t serdatalen[4],hash[4]; } PACKED; -int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); -int32_t iguana_validatehdr(char *symbol,struct iguana_msghdr *H); -int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp); -int32_t iguana_sethdr(struct iguana_msghdr *H,const uint8_t netmagic[4],char *command,uint8_t *data,int32_t datalen); -uint8_t *iguana_varint16(int32_t rwflag,uint8_t *serialized,uint16_t *varint16p); -uint8_t *iguana_varint32(int32_t rwflag,uint8_t *serialized,uint16_t *varint16p); -uint8_t *iguana_varint64(int32_t rwflag,uint8_t *serialized,uint32_t *varint32p); -int32_t iguana_rwvarint(int32_t rwflag,uint8_t *serialized,uint64_t *varint64p); -int32_t iguana_rwvarint32(int32_t rwflag,uint8_t *serialized,uint32_t *int32p); -int32_t iguana_rwvarstr(int32_t rwflag,uint8_t *serialized,int32_t maxlen,char *endianedp); -int32_t iguana_rwmem(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); +int32_t dragon_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); +int32_t dragon_validatehdr(char *symbol,struct dragon_msghdr *H); +int32_t dragon_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp); +int32_t dragon_sethdr(struct dragon_msghdr *H,const uint8_t netmagic[4],char *command,uint8_t *data,int32_t datalen); +uint8_t *dragon_varint16(int32_t rwflag,uint8_t *serialized,uint16_t *varint16p); +uint8_t *dragon_varint32(int32_t rwflag,uint8_t *serialized,uint16_t *varint16p); +uint8_t *dragon_varint64(int32_t rwflag,uint8_t *serialized,uint32_t *varint32p); +int32_t dragon_rwvarint(int32_t rwflag,uint8_t *serialized,uint64_t *varint64p); +int32_t dragon_rwvarint32(int32_t rwflag,uint8_t *serialized,uint32_t *int32p); +int32_t dragon_rwvarstr(int32_t rwflag,uint8_t *serialized,int32_t maxlen,char *endianedp); +int32_t dragon_rwmem(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); #define bits256_nonz(a) (((a).ulongs[0] | (a).ulongs[1] | (a).ulongs[2] | (a).ulongs[3]) != 0) bits256 bits256_ave(bits256 a,bits256 b); diff --git a/src/cc/includes/curve25519.h b/src/cc/includes/curve25519.h index 657fab4d0..1f714861e 100755 --- a/src/cc/includes/curve25519.h +++ b/src/cc/includes/curve25519.h @@ -55,8 +55,8 @@ void vcalc_sha256(char hashstr[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_ void vcalc_sha256cat(uint8_t hash[256 >> 3],uint8_t *src,int32_t len,uint8_t *src2,int32_t len2); void vupdate_sha256(uint8_t hash[256 >> 3],struct sha256_vstate *state,uint8_t *src,int32_t len); bits256 curve25519_shared(bits256 privkey,bits256 otherpub); -int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); -int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp); +int32_t dragon_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); +int32_t dragon_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp); uint32_t calc_crc32(uint32_t crc,const void *buf,size_t size); uint64_t conv_NXTpassword(unsigned char *mysecret,unsigned char *mypublic,uint8_t *pass,int32_t passlen); diff --git a/src/cc/oracles.cpp b/src/cc/oracles.cpp index 61e5c9619..3ec5a0935 100644 --- a/src/cc/oracles.cpp +++ b/src/cc/oracles.cpp @@ -384,7 +384,7 @@ int32_t oracle_format(uint256 *hashp,int64_t *valp,char *str,uint8_t fmt,uint8_t { if ( len == 32 ) { - iguana_rwbignum(0,&data[offset],len,(uint8_t *)hashp); + dragon_rwbignum(0,&data[offset],len,(uint8_t *)hashp); if ( str != 0 ) sprintf(str,"%s",uint256_str(_str,*hashp)); } @@ -395,9 +395,9 @@ int32_t oracle_format(uint256 *hashp,int64_t *valp,char *str,uint8_t fmt,uint8_t switch ( len ) { case 1: val = (int8_t)data[offset]; break; - case 2: iguana_rwnum(0,&data[offset],len,(void *)&val16); val = val16; break; - case 4: iguana_rwnum(0,&data[offset],len,(void *)&val32); val = val32; break; - case 8: iguana_rwnum(0,&data[offset],len,(void *)&val); break; + case 2: dragon_rwnum(0,&data[offset],len,(void *)&val16); val = val16; break; + case 4: dragon_rwnum(0,&data[offset],len,(void *)&val32); val = val32; break; + case 8: dragon_rwnum(0,&data[offset],len,(void *)&val); break; } if ( str != 0 ) sprintf(str,"%lld",(long long)val); @@ -408,9 +408,9 @@ int32_t oracle_format(uint256 *hashp,int64_t *valp,char *str,uint8_t fmt,uint8_t switch ( len ) { case 1: uval = data[offset]; break; - case 2: iguana_rwnum(0,&data[offset],len,(void *)&uval16); uval = uval16; break; - case 4: iguana_rwnum(0,&data[offset],len,(void *)&uval32); uval = uval32; break; - case 8: iguana_rwnum(0,&data[offset],len,(void *)&uval); break; + case 2: dragon_rwnum(0,&data[offset],len,(void *)&uval16); uval = uval16; break; + case 4: dragon_rwnum(0,&data[offset],len,(void *)&uval32); uval = uval32; break; + case 8: dragon_rwnum(0,&data[offset],len,(void *)&uval); break; } if ( str != 0 ) sprintf(str,"%llu",(long long)uval); diff --git a/src/komodo.h b/src/komodo.h index 1cfbd283b..06d614810 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -631,10 +631,10 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar notarized = 1; if ( 0 && opretlen != 149 ) printf("[%s].%d (%s) matched.%d i.%d j.%d notarized.%d %llx opretlen.%d len.%d offset.%d opoffset.%d\n",ASSETCHAINS_SYMBOL,height,ccdata.symbol,matched,i,j,notarized,(long long)signedmask,opretlen,len,offset,opoffset); - len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&srchash); - len += iguana_rwnum(0,&scriptbuf[len],sizeof(*notarizedheightp),(uint8_t *)notarizedheightp); + len += dragon_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&srchash); + len += dragon_rwnum(0,&scriptbuf[len],sizeof(*notarizedheightp),(uint8_t *)notarizedheightp); if ( matched != 0 ) - len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&desttxid); + len += dragon_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&desttxid); if ( matched != 0 ) validated = komodo_validate_chain(srchash,*notarizedheightp); else validated = 1; @@ -655,13 +655,13 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar //printf("nameoffset.%d len.%d + 36 %d opoffset.%d vs opretlen.%d\n",nameoffset,len,len+36,opoffset,opretlen); if ( len+36-opoffset <= opretlen ) { - len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&MoM); - len += iguana_rwnum(0,&scriptbuf[len],sizeof(MoMdepth),(uint8_t *)&MoMdepth); + len += dragon_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&MoM); + len += dragon_rwnum(0,&scriptbuf[len],sizeof(MoMdepth),(uint8_t *)&MoMdepth); ccdata.MoMdata.MoM = MoM; ccdata.MoMdata.MoMdepth = MoMdepth & 0xffff; if ( len+sizeof(ccdata.CCid)-opoffset <= opretlen ) { - len += iguana_rwnum(0,&scriptbuf[len],sizeof(ccdata.CCid),(uint8_t *)&ccdata.CCid); + len += dragon_rwnum(0,&scriptbuf[len],sizeof(ccdata.CCid),(uint8_t *)&ccdata.CCid); //if ( ((MoMdepth>>16) & 0xffff) != (ccdata.CCid & 0xffff) ) // fprintf(stderr,"%s CCid mismatch %u != %u\n",ASSETCHAINS_SYMBOL,((MoMdepth>>16) & 0xffff),(ccdata.CCid & 0xffff)); ccdata.len = sizeof(ccdata.CCid); @@ -670,19 +670,19 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar // MoMoM, depth, numpairs, (notarization ht, MoMoM offset) if ( len+48-opoffset <= opretlen && strcmp(ccdata.symbol,ASSETCHAINS_SYMBOL) == 0 ) { - len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.kmdstarti); - len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.kmdendi); - len += iguana_rwbignum(0,&scriptbuf[len],sizeof(MoMoMdata.MoMoM),(uint8_t *)&MoMoMdata.MoMoM); - len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.MoMoMdepth); - len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.numpairs); + len += dragon_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.kmdstarti); + len += dragon_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.kmdendi); + len += dragon_rwbignum(0,&scriptbuf[len],sizeof(MoMoMdata.MoMoM),(uint8_t *)&MoMoMdata.MoMoM); + len += dragon_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.MoMoMdepth); + len += dragon_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.numpairs); MoMoMdata.len += sizeof(MoMoMdata.MoMoM) + sizeof(uint32_t)*4; if ( len+MoMoMdata.numpairs*8-opoffset == opretlen ) { MoMoMdata.pairs = (struct komodo_ccdatapair *)calloc(MoMoMdata.numpairs,sizeof(*MoMoMdata.pairs)); for (k=0; knumpairs > 0 ) { - len += iguana_rwnum(1,&hexdata[len],sizeof(CCid),(uint8_t *)&CCid); - len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->kmdstarti); - len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->kmdendi); - len += iguana_rwbignum(1,&hexdata[len],sizeof(mdata->MoMoM),(uint8_t *)&mdata->MoMoM); - len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->MoMoMdepth); - len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->numpairs); + len += dragon_rwnum(1,&hexdata[len],sizeof(CCid),(uint8_t *)&CCid); + len += dragon_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->kmdstarti); + len += dragon_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->kmdendi); + len += dragon_rwbignum(1,&hexdata[len],sizeof(mdata->MoMoM),(uint8_t *)&mdata->MoMoM); + len += dragon_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->MoMoMdepth); + len += dragon_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->numpairs); for (i=0; inumpairs; i++) { if ( len + sizeof(uint32_t)*2 > sizeof(hexdata) ) @@ -160,8 +160,8 @@ int32_t komodo_MoMoMdata(char *hexstr,int32_t hexsize,struct komodo_ccdataMoMoM fprintf(stderr,"%s %d %d i.%d of %d exceeds hexdata.%d\n",symbol,kmdheight,notarized_height,i,mdata->numpairs,(int32_t)sizeof(hexdata)); break; } - len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->pairs[i].notarized_height); - len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->pairs[i].MoMoMoffset); + len += dragon_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->pairs[i].notarized_height); + len += dragon_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->pairs[i].MoMoMoffset); } if ( i == mdata->numpairs && len*2+1 < hexsize ) { diff --git a/src/komodo_defs.h b/src/komodo_defs.h index e482390bb..c372ed3e4 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -265,7 +265,7 @@ static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = {"decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, // 63 }, { - // Season 3.5 third party NN pubkeys from https://github.com/KomodoPlatform/dPoW/blob/master/iguana/3rd_party + // Season 3.5 third party NN pubkeys from https://github.com/KomodoPlatform/dPoW/blob/master/dragon/3rd_party {"madmax_NA", "02ef81a360411adf71184ff04d0c5793fc41fd1d7155a28dd909f21f35f4883ac1" }, {"alright_AR", "036a6bca1c2a8166f79fa8a979662892742346cc972b432f8e61950a358d705517" }, {"strob_NA", "02049202f3872877e81035549f6f3a0f868d0ad1c9b0e0d2b48b1f30324255d26d" }, @@ -332,7 +332,7 @@ static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = {"decker_AR", "02a85540db8d41c7e60bf0d33d1364b4151cad883dd032878ea4c037f67b769635" } }, { - // Season 4 https://github.com/KomodoPlatform/dPoW/blob/s4/iguana/3rd_party + // Season 4 https://github.com/KomodoPlatform/dPoW/blob/s4/dragon/3rd_party {"alien_AR", "024f20c096b085308e21893383f44b4faf1cdedea9ad53cc7d7e7fbfa0c30c1e71" }, {"alien_EU", "022b85908191788f409506ebcf96a892f3274f352864c3ed566c5a16de63953236" }, {"alien_NA", "022f62b56ddfd07c9860921c701285ac39bb3ac8f6f083d1b59c8f4943be3de162" }, diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index aba43e0aa..a6b8d612f 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -188,10 +188,10 @@ int32_t komodo_rwapproval(int32_t rwflag,uint8_t *opretbuf,struct pax_transactio pax->vout += ((uint32_t)opretbuf[len++] << 8); //printf(" txid v.%d\n",pax->vout); } - len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->komodoshis),&pax->komodoshis); - len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->fiatoshis),&pax->fiatoshis); - len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->height),&pax->height); - len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->otherheight),&pax->otherheight); + len += dragon_rwnum(rwflag,&opretbuf[len],sizeof(pax->komodoshis),&pax->komodoshis); + len += dragon_rwnum(rwflag,&opretbuf[len],sizeof(pax->fiatoshis),&pax->fiatoshis); + len += dragon_rwnum(rwflag,&opretbuf[len],sizeof(pax->height),&pax->height); + len += dragon_rwnum(rwflag,&opretbuf[len],sizeof(pax->otherheight),&pax->otherheight); if ( rwflag != 0 ) { memcpy(&opretbuf[len],pax->rmd160,20), len += 20; @@ -855,7 +855,7 @@ const char *komodo_opreturn(int32_t height,uint64_t value,uint8_t *opretbuf,int3 tokomodo = 0; if ( opretlen == 38 ) // any KMD tx { - iguana_rwnum(0,&opretbuf[34],sizeof(kmdheight),&kmdheight); + dragon_rwnum(0,&opretbuf[34],sizeof(kmdheight),&kmdheight); memset(base,0,sizeof(base)); PAX_pubkey(0,&opretbuf[1],&addrtype,rmd160,base,&shortflag,&fiatoshis); bitcoin_address(coinaddr,addrtype,rmd160,20); @@ -998,7 +998,7 @@ const char *komodo_opreturn(int32_t height,uint64_t value,uint8_t *opretbuf,int3 return(typestr); } tokomodo = 1; - iguana_rwnum(0,&opretbuf[34],sizeof(kmdheight),&kmdheight); + dragon_rwnum(0,&opretbuf[34],sizeof(kmdheight),&kmdheight); memset(base,0,sizeof(base)); PAX_pubkey(0,&opretbuf[1],&addrtype,rmd160,base,&shortflag,&komodoshis); bitcoin_address(coinaddr,addrtype,rmd160,20); diff --git a/src/komodo_kv.h b/src/komodo_kv.h index a879340ff..be7eb8515 100644 --- a/src/komodo_kv.h +++ b/src/komodo_kv.h @@ -103,10 +103,10 @@ void komodo_kvupdate(uint8_t *opretbuf,int32_t opretlen,uint64_t value) uint32_t flags; uint256 pubkey,refpubkey,sig; int32_t i,refvaluesize,hassig,coresize,haspubkey,height,kvheight; uint16_t keylen,valuesize,newflag = 0; uint8_t *key,*valueptr,keyvalue[IGUANA_MAXSCRIPTSIZE*8]; struct komodo_kv *ptr; char *transferpubstr,*tstr; uint64_t fee; if ( ASSETCHAINS_SYMBOL[0] == 0 ) // disable KV for KMD return; - iguana_rwnum(0,&opretbuf[1],sizeof(keylen),&keylen); - iguana_rwnum(0,&opretbuf[3],sizeof(valuesize),&valuesize); - iguana_rwnum(0,&opretbuf[5],sizeof(height),&height); - iguana_rwnum(0,&opretbuf[9],sizeof(flags),&flags); + dragon_rwnum(0,&opretbuf[1],sizeof(keylen),&keylen); + dragon_rwnum(0,&opretbuf[3],sizeof(valuesize),&valuesize); + dragon_rwnum(0,&opretbuf[5],sizeof(height),&height); + dragon_rwnum(0,&opretbuf[9],sizeof(flags),&flags); key = &opretbuf[13]; if ( keylen+13 > opretlen ) { diff --git a/src/komodo_nSPV.h b/src/komodo_nSPV.h index fe4d784cb..ac6168c35 100644 --- a/src/komodo_nSPV.h +++ b/src/komodo_nSPV.h @@ -26,7 +26,7 @@ #ifndef KOMODO_NSPV_H #define KOMODO_NSPV_H -int32_t iguana_rwbuf(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *buf) +int32_t dragon_rwbuf(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *buf) { if ( rwflag != 0 ) memcpy(serialized,buf,len); @@ -37,21 +37,21 @@ int32_t iguana_rwbuf(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *buf int32_t NSPV_rwequihdr(int32_t rwflag,uint8_t *serialized,struct NSPV_equihdr *ptr) { int32_t len = 0; - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nVersion),&ptr->nVersion); - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->hashPrevBlock),(uint8_t *)&ptr->hashPrevBlock); - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->hashMerkleRoot),(uint8_t *)&ptr->hashMerkleRoot); - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->hashFinalSaplingRoot),(uint8_t *)&ptr->hashFinalSaplingRoot); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nTime),&ptr->nTime); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nBits),&ptr->nBits); - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->nNonce),(uint8_t *)&ptr->nNonce); - len += iguana_rwbuf(rwflag,&serialized[len],sizeof(ptr->nSolution),ptr->nSolution); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->nVersion),&ptr->nVersion); + len += dragon_rwbignum(rwflag,&serialized[len],sizeof(ptr->hashPrevBlock),(uint8_t *)&ptr->hashPrevBlock); + len += dragon_rwbignum(rwflag,&serialized[len],sizeof(ptr->hashMerkleRoot),(uint8_t *)&ptr->hashMerkleRoot); + len += dragon_rwbignum(rwflag,&serialized[len],sizeof(ptr->hashFinalSaplingRoot),(uint8_t *)&ptr->hashFinalSaplingRoot); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->nTime),&ptr->nTime); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->nBits),&ptr->nBits); + len += dragon_rwbignum(rwflag,&serialized[len],sizeof(ptr->nNonce),(uint8_t *)&ptr->nNonce); + len += dragon_rwbuf(rwflag,&serialized[len],sizeof(ptr->nSolution),ptr->nSolution); return(len); } -int32_t iguana_rwequihdrvec(int32_t rwflag,uint8_t *serialized,uint16_t *vecsizep,struct NSPV_equihdr **ptrp) +int32_t dragon_rwequihdrvec(int32_t rwflag,uint8_t *serialized,uint16_t *vecsizep,struct NSPV_equihdr **ptrp) { int32_t i,vsize,len = 0; - len += iguana_rwnum(rwflag,&serialized[len],sizeof(*vecsizep),vecsizep); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(*vecsizep),vecsizep); if ( (vsize= *vecsizep) != 0 ) { //fprintf(stderr,"vsize.%d ptrp.%p alloc %ld\n",vsize,*ptrp,sizeof(struct NSPV_equihdr)*vsize); @@ -63,15 +63,15 @@ int32_t iguana_rwequihdrvec(int32_t rwflag,uint8_t *serialized,uint16_t *vecsize return(len); } -int32_t iguana_rwuint8vec(int32_t rwflag,uint8_t *serialized,int32_t *biglenp,uint8_t **ptrp) +int32_t dragon_rwuint8vec(int32_t rwflag,uint8_t *serialized,int32_t *biglenp,uint8_t **ptrp) { int32_t vsize,len = 0; - len += iguana_rwnum(rwflag,&serialized[len],sizeof(*biglenp),biglenp); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(*biglenp),biglenp); if ( (vsize= *biglenp) > 0 && vsize < MAX_TX_SIZE_AFTER_SAPLING ) { if ( *ptrp == 0 ) *ptrp = (uint8_t *)calloc(1,vsize); - len += iguana_rwbuf(rwflag,&serialized[len],vsize,*ptrp); + len += dragon_rwbuf(rwflag,&serialized[len],vsize,*ptrp); } return(len); } @@ -79,18 +79,18 @@ int32_t iguana_rwuint8vec(int32_t rwflag,uint8_t *serialized,int32_t *biglenp,ui int32_t NSPV_rwutxoresp(int32_t rwflag,uint8_t *serialized,struct NSPV_utxoresp *ptr) { int32_t len = 0; - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->txid),(uint8_t *)&ptr->txid); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->satoshis),&ptr->satoshis); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->extradata),&ptr->extradata); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->vout),&ptr->vout); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->height),&ptr->height); + len += dragon_rwbignum(rwflag,&serialized[len],sizeof(ptr->txid),(uint8_t *)&ptr->txid); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->satoshis),&ptr->satoshis); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->extradata),&ptr->extradata); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->vout),&ptr->vout); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->height),&ptr->height); return(len); } int32_t NSPV_rwutxosresp(int32_t rwflag,uint8_t *serialized,struct NSPV_utxosresp *ptr) // check mempool { int32_t i,len = 0; - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->numutxos),&ptr->numutxos); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->numutxos),&ptr->numutxos); if ( ptr->numutxos != 0 ) { if ( ptr->utxos == 0 ) @@ -98,12 +98,12 @@ int32_t NSPV_rwutxosresp(int32_t rwflag,uint8_t *serialized,struct NSPV_utxosres for (i=0; inumutxos; i++) len += NSPV_rwutxoresp(rwflag,&serialized[len],&ptr->utxos[i]); } - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->total),&ptr->total); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->interest),&ptr->interest); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nodeheight),&ptr->nodeheight); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->filter),&ptr->filter); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->CCflag),&ptr->CCflag); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->skipcount),&ptr->skipcount); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->total),&ptr->total); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->interest),&ptr->interest); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->nodeheight),&ptr->nodeheight); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->filter),&ptr->filter); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->CCflag),&ptr->CCflag); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->skipcount),&ptr->skipcount); if ( rwflag != 0 ) { memcpy(&serialized[len],ptr->coinaddr,sizeof(ptr->coinaddr)); @@ -140,17 +140,17 @@ void NSPV_utxosresp_copy(struct NSPV_utxosresp *dest,struct NSPV_utxosresp *ptr) int32_t NSPV_rwtxidresp(int32_t rwflag,uint8_t *serialized,struct NSPV_txidresp *ptr) { int32_t len = 0; - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->txid),(uint8_t *)&ptr->txid); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->satoshis),&ptr->satoshis); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->vout),&ptr->vout); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->height),&ptr->height); + len += dragon_rwbignum(rwflag,&serialized[len],sizeof(ptr->txid),(uint8_t *)&ptr->txid); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->satoshis),&ptr->satoshis); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->vout),&ptr->vout); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->height),&ptr->height); return(len); } int32_t NSPV_rwtxidsresp(int32_t rwflag,uint8_t *serialized,struct NSPV_txidsresp *ptr) { int32_t i,len = 0; - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->numtxids),&ptr->numtxids); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->numtxids),&ptr->numtxids); if ( ptr->numtxids != 0 ) { if ( ptr->txids == 0 ) @@ -158,10 +158,10 @@ int32_t NSPV_rwtxidsresp(int32_t rwflag,uint8_t *serialized,struct NSPV_txidsres for (i=0; inumtxids; i++) len += NSPV_rwtxidresp(rwflag,&serialized[len],&ptr->txids[i]); } - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nodeheight),&ptr->nodeheight); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->filter),&ptr->filter); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->CCflag),&ptr->CCflag); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->skipcount),&ptr->skipcount); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->nodeheight),&ptr->nodeheight); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->filter),&ptr->filter); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->CCflag),&ptr->CCflag); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->skipcount),&ptr->skipcount); if ( rwflag != 0 ) { memcpy(&serialized[len],ptr->coinaddr,sizeof(ptr->coinaddr)); @@ -199,20 +199,20 @@ void NSPV_txidsresp_copy(struct NSPV_txidsresp *dest,struct NSPV_txidsresp *ptr) int32_t NSPV_rwmempoolresp(int32_t rwflag,uint8_t *serialized,struct NSPV_mempoolresp *ptr) { int32_t i,len = 0; - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->numtxids),&ptr->numtxids); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->numtxids),&ptr->numtxids); if ( ptr->numtxids != 0 ) { if ( ptr->txids == 0 ) ptr->txids = (uint256 *)calloc(sizeof(*ptr->txids),ptr->numtxids); for (i=0; inumtxids; i++) - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->txids[i]),(uint8_t *)&ptr->txids[i]); + len += dragon_rwbignum(rwflag,&serialized[len],sizeof(ptr->txids[i]),(uint8_t *)&ptr->txids[i]); } - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->txid),(uint8_t *)&ptr->txid); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nodeheight),&ptr->nodeheight); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->vout),&ptr->vout); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->vindex),&ptr->vindex); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->CCflag),&ptr->CCflag); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->funcid),&ptr->funcid); + len += dragon_rwbignum(rwflag,&serialized[len],sizeof(ptr->txid),(uint8_t *)&ptr->txid); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->nodeheight),&ptr->nodeheight); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->vout),&ptr->vout); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->vindex),&ptr->vindex); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->CCflag),&ptr->CCflag); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->funcid),&ptr->funcid); if ( rwflag != 0 ) { memcpy(&serialized[len],ptr->coinaddr,sizeof(ptr->coinaddr)); @@ -250,12 +250,12 @@ void NSPV_mempoolresp_copy(struct NSPV_mempoolresp *dest,struct NSPV_mempoolresp int32_t NSPV_rwntz(int32_t rwflag,uint8_t *serialized,struct NSPV_ntz *ptr) { int32_t len = 0; - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->blockhash),(uint8_t *)&ptr->blockhash); - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->txid),(uint8_t *)&ptr->txid); - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->othertxid),(uint8_t *)&ptr->othertxid); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->height),&ptr->height); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->txidheight),&ptr->txidheight); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->timestamp),&ptr->timestamp); + len += dragon_rwbignum(rwflag,&serialized[len],sizeof(ptr->blockhash),(uint8_t *)&ptr->blockhash); + len += dragon_rwbignum(rwflag,&serialized[len],sizeof(ptr->txid),(uint8_t *)&ptr->txid); + len += dragon_rwbignum(rwflag,&serialized[len],sizeof(ptr->othertxid),(uint8_t *)&ptr->othertxid); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->height),&ptr->height); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->txidheight),&ptr->txidheight); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->timestamp),&ptr->timestamp); return(len); } @@ -264,7 +264,7 @@ int32_t NSPV_rwntzsresp(int32_t rwflag,uint8_t *serialized,struct NSPV_ntzsresp int32_t len = 0; len += NSPV_rwntz(rwflag,&serialized[len],&ptr->prevntz); len += NSPV_rwntz(rwflag,&serialized[len],&ptr->nextntz); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->reqheight),&ptr->reqheight); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->reqheight),&ptr->reqheight); return(len); } @@ -283,11 +283,11 @@ int32_t NSPV_rwinforesp(int32_t rwflag,uint8_t *serialized,struct NSPV_inforesp { int32_t len = 0; len += NSPV_rwntz(rwflag,&serialized[len],&ptr->notarization); - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->blockhash),(uint8_t *)&ptr->blockhash); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->height),&ptr->height); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->hdrheight),&ptr->hdrheight); + len += dragon_rwbignum(rwflag,&serialized[len],sizeof(ptr->blockhash),(uint8_t *)&ptr->blockhash); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->height),&ptr->height); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->hdrheight),&ptr->hdrheight); len += NSPV_rwequihdr(rwflag,&serialized[len],&ptr->H); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->version),&ptr->version); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->version),&ptr->version); //fprintf(stderr,"getinfo rwlen.%d\n",len); return(len); } @@ -301,13 +301,13 @@ void NSPV_inforesp_purge(struct NSPV_inforesp *ptr) int32_t NSPV_rwtxproof(int32_t rwflag,uint8_t *serialized,struct NSPV_txproof *ptr) { int32_t len = 0; - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->txid),(uint8_t *)&ptr->txid); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->unspentvalue),&ptr->unspentvalue); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->height),&ptr->height); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->vout),&ptr->vout); - len += iguana_rwuint8vec(rwflag,&serialized[len],&ptr->txlen,&ptr->tx); - len += iguana_rwuint8vec(rwflag,&serialized[len],&ptr->txprooflen,&ptr->txproof); - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->hashblock),(uint8_t *)&ptr->hashblock); + len += dragon_rwbignum(rwflag,&serialized[len],sizeof(ptr->txid),(uint8_t *)&ptr->txid); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->unspentvalue),&ptr->unspentvalue); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->height),&ptr->height); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->vout),&ptr->vout); + len += dragon_rwuint8vec(rwflag,&serialized[len],&ptr->txlen,&ptr->tx); + len += dragon_rwuint8vec(rwflag,&serialized[len],&ptr->txprooflen,&ptr->txproof); + len += dragon_rwbignum(rwflag,&serialized[len],sizeof(ptr->hashblock),(uint8_t *)&ptr->hashblock); return(len); } @@ -341,11 +341,11 @@ void NSPV_txproof_purge(struct NSPV_txproof *ptr) int32_t NSPV_rwntzproofshared(int32_t rwflag,uint8_t *serialized,struct NSPV_ntzproofshared *ptr) { int32_t len = 0; - len += iguana_rwequihdrvec(rwflag,&serialized[len],&ptr->numhdrs,&ptr->hdrs); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->prevht),&ptr->prevht); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nextht),&ptr->nextht); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->pad32),&ptr->pad32); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->pad16),&ptr->pad16); + len += dragon_rwequihdrvec(rwflag,&serialized[len],&ptr->numhdrs,&ptr->hdrs); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->prevht),&ptr->prevht); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->nextht),&ptr->nextht); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->pad32),&ptr->pad32); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->pad16),&ptr->pad16); //fprintf(stderr,"rwcommon prev.%d next.%d\n",ptr->prevht,ptr->nextht); return(len); } @@ -354,12 +354,12 @@ int32_t NSPV_rwntzsproofresp(int32_t rwflag,uint8_t *serialized,struct NSPV_ntzs { int32_t len = 0; len += NSPV_rwntzproofshared(rwflag,&serialized[len],&ptr->common); - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->prevtxid),(uint8_t *)&ptr->prevtxid); - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->nexttxid),(uint8_t *)&ptr->nexttxid); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->prevtxidht),&ptr->prevtxidht); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nexttxidht),&ptr->nexttxidht); - len += iguana_rwuint8vec(rwflag,&serialized[len],&ptr->prevtxlen,&ptr->prevntz); - len += iguana_rwuint8vec(rwflag,&serialized[len],&ptr->nexttxlen,&ptr->nextntz); + len += dragon_rwbignum(rwflag,&serialized[len],sizeof(ptr->prevtxid),(uint8_t *)&ptr->prevtxid); + len += dragon_rwbignum(rwflag,&serialized[len],sizeof(ptr->nexttxid),(uint8_t *)&ptr->nexttxid); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->prevtxidht),&ptr->prevtxidht); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->nexttxidht),&ptr->nexttxidht); + len += dragon_rwuint8vec(rwflag,&serialized[len],&ptr->prevtxlen,&ptr->prevntz); + len += dragon_rwuint8vec(rwflag,&serialized[len],&ptr->nexttxlen,&ptr->nextntz); //fprintf(stderr,"retlen.%d\n",len); return(len); } @@ -402,9 +402,9 @@ int32_t NSPV_rwspentinfo(int32_t rwflag,uint8_t *serialized,struct NSPV_spentinf { int32_t len = 0; len += NSPV_rwtxproof(rwflag,&serialized[len],&ptr->spent); - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->txid),(uint8_t *)&ptr->txid); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->vout),&ptr->vout); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->spentvini),&ptr->spentvini); + len += dragon_rwbignum(rwflag,&serialized[len],sizeof(ptr->txid),(uint8_t *)&ptr->txid); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->vout),&ptr->vout); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->spentvini),&ptr->spentvini); return(len); } @@ -420,8 +420,8 @@ void NSPV_spentinfo_purge(struct NSPV_spentinfo *ptr) int32_t NSPV_rwbroadcastresp(int32_t rwflag,uint8_t *serialized,struct NSPV_broadcastresp *ptr) { int32_t len = 0; - len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->txid),(uint8_t *)&ptr->txid); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->retcode),&ptr->retcode); + len += dragon_rwbignum(rwflag,&serialized[len],sizeof(ptr->txid),(uint8_t *)&ptr->txid); + len += dragon_rwnum(rwflag,&serialized[len],sizeof(ptr->retcode),&ptr->retcode); return(len); } @@ -434,8 +434,8 @@ void NSPV_broadcast_purge(struct NSPV_broadcastresp *ptr) int32_t NSPV_rwremoterpcresp(int32_t rwflag,uint8_t *serialized,struct NSPV_remoterpcresp *ptr, int32_t slen) { int32_t len = 0; - len+=iguana_rwbuf(rwflag,&serialized[len],sizeof(ptr->method),(uint8_t*)ptr->method); - len+=iguana_rwbuf(rwflag,&serialized[len],slen-len,(uint8_t*)ptr->json); + len+=dragon_rwbuf(rwflag,&serialized[len],sizeof(ptr->method),(uint8_t*)ptr->method); + len+=dragon_rwbuf(rwflag,&serialized[len],slen-len,(uint8_t*)ptr->json); return(len); } @@ -562,7 +562,7 @@ int32_t NSPV_notariescount(CTransaction tx,uint8_t elected[64][33]) uint256 NSPV_opretextract(int32_t *heightp,uint256 *blockhashp,char *symbol,std::vector opret,uint256 txid) { uint256 desttxid; int32_t i; - iguana_rwnum(0,&opret[32],sizeof(*heightp),heightp); + dragon_rwnum(0,&opret[32],sizeof(*heightp),heightp); for (i=0; i<32; i++) ((uint8_t *)blockhashp)[i] = opret[i]; for (i=0; i<32; i++) diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 90ec9027c..468e14b04 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -637,13 +637,13 @@ int32_t NSPV_mempooltxids(struct NSPV_mempoolresp *ptr,char *coinaddr,uint8_t is for (i=0; inumtxids; i++) { tmp = txids[i]; - iguana_rwbignum(0,(uint8_t *)&tmp,sizeof(*ptr->txids),(uint8_t *)&ptr->txids[i]); + dragon_rwbignum(0,(uint8_t *)&tmp,sizeof(*ptr->txids),(uint8_t *)&ptr->txids[i]); } } if ( funcid == NSPV_MEMPOOL_ADDRESS ) { memcpy(&tmp,&satoshis,sizeof(tmp)); - iguana_rwbignum(0,(uint8_t *)&tmp,sizeof(ptr->txid),(uint8_t *)&ptr->txid); + dragon_rwbignum(0,(uint8_t *)&tmp,sizeof(ptr->txid),(uint8_t *)&ptr->txid); } len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->txids)*ptr->numtxids - sizeof(ptr->txids)); return(len); @@ -883,7 +883,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req { struct NSPV_inforesp I; if ( len == 1+sizeof(reqheight) ) - iguana_rwnum(0,&request[1],sizeof(reqheight),&reqheight); + dragon_rwnum(0,&request[1],sizeof(reqheight),&reqheight); else reqheight = 0; //fprintf(stderr,"request height.%d\n",reqheight); memset(&I,0,sizeof(I)); @@ -918,13 +918,13 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req else if ( request[1] == len-7 ) { isCC = (request[len-5] != 0); - iguana_rwnum(0,&request[len-4],sizeof(skipcount),&skipcount); + dragon_rwnum(0,&request[len-4],sizeof(skipcount),&skipcount); } else { isCC = (request[len-9] != 0); - iguana_rwnum(0,&request[len-8],sizeof(skipcount),&skipcount); - iguana_rwnum(0,&request[len-4],sizeof(filter),&filter); + dragon_rwnum(0,&request[len-8],sizeof(skipcount),&skipcount); + dragon_rwnum(0,&request[len-4],sizeof(filter),&filter); } if ( 0 && isCC != 0 ) fprintf(stderr,"utxos %s isCC.%d skipcount.%d filter.%x\n",coinaddr,isCC,skipcount,filter); @@ -958,13 +958,13 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req else if ( request[1] == len-7 ) { isCC = (request[len-5] != 0); - iguana_rwnum(0,&request[len-4],sizeof(skipcount),&skipcount); + dragon_rwnum(0,&request[len-4],sizeof(skipcount),&skipcount); } else { isCC = (request[len-9] != 0); - iguana_rwnum(0,&request[len-8],sizeof(skipcount),&skipcount); - iguana_rwnum(0,&request[len-4],sizeof(filter),&filter); + dragon_rwnum(0,&request[len-8],sizeof(skipcount),&skipcount); + dragon_rwnum(0,&request[len-4],sizeof(filter),&filter); } if ( 0 && isCC != 0 ) fprintf(stderr,"txids %s isCC.%d skipcount.%d filter.%d\n",coinaddr,isCC,skipcount,filter); @@ -993,10 +993,10 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req { int32_t vout; uint256 txid; uint8_t funcid,isCC = 0; n = 1; - n += iguana_rwnum(0,&request[n],sizeof(isCC),&isCC); - n += iguana_rwnum(0,&request[n],sizeof(funcid),&funcid); - n += iguana_rwnum(0,&request[n],sizeof(vout),&vout); - n += iguana_rwbignum(0,&request[n],sizeof(txid),(uint8_t *)&txid); + n += dragon_rwnum(0,&request[n],sizeof(isCC),&isCC); + n += dragon_rwnum(0,&request[n],sizeof(funcid),&funcid); + n += dragon_rwnum(0,&request[n],sizeof(vout),&vout); + n += dragon_rwbignum(0,&request[n],sizeof(txid),(uint8_t *)&txid); slen = request[n++]; if ( slen < 63 ) { @@ -1028,7 +1028,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req struct NSPV_ntzsresp N; int32_t height; if ( len == 1+sizeof(height) ) { - iguana_rwnum(0,&request[1],sizeof(height),&height); + dragon_rwnum(0,&request[1],sizeof(height),&height); memset(&N,0,sizeof(N)); if ( (slen= NSPV_getntzsresp(&N,height)) > 0 ) { @@ -1051,8 +1051,8 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req struct NSPV_ntzsproofresp P; uint256 prevntz,nextntz; if ( len == 1+sizeof(prevntz)+sizeof(nextntz) ) { - iguana_rwbignum(0,&request[1],sizeof(prevntz),(uint8_t *)&prevntz); - iguana_rwbignum(0,&request[1+sizeof(prevntz)],sizeof(nextntz),(uint8_t *)&nextntz); + dragon_rwbignum(0,&request[1],sizeof(prevntz),(uint8_t *)&prevntz); + dragon_rwbignum(0,&request[1+sizeof(prevntz)],sizeof(nextntz),(uint8_t *)&nextntz); memset(&P,0,sizeof(P)); if ( (slen= NSPV_getntzsproofresp(&P,prevntz,nextntz)) > 0 ) { @@ -1076,9 +1076,9 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req struct NSPV_txproof P; uint256 txid; int32_t height,vout; if ( len == 1+sizeof(txid)+sizeof(height)+sizeof(vout) ) { - iguana_rwnum(0,&request[1],sizeof(height),&height); - iguana_rwnum(0,&request[1+sizeof(height)],sizeof(vout),&vout); - iguana_rwbignum(0,&request[1+sizeof(height)+sizeof(vout)],sizeof(txid),(uint8_t *)&txid); + dragon_rwnum(0,&request[1],sizeof(height),&height); + dragon_rwnum(0,&request[1+sizeof(height)],sizeof(vout),&vout); + dragon_rwbignum(0,&request[1+sizeof(height)+sizeof(vout)],sizeof(txid),(uint8_t *)&txid); //fprintf(stderr,"got txid %s/v%d ht.%d\n",txid.GetHex().c_str(),vout,height); memset(&P,0,sizeof(P)); if ( (slen= NSPV_gettxproof(&P,vout,txid,height)) > 0 ) @@ -1104,8 +1104,8 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req struct NSPV_spentinfo S; int32_t vout; uint256 txid; if ( len == 1+sizeof(txid)+sizeof(vout) ) { - iguana_rwnum(0,&request[1],sizeof(vout),&vout); - iguana_rwbignum(0,&request[1+sizeof(vout)],sizeof(txid),(uint8_t *)&txid); + dragon_rwnum(0,&request[1],sizeof(vout),&vout); + dragon_rwbignum(0,&request[1+sizeof(vout)],sizeof(txid),(uint8_t *)&txid); memset(&S,0,sizeof(S)); if ( (slen= NSPV_getspentinfo(&S,txid,vout)) > 0 ) { @@ -1128,8 +1128,8 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req struct NSPV_broadcastresp B; uint32_t n,offset; uint256 txid; if ( len > 1+sizeof(txid)+sizeof(n) ) { - iguana_rwbignum(0,&request[1],sizeof(txid),(uint8_t *)&txid); - iguana_rwnum(0,&request[1+sizeof(txid)],sizeof(n),&n); + dragon_rwbignum(0,&request[1],sizeof(txid),(uint8_t *)&txid); + dragon_rwnum(0,&request[1+sizeof(txid)],sizeof(n),&n); memset(&B,0,sizeof(B)); offset = 1 + sizeof(txid) + sizeof(n); if ( n < MAX_TX_SIZE_AFTER_SAPLING && request.size() == offset+n && (slen= NSPV_sendrawtransaction(&B,&request[offset],n)) > 0 ) @@ -1152,7 +1152,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req { struct NSPV_remoterpcresp R; int32_t p; p = 1; - p+=iguana_rwnum(0,&request[p],sizeof(slen),&slen); + p+=dragon_rwnum(0,&request[p],sizeof(slen),&slen); memset(&R,0,sizeof(R)); if (request.size() == p+slen && (slen=NSPV_remoterpc(&R,(char *)&request[p],slen))>0 ) { @@ -1191,9 +1191,9 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req memcpy(coinaddr, &request[n], addrlen); coinaddr[addrlen] = 0; n += addrlen; - iguana_rwnum(0, &request[n], sizeof(amount), &amount); + dragon_rwnum(0, &request[n], sizeof(amount), &amount); n += sizeof(amount); - iguana_rwnum(0, &request[n], sizeof(evalcode), &evalcode); + dragon_rwnum(0, &request[n], sizeof(evalcode), &evalcode); n += sizeof(evalcode); int32_t funcidslen = request[n++]; @@ -1202,7 +1202,7 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req memcpy(funcids, &request[n], funcidslen); funcids[funcidslen] = 0; n += funcidslen; - iguana_rwbignum(0, &request[n], sizeof(filtertxid), (uint8_t *)&filtertxid); + dragon_rwbignum(0, &request[n], sizeof(filtertxid), (uint8_t *)&filtertxid); std::cerr << __func__ << " " << "request addr=" << coinaddr << " amount=" << amount << " evalcode=" << (int)evalcode << " funcids=" << funcids << " filtertxid=" << filtertxid.GetHex() << std::endl; memset(&U, 0, sizeof(U)); diff --git a/src/komodo_nSPV_superlite.h b/src/komodo_nSPV_superlite.h index 3d56d44ba..6244359fd 100644 --- a/src/komodo_nSPV_superlite.h +++ b/src/komodo_nSPV_superlite.h @@ -293,7 +293,7 @@ void komodo_nSPV(CNode *pto) // polling loop from SendMessages reqht = 0; len = 0; msg[len++] = NSPV_INFO; - len += iguana_rwnum(1,&msg[len],sizeof(reqht),&reqht); + len += dragon_rwnum(1,&msg[len],sizeof(reqht),&reqht); //fprintf(stderr,"issue getinfo\n"); NSPV_req(pto,msg,len,NODE_NSPV,NSPV_INFO>>1); } @@ -556,7 +556,7 @@ UniValue NSPV_getinfo_req(int32_t reqht) uint8_t msg[512]; int32_t i,iter,len = 0; struct NSPV_inforesp I; NSPV_inforesp_purge(&NSPV_inforesult); msg[len++] = NSPV_INFO; - len += iguana_rwnum(1,&msg[len],sizeof(reqht),&reqht); + len += dragon_rwnum(1,&msg[len],sizeof(reqht),&reqht); for (iter=0; iter<3; iter++) if ( NSPV_req(0,msg,len,NODE_NSPV,msg[0]>>1) != 0 ) { @@ -609,8 +609,8 @@ UniValue NSPV_addressutxos(char *coinaddr,int32_t CCflag,int32_t skipcount,int32 msg[len++] = slen; memcpy(&msg[len],coinaddr,slen), len += slen; msg[len++] = (CCflag != 0); - len += iguana_rwnum(1,&msg[len],sizeof(skipcount),&skipcount); - len += iguana_rwnum(1,&msg[len],sizeof(filter),&filter); + len += dragon_rwnum(1,&msg[len],sizeof(skipcount),&skipcount); + len += dragon_rwnum(1,&msg[len],sizeof(filter),&filter); for (iter=0; iter<3; iter++) if ( NSPV_req(0,msg,len,NODE_ADDRINDEX,msg[0]>>1) != 0 ) { @@ -646,8 +646,8 @@ UniValue NSPV_addresstxids(char *coinaddr,int32_t CCflag,int32_t skipcount,int32 msg[len++] = slen; memcpy(&msg[len],coinaddr,slen), len += slen; msg[len++] = (CCflag != 0); - len += iguana_rwnum(1,&msg[len],sizeof(skipcount),&skipcount); - len += iguana_rwnum(1,&msg[len],sizeof(filter),&filter); + len += dragon_rwnum(1,&msg[len],sizeof(skipcount),&skipcount); + len += dragon_rwnum(1,&msg[len],sizeof(filter),&filter); //fprintf(stderr,"skipcount.%d\n",skipcount); for (iter=0; iter<3; iter++) if ( NSPV_req(0,msg,len,NODE_ADDRINDEX,msg[0]>>1) != 0 ) @@ -681,9 +681,9 @@ UniValue NSPV_ccaddresstxids(char *coinaddr,int32_t CCflag,int32_t skipcount,uin vout=skipcount << 16 | evalcode << 8 | func; msg[len++] = NSPV_MEMPOOL; msg[len++] = (CCflag != 0); - len += iguana_rwnum(1,&msg[len],sizeof(funcid),&funcid); - len += iguana_rwnum(1,&msg[len],sizeof(vout),&vout); - len += iguana_rwbignum(1,&msg[len],sizeof(filtertxid),(uint8_t *)&filtertxid); + len += dragon_rwnum(1,&msg[len],sizeof(funcid),&funcid); + len += dragon_rwnum(1,&msg[len],sizeof(vout),&vout); + len += dragon_rwbignum(1,&msg[len],sizeof(filtertxid),(uint8_t *)&filtertxid); slen = (int32_t)strlen(coinaddr); msg[len++] = slen; memcpy(&msg[len],coinaddr,slen), len += slen; @@ -719,9 +719,9 @@ UniValue NSPV_mempooltxids(char *coinaddr,int32_t CCflag,uint8_t funcid,uint256 } msg[len++] = NSPV_MEMPOOL; msg[len++] = (CCflag != 0); - len += iguana_rwnum(1,&msg[len],sizeof(funcid),&funcid); - len += iguana_rwnum(1,&msg[len],sizeof(vout),&vout); - len += iguana_rwbignum(1,&msg[len],sizeof(txid),(uint8_t *)&txid); + len += dragon_rwnum(1,&msg[len],sizeof(funcid),&funcid); + len += dragon_rwnum(1,&msg[len],sizeof(vout),&vout); + len += dragon_rwbignum(1,&msg[len],sizeof(txid),(uint8_t *)&txid); slen = (int32_t)strlen(coinaddr); msg[len++] = slen; memcpy(&msg[len],coinaddr,slen), len += slen; @@ -792,7 +792,7 @@ UniValue NSPV_notarizations(int32_t reqheight) return(NSPV_ntzsresp_json(ptr)); } msg[len++] = NSPV_NTZS; - len += iguana_rwnum(1,&msg[len],sizeof(reqheight),&reqheight); + len += dragon_rwnum(1,&msg[len],sizeof(reqheight),&reqheight); for (iter=0; iter<3; iter++) if ( NSPV_req(0,msg,len,NODE_NSPV,msg[0]>>1) != 0 ) { @@ -819,8 +819,8 @@ UniValue NSPV_txidhdrsproof(uint256 prevtxid,uint256 nexttxid) } NSPV_ntzsproofresp_purge(&NSPV_ntzsproofresult); msg[len++] = NSPV_NTZSPROOF; - len += iguana_rwbignum(1,&msg[len],sizeof(prevtxid),(uint8_t *)&prevtxid); - len += iguana_rwbignum(1,&msg[len],sizeof(nexttxid),(uint8_t *)&nexttxid); + len += dragon_rwbignum(1,&msg[len],sizeof(prevtxid),(uint8_t *)&prevtxid); + len += dragon_rwbignum(1,&msg[len],sizeof(nexttxid),(uint8_t *)&nexttxid); for (iter=0; iter<3; iter++) if ( NSPV_req(0,msg,len,NODE_NSPV,msg[0]>>1) != 0 ) { @@ -857,9 +857,9 @@ UniValue NSPV_txproof(int32_t vout,uint256 txid,int32_t height) } NSPV_txproof_purge(&NSPV_txproofresult); msg[len++] = NSPV_TXPROOF; - len += iguana_rwnum(1,&msg[len],sizeof(height),&height); - len += iguana_rwnum(1,&msg[len],sizeof(vout),&vout); - len += iguana_rwbignum(1,&msg[len],sizeof(txid),(uint8_t *)&txid); + len += dragon_rwnum(1,&msg[len],sizeof(height),&height); + len += dragon_rwnum(1,&msg[len],sizeof(vout),&vout); + len += dragon_rwbignum(1,&msg[len],sizeof(txid),(uint8_t *)&txid); fprintf(stderr,"req txproof %s/v%d at height.%d\n",txid.GetHex().c_str(),vout,height); for (iter=0; iter<3; iter++) if ( NSPV_req(0,msg,len,NODE_NSPV,msg[0]>>1) != 0 ) @@ -881,8 +881,8 @@ UniValue NSPV_spentinfo(uint256 txid,int32_t vout) uint8_t msg[512]; int32_t i,iter,len = 0; struct NSPV_spentinfo I; NSPV_spentinfo_purge(&NSPV_spentresult); msg[len++] = NSPV_SPENTINFO; - len += iguana_rwnum(1,&msg[len],sizeof(vout),&vout); - len += iguana_rwbignum(1,&msg[len],sizeof(txid),(uint8_t *)&txid); + len += dragon_rwnum(1,&msg[len],sizeof(vout),&vout); + len += dragon_rwbignum(1,&msg[len],sizeof(txid),(uint8_t *)&txid); for (iter=0; iter<3; iter++) if ( NSPV_req(0,msg,len,NODE_SPENTINDEX,msg[0]>>1) != 0 ) { @@ -907,8 +907,8 @@ UniValue NSPV_broadcast(char *hex) txid = NSPV_doublesha256(data,n); msg = (uint8_t *)malloc(1 + sizeof(txid) + sizeof(n) + n); msg[len++] = NSPV_BROADCAST; - len += iguana_rwbignum(1,&msg[len],sizeof(txid),(uint8_t *)&txid); - len += iguana_rwnum(1,&msg[len],sizeof(n),&n); + len += dragon_rwbignum(1,&msg[len],sizeof(txid),(uint8_t *)&txid); + len += dragon_rwnum(1,&msg[len],sizeof(n),&n); memcpy(&msg[len],data,n), len += n; free(data); //fprintf(stderr,"send txid.%s\n",txid.GetHex().c_str()); @@ -953,14 +953,14 @@ UniValue NSPV_ccmoduleutxos(char *coinaddr, int64_t amount, uint8_t evalcode, st msg[len++] = slen; memcpy(&msg[len], coinaddr, slen), len += slen; - len += iguana_rwnum(1, &msg[len], sizeof(amount), &amount); - len += iguana_rwnum(1, &msg[len], sizeof(evalcode), &evalcode); + len += dragon_rwnum(1, &msg[len], sizeof(amount), &amount); + len += dragon_rwnum(1, &msg[len], sizeof(evalcode), &evalcode); slen = (int32_t)(funcids.size()); msg[len++] = slen; memcpy(&msg[len], funcids.data(), slen), len += slen; - len += iguana_rwbignum(1, &msg[len], sizeof(filtertxid), (uint8_t *)&filtertxid); + len += dragon_rwbignum(1, &msg[len], sizeof(filtertxid), (uint8_t *)&filtertxid); for (iter = 0; iter<3; iter++) if (NSPV_req(0, msg, len, NODE_ADDRINDEX, msg[0] >> 1) != 0) { diff --git a/src/komodo_pax.h b/src/komodo_pax.h index 9935f3463..787295a0f 100644 --- a/src/komodo_pax.h +++ b/src/komodo_pax.h @@ -197,16 +197,16 @@ int32_t dpow_readprices(int32_t height,uint8_t *data,uint32_t *timestampp,double uint32_t kmdbtc,btcusd,cnyusd; int32_t i,n,nonz,len = 0; if ( data[0] == 'P' && data[5] == 35 ) data++; - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)timestampp); - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&n); + len += dragon_rwnum(0,&data[len],sizeof(uint32_t),(void *)timestampp); + len += dragon_rwnum(0,&data[len],sizeof(uint32_t),(void *)&n); if ( n != 35 ) { printf("dpow_readprices illegal n.%d\n",n); return(-1); } - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&kmdbtc); // /= 1000 - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&btcusd); // *= 1000 - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&cnyusd); + len += dragon_rwnum(0,&data[len],sizeof(uint32_t),(void *)&kmdbtc); // /= 1000 + len += dragon_rwnum(0,&data[len],sizeof(uint32_t),(void *)&btcusd); // *= 1000 + len += dragon_rwnum(0,&data[len],sizeof(uint32_t),(void *)&cnyusd); *KMDBTCp = ((double)kmdbtc / (1000000000. * 1000.)); *BTCUSDp = PAX_BTCUSD(height,btcusd); *CNYUSDp = ((double)cnyusd / 1000000000.); @@ -216,7 +216,7 @@ int32_t dpow_readprices(int32_t height,uint8_t *data,uint32_t *timestampp,double nonz++; //else if ( nonz != 0 ) // printf("pvals[%d] is zero\n",i); - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&pvals[i]); + len += dragon_rwnum(0,&data[len],sizeof(uint32_t),(void *)&pvals[i]); //printf("%u ",pvals[i]); } /*if ( nonz < n-3 ) @@ -249,7 +249,7 @@ int32_t komodo_pax_opreturn(int32_t height,uint8_t *opret,int32_t maxsize) { if ( (retval= (int32_t)fread(data,1,fsize,fp)) == fsize ) { - len = iguana_rwnum(0,data,sizeof(crc32),(void *)&crc32); + len = dragon_rwnum(0,data,sizeof(crc32),(void *)&crc32); check = calc_crc32(0,data+sizeof(crc32),(int32_t)(fsize-sizeof(crc32))); if ( check == crc32 ) { @@ -301,7 +301,7 @@ int32_t PAX_pubkey(int32_t rwflag,uint8_t *pubkey33,uint8_t *addrtypep,uint8_t r memset(pubkey33,0,33); pubkey33[0] = 0x02 | (*shortflagp != 0); memcpy(&pubkey33[1],fiat,3); - iguana_rwnum(rwflag,&pubkey33[4],sizeof(*fiatoshisp),(void *)fiatoshisp); + dragon_rwnum(rwflag,&pubkey33[4],sizeof(*fiatoshisp),(void *)fiatoshisp); pubkey33[12] = *addrtypep; memcpy(&pubkey33[13],rmd160,20); } @@ -310,7 +310,7 @@ int32_t PAX_pubkey(int32_t rwflag,uint8_t *pubkey33,uint8_t *addrtypep,uint8_t r *shortflagp = (pubkey33[0] == 0x03); memcpy(fiat,&pubkey33[1],3); fiat[3] = 0; - iguana_rwnum(rwflag,&pubkey33[4],sizeof(*fiatoshisp),(void *)fiatoshisp); + dragon_rwnum(rwflag,&pubkey33[4],sizeof(*fiatoshisp),(void *)fiatoshisp); if ( *shortflagp != 0 ) *fiatoshisp = -(*fiatoshisp); *addrtypep = pubkey33[12]; diff --git a/src/komodo_port.c b/src/komodo_port.c index fd68db881..fe05b0e3f 100644 --- a/src/komodo_port.c +++ b/src/komodo_port.c @@ -727,7 +727,7 @@ void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen) calc_rmd160(0,rmd160,hash.bytes,sizeof(hash)); } -int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp) +int32_t dragon_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp) { int32_t i; uint64_t x; if ( rwflag == 0 ) @@ -767,7 +767,7 @@ uint32_t komodo_assetmagic(char *symbol,uint64_t supply,uint8_t *extraptr,int32_ uint8_t buf[512]; uint32_t crc0=0; int32_t len = 0; bits256 hash; if ( strcmp(symbol,"KMD") == 0 ) return(0x8de4eef9); - len = iguana_rwnum(1,&buf[len],sizeof(supply),(void *)&supply); + len = dragon_rwnum(1,&buf[len],sizeof(supply),(void *)&supply); strcpy((char *)&buf[len],symbol); len += strlen(symbol); if ( extraptr != 0 && extralen != 0 ) @@ -821,12 +821,12 @@ uint16_t komodo_calcport(char *name,uint64_t supply,uint64_t endsubsidy,uint64_t //printf("end.%llu reward.%llu halving.%llu decay.%llu perc.%llu\n",(long long)endsubsidy,(long long)reward,(long long)halving,(long long)decay,(long long)commission); extraptr = extrabuf; memcpy(extraptr,ASSETCHAINS_OVERRIDE_PUBKEY33,33), extralen = 33; - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(endsubsidy),(void *)&endsubsidy); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(reward),(void *)&reward); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(halving),(void *)&halving); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(decay),(void *)&decay); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(endsubsidy),(void *)&endsubsidy); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(reward),(void *)&reward); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(halving),(void *)&halving); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(decay),(void *)&decay); val = commission | (((uint64_t)staked & 0xff) << 32) | (((uint64_t)cc & 0xffffff) << 40); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(val),(void *)&val); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(val),(void *)&val); } return(komodo_port(name,supply,&ASSETCHAINS_MAGIC,extraptr,extralen)); } diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 2e4e679ca..ff55c2833 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -927,7 +927,7 @@ char *bits256_str(char hexstr[65],bits256 x) return(hexstr); } -int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp) +int32_t dragon_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp) { int32_t i; uint64_t x; if ( rwflag == 0 ) @@ -962,7 +962,7 @@ int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endian return(len); } -int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp) +int32_t dragon_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp) { int32_t i; if ( rwflag == 0 ) @@ -1282,7 +1282,7 @@ int32_t queue_size(queue_t *queue) return count; } -void iguana_initQ(queue_t *Q,char *name) +void dragon_initQ(queue_t *Q,char *name) { struct queueitem *item,*I; memset(Q,0,sizeof(*Q)); @@ -1465,7 +1465,7 @@ uint32_t komodo_assetmagic(char *symbol,uint64_t supply,uint8_t *extraptr,int32_ uint8_t buf[512]; uint32_t crc0=0; int32_t len = 0; bits256 hash; if ( strcmp(symbol,"KMD") == 0 ) return(0x8de4eef9); - len = iguana_rwnum(1,&buf[len],sizeof(supply),(void *)&supply); + len = dragon_rwnum(1,&buf[len],sizeof(supply),(void *)&supply); strcpy((char *)&buf[len],symbol); len += strlen(symbol); if ( extraptr != 0 && extralen != 0 ) @@ -1510,7 +1510,7 @@ uint16_t komodo_port(char *symbol,uint64_t supply,uint32_t *magicp,uint8_t *extr printf("ports\n"); }*/ -char *iguanafmtstr = (char *)"curl --url \"http://127.0.0.1:7776\" --data \"{\\\"conf\\\":\\\"%s.conf\\\",\\\"path\\\":\\\"${HOME#\"/\"}/.komodo/%s\\\",\\\"unitval\\\":\\\"20\\\",\\\"zcash\\\":1,\\\"RELAY\\\":-1,\\\"VALIDATE\\\":0,\\\"prefetchlag\\\":-1,\\\"poll\\\":100,\\\"active\\\":1,\\\"agent\\\":\\\"iguana\\\",\\\"method\\\":\\\"addcoin\\\",\\\"startpend\\\":4,\\\"endpend\\\":4,\\\"services\\\":129,\\\"maxpeers\\\":8,\\\"newcoin\\\":\\\"%s\\\",\\\"name\\\":\\\"%s\\\",\\\"hasheaders\\\":1,\\\"useaddmultisig\\\":0,\\\"netmagic\\\":\\\"%s\\\",\\\"p2p\\\":%u,\\\"rpc\\\":%u,\\\"pubval\\\":60,\\\"p2shval\\\":85,\\\"wifval\\\":188,\\\"txfee_satoshis\\\":\\\"10000\\\",\\\"isPoS\\\":0,\\\"minoutput\\\":10000,\\\"minconfirms\\\":2,\\\"genesishash\\\":\\\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\\\",\\\"protover\\\":170002,\\\"genesisblock\\\":\\\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\\\",\\\"debug\\\":0,\\\"seedipaddr\\\":\\\"%s\\\",\\\"sapling\\\":1,\\\"notarypay\\\":%i}\""; +char *dragonfmtstr = (char *)"curl --url \"http://127.0.0.1:7776\" --data \"{\\\"conf\\\":\\\"%s.conf\\\",\\\"path\\\":\\\"${HOME#\"/\"}/.komodo/%s\\\",\\\"unitval\\\":\\\"20\\\",\\\"zcash\\\":1,\\\"RELAY\\\":-1,\\\"VALIDATE\\\":0,\\\"prefetchlag\\\":-1,\\\"poll\\\":100,\\\"active\\\":1,\\\"agent\\\":\\\"dragon\\\",\\\"method\\\":\\\"addcoin\\\",\\\"startpend\\\":4,\\\"endpend\\\":4,\\\"services\\\":129,\\\"maxpeers\\\":8,\\\"newcoin\\\":\\\"%s\\\",\\\"name\\\":\\\"%s\\\",\\\"hasheaders\\\":1,\\\"useaddmultisig\\\":0,\\\"netmagic\\\":\\\"%s\\\",\\\"p2p\\\":%u,\\\"rpc\\\":%u,\\\"pubval\\\":60,\\\"p2shval\\\":85,\\\"wifval\\\":188,\\\"txfee_satoshis\\\":\\\"10000\\\",\\\"isPoS\\\":0,\\\"minoutput\\\":10000,\\\"minconfirms\\\":2,\\\"genesishash\\\":\\\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\\\",\\\"protover\\\":170002,\\\"genesisblock\\\":\\\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\\\",\\\"debug\\\":0,\\\"seedipaddr\\\":\\\"%s\\\",\\\"sapling\\\":1,\\\"notarypay\\\":%i}\""; @@ -2162,58 +2162,58 @@ void komodo_args(char *argv0) (long long)ASSETCHAINS_NOTARY_PAY[i]); // TODO: Verify that we don't overrun extrabuf here, which is a 256 byte buffer - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_ENDSUBSIDY[i]),(void *)&ASSETCHAINS_ENDSUBSIDY[i]); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_REWARD[i]),(void *)&ASSETCHAINS_REWARD[i]); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_HALVING[i]),(void *)&ASSETCHAINS_HALVING[i]); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_DECAY[i]),(void *)&ASSETCHAINS_DECAY[i]); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_ENDSUBSIDY[i]),(void *)&ASSETCHAINS_ENDSUBSIDY[i]); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_REWARD[i]),(void *)&ASSETCHAINS_REWARD[i]); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_HALVING[i]),(void *)&ASSETCHAINS_HALVING[i]); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_DECAY[i]),(void *)&ASSETCHAINS_DECAY[i]); if ( ASSETCHAINS_NOTARY_PAY[0] != 0 ) - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_NOTARY_PAY[i]),(void *)&ASSETCHAINS_NOTARY_PAY[i]); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_NOTARY_PAY[i]),(void *)&ASSETCHAINS_NOTARY_PAY[i]); } if (ASSETCHAINS_LASTERA > 0) { - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_LASTERA),(void *)&ASSETCHAINS_LASTERA); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_LASTERA),(void *)&ASSETCHAINS_LASTERA); } // hash in lock above for time locked coinbase transactions above a certain reward value only if the lock above // param was specified, otherwise, for compatibility, do nothing if ( ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF ) { - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_TIMELOCKGTE),(void *)&ASSETCHAINS_TIMELOCKGTE); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_TIMEUNLOCKFROM),(void *)&ASSETCHAINS_TIMEUNLOCKFROM); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_TIMEUNLOCKTO),(void *)&ASSETCHAINS_TIMEUNLOCKTO); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_TIMELOCKGTE),(void *)&ASSETCHAINS_TIMELOCKGTE); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_TIMEUNLOCKFROM),(void *)&ASSETCHAINS_TIMEUNLOCKFROM); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_TIMEUNLOCKTO),(void *)&ASSETCHAINS_TIMEUNLOCKTO); } if ( ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH ) { - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_ALGO),(void *)&ASSETCHAINS_ALGO); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_ALGO),(void *)&ASSETCHAINS_ALGO); } if ( ASSETCHAINS_LWMAPOS != 0 ) { - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_LWMAPOS),(void *)&ASSETCHAINS_LWMAPOS); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_LWMAPOS),(void *)&ASSETCHAINS_LWMAPOS); } val = ASSETCHAINS_COMMISSION | (((int64_t)ASSETCHAINS_STAKED & 0xff) << 32) | (((uint64_t)ASSETCHAINS_CC & 0xffff) << 40) | ((ASSETCHAINS_PUBLIC != 0) << 7) | ((ASSETCHAINS_PRIVATE != 0) << 6) | ASSETCHAINS_TXPOW; - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(val),(void *)&val); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(val),(void *)&val); if ( ASSETCHAINS_FOUNDERS != 0 ) { uint8_t tmp = 1; - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(tmp),(void *)&tmp); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(tmp),(void *)&tmp); if ( ASSETCHAINS_FOUNDERS > 1 ) - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_FOUNDERS),(void *)&ASSETCHAINS_FOUNDERS); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_FOUNDERS),(void *)&ASSETCHAINS_FOUNDERS); if ( ASSETCHAINS_FOUNDERS_REWARD != 0 ) { fprintf(stderr, "set founders reward.%lld\n",(long long)ASSETCHAINS_FOUNDERS_REWARD); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_FOUNDERS_REWARD),(void *)&ASSETCHAINS_FOUNDERS_REWARD); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_FOUNDERS_REWARD),(void *)&ASSETCHAINS_FOUNDERS_REWARD); } } if ( ASSETCHAINS_SCRIPTPUB.size() > 1 ) { decode_hex(&extraptr[extralen],ASSETCHAINS_SCRIPTPUB.size()/2,(char *)ASSETCHAINS_SCRIPTPUB.c_str()); extralen += ASSETCHAINS_SCRIPTPUB.size()/2; - //extralen += iguana_rwnum(1,&extraptr[extralen],(int32_t)ASSETCHAINS_SCRIPTPUB.size(),(void *)ASSETCHAINS_SCRIPTPUB.c_str()); + //extralen += dragon_rwnum(1,&extraptr[extralen],(int32_t)ASSETCHAINS_SCRIPTPUB.size(),(void *)ASSETCHAINS_SCRIPTPUB.c_str()); fprintf(stderr,"append ac_script %s\n",ASSETCHAINS_SCRIPTPUB.c_str()); } if ( ASSETCHAINS_SELFIMPORT.size() > 0 ) @@ -2246,7 +2246,7 @@ fprintf(stderr,"extralen.%d before disable bits\n",extralen); fprintf(stderr," <- CCLIB name\n"); } if ( ASSETCHAINS_BLOCKTIME != 60 ) - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_BLOCKTIME),(void *)&ASSETCHAINS_BLOCKTIME); + extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_BLOCKTIME),(void *)&ASSETCHAINS_BLOCKTIME); if ( Mineropret.size() != 0 ) { for (i=0; i overrideMinSigs ) minsigs = (num_notaries_STAKED[era] / 5) + 1; else minsigs = overrideMinSigs; - json.push_back(Pair("port",iguanaPort)); + json.push_back(Pair("port",dragonPort)); json.push_back(Pair("BTCminsigs",BTCminsigs)); json.push_back(Pair("minsigs",minsigs)); json.push_back(Pair("seeds",seeds)); diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 22c8c7eae..f6b3ab480 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -298,7 +298,7 @@ static const CRPCCommand vRPCCommands[] = // --------------------- ------------------------ ----------------------- ---------- /* Overall control/query calls */ { "control", "help", &help, true }, - { "control", "getiguanajson", &getiguanajson, true }, + { "control", "getdragonjson", &getdragonjson, true }, { "control", "getnotarysendmany", &getnotarysendmany, true }, { "control", "geterablockheights", &geterablockheights, true }, { "control", "stop", &stop, true }, diff --git a/src/rpc/server.h b/src/rpc/server.h index 69c50add3..bbcbc05ed 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -391,7 +391,7 @@ extern UniValue validateaddress(const UniValue& params, bool fHelp, const CPubKe extern UniValue txnotarizedconfirmed(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue decodeccopret(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue getiguanajson(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue getdragonjson(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue getnotarysendmany(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue geterablockheights(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index f98abe2a1..29f1a15ee 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -587,7 +587,7 @@ int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_ extern int32_t KOMODO_PAX; extern uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; int32_t komodo_is_issuer(); -int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); +int32_t dragon_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); int32_t komodo_isrealtime(int32_t *kmdheightp); int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base); int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); @@ -703,10 +703,10 @@ UniValue kvupdate(const UniValue& params, bool fHelp, const CPubKey& mypk) ret.push_back(Pair("value",params[1].get_str())); ret.push_back(Pair("valuesize",valuesize)); } - iguana_rwnum(1,&keyvalue[0],sizeof(keylen),&keylen); - iguana_rwnum(1,&keyvalue[2],sizeof(valuesize),&valuesize); - iguana_rwnum(1,&keyvalue[4],sizeof(height),&height); - iguana_rwnum(1,&keyvalue[8],sizeof(flags),&flags); + dragon_rwnum(1,&keyvalue[0],sizeof(keylen),&keylen); + dragon_rwnum(1,&keyvalue[2],sizeof(valuesize),&valuesize); + dragon_rwnum(1,&keyvalue[4],sizeof(height),&height); + dragon_rwnum(1,&keyvalue[8],sizeof(flags),&flags); memcpy(&keyvalue[12],key,keylen); if ( value != 0 ) memcpy(&keyvalue[12 + keylen],value,valuesize); @@ -780,7 +780,7 @@ UniValue paxdeposit(const UniValue& params, bool fHelp, const CPubKey& mypk) uint8_t opretbuf[64]; int32_t opretlen; uint64_t fee = komodoshis / 1000; if ( fee < 10000 ) fee = 10000; - iguana_rwnum(1,&pubkey37[33],sizeof(height),&height); + dragon_rwnum(1,&pubkey37[33],sizeof(height),&height); opretlen = komodo_opreturnscript(opretbuf,'D',pubkey37,37); SendMoney(address.Get(),fee,fSubtractFeeFromAmount,wtx,opretbuf,opretlen,komodoshis); return wtx.GetHash().GetHex(); @@ -815,7 +815,7 @@ UniValue paxwithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk) uint8_t opretbuf[64]; int32_t opretlen; uint64_t fee = fiatoshis / 1000; if ( fee < 10000 ) fee = 10000; - iguana_rwnum(1,&pubkey37[33],sizeof(kmdheight),&kmdheight); + dragon_rwnum(1,&pubkey37[33],sizeof(kmdheight),&kmdheight); opretlen = komodo_opreturnscript(opretbuf,'W',pubkey37,37); SendMoney(destaddress.Get(),fee,fSubtractFeeFromAmount,wtx,opretbuf,opretlen,fiatoshis); return wtx.GetHash().GetHex(); @@ -5196,7 +5196,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp + strprintf("%d", MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT) + ") Limit on the maximum number of UTXOs to merge. Set to 0 to use node option -mempooltxinputlimit (before Overwinter), or as many as will fit in the transaction (after Overwinter).\n" "4. shielded_limit (numeric, optional, default=" + strprintf("%d Sapling Notes", MERGE_TO_ADDRESS_DEFAULT_SAPLING_LIMIT) + ") Limit on the maximum number of notes to merge. Set to 0 to merge as many as will fit in the transaction.\n" - "5. maximum_utxo_size (numeric, optional) eg, 0.0001 anything under 10000 satoshies will be merged, ignores 10,000 sat p2pk utxo that iguana uses, and merges coinbase utxo.\n" + "5. maximum_utxo_size (numeric, optional) eg, 0.0001 anything under 10000 satoshies will be merged, ignores 10,000 sat p2pk utxo that dragon uses, and merges coinbase utxo.\n" "6. \"memo\" (string, optional) Encoded as hex. When toaddress is a z-addr, this will be stored in the memo field of the new note.\n" "\nResult:\n" From 5f86d516c35da4c00d09338475e177237cbb7816 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 19:42:08 -0400 Subject: [PATCH 02/31] Document HushDEX z-swaps --- src/cc/dapps/README.md | 52 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/src/cc/dapps/README.md b/src/cc/dapps/README.md index d59878d47..86930e87a 100644 --- a/src/cc/dapps/README.md +++ b/src/cc/dapps/README.md @@ -9,6 +9,8 @@ To compile all dapps in this directory: ## zmigrate - Sprout to Sapling Migration dApp This tool converts Sprout zaddress funds into Sapling funds in a new Sapling address. +This is not applicable to HUSH3, since we have no Sprout funds, but left for historical +purposes. ### Usage @@ -19,10 +21,52 @@ The above command may need to be run multiple times to complete the process. This CLI implementation will be called by GUI wallets, average users do not need to worry about using this low-level tool. -## oraclefeed - feed of price data using oracles +## HushDEX -### Usage +HushDEX forked from the Subatomic Decentralized App (dapp) and we focus purely +on privacy coin swaps, and specifically, shielded swaps between Zcash Protocol +coins. These are called z-swaps. - ./oraclefeed $ACNAME $ORACLETXID $MYPUBKEY $FORMAT $BINDTXID [refcoin_cli] +### Z-swap example + +Alice has 1 ZEC and wants to trade it for 5 HUSH, since she hears HushChat is +pretty awesome and ZEC just goes down in price, always. We represent this in +a diagram like this + + Alice (ZEC) <> Bob (HUSH) + +HushDEX is only concerns with Sapling shielded addresses (zaddrs) which start +with `zs1`. Even though ZEC supports Sprout addresses (which start with `zc`), +they cannot be used on HushDEX. Sprout is unsupported on HushDEX. + +So Alice must make sure her ZEC is in a Sapling zaddr, and then she can use +HushDEX on her computer, to z-swap with Bob, in a decentralized way, with +no centralized service. The system is not completely trustless, users must +trust the developers and miners on the relevant chains to not do nefarious +things. There is no central authority to decide who gets to do what, it's +peer-to-peer like BitTorrent or Tor. + +### Privacy Features of Z-Swaps + + * No KYC + * We will not feed the identity theft industry any more free data + * No IP address limiting + * It is trivial to pay for an IP address from any country in the world + * Alice's address never appears in public data + * Bob's address never appears in public data + * Consequently, Alice and Bob's address cannot be searched for on an explorer + * Since you can't see the address of any transaction, you cannot infer if + the same address appears as sender or receiver in many transactions. + * The amount of the transaction, how much ZEC and how much HUSH, is unknown + * It could be pennies or millions + * The exchange rate of the transaction never appears on the blockchain + * The exchange rate will be leaked to the network p2p layer, but it is never + recorded in blockchain history. If you are not there to record it, it is gone. + * Realistically, it's simple to run a malicious node which records all exchange rates + and so we assume an adversary does this + * Since the exchange rate of ZEC/HUSH is already public data, this is not considered valuable + information leakage. We are leaking the differential of CEX ZEC/HUSH exchange ratio to + this DEX's ratio. + * Adversaries watching all possible public data can infer exchange ratios but no amounts + or addresses, which is considered a massive blow against blockchain analysis. -Supported formats are L and Ihh. Price data from CoinDesk API. From c9a4f252e4a0236ae24eadc8609db4843f1e6900 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 19:42:30 -0400 Subject: [PATCH 03/31] Update subatomic json config --- src/cc/dapps/subatomic.json | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/src/cc/dapps/subatomic.json b/src/cc/dapps/subatomic.json index 7832fdb9e..dbb7df058 100644 --- a/src/cc/dapps/subatomic.json +++ b/src/cc/dapps/subatomic.json @@ -1,27 +1,19 @@ { "authorized": [ - {"chmex":"030754bffcf6dfcb34a20c486ff5a5be5546b9cc16fba9692165272b3f8e98c4af" }, - {"SHossain":"03c8657bd57b6ceb14514a10e99fe8a0cec5a9bc24592df7f66f050e670e4f6bac" }, - {"satinder":"03732f8ef851ff234c74d0df575c2c5b159e2bab3faca4ec52b3f217d5cda5361d" }, - {"ml777":"02453d028c74cb9551e1aaf35113383b6ecbd9f06ff23a4ab1a953429b9763e345" }, - {"tonylhub":"0218e0f435d4544404c25a7759b7f7174d821215085ef936218c5569d975af468b" }, - {"gthub":"036c7de9a5090fbad78b9eea41549ccacc07bd0e9e7f8d290c88f470f3569e1a35" }, - {"zkTrader":"026c6b0b35ec0adc2f8a5c648da1fce634f798c69d5e9fe518400447e88398b830" }, - {"nutellalicka":"03aee08860e0340f0f490a3ef3718d6676882f2d63d4f536dfebb1d348b82c79ee" }, - {"gcharang":"02d3431950c2f0f9654217b6ce3d44468d3a9ca7255741767fdeee7c5ec6b47567" }, - {"jl777":"02b27de3ee5335518b06f69f4fbabb029cfc737613b100996841d5532b324a5a61" } + {"dukeleto":"030554bffcf6dfcb34a20c486ff0a5be5546b9cc16fba969216527263f8e98c4af" }, + {"gilardh":"020554bffcf6dfcb34a20c486ff5a5be5546b9cc06fba9692165272b3f8e98c448" }, + {"nhdigitalcash":"030554bffcf6dfcb34a20c086ff5a5be5546b9cc16fba9692105272b3f8e98c4a0" }, + {"miodrag":"02b25de3ee5335518b06f69f4fbabb029cfc737603b100996841d5532b324a5a61" } ], "tokens":[ - {"RICK.demo":"2b1feef719ecb526b07416dd432bce603ac6dc8bfe794cddf105cb52f6aae3cd"} ], "files":[ - {"filename":"hushd","prices":[{"HUSH":0.1}, {"PIRATE":1}]} + {"filename":"hushd","prices":[{"HUSH":0.1}, {"ZEC":1}]} ], "externalcoins":[ { "BTC":"bitcoin-cli" }, - { "KMD":"komodod-cli" }, - { "CHIPS":"chips-cli" }, - { "PIRATE":"pirate-cli" } + { "HUSH":"hush-cli" }, + { "ZEC":"zcash-cli" } ] } From f589aff1fc25c055632d84a74ca907b7b9e1ae50 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 19:42:57 -0400 Subject: [PATCH 04/31] Get rid of shitty jl777 copy+paste garbage and KMD-isms --- src/cc/dapps/subatomic.c | 52 +++++++--------------------------------- 1 file changed, 9 insertions(+), 43 deletions(-) diff --git a/src/cc/dapps/subatomic.c b/src/cc/dapps/subatomic.c index 2f6ebf824..8ea688abc 100644 --- a/src/cc/dapps/subatomic.c +++ b/src/cc/dapps/subatomic.c @@ -1,3 +1,4 @@ +// Copyright (c) 2019-2020 The Hush developers /****************************************************************************** * Copyright © 2014-2020 The SuperNET Developers. * * * @@ -43,9 +44,7 @@ #define SUBATOMIC_TIMEOUT 60 #define SUBATOMIC_LOCKTIME 3600 #define SUBATOMIC_TXFEE 10000 - #define SUBATOMIC_PRIORITY 5 - #define SUBATOMIC_OPENREQUEST 1 #define SUBATOMIC_APPROVED 2 #define SUBATOMIC_OPENED 3 @@ -130,16 +129,9 @@ char *subatomic_checkname(char *tmpstr,struct msginfo *mp,int32_t baserel,char * } if ( ptr->isexternal == 0 ) { - if ( strcmp(coin,"KMD") != 0 ) - { strcpy(ptr->acname,coin); strcpy(ptr->coinstr,""); - } - else - { - strcpy(ptr->coinstr,coin); strcpy(ptr->acname,""); - } } else { @@ -153,7 +145,6 @@ char *subatomic_checkname(char *tmpstr,struct msginfo *mp,int32_t baserel,char * for (i=1; coin[i]!=0; i++) if ( isupper(coin[i]) == 0 ) return(coin); - if ( strcmp(coin+1,"KMD") != 0 ) ptr->iszaddr = 1; return(coin+1); } @@ -229,11 +220,7 @@ cJSON *_subatomic_rawtransaction(struct coininfo *coin,bits256 txid) int64_t subatomic_getbalance(struct coininfo *coin) { char *coinstr,*acname=""; FILE *fp; int64_t retval = 0; - if ( strcmp(coin->coin,"KMD") != 0 ) - { - acname = coin->coin; - coinstr = ""; - } else coinstr = coin->coin; + coinstr = coin->coin; if ( coin->isfile != 0 ) { if ( (fp= fopen(coin->name+1,"rb")) != 0 ) // if alice, add bob pubkey to fname @@ -327,11 +314,7 @@ bits256 subatomic_coinpayment(uint32_t origid,int32_t OTCmode,struct coininfo *c } else { - if ( strcmp(coin->coin,"KMD") != 0 ) - { - acname = coin->coin; - coinstr = ""; - } else coinstr = coin->coin; + coinstr = coin->coin; if ( coin->istoken != 0 ) txid = tokentransfer(coinstr,acname,coin->tokenid,destpub,paytoshis/SATOSHIDEN); else if ( coin->isexternal == 0 ) @@ -356,11 +339,7 @@ cJSON *subatomic_txidwait(struct coininfo *coin,bits256 txid,char *hexstr,int32_ // if matches, sendrawtransaction if OTC mode, decoode and return if channels mode } zflag = (subatomic_zonly(coin) != 0); - if ( strcmp(coin->coin,"KMD") != 0 ) - { - acname = coin->coin; - coinstr = ""; - } else coinstr = coin->coin; + coinstr = coin->coin; for (i=0; iisfile != 0 ) @@ -421,11 +400,7 @@ int64_t subatomic_verifypayment(struct coininfo *coin,cJSON *rawtx,uint64_t dest item = jitem(array,0); if ( (sobj= jobj(item,"scriptPubKey")) != 0 && (a= jarray(&m,sobj,"addresses")) != 0 && m == 1 ) { - if ( strcmp(coin->coin,"KMD") != 0 ) - { - acname = coin->coin; - coinstr = ""; - } else coinstr = coin->coin; + coinstr = coin->coin; if ( get_tokenaddress(coinstr,acname,tokenaddr) != 0 ) { //fprintf(stderr,"tokenaddr.%s\n",tokenaddr); @@ -775,11 +750,6 @@ int32_t subatomic_approved(struct msginfo *mp,cJSON *approval,cJSON *msgjson,cha if ( mp->OTCmode == 0 ) { coin = (mp->bobflag != 0) ? mp->base.coin : mp->rel.coin; // the other side gets this coin - if ( strcmp(coin,"KMD") != 0 ) - { - acname = coin; - coin = ""; - } if ( get_createmultisig2(coin,acname,mp->msigaddr,mp->redeemscript,mp->alice.secp,mp->bob.secp) != 0 ) { subatomic_redeemscript(redeemscript,mp->locktime,mp->alice.secp,mp->bob.secp); @@ -1233,7 +1203,7 @@ void subatomic_filesregister(int32_t priority) file = jitem(files,i); if ( file != 0 ) { - // {"filename":"komodod",prices:[{"KMD":0.1}, {"PIRATE:1"}]} + // {"filename":"hushd",prices:[{"HUSH":1}, {"ZEC:1"}]} fname = jstr(file,"filename"); if ( (prices= jarray(&m,file,"prices")) != 0 && m > 0 ) { @@ -1343,14 +1313,10 @@ int32_t main(int32_t argc,char **argv) return(-1); } coin = (char *)argv[1]; - if ( argv[2][0] != 0 ) + if ( argv[2][0] != 0 ) { REFCOIN_CLI = (char *)argv[2]; - else - { - if ( strcmp(coin,"KMD") != 0 ) - { - acname = coin; - } + } else { + acname = coin; } hashstr = (char *)argv[3]; strcpy(M.rel.coin,subatomic_checkname(tmpstr,&M,1,coin)); From 293f8bf7d2885255f8538b03e62699f8498d9153 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 20:10:50 -0400 Subject: [PATCH 05/31] We call it HushDEX around here --- src/cc/dapps/{subatomic.c => hushdex.c} | 0 src/cc/dapps/{subatomic.json => hushdex.json} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/cc/dapps/{subatomic.c => hushdex.c} (100%) rename src/cc/dapps/{subatomic.json => hushdex.json} (100%) diff --git a/src/cc/dapps/subatomic.c b/src/cc/dapps/hushdex.c similarity index 100% rename from src/cc/dapps/subatomic.c rename to src/cc/dapps/hushdex.c diff --git a/src/cc/dapps/subatomic.json b/src/cc/dapps/hushdex.json similarity index 100% rename from src/cc/dapps/subatomic.json rename to src/cc/dapps/hushdex.json From 391731b79bf1d88b2960a9f13c74546d2e0e8c58 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 20:13:10 -0400 Subject: [PATCH 06/31] HushDEX is the future of decentralized private trading --- src/cc/dapps/hushdex.c | 314 ++++++++++++++++++++--------------------- 1 file changed, 157 insertions(+), 157 deletions(-) diff --git a/src/cc/dapps/hushdex.c b/src/cc/dapps/hushdex.c index 8ea688abc..f3ac51dce 100644 --- a/src/cc/dapps/hushdex.c +++ b/src/cc/dapps/hushdex.c @@ -14,18 +14,18 @@ * * ******************************************************************************/ -// build subatomic and put in path: git pull; gcc cc/dapps/subatomic.c -lm -o subatomic; cp subatomic /usr/bin +// build hushdex and put in path: git pull; gcc cc/dapps/hushdex.c -lm -o hushdex; cp hushdex /usr/bin // alice sends relcoin and gets basecoin #define DEXP2P_CHAIN ((char *)"DEX") -#define DEXP2P_PUBKEYS ((char *)"subatomic") +#define DEXP2P_PUBKEYS ((char *)"hushdex") #include "dappinc.h" // for OTC mode, the following 4 functions are the only ones that should be needed to support a new "coin" -//int64_t subatomic_getbalance(char *coin); -//bits256 subatomic_coinpayment(int32_t OTCmode,char *coin,char *destaddr,uint64_t paytoshis,char *memostr); -//cJSON *subatomic_txidwait(char *coin,bits256 txid,char *hexstr,int32_t numseconds); -//int64_t subatomic_verifypayment(char *coin,cJSON *rawtx,uint64_t destsatoshis,char *destaddr); +//int64_t hushdex_getbalance(char *coin); +//bits256 hushdex_coinpayment(int32_t OTCmode,char *coin,char *destaddr,uint64_t paytoshis,char *memostr); +//cJSON *hushdex_txidwait(char *coin,bits256 txid,char *hexstr,int32_t numseconds); +//int64_t hushdex_verifypayment(char *coin,cJSON *rawtx,uint64_t destsatoshis,char *destaddr); // TODO: // address conversion @@ -79,12 +79,12 @@ struct msginfo struct abinfo alice,bob; } *Messages; -uint64_t subatomic_txfee(char *coin) +uint64_t hushdex_txfee(char *coin) { return(SUBATOMIC_TXFEE); } -char *subatomic_checkname(char *tmpstr,struct msginfo *mp,int32_t baserel,char *coin) +char *hushdex_checkname(char *tmpstr,struct msginfo *mp,int32_t baserel,char *coin) { int32_t i,n; cJSON *external,*item; char *coinstr,*clistr; struct coininfo *ptr; ptr = (baserel == 0) ? &mp->base : &mp->rel; @@ -150,21 +150,21 @@ char *subatomic_checkname(char *tmpstr,struct msginfo *mp,int32_t baserel,char * } } -int32_t subatomic_zonly(struct coininfo *coin) +int32_t hushdex_zonly(struct coininfo *coin) { if ( strcmp(coin->coin,"PIRATE") == 0 ) return(1); else return(coin->iszaddr); } -// //////////////////////////////// the four key functions needed to support a new item for subatomics +// //////////////////////////////// the four key functions needed to support a new item for hushdexs -int64_t _subatomic_getbalance(struct coininfo *coin) +int64_t _hushdex_getbalance(struct coininfo *coin) { cJSON *retjson; char *retstr,cmpstr[64]; int64_t amount=0; - if ( (retjson= subatomic_cli(coin->cli,&retstr,"getbalance","","","","","","","")) != 0 ) + if ( (retjson= hushdex_cli(coin->cli,&retstr,"getbalance","","","","","","","")) != 0 ) { - fprintf(stderr,"_subatomic_getbalance.(%s) %s returned json!\n",coin->coinstr,coin->cli); + fprintf(stderr,"_hushdex_getbalance.(%s) %s returned json!\n",coin->coinstr,coin->cli); free_json(retjson); } else if ( retstr != 0 ) @@ -179,14 +179,14 @@ int64_t _subatomic_getbalance(struct coininfo *coin) return (amount); } -bits256 _subatomic_sendtoaddress(struct coininfo *coin,char *destaddr,int64_t satoshis) +bits256 _hushdex_sendtoaddress(struct coininfo *coin,char *destaddr,int64_t satoshis) { char numstr[32],*retstr,str[65]; cJSON *retjson; bits256 txid; memset(txid.bytes,0,sizeof(txid)); sprintf(numstr,"%.8f",(double)satoshis/SATOSHIDEN); - if ( (retjson= subatomic_cli(coin->cli,&retstr,"sendtoaddress",destaddr,numstr,"false","","","","")) != 0 ) + if ( (retjson= hushdex_cli(coin->cli,&retstr,"sendtoaddress",destaddr,numstr,"false","","","","")) != 0 ) { - fprintf(stderr,"unexpected _subatomic_sendtoaddress json.(%s)\n",jprint(retjson,0)); + fprintf(stderr,"unexpected _hushdex_sendtoaddress json.(%s)\n",jprint(retjson,0)); free_json(retjson); } else if ( retstr != 0 ) @@ -196,28 +196,28 @@ bits256 _subatomic_sendtoaddress(struct coininfo *coin,char *destaddr,int64_t sa retstr[64] = 0; decode_hex(txid.bytes,32,retstr); } - fprintf(stderr,"_subatomic_sendtoaddress %s %.8f txid.(%s)\n",destaddr,(double)satoshis/SATOSHIDEN,bits256_str(str,txid)); + fprintf(stderr,"_hushdex_sendtoaddress %s %.8f txid.(%s)\n",destaddr,(double)satoshis/SATOSHIDEN,bits256_str(str,txid)); free(retstr); } return(txid); } -cJSON *_subatomic_rawtransaction(struct coininfo *coin,bits256 txid) +cJSON *_hushdex_rawtransaction(struct coininfo *coin,bits256 txid) { cJSON *retjson; char *retstr,str[65]; - if ( (retjson= subatomic_cli(coin->cli,&retstr,"getrawtransaction",bits256_str(str,txid),"1","","","","","")) != 0 ) + if ( (retjson= hushdex_cli(coin->cli,&retstr,"getrawtransaction",bits256_str(str,txid),"1","","","","","")) != 0 ) { return(retjson); } else if ( retstr != 0 ) { - fprintf(stderr,"_subatomic_rawtransaction.(%s) %s error.(%s)\n",coin->coin,coin->name,retstr); + fprintf(stderr,"_hushdex_rawtransaction.(%s) %s error.(%s)\n",coin->coin,coin->name,retstr); free(retstr); } return(0); } -int64_t subatomic_getbalance(struct coininfo *coin) +int64_t hushdex_getbalance(struct coininfo *coin) { char *coinstr,*acname=""; FILE *fp; int64_t retval = 0; coinstr = coin->coin; @@ -230,7 +230,7 @@ int64_t subatomic_getbalance(struct coininfo *coin) } return(retval); } - else if ( subatomic_zonly(coin) != 0 ) + else if ( hushdex_zonly(coin) != 0 ) return(z_getbalance(coinstr,acname,DPOW_recvZaddr)); else { @@ -246,11 +246,11 @@ int64_t subatomic_getbalance(struct coininfo *coin) } else if ( coin->isexternal == 0 ) return(get_getbalance(coinstr,acname)); - else return(_subatomic_getbalance(coin)); + else return(_hushdex_getbalance(coin)); } } -bits256 subatomic_coinpayment(uint32_t origid,int32_t OTCmode,struct coininfo *coin,char *destaddr,uint64_t paytoshis,char *memostr,char *destpub,char *senderpub) +bits256 hushdex_coinpayment(uint32_t origid,int32_t OTCmode,struct coininfo *coin,char *destaddr,uint64_t paytoshis,char *memostr,char *destpub,char *senderpub) { bits256 txid; char opidstr[128],opretstr[32],str[65],*status,*coinstr,*acname=""; cJSON *retjson,*retjson2,*item,*res; int32_t i,pending=0; memset(&txid,0,sizeof(txid)); @@ -275,7 +275,7 @@ bits256 subatomic_coinpayment(uint32_t origid,int32_t OTCmode,struct coininfo *c fprintf(stderr,"end broadcast of (%s) to %s\n",coin->coin+1,senderpub); return(txid); } - else if ( subatomic_zonly(coin) != 0 ) + else if ( hushdex_zonly(coin) != 0 ) { if ( memostr[0] == 0 ) memostr = "beef"; @@ -321,13 +321,13 @@ bits256 subatomic_coinpayment(uint32_t origid,int32_t OTCmode,struct coininfo *c { sprintf(opretstr,"%08x",origid); txid = sendtoaddress(coinstr,acname,destaddr,paytoshis,opretstr); - } else txid = _subatomic_sendtoaddress(coin,destaddr,paytoshis); + } else txid = _hushdex_sendtoaddress(coin,destaddr,paytoshis); printf("%u got txid.%s\n",origid,bits256_str(str,txid)); } return(txid); } -cJSON *subatomic_txidwait(struct coininfo *coin,bits256 txid,char *hexstr,int32_t numseconds,char *senderpub) +cJSON *hushdex_txidwait(struct coininfo *coin,bits256 txid,char *hexstr,int32_t numseconds,char *senderpub) { int32_t i,zflag; char *coinstr,str[65],*acname=""; cJSON *rawtx; bits256 z; bits256 filehash; memset(&z,0,sizeof(z)); @@ -338,7 +338,7 @@ cJSON *subatomic_txidwait(struct coininfo *coin,bits256 txid,char *hexstr,int32_ // compare against txid // if matches, sendrawtransaction if OTC mode, decoode and return if channels mode } - zflag = (subatomic_zonly(coin) != 0); + zflag = (hushdex_zonly(coin) != 0); coinstr = coin->coin; for (i=0; iisexternal == 0 ) rawtx = get_rawtransaction(coinstr,acname,txid); - else rawtx = _subatomic_rawtransaction(coin,txid); + else rawtx = _hushdex_rawtransaction(coin,txid); if ( rawtx != 0 ) return(rawtx); sleep(1); @@ -368,7 +368,7 @@ cJSON *subatomic_txidwait(struct coininfo *coin,bits256 txid,char *hexstr,int32_ return(0); } -int64_t subatomic_verifypayment(struct coininfo *coin,cJSON *rawtx,uint64_t destsatoshis,char *destaddr,bits256 txid) +int64_t hushdex_verifypayment(struct coininfo *coin,cJSON *rawtx,uint64_t destsatoshis,char *destaddr,bits256 txid) { int32_t i,n,m,valid=0; bits256 tokenid,filehash,checkhash; cJSON *array,*item,*sobj,*a; char *addr,*acname,*coinstr,tokenaddr[64],*hex; uint8_t hexbuf[512],pub33[33]; uint64_t netval,recvsatoshis = 0; if ( coin->isfile != 0 ) @@ -381,7 +381,7 @@ int64_t subatomic_verifypayment(struct coininfo *coin,cJSON *rawtx,uint64_t dest return(SATOSHIDEN); } else return(0); } - else if ( subatomic_zonly(coin) != 0 ) + else if ( hushdex_zonly(coin) != 0 ) { if ( (array= jarray(&n,rawtx,"outputs")) != 0 && n > 0 ) { @@ -448,14 +448,14 @@ int64_t subatomic_verifypayment(struct coininfo *coin,cJSON *rawtx,uint64_t dest } // //////////// end -struct msginfo *subatomic_find(uint32_t origid) +struct msginfo *hushdex_find(uint32_t origid) { struct msginfo *mp; HASH_FIND(hh,Messages,&origid,sizeof(origid),mp); return(mp); } -struct msginfo *subatomic_add(uint32_t origid) +struct msginfo *hushdex_add(uint32_t origid) { struct msginfo *mp = calloc(1,sizeof(*mp)); mp->origid = origid; @@ -463,7 +463,7 @@ struct msginfo *subatomic_add(uint32_t origid) return(mp); } -int32_t subatomic_status(struct msginfo *mp,int32_t status) +int32_t hushdex_status(struct msginfo *mp,int32_t status) { static FILE *fp; if ( fp == 0 ) @@ -501,9 +501,9 @@ int32_t subatomic_status(struct msginfo *mp,int32_t status) exit(-1); } //fprintf(stderr,"%u <- %d\n",oid,s); - if ( (m= subatomic_find(oid)) == 0 ) + if ( (m= hushdex_find(oid)) == 0 ) { - m = subatomic_add(oid); + m = hushdex_add(oid); count++; } if ( s > m->status ) @@ -524,18 +524,18 @@ int32_t subatomic_status(struct msginfo *mp,int32_t status) return(0); } -struct msginfo *subatomic_tracker(uint32_t origid) +struct msginfo *hushdex_tracker(uint32_t origid) { struct msginfo *mp; - if ( (mp= subatomic_find(origid)) == 0 ) + if ( (mp= hushdex_find(origid)) == 0 ) { - mp = subatomic_add(origid); - subatomic_status(mp,0); + mp = hushdex_add(origid); + hushdex_status(mp,0); } return(mp); } -char *subatomic_hexstr(char *jsonstr) +char *hushdex_hexstr(char *jsonstr) { char *hexstr; int32_t i,c,n = (int32_t)strlen(jsonstr); hexstr = malloc(2*n + 3); @@ -552,7 +552,7 @@ char *subatomic_hexstr(char *jsonstr) return(hexstr); } -cJSON *subatomic_mpjson(struct msginfo *mp) +cJSON *hushdex_mpjson(struct msginfo *mp) { cJSON *item; item = cJSON_CreateObject(); @@ -573,12 +573,12 @@ cJSON *subatomic_mpjson(struct msginfo *mp) jaddstr(item,"alicesecp",mp->alice.secp); jaddstr(item,"bob",mp->bob.pubkey); jaddstr(item,"bobsecp",mp->bob.secp); - if ( subatomic_zonly(&mp->rel) != 0 ) + if ( hushdex_zonly(&mp->rel) != 0 ) jaddstr(item,"bobZaddr",mp->bob.recvZaddr); else jaddstr(item,"bobaddr",mp->bob.recvaddr); if ( mp->rel.istoken != 0 ) jaddstr(item,"bobtoken",mp->rel.tokenid); - if ( subatomic_zonly(&mp->base) != 0 ) + if ( hushdex_zonly(&mp->base) != 0 ) jaddstr(item,"aliceZaddr",mp->alice.recvZaddr); else jaddstr(item,"aliceaddr",mp->alice.recvaddr); if ( mp->base.istoken != 0 ) @@ -586,19 +586,19 @@ cJSON *subatomic_mpjson(struct msginfo *mp) return(item); } -uint64_t subatomic_orderbook_mpset(struct msginfo *mp,char *basecheck) +uint64_t hushdex_orderbook_mpset(struct msginfo *mp,char *basecheck) { cJSON *retjson; char *tagA,*tagB,*senderpub,*str,tmpstr[32]; int32_t matches=0; double volA,volB; int64_t txfee=0; strcpy(mp->base.name,basecheck); - strcpy(mp->base.coin,subatomic_checkname(tmpstr,mp,0,basecheck)); - mp->rel.txfee = subatomic_txfee(mp->rel.coin); + strcpy(mp->base.coin,hushdex_checkname(tmpstr,mp,0,basecheck)); + mp->rel.txfee = hushdex_txfee(mp->rel.coin); if ( (retjson= dpow_get(mp->origid)) != 0 ) { //fprintf(stderr,"dpow_get.(%s) (%s/%s)\n",jprint(retjson,0),mp->base.coin,mp->rel.coin); if ( (senderpub= jstr(retjson,"senderpub")) != 0 && is_hexstr(senderpub,0) == 66 && (tagA= jstr(retjson,"tagA")) != 0 && (tagB= jstr(retjson,"tagB")) != 0 && strncmp(tagB,mp->rel.name,strlen(mp->rel.name)) == 0 && strlen(tagA) < sizeof(mp->base.name) ) { strcpy(mp->base.name,tagA); - strcpy(mp->base.coin,subatomic_checkname(tmpstr,mp,0,tagA)); + strcpy(mp->base.coin,hushdex_checkname(tmpstr,mp,0,tagA)); if ( basecheck[0] == 0 || strncmp(basecheck,tagA,strlen(basecheck)) == 0 ) matches = 1; else if ( strcmp(tagA,mp->base.name) == 0 ) @@ -610,7 +610,7 @@ uint64_t subatomic_orderbook_mpset(struct msginfo *mp,char *basecheck) if ( (str= jstr(retjson,"decrypted")) != 0 && strlen(str) < 128 ) strcpy(mp->payload,str); mp->locktime = juint(retjson,"timestamp") + SUBATOMIC_LOCKTIME; - mp->base.txfee = subatomic_txfee(mp->base.coin); + mp->base.txfee = hushdex_txfee(mp->base.coin); strcpy(mp->senderpub,senderpub); volB = jdouble(retjson,"amountB"); volA = jdouble(retjson,"amountA"); @@ -640,7 +640,7 @@ char *randhashstr(char *str) return(str); } -void subatomic_extrafields(cJSON *dest,cJSON *src) +void hushdex_extrafields(cJSON *dest,cJSON *src) { char *str; if ( (str= jstr(src,"approval")) != 0 ) @@ -669,12 +669,12 @@ void subatomic_extrafields(cJSON *dest,cJSON *src) jaddstr(dest,"bobtoken",str); } -char *subatomic_submit(cJSON *argjson,int32_t tobob) +char *hushdex_submit(cJSON *argjson,int32_t tobob) { char *jsonstr,*hexstr; jaddnum(argjson,"tobob",tobob != 0); jsonstr = jprint(argjson,1); - hexstr = subatomic_hexstr(jsonstr); + hexstr = hushdex_hexstr(jsonstr); free(jsonstr); return(hexstr); } @@ -695,7 +695,7 @@ char *subatomic_submit(cJSON *argjson,int32_t tobob) #define SCRIPT_OP_CHECKMULTISIGVERIFY 0xaf #define SCRIPT_OP_CHECKLOCKTIMEVERIFY 0xb1 -int32_t subatomic_redeemscript(char *redeemscript,uint32_t locktime,char *pubkeyA,char *pubkeyB) // not needed +int32_t hushdex_redeemscript(char *redeemscript,uint32_t locktime,char *pubkeyA,char *pubkeyB) // not needed { // if ( refund ) OP_HASH160 <2of2 multisig hash> OP_EQUAL // standard multisig // else CLTV OP_DROP OP_CHECKSIG // standard spend @@ -743,16 +743,16 @@ int32_t subatomic_redeemscript(char *redeemscript,uint32_t locktime,char *pubkey return(n); } -int32_t subatomic_approved(struct msginfo *mp,cJSON *approval,cJSON *msgjson,char *senderpub) +int32_t hushdex_approved(struct msginfo *mp,cJSON *approval,cJSON *msgjson,char *senderpub) { char *hexstr,numstr[32],redeemscript[1024],*coin,*acname=""; cJSON *retjson,*decodejson; int32_t i,retval = 0; - subatomic_extrafields(approval,msgjson); + hushdex_extrafields(approval,msgjson); if ( mp->OTCmode == 0 ) { coin = (mp->bobflag != 0) ? mp->base.coin : mp->rel.coin; // the other side gets this coin if ( get_createmultisig2(coin,acname,mp->msigaddr,mp->redeemscript,mp->alice.secp,mp->bob.secp) != 0 ) { - subatomic_redeemscript(redeemscript,mp->locktime,mp->alice.secp,mp->bob.secp); + hushdex_redeemscript(redeemscript,mp->locktime,mp->alice.secp,mp->bob.secp); if ( (decodejson= get_decodescript(coin,acname,redeemscript)) != 0 ) { fprintf(stderr,"%s %s msigaddr.%s %s -> %s %s\n",mp->bobflag!=0?"bob":"alice",(mp->bobflag != 0) ? mp->base.coin : mp->rel.coin,mp->msigaddr,mp->redeemscript,redeemscript,jprint(decodejson,0)); @@ -767,51 +767,51 @@ int32_t subatomic_approved(struct msginfo *mp,cJSON *approval,cJSON *msgjson,cha i++; mp->approval[i<<1] = 0; jaddstr(approval,"approval",mp->approval); - hexstr = subatomic_submit(approval,!mp->bobflag); + hexstr = hushdex_submit(approval,!mp->bobflag); if ( (retjson= dpow_broadcast(SUBATOMIC_PRIORITY,hexstr,(char *)"inbox",(char *)"approved",senderpub,"","")) != 0 ) { if ( (mp->approvalid= juint(retjson,"id")) != 0 ) retval = 1; printf("%u approvalid.%u (%s)\n",mp->origid,mp->approvalid,senderpub); - subatomic_status(mp,SUBATOMIC_APPROVED); + hushdex_status(mp,SUBATOMIC_APPROVED); free_json(retjson); } free(hexstr); return(retval); } -int32_t subatomic_opened(struct msginfo *mp,cJSON *opened,cJSON *msgjson,char *senderpub) +int32_t hushdex_opened(struct msginfo *mp,cJSON *opened,cJSON *msgjson,char *senderpub) { char *hexstr,channelstr[65]; cJSON *retjson; int32_t retval = 0; - subatomic_extrafields(opened,msgjson); + hushdex_extrafields(opened,msgjson); jaddstr(opened,"opened",randhashstr(channelstr)); - hexstr = subatomic_submit(opened,!mp->bobflag); + hexstr = hushdex_submit(opened,!mp->bobflag); if ( (retjson= dpow_broadcast(SUBATOMIC_PRIORITY,hexstr,(char *)"inbox",(char *)"opened",senderpub,"","")) != 0 ) { if ( (mp->openedid= juint(retjson,"id")) != 0 ) retval = 1; printf("%u openedid.%u\n",mp->origid,mp->openedid); - subatomic_status(mp,SUBATOMIC_OPENED); + hushdex_status(mp,SUBATOMIC_OPENED); free_json(retjson); } free(hexstr); return(retval); } -int32_t subatomic_payment(struct msginfo *mp,cJSON *payment,cJSON *msgjson,char *senderpub) +int32_t hushdex_payment(struct msginfo *mp,cJSON *payment,cJSON *msgjson,char *senderpub) { bits256 txid; uint64_t paytoshis; cJSON *retjson; char numstr[32],*coin,*dest,*hexstr; int32_t retval = 0; if ( mp->bobflag == 0 ) { coin = mp->rel.name; paytoshis = mp->rel.satoshis; - if ( subatomic_zonly(&mp->rel) != 0 ) + if ( hushdex_zonly(&mp->rel) != 0 ) dest = mp->bob.recvZaddr; else dest = mp->bob.recvaddr; sprintf(numstr,"%llu",(long long)paytoshis); jaddstr(payment,"alicepays",numstr); jaddstr(payment,"bobdestaddr",dest); - txid = subatomic_coinpayment(mp->origid,mp->OTCmode,&mp->rel,dest,paytoshis,mp->approval,mp->bob.secp,senderpub); + txid = hushdex_coinpayment(mp->origid,mp->OTCmode,&mp->rel,dest,paytoshis,mp->approval,mp->bob.secp,senderpub); jaddbits256(payment,"alicepayment",txid); mp->alicepayment = txid; hexstr = 0; // get it from rawtransaction of txid @@ -821,60 +821,60 @@ int32_t subatomic_payment(struct msginfo *mp,cJSON *payment,cJSON *msgjson,char { coin = mp->base.name; paytoshis = mp->base.satoshis; - if ( subatomic_zonly(&mp->base) != 0 ) + if ( hushdex_zonly(&mp->base) != 0 ) dest = mp->alice.recvZaddr; else dest = mp->alice.recvaddr; sprintf(numstr,"%llu",(long long)paytoshis); jaddstr(payment,"bobpays",numstr); jaddstr(payment,"alicedestaddr",dest); - txid = subatomic_coinpayment(mp->origid,mp->OTCmode,&mp->base,dest,paytoshis,mp->approval,mp->alice.secp,senderpub); + txid = hushdex_coinpayment(mp->origid,mp->OTCmode,&mp->base,dest,paytoshis,mp->approval,mp->alice.secp,senderpub); jaddbits256(payment,"bobpayment",txid); mp->bobpayment = txid; hexstr = 0; // get it from rawtransaction of txid jaddstr(payment,"bobtx",hexstr); } - hexstr = subatomic_submit(payment,!mp->bobflag); + hexstr = hushdex_submit(payment,!mp->bobflag); if ( (retjson= dpow_broadcast(SUBATOMIC_PRIORITY,hexstr,(char *)"inbox",(char *)"payment",senderpub,"","")) != 0 ) { if ( (mp->paymentids[0]= juint(retjson,"id")) != 0 ) retval = 1; printf("%u: %.8f %s -> %s, paymentid[0] %u\n",mp->origid,dstr(paytoshis),coin,dest,mp->paymentids[0]); - subatomic_status(mp,SUBATOMIC_PAYMENT); + hushdex_status(mp,SUBATOMIC_PAYMENT); free_json(retjson); } free(hexstr); return(retval); } -int32_t subatomic_paidinfull(struct msginfo *mp,cJSON *paid,cJSON *msgjson,char *senderpub) +int32_t hushdex_paidinfull(struct msginfo *mp,cJSON *paid,cJSON *msgjson,char *senderpub) { char *hexstr; cJSON *retjson; int32_t retval = 0; jaddstr(paid,"paid","in full"); - subatomic_extrafields(paid,msgjson); - hexstr = subatomic_submit(paid,!mp->bobflag); + hushdex_extrafields(paid,msgjson); + hexstr = hushdex_submit(paid,!mp->bobflag); if ( (retjson= dpow_broadcast(SUBATOMIC_PRIORITY,hexstr,(char *)"inbox",(char *)"paid",senderpub,"","")) != 0 ) { if ( (mp->paidid= juint(retjson,"id")) != 0 ) retval = 1; printf("%u paidid.%u\n",mp->origid,mp->paidid); - subatomic_status(mp,SUBATOMIC_PAIDINFULL); + hushdex_status(mp,SUBATOMIC_PAIDINFULL); free_json(retjson); } free(hexstr); return(retval); } -int32_t subatomic_closed(struct msginfo *mp,cJSON *closed,cJSON *msgjson,char *senderpub) +int32_t hushdex_closed(struct msginfo *mp,cJSON *closed,cJSON *msgjson,char *senderpub) { char *hexstr; cJSON *retjson; int32_t retval = 0; jaddnum(closed,"closed",mp->origid); - subatomic_extrafields(closed,msgjson); - hexstr = subatomic_submit(closed,!mp->bobflag); + hushdex_extrafields(closed,msgjson); + hexstr = hushdex_submit(closed,!mp->bobflag); if ( (retjson= dpow_broadcast(SUBATOMIC_PRIORITY,hexstr,(char *)"inbox",(char *)"closed",senderpub,"","")) != 0 ) { if ( (mp->closedid= juint(retjson,"id")) != 0 ) retval = 1; - subatomic_status(mp,SUBATOMIC_CLOSED); + hushdex_status(mp,SUBATOMIC_CLOSED); printf("%u closedid.%u\n",mp->origid,mp->closedid); free_json(retjson); } @@ -882,25 +882,25 @@ int32_t subatomic_closed(struct msginfo *mp,cJSON *closed,cJSON *msgjson,char *s return(retval); } -uint32_t subatomic_alice_openrequest(struct msginfo *origmp) +uint32_t hushdex_alice_openrequest(struct msginfo *origmp) { struct msginfo *mp; cJSON *retjson,*openrequest; char *hexstr,*str,tmpstr[32]; - mp = subatomic_tracker(origmp->origid); + mp = hushdex_tracker(origmp->origid); mp->origid = origmp->origid; mp->rel.satoshis = origmp->rel.satoshis; mp->rel.istoken = origmp->rel.istoken; strcpy(mp->rel.tokenid,origmp->rel.tokenid); strcpy(mp->rel.name,origmp->rel.name); - strcpy(mp->rel.coin,subatomic_checkname(tmpstr,mp,1,origmp->rel.name)); + strcpy(mp->rel.coin,hushdex_checkname(tmpstr,mp,1,origmp->rel.name)); strcpy(mp->alice.pubkey,DPOW_pubkeystr); strcpy(mp->alice.secp,DPOW_secpkeystr); strcpy(mp->alice.recvZaddr,DPOW_recvZaddr); strcpy(mp->alice.recvaddr,DPOW_recvaddr); printf("rel.%s/%s %s openrequest %u status.%d (%s/%s)\n",mp->rel.name,mp->rel.coin,mp->rel.tokenid,mp->origid,mp->status,mp->alice.recvaddr,mp->alice.recvZaddr); - if ( mp->status == 0 && subatomic_orderbook_mpset(mp,"") != 0 ) + if ( mp->status == 0 && hushdex_orderbook_mpset(mp,"") != 0 ) { strcpy(mp->bob.pubkey,mp->senderpub); - if ( subatomic_zonly(&mp->base) != 0 || subatomic_zonly(&mp->rel) != 0 ) + if ( hushdex_zonly(&mp->base) != 0 || hushdex_zonly(&mp->rel) != 0 ) mp->OTCmode = 1; else mp->OTCmode = SUBATOMIC_OTCDEFAULT; strcpy(origmp->base.name,mp->base.name); @@ -918,14 +918,14 @@ uint32_t subatomic_alice_openrequest(struct msginfo *origmp) printf("%u cant do zaddr or fractional base %s.%s tokens %.8f\n",mp->origid,mp->base.coin,mp->base.tokenid,dstr(mp->base.satoshis)); return(0); } - else if ( (openrequest= subatomic_mpjson(mp)) != 0 ) + else if ( (openrequest= hushdex_mpjson(mp)) != 0 ) { - hexstr = subatomic_submit(openrequest,!mp->bobflag); + hexstr = hushdex_submit(openrequest,!mp->bobflag); if ( (retjson= dpow_broadcast(SUBATOMIC_PRIORITY,hexstr,(char *)"inbox",(char *)"openrequest",mp->bob.pubkey,"","")) != 0 ) { mp->openrequestid = juint(retjson,"id"); printf("%u openrequest.%u -> (%s)\n",mp->origid,mp->openrequestid,mp->bob.pubkey); - subatomic_status(mp,SUBATOMIC_OPENREQUEST); + hushdex_status(mp,SUBATOMIC_OPENREQUEST); free_json(retjson); } free(hexstr); @@ -934,15 +934,15 @@ uint32_t subatomic_alice_openrequest(struct msginfo *origmp) return(mp->openrequestid); } -void subatomic_bob_gotopenrequest(uint32_t inboxid,char *senderpub,cJSON *msgjson,char *basename,char *relname) +void hushdex_bob_gotopenrequest(uint32_t inboxid,char *senderpub,cJSON *msgjson,char *basename,char *relname) { struct msginfo *mp; cJSON *approval; int32_t origid; char *addr,tmpstr[32],*coin,*acname=""; origid = juint(msgjson,"origid"); - mp = subatomic_tracker(origid); + mp = hushdex_tracker(origid); strcpy(mp->base.name,basename); - strcpy(mp->base.coin,subatomic_checkname(tmpstr,mp,0,basename)); + strcpy(mp->base.coin,hushdex_checkname(tmpstr,mp,0,basename)); strcpy(mp->rel.name,relname); - strcpy(mp->rel.coin,subatomic_checkname(tmpstr,mp,1,relname)); + strcpy(mp->rel.coin,hushdex_checkname(tmpstr,mp,1,relname)); mp->origid = origid; mp->rel.satoshis = j64bits(msgjson,"relsatoshis"); mp->bobflag = 1; @@ -956,42 +956,42 @@ void subatomic_bob_gotopenrequest(uint32_t inboxid,char *senderpub,cJSON *msgjso strcpy(mp->alice.recvZaddr,addr); if ( (addr= jstr(msgjson,"alicesecp")) != 0 ) strcpy(mp->alice.secp,addr); - if ( subatomic_zonly(&mp->base) != 0 || subatomic_zonly(&mp->rel) != 0 ) + if ( hushdex_zonly(&mp->base) != 0 || hushdex_zonly(&mp->rel) != 0 ) mp->OTCmode = 1; else mp->OTCmode = SUBATOMIC_OTCDEFAULT; printf("%u got open request\n",mp->origid); - if ( mp->status == 0 && subatomic_orderbook_mpset(mp,basename) != 0 && (approval= subatomic_mpjson(mp)) != 0 ) + if ( mp->status == 0 && hushdex_orderbook_mpset(mp,basename) != 0 && (approval= hushdex_mpjson(mp)) != 0 ) { if ( mp->rel.istoken != 0 && ((mp->rel.satoshis % SATOSHIDEN) != 0 || mp->rel.iszaddr != 0) ) { printf("%u cant do zaddr or fractional rel %s.%s tokens %.8f\n",mp->origid,mp->rel.coin,mp->rel.tokenid,dstr(mp->rel.satoshis)); - subatomic_closed(mp,approval,msgjson,senderpub); + hushdex_closed(mp,approval,msgjson,senderpub); return; } else if ( mp->base.istoken != 0 && ((mp->base.satoshis % SATOSHIDEN) != 0 || mp->base.iszaddr != 0 ) ) { printf("%u cant do zaddr or fractional base %s.%s tokens %.8f\n",mp->origid,mp->base.coin,mp->base.tokenid,dstr(mp->base.satoshis)); - subatomic_closed(mp,approval,msgjson,senderpub); + hushdex_closed(mp,approval,msgjson,senderpub); return; } - else if ( subatomic_getbalance(&mp->base) < mp->base.satoshis ) + else if ( hushdex_getbalance(&mp->base) < mp->base.satoshis ) { - printf("%u bob node low on %s funds! %.8f not enough for %.8f\n",mp->origid,mp->base.coin,dstr(subatomic_getbalance(&mp->base)),dstr(mp->base.satoshis)); - subatomic_closed(mp,approval,msgjson,senderpub); + printf("%u bob node low on %s funds! %.8f not enough for %.8f\n",mp->origid,mp->base.coin,dstr(hushdex_getbalance(&mp->base)),dstr(mp->base.satoshis)); + hushdex_closed(mp,approval,msgjson,senderpub); } else { printf("%u bob (%s/%s) gotopenrequest origid.%u status.%d (%s/%s) SENDERPUB.(%s)\n",mp->origid,mp->base.name,mp->rel.name,mp->origid,mp->status,mp->bob.recvaddr,mp->bob.recvZaddr,senderpub); - subatomic_approved(mp,approval,msgjson,senderpub); + hushdex_approved(mp,approval,msgjson,senderpub); } } } -int32_t subatomic_channelapproved(uint32_t inboxid,char *senderpub,cJSON *msgjson,struct msginfo *origmp) +int32_t hushdex_channelapproved(uint32_t inboxid,char *senderpub,cJSON *msgjson,struct msginfo *origmp) { struct msginfo *mp; cJSON *approval; char *addr,*coin,*acname; int32_t retval = 0; - mp = subatomic_tracker(juint(msgjson,"origid")); - if ( subatomic_orderbook_mpset(mp,mp->base.name) != 0 && (approval= subatomic_mpjson(mp)) != 0 ) + mp = hushdex_tracker(juint(msgjson,"origid")); + if ( hushdex_orderbook_mpset(mp,mp->base.name) != 0 && (approval= hushdex_mpjson(mp)) != 0 ) { printf("%u iambob.%d (%s/%s) channelapproved origid.%u status.%d\n",mp->origid,mp->bobflag,mp->base.name,mp->rel.name,mp->origid,mp->status); if ( mp->bobflag == 0 && mp->status == SUBATOMIC_OPENREQUEST ) @@ -1002,46 +1002,46 @@ int32_t subatomic_channelapproved(uint32_t inboxid,char *senderpub,cJSON *msgjso strcpy(mp->bob.recvZaddr,addr); if ( (addr= jstr(msgjson,"bobsecp")) != 0 ) strcpy(mp->bob.secp,addr); - retval = subatomic_approved(mp,approval,msgjson,senderpub); + retval = hushdex_approved(mp,approval,msgjson,senderpub); } else if ( mp->bobflag != 0 && mp->status == SUBATOMIC_APPROVED ) - retval = subatomic_opened(mp,approval,msgjson,senderpub); + retval = hushdex_opened(mp,approval,msgjson,senderpub); } return(retval); } -int32_t subatomic_incomingopened(uint32_t inboxid,char *senderpub,cJSON *msgjson,struct msginfo *origmp) +int32_t hushdex_incomingopened(uint32_t inboxid,char *senderpub,cJSON *msgjson,struct msginfo *origmp) { struct msginfo *mp; cJSON *payment; int32_t retval = 0; - mp = subatomic_tracker(juint(msgjson,"origid")); - if ( subatomic_orderbook_mpset(mp,mp->base.name) != 0 && (payment= subatomic_mpjson(mp)) != 0 ) + mp = hushdex_tracker(juint(msgjson,"origid")); + if ( hushdex_orderbook_mpset(mp,mp->base.name) != 0 && (payment= hushdex_mpjson(mp)) != 0 ) { printf("%u iambob.%d (%s/%s) incomingchannel status.%d\n",mp->origid,mp->bobflag,mp->base.name,mp->rel.name,mp->status); if ( mp->bobflag == 0 && mp->status == SUBATOMIC_APPROVED ) - retval = subatomic_payment(mp,payment,msgjson,senderpub); + retval = hushdex_payment(mp,payment,msgjson,senderpub); else if ( mp->bobflag != 0 && mp->status == SUBATOMIC_OPENED ) retval = 1; // nothing to do } return(retval); } -int32_t subatomic_incomingpayment(uint32_t inboxid,char *senderpub,cJSON *msgjson,struct msginfo *origmp) +int32_t hushdex_incomingpayment(uint32_t inboxid,char *senderpub,cJSON *msgjson,struct msginfo *origmp) { static FILE *fp; struct msginfo *mp; cJSON *pay,*rawtx,*retjson; bits256 txid; char str[65],*hexstr; int32_t retval = 0; - mp = subatomic_tracker(juint(msgjson,"origid")); - if ( subatomic_orderbook_mpset(mp,mp->base.name) != 0 && (pay= subatomic_mpjson(mp)) != 0 ) + mp = hushdex_tracker(juint(msgjson,"origid")); + if ( hushdex_orderbook_mpset(mp,mp->base.name) != 0 && (pay= hushdex_mpjson(mp)) != 0 ) { printf("%u iambob.%d (%s/%s) incomingpayment status.%d\n",mp->origid,mp->bobflag,mp->base.name,mp->rel.name,mp->status); if ( mp->bobflag == 0 ) { txid = jbits256(msgjson,"bobpayment"); jaddbits256(msgjson,"alicepayment",mp->alicepayment); - printf("%u alice waits for %s.%s to be in mempool (%.8f -> %s)\n",mp->origid,mp->base.name,bits256_str(str,txid),dstr(mp->base.satoshis),subatomic_zonly(&mp->base) == 0 ? mp->alice.recvaddr : mp->alice.recvZaddr); + printf("%u alice waits for %s.%s to be in mempool (%.8f -> %s)\n",mp->origid,mp->base.name,bits256_str(str,txid),dstr(mp->base.satoshis),hushdex_zonly(&mp->base) == 0 ? mp->alice.recvaddr : mp->alice.recvZaddr); hexstr = jstr(msgjson,"bobtx"); - if ( (rawtx= subatomic_txidwait(&mp->base,txid,hexstr,SUBATOMIC_TIMEOUT,senderpub)) != 0 ) + if ( (rawtx= hushdex_txidwait(&mp->base,txid,hexstr,SUBATOMIC_TIMEOUT,senderpub)) != 0 ) { - if ( subatomic_verifypayment(&mp->base,rawtx,mp->base.satoshis,subatomic_zonly(&mp->base) == 0 ? mp->alice.recvaddr : mp->alice.recvZaddr,txid) >= 0 ) + if ( hushdex_verifypayment(&mp->base,rawtx,mp->base.satoshis,hushdex_zonly(&mp->base) == 0 ? mp->alice.recvaddr : mp->alice.recvZaddr,txid) >= 0 ) mp->gotpayment = 1; free_json(rawtx); } @@ -1073,28 +1073,28 @@ int32_t subatomic_incomingpayment(uint32_t inboxid,char *senderpub,cJSON *msgjso if ( (retjson= dpow_broadcast(SUBATOMIC_PRIORITY,bits256_str(str,mp->alicepayment),(char *)"incomplete",str,DPOW_pubkeystr,"","")) != 0 ) free_json(retjson); } - subatomic_closed(mp,pay,msgjson,senderpub); + hushdex_closed(mp,pay,msgjson,senderpub); exit(-1); } } if ( mp->gotpayment != 0 ) - retval = subatomic_paidinfull(mp,pay,msgjson,senderpub); + retval = hushdex_paidinfull(mp,pay,msgjson,senderpub); else { if ( mp->bobflag != 0 && mp->status == SUBATOMIC_OPENED ) { txid = jbits256(msgjson,"alicepayment"); - printf("%u bob waits for %s.%s to be in mempool (%.8f -> %s)\n",mp->origid,mp->rel.name,bits256_str(str,txid),dstr(mp->rel.satoshis),subatomic_zonly(&mp->rel) == 0 ? mp->bob.recvaddr : mp->bob.recvZaddr); + printf("%u bob waits for %s.%s to be in mempool (%.8f -> %s)\n",mp->origid,mp->rel.name,bits256_str(str,txid),dstr(mp->rel.satoshis),hushdex_zonly(&mp->rel) == 0 ? mp->bob.recvaddr : mp->bob.recvZaddr); hexstr = jstr(msgjson,"alicetx"); - if ( (rawtx= subatomic_txidwait(&mp->rel,txid,hexstr,SUBATOMIC_TIMEOUT,senderpub)) != 0 ) + if ( (rawtx= hushdex_txidwait(&mp->rel,txid,hexstr,SUBATOMIC_TIMEOUT,senderpub)) != 0 ) { - if ( subatomic_verifypayment(&mp->rel,rawtx,mp->rel.satoshis,subatomic_zonly(&mp->rel) == 0 ? mp->bob.recvaddr : mp->bob.recvZaddr,txid) >= 0 ) + if ( hushdex_verifypayment(&mp->rel,rawtx,mp->rel.satoshis,hushdex_zonly(&mp->rel) == 0 ? mp->bob.recvaddr : mp->bob.recvZaddr,txid) >= 0 ) mp->gotpayment = 1; free_json(rawtx); } if ( mp->gotpayment != 0 ) { - retval = subatomic_payment(mp,pay,msgjson,senderpub); + retval = hushdex_payment(mp,pay,msgjson,senderpub); jaddbits256(msgjson,"bobpayment",mp->bobpayment); if ( mp->rel.iszaddr == 0 ) { @@ -1121,42 +1121,42 @@ int32_t subatomic_incomingpayment(uint32_t inboxid,char *senderpub,cJSON *msgjso return(retval); } -int32_t subatomic_incomingfullypaid(uint32_t inboxid,char *senderpub,cJSON *msgjson,struct msginfo *origmp) +int32_t hushdex_incomingfullypaid(uint32_t inboxid,char *senderpub,cJSON *msgjson,struct msginfo *origmp) { struct msginfo *mp; cJSON *closed; int32_t retval = 0; - mp = subatomic_tracker(juint(msgjson,"origid")); - if ( subatomic_orderbook_mpset(mp,mp->base.name) != 0 && (closed= subatomic_mpjson(mp)) != 0 ) + mp = hushdex_tracker(juint(msgjson,"origid")); + if ( hushdex_orderbook_mpset(mp,mp->base.name) != 0 && (closed= hushdex_mpjson(mp)) != 0 ) { printf("%u iambob.%d (%s/%s) incomingfullypaid status.%d\n",mp->origid,mp->bobflag,mp->base.name,mp->rel.name,mp->status); // error check msgjson vs M if ( mp->bobflag == 0 && mp->status == SUBATOMIC_PAIDINFULL ) - retval = subatomic_closed(mp,closed,msgjson,senderpub); + retval = hushdex_closed(mp,closed,msgjson,senderpub); else if ( mp->bobflag != 0 && mp->status == SUBATOMIC_PAYMENT ) - retval = subatomic_paidinfull(mp,closed,msgjson,senderpub); + retval = hushdex_paidinfull(mp,closed,msgjson,senderpub); } return(retval); } -int32_t subatomic_incomingclosed(uint32_t inboxid,char *senderpub,cJSON *msgjson,struct msginfo *origmp) +int32_t hushdex_incomingclosed(uint32_t inboxid,char *senderpub,cJSON *msgjson,struct msginfo *origmp) { struct msginfo *mp; cJSON *closed; int32_t retval = 0; - mp = subatomic_tracker(juint(msgjson,"origid")); - if ( subatomic_orderbook_mpset(mp,mp->base.name) != 0 && (closed= subatomic_mpjson(mp)) != 0 ) + mp = hushdex_tracker(juint(msgjson,"origid")); + if ( hushdex_orderbook_mpset(mp,mp->base.name) != 0 && (closed= hushdex_mpjson(mp)) != 0 ) { printf("%u iambob.%d (%s/%s) incomingclose status.%d\n",mp->origid,mp->bobflag,mp->base.name,mp->rel.name,mp->status); if ( mp->bobflag != 0 ) dpow_cancel(mp->origid); if ( mp->status < SUBATOMIC_CLOSED ) { - retval = subatomic_closed(mp,closed,msgjson,senderpub); - subatomic_status(mp,SUBATOMIC_CLOSED); + retval = hushdex_closed(mp,closed,msgjson,senderpub); + hushdex_status(mp,SUBATOMIC_CLOSED); } retval = 1; } return(retval); } -int32_t subatomic_ismine(int32_t bobflag,cJSON *json,char *basename,char *relname) +int32_t hushdex_ismine(int32_t bobflag,cJSON *json,char *basename,char *relname) { char *base,*rel; if ( (base= jstr(json,"base")) != 0 && (rel= jstr(json,"rel")) != 0 ) @@ -1173,7 +1173,7 @@ int32_t subatomic_ismine(int32_t bobflag,cJSON *json,char *basename,char *relnam return(0); } -void subatomic_tokensregister(int32_t priority) +void hushdex_tokensregister(int32_t priority) { char *token_name,*tokenid,existing[65]; cJSON *tokens,*token; int32_t i,numtokens; if ( SUBATOMIC_json != 0 && (tokens= jarray(&numtokens,SUBATOMIC_json,"tokens")) != 0 ) @@ -1193,7 +1193,7 @@ void subatomic_tokensregister(int32_t priority) } } -void subatomic_filesregister(int32_t priority) +void hushdex_filesregister(int32_t priority) { char *fname,*tokenid,*coin,existing[512]; int64_t price; cJSON *files,*file,*prices; int32_t i,j,m,numfiles; if ( SUBATOMIC_json != 0 && (files= jarray(&numfiles,SUBATOMIC_json,"files")) != 0 ) @@ -1221,12 +1221,12 @@ void subatomic_filesregister(int32_t priority) } } -void subatomic_loop(struct msginfo *mp) +void hushdex_loop(struct msginfo *mp) { static char *tagBs[] = { "openrequest", "approved", "opened", "payment", "paid", "closed" }; static uint32_t stopats[sizeof(tagBs)/sizeof(*tagBs)]; struct inboxinfo **ptrs,*ptr; char *tagB; int32_t i,iter,n,msgs=0,mask=0; cJSON *inboxjson; - fprintf(stderr,"start subatomic_loop iambob.%d %s -> %s, %u %llu %u\n",mp->bobflag,mp->base.name,mp->rel.name,mp->origid,(long long)mp->rel.satoshis,mp->openrequestid); + fprintf(stderr,"start hushdex_loop iambob.%d %s -> %s, %u %llu %u\n",mp->bobflag,mp->base.name,mp->rel.name,mp->origid,(long long)mp->rel.satoshis,mp->openrequestid); while ( 1 ) { if ( msgs == 0 ) @@ -1236,8 +1236,8 @@ void subatomic_loop(struct msginfo *mp) if ( mp->bobflag != 0 ) { dpow_pubkeyregister(SUBATOMIC_PRIORITY); - subatomic_tokensregister(SUBATOMIC_PRIORITY); - subatomic_filesregister(SUBATOMIC_PRIORITY); + hushdex_tokensregister(SUBATOMIC_PRIORITY); + hushdex_filesregister(SUBATOMIC_PRIORITY); } } msgs = 0; @@ -1255,24 +1255,24 @@ void subatomic_loop(struct msginfo *mp) { if ( jint(inboxjson,"tobob") != mp->bobflag ) continue; - if ( subatomic_ismine(mp->bobflag,inboxjson,mp->base.name,mp->rel.name) != 0 ) + if ( hushdex_ismine(mp->bobflag,inboxjson,mp->base.name,mp->rel.name) != 0 ) { if ( strcmp(tagB,"openrequest") == 0 && mp->bobflag != 0 ) - subatomic_bob_gotopenrequest(ptr->shorthash,ptr->senderpub,inboxjson,mp->base.name,mp->rel.name); + hushdex_bob_gotopenrequest(ptr->shorthash,ptr->senderpub,inboxjson,mp->base.name,mp->rel.name); else if ( strcmp(tagB,"approved") == 0 ) - mask |= subatomic_channelapproved(ptr->shorthash,ptr->senderpub,inboxjson,mp) << 0; + mask |= hushdex_channelapproved(ptr->shorthash,ptr->senderpub,inboxjson,mp) << 0; else if ( strcmp(tagB,"opened") == 0 ) - mask |= subatomic_incomingopened(ptr->shorthash,ptr->senderpub,inboxjson,mp) << 1; + mask |= hushdex_incomingopened(ptr->shorthash,ptr->senderpub,inboxjson,mp) << 1; else if ( strcmp(tagB,"payment") == 0 ) - mask |= subatomic_incomingpayment(ptr->shorthash,ptr->senderpub,inboxjson,mp) << 2; + mask |= hushdex_incomingpayment(ptr->shorthash,ptr->senderpub,inboxjson,mp) << 2; else if ( strcmp(tagB,"paid") == 0 ) - mask |= subatomic_incomingfullypaid(ptr->shorthash,ptr->senderpub,inboxjson,mp) << 3; + mask |= hushdex_incomingfullypaid(ptr->shorthash,ptr->senderpub,inboxjson,mp) << 3; else if ( strcmp(tagB,"closed") == 0 ) - mask |= subatomic_incomingclosed(ptr->shorthash,ptr->senderpub,inboxjson,mp) * 0x1f; + mask |= hushdex_incomingclosed(ptr->shorthash,ptr->senderpub,inboxjson,mp) * 0x1f; else fprintf(stderr,"iambob.%d unknown unexpected tagB.(%s)\n",mp->bobflag,tagB); } free_json(inboxjson); - } else fprintf(stderr,"subatomic iambob.%d loop got unparseable(%s)\n",mp->bobflag,ptr->jsonstr); + } else fprintf(stderr,"hushdex iambob.%d loop got unparseable(%s)\n",mp->bobflag,ptr->jsonstr); free(ptr); ptrs[i] = 0; } @@ -1290,21 +1290,21 @@ void subatomic_loop(struct msginfo *mp) int32_t main(int32_t argc,char **argv) { - char *fname = "subatomic.json"; - int32_t i,height; char *coin,*kcli,*subatomic,*hashstr,*acname=(char *)""; cJSON *retjson; bits256 blockhash; char checkstr[65],str[65],str2[65],tmpstr[32]; long fsize; struct msginfo M; + char *fname = "hushdex.json"; + int32_t i,height; char *coin,*kcli,*hushdex,*hashstr,*acname=(char *)""; cJSON *retjson; bits256 blockhash; char checkstr[65],str[65],str2[65],tmpstr[32]; long fsize; struct msginfo M; memset(&M,0,sizeof(M)); srand((int32_t)time(NULL)); - if ( (subatomic= filestr(&fsize,fname)) == 0 ) + if ( (hushdex= filestr(&fsize,fname)) == 0 ) { fprintf(stderr,"cant load %s file\n",fname); exit(-1); } - if ( (SUBATOMIC_json= cJSON_Parse(subatomic)) == 0 ) + if ( (SUBATOMIC_json= cJSON_Parse(hushdex)) == 0 ) { - fprintf(stderr,"cant parse subatomic.json file (%s)\n",subatomic); + fprintf(stderr,"cant parse hushdex.json file (%s)\n",hushdex); exit(-1); } - free(subatomic); + free(hushdex); if ( argc >= 4 ) { if ( dpow_pubkey() < 0 ) @@ -1319,7 +1319,7 @@ int32_t main(int32_t argc,char **argv) acname = coin; } hashstr = (char *)argv[3]; - strcpy(M.rel.coin,subatomic_checkname(tmpstr,&M,1,coin)); + strcpy(M.rel.coin,hushdex_checkname(tmpstr,&M,1,coin)); strcpy(M.rel.name,coin); if ( argc == 4 && strlen(hashstr) == 64 ) // for blocknotify usage, seems not needed { @@ -1370,24 +1370,24 @@ int32_t main(int32_t argc,char **argv) mult = SATOSHIDEN; break; } - if ( subatomic_getbalance(&M.rel) < M.rel.satoshis/mult ) + if ( hushdex_getbalance(&M.rel) < M.rel.satoshis/mult ) { - fprintf(stderr,"not enough balance %s %.8f for %.8f\n",M.rel.coin,dstr(subatomic_getbalance(&M.rel)),dstr(M.rel.satoshis/mult)); + fprintf(stderr,"not enough balance %s %.8f for %.8f\n",M.rel.coin,dstr(hushdex_getbalance(&M.rel)),dstr(M.rel.satoshis/mult)); return(-1); } - fprintf(stderr,"subatomic_channel_alice (%s/%s) %s %u with %.8f %llu\n",M.rel.name,M.rel.coin,hashstr,M.origid,atof(argv[4]),(long long)M.rel.satoshis); + fprintf(stderr,"hushdex_channel_alice (%s/%s) %s %u with %.8f %llu\n",M.rel.name,M.rel.coin,hashstr,M.origid,atof(argv[4]),(long long)M.rel.satoshis); dpow_pubkeyregister(SUBATOMIC_PRIORITY); - M.openrequestid = subatomic_alice_openrequest(&M); + M.openrequestid = hushdex_alice_openrequest(&M); if ( M.openrequestid != 0 ) - subatomic_loop(&M); + hushdex_loop(&M); } else fprintf(stderr,"checkstr mismatch %s %s != %s\n",coin,hashstr,checkstr); } else { M.bobflag = 1; strcpy(M.base.name,hashstr); - strcpy(M.base.coin,subatomic_checkname(tmpstr,&M,0,hashstr)); - subatomic_loop(&M); // while ( 1 ) loop for each relcoin -> basecoin + strcpy(M.base.coin,hushdex_checkname(tmpstr,&M,0,hashstr)); + hushdex_loop(&M); // while ( 1 ) loop for each relcoin -> basecoin } } return(SUBATOMIC_retval); From b45c7ef61d46f4e276bf6134f3a6e183fa1364d6 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 20:18:01 -0400 Subject: [PATCH 07/31] We no longer support oraclefeed dapp --- src/cc/dapps/oraclefeed.c | 1151 ------------------------------------- 1 file changed, 1151 deletions(-) delete mode 100644 src/cc/dapps/oraclefeed.c diff --git a/src/cc/dapps/oraclefeed.c b/src/cc/dapps/oraclefeed.c deleted file mode 100644 index ac1f88400..000000000 --- a/src/cc/dapps/oraclefeed.c +++ /dev/null @@ -1,1151 +0,0 @@ -/****************************************************************************** - * 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. * - * * - ******************************************************************************/ - -#include -#include -#include -#include -#include -#include "cJSON.c" - -bits256 zeroid; - -void myprintf(const char* format, ...) -{ - va_list marker; - va_start( marker, format ); - vfprintf(stdout, format, marker); - fflush(stdout); - va_end( marker ); -} - -char hexbyte(int32_t c) -{ - c &= 0xf; - if ( c < 10 ) - return('0'+c); - else if ( c < 16 ) - return('a'+c-10); - else return(0); -} - -int32_t _unhex(char c) -{ - if ( c >= '0' && c <= '9' ) - return(c - '0'); - else if ( c >= 'a' && c <= 'f' ) - return(c - 'a' + 10); - else if ( c >= 'A' && c <= 'F' ) - return(c - 'A' + 10); - return(-1); -} - -int32_t is_hexstr(char *str,int32_t n) -{ - int32_t i; - if ( str == 0 || str[0] == 0 ) - return(0); - for (i=0; str[i]!=0; i++) - { - if ( n > 0 && i >= n ) - break; - if ( _unhex(str[i]) < 0 ) - break; - } - if ( n == 0 ) - return(i); - return(i == n); -} - -int32_t unhex(char c) -{ - int32_t hex; - if ( (hex= _unhex(c)) < 0 ) - { - //myprintf("unhex: illegal hexchar.(%c)\n",c); - } - return(hex); -} - -unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])); } - -int32_t decode_hex(unsigned char *bytes,int32_t n,char *hex) -{ - int32_t adjust,i = 0; - //myprintf("decode.(%s)\n",hex); - if ( is_hexstr(hex,n) <= 0 ) - { - memset(bytes,0,n); - return(n); - } - if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) - hex[--n] = 0; - if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) - hex[--n] = 0; - if ( n == 0 || (hex[n*2+1] == 0 && hex[n*2] != 0) ) - { - if ( n > 0 ) - { - bytes[0] = unhex(hex[0]); - myprintf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex)); - } - bytes++; - hex++; - adjust = 1; - } else adjust = 0; - if ( n > 0 ) - { - for (i=0; i>4) & 0xf); - hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf); - //myprintf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]); - } - hexbytes[len*2] = 0; - //myprintf("len.%ld\n",len*2+1); - return((int32_t)len*2+1); -} - -long _stripwhite(char *buf,int accept) -{ - int32_t i,j,c; - if ( buf == 0 || buf[0] == 0 ) - return(0); - for (i=j=0; buf[i]!=0; i++) - { - buf[j] = c = buf[i]; - if ( c == accept || (c != ' ' && c != '\n' && c != '\r' && c != '\t' && c != '\b') ) - j++; - } - buf[j] = 0; - return(j); -} - -char *clonestr(char *str) -{ - char *clone; - if ( str == 0 || str[0]==0) - { - myprintf("warning cloning nullstr.%p\n",str); - //#ifdef __APPLE__ - // while ( 1 ) sleep(1); - //#endif - str = (char *)""; - } - clone = (char *)malloc(strlen(str)+16); - strcpy(clone,str); - return(clone); -} - -int32_t safecopy(char *dest,char *src,long len) -{ - int32_t i = -1; - if ( src != 0 && dest != 0 && src != dest ) - { - if ( dest != 0 ) - memset(dest,0,len); - for (i=0; i0; 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; - //myprintf("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 ) - myprintf("Null buf ???\n"); - else - { - if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize ) - myprintf("error reading filesize.%ld\n",(long)filesize); - buf[filesize] = 0; - } - fclose(fp); - *lenp = filesize; - //myprintf("loaded.(%s)\n",buf); - } //else myprintf("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 = malloc(strlen(_fname)+1); - strcpy(fname,_fname); - retptr = loadfile(fname,(uint8_t **)&buf,&filesize,allocsizep); - free(fname); - return(retptr); -} - -char *send_curl(char *url,char *fname) -{ - long fsize; char curlstr[1024]; - sprintf(curlstr,"curl --url \"%s\" > %s",url,fname); - system(curlstr); - return(filestr(&fsize,fname)); -} - -cJSON *get_urljson(char *url,char *fname) -{ - char *jsonstr; cJSON *json = 0; - if ( (jsonstr= send_curl(url,fname)) != 0 ) - { - //myprintf("(%s) -> (%s)\n",url,jsonstr); - json = cJSON_Parse(jsonstr); - free(jsonstr); - } - return(json); -} - -////////////////////////////////////////////// -// start of dapp -////////////////////////////////////////////// - -uint64_t get_btcusd() -{ - cJSON *pjson,*bpi,*usd; uint64_t btcusd = 0; - if ( (pjson= get_urljson("http://api.coindesk.com/v1/bpi/currentprice.json","/tmp/oraclefeed.json")) != 0 ) - { - if ( (bpi= jobj(pjson,"bpi")) != 0 && (usd= jobj(bpi,"USD")) != 0 ) - { - btcusd = jdouble(usd,"rate_float") * SATOSHIDEN; - myprintf("BTC/USD %.4f\n",dstr(btcusd)); - } - free_json(pjson); - } - return(btcusd); -} - -char *REFCOIN_CLI; - -cJSON *get_cli(char *refcoin,char **retstrp,char *acname,char *method,char *arg0,char *arg1,char *arg2,char *arg3) -{ - long fsize; cJSON *retjson = 0; char cmdstr[32768],*jsonstr,fname[256]; - sprintf(fname,"/tmp/oraclefeed.%s",method); - if ( acname[0] != 0 ) - { - if ( refcoin[0] == 0 ) - myprintf("must supply reference coin\n"); - sprintf(cmdstr,"./komodo-cli -ac_name=%s %s %s %s %s %s > %s 2>/tmp/oraclefeed.error\n",acname,method,arg0,arg1,arg2,arg3,fname); - } - else if ( REFCOIN_CLI != 0 && REFCOIN_CLI[0] != 0 ) - { - sprintf(cmdstr,"%s %s %s %s %s %s > %s 2>/tmp/oraclefeed.error\n",REFCOIN_CLI,method,arg0,arg1,arg2,arg3,fname); - //myprintf("ref.(%s) REFCOIN_CLI (%s)\n",refcoin,cmdstr); - } -#ifdef TESTMODE - fprintf(stderr,"cmd: %s\n",cmdstr); -#endif // TESTMODE - system(cmdstr); - *retstrp = 0; - if ( (jsonstr= filestr(&fsize,fname)) != 0 ) - { - jsonstr[strlen(jsonstr)-1]='\0'; -#ifdef TESTMODE - fprintf(stderr,"jsonstr.(%s)\n",jsonstr); -#endif // TESTMODE - if ( (jsonstr[0] != '{' && jsonstr[0] != '[') || (retjson= cJSON_Parse(jsonstr)) == 0) - *retstrp = jsonstr; - else free(jsonstr); - } - else if ( (jsonstr= filestr(&fsize,"/tmp/oraclefeed.error")) != 0 ) - *retstrp = jsonstr; - return(retjson); -} - -bits256 broadcasttx(char *refcoin,char *acname,cJSON *hexjson) -{ - char *hexstr,*retstr,str[65]; cJSON *retjson; bits256 txid; - memset(txid.bytes,0,sizeof(txid)); - if ( (hexstr= jstr(hexjson,"hex")) != 0 ) - { - if ( (retjson= get_cli(refcoin,&retstr,acname,"sendrawtransaction",hexstr,"","","")) != 0 ) - { - if (strcmp("error",jstr(retjson,"result"))==0) myprintf("%s\n",jstr(retjson,"error")); - free_json(retjson); - } - else if ( retstr != 0 ) - { - if ( strlen(retstr) >= 64 ) - { - retstr[64] = 0; - decode_hex(txid.bytes,32,retstr); - } - fprintf(stderr,"broadcast %s txid.(%s)\n",strlen(acname)>0?acname:refcoin,bits256_str(str,txid)); - free(retstr); - } - } - return(txid); -} - -int32_t get_coinheight(char *refcoin,char *acname) -{ - cJSON *retjson; char *retstr; int32_t height=0; - if ( (retjson= get_cli(refcoin,&retstr,acname,"getblockchaininfo","","","","")) != 0 ) - { - height = jint(retjson,"blocks"); - free_json(retjson); - - } - else if ( retstr != 0 ) - { - fprintf(stderr,"%s get_coinheight.(%s) error.(%s)\n",refcoin,acname,retstr); - free(retstr); - } - return(height); -} - -bits256 get_coinblockhash(char *refcoin,char *acname,int32_t height) -{ - cJSON *retjson; char *retstr,heightstr[32]; bits256 hash; - memset(hash.bytes,0,sizeof(hash)); - sprintf(heightstr,"%d",height); - if ( (retjson= get_cli(refcoin,&retstr,acname,"getblockhash",heightstr,"","","")) != 0 ) - { - fprintf(stderr,"unexpected blockhash json.(%s)\n",jprint(retjson,0)); - free_json(retjson); - } - else if ( retstr != 0 ) - { - if ( strlen(retstr) >= 64 ) - { - retstr[64] = 0; - decode_hex(hash.bytes,32,retstr); - } - free(retstr); - } - return(hash); -} - -bits256 get_coinmerkleroot(char *refcoin,char *acname,bits256 blockhash) -{ - cJSON *retjson; char *retstr,str[65]; bits256 merkleroot; - memset(merkleroot.bytes,0,sizeof(merkleroot)); - if ( (retjson= get_cli(refcoin,&retstr,acname,"getblockheader",bits256_str(str,blockhash),"","","")) != 0 ) - { - merkleroot = jbits256(retjson,"merkleroot"); - //fprintf(stderr,"got merkleroot.(%s)\n",bits256_str(str,merkleroot)); - free_json(retjson); - } - else if ( retstr != 0 ) - { - fprintf(stderr,"%s %s get_coinmerkleroot error.(%s)\n",refcoin,acname,retstr); - free(retstr); - } - return(merkleroot); -} - -int32_t get_coinheader(char *refcoin,char *acname,bits256 *blockhashp,bits256 *merklerootp,int32_t prevheight) -{ - int32_t height = 0; char str[65]; - if ( prevheight == 0 ) - height = get_coinheight(refcoin,acname) - 20; - else height = prevheight + 1; - if ( height > 0 ) - { - *blockhashp = get_coinblockhash(refcoin,acname,height); - if ( bits256_nonz(*blockhashp) != 0 ) - { - *merklerootp = get_coinmerkleroot(refcoin,acname,*blockhashp); - if ( bits256_nonz(*merklerootp) != 0 ) - return(height); - } - } - memset(blockhashp,0,sizeof(*blockhashp)); - memset(merklerootp,0,sizeof(*merklerootp)); - return(0); -} - -cJSON *get_gatewayspending(int8_t type,char *refcoin,char *acname,char *bindtxidstr) -{ - cJSON *retjson; char *retstr; char function[64]; - if (type==0) sprintf(function,"%s","gatewayspendingwithdraws"); - else if (type==1) sprintf(function,"%s","importgatewaypendingwithdraws"); - if ( (retjson= get_cli(refcoin,&retstr,acname,function,bindtxidstr,refcoin,"","")) != 0 ) - { - //myprintf("pending.(%s)\n",jprint(retjson,0)); - return(retjson); - } - else if ( retstr != 0 ) - { - fprintf(stderr,"%s get_gatewayspending.(%s) error.(%s)\n",refcoin,acname,retstr); - free(retstr); - } - return(0); -} - -cJSON *get_gatewaysprocessed(int8_t type,char *refcoin,char *acname,char *bindtxidstr) -{ - cJSON *retjson; char *retstr; - char function[64]; - if (type==0) sprintf(function,"%s","gatewaysprocessed"); - else if (type==1) sprintf(function,"%s","importgatewayprocessed"); - if ( (retjson= get_cli(refcoin,&retstr,acname,function,bindtxidstr,refcoin,"","")) != 0 ) - { - //myprintf("pending.(%s)\n",jprint(retjson,0)); - return(retjson); - } - else if ( retstr != 0 ) - { - fprintf(stderr,"%s get_gatewaysprocessed.(%s) error.(%s)\n",refcoin,acname,retstr); - free(retstr); - } - return(0); -} - -cJSON *get_rawmempool(char *refcoin,char *acname) -{ - cJSON *retjson; char *retstr; - if ( (retjson= get_cli(refcoin,&retstr,acname,"getrawmempool","","","","")) != 0 ) - { - //myprintf("mempool.(%s)\n",jprint(retjson,0)); - return(retjson); - } - else if ( retstr != 0 ) - { - fprintf(stderr,"get_rawmempool.(%s) error.(%s)\n",acname,retstr); - free(retstr); - } - return(0); -} - -cJSON *get_addressutxos(char *refcoin,char *acname,char *coinaddr) -{ - cJSON *retjson; char *retstr,jsonbuf[256]; - if ( refcoin[0] != 0 && strcmp(refcoin,"KMD") != 0 ) - myprintf("warning: assumes %s has addressindex enabled\n",refcoin); - sprintf(jsonbuf,"{\\\"addresses\\\":[\\\"%s\\\"]}",coinaddr); - if ( (retjson= get_cli(refcoin,&retstr,acname,"getaddressutxos",jsonbuf,"","","")) != 0 ) - { - //myprintf("addressutxos.(%s)\n",jprint(retjson,0)); - return(retjson); - } - else if ( retstr != 0 ) - { - //fprintf(stderr,"get_addressutxos.(%s) error.(%s)\n",acname,retstr); - free(retstr); - } - return(0); -} - -cJSON *get_rawtransaction(char *refcoin,char *acname,bits256 txid) -{ - cJSON *retjson; char *retstr,str[65]; - if ( (retjson= get_cli(refcoin,&retstr,acname,"getrawtransaction",bits256_str(str,txid),"1","","")) != 0 ) - { - return(retjson); - } - else if ( retstr != 0 ) - { - fprintf(stderr,"get_rawtransaction.(%s) %s error.(%s)\n",refcoin,acname,retstr); - free(retstr); - } - return(0); -} - -int32_t validateaddress(char *refcoin,char *acname,char *depositaddr, char* compare) -{ - cJSON *retjson; char *retstr; int32_t res=0; - if ( (retjson= get_cli(refcoin,&retstr,acname,"validateaddress",depositaddr,"","","")) != 0 ) - { - if (is_cJSON_True(jobj(retjson,compare)) != 0 ) res=1; - free_json(retjson); - } - else if ( retstr != 0 ) - { - fprintf(stderr,"validateaddress.(%s) %s error.(%s)\n",refcoin,acname,retstr); - free(retstr); - } - - return (res); -} - -void importaddress(char *refcoin,char *acname,char *depositaddr, char *label,int rescan) -{ - cJSON *retjson; char *retstr; char rescanstr[10]; - if (rescan) strcpy(rescanstr,"true"); - else strcpy(rescanstr,"false"); - if ( (retjson= get_cli(refcoin,&retstr,acname,"importaddress",depositaddr,label,rescanstr,"")) != 0 ) - { - myprintf("importaddress.(%s)\n",jprint(retjson,0)); - free_json(retjson); - } - else if ( retstr != 0 ) - { - fprintf(stderr,"importaddress.(%s) %s error.(%s)\n",refcoin,acname,retstr); - free(retstr); - } -} - -void addmultisigaddress(char *refcoin,char *acname,int32_t M, char *pubkeys) -{ - cJSON *retjson; char *retstr,Mstr[10],addr[64]; - - sprintf(Mstr,"%d",M); - if ( (retjson= get_cli(refcoin,&retstr,acname,"addmultisigaddress",Mstr,pubkeys,"","")) != 0 ) - { - fprintf(stderr,"unexpected addmultisigaddress json.(%s)\n",jprint(retjson,0)); - free(retstr); - } - else if ( retstr != 0 ) - { - sprintf(addr,"\"%s\"",retstr); - get_cli(refcoin,&retstr,acname,"importaddress",addr,"\"\"","false",""); - myprintf("addmultisigaddress.(%s)\n",retstr); - free_json(retjson); - } -} - -cJSON *getinputarray(int64_t *totalp,cJSON *unspents,int64_t required) -{ - cJSON *vin,*item,*vins = cJSON_CreateArray(); int32_t i,j=0,n,v; int64_t satoshis; bits256 txid; - *totalp = 0; - if ( (n= cJSON_GetArraySize(unspents)) > 0 ) - { - for (i=0; i= required ) - { - if (j<3) j++; - else break; - } - } - } - } - return(vins); -} - -char *createrawtx(char *refcoin,char *acname,char *depositaddr,char *withdrawaddr,char *txidaddr,int64_t satoshis) -{ - char *retstr,*retstr2,array[128],*txstr = 0; cJSON *retjson2,*retjson,*vins,*vouts; int64_t txfee,total,change = 0; - if ( strcmp(refcoin,"BTC") == 0 ) - txfee = 20000; - else txfee = 10000; - if ( satoshis < txfee ) - { - myprintf("createrawtx: satoshis %.8f < txfee %.8f\n",(double)satoshis/SATOSHIDEN,(double)txfee/SATOSHIDEN); - return(0); - } - sprintf(array,"\'[\"%s\"]\'",depositaddr); - if ( (retjson= get_cli(refcoin,&retstr,acname,"listunspent","1","99999999",array,"")) != 0 ) - { - //createrawtransaction [{"txid":"id","vout":n},...] {"address":amount,...} - if ( (vins= getinputarray(&total,retjson,satoshis)) != 0 ) - { - if ( total >= satoshis ) - { - vouts = cJSON_CreateObject(); - jaddnum(vouts,withdrawaddr,(double)(satoshis-2*txfee)/SATOSHIDEN); - jaddnum(vouts,txidaddr,(double)txfee/SATOSHIDEN); - if ( total > satoshis) - { - change = (total - satoshis); - jaddnum(vouts,depositaddr,(double)change/SATOSHIDEN); - } - char *tmpA=jprint(vins,1); - char *tmpB=jprint(vouts,1); - char *argA=malloc(sizeof(char) * (strlen(tmpA)+3)); - char *argB=malloc(sizeof(char) * (strlen(tmpB)+3)); - sprintf(argA,"\'%s\'",tmpA); - sprintf(argB,"\'%s\'",tmpB); - if ( (retjson2= get_cli(refcoin,&txstr,acname,"createrawtransaction",argA,argB,"","")) != 0 ) - { - myprintf("createrawtx: unexpected JSON2.(%s)\n",jprint(retjson2,0)); - free_json(retjson2); - } - else if ( txstr == 0 ) - myprintf("createrawtx: null txstr and JSON2\n"); - free(tmpA); - free(tmpB); - free(argA); - free(argB); - } - else myprintf("not enough funds to create withdraw tx\n"); - } - free_json(retjson); - } - else if ( retstr != 0 ) - { - myprintf("createrawtx: unexpected null JSON, retstr.(%s)\n",retstr); - free(retstr); - } - else myprintf("createrawtx: null retstr and JSON\n"); - return(txstr); -} - -cJSON *addsignature(char *refcoin,char *acname,char *rawtx, int M) -{ - char *retstr,*hexstr; cJSON *retjson; - if ( (retjson= get_cli(refcoin,&retstr,acname,"signrawtransaction",rawtx,"","","")) != 0 ) - { - if ( is_cJSON_True(jobj(retjson,"complete")) != 0 ) - return(retjson); - else if ((hexstr=jstr(retjson,"hex"))!= 0 && strlen(hexstr) > strlen(rawtx) + (M*2) + 1) - { - jaddnum(retjson,"partialtx",1); - return(retjson); - } - free_json(retjson); - } - else if ( retstr != 0 ) - { - myprintf("error parsing signrawtransaction.(%s)\n",retstr); - free(retstr); - } - return(0); -} - -bits256 gatewayspartialsign(int8_t type,char *refcoin,char *acname,bits256 txid,char *hex) -{ - char str[65],*retstr; cJSON *retjson; char function[64]; - if (type==0) sprintf(function,"%s","gatewayspartialsign"); - else if (type==1) sprintf(function,"%s","importgatewaypartialsign"); - if ( (retjson= get_cli(refcoin,&retstr,acname,function,bits256_str(str,txid),refcoin,hex,"")) != 0 ) - { - if (strcmp("error",jstr(retjson,"result"))!=0) txid=broadcasttx(refcoin,acname,retjson); - else myprintf("%s\n",jstr(retjson,"error")); - free(retjson); - return (txid); - } - else if ( retstr != 0 ) - { - myprintf("error parsing gatewayspartialsing.(%s)\n",retstr); - free(retstr); - } - return (zeroid); -} - -bits256 gatewayscompletesigning(int8_t type,char *refcoin,char *acname,bits256 withtxid,char *hex) -{ - char str[65],*retstr; cJSON *retjson; bits256 txid; char function[64]; - - if (type==0) sprintf(function,"%s","gatewayscompletesigning"); - else if (type==1) sprintf(function,"%s","importgatewaycompletesigning"); - if ( (retjson= get_cli(refcoin,&retstr,acname,function,bits256_str(str,withtxid),refcoin,hex,"")) != 0 ) - { - if (strcmp("error",jstr(retjson,"result"))!=0) txid=broadcasttx(refcoin,acname,retjson); - else myprintf("%s\n",jstr(retjson,"error")); - free(retjson); - return (txid); - } - else if ( retstr != 0 ) - { - myprintf("error parsing gatewayscompletesigning.(%s)\n",retstr); - free(retstr); - } - return (zeroid); -} - -bits256 gatewaysmarkdone(int8_t type,char *refcoin,char *acname,bits256 withtxid) -{ - char str[65],str2[65],*retstr; cJSON *retjson; bits256 txid; ; char function[64]; - - if (type==0) sprintf(function,"%s","gatewaysmarkdone"); - else if (type==1) sprintf(function,"%s","importgatewaymarkdone"); - if ( (retjson= get_cli(refcoin,&retstr,acname,function,bits256_str(str,withtxid),refcoin,"","")) != 0 ) - { - if (strcmp("error",jstr(retjson,"result"))!=0) txid=broadcasttx(refcoin,acname,retjson); - else myprintf("%s\n",jstr(retjson,"error")); - free(retjson); - return (txid); - } - else if ( retstr != 0 ) - { - myprintf("error parsing gatewaysmarkdone.(%s)\n",retstr); - free(retstr); - } - return (zeroid); -} - -int32_t get_gatewaysinfo(int8_t type,char *refcoin,char *acname,char *depositaddr,int32_t *Mp,int32_t *Np,char *bindtxidstr,char *coin,char *oraclestr, char **pubkeys) -{ - char *oracle,*retstr,*name,*deposit,temp[128]; cJSON *retjson,*pubarray; int32_t n; char function[64]; - - if (type==0) sprintf(function,"%s","gatewaysinfo"); - else if (type==1) sprintf(function,"%s","importgatewayinfo"); - if ( (retjson= get_cli(refcoin,&retstr,acname,function,bindtxidstr,"","","")) != 0 ) - { - if ( (oracle= jstr(retjson,"oracletxid")) != 0 && strcmp(oracle,oraclestr) == 0 && (deposit= jstr(retjson,"deposit")) != 0 ) - { - strcpy(depositaddr,deposit); - if ( jstr(retjson,"coin") != 0 && strcmp(jstr(retjson,"coin"),coin) == 0 && jint(retjson,"N") >= 1 ) - { - *Mp = jint(retjson,"M"); - *Np = jint(retjson,"N"); - } - else myprintf("coin.%s vs %s\n",jstr(retjson,"coin"),coin); - if ((pubarray=jarray(&n,retjson,"pubkeys"))!=0) - { - *pubkeys=malloc((sizeof(char)*70*n)+64); - sprintf(*pubkeys,"\"["); - for (int i=0;i 0 ) - { - num = 1; - break; - } - } - } - free_json(array); - } - } - return(num); - -} - -void update_gatewayspending(int8_t type,char *refcoin,char *acname,char *bindtxidstr,int32_t M,int32_t N) -{ - // check queue to prevent duplicate - // check KMD chain and mempool for txidaddr - // if txidaddr exists properly, spend the marker (txid.2) - // create withdraw tx and sign it - /// if enough sigs, sendrawtransaction and when it confirms spend marker (txid.2) - /// if not enough sigs, post partially signed to acname with marker2 - // monitor marker2, for the partially signed withdraws - cJSON *retjson,*pending,*item,*clijson; char str[65],str1[65],str2[65],*rawtx,*coinstr,*txidaddr,*signeraddr,*depositaddr,*withdrawaddr; - int32_t i,j,n,K,retval,processed = 0; bits256 txid,cointxid,withdrawtxid,lasttxid,completetxid; int64_t satoshis; - - memset(&zeroid,0,sizeof(zeroid)); - if ( (retjson= get_gatewayspending(type,refcoin,acname,bindtxidstr)) != 0 ) - { - if ( jint(retjson,"queueflag") != 0 && (coinstr= jstr(retjson,"coin")) != 0 && strcmp(coinstr,refcoin) == 0 ) - { - if ( (pending= jarray(&n,retjson,"pending")) != 0 ) - { - for (i=0; i> (i*8)) & 0xff)); - hexstr[16] = 0; - return(16); - } - } - else if ( strcmp(format,"Ihh") == 0 ) - { - if ( (height= get_coinheader(refcoin,acname,&blockhash,&merkleroot,prevheight)) > prevheight ) - { - for (i=0; i<4; i++) - sprintf(&hexstr[i*2],"%02x",(uint8_t)((height >> (i*8)) & 0xff)); - for (i=31; i>=0; i--) - sprintf(&hexstr[8 + (31-i)*2],"%02x",blockhash.bytes[i]); - for (i=31; i>=0; i--) - sprintf(&hexstr[8 + 64 + (31-i)*2],"%02x",merkleroot.bytes[i]); - hexstr[8 + 64*2] = 0; - return(height); - } - } - return(0); -} - -/* - oraclescreate "BTCUSD" "coindeskpricedata" "L" -> 4895f631316a649e216153aee7a574bd281686265dc4e8d37597f72353facac3 - oraclesregister 4895f631316a649e216153aee7a574bd281686265dc4e8d37597f72353facac3 1000000 -> 11c54d4ab17293217276396e27d86f714576ff55a3300dac34417047825edf93 - oraclessubscribe 4895f631316a649e216153aee7a574bd281686265dc4e8d37597f72353facac3 02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92 1.5 -> ce4e4afa53765b11a74543dacbd3174a93f33f12bb94cdc080c2c023726b5838 - oraclesdata 4895f631316a649e216153aee7a574bd281686265dc4e8d37597f72353facac3 000000ff00000000 -> e8a8c897e97389dcac31d81b617ab73a829110bd5c6f99f9f533b9c0e22700d0 - oraclessamples 4895f631316a649e216153aee7a574bd281686265dc4e8d37597f72353facac3 90ff8813a93b5b2615ec43974ff4fc91e4373dfd672d995676c43ff2dcda1010 10 -> -{ -"result": "success", -"samples": [ - [ - "4278190080" - ] - ] -} - -oraclescreate test testsformat s -> 17a841a919c284cea8a676f34e793da002e606f19a9258a3190bed12d5aaa3ff -oraclesregister -> 7825ad75ba854ab12868f7d2e06b4061903687fe93f41a2a99202a6b9ca3c029 -oraclessubscribe 17a841a919c284cea8a676f34e793da002e606f19a9258a3190bed12d5aaa3ff 02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92 1.5 -> faf8a6676f6389abad9e7f397015d200395c9f8a24c4ded291d83e6265b2f4d1 -oraclesdata 17a841a919c284cea8a676f34e793da002e606f19a9258a3190bed12d5aaa3ff 03404040 -> e8a8c897e97389dcac31d81b617ab73a829110bd5c6f99f9f533b9c0e22700d0 - -*/ - -// ./a.out AT5 1f1aefcca2bdea8196cfd77337fb21de22d200ddea977c2f9e8742c55829d808 02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92 Ihh e6c99f79d4afb216aa8063658b4222edb773dd24bb0f8e91bd4ef341f3e47e5e - -int32_t main(int32_t argc,char **argv) -{ - cJSON *clijson,*clijson2,*regjson,*item; int32_t type,i,retval,M,N,n,height,prevheight = 0; char *pubkeys,*format,*acname,*oraclestr,*bindtxidstr,*pkstr,*pubstr,*retstr,*retstr2,depositaddr[64],hexstr[4096],refcoin[64]; uint64_t price; bits256 txid; - if ( argc < 6 ) - { - myprintf("usage: oraclefeed $ACNAME $ORACLETXID $MYPUBKEY $FORMAT $BINDTXID [refcoin_cli]\n"); - return(-1); - } - myprintf("Powered by CoinDesk (%s) %.8f\n","https://www.coindesk.com/price/",dstr(get_btcusd())); - acname = argv[1]; - oraclestr = argv[2]; - pkstr = argv[3]; - format = argv[4]; - bindtxidstr = argv[5]; - if ( argc > 6 ) - REFCOIN_CLI = argv[6]; - else REFCOIN_CLI = "./komodo-cli"; - if ( strncmp(format,"Ihh",3) != 0 && format[0] != 'L' ) - { - myprintf("only formats of L and Ihh are supported now\n"); - return(-1); - } - M = N = 0; - refcoin[0] = 0; - while ( 1 ) - { - retstr = 0; - if ( (refcoin[0] == 0 || prevheight < (get_coinheight(refcoin,"") - 10)) && (clijson= get_cli(refcoin,&retstr,acname,"oraclesinfo",oraclestr,"","","")) != 0 ) - { - if ( refcoin[0] == 0 && jstr(clijson,"name") != 0 ) - { - strcpy(refcoin,jstr(clijson,"name")); - if ( strcmp("KMD",refcoin) != 0 && argc != 7 ) - { - myprintf("need to specify path to refcoin's cli as last argv\n"); - exit(0); - } - pubkeys=0; - if ( get_gatewaysinfo(0,refcoin,acname,depositaddr,&M,&N,bindtxidstr,refcoin,oraclestr,&pubkeys) == 0 ) type=0; - else if ( get_gatewaysinfo(1,refcoin,acname,depositaddr,&M,&N,bindtxidstr,refcoin,oraclestr,&pubkeys) == 0 ) type=1; - else - { - myprintf("cant find bindtxid.(%s)\n",bindtxidstr); - exit(0); - } - if (validateaddress(refcoin,"",depositaddr,"iswatchonly")==0 && validateaddress(refcoin,"",depositaddr,"ismine")==0) - { - if (M==1 && N==1) importaddress(refcoin,"",depositaddr,bindtxidstr,0); - else addmultisigaddress(refcoin,"",M,pubkeys); - } - if (pubkeys!=0) free(pubkeys); - myprintf("set refcoin %s <- %s [%s] M.%d of N.%d\n",depositaddr,refcoin,REFCOIN_CLI,M,N); - } - if ( (regjson= jarray(&n,clijson,"registered")) != 0 ) - { - for (i=0; i Date: Sun, 25 Oct 2020 20:18:57 -0400 Subject: [PATCH 08/31] Update dapps makefile; remove oraclefeed, hushdex updates, no longer build zmigrate --- src/cc/dapps/Makefile | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/cc/dapps/Makefile b/src/cc/dapps/Makefile index 1fea27084..f74df15e5 100644 --- a/src/cc/dapps/Makefile +++ b/src/cc/dapps/Makefile @@ -1,16 +1,17 @@ # Copyright 2020 The Hush Developers -# just type make to compile all dapps -all: zmigrate oraclefeed +# Just type make to compile all dat dapp code, fellow cypherpunk -subatomic: - $(CC) subatomic.c -o subatomic -lm +# we no longer build zmigrate by default, nobody uses that fucking code +all: hushdex +hushdex: + $(CC) hushdex.c -o hushdex -lm + +# Just for historical knowledge, to study how fucking stupid +# ZEC+KMD were to still support sprout, to this day!!!!!!!! zmigrate: $(CC) zmigrate.c -o zmigrate -lm -oraclefeed: - $(CC) oraclefeed.c -o oraclefeed -lm - clean: - rm zmigrate oraclefeed + rm zmigrate From aef46cd5a0a70751b5d59b342b96199204f6bdd1 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 20:19:19 -0400 Subject: [PATCH 09/31] HushDEX updates --- src/cc/dapps/dappinc.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/cc/dapps/dappinc.h b/src/cc/dapps/dappinc.h index 3c71dfdec..6a95adb29 100644 --- a/src/cc/dapps/dappinc.h +++ b/src/cc/dapps/dappinc.h @@ -349,7 +349,7 @@ cJSON *get_komodocli(char *refcoin,char **retstrp,char *acname,char *method,char sprintf(cmdstr,"%s %s %s %s %s %s %s %s %s > %s\n",REFCOIN_CLI,method,arg0,arg1,arg2,arg3,arg4,arg5,arg6,fname); //printf("ref.(%s) REFCOIN_CLI (%s)\n",refcoin,cmdstr); } -//fprintf(stderr,"system(%s)\n",cmdstr); + //fprintf(stderr,"system(%s)\n",cmdstr); system(cmdstr); *retstrp = 0; if ( (jsonstr= filestr(&fsize,fname)) != 0 ) @@ -364,12 +364,13 @@ cJSON *get_komodocli(char *refcoin,char **retstrp,char *acname,char *method,char return(retjson); } -cJSON *subatomic_cli(char *clistr,char **retstrp,char *method,char *arg0,char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6) +cJSON *hushdex_cli(char *clistr,char **retstrp,char *method,char *arg0,char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6) { long fsize; cJSON *retjson = 0; char cmdstr[32768],*jsonstr,fname[32768]; - sprintf(fname,"/tmp/subatomic_%s_%d",method,(rand() >> 17) % 10000); + //TODO: fix this shitty insecure jl777 fucktwattery + sprintf(fname,"/tmp/hushdex_%s_%d",method,(rand() >> 17) % 10000); sprintf(cmdstr,"%s %s %s %s %s %s %s %s %s > %s\n",clistr,method,arg0,arg1,arg2,arg3,arg4,arg5,arg6,fname); -//fprintf(stderr,"system(%s)\n",cmdstr); + //fprintf(stderr,"system(%s)\n",cmdstr); system(cmdstr); *retstrp = 0; if ( (jsonstr= filestr(&fsize,fname)) != 0 ) From 1ef7fba5877b499a0ae3b3ce47fa8638ddd27103 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 20:33:48 -0400 Subject: [PATCH 10/31] Zex mit der Ex --- src/cc/dapps/hushdex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc/dapps/hushdex.c b/src/cc/dapps/hushdex.c index f3ac51dce..2c150495b 100644 --- a/src/cc/dapps/hushdex.c +++ b/src/cc/dapps/hushdex.c @@ -17,7 +17,7 @@ // build hushdex and put in path: git pull; gcc cc/dapps/hushdex.c -lm -o hushdex; cp hushdex /usr/bin // alice sends relcoin and gets basecoin -#define DEXP2P_CHAIN ((char *)"DEX") +#define DEXP2P_CHAIN ((char *)"ZEX") #define DEXP2P_PUBKEYS ((char *)"hushdex") #include "dappinc.h" From c3c431cb1de4fb10a53e24bfd101d1849b670807 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 20:38:20 -0400 Subject: [PATCH 11/31] Delete a bunch of shitcoins --- src/cc/dapps/hushdex.c | 2 +- src/fiat/axo | 2 -- src/fiat/beer | 2 -- src/fiat/bet | 2 -- src/fiat/bntn | 2 -- src/fiat/bots | 2 -- src/fiat/btch | 2 -- src/fiat/ccl | 2 -- src/fiat/ceal | 2 -- src/fiat/chain | 2 -- src/fiat/coquicash | 2 -- src/fiat/crypto | 2 -- src/fiat/dex | 2 -- src/fiat/dion | 2 -- src/fiat/dsec | 2 -- src/fiat/eql | 2 -- src/fiat/etomic | 2 -- src/fiat/glxt | 2 -- src/fiat/hodl | 2 -- src/fiat/hush | 4 ++-- src/fiat/ilien | 3 --- src/fiat/iln | 2 -- src/fiat/jumblr | 2 -- src/fiat/k64 | 2 -- src/fiat/kmdice | 2 -- src/fiat/koin | 2 -- src/fiat/ksb | 2 -- src/fiat/kv | 2 -- src/fiat/mesh | 2 -- src/fiat/mgnx | 2 -- src/fiat/mgw | 2 -- src/fiat/mnz | 2 -- src/fiat/morty | 2 -- src/fiat/mshark | 2 -- src/fiat/ninja | 2 -- src/fiat/oot | 2 -- src/fiat/our | 2 -- src/fiat/pangea | 2 -- src/fiat/pgt | 2 -- src/fiat/pirate | 2 -- src/fiat/pizza | 2 -- src/fiat/prlpay | 2 -- src/fiat/revs | 2 -- src/fiat/rfox | 2 -- src/fiat/rick | 2 -- src/fiat/sec | 2 -- src/fiat/supernet | 2 -- src/fiat/thc | 2 -- src/fiat/wlc | 2 -- src/fiat/zexo | 2 -- src/fiat/zilla | 2 -- 51 files changed, 3 insertions(+), 102 deletions(-) delete mode 100755 src/fiat/axo delete mode 100755 src/fiat/beer delete mode 100755 src/fiat/bet delete mode 100755 src/fiat/bntn delete mode 100755 src/fiat/bots delete mode 100755 src/fiat/btch delete mode 100755 src/fiat/ccl delete mode 100755 src/fiat/ceal delete mode 100755 src/fiat/chain delete mode 100755 src/fiat/coquicash delete mode 100755 src/fiat/crypto delete mode 100755 src/fiat/dex delete mode 100755 src/fiat/dion delete mode 100755 src/fiat/dsec delete mode 100755 src/fiat/eql delete mode 100755 src/fiat/etomic delete mode 100755 src/fiat/glxt delete mode 100755 src/fiat/hodl delete mode 100755 src/fiat/ilien delete mode 100755 src/fiat/iln delete mode 100755 src/fiat/jumblr delete mode 100755 src/fiat/k64 delete mode 100755 src/fiat/kmdice delete mode 100755 src/fiat/koin delete mode 100755 src/fiat/ksb delete mode 100755 src/fiat/kv delete mode 100755 src/fiat/mesh delete mode 100755 src/fiat/mgnx delete mode 100755 src/fiat/mgw delete mode 100755 src/fiat/mnz delete mode 100755 src/fiat/morty delete mode 100755 src/fiat/mshark delete mode 100755 src/fiat/ninja delete mode 100755 src/fiat/oot delete mode 100755 src/fiat/our delete mode 100755 src/fiat/pangea delete mode 100755 src/fiat/pgt delete mode 100755 src/fiat/pirate delete mode 100755 src/fiat/pizza delete mode 100755 src/fiat/prlpay delete mode 100755 src/fiat/revs delete mode 100755 src/fiat/rfox delete mode 100755 src/fiat/rick delete mode 100755 src/fiat/sec delete mode 100755 src/fiat/supernet delete mode 100755 src/fiat/thc delete mode 100755 src/fiat/wlc delete mode 100755 src/fiat/zexo delete mode 100755 src/fiat/zilla diff --git a/src/cc/dapps/hushdex.c b/src/cc/dapps/hushdex.c index 2c150495b..bf97e658b 100644 --- a/src/cc/dapps/hushdex.c +++ b/src/cc/dapps/hushdex.c @@ -1309,7 +1309,7 @@ int32_t main(int32_t argc,char **argv) { if ( dpow_pubkey() < 0 ) { - fprintf(stderr,"couldnt set pubkey for DEX\n"); + fprintf(stderr,"couldnt set pubkey for ZEX\n"); return(-1); } coin = (char *)argv[1]; diff --git a/src/fiat/axo b/src/fiat/axo deleted file mode 100755 index 18d38cac0..000000000 --- a/src/fiat/axo +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=AXO $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/beer b/src/fiat/beer deleted file mode 100755 index 34317bb93..000000000 --- a/src/fiat/beer +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=BEER $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/bet b/src/fiat/bet deleted file mode 100755 index ed99ce59f..000000000 --- a/src/fiat/bet +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=BET $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/bntn b/src/fiat/bntn deleted file mode 100755 index 7ae6f4e8d..000000000 --- a/src/fiat/bntn +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=BNTN $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/bots b/src/fiat/bots deleted file mode 100755 index 15c0fc288..000000000 --- a/src/fiat/bots +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=BOTS $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/btch b/src/fiat/btch deleted file mode 100755 index 6a57ea8d1..000000000 --- a/src/fiat/btch +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=BTCH $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/ccl b/src/fiat/ccl deleted file mode 100755 index c3d03a0a4..000000000 --- a/src/fiat/ccl +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=CCL $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/ceal b/src/fiat/ceal deleted file mode 100755 index 0cbeba67b..000000000 --- a/src/fiat/ceal +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=CEAL $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/chain b/src/fiat/chain deleted file mode 100755 index c55d30fbd..000000000 --- a/src/fiat/chain +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=CHAIN $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/coquicash b/src/fiat/coquicash deleted file mode 100755 index c882b2239..000000000 --- a/src/fiat/coquicash +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=COQUICASH $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/crypto b/src/fiat/crypto deleted file mode 100755 index 5a3d46188..000000000 --- a/src/fiat/crypto +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=CRYPTO $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/dex b/src/fiat/dex deleted file mode 100755 index 67331201a..000000000 --- a/src/fiat/dex +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=DEX $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/dion b/src/fiat/dion deleted file mode 100755 index 889f9e1ad..000000000 --- a/src/fiat/dion +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=DION $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/dsec b/src/fiat/dsec deleted file mode 100755 index a050ca94f..000000000 --- a/src/fiat/dsec +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=DSEC $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/eql b/src/fiat/eql deleted file mode 100755 index 99cfa9a09..000000000 --- a/src/fiat/eql +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=EQL $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/etomic b/src/fiat/etomic deleted file mode 100755 index 76eb0191c..000000000 --- a/src/fiat/etomic +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=ETOMIC $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/glxt b/src/fiat/glxt deleted file mode 100755 index 6cedfbf87..000000000 --- a/src/fiat/glxt +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=GLXT $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/hodl b/src/fiat/hodl deleted file mode 100755 index a5430db59..000000000 --- a/src/fiat/hodl +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=HODL $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/hush b/src/fiat/hush index 3d7a3425d..9ac3edcd4 100755 --- a/src/fiat/hush +++ b/src/fiat/hush @@ -1,7 +1,7 @@ #!/bin/bash - +# Copyright (c) 2018-2020 The Hush developers #set working directory to the location of this script DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $DIR -../komodo-cli -ac_name=HUSH3 "$@" +../hush-cli $@ diff --git a/src/fiat/ilien b/src/fiat/ilien deleted file mode 100755 index 53e571661..000000000 --- a/src/fiat/ilien +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=ILN $1 $2 $3 $4 $5 $6 - diff --git a/src/fiat/iln b/src/fiat/iln deleted file mode 100755 index f453c338e..000000000 --- a/src/fiat/iln +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=ILN $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/jumblr b/src/fiat/jumblr deleted file mode 100755 index 2969c5009..000000000 --- a/src/fiat/jumblr +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=JUMBLR $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/k64 b/src/fiat/k64 deleted file mode 100755 index a3b3bc835..000000000 --- a/src/fiat/k64 +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=K64 $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/kmdice b/src/fiat/kmdice deleted file mode 100755 index ca91bf9a5..000000000 --- a/src/fiat/kmdice +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=KMDICE $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/koin b/src/fiat/koin deleted file mode 100755 index 7e76c6b54..000000000 --- a/src/fiat/koin +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=KOIN $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/ksb b/src/fiat/ksb deleted file mode 100755 index 450c3b3f6..000000000 --- a/src/fiat/ksb +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=KSB $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/kv b/src/fiat/kv deleted file mode 100755 index 997fccb33..000000000 --- a/src/fiat/kv +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=KV $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/mesh b/src/fiat/mesh deleted file mode 100755 index 19b359509..000000000 --- a/src/fiat/mesh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=MESH $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/mgnx b/src/fiat/mgnx deleted file mode 100755 index 9bd85336e..000000000 --- a/src/fiat/mgnx +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=MGNX $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/mgw b/src/fiat/mgw deleted file mode 100755 index 9afa86b7a..000000000 --- a/src/fiat/mgw +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=MGW $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/mnz b/src/fiat/mnz deleted file mode 100755 index f4e1f3501..000000000 --- a/src/fiat/mnz +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=MNZ $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/morty b/src/fiat/morty deleted file mode 100755 index 4579324b7..000000000 --- a/src/fiat/morty +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=MORTY $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/mshark b/src/fiat/mshark deleted file mode 100755 index 1f0c950c6..000000000 --- a/src/fiat/mshark +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=MSHARK $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/ninja b/src/fiat/ninja deleted file mode 100755 index f7722abb0..000000000 --- a/src/fiat/ninja +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=NINJA $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/oot b/src/fiat/oot deleted file mode 100755 index 4c7c6b683..000000000 --- a/src/fiat/oot +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=OOT $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/our b/src/fiat/our deleted file mode 100755 index 66c774476..000000000 --- a/src/fiat/our +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=OUR $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/pangea b/src/fiat/pangea deleted file mode 100755 index 9920189ea..000000000 --- a/src/fiat/pangea +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=PANGEA $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/pgt b/src/fiat/pgt deleted file mode 100755 index 8e124bbd1..000000000 --- a/src/fiat/pgt +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=PGT $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/pirate b/src/fiat/pirate deleted file mode 100755 index 9314209da..000000000 --- a/src/fiat/pirate +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=PIRATE $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/pizza b/src/fiat/pizza deleted file mode 100755 index d8400d9d3..000000000 --- a/src/fiat/pizza +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=PIZZA $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/prlpay b/src/fiat/prlpay deleted file mode 100755 index 3d1063d13..000000000 --- a/src/fiat/prlpay +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=PRLPAY $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/revs b/src/fiat/revs deleted file mode 100755 index b898eb5dc..000000000 --- a/src/fiat/revs +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=REVS $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/rfox b/src/fiat/rfox deleted file mode 100755 index e082505d0..000000000 --- a/src/fiat/rfox +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=RFOX $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/rick b/src/fiat/rick deleted file mode 100755 index b68bd56ab..000000000 --- a/src/fiat/rick +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=RICK $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/sec b/src/fiat/sec deleted file mode 100755 index 185a76cf1..000000000 --- a/src/fiat/sec +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=SEC $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/supernet b/src/fiat/supernet deleted file mode 100755 index d841ffa0e..000000000 --- a/src/fiat/supernet +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=SUPERNET $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/thc b/src/fiat/thc deleted file mode 100755 index 84f9ea69c..000000000 --- a/src/fiat/thc +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=THC $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/wlc b/src/fiat/wlc deleted file mode 100755 index ef7c47b90..000000000 --- a/src/fiat/wlc +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=WLC $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/zexo b/src/fiat/zexo deleted file mode 100755 index b6fd508f2..000000000 --- a/src/fiat/zexo +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=ZEXO $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/zilla b/src/fiat/zilla deleted file mode 100755 index d8c713369..000000000 --- a/src/fiat/zilla +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=ZILLA $1 $2 $3 $4 $5 $6 From 1efc02ff0051f52ad51b1b70241c1597cc485f2c Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 20:40:35 -0400 Subject: [PATCH 12/31] New Hush Smart Chains: ZEX, KUSH and KOOLAID --- src/fiat/koolaid | 3 +++ src/fiat/kush | 3 +++ src/fiat/zex | 3 +++ 3 files changed, 9 insertions(+) create mode 100755 src/fiat/koolaid create mode 100755 src/fiat/kush create mode 100755 src/fiat/zex diff --git a/src/fiat/koolaid b/src/fiat/koolaid new file mode 100755 index 000000000..5c3543ecf --- /dev/null +++ b/src/fiat/koolaid @@ -0,0 +1,3 @@ +#!/bin/bash +# Copyright (c) 2018-2020 The Hush developers +./hush-smart-chain -ac_name=KOOLAID $@ diff --git a/src/fiat/kush b/src/fiat/kush new file mode 100755 index 000000000..b39a0d5fd --- /dev/null +++ b/src/fiat/kush @@ -0,0 +1,3 @@ +#!/bin/bash +# Copyright (c) 2018-2020 The Hush developers +./hush-smart-chain -ac_name=KUSH $@ diff --git a/src/fiat/zex b/src/fiat/zex new file mode 100755 index 000000000..2c95cf1a9 --- /dev/null +++ b/src/fiat/zex @@ -0,0 +1,3 @@ +#!/bin/bash +# Copyright (c) 2018-2020 The Hush developers +./hush-smart-chain -ac_name=ZEX $@ From ce3039d96c26117570164acbb5a9169395e68e6f Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 21:32:27 -0400 Subject: [PATCH 13/31] Delete the failed jl777 experiment called JUMBLR --- src/komodo.h | 1 - src/komodo_gateway.h | 12 +- src/komodo_jumblr.h | 795 ------------------------------------------- src/rpc/misc.cpp | 67 +--- src/rpc/server.cpp | 14 +- src/rpc/server.h | 5 - 6 files changed, 13 insertions(+), 881 deletions(-) delete mode 100644 src/komodo_jumblr.h diff --git a/src/komodo.h b/src/komodo.h index 06d614810..01e81ed1c 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -56,7 +56,6 @@ bool check_pprevnotarizedht(); int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char *dest); #include "komodo_kv.h" -#include "komodo_jumblr.h" #include "komodo_gateway.h" #include "komodo_events.h" #include "komodo_ccdata.h" diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index a6b8d612f..0d9616584 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1442,14 +1442,11 @@ void komodo_passport_iteration() lastinterest = komodo_chainactive_timestamp(); } refsp = komodo_stateptr(symbol,dest); - if ( ASSETCHAINS_SYMBOL[0] == 0 || strcmp(ASSETCHAINS_SYMBOL,"KMDCC") == 0 ) + if ( ASSETCHAINS_SYMBOL[0] == 0 || strcmp(ASSETCHAINS_SYMBOL,"JUSTLIES") == 0 ) { refid = 33; limit = 10000000; - jumblr_iteration(); - } - else - { + } else { limit = 10000000; refid = komodo_baseid(ASSETCHAINS_SYMBOL)+1; // illegal base -> baseid.-1 -> 0 if ( refid == 0 ) @@ -1458,11 +1455,6 @@ void komodo_passport_iteration() return; } } - /*if ( KOMODO_PAX == 0 ) - { - KOMODO_PASSPORT_INITDONE = 1; - return; - }*/ starttime = (uint32_t)time(NULL); if ( callcounter++ < 1 ) limit = 10000; diff --git a/src/komodo_jumblr.h b/src/komodo_jumblr.h deleted file mode 100644 index fca7395e5..000000000 --- a/src/komodo_jumblr.h +++ /dev/null @@ -1,795 +0,0 @@ -/****************************************************************************** - * 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. * - * * - ******************************************************************************/ - -/* - z_exportkey "zaddr" - z_exportwallet "filename" - z_getoperationstatus (["operationid", ... ]) - z_gettotalbalance ( minconf ) - z_importkey "zkey" ( rescan ) - z_importwallet "filename" - z_listaddresses - z_sendmany "fromaddress" [{"address":... ,"amount":..., "memo":""},...] ( minconf ) ( fee ) - */ - -#ifdef _WIN32 -#include -#endif -#include "komodo_defs.h" - -#define JUMBLR_ADDR "RGhxXpXSSBTBm9EvNsXnTQczthMCxHX91t" -#define JUMBLR_BTCADDR "18RmTJe9qMech8siuhYfMtHo8RtcN1obC6" -#define JUMBLR_MAXSECRETADDRS 777 -#define JUMBLR_SYNCHRONIZED_BLOCKS 10 -#define JUMBLR_INCR 9.965 -#define JUMBLR_FEE 0.001 -#define JUMBLR_TXFEE 0.01 -#define SMALLVAL 0.000000000000001 - -#define JUMBLR_ERROR_DUPLICATEDEPOSIT -1 -#define JUMBLR_ERROR_SECRETCANTBEDEPOSIT -2 -#define JUMBLR_ERROR_TOOMANYSECRETS -3 -#define JUMBLR_ERROR_NOTINWALLET -4 - -struct jumblr_item -{ - UT_hash_handle hh; - int64_t amount,fee,txfee; // fee and txfee not really used (yet) - uint32_t spent,pad; - char opid[66],src[128],dest[128],status; -} *Jumblrs; - -char Jumblr_secretaddrs[JUMBLR_MAXSECRETADDRS][64],Jumblr_deposit[64]; -int32_t Jumblr_numsecretaddrs; // if 0 -> run silent mode - -char *jumblr_issuemethod(char *userpass,char *method,char *params,uint16_t port) -{ - cJSON *retjson,*resjson = 0; char *retstr; - if ( (retstr= komodo_issuemethod(userpass,method,params,port)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( jobj(retjson,(char *)"result") != 0 ) - resjson = jduplicate(jobj(retjson,(char *)"result")); - else if ( jobj(retjson,(char *)"error") != 0 ) - resjson = jduplicate(jobj(retjson,(char *)"error")); - else - { - resjson = cJSON_CreateObject(); - jaddstr(resjson,(char *)"error",(char *)"cant parse return"); - } - free_json(retjson); - } - free(retstr); - } - if ( resjson != 0 ) - return(jprint(resjson,1)); - else return(clonestr((char *)"{\"error\":\"unknown error\"}")); -} - -char *jumblr_importaddress(char *address) -{ - char params[1024]; - sprintf(params,"[\"%s\", \"%s\", false]",address,address); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"importaddress",params,BITCOIND_RPCPORT)); -} - -char *jumblr_validateaddress(char *addr) -{ - char params[1024]; - sprintf(params,"[\"%s\"]",addr); - printf("validateaddress.%s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"validateaddress",params,BITCOIND_RPCPORT)); -} - -int32_t Jumblr_secretaddrfind(char *searchaddr) -{ - int32_t i; - for (i=0; i 0 ) - { - OS_randombytes((uint8_t *)&r,sizeof(r)); - r %= Jumblr_numsecretaddrs; - safecopy(secretaddr,Jumblr_secretaddrs[r],64); - } - return(r); -} - -int32_t jumblr_addresstype(char *addr) -{ - if ( addr[0] == '"' && addr[strlen(addr)-1] == '"' ) - { - addr[strlen(addr)-1] = 0; - addr++; - } - if ( addr[0] == 'z' && addr[1] == 'c' && strlen(addr) >= 40 ) - return('z'); - else if ( strlen(addr) < 40 ) - return('t'); - printf("strange.(%s)\n",addr); - return(-1); -} - -struct jumblr_item *jumblr_opidfind(char *opid) -{ - struct jumblr_item *ptr; - HASH_FIND(hh,Jumblrs,opid,(int32_t)strlen(opid),ptr); - return(ptr); -} - -struct jumblr_item *jumblr_opidadd(char *opid) -{ - struct jumblr_item *ptr = 0; - if ( opid != 0 && (ptr= jumblr_opidfind(opid)) == 0 ) - { - ptr = (struct jumblr_item *)calloc(1,sizeof(*ptr)); - safecopy(ptr->opid,opid,sizeof(ptr->opid)); - HASH_ADD_KEYPTR(hh,Jumblrs,ptr->opid,(int32_t)strlen(ptr->opid),ptr); - if ( ptr != jumblr_opidfind(opid) ) - printf("jumblr_opidadd.(%s) ERROR, couldnt find after add\n",opid); - } - return(ptr); -} - -char *jumblr_zgetnewaddress() -{ - char params[1024]; - sprintf(params,"[]"); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getnewaddress",params,BITCOIND_RPCPORT)); -} - -char *jumblr_zlistoperationids() -{ - char params[1024]; - sprintf(params,"[]"); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listoperationids",params,BITCOIND_RPCPORT)); -} - -char *jumblr_zgetoperationresult(char *opid) -{ - char params[1024]; - sprintf(params,"[[\"%s\"]]",opid); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getoperationresult",params,BITCOIND_RPCPORT)); -} - -char *jumblr_zgetoperationstatus(char *opid) -{ - char params[1024]; - sprintf(params,"[[\"%s\"]]",opid); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getoperationstatus",params,BITCOIND_RPCPORT)); -} - -char *jumblr_sendt_to_z(char *taddr,char *zaddr,double amount) -{ - char params[1024]; double fee = ((amount-3*JUMBLR_TXFEE) * JUMBLR_FEE) * 1.5; - if ( jumblr_addresstype(zaddr) != 'z' || jumblr_addresstype(taddr) != 't' ) - return(clonestr((char *)"{\"error\":\"illegal address in t to z\"}")); - sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",taddr,zaddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); - printf("t -> z: %s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); -} - -char *jumblr_sendz_to_z(char *zaddrS,char *zaddrD,double amount) -{ - char params[1024]; double fee = (amount-2*JUMBLR_TXFEE) * JUMBLR_FEE; - if ( jumblr_addresstype(zaddrS) != 'z' || jumblr_addresstype(zaddrD) != 'z' ) - return(clonestr((char *)"{\"error\":\"illegal address in z to z\"}")); - //sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); - sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_TXFEE); - printf("z -> z: %s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); -} - -char *jumblr_sendz_to_t(char *zaddr,char *taddr,double amount) -{ - char params[1024]; double fee = ((amount-JUMBLR_TXFEE) * JUMBLR_FEE) * 1.5; - if ( jumblr_addresstype(zaddr) != 'z' || jumblr_addresstype(taddr) != 't' ) - return(clonestr((char *)"{\"error\":\"illegal address in z to t\"}")); - sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddr,taddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); - printf("z -> t: %s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); -} - -char *jumblr_zlistaddresses() -{ - char params[1024]; - sprintf(params,"[]"); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listaddresses",params,BITCOIND_RPCPORT)); -} - -char *jumblr_zlistreceivedbyaddress(char *addr) -{ - char params[1024]; - sprintf(params,"[\"%s\", 1]",addr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listreceivedbyaddress",params,BITCOIND_RPCPORT)); -} - -char *jumblr_getreceivedbyaddress(char *addr) -{ - char params[1024]; - sprintf(params,"[\"%s\", 1]",addr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"getreceivedbyaddress",params,BITCOIND_RPCPORT)); -} - -char *jumblr_importprivkey(char *wifstr) -{ - char params[1024]; - sprintf(params,"[\"%s\", \"\", false]",wifstr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"importprivkey",params,BITCOIND_RPCPORT)); -} - -char *jumblr_zgetbalance(char *addr) -{ - char params[1024]; - sprintf(params,"[\"%s\", 1]",addr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getbalance",params,BITCOIND_RPCPORT)); -} - -char *jumblr_listunspent(char *coinaddr) -{ - char params[1024]; - sprintf(params,"[1, 99999999, [\"%s\"]]",coinaddr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"listunspent",params,BITCOIND_RPCPORT)); -} - -char *jumblr_gettransaction(char *txidstr) -{ - char params[1024]; - sprintf(params,"[\"%s\", 1]",txidstr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,BITCOIND_RPCPORT)); -} - -int32_t jumblr_numvins(bits256 txid) -{ - char txidstr[65],params[1024],*retstr; cJSON *retjson,*vins; int32_t n,numvins = -1; - bits256_str(txidstr,txid); - if ( (retstr= jumblr_gettransaction(txidstr)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( jobj(retjson,(char *)"vin") != 0 && ((vins= jarray(&n,retjson,(char *)"vin")) == 0 || n == 0) ) - { - numvins = n; - //printf("numvins.%d\n",n); - } //else printf("no vin.(%s)\n",retstr); - free_json(retjson); - } - free(retstr); - } - return(numvins); -} - -int64_t jumblr_receivedby(char *addr) -{ - char *retstr; int64_t total = 0; - if ( (retstr= jumblr_getreceivedbyaddress(addr)) != 0 ) - { - total = atof(retstr) * SATOSHIDEN; - free(retstr); - } - return(total); -} - -int64_t jumblr_balance(char *addr) -{ - char *retstr; double val; int64_t balance = 0; //cJSON *retjson; int32_t i,n; - /*if ( jumblr_addresstype(addr) == 't' ) - { - if ( (retstr= jumblr_listunspent(addr)) != 0 ) - { - //printf("jumblr.[%s].(%s)\n","KMD",retstr); - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( (n= cJSON_GetArraySize(retjson)) > 0 && cJSON_IsArray(retjson) != 0 ) - for (i=0; i SMALLVAL ) - balance = val * SATOSHIDEN; - free(retstr); - } - return(balance); -} - -int32_t jumblr_itemset(struct jumblr_item *ptr,cJSON *item,char *status) -{ - cJSON *params,*amounts,*dest; char *from,*addr; int32_t i,n; int64_t amount; - /*"params" : { - "fromaddress" : "RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5", - "amounts" : [ - { - "address" : "zc9s3UdkDFTnnwHrMCr1vYy2WmkjhmTxXNiqC42s7BjeKBVUwk766TTSsrRPKfnX31Bbu8wbrTqnjDqskYGwx48FZMPHvft", - "amount" : 3.00000000 - } - ], - "minconf" : 1, - "fee" : 0.00010000 - }*/ - if ( (params= jobj(item,(char *)"params")) != 0 ) - { - //printf("params.(%s)\n",jprint(params,0)); - if ( (from= jstr(params,(char *)"fromaddress")) != 0 ) - { - safecopy(ptr->src,from,sizeof(ptr->src)); - } - if ( (amounts= jarray(&n,params,(char *)"amounts")) != 0 ) - { - for (i=0; i 0 ) - { - if ( strcmp(addr,JUMBLR_ADDR) == 0 ) - ptr->fee = amount; - else - { - ptr->amount = amount; - safecopy(ptr->dest,addr,sizeof(ptr->dest)); - } - } - } - } - ptr->txfee = jdouble(params,(char *)"fee") * SATOSHIDEN; - } - return(1); -} - -void jumblr_opidupdate(struct jumblr_item *ptr) -{ - char *retstr,*status; cJSON *retjson,*item; - if ( ptr->status == 0 ) - { - if ( (retstr= jumblr_zgetoperationstatus(ptr->opid)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( cJSON_GetArraySize(retjson) == 1 && cJSON_IsArray(retjson) != 0 ) - { - item = jitem(retjson,0); - //printf("%s\n",jprint(item,0)); - if ( (status= jstr(item,(char *)"status")) != 0 ) - { - if ( strcmp(status,(char *)"success") == 0 ) - { - ptr->status = jumblr_itemset(ptr,item,status); - if ( (jumblr_addresstype(ptr->src) == 't' && jumblr_addresstype(ptr->src) == 'z' && strcmp(ptr->src,Jumblr_deposit) != 0) || (jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->src) == 't' && Jumblr_secretaddrfind(ptr->dest) < 0) ) - { - printf("a non-jumblr t->z pruned\n"); - free(jumblr_zgetoperationresult(ptr->opid)); - ptr->status = -1; - } - - } - else if ( strcmp(status,(char *)"failed") == 0 ) - { - printf("jumblr_opidupdate %s failed\n",ptr->opid); - free(jumblr_zgetoperationresult(ptr->opid)); - ptr->status = -1; - } - } - } - free_json(retjson); - } - free(retstr); - } - } -} - -void jumblr_prune(struct jumblr_item *ptr) -{ - struct jumblr_item *tmp; char oldsrc[128]; int32_t flag = 1; - if ( is_hexstr(ptr->opid,0) == 64 ) - return; - printf("jumblr_prune %s\n",ptr->opid); - strcpy(oldsrc,ptr->src); - free(jumblr_zgetoperationresult(ptr->opid)); - while ( flag != 0 ) - { - flag = 0; - HASH_ITER(hh,Jumblrs,ptr,tmp) - { - if ( strcmp(oldsrc,ptr->dest) == 0 ) - { - if ( is_hexstr(ptr->opid,0) != 64 ) - { - printf("jumblr_prune %s (%s -> %s) matched oldsrc\n",ptr->opid,ptr->src,ptr->dest); - free(jumblr_zgetoperationresult(ptr->opid)); - strcpy(oldsrc,ptr->src); - flag = 1; - break; - } - } - } - } -} - - -bits256 jbits256(cJSON *json,char *field); - - -void jumblr_zaddrinit(char *zaddr) -{ - struct jumblr_item *ptr; char *retstr,*totalstr; cJSON *item,*array; double total; bits256 txid; char txidstr[65],t_z,z_z; - if ( (totalstr= jumblr_zgetbalance(zaddr)) != 0 ) - { - if ( (total= atof(totalstr)) > SMALLVAL ) - { - if ( (retstr= jumblr_zlistreceivedbyaddress(zaddr)) != 0 ) - { - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - t_z = z_z = 0; - if ( cJSON_GetArraySize(array) == 1 && cJSON_IsArray(array) != 0 ) - { - item = jitem(array,0); - if ( (uint64_t)((total+0.0000000049) * SATOSHIDEN) == (uint64_t)((jdouble(item,(char *)"amount")+0.0000000049) * SATOSHIDEN) ) - { - txid = jbits256(item,(char *)"txid"); - bits256_str(txidstr,txid); - if ( (ptr= jumblr_opidadd(txidstr)) != 0 ) - { - ptr->amount = (total * SATOSHIDEN); - ptr->status = 1; - strcpy(ptr->dest,zaddr); - if ( jumblr_addresstype(ptr->dest) != 'z' ) - printf("error setting dest type to Z: %s\n",jprint(item,0)); - if ( jumblr_numvins(txid) == 0 ) - { - z_z = 1; - strcpy(ptr->src,zaddr); - ptr->src[3] = '0'; - ptr->src[4] = '0'; - ptr->src[5] = '0'; - if ( jumblr_addresstype(ptr->src) != 'z' ) - printf("error setting address type to Z: %s\n",jprint(item,0)); - } - else - { - t_z = 1; - strcpy(ptr->src,"taddr"); - if ( jumblr_addresstype(ptr->src) != 't' ) - printf("error setting address type to T: %s\n",jprint(item,0)); - } - printf("%s %s %.8f t_z.%d z_z.%d\n",zaddr,txidstr,total,t_z,z_z); // cant be z->t from spend - } - } else printf("mismatched %s %s total %.8f vs %.8f -> %lld\n",zaddr,totalstr,dstr(SATOSHIDEN * total),dstr(SATOSHIDEN * jdouble(item,(char *)"amount")),(long long)((uint64_t)(total * SATOSHIDEN) - (uint64_t)(jdouble(item,(char *)"amount") * SATOSHIDEN))); - } - free_json(array); - } - free(retstr); - } - } - free(totalstr); - } -} - -void jumblr_opidsupdate() -{ - char *retstr; cJSON *array; int32_t i,n; struct jumblr_item *ptr; - if ( (retstr= jumblr_zlistoperationids()) != 0 ) - { - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - if ( (n= cJSON_GetArraySize(array)) > 0 && cJSON_IsArray(array) != 0 ) - { - //printf("%s -> n%d\n",retstr,n); - for (i=0; istatus == 0 ) - jumblr_opidupdate(ptr); - //printf("%d: %s -> %s %.8f\n",ptr->status,ptr->src,ptr->dest,dstr(ptr->amount)); - if ( jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->dest) == 't' ) - jumblr_prune(ptr); - } - } - } - free_json(array); - } - free(retstr); - } -} - -uint64_t jumblr_increment(uint8_t r,int32_t height,uint64_t total,uint64_t biggest,uint64_t medium, uint64_t smallest) -{ - int32_t i,n; uint64_t incrs[1000],remains = total; - height /= JUMBLR_SYNCHRONIZED_BLOCKS; - if ( (height % JUMBLR_SYNCHRONIZED_BLOCKS) == 0 || total >= 100*biggest ) - { - if ( total >= biggest ) - return(biggest); - else if ( total >= medium ) - return(medium); - else if ( total >= smallest ) - return(smallest); - else return(0); - } - else - { - n = 0; - while ( remains > smallest && n < sizeof(incrs)/sizeof(*incrs) ) - { - if ( remains >= biggest ) - incrs[n] = biggest; - else if ( remains >= medium ) - incrs[n] = medium; - else if ( remains >= smallest ) - incrs[n] = smallest; - else break; - remains -= incrs[n]; - n++; - } - if ( n > 0 ) - { - r %= n; - for (i=0; i %.8f\n",n,r,dstr(incrs[r])); - return(incrs[r]); - } - } - return(0); -} - -void jumblr_iteration() -{ - static int32_t lastheight; static uint32_t lasttime; - char *zaddr,*addr,*retstr=0,secretaddr[64]; cJSON *array; int32_t i,iter,height,acpublic,counter,chosen_one,n; uint64_t smallest,medium,biggest,amount=0,total=0; double fee; struct jumblr_item *ptr,*tmp; uint16_t r,s; - acpublic = ASSETCHAINS_PUBLIC; - if ( ASSETCHAINS_SYMBOL[0] == 0 && GetTime() >= KOMODO_SAPLING_DEADLINE ) - acpublic = 1; - if ( JUMBLR_PAUSE != 0 || acpublic != 0 ) - return; - if ( lasttime == 0 ) - { - if ( (retstr= jumblr_zlistaddresses()) != 0 ) - { - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - if ( (n= cJSON_GetArraySize(array)) > 0 && cJSON_IsArray(array) != 0 ) - { - for (i=0; iGetHeight(); - if ( time(NULL) < lasttime+40 ) - return; - lasttime = (uint32_t)time(NULL); - if ( lastheight == height ) - return; - lastheight = height; - if ( (height % JUMBLR_SYNCHRONIZED_BLOCKS) != JUMBLR_SYNCHRONIZED_BLOCKS-3 ) - return; - fee = JUMBLR_INCR * JUMBLR_FEE; - smallest = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE); - medium = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE); - biggest = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*777 + 3*JUMBLR_TXFEE); - OS_randombytes((uint8_t *)&r,sizeof(r)); - s = (r % 3); - //printf("jumblr_iteration r.%u s.%u\n",r,s); - switch ( s ) - { - case 0: // t -> z - default: - if ( Jumblr_deposit[0] != 0 && (total= jumblr_balance(Jumblr_deposit)) >= smallest ) - { - if ( (zaddr= jumblr_zgetnewaddress()) != 0 ) - { - if ( zaddr[0] == '"' && zaddr[strlen(zaddr)-1] == '"' ) - { - zaddr[strlen(zaddr)-1] = 0; - addr = zaddr+1; - } else addr = zaddr; - amount = jumblr_increment(r/3,height,total,biggest,medium,smallest); - /* - amount = 0; - if ( (height % (JUMBLR_SYNCHRONIZED_BLOCKS*JUMBLR_SYNCHRONIZED_BLOCKS)) == 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE) ) - amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE); - else if ( (r & 3) == 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE) ) - amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE); - else amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE);*/ - if ( amount > 0 && (retstr= jumblr_sendt_to_z(Jumblr_deposit,addr,dstr(amount))) != 0 ) - { - printf("sendt_to_z.(%s)\n",retstr); - free(retstr), retstr = 0; - } - free(zaddr); - } else printf("no zaddr from jumblr_zgetnewaddress\n"); - } - else if ( Jumblr_deposit[0] != 0 ) - printf("%s total %.8f vs %.8f\n",Jumblr_deposit,dstr(total),(JUMBLR_INCR + 3*(fee+JUMBLR_TXFEE))); - break; - case 1: // z -> z - jumblr_opidsupdate(); - chosen_one = -1; - for (iter=counter=0; iter<2; iter++) - { - counter = n = 0; - HASH_ITER(hh,Jumblrs,ptr,tmp) - { - if ( ptr->spent == 0 && ptr->status > 0 && jumblr_addresstype(ptr->src) == 't' && jumblr_addresstype(ptr->dest) == 'z' ) - { - if ( (total= jumblr_balance(ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) - { - if ( iter == 1 && counter == chosen_one ) - { - if ( (zaddr= jumblr_zgetnewaddress()) != 0 ) - { - if ( zaddr[0] == '"' && zaddr[strlen(zaddr)-1] == '"' ) - { - zaddr[strlen(zaddr)-1] = 0; - addr = zaddr+1; - } else addr = zaddr; - if ( (retstr= jumblr_sendz_to_z(ptr->dest,addr,dstr(total))) != 0 ) - { - printf("n.%d counter.%d chosen_one.%d send z_to_z.(%s)\n",n,counter,chosen_one,retstr); - free(retstr), retstr = 0; - } - ptr->spent = (uint32_t)time(NULL); - free(zaddr); - break; - } - } - counter++; - } - } - n++; - } - if ( counter == 0 ) - break; - if ( iter == 0 ) - { - OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one)); - if ( chosen_one < 0 ) - chosen_one = -chosen_one; - chosen_one %= counter; - printf("jumblr z->z chosen_one.%d of %d, from %d\n",chosen_one,counter,n); - } - } - break; - case 2: // z -> t - if ( Jumblr_numsecretaddrs > 0 ) - { - jumblr_opidsupdate(); - chosen_one = -1; - for (iter=0; iter<2; iter++) - { - counter = n = 0; - HASH_ITER(hh,Jumblrs,ptr,tmp) - { - //printf("status.%d %c %c %.8f\n",ptr->status,jumblr_addresstype(ptr->src),jumblr_addresstype(ptr->dest),dstr(ptr->amount)); - if ( ptr->spent == 0 && ptr->status > 0 && jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->dest) == 'z' ) - { - if ( (total= jumblr_balance(ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) - { - if ( iter == 1 && counter == chosen_one ) - { - Jumblr_secretaddr(secretaddr); - if ( (retstr= jumblr_sendz_to_t(ptr->dest,secretaddr,dstr(total))) != 0 ) - { - printf("%s send z_to_t.(%s)\n",secretaddr,retstr); - free(retstr), retstr = 0; - } else printf("null return from jumblr_sendz_to_t\n"); - ptr->spent = (uint32_t)time(NULL); - break; - } - counter++; - } //else printf("z->t spent.%u total %.8f error\n",ptr->spent,dstr(total)); - } - n++; - } - if ( counter == 0 ) - break; - if ( iter == 0 ) - { - OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one)); - if ( chosen_one < 0 ) - chosen_one = -chosen_one; - chosen_one %= counter; - printf("jumblr z->t chosen_one.%d of %d, from %d\n",chosen_one,counter,n); - } //else printf("n.%d counter.%d chosen.%d\n",n,counter,chosen_one); - } - } - break; - } -} diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 0e3a838bf..654c0262e 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -207,8 +207,8 @@ UniValue getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) " \"balance\": xxxxxxx, (numeric) the total Hush balance of the wallet\n" " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n" " \"timeoffset\": xxxxx, (numeric) the time offset (deprecated, always 0)\n" - " \"connections\": xxxxx, (numeric) the number of connections\n" - " \"tls_connections\": xxxxx, (numeric) the number of TLS connections\n" + " \"connections\": xxxxx, (numeric) the number of plaintext connections\n" + " \"tls_connections\": xxxxx, (numeric) the number of encrypted TLS (SSL) connections\n" " \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n" " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" " \"testnet\": true|false, (boolean) if the server is using testnet or not\n" @@ -237,8 +237,11 @@ UniValue getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) UniValue obj(UniValue::VOBJ); obj.push_back(Pair("version", CLIENT_VERSION)); obj.push_back(Pair("protocolversion", PROTOCOL_VERSION)); - obj.push_back(Pair("KMDversion", KOMODO_VERSION)); + // this KMD version represents the last time we did a full merge, we only cherry-pick or take nothing + // in the post-KYC "era" of KMD + obj.push_back(Pair("KMDversion", KOMODO_VERSION)); // never change this again, it's set in stone. -- Duke obj.push_back(Pair("synced", KOMODO_INSYNC!=0)); + // any height larger than this can be attacked! obj.push_back(Pair("notarized", notarized_height)); obj.push_back(Pair("prevMoMheight", prevMoMheight)); obj.push_back(Pair("notarizedhash", notarized_hash.ToString())); @@ -477,64 +480,6 @@ UniValue coinsupply(const UniValue& params, bool fHelp, const CPubKey& mypk) return(result); } -UniValue jumblr_deposit(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - int32_t retval; UniValue result(UniValue::VOBJ); - if (fHelp || params.size() != 1) - throw runtime_error("jumblr_deposit \"depositaddress\"\n"); - CBitcoinAddress address(params[0].get_str()); - bool isValid = address.IsValid(); - if ( isValid != 0 ) - { - string addr = params[0].get_str(); - if ( (retval= Jumblr_depositaddradd((char *)addr.c_str())) >= 0 ) - { - result.push_back(Pair("result", retval)); - JUMBLR_PAUSE = 0; - } - else result.push_back(Pair("error", retval)); - } else result.push_back(Pair("error", "invalid address")); - return(result); -} - -UniValue jumblr_secret(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - int32_t retval; UniValue result(UniValue::VOBJ); - if (fHelp || params.size() != 1) - throw runtime_error("jumblr_secret \"secretaddress\"\n"); - CBitcoinAddress address(params[0].get_str()); - bool isValid = address.IsValid(); - if ( isValid != 0 ) - { - string addr = params[0].get_str(); - retval = Jumblr_secretaddradd((char *)addr.c_str()); - result.push_back(Pair("result", "success")); - result.push_back(Pair("num", retval)); - JUMBLR_PAUSE = 0; - } else result.push_back(Pair("error", "invalid address")); - return(result); -} - -UniValue jumblr_pause(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - int32_t retval; UniValue result(UniValue::VOBJ); - if (fHelp ) - throw runtime_error("jumblr_pause\n"); - JUMBLR_PAUSE = 1; - result.push_back(Pair("result", "paused")); - return(result); -} - -UniValue jumblr_resume(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - int32_t retval; UniValue result(UniValue::VOBJ); - if (fHelp ) - throw runtime_error("jumblr_resume\n"); - JUMBLR_PAUSE = 0; - result.push_back(Pair("result", "resumed")); - return(result); -} - UniValue validateaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) { if (fHelp || params.size() != 1) diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index f6b3ab480..aa5375d94 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -594,15 +594,11 @@ static const CRPCCommand vRPCCommands[] = { "util", "estimatefee", &estimatefee, true }, { "util", "estimatepriority", &estimatepriority, true }, { "util", "z_validateaddress", &z_validateaddress, true }, /* uses wallet if enabled */ - { "util", "jumblr_deposit", &jumblr_deposit, true }, - { "util", "jumblr_secret", &jumblr_secret, true }, - { "util", "jumblr_pause", &jumblr_pause, true }, - { "util", "jumblr_resume", &jumblr_resume, true }, - - { "util", "invalidateblock", &invalidateblock, true }, - { "util", "reconsiderblock", &reconsiderblock, true }, - /* Not shown in help */ - { "hidden", "setmocktime", &setmocktime, true }, + { "util", "invalidateblock", &invalidateblock, true }, + { "util", "reconsiderblock", &reconsiderblock, true }, + /* Fuck not showing users all the options -- Duke */ + /* setmocktime used to Not be shown in help */ + { "util", "setmocktime", &setmocktime, true }, #ifdef ENABLE_WALLET diff --git a/src/rpc/server.h b/src/rpc/server.h index bbcbc05ed..65422ab1b 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -403,11 +403,6 @@ extern UniValue getdeprecationinfo(const UniValue& params, bool fHelp, const CPu extern UniValue setmocktime(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue resendwallettransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue jumblr_deposit(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue jumblr_secret(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue jumblr_pause(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue jumblr_resume(const UniValue& params, bool fHelp, const CPubKey& mypk); - extern UniValue getrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rcprawtransaction.cpp extern UniValue listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue lockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); From 3e68510a54393d7bb0b635140411a64836301de8 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 21:32:40 -0400 Subject: [PATCH 14/31] Delete KMD shitcoins --- src/assetchains.json | 313 ------------------------------------------- 1 file changed, 313 deletions(-) diff --git a/src/assetchains.json b/src/assetchains.json index 23a8ea959..c81d72c57 100644 --- a/src/assetchains.json +++ b/src/assetchains.json @@ -1,271 +1,4 @@ [ - { - "ac_name": "REVS", - "ac_supply": "1300000" - }, - { - "ac_name": "SUPERNET", - "ac_supply": "816061" - }, - { - "ac_name": "DEX", - "ac_supply": "999999" - }, - { - "ac_name": "PANGEA", - "ac_supply": "999999" - }, - { - "ac_name": "JUMBLR", - "ac_supply": "999999" - }, - { - "ac_name": "BET", - "ac_supply": "999999" - }, - { - "ac_name": "CRYPTO", - "ac_supply": "999999" - }, - { - "ac_name": "HODL", - "ac_supply": "9999999" - }, - { - "ac_name": "MSHARK", - "ac_supply": "1400000" - }, - { - "ac_name": "BOTS", - "ac_supply": "999999" - }, - { - "ac_name": "MGW", - "ac_supply": "999999" - }, - { - "ac_name": "COQUICASH", - "ac_supply": "72000000", - "ac_reward": "7200000000", - "ac_staked": "50", - "ac_halving": "420000", - "ac_cc": "2", - "ac_ccenable": "227,235,236,241", - "addnode": [ - "78.47.108.168" - ] - }, - { - "ac_name": "WLC", - "ac_supply": "210000000" - }, - { - "ac_name": "KV", - "ac_supply": "1000000" - }, - { - "ac_name": "CEAL", - "ac_supply": "366666666" - }, - { - "ac_name": "MESH", - "ac_supply": "1000007" - }, - { - "ac_name": "AXO", - "ac_supply": "200000000", - "ac_ccactivate": "130000" - }, - { - "ac_name": "ETOMIC", - "ac_supply": "100000000" - }, - { - "ac_name": "BTCH", - "ac_supply": "20998641" - }, - { - "ac_name": "NINJA", - "ac_supply": "100000000" - }, - { - "ac_name": "OOT", - "ac_supply": "216000000", - "ac_sapling": "5000000" - }, - { - "ac_name": "BNTN", - "ac_supply": "500000000" - }, - { - "ac_name": "CHAIN", - "ac_supply": "999999" - }, - { - "ac_name": "PRLPAY", - "ac_supply": "500000000" - }, - { - "ac_name": "DSEC", - "ac_supply": "7000000" - }, - { - "ac_name": "EQL", - "ac_supply": "500000000", - "ac_ccactivate": "205000" - }, - { - "ac_name": "ZILLA", - "ac_supply": "11000000", - "ac_sapling": "5000000", - "addnode": [ - "51.68.215.104" - ] - }, - { - "ac_name": "RFOX", - "ac_supply": "1000000000", - "ac_reward": "100000000" - }, - { - "ac_name": "SEC", - "ac_supply": "1000000000", - "ac_cc": "333" - }, - { - "ac_name": "CCL", - "ac_supply": "200000000", - "ac_end": "1", - "ac_cc": "2", - "addressindex": "1", - "spentindex": "1", - "addnode": [ - "142.93.136.89", - "195.201.22.89" - ] - }, - { - "ac_name": "PIRATE", - "ac_supply": "0", - "ac_reward": "25600000000", - "ac_halving": "77777", - "ac_private": "1", - "addnode": [ - "136.243.102.225" - ] - }, - { - "ac_name": "PGT", - "ac_supply": "10000000", - "ac_end": "1", - "addnode": [ - "190.114.254.104" - ] - }, - { - "ac_name": "DION", - "ac_supply": "3900000000", - "ac_reward": "22260000000", - "ac_staked": "100", - "ac_cc": "1", - "ac_end": "4300000000", - "addnode": [ - "51.75.124.34" - ] - }, - { - "ac_name": "KMDICE", - "ac_supply": "10500000", - "ac_reward": "2500000000", - "ac_halving": "210000", - "ac_cc": "2", - "addressindex": "1", - "spentindex": "1", - "addnode": [ - "144.76.217.232" - ] - }, - { - "ac_name": "KSB", - "ac_supply": "1000000000", - "ac_end": "1", - "ac_public": "1", - "addnode": [ - "37.187.225.231" - ] - }, - { - "ac_name": "OUR", - "ac_reward": "1478310502", - "ac_halving": "525600", - "ac_cc": "42", - "ac_supply": "100000000", - "ac_perc": "77700", - "ac_staked": "93", - "ac_pubkey": "02652a3f3e00b3a1875a918314f0bac838d6dd189a346fa623f5efe9541ac0b98c", - "ac_public": "1", - "addnode": [ - "51.255.195.65", - "217.182.129.38", - "37.187.225.231" - ] - }, - { - "ac_name": "ILN", - "ac_supply": "10000000000", - "ac_cc": "2", - "addnode": ["51.75.122.83"] - }, - { - "ac_name": "RICK", - "ac_supply": "90000000000", - "ac_reward": "100000000", - "ac_cc": "3", - "ac_staked": "10", - "addnode": [ - "138.201.136.145", - "95.217.44.58" - ] - }, - { - "ac_name": "MORTY", - "ac_supply": "90000000000", - "ac_reward": "100000000", - "ac_cc": "3", - "ac_staked": "10", - "addnode": [ - "138.201.136.145", - "95.217.44.58" - ] - }, - { - "ac_name": "KOIN", - "ac_supply": "125000000", - "addnode": ["3.0.32.10"] - }, - { - "ac_name": "ZEXO", - "ac_reward": "1478310502", - "ac_halving": "525600", - "ac_cc": "42", - "ac_ccenable": "236", - "ac_supply": "100000000", - "ac_perc": "77700", - "ac_staked": "93", - "ac_pubkey": "02713bd85e054db923694b6b7a85306264edf4d6bd6d331814f2b40af444b3ebbc", - "ac_public": "1", - "addnode": [ - "195.201.20.230", - "80.240.17.222" - ] - }, - { - "ac_name": "K64", - "ac_reward": "0", - "ac_supply": "64000777", - "ac_staked": "10", - "addnode": ["18.197.20.21"] - }, { "ac_name": "HUSH3", "ac_sapling": "1", @@ -288,50 +21,4 @@ "5.9.224.250" ] }, - { - "ac_name": "THC", - "ac_supply": "251253103", - "ac_reward": "360000000,300000000,240000000,180000000,150000000,90000000,0", - "ac_staked": "100", - "ac_eras": "7", - "ac_end": "500001,1000001,1500001,2000001,2500001,4500001,0", - "ac_perc": "233333333", - "ac_cc": "2", - "ac_ccenable": "229,236,240", - "ac_script": "2ea22c8020987fad30df055db6fd922c3a57e55d76601229ed3da3b31340112e773df3d0d28103120c008203000401ccb8", - "ac_founders": "150", - "ac_cbmaturity": "1", - "ac_sapling": "1", - "earlytxid": "7e4a76259e99c9379551389e9f757fc5f46c33ae922a8644dc2b187af2a6adc1", - "addnode": [ - "157.230.45.184", - "165.22.52.123" - ] - }, - { - "ac_name": "COMMOD", - "ac_supply": "0", - "ac_reward": "204800000000,100000000", - "ac_end": "482130,0", - "ac_halving": "43830,525960", - "ac_decay": "50000000,10000000", - "ac_eras": "2", - "ac_cc": "777", - "ac_public": "1", - "addnode": [ - "34.246.186.176", - "34.251.151.148" - ] - }, - { - "ac_name": "WLC21", - "ac_supply": "21000000", - "ac_reward": "190258751", - "ac_staked": "90", - "ac_public": "1", - "addnode": [ - "37.187.225.231", - "51.38.38.134" - ] - } ] From ce3c4974af1b91eff5b5d578de8683882aa6d649 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 21:32:57 -0400 Subject: [PATCH 15/31] Name change --- src/{assetchains.json => smartchains.json} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{assetchains.json => smartchains.json} (100%) diff --git a/src/assetchains.json b/src/smartchains.json similarity index 100% rename from src/assetchains.json rename to src/smartchains.json From 8d991a11e7f1609b127f770b4bf564d0b268dd71 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 21:34:34 -0400 Subject: [PATCH 16/31] Since they day I looked at this codebase the subdir ./fiat made no sense to me --- src/ac/axo | 2 -- src/ac/beer | 2 -- src/ac/bet | 2 -- src/ac/bntn | 2 -- src/ac/bots | 2 -- src/ac/btch | 2 -- src/ac/ccl | 2 -- src/ac/ceal | 2 -- src/ac/chain | 2 -- src/ac/coquicash | 2 -- src/ac/crypto | 2 -- src/ac/dex | 2 -- src/ac/dion | 2 -- src/ac/dsec | 2 -- src/ac/eql | 2 -- src/ac/etomic | 2 -- src/ac/glxt | 2 -- src/ac/hodl | 2 -- src/ac/ilien | 3 --- src/ac/iln | 2 -- src/ac/jumblr | 2 -- src/ac/k64 | 2 -- src/ac/kmdice | 2 -- src/ac/koin | 2 -- src/ac/ksb | 2 -- src/ac/kv | 2 -- src/ac/mesh | 2 -- src/ac/mgnx | 2 -- src/ac/mgw | 2 -- src/ac/mnz | 2 -- src/ac/morty | 2 -- src/ac/mshark | 2 -- src/ac/ninja | 2 -- src/ac/oot | 2 -- src/ac/our | 2 -- src/ac/pangea | 2 -- src/ac/pgt | 2 -- src/ac/pirate | 2 -- src/ac/pizza | 2 -- src/ac/prlpay | 2 -- src/ac/revs | 2 -- src/ac/rick | 2 -- src/ac/supernet | 2 -- src/ac/thc | 2 -- src/ac/vote2018 | 2 -- src/ac/vote2019 | 2 -- src/ac/wlc | 2 -- src/ac/zexo | 2 -- src/{fiat => sc}/hush | 0 src/{fiat => sc}/koolaid | 0 src/{fiat => sc}/kush | 0 src/{fiat => sc}/zex | 0 52 files changed, 97 deletions(-) delete mode 100755 src/ac/axo delete mode 100755 src/ac/beer delete mode 100755 src/ac/bet delete mode 100755 src/ac/bntn delete mode 100755 src/ac/bots delete mode 100755 src/ac/btch delete mode 100755 src/ac/ccl delete mode 100755 src/ac/ceal delete mode 100755 src/ac/chain delete mode 100755 src/ac/coquicash delete mode 100755 src/ac/crypto delete mode 100755 src/ac/dex delete mode 100755 src/ac/dion delete mode 100755 src/ac/dsec delete mode 100755 src/ac/eql delete mode 100755 src/ac/etomic delete mode 100755 src/ac/glxt delete mode 100755 src/ac/hodl delete mode 100755 src/ac/ilien delete mode 100755 src/ac/iln delete mode 100755 src/ac/jumblr delete mode 100755 src/ac/k64 delete mode 100755 src/ac/kmdice delete mode 100755 src/ac/koin delete mode 100755 src/ac/ksb delete mode 100755 src/ac/kv delete mode 100755 src/ac/mesh delete mode 100755 src/ac/mgnx delete mode 100755 src/ac/mgw delete mode 100755 src/ac/mnz delete mode 100755 src/ac/morty delete mode 100755 src/ac/mshark delete mode 100755 src/ac/ninja delete mode 100755 src/ac/oot delete mode 100755 src/ac/our delete mode 100755 src/ac/pangea delete mode 100755 src/ac/pgt delete mode 100755 src/ac/pirate delete mode 100755 src/ac/pizza delete mode 100755 src/ac/prlpay delete mode 100755 src/ac/revs delete mode 100755 src/ac/rick delete mode 100755 src/ac/supernet delete mode 100755 src/ac/thc delete mode 100755 src/ac/vote2018 delete mode 100755 src/ac/vote2019 delete mode 100755 src/ac/wlc delete mode 100755 src/ac/zexo rename src/{fiat => sc}/hush (100%) rename src/{fiat => sc}/koolaid (100%) rename src/{fiat => sc}/kush (100%) rename src/{fiat => sc}/zex (100%) diff --git a/src/ac/axo b/src/ac/axo deleted file mode 100755 index 18d38cac0..000000000 --- a/src/ac/axo +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=AXO $1 $2 $3 $4 $5 $6 diff --git a/src/ac/beer b/src/ac/beer deleted file mode 100755 index 34317bb93..000000000 --- a/src/ac/beer +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=BEER $1 $2 $3 $4 $5 $6 diff --git a/src/ac/bet b/src/ac/bet deleted file mode 100755 index ed99ce59f..000000000 --- a/src/ac/bet +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=BET $1 $2 $3 $4 $5 $6 diff --git a/src/ac/bntn b/src/ac/bntn deleted file mode 100755 index 7ae6f4e8d..000000000 --- a/src/ac/bntn +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=BNTN $1 $2 $3 $4 $5 $6 diff --git a/src/ac/bots b/src/ac/bots deleted file mode 100755 index 15c0fc288..000000000 --- a/src/ac/bots +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=BOTS $1 $2 $3 $4 $5 $6 diff --git a/src/ac/btch b/src/ac/btch deleted file mode 100755 index 6a57ea8d1..000000000 --- a/src/ac/btch +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=BTCH $1 $2 $3 $4 $5 $6 diff --git a/src/ac/ccl b/src/ac/ccl deleted file mode 100755 index c3d03a0a4..000000000 --- a/src/ac/ccl +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=CCL $1 $2 $3 $4 $5 $6 diff --git a/src/ac/ceal b/src/ac/ceal deleted file mode 100755 index 0cbeba67b..000000000 --- a/src/ac/ceal +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=CEAL $1 $2 $3 $4 $5 $6 diff --git a/src/ac/chain b/src/ac/chain deleted file mode 100755 index c55d30fbd..000000000 --- a/src/ac/chain +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=CHAIN $1 $2 $3 $4 $5 $6 diff --git a/src/ac/coquicash b/src/ac/coquicash deleted file mode 100755 index c882b2239..000000000 --- a/src/ac/coquicash +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=COQUICASH $1 $2 $3 $4 $5 $6 diff --git a/src/ac/crypto b/src/ac/crypto deleted file mode 100755 index 5a3d46188..000000000 --- a/src/ac/crypto +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=CRYPTO $1 $2 $3 $4 $5 $6 diff --git a/src/ac/dex b/src/ac/dex deleted file mode 100755 index 67331201a..000000000 --- a/src/ac/dex +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=DEX $1 $2 $3 $4 $5 $6 diff --git a/src/ac/dion b/src/ac/dion deleted file mode 100755 index 889f9e1ad..000000000 --- a/src/ac/dion +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=DION $1 $2 $3 $4 $5 $6 diff --git a/src/ac/dsec b/src/ac/dsec deleted file mode 100755 index a050ca94f..000000000 --- a/src/ac/dsec +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=DSEC $1 $2 $3 $4 $5 $6 diff --git a/src/ac/eql b/src/ac/eql deleted file mode 100755 index 99cfa9a09..000000000 --- a/src/ac/eql +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=EQL $1 $2 $3 $4 $5 $6 diff --git a/src/ac/etomic b/src/ac/etomic deleted file mode 100755 index 76eb0191c..000000000 --- a/src/ac/etomic +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=ETOMIC $1 $2 $3 $4 $5 $6 diff --git a/src/ac/glxt b/src/ac/glxt deleted file mode 100755 index 6cedfbf87..000000000 --- a/src/ac/glxt +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=GLXT $1 $2 $3 $4 $5 $6 diff --git a/src/ac/hodl b/src/ac/hodl deleted file mode 100755 index a5430db59..000000000 --- a/src/ac/hodl +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=HODL $1 $2 $3 $4 $5 $6 diff --git a/src/ac/ilien b/src/ac/ilien deleted file mode 100755 index 53e571661..000000000 --- a/src/ac/ilien +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=ILN $1 $2 $3 $4 $5 $6 - diff --git a/src/ac/iln b/src/ac/iln deleted file mode 100755 index f453c338e..000000000 --- a/src/ac/iln +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=ILN $1 $2 $3 $4 $5 $6 diff --git a/src/ac/jumblr b/src/ac/jumblr deleted file mode 100755 index 2969c5009..000000000 --- a/src/ac/jumblr +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=JUMBLR $1 $2 $3 $4 $5 $6 diff --git a/src/ac/k64 b/src/ac/k64 deleted file mode 100755 index a3b3bc835..000000000 --- a/src/ac/k64 +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=K64 $1 $2 $3 $4 $5 $6 diff --git a/src/ac/kmdice b/src/ac/kmdice deleted file mode 100755 index ca91bf9a5..000000000 --- a/src/ac/kmdice +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=KMDICE $1 $2 $3 $4 $5 $6 diff --git a/src/ac/koin b/src/ac/koin deleted file mode 100755 index 7e76c6b54..000000000 --- a/src/ac/koin +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=KOIN $1 $2 $3 $4 $5 $6 diff --git a/src/ac/ksb b/src/ac/ksb deleted file mode 100755 index 450c3b3f6..000000000 --- a/src/ac/ksb +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=KSB $1 $2 $3 $4 $5 $6 diff --git a/src/ac/kv b/src/ac/kv deleted file mode 100755 index 997fccb33..000000000 --- a/src/ac/kv +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=KV $1 $2 $3 $4 $5 $6 diff --git a/src/ac/mesh b/src/ac/mesh deleted file mode 100755 index 19b359509..000000000 --- a/src/ac/mesh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=MESH $1 $2 $3 $4 $5 $6 diff --git a/src/ac/mgnx b/src/ac/mgnx deleted file mode 100755 index 9bd85336e..000000000 --- a/src/ac/mgnx +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=MGNX $1 $2 $3 $4 $5 $6 diff --git a/src/ac/mgw b/src/ac/mgw deleted file mode 100755 index 9afa86b7a..000000000 --- a/src/ac/mgw +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=MGW $1 $2 $3 $4 $5 $6 diff --git a/src/ac/mnz b/src/ac/mnz deleted file mode 100755 index f4e1f3501..000000000 --- a/src/ac/mnz +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=MNZ $1 $2 $3 $4 $5 $6 diff --git a/src/ac/morty b/src/ac/morty deleted file mode 100755 index 4579324b7..000000000 --- a/src/ac/morty +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=MORTY $1 $2 $3 $4 $5 $6 diff --git a/src/ac/mshark b/src/ac/mshark deleted file mode 100755 index 1f0c950c6..000000000 --- a/src/ac/mshark +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=MSHARK $1 $2 $3 $4 $5 $6 diff --git a/src/ac/ninja b/src/ac/ninja deleted file mode 100755 index f7722abb0..000000000 --- a/src/ac/ninja +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=NINJA $1 $2 $3 $4 $5 $6 diff --git a/src/ac/oot b/src/ac/oot deleted file mode 100755 index 4c7c6b683..000000000 --- a/src/ac/oot +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=OOT $1 $2 $3 $4 $5 $6 diff --git a/src/ac/our b/src/ac/our deleted file mode 100755 index 66c774476..000000000 --- a/src/ac/our +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=OUR $1 $2 $3 $4 $5 $6 diff --git a/src/ac/pangea b/src/ac/pangea deleted file mode 100755 index 9920189ea..000000000 --- a/src/ac/pangea +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=PANGEA $1 $2 $3 $4 $5 $6 diff --git a/src/ac/pgt b/src/ac/pgt deleted file mode 100755 index 8e124bbd1..000000000 --- a/src/ac/pgt +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=PGT $1 $2 $3 $4 $5 $6 diff --git a/src/ac/pirate b/src/ac/pirate deleted file mode 100755 index 9314209da..000000000 --- a/src/ac/pirate +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=PIRATE $1 $2 $3 $4 $5 $6 diff --git a/src/ac/pizza b/src/ac/pizza deleted file mode 100755 index d8400d9d3..000000000 --- a/src/ac/pizza +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=PIZZA $1 $2 $3 $4 $5 $6 diff --git a/src/ac/prlpay b/src/ac/prlpay deleted file mode 100755 index 3d1063d13..000000000 --- a/src/ac/prlpay +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=PRLPAY $1 $2 $3 $4 $5 $6 diff --git a/src/ac/revs b/src/ac/revs deleted file mode 100755 index b898eb5dc..000000000 --- a/src/ac/revs +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=REVS $1 $2 $3 $4 $5 $6 diff --git a/src/ac/rick b/src/ac/rick deleted file mode 100755 index b68bd56ab..000000000 --- a/src/ac/rick +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=RICK $1 $2 $3 $4 $5 $6 diff --git a/src/ac/supernet b/src/ac/supernet deleted file mode 100755 index d841ffa0e..000000000 --- a/src/ac/supernet +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=SUPERNET $1 $2 $3 $4 $5 $6 diff --git a/src/ac/thc b/src/ac/thc deleted file mode 100755 index 84f9ea69c..000000000 --- a/src/ac/thc +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=THC $1 $2 $3 $4 $5 $6 diff --git a/src/ac/vote2018 b/src/ac/vote2018 deleted file mode 100755 index 4e385d76f..000000000 --- a/src/ac/vote2018 +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=VOTE2018 $1 $2 $3 $4 $5 $6 diff --git a/src/ac/vote2019 b/src/ac/vote2019 deleted file mode 100755 index 029558808..000000000 --- a/src/ac/vote2019 +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=VOTE2019 $1 $2 $3 $4 $5 $6 diff --git a/src/ac/wlc b/src/ac/wlc deleted file mode 100755 index ef7c47b90..000000000 --- a/src/ac/wlc +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=WLC $1 $2 $3 $4 $5 $6 diff --git a/src/ac/zexo b/src/ac/zexo deleted file mode 100755 index b6fd508f2..000000000 --- a/src/ac/zexo +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=ZEXO $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/hush b/src/sc/hush similarity index 100% rename from src/fiat/hush rename to src/sc/hush diff --git a/src/fiat/koolaid b/src/sc/koolaid similarity index 100% rename from src/fiat/koolaid rename to src/sc/koolaid diff --git a/src/fiat/kush b/src/sc/kush similarity index 100% rename from src/fiat/kush rename to src/sc/kush diff --git a/src/fiat/zex b/src/sc/zex similarity index 100% rename from src/fiat/zex rename to src/sc/zex From a414330ad8e3ca6c0046dbdb35630f115d9d29b4 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 21:38:23 -0400 Subject: [PATCH 17/31] We call them Hush Smart Chains (HSC) --- src/{assetchains.old => smartchains} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{assetchains.old => smartchains} (100%) diff --git a/src/assetchains.old b/src/smartchains similarity index 100% rename from src/assetchains.old rename to src/smartchains From c1686d7baaf8af1acc69421f82801c863aca4820 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 21:44:39 -0400 Subject: [PATCH 18/31] Update smartchains script --- src/smartchains | 60 +++++++++---------------------------------------- 1 file changed, 11 insertions(+), 49 deletions(-) diff --git a/src/smartchains b/src/smartchains index 0a2c4fb7b..529985f35 100755 --- a/src/smartchains +++ b/src/smartchains @@ -1,55 +1,17 @@ #!/bin/bash +# Copyright (c) 2018-2020 The Hush developers set -x delay=60 source pubkey.txt echo $pubkey +echo "jl777 is a traitor to his village of cypherpunks, ca333 is his obedient servant" -./komodod -pubkey=$pubkey -ac_name=REVS -ac_supply=1300000 -addnode=95.213.238.98 $1 & -./komodod -pubkey=$pubkey -ac_name=SUPERNET -ac_supply=816061 -addnode=95.213.238.98 $1 & -./komodod -pubkey=$pubkey -ac_name=DEX -ac_supply=999999 -addnode=95.213.238.98 $1 & -./komodod -pubkey=$pubkey -ac_name=PANGEA -ac_supply=999999 -addnode=95.213.238.98 $1 & -./komodod -pubkey=$pubkey -ac_name=JUMBLR -ac_supply=999999 -addnode=95.213.238.98 $1 & -./komodod -pubkey=$pubkey -ac_name=BET -ac_supply=999999 -addnode=95.213.238.98 $1 & -./komodod -pubkey=$pubkey -ac_name=CRYPTO -ac_supply=999999 -addnode=95.213.238.98 $1 & -./komodod -pubkey=$pubkey -ac_name=HODL -ac_supply=9999999 -addnode=95.213.238.98 $1 & -./komodod -pubkey=$pubkey -ac_name=MSHARK -ac_supply=1400000 -addnode=95.213.238.98 $1 & -./komodod -pubkey=$pubkey -ac_name=BOTS -ac_supply=999999 -addnode=95.213.238.98 $1 & -./komodod -pubkey=$pubkey -ac_name=MGW -ac_supply=999999 -addnode=95.213.238.98 $1 & -./komodod -pubkey=$pubkey -ac_name=COQUICASH -ac_supply=72000000 -ac_reward=7200000000 -ac_staked=50 -ac_halving=420000 -ac_cc=2 -ac_ccenable=227,235,236,241 -addnode=78.47.108.168 & -./komodod -pubkey=$pubkey -ac_name=WLC -ac_supply=210000000 -addnode=95.213.238.98 $1 & -./komodod -pubkey=$pubkey -ac_name=KV -ac_supply=1000000 -addnode=95.213.238.98 $1 & -./komodod -pubkey=$pubkey -ac_name=CEAL -ac_supply=366666666 -addnode=95.213.238.98 $1 & -./komodod -pubkey=$pubkey -ac_name=MESH -ac_supply=1000007 -addnode=95.213.238.98 $1 & -./komodod -pubkey=$pubkey -ac_name=AXO -ac_supply=200000000 -ac_ccactivate=130000 -addnode=95.213.238.98 & -./komodod -pubkey=$pubkey -ac_name=ETOMIC -ac_supply=100000000 -addnode=95.213.238.98 & -./komodod -pubkey=$pubkey -ac_name=BTCH -ac_supply=20998641 -addnode=95.213.238.98 & -#./komodod -pubkey=$pubkey -ac_name=BEER -ac_supply=100000000 -addnode=95.213.238.98 & -#./komodod -pubkey=$pubkey -ac_name=PIZZA -ac_supply=100000000 -addnode=95.213.238.98 & -./komodod -pubkey=$pubkey -ac_name=NINJA -ac_supply=100000000 -addnode=95.213.238.98 & -./komodod -pubkey=$pubkey -ac_name=OOT -ac_supply=216000000 -ac_sapling=5000000 -addnode=95.213.238.98 & -./komodod -pubkey=$pubkey -ac_name=BNTN -ac_supply=500000000 -addnode=95.213.238.98 & -./komodod -pubkey=$pubkey -ac_name=CHAIN -ac_supply=999999 -addnode=95.213.238.98 & -./komodod -pubkey=$pubkey -ac_name=PRLPAY -ac_supply=500000000 -addnode=13.250.226.125 & -./komodod -pubkey=$pubkey -ac_name=DSEC -ac_supply=7000000 -addnode=185.148.147.30 & -#./komodod -pubkey=$pubkey -ac_name=GLXT -ac_supply=10000000000 -addnode=13.230.224.15 & -./komodod -pubkey=$pubkey -ac_name=EQL -ac_supply=500000000 -ac_ccactivate=205000 -addnode=46.101.124.153 & -./komodod -pubkey=$pubkey -ac_name=ZILLA -ac_supply=11000000 -ac_sapling=5000000 -addnode=51.68.215.104 & -./komodod -pubkey=$pubkey -ac_name=RFOX -ac_supply=1000000000 -ac_reward=100000000 -addnode=95.213.238.98 & -./komodod -pubkey=$pubkey -ac_name=SEC -ac_cc=333 -ac_supply=1000000000 -addnode=185.148.145.43 & -./komodod -pubkey=$pubkey -ac_name=CCL -ac_supply=200000000 -ac_end=1 -ac_cc=2 -addressindex=1 -spentindex=1 -addnode=142.93.136.89 -addnode=195.201.22.89 & -./komodod -pubkey=$pubkey -ac_name=PIRATE -ac_supply=0 -ac_reward=25600000000 -ac_halving=77777 -ac_private=1 -addnode=178.63.77.56 & -#./komodod -pubkey=$pubkey -ac_name=MGNX -ac_supply=12465003 -ac_staked=90 -ac_reward=2000000000 -ac_halving=525960 -ac_cc=2 -ac_end=2629800 -addnode=142.93.27.180 & -./komodod -pubkey=$pubkey -ac_name=PGT -ac_supply=10000000 -ac_end=1 -addnode=190.114.254.104 & -./komodod -pubkey=$pubkey -ac_name=KMDICE -ac_supply=10500000 -ac_reward=2500000000 -ac_halving=210000 -ac_cc=2 -addressindex=1 -spentindex=1 -addnode=144.76.217.232 & -./komodod -pubkey=$pubkey -ac_name=DION -ac_supply=3900000000 -ac_reward=22260000000 -ac_staked=100 -ac_cc=1 -ac_end=4300000000 -addnode=51.75.124.34 & -./komodod -pubkey=$pubkey -ac_name=KSB -ac_supply=1000000000 -ac_end=1 -ac_public=1 -addnode=37.187.225.231 & -./komodod -pubkey=$pubkey -ac_name=OUR -ac_reward=1478310502 -ac_halving=525600 -ac_cc=42 -ac_supply=100000000 -ac_perc=77700 -ac_staked=93 -ac_pubkey=02652a3f3e00b3a1875a918314f0bac838d6dd189a346fa623f5efe9541ac0b98c -ac_public=1 -addnode=51.255.195.65 -addnode=217.182.129.38 -addnode=37.187.225.231 & -./komodod -pubkey=$pubkey -ac_name=ILN -ac_supply=10000000000 -ac_cc=2 -addressindex=1 -spentindex=1 -addnode=51.75.122.83 & -./komodod -pubkey=$pubkey -ac_name=RICK -ac_supply=90000000000 -ac_reward=100000000 -ac_cc=3 -ac_staked=10 -addnode=95.217.44.58 -addnode=138.201.136.145 & -./komodod -pubkey=$pubkey -ac_name=MORTY -ac_supply=90000000000 -ac_reward=100000000 -ac_cc=3 -ac_staked=10 -addnode=95.217.44.58 -addnode=138.201.136.145 & -./komodod -pubkey=$pubkey -ac_name=VOTE2019 -ac_supply=123651638 -ac_public=1 -addnode=95.213.238.98 & -./komodod -pubkey=$pubkey -ac_name=KOIN -ac_supply=125000000 -addnode=3.0.32.10 & -./komodod -pubkey=$pubkey -ac_name=ZEXO -ac_supply=100000000 -ac_reward=1478310502 -ac_halving=525600 -ac_cc=42 -ac_ccenable=236 -ac_perc=77700 -ac_staked=93 -ac_pubkey=02713bd85e054db923694b6b7a85306264edf4d6bd6d331814f2b40af444b3ebbc -ac_public=1 -addnode=80.240.17.222 & -./komodod -pubkey=$pubkey -ac_name=K64 -ac_supply=64000777 -ac_reward=0 -ac_staked=10 -addnode=18.197.20.211 & -./komodod -pubkey=$pubkey -ac_name=HUSH3 -ac_sapling=1 -ac_reward=0,1125000000,562500000 -ac_halving=129,340000,840000 -ac_end=128,340000,5422111 -ac_eras=3 -ac_blocktime=150 -ac_cc=2 -ac_ccenable=228,234,235,236,241 -ac_founders=1 -ac_supply=6178674 -ac_perc=11111111 -clientname=GoldenSandtrout -addnode=188.165.212.101 -addnode=136.243.227.142 -addnode=5.9.224.250 -ac_cclib=hush3 -ac_script=76a9145eb10cf64f2bab1b457f1f25e658526155928fac88ac & -./komodod -pubkey=$pubkey -ac_name=THC -ac_supply=251253103 -ac_reward=360000000,300000000,240000000,180000000,150000000,90000000,0 -ac_staked=100 -ac_eras=7 -ac_end=500001,1000001,1500001,2000001,2500001,4500001,0 -ac_perc=233333333 -ac_cc=2 -ac_ccenable=229,236,240 -ac_script=2ea22c8020987fad30df055db6fd922c3a57e55d76601229ed3da3b31340112e773df3d0d28103120c008203000401ccb8 -ac_founders=150 -ac_cbmaturity=1 -ac_sapling=1 -addnode=157.230.45.184 -addnode=165.22.52.123 -earlytxid=7e4a76259e99c9379551389e9f757fc5f46c33ae922a8644dc2b187af2a6adc1 & +hsc="./hush-smart-chain" +ip="10.10.10.10" + +# this chain helps power HushDEX +$hsc -pubkey=$pubkey -ac_name=ZEX -ac_supply=100000000 -addnode=$ip $@ & + +# these are testcoins, like ARRR +$hsc -pubkey=$pubkey -ac_name=ZUSH -ac_supply=100000000 -addnode=$ip $@ & +$hsc -pubkey=$pubkey -ac_name=KOOLAID -ac_supply=100000000 -addnode=$ip $@ & From 25648197b6a89adb7b4e0c2d1daf72311aacadb6 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 21:46:16 -0400 Subject: [PATCH 19/31] Still amazes me jl777 hardcodes IP addresses in all his code to this day, lulz --- src/smartchains | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/smartchains b/src/smartchains index 529985f35..3a369677f 100755 --- a/src/smartchains +++ b/src/smartchains @@ -7,7 +7,7 @@ echo $pubkey echo "jl777 is a traitor to his village of cypherpunks, ca333 is his obedient servant" hsc="./hush-smart-chain" -ip="10.10.10.10" +ip=$(HUSHDEX_SEEDNODE) # this chain helps power HushDEX $hsc -pubkey=$pubkey -ac_name=ZEX -ac_supply=100000000 -addnode=$ip $@ & From f97412f5f025dfa074c16d9f8cddab543edf6a82 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 22:23:40 -0400 Subject: [PATCH 20/31] Hush Smart Chains updates --- src/assetchains | 20 -------------------- src/smartchains | 26 +++++++++++++++----------- src/smartchains.json | 6 ++---- src/smartchains.old | 17 +++++++++++++++++ 4 files changed, 34 insertions(+), 35 deletions(-) delete mode 100755 src/assetchains create mode 100755 src/smartchains.old diff --git a/src/assetchains b/src/assetchains deleted file mode 100755 index 0469fa728..000000000 --- a/src/assetchains +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash -set -eo pipefail - -# You can now add delay line to pubkey.txt file -source pubkey.txt -overide_args="$@" -seed_ip=`getent hosts zero.kolo.supernet.org | awk '{ print $1 }'` -komodo_binary='./komodod' - -if [ -z "$delay" ]; then delay=20; fi - -./listassetchainparams | while read args; do - gen="" - if [ $[RANDOM % 10] == 1 ]; then - gen=" -gen -genproclimit=1" - fi - - $komodo_binary $gen $args $overide_args -pubkey=$pubkey -addnode=$seed_ip & - sleep $delay -done diff --git a/src/smartchains b/src/smartchains index 3a369677f..5dd954c12 100755 --- a/src/smartchains +++ b/src/smartchains @@ -1,17 +1,21 @@ #!/bin/bash # Copyright (c) 2018-2020 The Hush developers -set -x -delay=60 +set -eo pipefail + +# You can now add delay line to pubkey.txt file source pubkey.txt -echo $pubkey -echo "jl777 is a traitor to his village of cypherpunks, ca333 is his obedient servant" +overide_args="$@" +seed_ip=$(SEEDNODE) +hsc='./hush-smart-chain' -hsc="./hush-smart-chain" -ip=$(HUSHDEX_SEEDNODE) +if [ -z "$delay" ]; then delay=20; fi -# this chain helps power HushDEX -$hsc -pubkey=$pubkey -ac_name=ZEX -ac_supply=100000000 -addnode=$ip $@ & +./listassetchainparams | while read args; do + gen="" + if [ $[RANDOM % 10] == 1 ]; then + gen=" -gen -genproclimit=1" + fi -# these are testcoins, like ARRR -$hsc -pubkey=$pubkey -ac_name=ZUSH -ac_supply=100000000 -addnode=$ip $@ & -$hsc -pubkey=$pubkey -ac_name=KOOLAID -ac_supply=100000000 -addnode=$ip $@ & + $hsc $gen $args $overide_args -pubkey=$pubkey -addnode=$seed_ip & + sleep $delay +done diff --git a/src/smartchains.json b/src/smartchains.json index c81d72c57..9e71fa4db 100644 --- a/src/smartchains.json +++ b/src/smartchains.json @@ -16,9 +16,7 @@ "ac_script": "76a9145eb10cf64f2bab1b457f1f25e658526155928fac88ac", "clientname": "GoldenSandtrout", "addnode": [ - "188.165.212.101", - "136.243.227.142", - "5.9.224.250" + "1.1.1.1" ] - }, + } ] diff --git a/src/smartchains.old b/src/smartchains.old new file mode 100755 index 000000000..3a369677f --- /dev/null +++ b/src/smartchains.old @@ -0,0 +1,17 @@ +#!/bin/bash +# Copyright (c) 2018-2020 The Hush developers +set -x +delay=60 +source pubkey.txt +echo $pubkey +echo "jl777 is a traitor to his village of cypherpunks, ca333 is his obedient servant" + +hsc="./hush-smart-chain" +ip=$(HUSHDEX_SEEDNODE) + +# this chain helps power HushDEX +$hsc -pubkey=$pubkey -ac_name=ZEX -ac_supply=100000000 -addnode=$ip $@ & + +# these are testcoins, like ARRR +$hsc -pubkey=$pubkey -ac_name=ZUSH -ac_supply=100000000 -addnode=$ip $@ & +$hsc -pubkey=$pubkey -ac_name=KOOLAID -ac_supply=100000000 -addnode=$ip $@ & From ef52325a449c10fa40b755abc9578b47e7828603 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 22:25:06 -0400 Subject: [PATCH 21/31] Remove this fucking Suduko GUI --- src/gui/komodoku/README.md | 27 --- src/gui/komodoku/Roboto-Light.ttf | Bin 140276 -> 0 bytes src/gui/komodoku/Sudoku.py | 362 ------------------------------ src/gui/komodoku/background.png | Bin 308479 -> 0 bytes src/gui/komodoku/board.png | Bin 5678 -> 0 bytes src/gui/komodoku/sudoku_kmdlib.py | 41 ---- 6 files changed, 430 deletions(-) delete mode 100644 src/gui/komodoku/README.md delete mode 100755 src/gui/komodoku/Roboto-Light.ttf delete mode 100644 src/gui/komodoku/Sudoku.py delete mode 100644 src/gui/komodoku/background.png delete mode 100644 src/gui/komodoku/board.png delete mode 100644 src/gui/komodoku/sudoku_kmdlib.py diff --git a/src/gui/komodoku/README.md b/src/gui/komodoku/README.md deleted file mode 100644 index 8a3778ea0..000000000 --- a/src/gui/komodoku/README.md +++ /dev/null @@ -1,27 +0,0 @@ -About ------ -Komodo SudokuCC GUI - -Just solve Sudoku and earn SUDOKU coins! - -![alt text](https://i.imgur.com/std99XW.png) - -To run you need up and running SUDOKU chain daemon built from latest https://github.com/jl777/komodo/tree/FSM and started with valid for your wallet pubkey in `-pubkey=` param. - -SUDOKU chain params: -```./komodod -ac_name=SUDOKU -ac_supply=1000000 -pubkey= -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 -``` diff --git a/src/gui/komodoku/Roboto-Light.ttf b/src/gui/komodoku/Roboto-Light.ttf deleted file mode 100755 index 664e1b2f9dbafbf6280305123d2df7fa0c66cee9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 140276 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 diff --git a/src/gui/komodoku/Sudoku.py b/src/gui/komodoku/Sudoku.py deleted file mode 100644 index 7b46d93fc..000000000 --- a/src/gui/komodoku/Sudoku.py +++ /dev/null @@ -1,362 +0,0 @@ -#!/usr/bin/env python - -# Copyright (C) 2010 Paul Bourke -# Copyright (C) 2019 Anton Lysakov -# -# 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 . - -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%22,%22%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() diff --git a/src/gui/komodoku/background.png b/src/gui/komodoku/background.png deleted file mode 100644 index dc4844a0bfb7b2e023fb5b008c3ad35565277f6c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 308479 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%0DIMW)1ob#@zUwv~hUnR6cWAd1 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

@^0LcoFZ<}_-7$K_YTr&=5cC(gJyQ+M#*Z1%m% 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�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

+tP3Z)2P z4TRd5Qo-hD^7E?_j)lzHbmprDgPaq`1U{#JwcJg$@fq3MiI8&XpT%i345<4^waVP0 z5MmE)ZjHKovyNZT5iXIkHsi)FrjmAnkOX(y3VJ@Y(LYBBOzvIRmAOWZNq=gvsVIY! z`7!@&&qPf%2^AF*IS!pYQ26nFhD5zVzVRZ}d7s-V~r$(3>!xQ3){Wy5N$z`t3 zfC=G{a9EngbvoKq9*TC^_L3d$;bDqR;!!#O`MPe%`9uuyLq4A>Fj>_$^Hi>c=MJ@- zi(QKWy?C1S&XYm_O-H5U@LiVpBKF{sVZrTof9Wdi!B?c1(MwL_OLTAaTrtydT*V|- zIuE(@`Z{P#eAgOTk3|^>sLG;k3N3U@54m<(dE7xzv2VL2$NdN zT0&UfUP`BgBhyR9pzoyf+(+mHE*9gm;5hb9$nPrciWfuQo_S~@n_AWt))&%Vm~3Y z33V^GYh9najbpKqMAm|3GUZkzKE!Fib@Zk-Q5@$!%}_Jw-bAH}`j7t^Zhzs=p`zjO zcn6$A46B5+v!^4AVXUHE{3II$c#z490syu3LP*zkZKbPqy(46?*ioM6hZqkow_2iZva5@q?(n z(8-yhPoQ?WY3XqO2r4EFM1>cfC=1cBt(&+(2lJA%AZ-gTBtaf{kqtA$D$j#@Hw`RH zkmqCx!^3r+3HZ!W7+pr~C}Vf)CD;9mtd)bc@@EKEy3JN6JmOkopER&cRlj7F*e5675jelqHgJVd)J~&q7zca zah%wCLEBJE#J{OL7jA@>fTMiY)3HVUMGVY7#D%bw)8d9Rg$QI@^Uc#Dg5~*zYOxL?xDrFaPcTjPL&4e*> zKIg(vk0bPPt%{LGG*_L*!0Lmjo_9T-xp5ufFbbi;t@bD>v6aKc4-TU2wZ)Mg!;&a- zn@M-bsG{C;AZjv=VFhC@r8lmF#J?CGba@f4*#b}Phq4Ka*ElRikF9NvQ=G@|jhLYNFDfrv}`%f(;Rs%fVpQ1o0s0CQo6+{i6Kdtao;3y(z!k!M? zZ!5mNAKe5jdWYNFg5!B01lOIGi7K{0D1|p;@Bn!xuzvme#C=-;VkJsz8MSdypaG(_ z6|8H-moE>jYmm!{M~>^}P)ft?9Dn^;%M+I9*+|Q!kG%bUn9tCVFPUUi2cEc zz!se-5i)j>e4=IC-&Q8jfmkR|B|uX;cJ4F?x7#8dCoX1P@IWo7%?VG644`M}~Gf^a=j;cpQG zNycCWiHo&!!2A1w+wGGa{slx4HJ^xH_%5a5%n2d#v*!)5AlHQ4n8O!6a2z|m;yZyd{0WenAHG}8hC3cPCo1w79zuDuPYCmK9lSaBQ` zC_FN?NRIan`*C26Zyd$sz(te5IwcpR^T8Vx+(_s%YZaj2kj^R!umkH7WK=4MP+>Il zICiX}H1f`M&R`Xu8Cpg<4=gJaKZA=nj$NXFhIbi@Ci%bUpJvtF+Oq*_6h;2m>Qd?f5i5aJlvt0!f+=n$y_H6u5m!eJFfWGNLfa1p2p55e<( z;E_sz_ka%(=a~Uy1USGiIC8?uXl`uvn>gU{G1SI!sf?* zY6#9Dm4x63A$shBL=h2|z=d#28KnWvN1#=B2c(>OuIX_cxZUo^>4XEY1c!CKq2!8Z zdWzbNX(Rh_;I=M;nsYPkokM9FE#!?|z)*a$`jws9O96t5tZ+m@sg83!%gHt{KBDEq znW-o^_JrUUEMjX=NogexF$Cn45#j<*4M%!{DB`wlNGBH(&NEp&XXZ^7A#^ua!McV4 z4DiHdm64-Ik1SL*s_^fspjF-x&hvnCk%eTWd7=ECVk-E9|N8IX*Z<0IqunEFuBeTR zd>^9FO-gU(s82kKLG5ZU3`*95BA}Gid9;HsRfZ2;Iw#Z;sG!gQK|HlFsfGDqTF5Xz ziv?`nJ1jBsS`_|bk`xtg+T`;&2Nyif<3wE8C7%o66*(oKIjq}_3p;s+5Jj`2;Yja= zC#;1Phf4=M&jZUE@ykE_Lwx_;cL+|Dp~BHCrEn^UoC7)mNsk?km~+ipwgIO;+fw8` zc~DKPwiadUx_X>R?Qa_BAOG>$YHgAe#Rq&`J)Tbq$P6BYhWio(ogsvX&Oqw2N;Cnc zOjlBv7`>lGLMpk)N;%7c!aqBPfF#IFl@6xJLFZi*#EL6I9~k|5JfFDVH<06lwIqO? z#}ar`m&&TOuy~MJ1hr^xpTlt!QQr|tVUCs$?2S`P!LkH~j^!CZD()q+icWKfY8xZa zocS`3apCBRGf77&yaGTZ{S9Z9Jiy@kf{Q`qwV69Qat-@QaGrSM%Y5Ba5U1f$q3dRH z#D$v@QnM(vVu%10l*W$f>13(jLj8ZnryX&DgdT$McCJ6_ASnD&B4jp8JWMGQR)*&L^nE;j~5~ zl;G#F1?F?95;8jWSxINYvPGm)ahw@`;e(S&!40J(tdWb-k~5YV_~*8a+kM63{ek6n z!~RT26>xDu%D|oyoOigz75U7FOT@Rw6L2eHXegO4Hf~Jbal5a$ts8#&>49b0uq+O_ zGG}2wPQ2Z32){n}r zr+_bC{sh1Fr+;82+%sWaJ>Xf17Q+fq1~rF2{F9&X`TOs&c#myyIG+z}w-xC;k!ykv z0b69T#QRf6F`h4*%GL?W0Sb<-LA>+b!|c=jj&I+-Nzwv$+V9^EeE0nw=lQ_r&)?(m zIAjEo`HYf4Xh%j|(D@W1$7e)@DnYlVxUC4$H! z213ahwN!+~BY0v}^q#s}tkjI#5;@*Wc*2Zw@jU_uiOOoyEDZxs=Ll!v#+RJO^U3cw z5CQeX5o>MOY(h)3~GqZ?{!Q z>kh}ksB=yUAu5H%!}-t=-BS2Ib`m`AJr_$wCnn^3bQ#|-369XGIywzmqNwMD+Z*Eo zij1fS;ouQDpj$GO&TFh1kJgw#@BJ0Qm$U(JT+u-CD;fo!Udag2JI@8Am}ysy!;(U~ zfj^ITgocQeSO`$%F6H8Gq>pUtCIXjXPM%W1e!TM;93pDryECj&6xE)U{Ux&#gC|Y{ zc|5-~Fa9JsSMi-7cprt#mHT4%&SP0OPKz!X-fIRP!zdO z2{>I`%#Rw%8io!l5=(rY*!rV_ig2k65v>uo`0DPB+R%hVUb9HWQQ0maad0(3yo0=M zV>U@6aNd`rV2sc*oMTlM3DK4Frfz~XLA*c!mx@UW57^HgF>VNvP5GXWcODDCcP<3; z#X1#*M~5=HXvDmlp=KzEiPU zI9at57zOyYe+8&v^|2EwT?^cKO9#7d8}eEB9TFkehBG%TkxA~YR=hvnal3D587S3t zc{QP+5w9fzcLs5ZvY2&9J0j5v>z(K;EqrkrrwHZce#_!!YZ2(5K9L^iDr*v|t{ zFE!cNj?n$6h#Xv4fGlCAf*Sfrs4~85s4QpCKst+bSb0*Ia_mS$hyfuumRhqgn|Xev zzy+W*CM}1+UD>*Rk}(4l?Q`Bik|W74n1)Kz3&JSxzKY0UT{fgsvcDp59FK19+A16W zmByEflUSe_JdWo(7uLe_+HMw^7w;_hRsks8=B}>!e@qF)1 zqHojP{Cqr-(1g!KNC!Wk=%YM)=I2psNG;>- z?Nc|pRO-OnjYm#Lsvx((N5XOLA`Ias^UOfWt#cGhDaZv_)}`|ROU_v1#xf@zhl8-6 zYzxD843Cb#J$Br-1&%Uq%Zlf7$L;MVS*QgiHylSs3_Mn3jL75hJaF40yd!-5`VBw) z@B`{G?u7|45K?9;8B18?`wufqhtdh{`dP?u z*t%hxkm{k3Xep@hjG%}$NG%oQBzZiE+p`ZKKe7qCy+&pAoAR@q_keHH%zO|s#RN1i za74%zK*^J1d2tQrejs`#z85eb%aa3n8DpVgi+4W!s&cYC_O$ajNO(UngwCx?iTOS; zu5ckR=cP3y8G$$g78j9>-2h9*)!Yx=`I|Wv4di83FXEdZMVs1k?B|JXy9t@Mff}PO zAo*eBuy|HfLeSfk65sRF;DT_|S|`SXSP@rhLGXMaZ+9MlW>Fu77=V)DT$ID?E|7lc=p>;bmlLhKsIn~q zt5gY(C$Etz=5ozf=CXA%ZG#JA&veOl;~?!)@(`Ug38`&ERS6V9!Z{$BCH@g9KY_;M zpBM>89)_r1){&#Zne6I163$pDjL`W2UvrNh>Kr?9J%^~C_-C_%n8~-ij@NDLBzEN{ z5;z#$dB>kM6?iXZpRIMp>ly+VYcf*Gh52)>Hjq#X6zOiVY0mRR@RCdC9I|k>Vjwu- zCR){FmN+x!Kvpz(tig+y8JiE+#>(813rCA+sCC#_^wfBS+!|2Y(ZiUte8(aUKx?&! z78k#w=EVE47U2-fSd!Fg#e;;zU1~!JtB9JC7+Z5;TpFW&Aw*V|*NW0ObXk)E^sx0_ zavVzqkxX{-3DDpWI`2?r&q0J;?7djwiI9(z(HtUB^gJGy0?P-7B^UhD|K{)DU-&Ek z4o(n!tEe8#u_IQt9=Y_?OvZ(ck*pZlV3#LY4bc-vuMwMEI|(cY2&FMdbDRl_ACYQ$7B)E>b56pu zbvScI7GZ@GAAwBFc}zz_u9?pzzi{K`9q8B}jcpm45Lf|#`3DT&d64&LNT|s0Alcxf zC~$JvK!TH{R^HKi)zsYzQ{+bi|iOSFojBWVY-x zlyiZPTzI4`WOwHfV2UO}M+&((ROMiktf)GZ`0_CsuzAl&VJ;#tFeZXJAJ2#Ub3%Gl zQgKd&)pF{mWK@XVl(W=Pv=Q?}vhWi8!iI*eBsdpwX0H5W2tuT0D+*6RRH#mTSpekB zMKc;a5n5qHaepSP+f8f{7@hK6(l0L5xdDzs8cG&ZCqnKAgHA9XL^t@iJ#4hMLefM;1iE(#^e1PZlAt`a|=@k zoGN@gYTd;wRSoTi(4y6Xih^aiBjt=zPqsZl=!XF}0EAMQNPZj#Z|a`)HO8#`dvqK< z{J*?kC+{dGIG>2(2}aHXp5MO>w=IRqur6}3(G>l2M&ahY+)2Z4CiihRxLJ|FSrA`b zAmH40+_oFmb-|GfQehjAl;!d`P9x!0{U`O1Z#4F^Tb8Y_YYomu&2S;Wlf!W)DYm$< z@WCO;2q^dkpp4)b`Cb{dx?y`lY(T22!gTIE06pi-F6v^N5xhqR5MtobzbJA!tFCnN zEPp=cRgohxYj!-fp9GyaKDECt0y-8Kh z=~|KU!6fxcaB_}&gf5X+3J4Q@8%j!uA>jV$J2Xjl;Pcyy&?p(viZrfqSTdj)%Mg?< zhvzepy|J8fpAw%PoQxng84?%7zpwJ;7^S&(+@v4*WJFTzb6WMHwvDJ_uhJxni;Mr- zEdmCoNfe)Aqf?TGlmqL!^s#8JsgD+;0273Unll^%vY_KGcz98tLntTVsQCZ>tKY}J z_@DeX+NTXDY|Oj}d0NvnilCDkXS1xUoP`BBAMB*=S2n;U-zO9~F^7-oAgQmVbQ}nt zI)PsE14&5joUp*nQP?)Ia6sq&b`_gabV`Xn$poHZhai7ih23S!^J;~dq2~XQsH_4 zwe>xTGr{>F%Ho8Q6Ds&l&85Qs_22z3f7Bn^m3_$UH$`$dx`tLW&i&}oDLlrKJRZj! zr|3Pr1JF37nip~F;g*6+@s}fKj4d_Su1crcq{|xJfS0)~(1d(Vo%=MhjktK~YQ1VD z+Mdw@?>Y%COa9#R`Q*b-kO%e2a^6W~1Z2~oyW%oDQfL1VK@+OXhaEAR=348cJVon> zAE2hNaaGTo(QYk`l_j-_i!Gy4OJJkL znhT?MjeiDnbPCqU2SEs2G^19;u!u7{U!YMCD0Rn;J|OLh5BO5y8sHieRL}iHbP=tv zi6>R=MApDWT>|jw{>Ir>=ZQduBZP+iVD;U)t~e8ObsUKqX({j^JidOz8W#j2R=%_b z@_fN?#Lmfuvnb=7_rp`h6tZffxW zn;?B8RtmLb#3isntg6@=j2(;RYE}+H-&nz1avGU|@;;X(iaBLPh(Q`+Af*Ehg};ZV z9_>PoN$90!0D{&_ks1OM@ZS}I@SwN-$)NeMBa zw1QkR!m>=s0O-jG)M*o03d>p>eDsp|Q3WMxy`f~qaT-<#pq~2~oJY+Ci!{j0>E!3Z zD%IMZ+OL7c(KGKA)WpGjsMhvlXFjTUE(UY{E|OjnJ>O*{f~4TQ_#-+LSzjri?7^5b z@<041xc%mz#m?63tb`Pf(Xa&xo#xOQ+e^e{czBJtD`y(BI!1)V_t6?7N|po-v3&_~ z!Jd>-5W3}0jEhW45|+Sckb_2{HJK0*q9=Gy$R|&5I5EM4TH|{W5RXJgFN5R%uT^fq z6?Jl`NaqutfEYv}E}jE;L)Xn!xAFjgMdu7STGjkyF@uR zYUWX|Bgb_N8nzhaP9wNR2%aRTaYUB|34iv^f%g5;Y*?$Z^s9_`hNG=W##>|liE+qP zdHRrNl5rWXT`q6Eh3dt^>GZMtkaje~nMF-^&M&GoKvbExDQ+sbft&^}SEtXo9+^oLt|t zHRrV1YgQ(I4agn;Ie*WwZblHRB7sV*rOVp2W{|Al877UO+M6u9udK1)@KBollr;Q! zWMXQBMVib2?O5FU`CRk;_zbBpmK^E`-M#6YLkzxWW=_6N#^llNTYIipM{G6Pz3!8% z*{$^?y5^lu=Aq_Y^*tkoo2}9mhFnX93tXh;RJz&pHP0^R%;u3qSj3Ja#>mCISwG%O z%#2BIAVH*h79*LET+MwmMy=Cc@V@_DYf5Z=th%3(`WTvLYh!b+-bdQV*HRIeIJtXw zvNg3STCJyFEDIug)3C>2Kexd}J3JO1ao~JD5!OW-JlAb;T5E8R9e?z<{wMs}fACw_ zy~i3oa;xxgQ#NIfK@!h0wH2^#>f>Hm73I^|?ujdk@I z*@Omb`=cZ4Da+G)ZrZIAo))t)PDaMP0rei_BXUZe`l41ccAwZiiEea*>3q|l8KUds zO8ql?e@}+%#)Gc4#-m%ae*vJ1|76Y?{%`)xAAjt>s9W_@R|=@pX%z+BA~RWgK-tjB zZng#sA+ZmJenFiVTPNWj%!oOwuc69ft}^D5#BIjUJKEE_sp%*j^wl^M)_XNFV~D>^ z@f2PV4gKFCvRcgRy!eu|tq)yI_^h|aaF13K&f2?0dx7dRP*Xd5FzJG^Q3UN`zSh&o zO@Y)sLG;g5f-1%5h@2P&qW<}LCai1h8E^JGkFZzQV`*&xIU}CWy`wfZ zm+~6B;RsXlrjF>tXD3XB!R*>T7qB)w)E*YfNzkIu{ftw2treRXvf9{=Q!f1}2=`(N zeD#947UF7uVWW!X!fP0k5>d~Mv++1rA03-B7lQAeK`QdlV#PK=_LA0YLmO|ht}BmU zjIY>vvh%$y2Cw1s*1&f-IuFFanikqaTn$Avw(A-vc8yZe%g9DAS#w0&Tv$IR>%gv` zNB54+OP$v`8Jmmo9QE&MiosNPwZ@9WBS};ZK+Xtn$03}5DGwt1W{GTV6SJ5aOI>+i8^T!jlZ*2$iwHZXZyqP2%6t3V+5(7Al<$(4JN zVZj9_>bp_IjXgvnN+`K7XRKBx^S2_Y4(g*-ft2y(AN)gn{>?v+>Hh&ePXS=YEs#jdV_Wm&q1o|-?~eQFJXnSLeABHT2IYGS+L>kn&M_H-_SsKRTF1t6*n)8U?>go4c`qXs))33MruD#W zaw^*&UAr!9Rl|@JHrH60=kw7owf#)2x(ku#(EyKijN3YTJSIR=zy|3a=k9QzmABii zZ!qg}-4O@5eAP5hzw_1My7MW_MW>gzeUAMSluK#5ZSZ0oYol^l9=}W%Ue7qZpr2RN z)}jyg{q^q0cx%}LZm6zuZwTxj(!#Syc)F(0KOT>PQ1t`&^#ZitUoQ$9@uP*1t^+L$ zbj_ASSw<(i>*&1kgfoxX?R+TRQ!KGubu45XC080K0q z52I#p6w`v9l7x6W-;Gss9$BCx?{s|E{<#P*S&5|#4wDv!aR~#dlNb_PwCi`%bI_iX z-n*#?(}MH`?esiS3MK>edj4L~KRu(p=O(|D+m2{0>pnUutO^I zoFNKRQiEmw4*58+|D!*^r@!#$P`yXX%pL5i@ej^RzQ@XR|7bj#MNLH~kGL#7*2@;n z>$)PP#Qtp}x*$Cl|8m;Hmx~}tiW?auL5^S>#$)M9(DB1I~wi!8pnR*G; zqZdI+xtV~K(9L=^BU0DWb#gRvYTJ}=TuMPJe81XrBo`K4)mq_y_jmvLj}{i^4>U+~ zT6Dw-#;2EYn08vF)XTwuDgWy_LbHd8>l@c~(yIMAod~RfkZ3Q5o?7eMkq6mM-8d6l zepavaG2$_72Vmi6{Vw*!TLLgprBXi3=XV_*w|RBiNm?Yzb{#fy#C{$-x*Xj@=!>?Q zg`x^dcNsY;A$R0#<>~iod`pb6L++2q!(2eE7ifyAsQdgWNZeEaNP%)5hoGVrki%9F z0J~xKeeaivjjOS-3)i>?+lhHGgG(v*=cV7((a4pvpK+iog{8oOWb?x;CAJZ^Rd0%GjTyqhxVdyr6-X2U^ z5OHx8`}5N^t_M(+2E~Tya-rP1TecP?HXe!jowbW-6yerF-FB+B=uq_6HdW*7@n)nw z{{JAPdfRY~P~vny+-FmTRzk?Pm_I%OxGVKNV z-FlYTrX?uX%zRE;Fs7V(P`yQdfZ83wS!6Rurs(LUnOwSoO0zh~Uc{QxpcnD7u$4xS zkHHvK>6xa5j%}=T4Ik$*H8;I6G<%)>x)u`|n?X(4 zZYdk|TMOzoAvD)UwF(#6(`#<09k-G2AZ=l(>oKJ?O(yK#Y8NWQvabDi=qi#>H6q^hfFKRq_09W>iiu3+F$#tKia~H z9gV#xDMq)YDjb_GZY#Svh3h*Ncli4AN%&Y= zNIWG2jI@#!I1;9dv=;%ZB~Ce@+r%r=2fY}`(T=pnGZ}mhySa2Tase8;A>5QQPLMI1 z;UzVV7D`iKEUy zXMdk$csCHP7ZZJ%TTtXyD`sXt6hu6Ftr7&P{wKMxdd-XDK8qd*XFes$#=(Wq$4Pd4 zpa;l6CdcO0ZmN`mGbfO9l2*V)3y*-gyW=q`k2SPY*3Yh&8;>L%_(8EDl@mJ z>`)*{SgEcv9R*8%S8HqmpyPnSNr9v!X#U{f3HIVrOeUK)9K@>8Wnme=u9=j0l&fn? zVRt(!xA7A;z?BRB(u*n$K4qjfgIvX#4iRUYjpS8{Dd>+88qsn-9kz>#j=l7xnQX7i;3IN5S(qT6 zZ!A{h_o{^}!S%SQ&XF;wgylJ%>FA9O8vAeE?%RlVQTj)dxEQ#JKck=7(hM|*l*FKQ zT~?IB>!sw1C9ZvRr(?&FzsM;drItRH)TXyLA&nCW7`YQ=8?m2Wmd0X?5NA%8-k&-h z;Iqv{hkGV{69~`e4yqhUS2CMkuG`97R`1Z7Lny$PfAEj+`8WS8TnIQG4>VDomR50` ztfXDHjm1&5;y8}6Czr^L8bnaAENl^@qq{1jyUa$@S^(*HR5Xy}>{}w!eu9i1Ls+mZ z(eP;-S}Rk4xm}mGfwSo9JUMfn;^QT(xd=Dg1Fdvu@K%g))S?a%?X5z`z#X1irMx;M${}X?E+IuaPlDN zf@EDeHo7R-Ww>_4L`mwF3t%s}EAidJpO*Kb&bNcp;a*08I>)!fc73MDu}`7MEb&h8 zVd<{lJ^rMr#CeeP^zWo}^a8+!p;|tUKBN8lM04RKz|?m0i(LHKj0WrmvgA^GdF$GG zKA+u)REhIMz4VVZ>rD9!H?B^i? z-+m%B+iq89@FDu1i>AD>D!F}EC||$xYxdwk$YKybDHA~48hW&k76f_#*k@o5G+mdr zAsI!&tH7X(G7P!ec5Qag+mKT&{6mNmI!xVrt5xa;nWA5IRH}!Qb96b-26_D>)O@Vr zG&LP|57~Y0okv0K{GV>ka9lpI7DT zwW}u@9k=DiS#i;oOE(Z#KM~!TuQN~>Eey`I_kGzzyfKKtebk3y?g|-m_si0ci_4+s zb`o(B*N`XTHKRB*2}kUx=Srv_9G4`9yKO>hA@Mf4cCSd46joy`b3|In z6}6`BQ8+Ry%XE(Q##lI?DlXz?HK~g+7r43N+;>pqMzOSl+JsA33GR8~{rCSq?tkfD z1H}anKnZSAE~;p%=2;K}qT%;v0^DbGm%7^6Hdf2Bh!Syu|4%kyHhi4xjniRdM@`m{^Z9&s z6TofTdS}v%M7CZEkSm`>4Z4S)Xl62|>b*?MTA%#*UxeshvdVB>C&^8zHWAX)_N)Mfe1l7VwbOL$hD43_I>ZqTA#Na6Y09L zO0}ur@NOEN=z7%AtiI<>9P{-ev^*<4NNjj4Nzga@&CrDW*%6Gr^sk&W%Z<}Nv-{JI z#8jyojUeNyqEaMQpL;*gIFu2~vfwy&JfF|Wr%Ctgx~~0@PKno^j`OTKwj1*b`InKb zv0wQ29MgBO&5b=X^qF)LxLJpaUY+O34(Ni?>F?6tVGFy~I7&v>fv!J2s~53K(DAV4 zb2;a*?|Uy6?bt`xlD;cF)B5)&*Aa2sRM|ZnLg??$5~=lG(0C{<8oi_u*ydv9&CP4c zj=mw*9(JsL4YgLJmt$bc%P9HE4<1G1_&q#WDg9n!?=rRvNF}4`Bt`^6!84*2BKs+> z>xvK=wed0FDf_ZFy!$@ATZICLq zr%^!V+=I#EMd@urn6oL~?Pm=kbaB}=a9j6--W|IBNeJ+zvbBmf>6&bCJ%23#U`Ln} z8YxpEJ1tX0-OHp;?*x73wrQou<6E=RRqq^Xo#mHg_)dB`+5^1`aa|2Y?Lt?HJXedB z1WR4nh7140Zq#ktCiyobTBD=YjlPMZz$zM4&FI8?0|1VcX7!iMb!%&UVSA5YlzUej z1v?V83J1GD?LT9?2m5oB#H)NSOPbWf^GaNurK3(bUSbgt7X;UO+)DTAaba3aT8Z;! z8KiB7JZG}z6%i?gGYIv&?)%=!%Kb2v&wUz&m^}b&H)BbsdH@_UCVV^|xZm$)V-1AE zB3||x>8MICal2_O0s#qCEh@*Z+@*RkuPjxvvB0QDmdj4Z#QL*~Nqw)ah5_<+$m%%#PY^mwQD-uKQ+LmZ|U{e?d^t#3WTw zo+t-sn=VmX?Ag6-3BC5YUlmu^ccMHjI||bgsGe(D6fR4Ak;Y#+K(<4l$+>f5%m@&@ zpn#)OAIREuYLO%=MK8x*WJ^=5F=wnyZdkWlkF2?>P3<_-76tZaTl);V)=Cvssh9v; zic7=A2I8VR9R<1*UtcnXV(Ci1K5DHJF(w{|mJ@fi=>XUgr=FQJeBF#V1xc8wwV~!B z_f8cBVBiQH@8MiTc%1m<-})c%-CzETXv>0jW*m*PEN#IULqI;$q#*Snu<5s~I~}Rp zW=j9A15L%SMK}E6Z(e-N2 zAQpf%| zpX?)MP*mNMN3O%{_ZL6@-j7x~?!3nm!wV5o=a07Pvx{4is9>xB#$_@(E(>ofIoKX# zSF+(1F1MRq6=X`Zv|JZU8upgNOCz>t1j3*nChp=3GzyURLUf#zBZdrZW!x6Yx{?F+ z8S!FnlLdtR9Tv_UgykZnQ_g2BEsJj%yO?Xfmnx|21a zE)(bkKUG9E7x(kTH<$8%*WtVpI z+F=Y8S?X&+otw3Q3qp$ZDuI`xH^$gKSL`8vo}A&htV_Q@RZ?81=pkHGc9@8l_VRVk zi@B}5QwbVxrqQu}J{IP-JPKPB=^?9Vh@#W>lC|ruHy6gS*V+Q;;iJ|fyhaL+WA9@# z{hgLD`u6rV@jERU_=+xT=I52yXo~{t8)iS>hvPHMhx)M}aPXZ+p**PWFLd#Nv&fR# zh}ivXxfpteX@P5tLPZ8G-^CV^R#;>Ay)8JbNI_Mu_VQ8=n!WI2<$T>i`2cTb$BSBtof+vV^ar9+IsQ z&aV%&|M!=;{VTtLEKQ0F0gEWFJJOaoH9+^;5~HZbF;Ow}+!^C|xlfI{vb(6evBr{E zK-9uTqZXwxuH2~0S;zt(KdGW^V{X@y<+EBpN;_fc^c&1VAH5^=uI)-%A3KPn#j;wa z1iy5Y-_jDUg}DA}S(a|TI|{jglul#$(U8uwD@N_~B$q1aWrgdu^yaY7B_r1|Eh0M) zx6uA|25!fMdMORG%L@|WJABHd$F;oE$ zLQNH}c~BuFPNqdA;LN#8rBw|&xE!WBKnrwS^@ks+o3 z8Oz>7AFJ_*CL@;uIG~_1(X`dBcCj$_D0H;bhCxz;aBv2}TE_vZda-hUh4X`3;95X% zKr1H#{A8MG4`?O(YsP3w8Ku;IVZ^u~t_yB&ceubV$7eoK8b@_J_6Ks!D6RBDm%Bvv z`?}xna@JJr`-yeE;YbHkNq8PlG>s(?0(&YMab5VCRd6(t^C-2UN?^L~14X=_$KC}2 zD#{oK)UCCKPoF+b=bp6`(EqKYeQTwl|9jt=l&o}d;}UY>?-toW zR4(rK_jfb$Uqr4?;$Tl8H;W=hQ!5cwiX6E%sarXefz^hs67IK8y-6M(cDajqS_QUc z<)%;aEfq;o`w(5fF~+`zSjEmnbLR;aOrQoy%u}7m>56#kJ6M;Eb444+iM7f(d+97a z1%uHJ|3Y!#gbeuBGP-r)Mcxt^_w;ENa& zQ_2IMQ3bVTJohJjYk1}pr8%GgA#P{|I1i3*((jgY#q&sTVL@0{9GPS2w0XA{JGLPz zrQkSE_GI!7E(U~UVF&)AcLES7Ah>|Itdi}@=-+Yd$hmUtP$RVFQ7iMyVq7L;XzP<1 zWt^|~o1O0HpV{-)HGrz5qkypWHQk1#RPY^rJ@ym(^8^}4Sb4WhK9YLZ@B5C-*>@i{ zKU%~NKBFc`FyD+vlL?go7Xz9jR08&N0w}|U;5eSmR&iBAGr7thJPQpf)q}#yV67|a z)q_a8aYc=aF<-mNjdNx)yn0tO$)VF*RpHj?JuA-){B9-Bid$b`*i;&o&QKhtsR`d~UMek6qV+s9x-@bhVInErjYF1W3jWrS_dO}SqZLw!N zxvO82B_yk1V~6pbJUR<960kkqW=NW-%+q5*EV_Z zT*u<}kkoh6(OEY<#B{w~xi2Kylvfmcd~Y|9oShW>Omg=NoD<2Ea0w)4V`Nv!#&pV-M>{QIQ4?>>QH{eZLkJ|Mcn8 zgyNN&%+x^ls1wC1pRa6OIwk^E{c7F*?RT|&#Ewye**d~a>)U=l+qhVS%LYde`&1FAL7CB9I|<&G9XEETcY2S9f=7oH=)3Zc^IVk%YqBt;3AN#=b-D zDNV*<_Rt%%cuO`MqmN=X_($GcS9j|xS=KHP{f@Q((t|@^v~~;k`+eH@77U8W5=r1zLelcko<=d+x#k7UahTEE?HePqH&*AO6BNZpdRRUD$o%XNJ* ze}ezJ?JljCmMWy2OH2~29CXZt(b>Gw`XNo66%!v)O2OOP8+-_&4qbZDWaFlKciCo7 z9`8N2ZJR^@j7|@yZ_BHgUE5Cya&G33%m~4~7RpN zv@E^Bj@7SRL|tQ7HD~Q3Y=^hEH*x)@VO*R!_mlhro_smU>2%2Xgrnh&XD_T?&`U}N z33|x?jPMfsXXJgmZMU9G(EWmpicP)pEb6D9UC|~x<+$JP6L(D4{JL&k-McOu7c!0C z)p;hATqin)ZGLT|cjd)>6eXmMiT;^#1l1EssRP&e6wU=?TaQ|*F=B3=pJ_?+t+IVb z60WmVZStj`I}M|~?|A$_{}kK5{2Lu`u#JLsH`m5Oi{T_7hMN1@6qBo=uti59`Lu-D z4yd&TAAI+z%qh=&X$2r8O3#`uU(us6K?twrpyp1$o?%LkXHPdTLVzsAFJ~o|T&BIK z4R}Y&%(DyLgQN&_;Cf+rz!6Hzoxnc!DovD)Wm!4sJ*8QUx&T#**b7rJs%uJIRFFAr6b)n%N zU1`VXJOP&ojG6m$c20vX2>mYB0a(YnIVEI?7GTe;j2O1=6J^l|EiP?`sFHE#NQ|Q@ zL-7WU(Q$!QBz~kEyYgcO55rGnaXVkP*^P0H-8`~)hK6^i!2Q`Ao(a9*FOAEtIxrt!NqVpavd<*?t@9*zY$TKo>f4ld0 z5o6?WD(d7y-&#Y>94%yxLu<NrYhO684O;$hqZ@ScERdI4Qoa z@gT1P7MhSo+mI=;Nff$`jRx66&?*uEN?aC1Pd%N$s+kp~=|7t)N;X-it|Ith>X_!mKabL)@bKa1tCCJ!jcV5_|^aL z_wd7i_-}P@yesl(sXKPE$cQccF^%XgD#Rq@(p zlkeYG^J05;S}Pz0D)daU&9=1?>1#+ppW)-Eb|1y0snClG*{&Hm?)hCeOvNXoy?I(Y z+=#R(f{wX-WkLxp=lVDj{4aj-dp}xOt(lk^M?->Zc|$gW!4lmqbZ*J0*8pQJu57rd z77O|kS%&L+LiMBqld3|0cQK1jU%1Un)51%uZF{(0FEoo@DTJ-_SW7mwnSoay4YkR) zCWKxAgXftw^{*LfjWnC zaxQx72xhG^V(?x}_yme3_Y&Z3M~$-y?KKu;pl!AbwQjtMw%C7Zk!h8n`niWOZh0Ye zeiYQJ?^h+aHUmw6*OiZ^NJBSz6uW~}6t5k*kRtOszUWZ698lNd)Q-kx)7!aWm=25X zSl%YIN8gE#xa^ogm0yF8!-2cO6Iwe#E}}I?I*S=$+SnXh80dJ?lKEM#{r|J|ZauSY z+f`T_w>hi6wf8o*z(}A-j!>ikA>@Tb0mM@t!+%K>kfX#A2mVg}20Y{`4=5Li6cby< z#`f_(XYch@)tuv&hu-@bZOmHd<(#wD`s%BiH7>ok-Y#n2KzV^BPgSNp`&!H5gl|RM zwrvAl{Qmpzk+lf2B4OWlHLb+byfIQfef6eE=NRq5FZp;$x@IB4#=2L<`Tc$$(NL^9 z<4Xs9?L3INX-IJjn2H)710%|& zwTA6>LnS&9Hxqo0?zbBplkTa3zS@I)%S*8X$oU)%C*Tl#R21nwyHe2pwV5${rrtZE zkBczNaya?y*!LY(O@N`+KF`+^-pzdg9hVvfsPYyRWGJitIDcpI5g}5mx42AGzkwBRfzJgN)-}u?RrV6Lw2R{ z9y_%2VrSmPDqZg5g5#Vy3njM2Vh1}berl}?()9J~S8Urp4sk=buK8ON6^O$D+c<3< z(izs)m7t5^mf!7jmnw#FdZC+}dOqt=k2vqqszVR5;BsjwwV^wQ+JNKCs7)l-xrhhN z^C>E>2lH_p4*tqHll4b_VVFpFPB)OL)tG97wp4zRlNy! zr4EjWchjYK5WUGi>pBi9rQoKa=c90QiokTa=qD-~7T8)El^Ne;M00LLc-`3HX{NHK zN;1e=iqSwZ5rGcf8DU|Wb9Q-{7uXV=q_z^T^NA2W&RoZ3dgTI|+~4?y=UFuT_l~0D z5^+n%BIe-3lRssAEuz$l=Sw10YOg9#Se1{hcCji65nV~TLyqmC!VJF{ z&kjVONz?XmzYm)ki@Um_*DP*fV^JN&v1{sG52X>|y3^!}z zr<{kL*-@L?HjwZTg(Fn*ftbvXY%2DWCK=e-dv#EsyhMx!?EZ0+fZezXt5|J&%|YbC z*$R68bM|*M4wZ$rr!6VRw~2Bu_;CgV?}t50t&{%2(Pb${R2>zH^Zy5YjOYk(0mwgp zqW=3I;eO|@YGW=6?GV%OVPjzuQyH9J^D|kL#)?w!JOTo?v>}BcYd}Rzawa)VlyC@E z?6)rHRI_ARiwJW#kJtFUSJPkqZ>H^VL&|l?H2|H9-ryYWx0@KOda+fi`dx@;Sw}7> zj`M|%rapP10<|;GywGg?d;QKk+FO{t_YUQ(!)J2e(y$@uBeqW+6bxm2y&jz(Tybhuzy#6AR(F6zA9P@{P;#YL^e$kafiXx42o9z(oC-KW!#^E`2!Cw}-k~3J(+4Tn?_&D;UO#NcKBU7Mp+|8Vouf)r5Ia=Ex z$DfTMVS7D85xC&k_k9@KuK9kmFlSXOk6O56TSg3BFNxl}cz-5+P!4fSI_7mnS` zCG(5JKQ|a$Tr9#1r%KO@pAx^9YmoW3&_*@|Wq#8@i@RQOy^R9cgb}RX8={lN@w*R) zZWEC(iZTvbgkhjL5v#iFZAPz|N5rIb9(P$_uJM;_O~mMM9H$~Nec{r`XNb%G@Xn*T zvLKDUcT_?E<-N5rHk{++GJFK>JLA{5ie0{yXmK^vw4YCE7r%aWh`0l^``{+&b0H4n% zV%i3ZY&Jz)fQS?OA)LC4X)livB^NcqbvKG621>XY9_w4xkT!;PG$y->ZfxzmUaw&b z(@4GF^fh?gcD*CpWqQSAc@qbW>50d}nPT5UwpZD=`@%)$yJ{pI)GDe~`kqBN)=>*l zJlq_Uvj{E5h%;vqWBk*9`cHoGcs%fUJQg#r>+I4<&4w7*n`cy@xArEx7P*<|Dfe$Eq zF7t4HH|XTimc6zaEAr-MzSW#r%f&tC-3|L~m8*)uW*P3@*Dzr>;AJ&~jg$MYN{c{Be-iZA}<&jJXR_;k6PPXUs%hoS+#U99*c2%>@ew_;=YR;}H#WX}DWr#Oi89 zIXPW&X@?Nd%DexPUAF9NWaGZ;h7W3fYh*|3lK3JXWA9~@90#eF4>c<^mdUUz?c3+E8S8gUA^&`%f@O?Rvz0qa=ieiFONv; zyPB?-TrZ)*?#)|i9L$DN_O_f`e9;OA%r7WF&@uQGslJ{SjK=bKkgW@*l?awGy`63E z=TjI3_&j61jG;n8aALi&>A$hd3xq&1;>v0$GfKyr(;}|hFANHIU=6Vz#2a0nlg!h ztaGNK=)ZYBpG$$0E?!JCP&!UBJsMK3__KfgZ}I)#`A-Iy@#FphT>S5>nXxnjv*EF3 zjGyn-s%9cmL33BjqL^m>bQq|zn1kC|3QBHYEn_Bqhkf99M9xLLjq41g;TnSLg6k-K zD6fm;Gs<0@bfOX$Z?x&xA)%k;) z@&`+bwNnVUU4k^Q}Nc zL*--S)CC&NMMg@!0)F?}0buYTX6Kn`tQVK}+*-$ZzJ^+bl~z}76~n<-_wsA8&L*$i z5!u?XgXF5x;-ZijK9ed#2&kPyaQ&Mq?puikyf*mHI8H(iPXDHSoQ0o%LyhG3uKS1! z*g4*?f@MWpnMi%*ZE>*_f*;&LdEL6Y+tX)U*Yql9ADy3%Z=*W?tQ=3oF++?Z@bB=H zz4$GsfBU^$&@n02E}NUF0W}&X=R+?sk@jC3o~pmo3RHOyQwYE@Ew$F6Y_#`hXg!Z% znEWfx!`4+_M&MUll-}iB7zlB#aQb=enM(d2#4Y?{bjd|3kJYHNA3yuUTaHudhi?x)&KVtg<=L61DxuB?szy8GMzx>zu?jQd{ zI4|O?rj!vmLSYW zydt93K=2s|Ma8OezuE<1aw=@IHE(Bo?;Tzp=ealt3C~RX~M*x#_iMNZM7o@%C<8>l!Y3aIb zyv9(qSAQT@%3ViQroOZ6qrnw8U!$mOy(vMvE0SND}QA{2!opAu5x28q^|rIRx>i{aE)X!!lpcrwLs;9gb{_DGrV(1 z+cuO?T*w3;E<%LFe6Ks-PHQ zGhZ5e?a{SwGs>sc)tgE(;KH)!tx;k{vi%+_!mfoKdpljdvE;o(-N%!gXWTe0{=JWH zb{_M!?DK4zY=H4z8D(RHi5tCB3p8^Mw=>BY2=Lp`cL!2s^4KcE3&&4~hDJj;fqCZl^hGDJX7qo_(uxk@H_fODtj49`L za6^?X;l^$VJ~$KdTVdp@+E2bGBSSOtH8{go>_(6F`NZr0{rC9zJAXsWPrcXzFtuVf zs$v^p4OTN60{Q}4T#;VyL~K$@UPKquf~d{Vda@{*LGgC)lPS5Sq;Ny;JvPeHOxreW znCuQ1$j>EI-3Kr4Q-KB!Y3FmLwpq}3N?~9y#wHhr{9eb7tBEp(wahXeZy0+)0Gu@o zlW8%vR)qiIzyI%kv2VM0Uz`~+D*vTdwCWVL6<@5{BnvR6sF17>$2&T*nc-=MnmJ3-i9Qi$zay`||PdImHKGBsR+|g8a5B)Py$iR6xCCQ&T zi-dVgDCI=-euR6r+K2xOS`#DL4!G{*yQodqq1b{%?}4UBO>j7~6t3r)v86OjL37U7 zHITS>hu3)^Zb4L#aBy7+?AsHB!(!ehg!{YQ0XNz*D?^JmqunwDmNE_i4cm# zP9>LfaK*fL@X@0dIY*+7Rz(q&5u%WUTNmTnZQqn@Xq>4k-$M|y%waa^fm~hy5_+u& zn?r-_7a6TJ%}5hxc^Rd*Ifn2-*Py8;)jKRVaXVK3&`*6r2-uGS{#D&yv68)}Y(g5codS@M~2yM2fms{Y-WROp=}XK3Bp zKmY(B07*naR8CbfO&qT1Hck@yg!-B4`RTmaC6sFZZC&pVufe~9ei_Qsx_llhNK9R4 zDGzarIF1*bx4kIo0OCO=qw)}gt`*IJ4H7$-YtehMDneFJ8`Lbj;H<*qu|VS98y?RG zQfDFHJ*$6V+zd#6<6coTVKIE}&*Hcb3CezXK!V`=kNX zK#V(_d3bqo_lNEgK<=xiB=-N%J{lRO+@IDPu%rqYU@hkmpeVT1|K67wLo_s zHCKJUSrouNz>)Al{>+n^bXSo;LrOQG*?BKXFEwXL5>NwU39)u+pCM#*?*JcVuZ1M% zR!jk|RYVmobgjVs-+%OD7xYIRww*_W zMA#fh!IzH@IM+sHTGhv+RgvyW#b#U}S#ajc z>E}AoQIS-tn)4|x$uS`x1tF+Kgp*AR$os3M4*4!RRBb00ZE#*C`R3=<^m1z0(hcYh zXURxWJXTWg<8=fsb|^8SwG6bTR{cc_RgV~@km%Q%7MrL`o}2 ziHuD{8ikXgBegcPoN?QC@!2UE4jy{0EIgq$#tiblYip>kBW-DzTgDg>y~BBA?6)0f zDafT@k4a_b(=olPprGcA`~4;X(`e|eBA1GNyNQE!>+m`rFqi6@Pi)&wgPaAfuCBsI ziMzi4lif zQ1W$~LAcHZwCa?^T_M3o0VPj@Y6Z}%W_$+aGzE|6H&L-2=$7pL*2GAdDh7LYu z$Kej%Q3c(xu@pK|h;V&2Owi)qxiGu)HUrHE%Ht!>QUEVwqx-(07L9&s8O{Z@CODOs z+i{#3DQ>9F$tC7QrR5NDo-)3T+AOA&5S^erF$R=sX$U~cSqdR_QAd-pku&r`v-3o7 zBAvV-me6&X<==NX6U|_GK@go#Cx*ec^XRqfb8`AV%CMM8NzSjVcR)%3jts7I$=H(c zW|MlsIe4TH09VjmghND%0ksv$AN4^0)lYc*tAB&v_{aYMtrz6h;2N-PVeCsOnB+4% zMdG(T;W#rwl4t0Yv*{g>k5l&+lpfGgQB;{&5re~?HlR&G!M5#6C4ua_B$g<>m9gGs zopgkd;JZC{xx?kG^8;*f#@DTDh+2b9h z3J0#_GU!1uL;$WpQNLAuw&6)8g}R;-t-&FU2CUXHRI-*&+tfm);)N6ieRCG+=H#vt z>9~Ry-QhS3eCTlh>%aPS|L)_4=Swzm0}wwVO3lbeQ|E5L_c)Y!IT!5r8@_(NaKCMG zU<5&r&Mb3mbl}UE@9@iC{t`JK`0c;?+c=L?I=u!o_rzcN{s**HaJ&xmRuQ+`AV@wR z4>cZ@4Zq(uv|5pKL$1K>wkgcov2QzomsI7!<2+8pB*gbGw;NK7`0l$e`26{2AZ+-J z-~287!5{nye*S!+Lo)F`ZVAp+Y|$h5j>jwGcDv*2*9Tgc0M0!)R8*uSq~?83_;NSs zv*YcPn^70MX?Fe!X7kF5oy$e0+SU)q}^rN1SJYLqINa;Cz=3q!8ry zTL0C6GiQVV-0nMSsd9*`?^RU8&aclCpI<-m@$m&QZpddw3>^-_wX3z_SHJoR*?Xit z;XGexRXUE}{EZK^4%}`Z`1P-TLM_t;_-H}eqid^`~%a2}_26oO3p-0|^o$F?Wz zyO2TeySP~Y_~TDFN&$R?L&yE&V{q|GF4`S+pjRm*wjF!g2G`C|os5px>%i^4i=s3a z{N``m@%ee+@q{7+K=cj)4rz;cJ~Co-@LR-@1$8V{!&V`m**n08hVyiAz2S=i5G+eOa)cnFG;^!>|v5L=0_Ka1be4}a+c-8H!0kpT~)h+Z{1TerGNf zog#kZ0-a=S1R+;X7vnyxApnQ_ZHMz7$MF;+%TtP587T=*u@wi~?b zsK^LG3LLrk0N0uv_O**Mb8EP#O)N!HKq-pE!efgb=qFyeqV*4;S0wGMOFbo^yJ8&P z(YT#HBg9QUmzQx$L_lc|!~pabQEEi-P7$Xvikf;>eB5rxS;DMSbZGt%{>)1ve0r}y zmEznCRAWkb<$@HylgrOFq*(Czs~5if@B>ncIP()*a5%Fc`DkXEyQP4fMS_02ZxT=) zHZfTgz)6}0@|=>QCJrG`sa5S95-J2i=`|y!h+HaauSnLN!=dYCk8a`)8RuOWI0f^836=Ew4B-3>xIw~zW?q6RZT0csT8Cw;I{8lw8n&5`xwQwTGfNd zDsDk2(DUFQZQBm?j^-t|vo}Erhbp=X3ZB$E$yBAm3|F04E7Xz^lOUOAKH0#BA-&c+tkB(X{6DV#!;oPO~GqnF3qXM&^cF7sz+-A419dK4*}BlIFSGM-$(n0 ze;d0OyOV~l4R#~`S{Q{wh#neFgjTBN@pc3kaFi2WkJT+k@sf)PC>_oxgy__B(xJMB zQj0!i9rdEC=aV$`Iaie05qv`_r^f$u#I(tor42&sby%KQk-qOcYOcz2lw4T!rYg)+ zxu$Y&Mi=3H1k9=31Eo9>lpDA2!gYGRo`Oh)s2nthJ*5$sS4#m@3~}aDig`uVL$nca zmUZGI(1ZRyrQ3vnv!3X+2^#CB0KYdaGE0GT0U?Qf((C+$d!5gImO?Xgg%w){pz63P z3(Zgv=bb%r)Fv=oP!y|cXPRbj`Kha9{ZM%OO{~HTH&H}eNKxo?_~s1h`0y&ZL(m!)9&2k*FS$9sprCl z5eaWoDZcO)ym$dAm!=rcj10|6lMcQ0fV3s#a!#n*rGZe?+O@-#?#zDId1moM@d7&w zzbc^ML<|w$>7m+no}!(9R6axuf;v7vAK21O#uM<$o6~Vw3~2R0a6;I0I!3KUH(83J zV)P!hRcs+(i$Q$2I#7F+G2n43dA&>*|0?jfjPQW-tmu%#dP`2nP<^00!6!I0Rjx=_ zY3stp3Fyg>j?3*8v;`FP@XOL(0fXRElSgjO?ZIYqwgOoo{>&biJctza@ANoX3INp72}0 z`GH^l#m^`;p%m#d@An&=YlE{HlLRjB%2}!HMC(AwO}=|=WWM{@(0jqpp9h@ZkWcAK zeRQLdJ8HrA-+zx@3u5r1zUmRJIsE!pzsC39f6;MGCo@lvTrzS4IwGWQt@!TCj@YH4 z72i4shlZaYf(E9P@Kh;!Q&*apJT|o?K<)5BkoxXCjziGRl8cVFq_LM1;_x*`yA(mJ*+;>&HrnG2q;6ZhL4 zX-oM0`V~P@;@9hekB<+W`2bo%+5((wNL#|=^NDRwBY1sFNiKG6nvY!2mFM#DWykCJ z#D3rL`1-)MZ}_<1@q8T`P1A9n1froe23#WP>vUT+~9-99`1B^G}E36KBn|3Lh2{vPh=2x-Gl&jVfyS1Bd}e*NpOh;hSr zUv4N_zE=c~$Mb~{BDPI9fwz4_P{i`_c;J5jP-;)bSsT85e8KbcD{fnYzB*z|`01xl zI0xK6cKJ@u1HC#tpD!RfeEHb1Z*eq#y&mGLmC{%@c2A`!cc(H=wSbm2?L$OXH~dmE zKEB+L^NC(Na_Oj51slO5Bst5ylhG}@$NjEk^eUsrnk!;}sQ$D7`uMox_0otrFL&dYgew|3FjL=_B-;K(YnJ?GPWdv@~w6)XaTe=YX}+c$j>e# zIe{AQ`yK5()vLrKp9S0Q;X@i#akIFSCPA*wD>UnrByeH9QR1#GvnXL#uKa z<@3;LHmk{6RNopmxED^-)Xy_Z0b#E9!zO=vK<(S6oGiIuQ{41@IW6dl@CzC_)GF^K zQ|@9^&Oxpx?zbDtnHBC8?v!M!#X;1T94bLadMi4@3fQ*|uh&!I>>@l4KgoI>4x5i^ zq?bk|-V~;PK3~|j1n;BfZYfH6$;OgRRdCyH_1+RTNQ-CB>Qgg)bi; zYD@{Z7}Xdv%=|YraWXfOda0=03G!p3=qe%u)Tx}z<mJPtWKGTFa4+lG>VnYMuF zWNmK&$W1sitrwtHROc!GEh72=F93+3Kv5+44MDxS3c7c22#8M9iD^sdRm?tb+lMxu zWsF81M@H}st}DsdCm9>YO^li~v#}N-6PKECybgpAA)uH?h?^Ku))#6~ML1L;9vxZ{ z?pbXG=W*ixag#zj+gSn)@Girkw5mz7-^3EYJ1Oc~175FFO(k^_;2hG{(OpFf>R0Ci zdNZ+zM>*uYY~9Rx9a?k31JntF0%CZ4KCs_+HK+}Ed>-QUb)K?5RY+vX1X&S5uSS<9 z#M*TPUCu1R66M(5Z<~(J9rBUY5Y^)p<_8?)Zr%3{$N571@z+TI=8tjy!@q^^LqzEv zpRFUmUbyW^1D1jA0=kaNddb2G^d6@Y-CLi@8Yu?E;FUKf=Dhp%fye8Bj}cL@4}8t4 zFboMXZg@VQA{40w9UUp$aGWQ)Z@BLf$LopPw&6U>K(L{P*OHGb_rsSjUxugHSqd7( z{^v1*N4Kd z)~0FULi}SZfb$eGt|`h|6|=a8CRnBi&_o>)^&+WynVF(b`aYRtO`slmIf(pN)Db;HLWS3 zS(RfmUZkTL@&%~laUZD#Q584#Z-U<>;1yHKA9S2xL}f#R4GoMj;`w?h-%AL;cA#4! z=MKwrO=(+N;Ox{5r6HvuL4 zc5SZIEOJX@Ew5HBaf~Iq7W^V6&`i?c2bx>7;c%LD*$Tsr z^|`ap(1j1=y^z(7bbPzr#X-9P+rFcmSY@(+HW4=vi9|q8hR8+9-(PTX{#C^Z`mJ5$=_o5ou32|KLx6fA^=j|D(T)*1I&9 zPR>0+@THLsF$_Pu!NnxCrE#Z?|Cue!JZ&PZQKEQLE|tu7yg2OF`MPH2YH?R^au+7` z#2P+Xecm_D6qlkPSc2VSN;-LPx(CIt&PIArp%AueE@K(^^2M;NScVZ^TOeI2%pzIUq5$t zL^g>bd(p_Esf&r>>SKgAqt2^Y8(Sfm+%qLn0$HYz-2FnZ{Q2jvxZSl=gn5_fgHXEM zG`a)|TOI5DfCAbZuY;oLQI>-xEPU5ubm@85!>yYfi*_ppt?%#EDVZZ?!%avUkT!!rD= z5bYP+1u?*Os;Y6rrodi*6c}UwOqXio;IVAmSPfF7Ob;4UEg2fP?>ow{cqqg0*4B>k zq*6+9NYyHYZT$>Z6i#RUX=QP>Az_0&_RcbiI~#Pe-_h!^#U42wj@;G@S!`T`yZJM- ziR;z4lYMR2dV~!>XYjRfbFR@R{F%66ahP6KQ^IflH$@dpm|PNdj5pc16`$-PZEMrk zoxLafZfmPraJb>xFGOHbI3_jgEoHjz=bZ6;K5@I<#y*tSF7tBLv98x*9%v&$V_2OG zRjr;krNC2e<+p53j3h4w@QTv%KD1PXtC6&v)f-|o8-%8W>oDvKoK7G_(H0l~yphLF zHa!+7%oaCSKRwR&G_=ILzOJ5erk-nEty!9qoO?rW+BgR_bX7YII|HPVS%acmtBY+z zN@<8)u6N?}AC!V9{rRu)`hWfq>A(70Xh9|pJy%su`Xv{W{TA8chd&obUCl6hRlVD} z(!^%LQ#72}1M&V9)N^`ZvB58bM^y_ZyPMck&zk?7&jEZGx7#=El*kXVbU8;QAba}N z*}t*o-mB@c6?Tj5jCUg@uQxvm-TVD6?^*MVtJws_AhZw5adZ$$2Ra<$c=jCy4skKr z9&4^Q9LI_9yTAKSf3c-)__}a1^zg*#>tSdAZ4SS<7<_SvGy4eHML(hhG_%P}6}zed zy_a#6>!RE;Q^}mm62ia=R=9zZ6VX7}{&ue{-Q?2kG=^DI-HG zk_vE|MdooynWqQ)nb^U}9zEBXh{d6~*U>!*UuZ34Ie?ZAA+yrp157T#sp=RG(tUcn z7=I(ipoL2x2COqEG%iI9n~bt~Cp+@8)BE_WPHh1-YUMe>3<3iZR#_azB^u=>(ped$ARn}4;nO^dprIbc7DQjRQOK+3B@7VmEF>0tMmqBOZhOyx0ldj4e5MmtXs8 zfXc>>kH=#ae*C`qwd`{LRxFPhgl^l0UJEuYuB>P}j+c_PyQO|Au`Io6rGq;5wjB3!b%*D15*rnkGM(86#7^tN*0Lc0oQl8*mc3s#^X1@P zw)f!uyM$6-LYcY9l6a_E-0LM(Y_FWT$C1fxX%SG$qqo7Z0Z~C(1)~ zUM{U~x!ZFwXf`S0ATB7T5Vf(mmOBUJ+SL{%{|_bZQI|aWVIx4OCe&7(Xu&3}44kkzZ0}9bu|7>;SI^O zG=ylAE#-vGI$@1uvhlu%2s}mXxh0`u+_QlAS*aJL4^9H*i!??}$K1Auw{06%5xsZK za$mDntGePl?*OYew62iML@b8EX1LzFQ!a1T$fr2?znsVGycfmrKl^9@%P+V}eed+u ziIw6Q_`(!ey^Uyq;kHd^_M91;cOUIm|{rLN9vt08*cek)R)I`E(IhX#IvAGGXlemU@4!jstRv9*NV|!YgmJ@yZYG-xEG_l z4^P3Ll zT~#-a=T~~4VRZED7A&vbsDtdwXJr?19y1F}e+gEm?~vCcqkhR`$VzBE&Mbz%F$m|0 zM$s}JDa+^M|M1v#X_V+9=Zk&e)Lpvars|+MdRRlWxv0D5mNNRlh5bNZXtXCLr}2_8 zxfVdL*Xzv<{yNsIbtX`7A;j?^HWt6Wj_~x-((PMOXs8vV3XJ&j8nd{ts+JUe{9U`` zoLcfl9b@b3=q#xHK?t*HnrD!h;(GN)vI5H*0!Dh69$`F2@!0cY+%0Cqlws(?QixjE zubdTO{Eph{7@>ve$NG1Q=T?ewx}w&zxosmLc{Bu6B-=>vnx|=JkTu`4a1&c1Qve%+ zDZhJ~@5<}PHI_^FFh@S|o*o4_p{l$VXV#uRhsO)}`a=4Tej8^M!BnsY`O+-#clE81 zW~Nc_xKIQuliJ{P6z0@{e=R`kTOKK6L)PGM;suD#AUwe^#;Ep#!TZsmU%896zxeEF zx))tnpT*urbHT3gks7v>-k06+b{6NHRhbz^o}r-bb@+T5k}UbXf^ayX{Ko(QAOJ~3 zK~%|k;|8E{Jxk3jIQ-u4{ZGH(t|f*@UFdXYmyO!=gSbJsy`lo+FySE45R^<8)YZM> zwhO^Gc!Bzav}cC}=lay)p04dbwtag;M%t1owc7OCWi5r^NkxOIp7da{oVM#IhQnJK zDjgD(?iP*=BQ>`0ISlvf*RRWboU`+Igfb!duw;dK^*yR}WJ8O~Bm2Cp1FDYE zLQJC2%I9(^8}H1b8q78TSkbR=F~K-+I|_otv-8{^wSVBNkC zZipakjWOB(noBmLm%1WfvQDbHU3VR^_SOf}tk$w{KR5%Ifx^_3Y9J#Q zR5xozEay(G4JpVdy(@|-JP|>#Ymqn-lgBeEJNP;j@e*T1+Qgh#*6cbS=aBGHW&>(! zF?3bz!r_M>e$XhSj8b%@Its%u_EpY@qS!{J);(Ye6jYGf8N%zu;%9opFolGU@~n`s zWu`G)WI5w@*KqXU)S9IZ4kbrvaU@!;MYP4OFU5v5?P~_1HK6wFYi;@--O6cl zeu?dAt)c()3IFp8?yvu4xxYeGm26vzPO(=}_kAifZO&#qjbv0WEgwW-iP4CdjgO%DrkJ(@t6HOQ0RilJaie6R>vm>AlPg51=7z!b96via zq*3`?P1a>m4zgDze{X#hksN9-DFvtSdUJVp zgSnZ%z%Xyn%a%J!Mk2T?<@u>ejhl8dJnQ#p>UqTBt+?=-jHEgLo)2rgFoO3ubQ4^8 zCS2Uu1^awH@$vCNo2D)Ve};KESC50E`J%UHWiYQ1+L!l8gkk1J*$iHkmi;ZkoVyUq z?6Ti!8_W(A?%C7hG5h zP429%#f#KrbL^xN00TcX1LDiN*#n3@p zL(Ca81Y_HF{hbmCA_&AB=N!+MA}2GtrZp^Ux+$SFl3I`paoz`p7BiWg#S8X+8Kva) zbtUt|t>eOuJ_xeh$YdH9UjuHrvE$C&vJ077!0+Sw^PE>{>niCegx78lQap_F#Cvqj zkIQnCq4kdAbq+#%*6++{0M~I5BXP3l!@}Eoe~#Nf`p@w?4s8U|+nFg&?Lxku z9JKaE__t=oz9$o>Iggbx;T)PGx4dVaM!zxo!vKVh23tE2!wtDqgrEg|5wywn6rVTT zkcW^IL6qh~1SL`|v6$j2Xb`n;8sX6PJ@U^8Nj@)v9ouu3jmnv$Lp7q~PZo|bPrCHB zPzhMbl}nWoAuEWukQf`ExDU&lrl8i9ur|kxW;aks*&|=1bRK-Dni9_*z_v}q!wrMW zHbxenAi+itoVi%sIddmzh}G?OTi{dc)~sWCn+NNAW*B{Lb_}G9t6AoE%$c@d3K~1y znYX~5vHg4FZr$(qCHU036}}Moa9@>UarivdQU{sc4wu1^Qj|=HgMLODjfHJWrdgo! zA%6WH?4V>$1s6sJkIOm>gG6tNDgI8Zz~W}WUdz5?=FKddqLiVIv7Zx^Ns5QR_=~>~ zr+t0D_B{4|UoI@$tYdEPMQ+aON-HcSXn9*M2JW;Con&>>Muo9i4Ok#AuPJdeUen;M zi=Cgh1FoVLQJsm&Y8pjtAa&BUQL;-w@&MyN9YN}0;lLd5&SBejY5)Y)vqFdiyLsfp zs1#qA!>&UwciVIJ9k5!N3$CluaW;>B2Kid?-R9`e#`laoFk*Avn;``J^wUrH`1qKT za1sY_gJYMdHM6z`7#a6;2HVf~OK`ZCS&rt>$+`6T_{6>m!fM%p*P`8C^Ez@LMR#vh zps#cb8+)>X+}^*Tgg^cC(>M?B_mA;i#u)MS>sOqo&?-tfhbobSrL73C=fR_6<`D5^ zX6yXQcjL?7QUz?U+IwO#6Q5hQ2l;o~Yl#vNnqk_6 zTx_$rFtb1=1lni6-|y5hx;Op-KLb%?Xn1Mq+7W5Sl@d_-`#0lSUf5SP>opC16n+}# zU>j84yTHDTFubd0`tmHt`m194XcxE~UT%y_0P4 z-~*g3LwJlnRal)4o-lYutTJOxfvsaX7@aD4J7U<;py+BZ1HIeRhT|yeSJkv=c5lkX zMrR0*CsOf7oh_KIDL)=@k=CuWcKdgyR{HdGz&w1KOdlU0q^f5+$( z^S{2O?zH#xd_Liv!^g*mj)Ve4n>ss8k-q8Nw&*1;)mk59V zZ^H$ThNiistId(+?)IjQl&h-9+m`Rfo|6??vOYb|d@NjG@5DRsYJtMY+|?Fk7CQ~j zSDdGq1Bc{L@`+lebSC2c^K&szawrhEqF zShs1!RD-K!Yyz>zC%>bhW_^4q7;!nqs99%uf$F%(i#j@Bk~(|Su#Xh;A^6V*H-Z+_ zwUDvDH*SF);H}NkoNabKWcd(dnBF#Mx+tyebD8}BcWxgaA4~VcmKogjUten$v|Uo{ z$KP>cIg@6+##m^$DkeEMrAWxnw)}4H%(*aRJ{XVlxT|;0;q`h9^TvI@sj*}mep~E4 z##{j_{`iu$zvnL1pmjzDhY*xV?Xd5glAE{XaJ6UX$e8oW3A5L~ zl5!Wm#lfD%3zpW_}x7aSplRU?t+gZkqL+>58eV4Fc6+tlaG43B9(0=-gEd%&#zolMn z4rmRZpP%C{wGm{|6a-mIl8|AZg;$iu_DzfuAtijo`FzFjxsI_J11CIgoW7EEoIU4x zqEyM<4Iv_*2cEB|=A>qP_x<h#QzA$)V7B#N5+r7q%@~KAd(clcy@#!-Z6$g z(7d@)H*l(fpB)AUyLpS;(Esf;$4y9kGA~vAyLz^$qbeOV&WYo!cVg^miXq!vyttTa zV_YU)+$>R-%drjRko~u*jo1^5zw}8YUJoLc(q6l>(IEz?LE1`^<%5Jt%XZM)n5x!> z;Jc8+^*tWviKuy4`LGe~Hjos)>@7FycDucG4Ew%oh7*w0?<@E)9o@ax{5?P9tPIK8 z?>W!Bm?kn(wjSyd<-kzC)jeFWZQDLB5nFqv47CGD{(efDM{%O&b+uL{D@t*2yWQ}7 zK9`HtE`qCpAvXfn^}q|aX#UyC6)1&y5T*p1WX|!OmxAxUd|9|a)yzwMAeU|bHfFI* z(JPd0-Ty2$EivAY*E95u$8|o0;WFR56=I2G%=04h&Pj|>oc7=ujvTN1+ie`DkSwvNZ+ti@nPhDw!zB^x_@W5EsrGaxv`jmkz~0f zPk0~Iy}XVf;c=FEZAR);>;}!Hv?km3yNsLmArRr_(4Lj>x5R7g>MwXT0cGA1qxhCY zz#~tI0&AmLH}di*pmdxMhXoB6Vse?$Erx=2QJvdoG{u?-ILHD=UCYHWUH0^u4@GkO zA{a9#^3}JnE$3nXcYlKVCx3yDfAn8SBiR~`T9ATTUBsZm8d0~IFJEf~`)x-)>o@si z%!w8E^|o00*gaV_KwI4LcX2jvT_U@-4ao;|H_r@H0tyj54S|o)N75p&Fmq=!$o1aT zlUT<6@@!^dTa|Bk^=-4J(Ju|OAKXttMvYeCm+`*D&6yH&*C~VsMt6DtA*c;ZYqEay z43(NBjOKMB{uS^Jr2wv!vm1d;9#WG)W;B$V#|R>Y_*QKv_1|H5`Kn~&?u`!_CZaKN z!=sr~A#fg9Fey|HjHrj(y7_qI!iO4jRE(%;n}kP)a?qcb_umHZhdXX2OEcHuYBE_a zCUJIX%3%!Tl97VAJTq*5mCaw#uYo2if2^xo%|QyH)*80By@?nY{x<~-OJv!5X^=?O z7fXD%^diQpBDJ-|2fZO6*Gq=SidSCWYICvrl1Xuy7xZlMhr(j`XX+Fl1Nq>UhZIn9 zU6g^0R#;)Sk?M-yFLS4I&hP;gCxe0LtOmGsC|~C9YfItj^|D=jSRCM^L#uA6V6S5j z?z*my_e_}QwK)sMpjH>>!rw6xDgV42j>6pueyaa?yfQ|=ml2eGPbSzH-(M>l8xv8g z5~6*2BZpf=jJ#~aw#Sh{H%5>bg8aDX%lYPsX3or9&^Pk28@xZbg&2F~l+{|bKz}Tw zH~tQ|NZ{`Wcy}tdi`kx&Q7GhRx}s3?y&Pv*#%J7=@mQ1#(1G@$YNADib8YzGncWD` zapn{Ic2~tTmN9vH^E&Hqq8p~3SYaj?*t@YZ(@?%erC|OdbKc})51eDU@?H~hWF8=xW#OwIP=i@6$;p0Le zA5cG4y>`G}{i3eCB39mAiRWw#_jo*(;^Fmrjjm;Orx-KRIT~@xX5y;Z-uLZx8=J)5 zhrz`2ef2lX1sl)sJR0y~QhDa#L@!*duH&1y5F+`K-BcQFQ4romJf4qnU@!h37l}T* z5qt0P<;xee-f`xPTq|Nqcs-wpG2!FOm$A5OtplOqVwVrHs}Ub>$g3mx)$y14PyDPH zLAnx|SvAC$78lGsRGv^I#;XK8#A^4=B$Z1iu^19+kFg9hj?{(Xf-Ys5@f+f18 zw2EBIh@2^{;5@UAUnSp=5j++Y*>g5Al$`^%-b@fut30!9Q!0iQiYY~TMjhC1Iu=V2 zN68}wY<_PTXQO~j^4wG0kaIg1Dmtp`!Y^|`_k!B$3sc0jgTvqlQvWWFXkvCe^aq`^(|xA+7L13Ce43W-&A$%0d*zz8`5OKoMtysOIwWk zuE-}77{6sKH=d&-ltOyi@wyf|+-9F)vO1{dVl z+(8}_o@W`C1S>Dk^F*KvZ6X1JcA3&=c6BQ`w$qrEQAtiG5N|ShFC{lP-!yjOws0sU zTs))XrUgb7M{l><5HPoFMv+7Wj|EYaU)6 z%y;9WQNH^`dsCYa@5Y{xw1uw83+wJ9_((w zTT+Fsa|=nI`Fd^fe-jt!fRE%z;svymHkp4>R^;r`v9qWtnlq`&u{BA0^LfI~x( z?W~ZqJW*aL+tl<$pu*@WBZcRA4CHOb<#h>m)`GsaDttiYo|%u@p#*s=pyjiukr_>) zB%gOB%6FwA2~acdWAFTk$CLlB2HtV{fO)UqPYhy6>m6M4E63J3lwL;6pHY{5Ta!|p zbLf8lT&aSn#_oqP`arw4wA2-{My$D4WUNZQaW-)3cYpVv{K9*OGrxvBGeq&dki*ld zTz)M?%=>2$R5hdPTNe~VgG?O0dP;HeG`%(a(ur}Gz=snuAoIX9)&mz=QQwb^!sT+TgP#~< z_$K*#9FjyBy?Qb+eIVzIR^_~r%(k+aFb+lNC|HYj+8!Rlmzk!*eNo_!bD-750>I7| z_PP^J)87=BzM?&e1mt!g%}4`Uj+;7 zsz0((zmc@S=Q9(Gx!7?*yu*A5D7Bzl!UE-e#+Yy_zsPvNQ7`on{NSuYIDc*qtgfXX|M`#bxuE^_Z^#~S9#v!J)`XHq{HGatvvPyW!rf&6!j$jU z@O5?4ALgFU;XK890Zt5M?K~>AEWg7W`liU)v-Jh|g|Ew(Medx`wJ6u(?xnNjnmMyiJ9#u!n1TbeTicI-W! z=Q)g)LyR(N%=yu4tN8inuc)t^ z61Jsm*HYmw9#HIJ?I6y^(8v%bh_m!w4zxBdHRCB5$+81>4 z)f%dZQgIwF{Q6fv;xGS|zl;z!yp98Roxg9}K3u^W5v-aP9%GolSHCZNKY$b0aqXB# zh_?^RC_+A4c{8Hr5!5yM;_8ge1>h`_+b|cs-)}<{aV5VS_rQv;@4x?H97Ljol!G>E z6vFHElA;N2prW($t~v&j??W!{x*Ux5zlX9dy5Vx&E>eD0rPz1Z`x??cd|SRT^6PG* zVsm_1$yGlr{3_YUe!%VXfC#!joL&ywjKi?(zYv6da|zd;nSgZ^($;`kR0^ZN=GC%-UM+ zG}cy;s2LiZL~WKQ3KmdXR&q1v#TknB8WCb{+zo-^h1^h@ng5=T!X3-`6w4Odb4Fm+ zacNhJ4H?&o$Y|a>t2dJf5+Z6B3W?Jqpp-m(6GfOKyuW?l5dhSG`$zccKl~}a{|A3} zIEp*(aF#rs`&&cs0UM#ia&Ng+!m>*W$ z4*^{^#ou;EZF90wa>mDfN7r;189OFqjrQujNx`Rt`Du?M&p#x;#1n}aOMU-x9!UhX zTOf3SdmTS_%jz3lZgayEV;rhmSok0o<f~S~8R@KzDlm^f4l`&iFh|^>JCpgDEAPCBMo3J%v@$l? z8zpcG0efCuxpY^TdloZX(O^amoO5_Q9t)po7+A*lVCvxfQeX&gjvA}+`{nc4`M}wl z-1s>U9d&qkJ5w*55km~vi;4@K>qy6nExR0NjEo;fklxQ=a5EaMdSO~JLEO?1r7+R| zivEirK!h{hCRpsmV`(1f&YuwGEz{Og;AIE_d=DB&h-SBuk23pAW zJTXZay+c?`I$65EDnkj?a?s`phOr1LxsW7$(M|N|YvUgbb^g=s1pH8{>mU zlf`Y=E|pTGQ1_G8VU`^n_cYM^{8do)@Ox~;$3Y-(pRPOo=SRL3sT5n6najALm z(HK}o!{imF!2mTlY6az*cTAgAa7eKebXjF59Z7IWciv&P8}lg`p`9Or0I zLre(2`@8?+FM^luJ@{zZi4$tojeeZ33#rSE+(IK2_YQcCiSZ%eECq2?(q#~0TWfeJ z@z#YPO2ltCHZvk(Gvf0+2bq-pZEP_!nVKC}r@;$*Gc&?{-%-xIj7ptz2q_FRPp-3d-kksdAOJ~3K~$g_ntmsvyJ5?~ zB8AuSlJ8pQ6lTk&rScPn26INZy-hl=`TSCVU@22Y4 zzN>2@gzz1q=tuk}2Z{?G7AV*VlP||Hvb43JTq36?!YNAOXa&jD$L;E`#U5R?$^MX{ zRf;UzU$(vhL5rNxJbwL03o_S#d$Sy7wta!V`Zrxpj` zz?2FrZmm;%J|BzgI&)}wxWwrA|MOc*u3bBmHn39dJ6 zYULDTKr03L$S7LOZZV>j3a3i(Oz}>B+zow&9IMHLkV;&5J+_I4^Kq$o9fzdBQ>GP@x1Dn+TBPvC zHSZo)!kD2YcdJ%pt#0b8^}cyyFuAgKQ7!O+Xxtl{w|nQ`;spk5PlkK@wkw31*XV+j z7IcfNZ+iyw;?ytk%t%|(?k&89Z<+T!v>Gn&WYw9ffu6sQ;`DjlW*Z3hJP zJ(I%_0jTEJb+Oc{|Fd#9d*6Bqo9@UcRgKdU^GvJgd?n9Sa1{9Nt#n-jK;|IYJ; z`~71TC&0!};mx)o1RD|Vl--8WNZ9XqS6qfc*q3}fMO!M~jAgS5RrnIL@0NK<%Ni%- zh}Xq6XVN-a8{1#Gj8}^kANm+A4=aV%m*SjB;8qZ_y@Y-LiOh|yU@N7-1#!a`vu5Q5 zwrRt`pWEE^d2D!9LE}wo?r`R!%CLtPAi_&AzaTqvs`84mD!0?V4X18KBHUt9i#3>- z3d6PN(sTwVg~+~%V$;T|lX$+`bBy)Tfzs<}SnWc0L;~l}&F7GeLe=oNGTJDl=xYHi z2vuH+A12f<_CspStE>neB?_6^)_!mO%_W@CR=#|_^XN`Evn5xJ9%I3k@SM7i+kNji z|IhyqF?htk^*cC^6K5^L2a8eFhNK4Wt5u7MiEN4xq96R>Va_Q-TpX{wpz3T@Gn?hA zw1=>`!Cw*37$fRg;5}5dOmOFWl#LYv_)+}2E`3A}MU2Jz&b7I?f+m;4} z#C$TvpR5i7y&rLOwyZnq1qm|_;)skJ!Ps#@^{uh7=GY4OT!fC2OGEg*-}|3`vFV(C zD9f}nfCFNRh$$ctf!4xAv-%J%hoJXJF(4_#{N0z2$>}f^5FIj%%9vLNcZfNk3&H#9 ziDhV3t!+U@uDOY0)O1m`En_Gj7J~Gs%txTHlFZeHK}HEvs&5AMvP1Lvd@5qr z@qE5UC(&vfLB2DBMbh2}T$`0#i+9_E)c{qy<6N=r+sH^9N)3wKv1~$HxDr;~lt3Jo z3&nrK`zBI$TI(Ip$74}g@#1AQ8IOo~Y`}z9KJ@IuXTPp`0F^*$zaiLPqY#WM#93Sx z!@xf)=u<~6^)1kRn99W&;yq1F+Zg{@A!1exwXE;ezAO9u9KgzJ=jsQ>#*5P+FOP%( z>z+)#$v#%=xHT+AtMM0%Sh|dd^!u~|?n+>{?{|F9(2+-XZ^+IydWWAooAC0!wt|e& z0v0l`EsH%PE3oatX2Sa@G^r>A9CFFH@3-O7%n0U6Twlq$c0SlM8Y4};h_iAyhXBN_ z$leSyZi{$@qm+hfR*S3{(^Pq3uGV@>S>^hQF zwnGwOY=w=Du?&bHAZQXnhd1CU91sq$G2klRfrp?AFF=D1FF*q~e33AvI;zXrd$09p z=A3g(8sjoY=GssSMM>xEz1II{&dV6z_%6qB0Mfu^FFuLW(A7J;-^uNa(8y>N8n;v~ zd?GKf(*1_W=eMVDnDTuL31eq9Tmyz(7hs7l+mrU=6;TkeN^QNyKH$TE99YIuiJgrjYw6{*Wt9!W# zpM||5LH=B^Mz?iQ-gaqvS1juW63(jf0;eE@Yy!sg19kczCj3dV*Us}mYxRSF745wNuIrf)FwLo_GP}lra!6sLLUvT>~2erWDzoJw%rHhHjgK zzd#h;1FJ1sfywz4`gB|t!Z&)bg06KD4m6F`8HT_mIiMIW z=7&DyW%9wzF)yVQ)K(eBj)8NR`e|fsme)4qyrR_uDG>Uo=wqOiS4V2kMnvWLH;;%? zD8S%g;1rW}(UhhI!Eu}-8W?D8j_lTT;m<8Uv-K{H`@uGkZZ4I5rx+$02pKEUm_+pB ziGd+dJ-Z}>hN<$@fKrj1VB;U=1K7-758pvpmcsrv)B%vapLt0G)B{>$>x5p%$(01`ioB^H)8=YRk%^nrkOcIFw;^gm)^bifcbs&Yimd$;kiHAfjVb-Z)Bw8Wm(Y&t3XK_q#@+_MJ#&u}K6W=#>=A;M^5M}Qm1Rkvo z!k{L?2o~xr+ltZa1z`@6zZ2Ush*7ebH;b~WZ)xLAl+Uym3g-uHJg z?Ia=Z4kNE$e5qOmA@U1s4LJdOJMegHc>nS)gnRxD%d+uBnxj%4eoTb!i1Ck(8VX!JBN5mfS{`PK?+YkeC2^N%HTf-t9pK>*{$V4orK2tu& zvT#?jABSC#IR?30zT)NaiM>-WJIq=e=R&3^st7`ee3@4|SUDlyJDmnH@TL8a$t@yOi8$u z1+5cONC=^WLdKR~P&%Qfh8`07Sy4*D(N0$G0LYO!Cfo%UJDe323xUI`NmNm6!k08} zT1E~4(2N(;d*x2CR^*bcx^11q+*8i1uoAW4;$lihP;TGK;qP5Tsyp(MnWsb5I&$+p z%hAGg2PGgzv0UITI%7zIej)@d*dI9RA!t*OMrKFK9HzUJ1;@dSTNPQkWpRda;WIt= zC$_v;mf#SDlBR7(3);?zNjY^iIaT4o%`3=aLP}Jj&x~JcLnsyq5>3L~nkareVFZ)g zcL^e&xrL0@@&$94VJR2q!-_?X3W3-^aB%xm)Yu6*6{Hk^2(;rwJK3c4@%oAp2LdsH zJjR5*o=C*&nePX_h%qAeV@HgfBNxSgto4SYo_I*J+$tB52te=E#@K_x%=@GP8XYlA z>yz_5u)e<7{^7IwWOXMn$AAIM*}*{Vf>J~V1+rK?3^#7Ku=$)!G1j`v$;|~cI*#)& zMOuhl)P$7K>LJe?rs^Ev;PFl;&VTl&c&QQL-~H=2&L?sY=t}}dmAg?WFtuYT4<7d& zPvp$O&@lk=>ZDj4h$C8#tny+>Y#rEw;Sl3&=FuJJ$@e66

Jq5C-aTifz(E5Kg}P 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⋙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 LNkvXXu0mjfL3yYq diff --git a/src/gui/komodoku/board.png b/src/gui/komodoku/board.png deleted file mode 100644 index bd77ca419999b45f31af1dc6e91aedd4b0f53a9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5678 zcmeAS@N?(olHy`uVBq!ia0y~yV5|jU4mP03i^?5=K#C>Z(btiI;o6NW{t-q%zGR7O zL`iUdT1k0gQ7VIDN`6wRf@f}GdTLN=VoGJ<$y6H#2GIkaE{-7;w~|s45`LUF;Bq^t zA;G#h!G)oLAxVn2DG(xJ$)L~>k~F@M{Q-MU|kN+74koMTY6Tl7ztmwLMJ)o!OKl^U$ z_Acp(KNlC;OMPGb(5mQ>955ZVmqSZM7DiyHsQbko(uWx3jfTYH1W+nSVtMp`@j+w+V|BDHrVGdyBIgycp zse|>{kN^MeA1_$HP(t!Qe_1)7sJYT-Q19TK`{B|jM{I$qitjzNR2=QlI_X`4raI^*LDqz40|2~awwXxSpWxo89ZJ6T-G@yGywpilHk$+ diff --git a/src/gui/komodoku/sudoku_kmdlib.py b/src/gui/komodoku/sudoku_kmdlib.py deleted file mode 100644 index a2b2aa239..000000000 --- a/src/gui/komodoku/sudoku_kmdlib.py +++ /dev/null @@ -1,41 +0,0 @@ -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)))) - - From daf2e4bc3ab2a9d5806636e68bf68b6efcc91b93 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 22:26:11 -0400 Subject: [PATCH 22/31] Delete this TUI shite with fire --- src/tui/LICENSE | 21 - src/tui/README.md | 58 - src/tui/lib/logo.txt | 39 - src/tui/lib/rpclib.py | 129 -- src/tui/lib/tuilib.py | 1992 ------------------------------ src/tui/requirements.txt | 8 - src/tui/tui_assets.py | 67 - src/tui/tui_gateways_creation.py | 67 - src/tui/tui_gateways_usage.py | 96 -- src/tui/tui_marmara.py | 68 - src/tui/tui_oracles.py | 67 - src/tui/tui_rogue.py | 116 -- src/tui/tui_tetris.py | 96 -- 13 files changed, 2824 deletions(-) delete mode 100644 src/tui/LICENSE delete mode 100644 src/tui/README.md delete mode 100644 src/tui/lib/logo.txt delete mode 100644 src/tui/lib/rpclib.py delete mode 100755 src/tui/lib/tuilib.py delete mode 100644 src/tui/requirements.txt delete mode 100755 src/tui/tui_assets.py delete mode 100755 src/tui/tui_gateways_creation.py delete mode 100755 src/tui/tui_gateways_usage.py delete mode 100755 src/tui/tui_marmara.py delete mode 100755 src/tui/tui_oracles.py delete mode 100755 src/tui/tui_rogue.py delete mode 100755 src/tui/tui_tetris.py diff --git a/src/tui/LICENSE b/src/tui/LICENSE deleted file mode 100644 index 3300ef648..000000000 --- a/src/tui/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -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. diff --git a/src/tui/README.md b/src/tui/README.md deleted file mode 100644 index 61e733794..000000000 --- a/src/tui/README.md +++ /dev/null @@ -1,58 +0,0 @@ -# Komodo Cryptoconditons Terminal User Interfaces (aka TUIs) - -These tools creating for demonstration and partial automation of Komodo cryptoconditions modules testing. (RogueCC game, AssetsCC, OraclesCC, GatewaysCC, MarmaraCC, ...) - - -Developer installation (on Ubuntu 18.04) : - -Python3 required for execution: - -* `sudo apt-get install python3.6 python3-pip libgnutls28-dev` - -pip packages needed: - -* `pip3 install setuptools wheel slick-bitcoinrpc` -* or `pip3 install -r requirements.txt` - -Starting: - -# TUI for RogueCC - -If you're looking for player 3 in 1 (daemon + game + TUI) multiOS bundle - please check `releases` of this repo. - -`python3 rogue_tui.py` - -![alt text](https://i.imgur.com/gkcxMGt.png) - -# TUI for OraclesCC - -Have files uploader/downloader functionality - also there is a AWS branch for AWS certificates uploading demonstration - -`python3 oracles_cc_tui.py` - -![alt text](https://i.imgur.com/tfHwRqc.png) - -# TUI for GatewaysCC - -![alt text](https://i.imgur.com/c8DPfpp.png) - -`python3 gateways_creation_tui.py` - -`python3 gateways_usage_tui.py` - -At the moment raw version of manual gateway how-to guide can be found here: https://docs.komodoplatform.com/cc/contracts/gateways/scenarios/tutorial.html I advice to read it before you start use this tool to understand the flow. - -# TUI for MarmaraCC - -`python3 marmara_tui.py` - -![alt text](https://i.imgur.com/uonMWHl.png) - -# TUI for AssetsCC (not much finished) - -`python3 assets_cc_tui.py` - -Before execution be sure than daemon for needed AC up. - - - diff --git a/src/tui/lib/logo.txt b/src/tui/lib/logo.txt deleted file mode 100644 index 15ace1ad5..000000000 --- a/src/tui/lib/logo.txt +++ /dev/null @@ -1,39 +0,0 @@ -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 \ No newline at end of file diff --git a/src/tui/lib/rpclib.py b/src/tui/lib/rpclib.py deleted file mode 100644 index a79fc73d4..000000000 --- a/src/tui/lib/rpclib.py +++ /dev/null @@ -1,129 +0,0 @@ -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 diff --git a/src/tui/lib/tuilib.py b/src/tui/lib/tuilib.py deleted file mode 100755 index afb4fad63..000000000 --- a/src/tui/lib/tuilib.py +++ /dev/null @@ -1,1992 +0,0 @@ -from lib import rpclib -import json -import time -import re -import sys -import pickle -import platform -import os -import subprocess -import random -import signal -from slickrpc import Proxy -from binascii import hexlify -from binascii import unhexlify -from functools import partial -from shutil import copy - - -operating_system = platform.system() -if operating_system != 'Win64' and operating_system != 'Windows': - import readline - - -class CustomProxy(Proxy): - def __init__(self, - service_url=None, - service_port=None, - conf_file=None, - timeout=3000): - config = dict() - if conf_file: - config = slickrpc.ConfigObj(conf_file) - if service_url: - config.update(self.url_to_conf(service_url)) - if service_port: - config.update(rpcport=service_port) - elif not config.get('rpcport'): - config['rpcport'] = 7771 - self.conn = self.prepare_connection(config, timeout=timeout) - - -def colorize(string, color): - - colors = { - 'blue': '\033[94m', - 'magenta': '\033[95m', - 'green': '\033[92m', - 'red': '\033[91m' - } - if color not in colors: - return string - else: - return colors[color] + string + '\033[0m' - - -def rpc_connection_tui(): - # TODO: possible to save multiply entries from successfull sessions and ask user to choose then - while True: - restore_choice = input("Do you want to use connection details from previous session? [y/n]: ") - if restore_choice == "y": - try: - with open("connection.json", "r") as file: - connection_json = json.load(file) - rpc_user = connection_json["rpc_user"] - rpc_password = connection_json["rpc_password"] - rpc_port = connection_json["rpc_port"] - rpc_connection = rpclib.rpc_connect(rpc_user, rpc_password, int(rpc_port)) - except FileNotFoundError: - print(colorize("You do not have cached connection details. Please select n for connection setup", "red")) - break - elif restore_choice == "n": - rpc_user = input("Input your rpc user: ") - rpc_password = input("Input your rpc password: ") - rpc_port = input("Input your rpc port: ") - connection_details = {"rpc_user": rpc_user, - "rpc_password": rpc_password, - "rpc_port": rpc_port} - connection_json = json.dumps(connection_details) - with open("connection.json", "w+") as file: - file.write(connection_json) - rpc_connection = rpclib.rpc_connect(rpc_user, rpc_password, int(rpc_port)) - break - else: - print(colorize("Please input y or n", "red")) - return rpc_connection - - -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 == 'Win64' or 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(CustomProxy("http://%s:%s@127.0.0.1:%d"%(rpcuser, rpcpassword, int(rpcport)))) - - -def getinfo_tui(rpc_connection): - - info_raw = rpclib.getinfo(rpc_connection) - if isinstance(info_raw, dict): - for key in info_raw: - print("{}: {}".format(key, info_raw[key])) - input("Press [Enter] to continue...") - else: - print("Error!\n") - print(info_raw) - input("\nPress [Enter] to continue...") - - -def token_create_tui(rpc_connection): - - while True: - try: - name = input("Set your token name: ") - supply = input("Set your token supply: ") - description = input("Set your token description: ") - except KeyboardInterrupt: - break - else: - token_hex = rpclib.token_create(rpc_connection, name, supply, description) - if token_hex['result'] == "error": - print(colorize("\nSomething went wrong!\n", "pink")) - print(token_hex) - print("\n") - input("Press [Enter] to continue...") - break - else: - try: - token_txid = rpclib.sendrawtransaction(rpc_connection, - token_hex['hex']) - except KeyError: - print(token_txid) - print("Error") - input("Press [Enter] to continue...") - break - finally: - print(colorize("Token creation transaction broadcasted: " + token_txid, "green")) - file = open("tokens_list", "a") - file.writelines(token_txid + "\n") - file.close() - print(colorize("Entry added to tokens_list file!\n", "green")) - input("Press [Enter] to continue...") - break - - -def oracle_create_tui(rpc_connection): - - print(colorize("\nAvailiable data types:\n", "blue")) - oracles_data_types = ["Ihh -> height, blockhash, merkleroot\ns -> <256 char string\nS -> <65536 char string\nd -> <256 binary data\nD -> <65536 binary data", - "c -> 1 byte signed little endian number, C unsigned\nt -> 2 byte signed little endian number, T unsigned", - "i -> 4 byte signed little endian number, I unsigned\nl -> 8 byte signed little endian number, L unsigned", - "h -> 32 byte hash\n"] - for oracles_type in oracles_data_types: - print(str(oracles_type)) - while True: - try: - name = input("Set your oracle name: ") - description = input("Set your oracle description: ") - oracle_data_type = input("Set your oracle type (e.g. Ihh): ") - except KeyboardInterrupt: - break - else: - oracle_hex = rpclib.oracles_create(rpc_connection, name, description, oracle_data_type) - if oracle_hex['result'] == "error": - print(colorize("\nSomething went wrong!\n", "pink")) - print(oracle_hex) - print("\n") - input("Press [Enter] to continue...") - break - else: - try: - oracle_txid = rpclib.sendrawtransaction(rpc_connection, oracle_hex['hex']) - except KeyError: - print(oracle_txid) - print("Error") - input("Press [Enter] to continue...") - break - finally: - print(colorize("Oracle creation transaction broadcasted: " + oracle_txid, "green")) - file = open("oracles_list", "a") - file.writelines(oracle_txid + "\n") - file.close() - print(colorize("Entry added to oracles_list file!\n", "green")) - input("Press [Enter] to continue...") - break - - -def oracle_register_tui(rpc_connection): - #TODO: have an idea since blackjoker new RPC call - #grab all list and printout only or which owner match with node pubkey - try: - print(colorize("Oracles created from this instance by TUI: \n", "blue")) - with open("oracles_list", "r") as file: - for oracle in file: - print(oracle) - print(colorize('_' * 65, "blue")) - print("\n") - except FileNotFoundError: - print("Seems like a no oracles created from this instance yet\n") - pass - while True: - try: - oracle_id = input("Input txid of oracle you want to register to: ") - data_fee = input("Set publisher datafee (in satoshis): ") - except KeyboardInterrupt: - break - oracle_register_hex = rpclib.oracles_register(rpc_connection, oracle_id, data_fee) - if oracle_register_hex['result'] == "error": - print(colorize("\nSomething went wrong!\n", "pink")) - print(oracle_register_hex) - print("\n") - input("Press [Enter] to continue...") - break - else: - try: - oracle_register_txid = rpclib.sendrawtransaction(rpc_connection, oracle_register_hex['hex']) - except KeyError: - print(oracle_register_hex) - print("Error") - input("Press [Enter] to continue...") - break - else: - print(colorize("Oracle registration transaction broadcasted: " + oracle_register_txid, "green")) - input("Press [Enter] to continue...") - break - - -def oracle_subscription_utxogen(rpc_connection): - # TODO: have an idea since blackjoker new RPC call - # grab all list and printout only or which owner match with node pubkey - try: - print(colorize("Oracles created from this instance by TUI: \n", "blue")) - with open("oracles_list", "r") as file: - for oracle in file: - print(oracle) - print(colorize('_' * 65, "blue")) - print("\n") - except FileNotFoundError: - print("Seems like a no oracles created from this instance yet\n") - pass - while True: - try: - oracle_id = input("Input oracle ID you want to subscribe to: ") - #printout to fast copypaste publisher id - oracle_info = rpclib.oracles_info(rpc_connection, oracle_id) - publishers = 0 - print(colorize("\nPublishers registered for a selected oracle: \n", "blue")) - try: - for entry in oracle_info["registered"]: - publisher = entry["publisher"] - print(publisher + "\n") - publishers = publishers + 1 - print("Total publishers:{}".format(publishers)) - except (KeyError, ConnectionResetError): - print(colorize("Please re-check your input. Oracle txid seems not valid.", "red")) - pass - print(colorize('_' * 65, "blue")) - print("\n") - if publishers == 0: - print(colorize("This oracle have no publishers to subscribe.\n" - "Please register as an oracle publisher first and/or wait since registration transaciton mined!", "red")) - input("Press [Enter] to continue...") - break - publisher_id = input("Input oracle publisher id you want to subscribe to: ") - data_fee = input("Input subscription fee (in COINS!): ") - utxo_num = int(input("Input how many transactions you want to broadcast: ")) - except KeyboardInterrupt: - break - while utxo_num > 0: - while True: - oracle_subscription_hex = rpclib.oracles_subscribe(rpc_connection, oracle_id, publisher_id, data_fee) - oracle_subscription_txid = rpclib.sendrawtransaction(rpc_connection, oracle_subscription_hex['hex']) - mempool = rpclib.get_rawmempool(rpc_connection) - if oracle_subscription_txid in mempool: - break - else: - pass - print(colorize("Oracle subscription transaction broadcasted: " + oracle_subscription_txid, "green")) - utxo_num = utxo_num - 1 - input("Press [Enter] to continue...") - break - -def gateways_bind_tui(rpc_connection): - # main loop with keyboard interrupt handling - while True: - try: - while True: - try: - print(colorize("Tokens created from this instance by TUI: \n", "blue")) - with open("tokens_list", "r") as file: - for oracle in file: - print(oracle) - print(colorize('_' * 65, "blue")) - print("\n") - except FileNotFoundError: - print("Seems like a no oracles created from this instance yet\n") - pass - token_id = input("Input id of token you want to use in gw bind: ") - try: - token_name = rpclib.token_info(rpc_connection, token_id)["name"] - except KeyError: - print(colorize("Not valid tokenid. Please try again.", "red")) - input("Press [Enter] to continue...") - token_info = rpclib.token_info(rpc_connection, token_id) - print(colorize("\n{} token total supply: {}\n".format(token_id, token_info["supply"]), "blue")) - token_supply = input("Input supply for token binding: ") - try: - print(colorize("\nOracles created from this instance by TUI: \n", "blue")) - with open("oracles_list", "r") as file: - for oracle in file: - print(oracle) - print(colorize('_' * 65, "blue")) - print("\n") - except FileNotFoundError: - print("Seems like a no oracles created from this instance yet\n") - pass - oracle_id = input("Input id of oracle you want to use in gw bind: ") - try: - oracle_name = rpclib.oracles_info(rpc_connection, oracle_id)["name"] - except KeyError: - print(colorize("Not valid oracleid. Please try again.", "red")) - input("Press [Enter] to continue...") - while True: - coin_name = input("Input external coin ticker (binded oracle and token need to have same name!): ") - if token_name == oracle_name and token_name == coin_name: - break - else: - print(colorize("Token name, oracle name and external coin ticker should match!", "red")) - while True: - M = input("Input minimal amount of pubkeys needed for transaction confirmation (1 for non-multisig gw): ") - N = input("Input maximal amount of pubkeys needed for transaction confirmation (1 for non-multisig gw): ") - if (int(N) >= int(M)): - break - else: - print("Maximal amount of pubkeys should be more or equal than minimal. Please try again.") - pubkeys = [] - for i in range(int(N)): - pubkeys.append(input("Input pubkey {}: ".format(i+1))) - pubtype = input("Input pubtype of external coin: ") - p2shtype = input("Input p2shtype of external coin: ") - wiftype = input("Input wiftype of external coin: ") - args = [rpc_connection, token_id, oracle_id, coin_name, token_supply, M, N] - new_args = [str(pubtype), str(p2shtype), wiftype] - args = args + pubkeys + new_args - # broadcasting block - try: - gateways_bind_hex = rpclib.gateways_bind(*args) - except Exception as e: - print(e) - input("Press [Enter] to continue...") - break - try: - gateways_bind_txid = rpclib.sendrawtransaction(rpc_connection, gateways_bind_hex["hex"]) - except Exception as e: - print(e) - print(gateways_bind_hex) - input("Press [Enter] to continue...") - break - else: - print(colorize("Gateway bind transaction broadcasted: " + gateways_bind_txid, "green")) - file = open("gateways_list", "a") - file.writelines(gateways_bind_txid + "\n") - file.close() - print(colorize("Entry added to gateways_list file!\n", "green")) - input("Press [Enter] to continue...") - break - break - except KeyboardInterrupt: - break - -# temporary :trollface: custom connection function solution -# to have connection to KMD daemon and cache it in separate file - - -def rpc_kmd_connection_tui(): - while True: - restore_choice = input("Do you want to use KMD daemon connection details from previous session? [y/n]: ") - if restore_choice == "y": - try: - with open("connection_kmd.json", "r") as file: - connection_json = json.load(file) - rpc_user = connection_json["rpc_user"] - rpc_password = connection_json["rpc_password"] - rpc_port = connection_json["rpc_port"] - rpc_connection_kmd = rpclib.rpc_connect(rpc_user, rpc_password, int(rpc_port)) - try: - print(rpc_connection_kmd.getinfo()) - print(colorize("Successfully connected!\n", "green")) - input("Press [Enter] to continue...") - break - except Exception as e: - print(e) - print(colorize("NOT CONNECTED!\n", "red")) - input("Press [Enter] to continue...") - break - except FileNotFoundError: - print(colorize("You do not have cached KMD daemon connection details." - " Please select n for connection setup", "red")) - input("Press [Enter] to continue...") - elif restore_choice == "n": - rpc_user = input("Input your rpc user: ") - rpc_password = input("Input your rpc password: ") - rpc_port = input("Input your rpc port: ") - connection_details = {"rpc_user": rpc_user, - "rpc_password": rpc_password, - "rpc_port": rpc_port} - connection_json = json.dumps(connection_details) - with open("connection_kmd.json", "w+") as file: - file.write(connection_json) - rpc_connection_kmd = rpclib.rpc_connect(rpc_user, rpc_password, int(rpc_port)) - try: - print(rpc_connection_kmd.getinfo()) - print(colorize("Successfully connected!\n", "green")) - input("Press [Enter] to continue...") - break - except Exception as e: - print(e) - print(colorize("NOT CONNECTED!\n", "red")) - input("Press [Enter] to continue...") - break - else: - print(colorize("Please input y or n", "red")) - return rpc_connection_kmd - - -def z_sendmany_twoaddresses(rpc_connection, sendaddress, recepient1, amount1, recepient2, amount2): - str_sending_block = "[{{\"address\":\"{}\",\"amount\":{}}},{{\"address\":\"{}\",\"amount\":{}}}]".format(recepient1, amount1, recepient2, amount2) - sending_block = json.loads(str_sending_block) - operation_id = rpc_connection.z_sendmany(sendaddress,sending_block) - return operation_id - - -def operationstatus_to_txid(rpc_connection, zstatus): - str_sending_block = "[\"{}\"]".format(zstatus) - sending_block = json.loads(str_sending_block) - operation_json = rpc_connection.z_getoperationstatus(sending_block) - operation_dump = json.dumps(operation_json) - operation_dict = json.loads(operation_dump)[0] - txid = operation_dict['result']['txid'] - return txid - - -def gateways_send_kmd(rpc_connection): - # TODO: have to handle CTRL+C on text input - print(colorize("Please be carefull when input wallet addresses and amounts since all transactions doing in real KMD!", "pink")) - print("Your addresses with balances: ") - list_address_groupings = rpc_connection.listaddressgroupings() - for address in list_address_groupings: - print(str(address) + "\n") - sendaddress = input("Input address from which you transfer KMD: ") - recepient1 = input("Input address which belongs to pubkey which will receive tokens: ") - amount1 = 0.0001 - recepient2 = input("Input gateway deposit address: ") - file = open("deposits_list", "a") - #have to show here deposit addresses for gateways created by user - amount2 = input("Input how many KMD you want to deposit on this gateway: ") - operation = z_sendmany_twoaddresses(rpc_connection, sendaddress, recepient1, amount1, recepient2, amount2) - print("Operation proceed! " + str(operation) + " Let's wait 2 seconds to get txid") - # trying to avoid pending status of operation - time.sleep(2) - txid = operationstatus_to_txid(rpc_connection, operation) - file.writelines(txid + "\n") - file.close() - print(colorize("KMD Transaction ID: " + str(txid) + " Entry added to deposits_list file", "green")) - input("Press [Enter] to continue...") - - -def gateways_deposit_tui(rpc_connection_assetchain, rpc_connection_komodo): - while True: - bind_txid = input("Input your gateway bind txid: ") - coin_name = input("Input your external coin ticker (e.g. KMD): ") - coin_txid = input("Input your deposit txid: ") - dest_pub = input("Input pubkey which claim deposit: ") - amount = input("Input amount of your deposit: ") - height = rpc_connection_komodo.getrawtransaction(coin_txid, 1)["height"] - deposit_hex = rpc_connection_komodo.getrawtransaction(coin_txid, 1)["hex"] - claim_vout = "0" - proof_sending_block = "[\"{}\"]".format(coin_txid) - proof = rpc_connection_komodo.gettxoutproof(json.loads(proof_sending_block)) - deposit_hex = rpclib.gateways_deposit(rpc_connection_assetchain, bind_txid, str(height), coin_name, \ - coin_txid, claim_vout, deposit_hex, proof, dest_pub, amount) - print(deposit_hex) - deposit_txid = rpclib.sendrawtransaction(rpc_connection_assetchain, deposit_hex["hex"]) - print("Done! Gateways deposit txid is: " + deposit_txid + " Please not forget to claim your deposit!") - input("Press [Enter] to continue...") - break - - -def gateways_claim_tui(rpc_connection): - while True: - bind_txid = input("Input your gateway bind txid: ") - coin_name = input("Input your external coin ticker (e.g. KMD): ") - deposit_txid = input("Input your gatewaysdeposit txid: ") - dest_pub = input("Input pubkey which claim deposit: ") - amount = input("Input amount of your deposit: ") - claim_hex = rpclib.gateways_claim(rpc_connection, bind_txid, coin_name, deposit_txid, dest_pub, amount) - try: - claim_txid = rpclib.sendrawtransaction(rpc_connection, claim_hex["hex"]) - except Exception as e: - print(e) - print(claim_hex) - input("Press [Enter] to continue...") - break - else: - print("Succesfully claimed! Claim transaction id: " + claim_txid) - input("Press [Enter] to continue...") - break - - -def gateways_withdrawal_tui(rpc_connection): - while True: - bind_txid = input("Input your gateway bind txid: ") - coin_name = input("Input your external coin ticker (e.g. KMD): ") - withdraw_pub = input("Input pubkey to which you want to withdraw: ") - amount = input("Input amount of withdrawal: ") - withdraw_hex = rpclib.gateways_withdraw(rpc_connection, bind_txid, coin_name, withdraw_pub, amount) - withdraw_txid = rpclib.sendrawtransaction(rpc_connection, withdraw_hex["hex"]) - print(withdraw_txid) - input("Press [Enter] to continue...") - break - - -def print_mempool(rpc_connection): - while True: - mempool = rpclib.get_rawmempool(rpc_connection) - tx_counter = 0 - print(colorize("Transactions in mempool: \n", "magenta")) - for transaction in mempool: - print(transaction + "\n") - tx_counter = tx_counter + 1 - print("Total: " + str(tx_counter) + " transactions\n") - print("R + Enter to refresh list. E + Enter to exit menu." + "\n") - is_refresh = input("Choose your destiny: ") - if is_refresh == "R": - print("\n") - pass - elif is_refresh == "E": - print("\n") - break - else: - print("\nPlease choose R or E\n") - - -def print_tokens_list(rpc_connection): - # TODO: have to print it with tokeninfo to have sense - pass - - -def print_tokens_balances(rpc_connection): - # TODO: checking tokenbalance for each token from tokenlist and reflect non zero ones - pass - - -def hexdump(filename, chunk_size=1<<15): - data = "" - #add_spaces = partial(re.compile(b'(..)').sub, br'\1 ') - #write = getattr(sys.stdout, 'buffer', sys.stdout).write - with open(filename, 'rb') as file: - for chunk in iter(partial(file.read, chunk_size), b''): - data += str(hexlify(chunk).decode()) - return data - - -def convert_file_oracle_d(rpc_connection): - while True: - path = input("Input path to file you want to upload to oracle: ") - try: - hex_data = (hexdump(path, 1))[2:] - except Exception as e: - print(e) - print("Seems something goes wrong (I guess you've specified wrong path)!") - input("Press [Enter] to continue...") - break - else: - length = round(len(hex_data) / 2) - if length > 256: - print("Length: " + str(length) + " bytes") - print("File is too big for this app") - input("Press [Enter] to continue...") - break - else: - hex_length = format(length, '#04x')[2:] - data_for_oracle = str(hex_length) + hex_data - print("File hex representation: \n") - print(data_for_oracle + "\n") - print("Length: " + str(length) + " bytes") - print("File converted!") - new_oracle_hex = rpclib.oracles_create(rpc_connection, "tonyconvert", path, "d") - new_oracle_txid = rpclib.sendrawtransaction(rpc_connection, new_oracle_hex["hex"]) - time.sleep(0.5) - oracle_register_hex = rpclib.oracles_register(rpc_connection, new_oracle_txid, "10000") - oracle_register_txid = rpclib.sendrawtransaction(rpc_connection, oracle_register_hex["hex"]) - time.sleep(0.5) - oracle_subscribe_hex = rpclib.oracles_subscribe(rpc_connection, new_oracle_txid, rpclib.getinfo(rpc_connection)["pubkey"], "0.001") - oracle_subscribe_txid = rpclib.sendrawtransaction(rpc_connection, oracle_subscribe_hex["hex"]) - time.sleep(0.5) - while True: - mempool = rpclib.get_rawmempool(rpc_connection) - if oracle_subscribe_txid in mempool: - print("Waiting for oracle subscribtion tx to be mined" + "\n") - time.sleep(6) - pass - else: - break - oracles_data_hex = rpclib.oracles_data(rpc_connection, new_oracle_txid, data_for_oracle) - try: - oracle_data_txid = rpclib.sendrawtransaction(rpc_connection, oracles_data_hex["hex"]) - except Exception as e: - print(oracles_data_hex) - print(e) - print("Oracle created: " + str(new_oracle_txid)) - print("Data published: " + str(oracle_data_txid)) - input("Press [Enter] to continue...") - break - - -def convert_file_oracle_D(rpc_connection): - while True: - path = input("Input path to file you want to upload to oracle: ") - try: - hex_data = (hexdump(path, 1)) - except Exception as e: - print(e) - print("Seems something goes wrong (I guess you've specified wrong path)!") - input("Press [Enter] to continue...") - break - else: - length = round(len(hex_data) / 2) - # if length > 800000: - # print("Too big file size to upload for this version of program. Maximum size is 800KB.") - # input("Press [Enter] to continue...") - # break - if length > 8000: - # if file is more than 8000 bytes - slicing it to <= 8000 bytes chunks (16000 symbols = 8000 bytes) - data = [hex_data[i:i + 16000] for i in range(0, len(hex_data), 16000)] - chunks_amount = len(data) - # TODO: have to create oracle but subscribe this time chunks amount times to send whole file in same block - # TODO: 2 - on some point file will not fit block - have to find this point - # TODO: 3 way how I want to implement it first will keep whole file in RAM - have to implement some way to stream chunks to oracle before whole file readed - # TODO: have to "optimise" registration fee - # Maybe just check size first by something like a du ? - print("Length: " + str(length) + " bytes.\n Chunks amount: " + str(chunks_amount)) - new_oracle_hex = rpclib.oracles_create(rpc_connection, "tonyconvert_" + str(chunks_amount), path, "D") - new_oracle_txid = rpclib.sendrawtransaction(rpc_connection, new_oracle_hex["hex"]) - time.sleep(0.5) - oracle_register_hex = rpclib.oracles_register(rpc_connection, new_oracle_txid, "10000") - oracle_register_txid = rpclib.sendrawtransaction(rpc_connection, oracle_register_hex["hex"]) - # subscribe chunks_amount + 1 times, but lets limit our broadcasting 100 tx per block (800KB/block) - if chunks_amount > 100: - utxo_num = 101 - else: - utxo_num = chunks_amount - while utxo_num > 0: - while True: - oracle_subscription_hex = rpclib.oracles_subscribe(rpc_connection, new_oracle_txid, rpclib.getinfo(rpc_connection)["pubkey"], "0.001") - oracle_subscription_txid = rpclib.sendrawtransaction(rpc_connection, - oracle_subscription_hex['hex']) - mempool = rpclib.get_rawmempool(rpc_connection) - if oracle_subscription_txid in mempool: - break - else: - pass - print(colorize("Oracle subscription transaction broadcasted: " + oracle_subscription_txid, "green")) - utxo_num = utxo_num - 1 - # waiting for last broadcasted subscribtion transaction to be mined to be sure that money are on oracle balance - while True: - mempool = rpclib.get_rawmempool(rpc_connection) - if oracle_subscription_txid in mempool: - print("Waiting for oracle subscribtion tx to be mined" + "\n") - time.sleep(6) - pass - else: - break - print("Oracle preparation is finished. Oracle txid: " + new_oracle_txid) - # can publish data now - counter = 0 - for chunk in data: - hex_length_bigendian = format(round(len(chunk) / 2), '#06x')[2:] - # swap to get little endian length - a = hex_length_bigendian[2:] - b = hex_length_bigendian[:2] - hex_length = a + b - data_for_oracle = str(hex_length) + chunk - counter = counter + 1 - # print("Chunk number: " + str(counter) + "\n") - # print(data_for_oracle) - try: - oracles_data_hex = rpclib.oracles_data(rpc_connection, new_oracle_txid, data_for_oracle) - except Exception as e: - print(data_for_oracle) - print(e) - input("Press [Enter] to continue...") - break - # on broadcasting ensuring that previous one reached mempool before blast next one - while True: - mempool = rpclib.get_rawmempool(rpc_connection) - oracle_data_txid = rpclib.sendrawtransaction(rpc_connection, oracles_data_hex["hex"]) - #time.sleep(0.1) - if oracle_data_txid in mempool: - break - else: - pass - # blasting not more than 100 at once (so maximum capacity per block can be changed here) - # but keep in mind that registration UTXOs amount needs to be changed too ! - if counter % 100 == 0 and chunks_amount > 100: - while True: - mempool = rpclib.get_rawmempool(rpc_connection) - if oracle_data_txid in mempool: - print("Waiting for previous data chunks to be mined before send new ones" + "\n") - print("Sent " + str(counter) + " chunks from " + str(chunks_amount)) - time.sleep(6) - pass - else: - break - - print("Last baton: " + oracle_data_txid) - input("Press [Enter] to continue...") - break - # if file suits single oraclesdata just broadcasting it straight without any slicing - else: - hex_length_bigendian = format(length, '#06x')[2:] - # swap to get little endian length - a = hex_length_bigendian[2:] - b = hex_length_bigendian[:2] - hex_length = a + b - data_for_oracle = str(hex_length) + hex_data - print("File hex representation: \n") - print(data_for_oracle + "\n") - print("Length: " + str(length) + " bytes") - print("File converted!") - new_oracle_hex = rpclib.oracles_create(rpc_connection, "tonyconvert_" + "1", path, "D") - new_oracle_txid = rpclib.sendrawtransaction(rpc_connection, new_oracle_hex["hex"]) - time.sleep(0.5) - oracle_register_hex = rpclib.oracles_register(rpc_connection, new_oracle_txid, "10000") - oracle_register_txid = rpclib.sendrawtransaction(rpc_connection, oracle_register_hex["hex"]) - time.sleep(0.5) - oracle_subscribe_hex = rpclib.oracles_subscribe(rpc_connection, new_oracle_txid, rpclib.getinfo(rpc_connection)["pubkey"], "0.001") - oracle_subscribe_txid = rpclib.sendrawtransaction(rpc_connection, oracle_subscribe_hex["hex"]) - time.sleep(0.5) - while True: - mempool = rpclib.get_rawmempool(rpc_connection) - if oracle_subscribe_txid in mempool: - print("Waiting for oracle subscribtion tx to be mined" + "\n") - time.sleep(6) - pass - else: - break - oracles_data_hex = rpclib.oracles_data(rpc_connection, new_oracle_txid, data_for_oracle) - try: - oracle_data_txid = rpclib.sendrawtransaction(rpc_connection, oracles_data_hex["hex"]) - except Exception as e: - print(oracles_data_hex) - print(e) - input("Press [Enter] to continue...") - break - else: - print("Oracle created: " + str(new_oracle_txid)) - print("Data published: " + str(oracle_data_txid)) - input("Press [Enter] to continue...") - break - - -def get_files_list(rpc_connection): - - start_time = time.time() - oracles_list = rpclib.oracles_list(rpc_connection) - files_list = [] - for oracle_txid in oracles_list: - oraclesinfo_result = rpclib.oracles_info(rpc_connection, oracle_txid) - description = oraclesinfo_result['description'] - name = oraclesinfo_result['name'] - if name[0:12] == 'tonyconvert_': - new_file = '[' + name + ': ' + description + ']: ' + oracle_txid - files_list.append(new_file) - print("--- %s seconds ---" % (time.time() - start_time)) - return files_list - - -def display_files_list(rpc_connection): - print("Scanning oracles. Please wait...") - list_to_display = get_files_list(rpc_connection) - while True: - for file in list_to_display: - print(file + "\n") - input("Press [Enter] to continue...") - break - - -def files_downloader(rpc_connection): - while True: - display_files_list(rpc_connection) - print("\n") - oracle_id = input("Input oracle ID you want to download file from: ") - output_path = input("Input output path for downloaded file (name included) e.g. /home/test.txt: ") - oracle_info = rpclib.oracles_info(rpc_connection, oracle_id) - name = oracle_info['name'] - latest_baton_txid = oracle_info['registered'][0]['batontxid'] - if name[0:12] == 'tonyconvert_': - # downloading process here - chunks_amount = int(name[12:]) - data = rpclib.oracles_samples(rpc_connection, oracle_id, latest_baton_txid, str(chunks_amount))["samples"] - for chunk in reversed(data): - with open(output_path, 'ab+') as file: - file.write(unhexlify(chunk[0])) - print("I hope that file saved to " + output_path + "\n") - input("Press [Enter] to continue...") - break - - else: - print("I cant recognize file inside this oracle. I'm very sorry, boss.") - input("Press [Enter] to continue...") - break - - -def marmara_receive_tui(rpc_connection): - while True: - issuer_pubkey = input("Input pubkey of person who do you want to receive MARMARA from: ") - issuance_sum = input("Input amount of MARMARA you want to receive: ") - blocks_valid = input("Input amount of blocks for cheque matures: ") - try: - marmara_receive_txinfo = rpc_connection.marmarareceive(issuer_pubkey, issuance_sum, "MARMARA", blocks_valid) - marmara_receive_txid = rpc_connection.sendrawtransaction(marmara_receive_txinfo["hex"]) - print("Marmara receive txid broadcasted: " + marmara_receive_txid + "\n") - print(json.dumps(marmara_receive_txinfo, indent=4, sort_keys=True) + "\n") - with open("receive_txids.txt", 'a+') as file: - file.write(marmara_receive_txid + "\n") - file.write(json.dumps(marmara_receive_txinfo, indent=4, sort_keys=True) + "\n") - print("Transaction id is saved to receive_txids.txt file.") - input("Press [Enter] to continue...") - break - except Exception as e: - print(marmara_receive_txinfo) - print(e) - print("Something went wrong. Please check your input") - - -def marmara_issue_tui(rpc_connection): - while True: - receiver_pubkey = input("Input pubkey of person who do you want to issue MARMARA: ") - issuance_sum = input("Input amount of MARMARA you want to issue: ") - maturing_block = input("Input number of block on which issuance mature: ") - approval_txid = input("Input receiving request transaction id: ") - try: - marmara_issue_txinfo = rpc_connection.marmaraissue(receiver_pubkey, issuance_sum, "MARMARA", maturing_block, approval_txid) - marmara_issue_txid = rpc_connection.sendrawtransaction(marmara_issue_txinfo["hex"]) - print("Marmara issuance txid broadcasted: " + marmara_issue_txid + "\n") - print(json.dumps(marmara_issue_txinfo, indent=4, sort_keys=True) + "\n") - with open("issue_txids.txt", "a+") as file: - file.write(marmara_issue_txid + "\n") - file.write(json.dumps(marmara_issue_txinfo, indent=4, sort_keys=True) + "\n") - print("Transaction id is saved to issue_txids.txt file.") - input("Press [Enter] to continue...") - break - except Exception as e: - print(marmara_issue_txinfo) - print(e) - print("Something went wrong. Please check your input") - - -def marmara_creditloop_tui(rpc_connection): - while True: - loop_txid = input("Input transaction ID of credit loop you want to get info about: ") - try: - marmara_creditloop_info = rpc_connection.marmaracreditloop(loop_txid) - print(json.dumps(marmara_creditloop_info, indent=4, sort_keys=True) + "\n") - input("Press [Enter] to continue...") - break - except Exception as e: - print(marmara_creditloop_info) - print(e) - print("Something went wrong. Please check your input") - - -def marmara_settlement_tui(rpc_connection): - while True: - loop_txid = input("Input transaction ID of credit loop to make settlement: ") - try: - marmara_settlement_info = rpc_connection.marmarasettlement(loop_txid) - marmara_settlement_txid = rpc_connection.sendrawtransaction(marmara_settlement_info["hex"]) - print("Loop " + loop_txid + " succesfully settled!\nSettlement txid: " + marmara_settlement_txid) - with open("settlement_txids.txt", "a+") as file: - file.write(marmara_settlement_txid + "\n") - file.write(json.dumps(marmara_settlement_info, indent=4, sort_keys=True) + "\n") - print("Transaction id is saved to settlement_txids.txt file.") - input("Press [Enter] to continue...") - break - except Exception as e: - print(marmara_settlement_info) - print(e) - print("Something went wrong. Please check your input") - input("Press [Enter] to continue...") - break - - -def marmara_lock_tui(rpc_connection): - while True: - amount = input("Input amount of coins you want to lock for settlement and staking: ") - unlock_height = input("Input height on which coins should be unlocked: ") - try: - marmara_lock_info = rpc_connection.marmaralock(amount, unlock_height) - marmara_lock_txid = rpc_connection.sendrawtransaction(marmara_lock_info["hex"]) - with open("lock_txids.txt", "a+") as file: - file.write(marmara_lock_txid + "\n") - file.write(json.dumps(marmara_lock_info, indent=4, sort_keys=True) + "\n") - print("Transaction id is saved to lock_txids.txt file.") - input("Press [Enter] to continue...") - break - except Exception as e: - print(e) - print("Something went wrong. Please check your input") - input("Press [Enter] to continue...") - break - - -def marmara_info_tui(rpc_connection): - while True: - firstheight = input("Input first height (default 0): ") - if not firstheight: - firstheight = "0" - lastheight = input("Input last height (default current (0) ): ") - if not lastheight: - lastheight = "0" - minamount = input("Input min amount (default 0): ") - if not minamount: - minamount = "0" - maxamount = input("Input max amount (default 0): ") - if not maxamount: - maxamount = "0" - issuerpk = input("Optional. Input issuer public key: ") - try: - if issuerpk: - marmara_info = rpc_connection.marmarainfo(firstheight, lastheight, minamount, maxamount, "MARMARA", issuerpk) - else: - marmara_info = rpc_connection.marmarainfo(firstheight, lastheight, minamount, maxamount) - print(json.dumps(marmara_info, indent=4, sort_keys=True) + "\n") - input("Press [Enter] to continue...") - break - except Exception as e: - print(marmara_info) - print(e) - print("Something went wrong. Please check your input") - input("Press [Enter] to continue...") - break - - -def rogue_game_info(rpc_connection, game_txid): - game_info_arg = '"' + "[%22" + game_txid + "%22]" + '"' - game_info = rpc_connection.cclib("gameinfo", "17", game_info_arg) - return game_info - - -def rogue_game_register(rpc_connection, game_txid, player_txid = False): - if player_txid: - registration_info_arg = '"' + "[%22" + game_txid + "%22,%22" + player_txid + "%22]" + '"' - else: - registration_info_arg = '"' + "[%22" + game_txid + "%22]" + '"' - registration_info = rpc_connection.cclib("register", "17", registration_info_arg) - return registration_info - - -def rogue_pending(rpc_connection): - rogue_pending_list = rpc_connection.cclib("pending", "17") - return rogue_pending_list - - -def rogue_bailout(rpc_connection, game_txid): - bailout_info_arg = '"' + "[%22" + game_txid + "%22]" + '"' - bailout_info = rpc_connection.cclib("bailout", "17", bailout_info_arg) - return bailout_info - - -def rogue_highlander(rpc_connection, game_txid): - highlander_info_arg = '"' + "[%22" + game_txid + "%22]" + '"' - highlander_info = rpc_connection.cclib("highlander", "17", highlander_info_arg) - return highlander_info - - -def rogue_players_list(rpc_connection): - rogue_players_list = rpc_connection.cclib("players", "17") - return rogue_players_list - - -def rogue_player_info(rpc_connection, playertxid): - player_info_arg = '"' + "[%22" + playertxid + "%22]" + '"' - player_info = rpc_connection.cclib("playerinfo", "17", player_info_arg) - return player_info - - -def rogue_extract(rpc_connection, game_txid, pubkey): - extract_info_arg = '"' + "[%22" + game_txid + "%22,%22" + pubkey + "%22]" + '"' - extract_info = rpc_connection.cclib("extract", "17", extract_info_arg) - return extract_info - - -def rogue_keystrokes(rpc_connection, game_txid, keystroke): - rogue_keystrokes_arg = '"' + "[%22" + game_txid + "%22,%22" + keystroke + "%22]" + '"' - keystroke_info = rpc_connection.cclib("keystrokes", "17", rogue_keystrokes_arg) - return keystroke_info - - -def print_multiplayer_games_list(rpc_connection): - while True: - pending_list = rogue_pending(rpc_connection) - multiplayer_pending_list = [] - for game in pending_list["pending"]: - if rogue_game_info(rpc_connection, game)["maxplayers"] > 1: - multiplayer_pending_list.append(game) - print("Multiplayer games availiable to join: \n") - for active_multiplayer_game in multiplayer_pending_list: - game_info = rogue_game_info(rpc_connection, active_multiplayer_game) - print(colorize("\n================================\n", "green")) - print("Game txid: " + game_info["gametxid"]) - print("Game buyin: " + str(game_info["buyin"])) - print("Game height: " + str(game_info["gameheight"])) - print("Start height: " + str(game_info["start"])) - print("Alive players: " + str(game_info["alive"])) - print("Registered players: " + str(game_info["numplayers"])) - print("Max players: " + str(game_info["maxplayers"])) - print(colorize("\n***\n", "blue")) - print("Players in game:") - for player in game_info["players"]: - print("Slot: " + str(player["slot"])) - if "baton" in player.keys(): - print("Baton: " + str(player["baton"])) - if "tokenid" in player.keys(): - print("Tokenid: " + str(player["tokenid"])) - print("Is mine?: " + str(player["ismine"])) - print(colorize("\nR + Enter - refresh list.\nE + Enter - to the game choice.\nCTRL + C - back to main menu", "blue")) - is_refresh = input("Choose your destiny: ") - if is_refresh == "R": - print("\n") - pass - elif is_refresh == "E": - print("\n") - break - else: - print("\nPlease choose R or E\n") - - -def rogue_newgame_singleplayer(rpc_connection, is_game_a_rogue=True): - try: - if is_game_a_rogue: - new_game_txid = rpc_connection.cclib("newgame", "17", "[1]")["txid"] - print("New singleplayer training game succesfully created. txid: " + new_game_txid) - while True: - mempool = rpc_connection.getrawmempool() - if new_game_txid in mempool: - print(colorize("Waiting for game transaction to be mined", "blue")) - time.sleep(5) - else: - print(colorize("Game transaction is mined", "green")) - break - else: - pending_games = rpc_connection.cclib("pending", "17")["pending"] - new_game_txid = random.choice(pending_games) - if is_game_a_rogue: - players_list = rogue_players_list(rpc_connection) - if len(players_list["playerdata"]) > 0: - print_players_list(rpc_connection) - while True: - is_choice_needed = input("Do you want to choose a player for this game? [y/n] ") - if is_choice_needed == "y": - player_txid = input("Please input player txid: ") - newgame_regisration_txid = rogue_game_register(rpc_connection, new_game_txid, player_txid)["txid"] - break - elif is_choice_needed == "n": - set_warriors_name(rpc_connection) - newgame_regisration_txid = rogue_game_register(rpc_connection, new_game_txid)["txid"] - break - else: - print("Please choose y or n !") - else: - print("No players available to select") - input("Press [Enter] to continue...") - newgame_regisration_txid = rogue_game_register(rpc_connection, new_game_txid)["txid"] - else: - newgame_regisration_txid = rogue_game_register(rpc_connection, new_game_txid)["txid"] - while True: - mempool = rpc_connection.getrawmempool() - if newgame_regisration_txid in mempool: - print(colorize("Waiting for registration transaction to be mined", "blue")) - time.sleep(5) - else: - print(colorize("Registration transaction is mined", "green")) - break - game_info = rogue_game_info(rpc_connection, new_game_txid) - start_time = time.time() - while True: - if is_game_a_rogue: - subprocess.call(["../cc/rogue/rogue", str(game_info["seed"]), str(game_info["gametxid"])]) - else: - subprocess.call(["../cc/games/tetris", str(game_info["seed"]), str(game_info["gametxid"])]) - time_elapsed = time.time() - start_time - if time_elapsed > 1: - break - else: - print("Game less than 1 second. Trying to start again") - time.sleep(1) - game_end_height = int(rpc_connection.getinfo()["blocks"]) - while True: - current_height = int(rpc_connection.getinfo()["blocks"]) - height_difference = current_height - game_end_height - if height_difference == 0: - print(current_height) - print(game_end_height) - print(colorize("Waiting for next block before bailout", "blue")) - time.sleep(5) - else: - break - #print("\nKeystrokes of this game:\n") - #time.sleep(0.5) - while True: - keystrokes_rpc_responses = find_game_keystrokes_in_log(new_game_txid)[1::2] - if len(keystrokes_rpc_responses) < 1: - print("No keystrokes broadcasted yet. Let's wait 5 seconds") - time.sleep(5) - else: - break - #print(keystrokes_rpc_responses) - for keystroke in keystrokes_rpc_responses: - json_keystroke = json.loads(keystroke)["result"] - if "status" in json_keystroke.keys() and json_keystroke["status"] == "error": - while True: - print("Trying to re-brodcast keystroke") - keystroke_rebroadcast = rogue_keystrokes(rpc_connection, json_keystroke["gametxid"], json_keystroke["keystrokes"]) - if "txid" in keystroke_rebroadcast.keys(): - print("Keystroke broadcasted! txid: " + keystroke_rebroadcast["txid"]) - break - else: - print("Let's try again in 5 seconds") - time.sleep(5) - # waiting for last keystroke confirmation here - last_keystroke_json = json.loads(keystrokes_rpc_responses[-1]) - while True: - while True: - try: - rpc_connection.sendrawtransaction(last_keystroke_json["result"]["hex"]) - except Exception as e: - pass - try: - confirmations_amount = rpc_connection.getrawtransaction(last_keystroke_json["result"]["txid"], 1)["confirmations"] - break - except Exception as e: - print(e) - print("Let's wait a little bit more") - time.sleep(5) - pass - if confirmations_amount < 1: - print("Last keystroke not confirmed yet! Let's wait a little") - time.sleep(10) - else: - print("Last keystroke confirmed!") - break - while True: - print("\nExtraction info:\n") - extraction_info = rogue_extract(rpc_connection, new_game_txid, rpc_connection.getinfo()["pubkey"]) - if extraction_info["status"] == "error": - print(colorize("Your warrior died or no any information about game was saved on blockchain", "red")) - print("If warrior was alive - try to wait a little (choose n to wait for a next block). If he is dead - you can bailout now (choose y).") - else: - print("Current game state:") - print("Game txid: " + extraction_info["gametxid"]) - print("Information about game saved on chain: " + extraction_info["extracted"]) - print("\n") - is_bailout_needed = input("Do you want to make bailout now [y] or wait for one more block [n]? [y/n]: ") - if is_bailout_needed == "y": - bailout_info = rogue_bailout(rpc_connection, new_game_txid) - if is_game_a_rogue: - while True: - try: - confirmations_amount = rpc_connection.getrawtransaction(bailout_info["txid"], 1)["confirmations"] - break - except Exception as e: - print(e) - print("Bailout not on blockchain yet. Let's wait a little bit more") - time.sleep(20) - pass - break - elif is_bailout_needed == "n": - game_end_height = int(rpc_connection.getinfo()["blocks"]) - while True: - current_height = int(rpc_connection.getinfo()["blocks"]) - height_difference = current_height - game_end_height - if height_difference == 0: - print(current_height) - print(game_end_height) - print(colorize("Waiting for next block before bailout", "blue")) - time.sleep(5) - else: - break - else: - print("Please choose y or n !") - print(bailout_info) - print("\nGame is finished!\n") - bailout_txid = bailout_info["txid"] - input("Press [Enter] to continue...") - except Exception as e: - print("Something went wrong.") - print(e) - input("Press [Enter] to continue...") - - -def play_multiplayer_game(rpc_connection): - # printing list of user active multiplayer games - active_games_list = rpc_connection.cclib("games", "17")["games"] - active_multiplayer_games_list = [] - for game in active_games_list: - gameinfo = rogue_game_info(rpc_connection, game) - if gameinfo["maxplayers"] > 1: - active_multiplayer_games_list.append(gameinfo) - games_counter = 0 - for active_multiplayer_game in active_multiplayer_games_list: - games_counter = games_counter + 1 - is_ready_to_start = False - try: - active_multiplayer_game["seed"] - is_ready_to_start = True - except Exception as e: - pass - print(colorize("\n================================\n", "green")) - print("Game txid: " + active_multiplayer_game["gametxid"]) - print("Game buyin: " + str(active_multiplayer_game["buyin"])) - if is_ready_to_start: - print(colorize("Ready for start!", "green")) - else: - print(colorize("Not ready for start yet, wait until start height!", "red")) - print("Game height: " + str(active_multiplayer_game["gameheight"])) - print("Start height: " + str(active_multiplayer_game["start"])) - print("Alive players: " + str(active_multiplayer_game["alive"])) - print("Registered players: " + str(active_multiplayer_game["numplayers"])) - print("Max players: " + str(active_multiplayer_game["maxplayers"])) - print(colorize("\n***\n", "blue")) - print("Players in game:") - for player in active_multiplayer_game["players"]: - print("Slot: " + str(player["slot"])) - print("Baton: " + str(player["baton"])) - print("Tokenid: " + str(player["tokenid"])) - print("Is mine?: " + str(player["ismine"])) - # asking user if he want to start any of them - while True: - start_game = input("\nDo you want to start any of your pendning multiplayer games?[y/n]: ") - if start_game == "y": - new_game_txid = input("Input txid of game which you want to start: ") - game_info = rogue_game_info(rpc_connection, new_game_txid) - try: - start_time = time.time() - while True: - subprocess.call(["cc/rogue/rogue", str(game_info["seed"]), str(game_info["gametxid"])]) - time_elapsed = time.time() - start_time - if time_elapsed > 1: - break - else: - print("Game less than 1 second. Trying to start again") - time.sleep(1) - except Exception as e: - print("Maybe game isn't ready for start yet or your input was not correct, sorry.") - input("Press [Enter] to continue...") - break - game_end_height = int(rpc_connection.getinfo()["blocks"]) - while True: - current_height = int(rpc_connection.getinfo()["blocks"]) - height_difference = current_height - game_end_height - if height_difference == 0: - print(current_height) - print(game_end_height) - print(colorize("Waiting for next block before bailout or highlander", "blue")) - time.sleep(5) - else: - break - while True: - keystrokes_rpc_responses = find_game_keystrokes_in_log(new_game_txid)[1::2] - if len(keystrokes_rpc_responses) < 1: - print("No keystrokes broadcasted yet. Let's wait 5 seconds") - time.sleep(5) - else: - break - for keystroke in keystrokes_rpc_responses: - json_keystroke = json.loads(keystroke)["result"] - if "status" in json_keystroke.keys() and json_keystroke["status"] == "error": - while True: - print("Trying to re-brodcast keystroke") - keystroke_rebroadcast = rogue_keystrokes(rpc_connection, json_keystroke["gametxid"], - json_keystroke["keystrokes"]) - if "txid" in keystroke_rebroadcast.keys(): - print("Keystroke broadcasted! txid: " + keystroke_rebroadcast["txid"]) - break - else: - print("Let's try again in 5 seconds") - time.sleep(5) - last_keystroke_json = json.loads(keystrokes_rpc_responses[-1]) - while True: - while True: - try: - confirmations_amount = rpc_connection.getrawtransaction(last_keystroke_json["result"]["txid"], 1)["confirmations"] - break - except Exception as e: - print(e) - print("Let's wait a little bit more") - rpc_connection.sendrawtransaction(last_keystroke_json["result"]["hex"]) - time.sleep(5) - pass - if confirmations_amount < 2: - print("Last keystroke not confirmed yet! Let's wait a little") - time.sleep(10) - else: - print("Last keystroke confirmed!") - break - while True: - print("\nExtraction info:\n") - extraction_info = rogue_extract(rpc_connection, new_game_txid, rpc_connection.getinfo()["pubkey"]) - if extraction_info["status"] == "error": - print(colorize("Your warrior died or no any information about game was saved on blockchain", "red")) - print("If warrior was alive - try to wait a little (choose n to wait for a next block). If he is dead - you can bailout now (choose y).") - else: - print("Current game state:") - print("Game txid: " + extraction_info["gametxid"]) - print("Information about game saved on chain: " + extraction_info["extracted"]) - print("\n") - is_bailout_needed = input( - "Do you want to make bailout now [y] or wait for one more block [n]? [y/n]: ") - if is_bailout_needed == "y": - if game_info["alive"] > 1: - bailout_info = rogue_bailout(rpc_connection, new_game_txid) - try: - bailout_txid = bailout_info["txid"] - print(bailout_info) - print("\nGame is finished!\n") - input("Press [Enter] to continue...") - break - except Exception: - highlander_info = rogue_highlander(rpc_connection, new_game_txid) - highlander_info = highlander_info["txid"] - print(highlander_info) - print("\nGame is finished!\n") - input("Press [Enter] to continue...") - break - else: - highlander_info = rogue_highlander(rpc_connection, new_game_txid) - if 'error' in highlander_info.keys() and highlander_info["error"] == 'numplayers != maxplayers': - bailout_info = rogue_bailout(rpc_connection, new_game_txid) - print(bailout_info) - print("\nGame is finished!\n") - input("Press [Enter] to continue...") - break - else: - print(highlander_info) - print("\nGame is finished!\n") - input("Press [Enter] to continue...") - break - elif is_bailout_needed == "n": - game_end_height = int(rpc_connection.getinfo()["blocks"]) - while True: - current_height = int(rpc_connection.getinfo()["blocks"]) - height_difference = current_height - game_end_height - if height_difference == 0: - print(current_height) - print(game_end_height) - print(colorize("Waiting for next block before bailout", "blue")) - time.sleep(5) - else: - break - break - break - if start_game == "n": - print("As you wish!") - input("Press [Enter] to continue...") - break - else: - print(colorize("Choose y or n!", "red")) - - -def rogue_newgame_multiplayer(rpc_connection): - while True: - max_players = input("Input game max. players (>1): ") - if int(max_players) > 1: - break - else: - print("Please re-check your input") - input("Press [Enter] to continue...") - while True: - buyin = input("Input game buyin (>0.001): ") - if float(buyin) > 0.001: - break - else: - print("Please re-check your input") - input("Press [Enter] to continue...") - try: - new_game_txid = rpc_connection.cclib("newgame", "17", '"[' + max_players + "," + buyin + ']"')["txid"] - print(colorize("New multiplayer game succesfully created. txid: " + new_game_txid, "green")) - input("Press [Enter] to continue...") - except Exception as e: - print("Something went wrong.") - print(e) - input("Press [Enter] to continue...") - - -def rogue_join_multiplayer_game(rpc_connection): - while True: - try: - print_multiplayer_games_list(rpc_connection) - # TODO: optional player data txid (print players you have and ask if you want to choose one) - game_txid = input("Input txid of game you want to join: ") - try: - while True: - print_players_list(rpc_connection) - is_choice_needed = input("Do you want to choose a player for this game? [y/n] ") - if is_choice_needed == "y": - player_txid = input("Please input player txid: ") - newgame_regisration_txid = rogue_game_register(rpc_connection, game_txid, player_txid)["txid"] - break - elif is_choice_needed == "n": - set_warriors_name(rpc_connection) - newgame_regisration_txid = rogue_game_register(rpc_connection, game_txid)["txid"] - break - else: - print("Please choose y or n !") - except Exception as e: - print("Something went wrong. Maybe you're trying to register on game twice or don't have enough funds to pay buyin.") - print(e) - input("Press [Enter] to continue...") - break - print(colorize("Succesfully registered.", "green")) - while True: - mempool = rpc_connection.getrawmempool() - if newgame_regisration_txid in mempool: - print(colorize("Waiting for registration transaction to be mined", "blue")) - time.sleep(5) - else: - print(colorize("Registration transaction is mined", "green")) - break - print(newgame_regisration_txid) - input("Press [Enter] to continue...") - break - except KeyboardInterrupt: - break - - -def print_players_list(rpc_connection): - players_list = rogue_players_list(rpc_connection) - print(colorize("\nYou own " + str(players_list["numplayerdata"]) + " warriors\n", "blue")) - warrior_counter = 0 - for player in players_list["playerdata"]: - warrior_counter = warrior_counter + 1 - player_data = rogue_player_info(rpc_connection, player)["player"] - print(colorize("\n================================\n","green")) - print("Warrior " + str(warrior_counter)) - print("Name: " + player_data["pname"] + "\n") - print("Player txid: " + player_data["playertxid"]) - print("Token txid: " + player_data["tokenid"]) - print("Hitpoints: " + str(player_data["hitpoints"])) - print("Strength: " + str(player_data["strength"])) - print("Level: " + str(player_data["level"])) - print("Experience: " + str(player_data["experience"])) - print("Dungeon Level: " + str(player_data["dungeonlevel"])) - print("Chain: " + player_data["chain"]) - print(colorize("\nInventory:\n","blue")) - for item in player_data["pack"]: - print(item) - print("\nTotal packsize: " + str(player_data["packsize"]) + "\n") - input("Press [Enter] to continue...") - - -def sell_warrior(rpc_connection): - print(colorize("Your brave warriors: \n", "blue")) - print_players_list(rpc_connection) - print("\n") - while True: - need_sell = input("Do you want to place order to sell any? [y/n]: ") - if need_sell == "y": - playertxid = input("Input playertxid of warrior you want to sell: ") - price = input("Input price (in ROGUE coins) you want to sell warrior for: ") - try: - tokenid = rogue_player_info(rpc_connection, playertxid)["player"]["tokenid"] - except Exception as e: - print(e) - print("Something went wrong. Be careful with input next time.") - input("Press [Enter] to continue...") - break - token_ask_raw = rpc_connection.tokenask("1", tokenid, price) - try: - token_ask_txid = rpc_connection.sendrawtransaction(token_ask_raw["hex"]) - except Exception as e: - print(e) - print(token_ask_raw) - print("Something went wrong. Be careful with input next time.") - input("Press [Enter] to continue...") - break - print(colorize("Ask succesfully placed. Ask txid is: " + token_ask_txid, "green")) - input("Press [Enter] to continue...") - break - if need_sell == "n": - print("As you wish!") - input("Press [Enter] to continue...") - break - else: - print(colorize("Choose y or n!", "red")) - - -#TODO: have to combine into single scanner with different cases -def is_warrior_alive(rpc_connection, warrior_txid): - warrior_alive = False - raw_transaction = rpc_connection.getrawtransaction(warrior_txid, 1) - for vout in raw_transaction["vout"]: - if vout["value"] == 0.00000001 and rpc_connection.gettxout(raw_transaction["txid"], vout["n"]): - warrior_alive = True - return warrior_alive - - -def warriors_scanner(rpc_connection): - start_time = time.time() - token_list = rpc_connection.tokenlist() - my_warriors_list = rogue_players_list(rpc_connection) - warriors_list = {} - for token in token_list: - player_info = rogue_player_info(rpc_connection, token) - if "status" in player_info and player_info["status"] == "error": - pass - elif player_info["player"]["playertxid"] in my_warriors_list["playerdata"]: - pass - elif not is_warrior_alive(rpc_connection, player_info["player"]["playertxid"]): - pass - else: - warriors_list[token] = player_info["player"] - print("--- %s seconds ---" % (time.time() - start_time)) - return warriors_list - - -def warriors_scanner_for_rating(rpc_connection): - print("It can take some time") - token_list = rpc_connection.tokenlist() - my_warriors_list = rogue_players_list(rpc_connection) - actual_playerids = [] - warriors_list = {} - for token in token_list: - player_info = rogue_player_info(rpc_connection, token) - if "status" in player_info and player_info["status"] == "error": - pass - else: - while True: - if "batontxid" in player_info["player"].keys(): - player_info = rogue_player_info(rpc_connection, player_info["player"]["batontxid"]) - else: - actual_playerids.append(player_info["player"]["playertxid"]) - break - for player_id in actual_playerids: - player_info = rogue_player_info(rpc_connection, player_id) - if not is_warrior_alive(rpc_connection, player_info["player"]["playertxid"]): - pass - else: - warriors_list[player_id] = player_info["player"] - return warriors_list - - -def warriors_scanner_for_dex(rpc_connection): - start_time = time.time() - token_list = rpc_connection.tokenlist() - my_warriors_list = rogue_players_list(rpc_connection) - warriors_list = {} - for token in token_list: - player_info = rogue_player_info(rpc_connection, token) - if "status" in player_info and player_info["status"] == "error": - pass - elif player_info["player"]["tokenid"] in my_warriors_list["playerdata"]: - pass - else: - warriors_list[token] = player_info["player"] - print("--- %s seconds ---" % (time.time() - start_time)) - return warriors_list - - -def print_warrior_list(rpc_connection): - players_list = warriors_scanner(rpc_connection) - print(colorize("All warriors on ROGUE chain: \n", "blue")) - warrior_counter = 0 - for player in players_list: - warrior_counter = warrior_counter + 1 - player_data = rogue_player_info(rpc_connection, player)["player"] - print(colorize("\n================================\n","green")) - print("Warrior " + str(warrior_counter)) - print("Name: " + player_data["pname"] + "\n") - print("Player txid: " + player_data["playertxid"]) - print("Token txid: " + player_data["tokenid"]) - print("Hitpoints: " + str(player_data["hitpoints"])) - print("Strength: " + str(player_data["strength"])) - print("Level: " + str(player_data["level"])) - print("Experience: " + str(player_data["experience"])) - print("Dungeon Level: " + str(player_data["dungeonlevel"])) - print("Chain: " + player_data["chain"]) - print(colorize("\nInventory:\n","blue")) - for item in player_data["pack"]: - print(item) - print("\nTotal packsize: " + str(player_data["packsize"]) + "\n") - input("Press [Enter] to continue...") - - -def place_bid_on_warriror(rpc_connection): - warriors_list = print_warrior_list(rpc_connection) - # TODO: have to drop my warriors or at least print my warriors ids - while True: - need_buy = input("Do you want to place order to buy some warrior? [y/n]: ") - if need_buy == "y": - playertxid = input("Input playertxid of warrior you want to place bid for: ") - price = input("Input price (in ROGUE coins) you want to buy warrior for: ") - tokenid = rogue_player_info(rpc_connection, playertxid)["player"]["tokenid"] - token_bid_raw = rpc_connection.tokenbid("1", tokenid, price) - try: - token_bid_txid = rpc_connection.sendrawtransaction(token_bid_raw["hex"]) - except Exception as e: - print(e) - print(token_bid_raw) - print("Something went wrong. Be careful with input next time.") - input("Press [Enter] to continue...") - break - print(colorize("Bid succesfully placed. Bid txid is: " + token_bid_txid, "green")) - input("Press [Enter] to continue...") - break - if need_buy == "n": - print("As you wish!") - input("Press [Enter] to continue...") - break - else: - print(colorize("Choose y or n!", "red")) - - -def check_incoming_bids(rpc_connection): - # TODO: have to scan for warriors which are in asks as well - players_list = rogue_players_list(rpc_connection) - incoming_orders = [] - for player in players_list["playerdata"]: - token_id = rogue_player_info(rpc_connection, player)["player"]["tokenid"] - orders = rpc_connection.tokenorders(token_id) - if len(orders) > 0: - for order in orders: - if order["funcid"] == "b": - incoming_orders.append(order) - return incoming_orders - - -def print_icoming_bids(rpc_connection): - incoming_bids = check_incoming_bids(rpc_connection) - for bid in incoming_bids: - print("Recieved bid for warrior " + bid["tokenid"]) - player_data = rogue_player_info(rpc_connection, bid["tokenid"])["player"] - print(colorize("\n================================\n", "green")) - print("Name: " + player_data["pname"] + "\n") - print("Player txid: " + player_data["playertxid"]) - print("Token txid: " + player_data["tokenid"]) - print("Hitpoints: " + str(player_data["hitpoints"])) - print("Strength: " + str(player_data["strength"])) - print("Level: " + str(player_data["level"])) - print("Experience: " + str(player_data["experience"])) - print("Dungeon Level: " + str(player_data["dungeonlevel"])) - print("Chain: " + player_data["chain"]) - print(colorize("\nInventory:\n", "blue")) - for item in player_data["pack"]: - print(item) - print("\nTotal packsize: " + str(player_data["packsize"]) + "\n") - print(colorize("\n================================\n", "blue")) - print("Order info: \n") - print("Bid txid: " + bid["txid"]) - print("Price: " + str(bid["price"]) + "\n") - if len(incoming_bids) == 0: - print(colorize("There is no any incoming orders!", "blue")) - input("Press [Enter] to continue...") - else: - while True: - want_to_sell = input("Do you want to fill any incoming bid? [y/n]: ") - if want_to_sell == "y": - bid_txid = input("Input bid txid you want to fill: ") - for bid in incoming_bids: - if bid_txid == bid["txid"]: - tokenid = bid["tokenid"] - fill_sum = bid["totalrequired"] - fillbid_hex = rpc_connection.tokenfillbid(tokenid, bid_txid, str(fill_sum)) - try: - fillbid_txid = rpc_connection.sendrawtransaction(fillbid_hex["hex"]) - except Exception as e: - print(e) - print(fillbid_hex) - print("Something went wrong. Be careful with input next time.") - input("Press [Enter] to continue...") - break - print(colorize("Warrior succesfully sold. Txid is: " + fillbid_txid, "green")) - input("Press [Enter] to continue...") - break - if want_to_sell == "n": - print("As you wish!") - input("Press [Enter] to continue...") - break - else: - print(colorize("Choose y or n!", "red")) - - -def find_warriors_asks(rpc_connection): - warriors_list = warriors_scanner_for_dex(rpc_connection) - warriors_asks = [] - for player in warriors_list: - orders = rpc_connection.tokenorders(player) - if len(orders) > 0: - for order in orders: - if order["funcid"] == "s": - warriors_asks.append(order) - for ask in warriors_asks: - print(colorize("\n================================\n", "green")) - print("Warrior selling on marketplace: " + ask["tokenid"]) - player_data = rogue_player_info(rpc_connection, ask["tokenid"])["player"] - print("Name: " + player_data["pname"] + "\n") - print("Player txid: " + player_data["playertxid"]) - print("Token txid: " + player_data["tokenid"]) - print("Hitpoints: " + str(player_data["hitpoints"])) - print("Strength: " + str(player_data["strength"])) - print("Level: " + str(player_data["level"])) - print("Experience: " + str(player_data["experience"])) - print("Dungeon Level: " + str(player_data["dungeonlevel"])) - print("Chain: " + player_data["chain"]) - print(colorize("\nInventory:\n", "blue")) - for item in player_data["pack"]: - print(item) - print("\nTotal packsize: " + str(player_data["packsize"]) + "\n") - print(colorize("Order info: \n", "red")) - print("Ask txid: " + ask["txid"]) - print("Price: " + str(ask["price"]) + "\n") - while True: - want_to_buy = input("Do you want to buy any warrior? [y/n]: ") - if want_to_buy == "y": - ask_txid = input("Input asktxid which you want to fill: ") - for ask in warriors_asks: - if ask_txid == ask["txid"]: - tokenid = ask["tokenid"] - try: - fillask_raw = rpc_connection.tokenfillask(tokenid, ask_txid, "1") - except Exception as e: - print("Something went wrong. Be careful with input next time.") - input("Press [Enter] to continue...") - break - try: - fillask_txid = rpc_connection.sendrawtransaction(fillask_raw["hex"]) - except Exception as e: - print(e) - print(fillask_raw) - print("Something went wrong. Be careful with input next time.") - input("Press [Enter] to continue...") - break - print(colorize("Warrior succesfully bought. Txid is: " + fillask_txid, "green")) - input("Press [Enter] to continue...") - break - if want_to_buy == "n": - print("As you wish!") - input("Press [Enter] to continue...") - break - else: - print(colorize("Choose y or n!", "red")) - - -def warriors_orders_check(rpc_connection): - my_orders_list = rpc_connection.mytokenorders("17") - warriors_orders = {} - for order in my_orders_list: - player_info = rogue_player_info(rpc_connection, order["tokenid"]) - if "status" in player_info and player_info["status"] == "error": - pass - else: - warriors_orders[order["tokenid"]] = order - bids_list = [] - asks_list = [] - for order in warriors_orders: - if warriors_orders[order]["funcid"] == "s": - asks_list.append(warriors_orders[order]) - else: - bids_list.append(order) - print(colorize("\nYour asks:\n", "blue")) - print(colorize("\n********************************\n", "red")) - for ask in asks_list: - print("txid: " + ask["txid"]) - print("Price: " + ask["price"]) - print("Warrior tokenid: " + ask["tokenid"]) - print(colorize("\n================================\n", "green")) - print("Warrior selling on marketplace: " + ask["tokenid"]) - player_data = rogue_player_info(rpc_connection, ask["tokenid"])["player"] - print("Name: " + player_data["pname"] + "\n") - print("Player txid: " + player_data["playertxid"]) - print("Token txid: " + player_data["tokenid"]) - print("Hitpoints: " + str(player_data["hitpoints"])) - print("Strength: " + str(player_data["strength"])) - print("Level: " + str(player_data["level"])) - print("Experience: " + str(player_data["experience"])) - print("Dungeon Level: " + str(player_data["dungeonlevel"])) - print("Chain: " + player_data["chain"]) - print(colorize("\nInventory:\n", "blue")) - for item in player_data["pack"]: - print(item) - print("\nTotal packsize: " + str(player_data["packsize"]) + "\n") - print(colorize("\n================================\n", "green")) - print(colorize("\nYour bids:\n", "blue")) - print(colorize("\n********************************\n", "red")) - for bid in bids_list: - print("txid: " + bid["txid"]) - print("Price: " + bid["price"]) - print("Warrior tokenid: " + bid["tokenid"]) - print(colorize("\n================================\n", "green")) - print("Warrior selling on marketplace: " + bid["tokenid"]) - player_data = rogue_player_info(rpc_connection, bid["tokenid"])["player"] - print("Name: " + player_data["pname"] + "\n") - print("Player txid: " + player_data["playertxid"]) - print("Token txid: " + player_data["tokenid"]) - print("Hitpoints: " + str(player_data["hitpoints"])) - print("Strength: " + str(player_data["strength"])) - print("Level: " + str(player_data["level"])) - print("Experience: " + str(player_data["experience"])) - print("Dungeon Level: " + str(player_data["dungeonlevel"])) - print("Chain: " + player_data["chain"]) - print(colorize("\nInventory:\n", "blue")) - for item in player_data["pack"]: - print(item) - print("\nTotal packsize: " + str(player_data["packsize"]) + "\n") - print(colorize("\n================================\n", "green")) - while True: - need_order_change = input("Do you want to cancel any of your orders? [y/n]: ") - if need_order_change == "y": - while True: - ask_or_bid = input("Do you want cancel ask or bid? [a/b]: ") - if ask_or_bid == "a": - ask_txid = input("Input txid of ask you want to cancel: ") - warrior_tokenid = input("Input warrior token id for this ask: ") - try: - ask_cancellation_hex = rpc_connection.tokencancelask(warrior_tokenid, ask_txid) - ask_cancellation_txid = rpc_connection.sendrawtransaction(ask_cancellation_hex["hex"]) - except Exception as e: - print(colorize("Please re-check your input!", "red")) - print(colorize("Ask succefully cancelled. Cancellation txid: " + ask_cancellation_txid, "green")) - break - if ask_or_bid == "b": - bid_txid = input("Input txid of bid you want to cancel: ") - warrior_tokenid = input("Input warrior token id for this bid: ") - try: - bid_cancellation_hex = rpc_connection.tokencancelbid(warrior_tokenid, bid_txid) - bid_cancellation_txid = rpc_connection.sendrawtransaction(bid_cancellation_hex["hex"]) - except Exception as e: - print(colorize("Please re-check your input!", "red")) - print(colorize("Bid succefully cancelled. Cancellation txid: " + bid_cancellation_txid, "green")) - break - else: - print(colorize("Choose a or b!", "red")) - input("Press [Enter] to continue...") - break - if need_order_change == "n": - print("As you wish!") - input("Press [Enter] to continue...") - break - else: - print(colorize("Choose y or n!", "red")) - - -def set_warriors_name(rpc_connection): - warriors_name = input("What warrior name do you want for legends and tales about your brave adventures?: ") - warrior_name_arg = '"' + "[%22" + warriors_name + "%22]" + '"' - set_name_status = rpc_connection.cclib("setname", "17", warrior_name_arg) - print(colorize("Warrior name succesfully set", "green")) - print("Result: " + set_name_status["result"]) - print("Name: " + set_name_status["pname"]) - input("Press [Enter] to continue...") - - -def top_warriors_rating(rpc_connection): - start_time = time.time() - warriors_list = warriors_scanner_for_rating(rpc_connection) - warriors_exp = {} - for warrior in warriors_list: - warriors_exp[warrior] = warriors_list[warrior]["experience"] - warriors_exp_sorted = {} - temp = [(k, warriors_exp[k]) for k in sorted(warriors_exp, key=warriors_exp.get, reverse=True)] - for k,v in temp: - warriors_exp_sorted[k] = v - counter = 0 - for experienced_warrior in warriors_exp_sorted: - if counter < 20: - counter = counter + 1 - print("\n" + str(counter) + " place.") - print(colorize("\n================================\n", "blue")) - player_data = rogue_player_info(rpc_connection, experienced_warrior)["player"] - print("Name: " + player_data["pname"] + "\n") - print("Player txid: " + player_data["playertxid"]) - print("Token txid: " + player_data["tokenid"]) - print("Hitpoints: " + str(player_data["hitpoints"])) - print("Strength: " + str(player_data["strength"])) - print("Level: " + str(player_data["level"])) - print("Experience: " + str(player_data["experience"])) - print("Dungeon Level: " + str(player_data["dungeonlevel"])) - print("Chain: " + player_data["chain"]) - print("--- %s seconds ---" % (time.time() - start_time)) - input("Press [Enter] to continue...") - - -def exit(): - sys.exit() - - -def warrior_trasnfer(rpc_connection): - print(colorize("Your brave warriors: \n", "blue")) - print_players_list(rpc_connection) - print("\n") - while True: - need_transfer = input("Do you want to transfer any warrior? [y/n]: ") - if need_transfer == "y": - warrior_tokenid = input("Input warrior tokenid: ") - recepient_pubkey = input("Input recepient pubkey: ") - try: - token_transfer_hex = rpc_connection.tokentransfer(warrior_tokenid, recepient_pubkey, "1") - token_transfer_txid = rpc_connection.sendrawtransaction(token_transfer_hex["hex"]) - except Exception as e: - print(e) - print("Something went wrong. Please be careful with your input next time!") - input("Press [Enter] to continue...") - break - print(colorize("Warrior succesfully transferred! Transfer txid: " + token_transfer_txid, "green")) - input("Press [Enter] to continue...") - break - if need_transfer == "n": - print("As you wish!") - input("Press [Enter] to continue...") - break - else: - print(colorize("Choose y or n!", "red")) - - -def check_if_config_is_here(rpc_connection, assetchain_name): - config_name = assetchain_name + ".conf" - if os.path.exists(config_name): - print(colorize("Config is already in daemon folder", "green")) - else: - if operating_system == 'Darwin': - path_to_config = os.environ['HOME'] + '/Library/Application Support/Komodo/' + assetchain_name + '/' + config_name - elif operating_system == 'Linux': - path_to_config = os.environ['HOME'] + '/.komodo/' + assetchain_name + '/' + config_name - elif operating_system == 'Win64' or operating_system == 'Windows': - path_to_config = '%s/komodo/' + assetchain_name + '/' + config_name % os.environ['APPDATA'] - try: - copy(path_to_config, os.getcwd()) - except Exception as e: - print(e) - print("Can't copy config to current daemon directory automatically by some reason.") - print("Please copy it manually. It's locating here: " + path_to_config) - - -def find_game_keystrokes_in_log(gametxid): - - operating_system = platform.system() - if operating_system == 'Win64' or operating_system == 'Windows': - p1 = subprocess.Popen(["type", "keystrokes.log"], stdout=subprocess.PIPE, shell=True) - p2 = subprocess.Popen(["findstr", gametxid], stdin=p1.stdout, stdout=subprocess.PIPE, shell=True) - else: - p1 = subprocess.Popen(["cat", "keystrokes.log"], stdout=subprocess.PIPE) - p2 = subprocess.Popen(["grep", gametxid], stdin=p1.stdout, stdout=subprocess.PIPE) - p1.stdout.close() - output = p2.communicate()[0] - keystrokes_log_for_game = bytes.decode(output).split("\n") - return keystrokes_log_for_game - - -def check_if_tx_in_mempool(rpc_connection, txid): - while True: - mempool = rpc_connection.getrawmempool() - if txid in mempool: - print(colorize("Waiting for " + txid + " transaction to be mined", "blue")) - time.sleep(5) - else: - print(colorize("Transaction is mined", "green")) - break diff --git a/src/tui/requirements.txt b/src/tui/requirements.txt deleted file mode 100644 index 734da529c..000000000 --- a/src/tui/requirements.txt +++ /dev/null @@ -1,8 +0,0 @@ -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 diff --git a/src/tui/tui_assets.py b/src/tui/tui_assets.py deleted file mode 100755 index 091484a40..000000000 --- a/src/tui/tui_assets.py +++ /dev/null @@ -1,67 +0,0 @@ -#!/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() - diff --git a/src/tui/tui_gateways_creation.py b/src/tui/tui_gateways_creation.py deleted file mode 100755 index 7bb489c7f..000000000 --- a/src/tui/tui_gateways_creation.py +++ /dev/null @@ -1,67 +0,0 @@ -#!/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() diff --git a/src/tui/tui_gateways_usage.py b/src/tui/tui_gateways_usage.py deleted file mode 100755 index 0c989e3af..000000000 --- a/src/tui/tui_gateways_usage.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/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() diff --git a/src/tui/tui_marmara.py b/src/tui/tui_marmara.py deleted file mode 100755 index cfe628890..000000000 --- a/src/tui/tui_marmara.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/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() diff --git a/src/tui/tui_oracles.py b/src/tui/tui_oracles.py deleted file mode 100755 index fec874d35..000000000 --- a/src/tui/tui_oracles.py +++ /dev/null @@ -1,67 +0,0 @@ -#!/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() diff --git a/src/tui/tui_rogue.py b/src/tui/tui_rogue.py deleted file mode 100755 index 9942369e2..000000000 --- a/src/tui/tui_rogue.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/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() diff --git a/src/tui/tui_tetris.py b/src/tui/tui_tetris.py deleted file mode 100755 index 3c42d4daa..000000000 --- a/src/tui/tui_tetris.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/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() From e3371f1d1ae3fa7ff8e091c1478e5c55716d2b22 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 22:27:34 -0400 Subject: [PATCH 23/31] Remove fiat-cli --- src/fiat-cli | 9 --------- 1 file changed, 9 deletions(-) delete mode 100755 src/fiat-cli diff --git a/src/fiat-cli b/src/fiat-cli deleted file mode 100755 index 49332696a..000000000 --- a/src/fiat-cli +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -args="$@" -komodo_cli='./komodo-cli' - -./listassetchains | while read chain; do - echo $chain - $komodo_cli --ac_name=$chain $args -done From 15138dc3cefa677ea0e289e95c6f36a513755031 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 22:41:55 -0400 Subject: [PATCH 24/31] This script is useless for Hush --- src/notarystats.py | 98 ---------------------------------------------- 1 file changed, 98 deletions(-) delete mode 100755 src/notarystats.py diff --git a/src/notarystats.py b/src/notarystats.py deleted file mode 100755 index 49713b6c3..000000000 --- a/src/notarystats.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python3 -""" -sudo apt-get install python3-dev -sudo apt-get install python3 libgnutls28-dev libssl-dev -sudo apt-get install python3-pip -pip3 install setuptools -pip3 install wheel -pip3 install base58 slick-bitcoinrpc -./notarystats.py ------------------------------------------------- -""" -import platform -import os -import re -import sys -import time -import pprint -from slickrpc import Proxy - -# fucntion to define rpc_connection -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)))) - - -rpc = def_credentials('KMD') -pp = pprint.PrettyPrinter(indent=2) - -notarynames = [ "0dev1_jl777", "0dev2_kolo", "0dev3_kolo", "0dev4_decker_AR", "a-team_SH", "artik_AR", "artik_EU", "artik_NA", "artik_SH", "badass_EU", "badass_NA", "batman_AR", "batman_SH", "ca333", "chainmakers_EU", "chainmakers_NA", "chainstrike_SH", "cipi_AR", "cipi_NA", "crackers_EU", "crackers_NA", "dwy_EU", "emmanux_SH", "etszombi_EU", "fullmoon_AR", "fullmoon_NA", "fullmoon_SH", "goldenman_EU", "indenodes_AR", "indenodes_EU", "indenodes_NA", "indenodes_SH", "jackson_AR", "jeezy_EU", "karasugoi_NA", "komodoninja_EU", "komodoninja_SH", "komodopioneers_SH", "libscott_SH", "lukechilds_AR", "madmax_AR", "meshbits_AR", "meshbits_SH", "metaphilibert_AR", "metaphilibert_SH", "patchkez_SH", "pbca26_NA", "peer2cloud_AR", "peer2cloud_SH", "polycryptoblog_NA", "hyper_AR", "hyper_EU", "hyper_SH", "hyper_NA", "popcornbag_AR", "popcornbag_NA", "alien_AR", "alien_EU", "thegaltmines_NA", "titomane_AR", "titomane_EU", "titomane_SH", "webworker01_NA", "xrobesx_NA" ] -notaries = 64 * [0] - -startheight = 821657 #Second time filter for assetchains (block 821657) for KMD its 814000 -stopheight = 1307200 -for i in range(startheight,stopheight): - ret = rpc.getNotarisationsForBlock(i) - KMD = ret['KMD'] - if len(KMD) > 0: - for obj in KMD: - #for now skip KMD for this. As official stats are from BTC chain - # this can be reversed to !== to count KMD numbers :) - if obj['chain'] == 'KMD': - continue; - for notary in obj['notaries']: - notaries[notary] = notaries[notary] + 1 - -i = 0 -SH = [] -AR = [] -EU = [] -NA = [] -for notary in notaries: - tmpnotary = {} - tmpnotary['node'] = notarynames[i] - tmpnotary['ac_count'] = notary - if notarynames[i].endswith('SH'): - SH.append(tmpnotary) - elif notarynames[i].endswith('AR'): - AR.append(tmpnotary) - elif notarynames[i].endswith('EU'): - EU.append(tmpnotary) - elif notarynames[i].endswith('NA'): - NA.append(tmpnotary) - i = i + 1 - -regions = {} -regions['SH'] = sorted(SH, key=lambda k: k['ac_count'], reverse=True) -regions['AR'] = sorted(AR, key=lambda k: k['ac_count'], reverse=True) -regions['EU'] = sorted(EU, key=lambda k: k['ac_count'], reverse=True) -regions["NA"] = sorted(NA, key=lambda k: k['ac_count'], reverse=True) - -pp.pprint(regions) From f510034fc3903b3c48f4b60e8d874a68c99e7f59 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 22:49:49 -0400 Subject: [PATCH 25/31] Reduce our JoinSplitty-ness --- src/zcash/JoinSplit.cpp | 11 ----------- src/zcash/JoinSplit.hpp | 13 ++++--------- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/src/zcash/JoinSplit.cpp b/src/zcash/JoinSplit.cpp index f4d558459..f4690f5dd 100644 --- a/src/zcash/JoinSplit.cpp +++ b/src/zcash/JoinSplit.cpp @@ -5,21 +5,10 @@ #include "prf.h" #include "sodium.h" -#include "zcash/util.h" - #include - -#include -#include -#include #include -#include "tinyformat.h" -#include "sync.h" -#include "amount.h" #include "librustzcash.h" -#include "streams.h" -#include "version.h" namespace libzcash { diff --git a/src/zcash/JoinSplit.hpp b/src/zcash/JoinSplit.hpp index 8193ba1bf..ceac79fe4 100644 --- a/src/zcash/JoinSplit.hpp +++ b/src/zcash/JoinSplit.hpp @@ -11,7 +11,6 @@ #include "Note.hpp" #include "IncrementalMerkleTree.hpp" #include "NoteEncryption.hpp" - #include "uint256.h" #include "uint252.h" @@ -27,19 +26,15 @@ static constexpr size_t GROTH_PROOF_SIZE = ( typedef std::array GrothProof; typedef boost::variant SproutProof; -class JSInput { -}; +class JSInput { }; -class JSOutput { -}; +class JSOutput { }; template -class JoinSplit { -}; +class JoinSplit { }; } -typedef libzcash::JoinSplit ZCJoinSplit; +typedef libzcash::JoinSplit ZCJoinSplit; #endif // ZC_JOINSPLIT_H_ From 5a9178b8976d75d62d98bbcc8fa1561a9e5049e1 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 22:52:43 -0400 Subject: [PATCH 26/31] Get rid of STAKEDMIN protocol version --- src/main.cpp | 2 -- src/version.h | 1 - 2 files changed, 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 2bf771e4c..c53a25a70 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7262,8 +7262,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, uint64_t nNonce = 1; int nVersion; // use temporary for version, don't set version number until validated as connected int minVersion = MIN_PEER_PROTO_VERSION; - if ( is_STAKED(ASSETCHAINS_SYMBOL) != 0 ) - minVersion = STAKEDMIN_PEER_PROTO_VERSION; vRecv >> nVersion >> pfrom->nServices >> nTime >> addrMe; if (nVersion == 10300) nVersion = 300; diff --git a/src/version.h b/src/version.h index 68d538615..a8098bded 100644 --- a/src/version.h +++ b/src/version.h @@ -35,7 +35,6 @@ static const int GETHEADERS_VERSION = 31800; //! disconnect from peers older than this proto version static const int MIN_PEER_PROTO_VERSION = 170007; -static const int STAKEDMIN_PEER_PROTO_VERSION = 170007; //! nTime field added to CAddress, starting with this version; //! if possible, avoid requesting addresses nodes older than this From af7e1f8a167fd8cd6731a3a0a9308104493d82f8 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 22:53:16 -0400 Subject: [PATCH 27/31] We are like, from the future --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index a8098bded..4e3c5417c 100644 --- a/src/version.h +++ b/src/version.h @@ -25,7 +25,7 @@ * network protocol versioning */ -static const int PROTOCOL_VERSION = 170009; +static const int PROTOCOL_VERSION = 170010; //! initial proto version, to be increased after version/verack negotiation static const int INIT_PROTO_VERSION = 209; From f78c0d2ce310a0c644a5b5b6ee36104c7165c198 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 22:53:47 -0400 Subject: [PATCH 28/31] We don't even want to think about talking to old nodes --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 4e3c5417c..9c18c44e8 100644 --- a/src/version.h +++ b/src/version.h @@ -34,7 +34,7 @@ static const int INIT_PROTO_VERSION = 209; static const int GETHEADERS_VERSION = 31800; //! disconnect from peers older than this proto version -static const int MIN_PEER_PROTO_VERSION = 170007; +static const int MIN_PEER_PROTO_VERSION = 170009; //! nTime field added to CAddress, starting with this version; //! if possible, avoid requesting addresses nodes older than this From 4c1a9a9df7411a08c0c2d8ea5ee3c9c80052fe26 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 23:42:22 -0400 Subject: [PATCH 29/31] Delete a git script we don't need --- resolve.sh | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100755 resolve.sh diff --git a/resolve.sh b/resolve.sh deleted file mode 100755 index 548e71dee..000000000 --- a/resolve.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -for f in $(git diff --name-only --diff-filter=U | cat); do - echo "Resolve conflict in $f ..." - git checkout --theirs $f -done - -for f in $(git diff --name-only --diff-filter=U | cat); do - echo "Adding file $f ..." - git add $f -done - From 2189e462f13fd6bba11d3c88fce58aac796bb4e6 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 25 Oct 2020 23:45:29 -0400 Subject: [PATCH 30/31] Imagine thinking this constant shite jl777 vomits is decent code, lulz --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b65cc58ef..badffc2b1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -43,7 +43,7 @@ If you don't see your idea listed, and you think it can contribute to Hush, do o ## Style guide -Don't write shitty code. +Don't write shitty code. Try to avoid emulating jl777 code style, which is like a rabbit donkey smoked bath salts with nothing to read but a K+R C book. ## Setting up your environment From 5c2ab33a6be7ad1c4d7b2b9257326935ddce3aea Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 26 Oct 2020 00:02:58 -0400 Subject: [PATCH 31/31] This script is not used --- makeReleaseMac.sh | 72 ----------------------------------------------- 1 file changed, 72 deletions(-) delete mode 100755 makeReleaseMac.sh diff --git a/makeReleaseMac.sh b/makeReleaseMac.sh deleted file mode 100755 index 171ccb43f..000000000 --- a/makeReleaseMac.sh +++ /dev/null @@ -1,72 +0,0 @@ -#!/bin/bash -# Copyright ? various authors too lazy to put a copyright header -# Copyright 2019 The Hush Developers - -PACKAGE_DIR="$@" -mkdir ${PACKAGE_DIR} -echo "Created ${PACKAGE_DIR}" - -binaries=("komodo-cli" "komodod") -alllibs=() -for binary in "${binaries[@]}"; -do - echo "Processing binary ${binary}" - # do the work in the destination directory - cp src/${binary} ${PACKAGE_DIR} - # find the dylibs to copy for komodod - DYLIBS=`otool -L ${PACKAGE_DIR}/${binary} | grep "/usr/local" | awk -F' ' '{ print $1 }'` - echo "copying ${DYLIBS} to ${PACKAGE_DIR}" - # copy the dylibs to the srcdir - for dylib in ${DYLIBS}; do cp -rf ${dylib} ${PACKAGE_DIR}; done -done - -libraries=("libgcc_s.1.dylib" "libgomp.1.dylib" "libidn2.0.dylib" "libstdc++.6.dylib") - -for binary in "${libraries[@]}"; -do - echo "Processing binary ${binary}" - # find the dylibs to copy for komodod - DYLIBS=`otool -L ${PACKAGE_DIR}/${binary} | grep "/usr/local" | awk -F' ' '{ print $1 }'` - echo "copying ${DYLIBS} to ${PACKAGE_DIR}" - # copy the dylibs to the srcdir - for dylib in ${DYLIBS}; do cp -rf ${dylib} ${PACKAGE_DIR}; alllibs+=(${dylib}); done -done - -indirectlibraries=("libintl.8.dylib" "libunistring.2.dylib") - -for binary in "${indirectlibraries[@]}"; -do - echo "Processing binary ${binary}" - # Need to undo this for the dylibs when we are done - chmod 755 src/${binary} - # find the dylibs to copy for komodod - DYLIBS=`otool -L ${PACKAGE_DIR}/${binary} | grep "/usr/local" | awk -F' ' '{ print $1 }'` - echo "copying indirect ${DYLIBS} to ${PACKAGE_DIR}" - # copy the dylibs to the dest dir - for dylib in ${DYLIBS}; do cp -rf ${dylib} ${PACKAGE_DIR}; alllibs+=(${dylib}); done -done - -for binary in "${binaries[@]}"; -do - echo "Processing binary ${binary}" - # modify komodod to point to dylibs - echo "modifying ${binary} to use local libraries" - for dylib in "${alllibs[@]}" - do - echo "Next lib is ${dylib} " - install_name_tool -change ${dylib} @executable_path/`basename ${dylib}` ${PACKAGE_DIR}/${binary} - done - chmod +x ${PACKAGE_DIR}/${binary} -done - -for binary in "${libraries[@]}"; -do - echo "Processing binary ${binary}" - # modify libraries to point to dylibs - echo "modifying ${binary} to use local libraries" - for dylib in "${alllibs[@]}" - do - echo "Next lib is ${dylib} " - install_name_tool -change ${dylib} @executable_path/`basename ${dylib}` ${PACKAGE_DIR}/${binary} - done -done