Merge branch 'FSM' of https://github.com/jl777/komodo into jl777-FSM

This commit is contained in:
blackjok3r
2019-02-26 09:42:51 +08:00
79 changed files with 13960 additions and 653 deletions

View File

@@ -139,7 +139,7 @@ int32_t komodo_nextheight();
int32_t CCgetspenttxid(uint256 &spenttxid,int32_t &vini,int32_t &height,uint256 txid,int32_t vout);
void CCclearvars(struct CCcontract_info *cp);
UniValue CClib(struct CCcontract_info *cp,char *method,cJSON *params);
UniValue CClib(struct CCcontract_info *cp,char *method,char *jsonstr);
UniValue CClib_info(struct CCcontract_info *cp);
CBlockIndex *komodo_blockindex(uint256 hash);
CBlockIndex *komodo_chainactive(int32_t height);

38
src/cc/Makefile_rogue Normal file
View File

@@ -0,0 +1,38 @@
SHELL = /bin/sh
CC = gcc
CC_DARWIN = g++-6
CC_WIN = x86_64-w64-mingw32-gcc-posix
CFLAGS_DARWIN = -DBUILD_ROGUE -std=c++11 -arch x86_64 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -Wl,-undefined -Wl,dynamic_lookup -Wno-write-strings -shared -dynamiclib
CFLAGS = -Wno-write-strings -DBUILD_ROGUE -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared
CFLAGS_WIN = -Wno-write-strings -DBUILD_ROGUE -std=c++11 -I../../depends/x86_64-w64-mingw32/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared
DEBUGFLAGS = -O0 -D _DEBUG
RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program
$(info $(OS))
OS := $(shell uname -s)
$(info $(OS))
TARGET = librogue.so
TARGET_DARWIN = librogue.dylib
TARGET_WIN = librogue.dll
SOURCES = cclib.cpp
#HEADERS = $(shell echo ../cryptoconditions/include/*.h) -I/usr/local/Cellar/gcc\@6/6.4.0_2/include/c++/6.4.0/
all: $(TARGET)
$(TARGET): $(SOURCES)
$(info Building cclib to src/)
ifeq ($(OS),Darwin)
$(CC_DARWIN) $(CFLAGS_DARWIN) $(DEBUGFLAGS) -o $(TARGET_DARWIN) -c $(SOURCES)
cp $(TARGET_DARWIN) ../libcc.dylib
else ifeq ($(HOST),x86_64-w64-mingw32)
$(info WINDOWS)
$(CC_WIN) $(CFLAGS_WIN) $(DEBUGFLAGS) -o $(TARGET_WIN) -c $(SOURCES)
cp $(TARGET_WIN) ../libcc.dll
#else ifeq ($(WIN_HOST),True) - todo: pass ENV var from build.sh if WIN host
else
$(info LINUX)
$(CC) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) -c $(SOURCES)
cp $(TARGET) ../libcc.so
endif
clean:
rm -rf $(TARGET)

View File

@@ -259,7 +259,7 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti
return eval->Invalid("invalid refund for cancelbuy");
preventCCvins = 3;
preventCCvouts = 0;
fprintf(stderr,"cancelbuy validated to origaddr.(%s)\n",origNormalAddr);
//fprintf(stderr,"cancelbuy validated to origaddr.(%s)\n",origNormalAddr);
break;
case 'B': // fillbuy:
@@ -305,7 +305,7 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti
return eval->Invalid("mismatched vout0 AssetsCCaddr for fillbuy");
}
}
fprintf(stderr,"fillbuy validated\n");
//fprintf(stderr,"fillbuy validated\n");
break;
//case 'e': // selloffer
// break; // disable swaps

View File

@@ -36,6 +36,8 @@ std::string MYCCLIBNAME = (char *)"rogue";
#else
#define EVAL_SUDOKU 17
#define EVAL_MUSIG 18
#define EVAL_DILITHIUM 19
std::string MYCCLIBNAME = (char *)"sudoku";
#endif
@@ -70,6 +72,21 @@ CClib_methods[] =
{ (char *)"sudoku", (char *)"txidinfo", (char *)"txid", 1, 1, 'T', EVAL_SUDOKU },
{ (char *)"sudoku", (char *)"pending", (char *)"<no args>", 0, 0, 'U', EVAL_SUDOKU },
{ (char *)"sudoku", (char *)"solution", (char *)"txid solution timestamps[81]", 83, 83, 'S', EVAL_SUDOKU },
{ (char *)"musig", (char *)"calcmsg", (char *)"sendtxid scriptPubKey", 2, 2, 'C', EVAL_MUSIG },
{ (char *)"musig", (char *)"combine", (char *)"pubkeys ...", 2, 999999999, 'P', EVAL_MUSIG },
{ (char *)"musig", (char *)"session", (char *)"myindex,numsigners,combined_pk,pkhash,msg32", 5, 5, 'R', EVAL_MUSIG },
{ (char *)"musig", (char *)"commit", (char *)"pkhash,ind,commitment", 3, 3, 'H', EVAL_MUSIG },
{ (char *)"musig", (char *)"nonce", (char *)"pkhash,ind,nonce", 3, 3, 'N', EVAL_MUSIG },
{ (char *)"musig", (char *)"partialsig", (char *)"pkhash,ind,partialsig", 3, 3, 'S', EVAL_MUSIG },
{ (char *)"musig", (char *)"verify", (char *)"msg sig pubkey", 3, 3, 'V', EVAL_MUSIG },
{ (char *)"musig", (char *)"send", (char *)"combined_pk amount", 2, 2, 'x', EVAL_MUSIG },
{ (char *)"musig", (char *)"spend", (char *)"sendtxid sig scriptPubKey", 3, 3, 'y', EVAL_MUSIG },
{ (char *)"dilithium", (char *)"keypair", (char *)"[hexseed]", 0, 1, 'K', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"register", (char *)"handle, [hexseed]", 1, 2, 'R', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"sign", (char *)"msg [hexseed]", 1, 2, 'S', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"verify", (char *)"pubtxid msg sig", 3, 3, 'V', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"send", (char *)"handle pubtxid amount", 3, 3, 'x', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"spend", (char *)"sendtxid scriptPubKey [hexseed]", 2, 3, 'y', EVAL_DILITHIUM },
#endif
};
@@ -98,11 +115,66 @@ UniValue sudoku_txidinfo(uint64_t txfee,struct CCcontract_info *cp,cJSON *params
UniValue sudoku_generate(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue sudoku_solution(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue sudoku_pending(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
bool musig_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx);
UniValue musig_calcmsg(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue musig_combine(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue musig_session(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue musig_commit(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue musig_nonce(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue musig_partialsig(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue musig_verify(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue musig_send(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue musig_spend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
bool dilithium_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx);
UniValue dilithium_register(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue dilithium_send(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue dilithium_spend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue dilithium_keypair(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue dilithium_sign(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue dilithium_verify(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
#endif
UniValue CClib_method(struct CCcontract_info *cp,char *method,cJSON *params)
cJSON *cclib_reparse(int32_t *nump,char *jsonstr) // assumes origparams will be freed by caller
{
UniValue result(UniValue::VOBJ); uint64_t txfee = 10000;
cJSON *params; char *newstr; int32_t i,j;
*nump = 0;
if ( jsonstr != 0 )
{
if ( jsonstr[0] == '"' && jsonstr[strlen(jsonstr)-1] == '"' )
{
jsonstr[strlen(jsonstr)-1] = 0;
jsonstr++;
}
newstr = (char *)malloc(strlen(jsonstr)+1);
for (i=j=0; jsonstr[i]!=0; i++)
{
if ( jsonstr[i] == '%' && jsonstr[i+1] == '2' && jsonstr[i+2] == '2' )
{
newstr[j++] = '"';
i += 2;
}
else if ( jsonstr[i] == '\'' )
newstr[j++] = '"';
else newstr[j++] = jsonstr[i];
}
newstr[j] = 0;
params = cJSON_Parse(newstr);
if ( 0 && params != 0 )
printf("new.(%s) -> %s\n",newstr,jprint(params,0));
free(newstr);
*nump = cJSON_GetArraySize(params);
//free(origparams);
} else params = 0;
return(params);
}
UniValue CClib_method(struct CCcontract_info *cp,char *method,char *jsonstr)
{
UniValue result(UniValue::VOBJ); uint64_t txfee = 10000; int32_t m; cJSON *params = cclib_reparse(&m,jsonstr);
//fprintf(stderr,"method.(%s) -> (%s)\n",jsonstr!=0?jsonstr:"",params!=0?jprint(params,0):"");
#ifdef BUILD_ROGUE
if ( cp->evalcode == EVAL_ROGUE )
{
@@ -158,6 +230,57 @@ UniValue CClib_method(struct CCcontract_info *cp,char *method,cJSON *params)
return(result);
}
}
else if ( cp->evalcode == EVAL_MUSIG )
{
//printf("CClib_method params.%p\n",params);
if ( strcmp(method,"combine") == 0 )
return(musig_combine(txfee,cp,params));
else if ( strcmp(method,"calcmsg") == 0 )
return(musig_calcmsg(txfee,cp,params));
else if ( strcmp(method,"session") == 0 )
return(musig_session(txfee,cp,params));
else if ( strcmp(method,"commit") == 0 )
return(musig_commit(txfee,cp,params));
else if ( strcmp(method,"nonce") == 0 ) // returns combined nonce if ready
return(musig_nonce(txfee,cp,params));
else if ( strcmp(method,"partialsig") == 0 )
return(musig_partialsig(txfee,cp,params));
else if ( strcmp(method,"verify") == 0 )
return(musig_verify(txfee,cp,params));
else if ( strcmp(method,"send") == 0 )
return(musig_send(txfee,cp,params));
else if ( strcmp(method,"spend") == 0 )
return(musig_spend(txfee,cp,params));
else
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","invalid musig method"));
result.push_back(Pair("method",method));
return(result);
}
}
else if ( cp->evalcode == EVAL_DILITHIUM )
{
if ( strcmp(method,"send") == 0 )
return(dilithium_send(txfee,cp,params));
else if ( strcmp(method,"spend") == 0 )
return(dilithium_spend(txfee,cp,params));
else if ( strcmp(method,"keypair") == 0 )
return(dilithium_keypair(txfee,cp,params));
else if ( strcmp(method,"register") == 0 )
return(dilithium_register(txfee,cp,params));
else if ( strcmp(method,"sign") == 0 )
return(dilithium_sign(txfee,cp,params));
else if ( strcmp(method,"verify") == 0 )
return(dilithium_verify(txfee,cp,params));
else
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","invalid dilithium method"));
result.push_back(Pair("method",method));
return(result);
}
}
#endif
else
{
@@ -196,10 +319,10 @@ UniValue CClib_info(struct CCcontract_info *cp)
return(result);
}
UniValue CClib(struct CCcontract_info *cp,char *method,cJSON *params)
UniValue CClib(struct CCcontract_info *cp,char *method,char *jsonstr)
{
UniValue result(UniValue::VOBJ); int32_t i; std::string rawtx;
//printf("CClib params.%p\n",params);
UniValue result(UniValue::VOBJ); int32_t i; std::string rawtx; cJSON *params;
//printf("CClib params.(%s)\n",jsonstr!=0?jsonstr:"");
for (i=0; i<sizeof(CClib_methods)/sizeof(*CClib_methods); i++)
{
if ( cp->evalcode == CClib_methods[i].evalcode && strcmp(method,CClib_methods[i].method) == 0 )
@@ -208,10 +331,12 @@ UniValue CClib(struct CCcontract_info *cp,char *method,cJSON *params)
{
result.push_back(Pair("result","success"));
result.push_back(Pair("method",CClib_methods[i].method));
params = cJSON_Parse(jsonstr);
rawtx = CClib_rawtxgen(cp,CClib_methods[i].funcid,params);
free_json(params);
result.push_back(Pair("rawtx",rawtx));
return(result);
} else return(CClib_method(cp,method,params));
} else return(CClib_method(cp,method,jsonstr));
}
}
result.push_back(Pair("result","error"));
@@ -278,7 +403,13 @@ bool CClib_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const C
#ifdef BUILD_ROGUE
return(rogue_validate(cp,height,eval,tx));
#else
return(sudoku_validate(cp,height,eval,tx));
if ( cp->evalcode == EVAL_SUDOKU )
return(sudoku_validate(cp,height,eval,tx));
else if ( cp->evalcode == EVAL_MUSIG )
return(musig_validate(cp,height,eval,tx));
else if ( cp->evalcode == EVAL_DILITHIUM )
return(dilithium_validate(cp,height,eval,tx));
else return eval->Invalid("invalid evalcode");
#endif
}
numvins = tx.vin.size();
@@ -385,21 +516,6 @@ std::string Faucet2Fund(struct CCcontract_info *cp,uint64_t txfee,int64_t funds)
return("");
}
/*UniValue FaucetInfo()
{
UniValue result(UniValue::VOBJ); char numstr[64];
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey faucetpk; struct CCcontract_info *cp,C; int64_t funding;
result.push_back(Pair("result","success"));
result.push_back(Pair("name","Faucet"));
cp = CCinit(&C,EVAL_FAUCET);
faucetpk = GetUnspendable(cp,0);
funding = AddFaucetInputs(cp,mtx,faucetpk,0,0);
sprintf(numstr,"%.8f",(double)funding/COIN);
result.push_back(Pair("funding",numstr));
return(result);
}*/
std::string CClib_rawtxgen(struct CCcontract_info *cp,uint8_t funcid,cJSON *params)
{
CMutableTransaction tmpmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
@@ -464,34 +580,14 @@ uint256 juint256(cJSON *obj)
return(revuint256(tmp));
}
cJSON *cclib_reparse(int32_t *nump,cJSON *origparams) // assumes origparams will be freed by caller
int32_t cclib_parsehash(uint8_t *hash32,cJSON *item,int32_t len)
{
cJSON *params; char *jsonstr,*newstr; int32_t i,j;
if ( (jsonstr= jprint(origparams,0)) != 0 )
char *hexstr;
if ( (hexstr= jstr(item,0)) != 0 && is_hexstr(hexstr,0) == len*2 )
{
if ( jsonstr[0] == '"' && jsonstr[strlen(jsonstr)-1] == '"' )
{
jsonstr[strlen(jsonstr)-1] = 0;
jsonstr++;
}
newstr = (char *)malloc(strlen(jsonstr)+1);
for (i=j=0; jsonstr[i]!=0; i++)
{
if ( jsonstr[i] == '%' && jsonstr[i+1] == '2' && jsonstr[i+2] == '2' )
{
newstr[j++] = '"';
i += 2;
} else newstr[j++] = jsonstr[i];
}
newstr[j] = 0;
params = cJSON_Parse(newstr);
if ( 0 && params != 0 )
printf("new.(%s) -> %s\n",newstr,jprint(params,0));
free(newstr);
*nump = cJSON_GetArraySize(params);
//free(origparams);
} else params = 0;
return(params);
decode_hex(hash32,len,hexstr);
return(0);
} else return(-1);
}
#ifdef BUILD_ROGUE
@@ -533,5 +629,8 @@ cJSON *cclib_reparse(int32_t *nump,cJSON *origparams) // assumes origparams will
#else
#include "sudoku.cpp"
#include "musig.cpp"
#include "dilithium.c"
//#include "../secp256k1/src/modules/musig/example.c"
#endif

0
src/cc/dapps/cJSON.c Executable file → Normal file
View File

3269
src/cc/dilithium.c Normal file

File diff suppressed because one or more lines are too long

475
src/cc/dilithium.h Normal file
View File

@@ -0,0 +1,475 @@
#include <stdint.h>
/*
#ifndef CPUCYCLES_H
#define CPUCYCLES_H
#ifdef DBENCH
#define DBENCH_START() uint64_t time = cpucycles_start()
#define DBENCH_STOP(t) t += cpucycles_stop() - time - timing_overhead
#else
#define DBENCH_START()
#define DBENCH_STOP(t)
#endif
#ifdef USE_RDPMC // Needs echo 2 > /sys/devices/cpu/rdpmc
#ifdef SERIALIZE_RDC
static inline uint64_t cpucycles_start(void) {
const uint32_t ecx = (1U << 30) + 1;
uint64_t result;
asm volatile("cpuid; movl %1,%%ecx; rdpmc; shlq $32,%%rdx; orq %%rdx,%%rax"
: "=&a" (result) : "r" (ecx) : "rbx", "rcx", "rdx");
return result;
}
static inline uint64_t cpucycles_stop(void) {
const uint32_t ecx = (1U << 30) + 1;
uint64_t result, dummy;
asm volatile("rdpmc; shlq $32,%%rdx; orq %%rdx,%%rax; movq %%rax,%0; cpuid"
: "=&r" (result), "=c" (dummy) : "c" (ecx) : "rax", "rbx", "rdx");
return result;
}
#else
static inline uint64_t cpucycles_start(void) {
const uint32_t ecx = (1U << 30) + 1;
uint64_t result;
asm volatile("rdpmc; shlq $32,%%rdx; orq %%rdx,%%rax"
: "=a" (result) : "c" (ecx) : "rdx");
return result;
}
static inline uint64_t cpucycles_stop(void) {
const uint32_t ecx = (1U << 30) + 1;
uint64_t result;
asm volatile("rdpmc; shlq $32,%%rdx; orq %%rdx,%%rax"
: "=a" (result) : "c" (ecx) : "rdx");
return result;
}
#endif
#else
#ifdef SERIALIZE_RDC
static inline uint64_t cpucycles_start(void) {
uint64_t result;
asm volatile("cpuid; rdtsc; shlq $32,%%rdx; orq %%rdx,%%rax"
: "=a" (result) : : "%rbx", "%rcx", "%rdx");
return result;
}
static inline uint64_t cpucycles_stop(void) {
uint64_t result;
asm volatile("rdtscp; shlq $32,%%rdx; orq %%rdx,%%rax; mov %%rax,%0; cpuid"
: "=r" (result) : : "%rax", "%rbx", "%rcx", "%rdx");
return result;
}
#else
static inline uint64_t cpucycles_start(void) {
uint64_t result;
asm volatile("rdtsc; shlq $32,%%rdx; orq %%rdx,%%rax"
: "=a" (result) : : "%rdx");
return result;
}
static inline uint64_t cpucycles_stop(void) {
uint64_t result;
asm volatile("rdtsc; shlq $32,%%rdx; orq %%rdx,%%rax"
: "=a" (result) : : "%rdx");
return result;
}
#endif
#endif
int64_t cpucycles_overhead(void);
#endif*/
#ifndef FIPS202_H
#define FIPS202_H
#define SHAKE128_RATE 168
#define SHAKE256_RATE 136
void shake128_absorb(uint64_t *s,
const uint8_t *input,
int32_t inlen);
void shake128_squeezeblocks(uint8_t *output,
int32_t nblocks,
uint64_t *s);
void shake256_absorb(uint64_t *s,
const uint8_t *input,
int32_t inlen);
void shake256_squeezeblocks(uint8_t *output,
int32_t nblocks,
uint64_t *s);
void shake128(uint8_t *output,
int32_t outlen,
const uint8_t *input,
int32_t inlen);
void shake256(uint8_t *output,
int32_t outlen,
const uint8_t *input,
int32_t inlen);
#endif
#ifndef PARAMS_H
#define PARAMS_H
#ifndef MODE
#define MODE 3
#endif
#define SEEDBYTES 32U
#define CRHBYTES 48U
#define N 256U
#define Q 8380417U
#define QBITS 23U
#define ROOT_OF_UNITY 1753U
#define D 14U
#define GAMMA1 ((Q - 1U)/16U)
#define GAMMA2 (GAMMA1/2U)
#define ALPHA (2U*GAMMA2)
#if MODE == 0
#define K 3U
#define L 2U
#define ETA 7U
#define SETABITS 4U
#define BETA 375U
#define OMEGA 64U
#elif MODE == 1
#define K 4U
#define L 3U
#define ETA 6U
#define SETABITS 4U
#define BETA 325U
#define OMEGA 80U
#elif MODE == 2
#define K 5U
#define L 4U
#define ETA 5U
#define SETABITS 4U
#define BETA 275U
#define OMEGA 96U
#elif MODE == 3
#define K 6U
#define L 5U
#define ETA 3U
#define SETABITS 3U
#define BETA 175U
#define OMEGA 120U
#endif
#define POL_SIZE_PACKED ((N*QBITS)/8)
#define POLT1_SIZE_PACKED ((N*(QBITS - D))/8)
#define POLT0_SIZE_PACKED ((N*D)/8)
#define POLETA_SIZE_PACKED ((N*SETABITS)/8)
#define POLZ_SIZE_PACKED ((N*(QBITS - 3))/8)
#define POLW1_SIZE_PACKED ((N*4)/8)
#define POLVECK_SIZE_PACKED (K*POL_SIZE_PACKED)
#define POLVECL_SIZE_PACKED (L*POL_SIZE_PACKED)
#define CRYPTO_PUBLICKEYBYTES (SEEDBYTES + K*POLT1_SIZE_PACKED)
#define CRYPTO_SECRETKEYBYTES (2*SEEDBYTES + (L + K)*POLETA_SIZE_PACKED + CRHBYTES + K*POLT0_SIZE_PACKED)
#define CRYPTO_BYTES (L*POLZ_SIZE_PACKED + (OMEGA + K) + (N/8 + 8))
#endif
#ifndef POLY_H
#define POLY_H
//#include <stdint.h>
//#include "params.h"
//#include "fips202.h"
typedef struct {
uint32_t coeffs[N];
} poly __attribute__((aligned(32)));
void poly_reduce(poly *a);
void poly_csubq(poly *a);
void poly_freeze(poly *a);
void poly_add(poly *c, const poly *a, const poly *b);
void poly_sub(poly *c, const poly *a, const poly *b);
void poly_neg(poly *a);
void poly_shiftl(poly *a, uint32_t k);
void poly_ntt(poly *a);
void poly_invntt_montgomery(poly *a);
void poly_pointwise_invmontgomery(poly *c, const poly *a, const poly *b);
void poly_power2round(poly *a1, poly *a0, const poly *a);
void poly_decompose(poly *a1, poly *a0, const poly *a);
uint32_t poly_make_hint(poly *h, const poly *a, const poly *b);
void poly_use_hint(poly *a, const poly *b, const poly *h);
int poly_chknorm(const poly *a, uint32_t B);
void poly_uniform(poly *a, const uint8_t *buf);
void poly_uniform_eta(poly *a,
const uint8_t seed[SEEDBYTES],
uint8_t nonce);
void poly_uniform_gamma1m1(poly *a,
const uint8_t seed[SEEDBYTES + CRHBYTES],
uint16_t nonce);
void polyeta_pack(uint8_t *r, const poly *a);
void polyeta_unpack(poly *r, const uint8_t *a);
void polyt1_pack(uint8_t *r, const poly *a);
void polyt1_unpack(poly *r, const uint8_t *a);
void polyt0_pack(uint8_t *r, const poly *a);
void polyt0_unpack(poly *r, const uint8_t *a);
void polyz_pack(uint8_t *r, const poly *a);
void polyz_unpack(poly *r, const uint8_t *a);
void polyw1_pack(uint8_t *r, const poly *a);
#endif
#ifndef POLYVEC_H
#define POLYVEC_H
//#include <stdint.h>
//#include "params.h"
//#include "poly.h"
/* Vectors of polynomials of length L */
typedef struct {
poly vec[L];
} polyvecl;
void polyvecl_freeze(polyvecl *v);
void polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v);
void polyvecl_ntt(polyvecl *v);
void polyvecl_pointwise_acc_invmontgomery(poly *w,
const polyvecl *u,
const polyvecl *v);
int polyvecl_chknorm(const polyvecl *v, uint32_t B);
/* Vectors of polynomials of length K */
typedef struct {
poly vec[K];
} polyveck;
void polyveck_reduce(polyveck *v);
void polyveck_csubq(polyveck *v);
void polyveck_freeze(polyveck *v);
void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v);
void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v);
void polyveck_shiftl(polyveck *v, uint32_t k);
void polyveck_ntt(polyveck *v);
void polyveck_invntt_montgomery(polyveck *v);
int polyveck_chknorm(const polyveck *v, uint32_t B);
void polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v);
void polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v);
uint32_t polyveck_make_hint(polyveck *h,
const polyveck *u,
const polyveck *v);
void polyveck_use_hint(polyveck *w, const polyveck *v, const polyveck *h);
#endif
#ifndef NTT_H
#define NTT_H
//#include <stdint.h>
//#include "params.h"
void ntt(uint32_t p[N]);
void invntt_frominvmont(uint32_t p[N]);
#endif
#ifndef PACKING_H
#define PACKING_H
//#include "params.h"
//#include "polyvec.h"
void pack_pk(uint8_t pk[CRYPTO_PUBLICKEYBYTES],
const uint8_t rho[SEEDBYTES], const polyveck *t1);
void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES],
const uint8_t rho[SEEDBYTES],
const uint8_t key[SEEDBYTES],
const uint8_t tr[CRHBYTES],
const polyvecl *s1,
const polyveck *s2,
const polyveck *t0);
void pack_sig(uint8_t sig[CRYPTO_BYTES],
const polyvecl *z, const polyveck *h, const poly *c);
void unpack_pk(uint8_t rho[SEEDBYTES], polyveck *t1,
const uint8_t pk[CRYPTO_PUBLICKEYBYTES]);
void unpack_sk(uint8_t rho[SEEDBYTES],
uint8_t key[SEEDBYTES],
uint8_t tr[CRHBYTES],
polyvecl *s1,
polyveck *s2,
polyveck *t0,
const uint8_t sk[CRYPTO_SECRETKEYBYTES]);
int unpack_sig(polyvecl *z, polyveck *h, poly *c,
const uint8_t sig[CRYPTO_BYTES]);
#endif
#ifndef REDUCE_H
#define REDUCE_H
//#include <stdint.h>
#define MONT 4193792U // 2^32 % Q
#define QINV 4236238847U // -q^(-1) mod 2^32
/* a <= Q*2^32 => r < 2*Q */
uint32_t montgomery_reduce(uint64_t a);
/* r < 2*Q */
uint32_t reduce32(uint32_t a);
/* a < 2*Q => r < Q */
uint32_t csubq(uint32_t a);
/* r < Q */
uint32_t freeze(uint32_t a);
#endif
#ifndef ROUNDING_H
#define ROUNDING_H
//#include <stdint.h>
uint32_t power2round(const uint32_t a, uint32_t *a0);
uint32_t decompose(uint32_t a, uint32_t *a0);
uint32_t make_hint(const uint32_t a, const uint32_t b);
uint32_t use_hint(const uint32_t a, const uint32_t hint);
#endif
#ifndef SIGN_H
#define SIGN_H
//#include "params.h"
//#include "poly.h"
//#include "polyvec.h"
void expand_mat(polyvecl mat[K], const uint8_t rho[SEEDBYTES]);
void challenge(poly *c, const uint8_t mu[CRHBYTES],
const polyveck *w1);
int crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
int crypto_sign(uint8_t *sm, int32_t *smlen,
const uint8_t *msg, int32_t len,
const uint8_t *sk);
int crypto_sign_open(uint8_t *m, int32_t *mlen,
const uint8_t *sm, int32_t smlen,
const uint8_t *pk);
#endif
#ifndef API_H
#define API_H
#ifndef MODE
#define MODE 3
#endif
#if MODE == 0
#if CRYPTO_PUBLICKEYBYTES -896U
CRYPTO_PUBLICKEYBYTES size error
#endif
#if CRYPTO_SECRETKEYBYTES -2096U
CRYPTO_SECRETKEYBYTES size error
#endif
#if CRYPTO_BYTES -1387U
CRYPTO_BYTES size error
#endif
#elif MODE == 1
#if CRYPTO_PUBLICKEYBYTES -1184U
CRYPTO_PUBLICKEYBYTES size error
#endif
#if CRYPTO_SECRETKEYBYTES -2800U
CRYPTO_SECRETKEYBYTES size error
#endif
#if CRYPTO_BYTES -2044U
CRYPTO_BYTES size error
#endif
#elif MODE == 2
#if CRYPTO_PUBLICKEYBYTES -1472U
CRYPTO_PUBLICKEYBYTES size error
#endif
#if CRYPTO_SECRETKEYBYTES -3504U
CRYPTO_SECRETKEYBYTES size error
#endif
#if CRYPTO_BYTES -2701U
CRYPTO_BYTES size error
#endif
#elif MODE == 3
#if CRYPTO_PUBLICKEYBYTES -1760U
CRYPTO_PUBLICKEYBYTES size error
#endif
#if CRYPTO_SECRETKEYBYTES -3856U
CRYPTO_SECRETKEYBYTES size error
#endif
#if CRYPTO_BYTES -3366U
CRYPTO_BYTES size error
#endif
#endif
#define CRYPTO_ALGNAME "Dilithium"
int crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
int crypto_sign(uint8_t *sm, int32_t *smlen,
const uint8_t *msg, int32_t len,
const uint8_t *sk);
int crypto_sign_open(uint8_t *m, int32_t *mlen,
const uint8_t *sm, int32_t smlen,
const uint8_t *pk);
#endif

View File

@@ -124,9 +124,9 @@ bool FaucetValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx
//int height = it->first.blockHeight;
if ( CCduration(numblocks,it->first.txhash) > 0 && numblocks > 3 )
{
//fprintf(stderr,"would return error %s numblocks.%d ago\n",uint256_str(str,it->first.txhash),numblocks);
return eval->Invalid("faucet is only for brand new addresses");
}
//fprintf(stderr,"txid %s numblocks.%d ago\n",uint256_str(str,it->first.txhash),numblocks);
}
retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts);
if ( retval != 0 )

View File

@@ -1,2 +1,2 @@
#!/bin/sh
gcc -std=c++11 -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o ../libcc.so cclib.cpp
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o ../libcc.so cclib.cpp

View File

@@ -1,8 +1,38 @@
#!/bin/sh
cd rogue;
./configure # only need this first time
make; cd ..
gcc -Wno-write-strings -DBUILD_ROGUE -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -o librogue.so -c cclib.cpp
#gcc -std=c++11 -fPIC -shared -o librogue.so cclib.o rogue/rogue.so
cp librogue.so ../libcc.so
if [ "$HOST" = "x86_64-w64-mingw32" ]; then
echo building rogue.exe...
./configure --host=x86_64-w64-mingw32
mkdir ncurses && cd ncurses
echo $PWD
wget https://invisible-island.net/datafiles/release/mingw32.zip
unzip mingw32.zip && rm mingw32.zip
echo lib archive cleaned
cd ..
echo $PWD
if make -f Makefile_win "$@"; then
echo rogue.exe build SUCCESSFUL
cd ..
else
echo rogue.exe build FAILED
exit 1
fi
else
echo building rogue...
./configure
if make "$@"; then
echo rogue build SUCCESSFUL
cd ..
else
echo rogue build FAILED
exit 1
fi
fi
if make -f Makefile_rogue "$@"; then
echo ROGUE BUILD SUCCESSFUL
else
echo ROGUE BUILD FAILED
exit 1
fi

868
src/cc/musig.cpp Normal file
View File

@@ -0,0 +1,868 @@
/******************************************************************************
* 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. *
* *
******************************************************************************/
/* first make a combined pk:
./komodo-cli -ac_name=MUSIG cclib combine 18 '["02fb6aa0b96cad24d46b5da93eba3864c45ce07a73bba12da530ae841e140fcf28","0255c46dbce584e3751081b39d7fc054fc807100557e73fc444481618b5706afb4"]'
{
"pkhash": "5cb5a225064ca6ffc1438cb2a6ac2ac65fe2d5055dc7f6c7ebffb9a231f8912b",
"combined_pk": "03f016c348437c7422eed92d865aa9789614f75327cada463eefc566126b54785b",
"result": "success"
}
the combined_pk and pkhash will be needed for various other rpc calls
second, send 1 coin to the combined_pk
./komodo-cli -ac_name=MUSIG cclib send 18 '["03f016c348437c7422eed92d865aa9789614f75327cada463eefc566126b54785b",1]'
{
"hex": "0400008085202f8901a980664dffc810725a79ffb89ac48be4c7b6bade9b789732fcf871acf8e81a2e010000006a47304402207e52763661ecd2c34a65d6623950be11794825db71576dc11894c606ddc317800220028fef46dc20630d0fdf22647b5d4ff0f1c47cf75f48702d0a91d5589eff99d001210255c46dbce584e3751081b39d7fc054fc807100557e73fc444481618b5706afb4ffffffff031008f60500000000302ea22c8020c71ddb3aac7f9b9e4bdacf032aaa8b8e4433c4ff9f8a43cebb9c1f5da96928a48103120c008203000401cce09aa4350000000023210255c46dbce584e3751081b39d7fc054fc807100557e73fc444481618b5706afb4ac0000000000000000266a2412782103f016c348437c7422eed92d865aa9789614f75327cada463eefc566126b54785b00000000920500000000000000000000000000",
"txid": "5ce74037a153ee210413b48d4e88638b99825a2de1a1f1aa0d36ebf93019824c",
"result": "success"
}
sendrawtransaction of the above hex.
./komodo-cli -ac_name=MUSIG getrawtransaction 5ce74037a153ee210413b48d4e88638b99825a2de1a1f1aa0d36ebf93019824c 1
"vout": [
{
"value": 1.00010000,
"valueSat": 100010000,
"n": 0,
"scriptPubKey": {
"asm": "a22c8020c71ddb3aac7f9b9e4bdacf032aaa8b8e4433c4ff9f8a43cebb9c1f5da96928a48103120c008203000401 OP_CHECKCRYPTOCONDITION",
"hex": "2ea22c8020c71ddb3aac7f9b9e4bdacf032aaa8b8e4433c4ff9f8a43cebb9c1f5da96928a48103120c008203000401cc",
"reqSigs": 1,
"type": "cryptocondition",
"addresses": [
"RKWS7jxyjPX9iaJttk8iMKf1AumanKypez"
]
}
},
{
"value": 8.99980000,
"valueSat": 899980000,
"n": 1,
"scriptPubKey": {
"asm": "0255c46dbce584e3751081b39d7fc054fc807100557e73fc444481618b5706afb4 OP_CHECKSIG",
"hex": "210255c46dbce584e3751081b39d7fc054fc807100557e73fc444481618b5706afb4ac",
"reqSigs": 1,
"type": "pubkey",
"addresses": [
"RVQjvGdRbYLJ49bfH4SAFseipvwE3UdoDw"
]
}
script: 210255c46dbce584e3751081b39d7fc054fc807100557e73fc444481618b5706afb4ac
sendtxid: 5ce74037a153ee210413b48d4e88638b99825a2de1a1f1aa0d36ebf93019824c
get the msg we need to sign:
./komodo-cli -ac_name=MUSIG cclib calcmsg 18 '["5ce74037a153ee210413b48d4e88638b99825a2de1a1f1aa0d36ebf93019824c","210255c46dbce584e3751081b39d7fc054fc807100557e73fc444481618b5706afb4ac"]'
{
"msg": "f7fb85d1412814e3c2f98b990802af6ee33dad368c6ba05c2050e9e5506fcd75",
"result": "success"
}
the "msg" is what needs to be signed to create a valid spend
now on each signing node, a session needs to be created:
5 args: ind, numsigners, combined_pk, pkhash, message to be signed
on node with pubkey: 02fb6aa0b96cad24d46b5da93eba3864c45ce07a73bba12da530ae841e140fcf28
./komodo-cli -ac_name=MUSIG cclib session 18 '[0,2,"03f016c348437c7422eed92d865aa9789614f75327cada463eefc566126b54785b","5cb5a225064ca6ffc1438cb2a6ac2ac65fe2d5055dc7f6c7ebffb9a231f8912b","f7fb85d1412814e3c2f98b990802af6ee33dad368c6ba05c2050e9e5506fcd75"]'
{
"myind": 0,
"numsigners": 2,
"commitment": "bbea1f2562eca01b9a1393c5dc188bdd44551aebf684f4459930f59dde01f7ae",
"result": "success"
}
on node with pubkey: 0255c46dbce584e3751081b39d7fc054fc807100557e73fc444481618b5706afb4
./komodo-cli -ac_name=MUSIG cclib session 18 '[1,2,"03f016c348437c7422eed92d865aa9789614f75327cada463eefc566126b54785b","5cb5a225064ca6ffc1438cb2a6ac2ac65fe2d5055dc7f6c7ebffb9a231f8912b","f7fb85d1412814e3c2f98b990802af6ee33dad368c6ba05c2050e9e5506fcd75"]'
{
"myind": 1,
"numsigners": 2,
"commitment": "c2291acb747a75b1a40014d8eb0cc90a1360f74d413f65f78e20a7de45eda851",
"result": "success"
}
now we need to get the commitment from each node to the other one. the session already put the commitment for each node into the global struct. Keep in mind there is a single global struct with session unique to each cclib session call. that means no restarting any deamon in the middle of the process on any of the nodes and only call cclib session a single time. this is an artificial restriction just to simplify the initial implementation of musig
./komodo-cli -ac_name=MUSIG cclib commit 18 '["5cb5a225064ca6ffc1438cb2a6ac2ac65fe2d5055dc7f6c7ebffb9a231f8912b","1","c2291acb747a75b1a40014d8eb0cc90a1360f74d413f65f78e20a7de45eda851"]'
{
"added_index": 1,
"myind": 0,
"nonce": "02fec7a9310c959a0a97b86bc3f8c30d392d1fb51793915898c568f73f1f70476b",
"result": "success"
}
./komodo-cli -ac_name=MUSIG cclib commit 18 '["5cb5a225064ca6ffc1438cb2a6ac2ac65fe2d5055dc7f6c7ebffb9a231f8912b",0,"d242cff13fa8c9b83248e4219fda459ada146b885f2171481f1b0f66c66d94ad"]'
{
"added_index": 0,
"myind": 1,
"nonce": "039365deaaaea089d509ba4c9f846de2baf4aa04cf6b26fa2c1cd818553e47f80c",
"result": "success"
}
Now exchange the revealed nonces to each node:
./komodo-cli -ac_name=MUSIG cclib nonce 18 '["5cb5a225064ca6ffc1438cb2a6ac2ac65fe2d5055dc7f6c7ebffb9a231f8912b","1","039365deaaaea089d509ba4c9f846de2baf4aa04cf6b26fa2c1cd818553e47f80c"]'
{
"added_index": 1,
"myind": 0,
"partialsig": "1d65c09cd9bffe4f0604227e66cd7cd221480bbb08262fe885563a9df7cf8f5b",
"result": "success"
}
./komodo-cli -ac_name=MUSIG cclib nonce 18 '["5cb5a225064ca6ffc1438cb2a6ac2ac65fe2d5055dc7f6c7ebffb9a231f8912b",0,"02fec7a9310c959a0a97b86bc3f8c30d392d1fb51793915898c568f73f1f70476b"]'
{
"added_index": 0,
"myind": 1,
"partialsig": "4a3795e6801b355102c617390cf5a462061e082e35dc2ed8f8b1fab54cc0769e",
"result": "success"
}
Almost there! final step is to exchange the partial sigs between signers
./komodo-cli -ac_name=MUSIG cclib partialsig 18 '["5cb5a225064ca6ffc1438cb2a6ac2ac65fe2d5055dc7f6c7ebffb9a231f8912b","1","4a3795e6801b355102c617390cf5a462061e082e35dc2ed8f8b1fab54cc0769e"]'
{
"added_index": 1,
"result": "success",
"combinedsig": "a76f2790747ed2436a281f2660bdbee21bad9ee130b9cab6e542fa618fba1512679d568359db33a008ca39b773c32134276613e93e025ec17e083553449005f9"
}
./komodo-cli -ac_name=MUSIG cclib partialsig 18 '["5cb5a225064ca6ffc1438cb2a6ac2ac65fe2d5055dc7f6c7ebffb9a231f8912b",0,"1d65c09cd9bffe4f0604227e66cd7cd221480bbb08262fe885563a9df7cf8f5b"]'
{
"added_index": 0,
"result": "success",
"combinedsig": "a76f2790747ed2436a281f2660bdbee21bad9ee130b9cab6e542fa618fba1512679d568359db33a008ca39b773c32134276613e93e025ec17e083553449005f9"
}
Notice both nodes generated the same combined signature!
Now for a sanity test, we can use the verify call to make sure this sig will work with the msg needed for the spend:
./komodo-cli -ac_name=MUSIG cclib verify 18 '["f7fb85d1412814e3c2f98b990802af6ee33dad368c6ba05c2050e9e5506fcd75","03f016c348437c7422eed92d865aa9789614f75327cada463eefc566126b54785b","a76f2790747ed2436a281f2660bdbee21bad9ee130b9cab6e542fa618fba1512679d568359db33a008ca39b773c32134276613e93e025ec17e083553449005f9"]'
{
"msg": "f7fb85d1412814e3c2f98b990802af6ee33dad368c6ba05c2050e9e5506fcd75",
"combined_pk": "03f016c348437c7422eed92d865aa9789614f75327cada463eefc566126b54785b",
"combinedsig": "a76f2790747ed2436a281f2660bdbee21bad9ee130b9cab6e542fa618fba1512679d568359db33a008ca39b773c32134276613e93e025ec17e083553449005f9",
"result": "success"
}
and finally the spend: sendtxid, scriptPubKey, musig
./komodo-cli -ac_name=MUSIG cclib spend 18 '["5ce74037a153ee210413b48d4e88638b99825a2de1a1f1aa0d36ebf93019824c","210255c46dbce584e3751081b39d7fc054fc807100557e73fc444481618b5706afb4ac","a76f2790747ed2436a281f2660bdbee21bad9ee130b9cab6e542fa618fba1512679d568359db33a008ca39b773c32134276613e93e025ec17e083553449005f9"]'
{
"scriptpubkey": "210255c46dbce584e3751081b39d7fc054fc807100557e73fc444481618b5706afb4ac",
"msg": "f7fb85d1412814e3c2f98b990802af6ee33dad368c6ba05c2050e9e5506fcd75",
"combined_pk": "03f016c348437c7422eed92d865aa9789614f75327cada463eefc566126b54785b",
"combinedsig": "a76f2790747ed2436a281f2660bdbee21bad9ee130b9cab6e542fa618fba1512679d568359db33a008ca39b773c32134276613e93e025ec17e083553449005f9",
"hex": "0400008085202f89014c821930f9eb360daaf1a1e12d5a82998b63884e8db4130421ee53a13740e75c000000007b4c79a276a072a26ba067a5658021032d29d6545a2aafad795d9cf50912ecade549137
163934dfb2895ebc0e211ce8a81409671a60db89b3bc58966f3acc80194479b1a43d868e95a11ebc5609646d18710341a8ff92a7817571980307f5d660cc00a2735ac6333e0a7191243f1263f1959a100af03800112
a10001ffffffff0200e1f5050000000023210255c46dbce584e3751081b39d7fc054fc807100557e73fc444481618b5706afb4ac0000000000000000686a4c6512792103f016c348437c7422eed92d865aa9789614f
75327cada463eefc566126b54785b40a76f2790747ed2436a281f2660bdbee21bad9ee130b9cab6e542fa618fba1512679d568359db33a008ca39b773c32134276613e93e025ec17e083553449005f900000000a805
00000000000000000000000000",
"txid": "910635bf69a047fc90567a83ff12e47b753f470658b6d0855ec96e07e7349a8a",
"result": "success"
}
*/
#define USE_BASIC_CONFIG
#define ENABLE_MODULE_MUSIG
#include "../secp256k1/src/basic-config.h"
#include "../secp256k1/include/secp256k1.h"
#include "../secp256k1/src/ecmult.h"
#include "../secp256k1/src/ecmult_gen.h"
typedef struct { unsigned char data[64]; } secp256k1_schnorrsig;
struct secp256k1_context_struct {
secp256k1_ecmult_context ecmult_ctx;
secp256k1_ecmult_gen_context ecmult_gen_ctx;
secp256k1_callback illegal_callback;
secp256k1_callback error_callback;
};
//#include "../secp256k1/include/secp256k1.h"
//#include "../secp256k1/include/secp256k1_schnorrsig.h"
#include "../secp256k1/include/secp256k1_musig.h"
extern "C" int secp256k1_ecmult_multi_var(const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n);
extern "C" int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const secp256k1_schnorrsig *sig, const unsigned char *msg32, const secp256k1_pubkey *pk);
extern "C" int secp256k1_schnorrsig_parse(const secp256k1_context* ctx, secp256k1_schnorrsig* sig, const unsigned char *in64);
extern "C" int secp256k1_musig_pubkey_combine(const secp256k1_context* ctx, secp256k1_scratch_space *scratch, secp256k1_pubkey *combined_pk, unsigned char *pk_hash32, const secp256k1_pubkey *pubkeys, size_t n_pubkeys);
extern "C" int secp256k1_musig_session_initialize(const secp256k1_context* ctx, secp256k1_musig_session *session, secp256k1_musig_session_signer_data *signers, unsigned char *nonce_commitment32, const unsigned char *session_id32, const unsigned char *msg32, const secp256k1_pubkey *combined_pk, const unsigned char *pk_hash32, size_t n_signers, size_t my_index, const unsigned char *seckey);
extern "C" int secp256k1_schnorrsig_serialize(const secp256k1_context* ctx, unsigned char *out64, const secp256k1_schnorrsig* sig);
#define MUSIG_PREVN 0 // for now, just use vout0 for the musig output
#define MUSIG_TXFEE 10000
struct musig_info
{
secp256k1_musig_session session;
secp256k1_pubkey combined_pk;
uint8_t *nonce_commitments,**commitment_ptrs; // 32*N_SIGNERS
secp256k1_musig_session_signer_data *signer_data; //[N_SIGNERS];
secp256k1_pubkey *nonces; //[N_SIGNERS];
secp256k1_musig_partial_signature *partial_sig; //[N_SIGNERS];
int32_t myind,num,numcommits,numnonces,numpartials;
uint8_t msg[32],pkhash[32],combpk[33];
};
std::vector <struct musig_info *> MUSIG;
struct musig_info *musig_infocreate(int32_t myind,int32_t num)
{
int32_t i; struct musig_info *mp = (struct musig_info *)calloc(1,sizeof(*mp));
mp->myind = myind, mp->num = num;
mp->nonce_commitments = (uint8_t *)calloc(num,32);
mp->commitment_ptrs = (uint8_t **)calloc(num,sizeof(*mp->commitment_ptrs));
for (i=0; i<num; i++)
mp->commitment_ptrs[i] = &mp->nonce_commitments[i*32];
mp->signer_data = (secp256k1_musig_session_signer_data *)calloc(num,sizeof(*mp->signer_data));
mp->nonces = (secp256k1_pubkey *)calloc(num,sizeof(*mp->nonces));
mp->partial_sig = (secp256k1_musig_partial_signature *)calloc(num,sizeof(*mp->partial_sig));
return(mp);
}
void musig_infofree(struct musig_info *mp)
{
if ( mp->partial_sig != 0 )
{
GetRandBytes((uint8_t *)mp->partial_sig,mp->num*sizeof(*mp->partial_sig));
free(mp->partial_sig);
}
if ( mp->nonces != 0 )
{
GetRandBytes((uint8_t *)mp->nonces,mp->num*sizeof(*mp->nonces));
free(mp->nonces);
}
if ( mp->signer_data != 0 )
{
GetRandBytes((uint8_t *)mp->signer_data,mp->num*sizeof(*mp->signer_data));
free(mp->signer_data);
}
if ( mp->nonce_commitments != 0 )
{
GetRandBytes((uint8_t *)mp->nonce_commitments,mp->num*32);
free(mp->nonce_commitments);
}
if ( mp->commitment_ptrs != 0 )
{
GetRandBytes((uint8_t *)mp->commitment_ptrs,mp->num*sizeof(*mp->commitment_ptrs));
free(mp->commitment_ptrs);
}
GetRandBytes((uint8_t *)mp,sizeof(*mp));
free(mp);
}
CScript musig_sendopret(uint8_t funcid,CPubKey pk)
{
CScript opret; uint8_t evalcode = EVAL_MUSIG;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << pk);
return(opret);
}
uint8_t musig_sendopretdecode(CPubKey &pk,CScript scriptPubKey)
{
std::vector<uint8_t> vopret; uint8_t e,f;
GetOpReturnData(scriptPubKey,vopret);
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> pk) != 0 && e == EVAL_MUSIG && f == 'x' )
{
return(f);
}
return(0);
}
CScript musig_spendopret(uint8_t funcid,CPubKey pk,std::vector<uint8_t> musig64)
{
CScript opret; uint8_t evalcode = EVAL_MUSIG;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << pk << musig64);
return(opret);
}
uint8_t musig_spendopretdecode(CPubKey &pk,std::vector<uint8_t> &musig64,CScript scriptPubKey)
{
std::vector<uint8_t> vopret; uint8_t e,f;
GetOpReturnData(scriptPubKey,vopret);
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> pk; ss >> musig64) != 0 && e == EVAL_MUSIG && f == 'y' )
{
return(f);
}
return(0);
}
int32_t musig_parsepubkey(secp256k1_context *ctx,secp256k1_pubkey &spk,cJSON *item)
{
char *hexstr;
if ( (hexstr= jstr(item,0)) != 0 && is_hexstr(hexstr,0) == 66 )
{
CPubKey pk(ParseHex(hexstr));
if ( secp256k1_ec_pubkey_parse(ctx,&spk,pk.begin(),33) > 0 )
return(1);
} else return(-1);
}
int32_t musig_msghash(uint8_t *msg,uint256 prevhash,int32_t prevn,CTxOut vout,CPubKey pk)
{
CScript data; uint256 hash; int32_t len = 0;
data << E_MARSHAL(ss << prevhash << prevn << vout << pk);
hash = Hash(data.begin(),data.end());
memcpy(msg,&hash,sizeof(hash));
return(0);
}
int32_t musig_prevoutmsg(uint8_t *msg,uint256 sendtxid,CScript scriptPubKey)
{
CTransaction vintx; uint256 hashBlock; int32_t numvouts; CTxOut vout; CPubKey pk;
memset(msg,0,32);
if ( myGetTransaction(sendtxid,vintx,hashBlock) != 0 && (numvouts= vintx.vout.size()) > 1 )
{
if ( musig_sendopretdecode(pk,vintx.vout[numvouts-1].scriptPubKey) == 'x' )
{
vout.nValue = vintx.vout[MUSIG_PREVN].nValue - MUSIG_TXFEE;
vout.scriptPubKey = scriptPubKey;
return(musig_msghash(msg,sendtxid,MUSIG_PREVN,vout,pk));
}
}
return(-1);
}
UniValue musig_calcmsg(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
UniValue result(UniValue::VOBJ); uint256 sendtxid; int32_t i,zeros=0; uint8_t msg[32]; char *scriptstr,str[65]; int32_t n;
if ( params != 0 && (n= cJSON_GetArraySize(params)) > 0 )
{
if ( n == 2 )
{
sendtxid = juint256(jitem(params,0));
scriptstr = jstr(jitem(params,1),0);
if ( is_hexstr(scriptstr,0) != 0 )
{
CScript scriptPubKey;
scriptPubKey.resize(strlen(scriptstr)/2);
decode_hex(&scriptPubKey[0],strlen(scriptstr)/2,scriptstr);
musig_prevoutmsg(msg,sendtxid,scriptPubKey);
for (i=0; i<32; i++)
{
sprintf(&str[i<<1],"%02x",msg[i]);
if ( msg[i] == 0 )
zeros++;
}
str[64] = 0;
if ( zeros != 32 )
{
result.push_back(Pair("msg",str));
result.push_back(Pair("result","success"));
return(result);
} else return(cclib_error(result,"null result, make sure params are sendtxid, scriptPubKey"));
} else return(cclib_error(result,"script is not hex"));
} else return(cclib_error(result,"need exactly 2 parameters: sendtxid, scriptPubKey"));
} else return(cclib_error(result,"couldnt parse params"));
}
UniValue musig_combine(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
static secp256k1_context *ctx;
size_t clen = CPubKey::PUBLIC_KEY_SIZE;
UniValue result(UniValue::VOBJ); CPubKey pk; int32_t i,n; uint8_t pkhash[32]; char *hexstr,str[67]; secp256k1_pubkey combined_pk,spk; std::vector<secp256k1_pubkey> pubkeys;
if ( ctx == 0 )
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
if ( params != 0 && (n= cJSON_GetArraySize(params)) > 0 )
{
//fprintf(stderr,"n.%d args.(%s)\n",n,jprint(params,0));
for (i=0; i<n; i++)
{
if ( musig_parsepubkey(ctx,spk,jitem(params,i)) < 0 )
return(cclib_error(result,"error parsing pk"));
pubkeys.push_back(spk);
}
if ( secp256k1_musig_pubkey_combine(ctx,NULL,&combined_pk,pkhash,&pubkeys[0],n) > 0 )
{
if ( secp256k1_ec_pubkey_serialize(ctx,(uint8_t *)pk.begin(),&clen,&combined_pk,SECP256K1_EC_COMPRESSED) > 0 && clen == 33 )
{
for (i=0; i<32; i++)
sprintf(&str[i<<1],"%02x",pkhash[i]);
str[64] = 0;
result.push_back(Pair("pkhash",str));
for (i=0; i<33; i++)
sprintf(&str[i<<1],"%02x",((uint8_t *)pk.begin())[i]);
str[66] = 0;
result.push_back(Pair("combined_pk",str));
result.push_back(Pair("result","success"));
return(result);
} else return(cclib_error(result,"error serializeing combined_pk"));
} else return(cclib_error(result,"error combining pukbeys"));
} else return(cclib_error(result,"need pubkeys params"));
}
UniValue musig_session(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
static secp256k1_context *ctx;
UniValue result(UniValue::VOBJ); int32_t i,n,myind,num,musiglocation; char *pkstr,*pkhashstr,*msgstr; uint8_t session[32],msg[32],pkhash[32],privkey[32],pub33[33]; CPubKey pk; char str[67];
if ( ctx == 0 )
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
if ( params != 0 && (n= cJSON_GetArraySize(params)) >= 5 )
{
myind = juint(jitem(params,0),0);
num = juint(jitem(params,1),0);
if ( myind < 0 || myind >= num || num <= 0 )
return(cclib_error(result,"illegal myindex and numsigners"));
if ( n > 5 )
musiglocation = juint(jitem(params,5),0);
else if ( n == 5 )
musiglocation = 0;
//printf("number of params.%i musiglocation.%i\n",n,musiglocation);
if ( MUSIG.size() > musiglocation )
{
for (int i = 0; i < MUSIG.size()-1; i++)
musig_infofree(MUSIG[i]);
MUSIG.clear();
}
struct musig_info *temp_musig = musig_infocreate(myind,num);
MUSIG.push_back(temp_musig);
if ( musig_parsepubkey(ctx,MUSIG[musiglocation]->combined_pk,jitem(params,2)) < 0 )
return(cclib_error(result,"error parsing combined_pubkey"));
else if ( cclib_parsehash(MUSIG[musiglocation]->pkhash,jitem(params,3),32) < 0 )
return(cclib_error(result,"error parsing pkhash"));
else if ( cclib_parsehash(MUSIG[musiglocation]->msg,jitem(params,4),32) < 0 )
return(cclib_error(result,"error parsing msg"));
Myprivkey(privkey);
GetRandBytes(session,32);
/** Initializes a signing session for a signer
*
* Returns: 1: session is successfully initialized
* 0: session could not be initialized: secret key or secret nonce overflow
* Args: ctx: pointer to a context object, initialized for signing (cannot
* be NULL)
* Out: session: the session structure to initialize (cannot be NULL)
* signers: an array of signers' data to be initialized. Array length must
* equal to `n_signers` (cannot be NULL)
* nonce_commitment32: filled with a 32-byte commitment to the generated nonce
* (cannot be NULL)
* In: session_id32: a *unique* 32-byte ID to assign to this session (cannot be
* NULL). If a non-unique session_id32 was given then a partial
* signature will LEAK THE SECRET KEY.
* msg32: the 32-byte message to be signed. Shouldn't be NULL unless you
* require sharing public nonces before the message is known
* because it reduces nonce misuse resistance. If NULL, must be
* set with `musig_session_set_msg` before signing and verifying.
* combined_pk: the combined public key of all signers (cannot be NULL)
* pk_hash32: the 32-byte hash of the signers' individual keys (cannot be
* NULL)
* n_signers: length of signers array. Number of signers participating in
* the MuSig. Must be greater than 0 and at most 2^32 - 1.
* my_index: index of this signer in the signers array
* seckey: the signer's 32-byte secret key (cannot be NULL)
*/
//fprintf(stderr, "SESSION: struct_size.%li using struct %i\n",MUSIG.size(), musiglocation);
if ( secp256k1_musig_session_initialize(ctx,&MUSIG[musiglocation]->session,MUSIG[musiglocation]->signer_data, &MUSIG[musiglocation]->nonce_commitments[MUSIG[musiglocation]->myind * 32],session,MUSIG[musiglocation]->msg,&MUSIG[musiglocation]->combined_pk,MUSIG[musiglocation]->pkhash,MUSIG[musiglocation]->num,MUSIG[musiglocation]->myind,privkey) > 0 )
{
memset(session,0,sizeof(session));
result.push_back(Pair("myind",(int64_t)myind));
result.push_back(Pair("numsigners",(int64_t)num));
for (i=0; i<32; i++)
sprintf(&str[i<<1],"%02x",MUSIG[musiglocation]->nonce_commitments[MUSIG[musiglocation]->myind*32 + i]);
str[64] = 0;
if ( n == 5 )
MUSIG[musiglocation]->numcommits = 1;
result.push_back(Pair("commitment",str));
result.push_back(Pair("result","success"));
return(result);
}
else
{
memset(session,0,sizeof(session));
return(cclib_error(result,"couldnt initialize session"));
}
} else return(cclib_error(result,"wrong number of params, need 5: myindex, numsigners, combined_pk, pkhash, msg32"));
}
UniValue musig_commit(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
static secp256k1_context *ctx;
size_t clen = CPubKey::PUBLIC_KEY_SIZE;
UniValue result(UniValue::VOBJ); int32_t i,n,ind,myind; uint8_t pkhash[32]; CPubKey pk; char str[67];
if ( ctx == 0 )
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
if ( params != 0 && (n= cJSON_GetArraySize(params)) >= 3 )
{
if ( n > 3 )
myind = juint(jitem(params,3),0);
else if ( n == 3 )
myind = 0;
if ( cclib_parsehash(pkhash,jitem(params,0),32) < 0 )
return(cclib_error(result,"error parsing pkhash"));
else if ( memcmp(MUSIG[myind]->pkhash,pkhash,32) != 0 )
return(cclib_error(result,"pkhash doesnt match session pkhash"));
else if ( (ind= juint(jitem(params,1),0)) < 0 || ind >= MUSIG[myind]->num )
return(cclib_error(result,"illegal ind for session"));
else if ( cclib_parsehash(&MUSIG[myind]->nonce_commitments[ind*32],jitem(params,2),32) < 0 )
return(cclib_error(result,"error parsing commitment"));
/** Gets the signer's public nonce given a list of all signers' data with commitments
*
* Returns: 1: public nonce is written in nonce
* 0: signer data is missing commitments or session isn't initialized
* for signing
* Args: ctx: pointer to a context object (cannot be NULL)
* session: the signing session to get the nonce from (cannot be NULL)
* signers: an array of signers' data initialized with
* `musig_session_initialize`. Array length must equal to
* `n_commitments` (cannot be NULL)
* Out: nonce: the nonce (cannot be NULL)
* In: commitments: array of 32-byte nonce commitments (cannot be NULL)
* n_commitments: the length of commitments and signers array. Must be the total
* number of signers participating in the MuSig.
*/
result.push_back(Pair("added_index",ind));
//fprintf(stderr, "COMMIT: struct_size.%li using_struct.%i added_index.%i\n",MUSIG.size(), myind, ind);
MUSIG[myind]->numcommits++;
if ( MUSIG[myind]->numcommits >= MUSIG[myind]->num && secp256k1_musig_session_get_public_nonce(ctx,&MUSIG[myind]->session,MUSIG[myind]->signer_data,&MUSIG[myind]->nonces[MUSIG[myind]->myind],MUSIG[myind]->commitment_ptrs,MUSIG[myind]->num) > 0 )
{
if ( secp256k1_ec_pubkey_serialize(ctx,(uint8_t *)pk.begin(),&clen,&MUSIG[myind]->nonces[MUSIG[myind]->myind],SECP256K1_EC_COMPRESSED) > 0 && clen == 33 )
{
for (i=0; i<33; i++)
sprintf(&str[i<<1],"%02x",((uint8_t *)pk.begin())[i]);
str[66] = 0;
if ( n == 5 )
MUSIG[myind]->numnonces = 1;
result.push_back(Pair("myind",MUSIG[myind]->myind));
result.push_back(Pair("nonce",str));
result.push_back(Pair("result","success"));
} else return(cclib_error(result,"error serializing nonce (pubkey)"));
}
else
{
result.push_back(Pair("status","not enough commitments"));
result.push_back(Pair("result","success"));
}
return(result);
} else return(cclib_error(result,"wrong number of params, need 3: pkhash, ind, commitment"));
}
UniValue musig_nonce(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
static secp256k1_context *ctx;
UniValue result(UniValue::VOBJ); int32_t i,n,ind,myind; uint8_t pkhash[32],psig[32]; CPubKey pk; char str[67];
if ( ctx == 0 )
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
if ( params != 0 && (n= cJSON_GetArraySize(params)) >= 3 )
{
if ( n > 3 )
myind = juint(jitem(params,3),0);
else if ( n == 3 )
myind = 0;
if ( cclib_parsehash(pkhash,jitem(params,0),32) < 0 )
return(cclib_error(result,"error parsing pkhash"));
else if ( memcmp(MUSIG[myind]->pkhash,pkhash,32) != 0 )
return(cclib_error(result,"pkhash doesnt match session pkhash"));
else if ( (ind= juint(jitem(params,1),0)) < 0 || ind >= MUSIG[myind]->num )
return(cclib_error(result,"illegal ind for session"));
else if ( musig_parsepubkey(ctx,MUSIG[myind]->nonces[ind],jitem(params,2)) < 0 )
return(cclib_error(result,"error parsing nonce"));
result.push_back(Pair("added_index",ind));
/** Checks a signer's public nonce against a commitment to said nonce, and update
* data structure if they match
*
* Returns: 1: commitment was valid, data structure updated
* 0: commitment was invalid, nothing happened
* Args: ctx: pointer to a context object (cannot be NULL)
* signer: pointer to the signer data to update (cannot be NULL). Must have
* been used with `musig_session_get_public_nonce` or initialized
* with `musig_session_initialize_verifier`.
* In: nonce: signer's alleged public nonce (cannot be NULL)
*/
MUSIG[myind]->numnonces++;
//fprintf(stderr, "NONCE: struct_size.%li using_struct.%i added_index.%i numnounces.%i num.%i\n",MUSIG.size(), myind, ind, MUSIG[myind]->numnonces, MUSIG[myind]->num);
if ( MUSIG[myind]->numnonces < MUSIG[myind]->num )
{
result.push_back(Pair("status","not enough nonces"));
result.push_back(Pair("result","success"));
return(result);
}
for (i=0; i<MUSIG[myind]->num; i++)
{
if ( secp256k1_musig_set_nonce(ctx,&MUSIG[myind]->signer_data[i],&MUSIG[myind]->nonces[i]) == 0 )
return(cclib_error(result,"error setting nonce"));
}
/** Updates a session with the combined public nonce of all signers. The combined
* public nonce is the sum of every signer's public nonce.
*
* Returns: 1: nonces are successfully combined
* 0: a signer's nonce is missing
* Args: ctx: pointer to a context object (cannot be NULL)
* session: session to update with the combined public nonce (cannot be
* NULL)
* signers: an array of signers' data, which must have had public nonces
* set with `musig_set_nonce`. Array length must equal to `n_signers`
* (cannot be NULL)
* n_signers: the length of the signers array. Must be the total number of
* signers participating in the MuSig.
* Out: nonce_is_negated: a pointer to an integer that indicates if the combined
* public nonce had to be negated.
* adaptor: point to add to the combined public nonce. If NULL, nothing is
* added to the combined nonce.
*/
if ( secp256k1_musig_session_combine_nonces(ctx,&MUSIG[myind]->session,MUSIG[myind]->signer_data,MUSIG[myind]->num,NULL,NULL) > 0 )
{
if ( secp256k1_musig_partial_sign(ctx,&MUSIG[myind]->session,&MUSIG[myind]->partial_sig[MUSIG[myind]->myind]) > 0 )
{
if ( secp256k1_musig_partial_signature_serialize(ctx,psig,&MUSIG[myind]->partial_sig[MUSIG[myind]->myind]) > 0 )
{
for (i=0; i<32; i++)
sprintf(&str[i<<1],"%02x",psig[i]);
str[64] = 0;
result.push_back(Pair("myind",MUSIG[myind]->myind));
result.push_back(Pair("partialsig",str));
result.push_back(Pair("result","success"));
if ( n == 5 )
MUSIG[myind]->numpartials = 1;
return(result);
} else return(cclib_error(result,"error serializing partial sig"));
} else return(cclib_error(result,"error making partial sig"));
} else return(cclib_error(result,"error combining nonces"));
} else return(cclib_error(result,"wrong number of params, need 3: pkhash, ind, nonce"));
}
UniValue musig_partialsig(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
static secp256k1_context *ctx;
UniValue result(UniValue::VOBJ); int32_t i,ind,n,myind; uint8_t pkhash[32],psig[32],out64[64]; char str[129]; secp256k1_schnorrsig sig;
if ( ctx == 0 )
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
if ( params != 0 && (n= cJSON_GetArraySize(params)) >= 3 )
{
if ( n > 3 )
myind = juint(jitem(params,3),0);
else if ( n == 3 )
myind = 0;
if ( cclib_parsehash(pkhash,jitem(params,0),32) < 0 )
return(cclib_error(result,"error parsing pkhash"));
else if ( memcmp(MUSIG[myind]->pkhash,pkhash,32) != 0 )
return(cclib_error(result,"pkhash doesnt match session pkhash"));
else if ( (ind= juint(jitem(params,1),0)) < 0 || ind >= MUSIG[myind]->num )
return(cclib_error(result,"illegal ind for session"));
else if ( cclib_parsehash(psig,jitem(params,2),32) < 0 )
return(cclib_error(result,"error parsing psig"));
else if ( secp256k1_musig_partial_signature_parse(ctx,&MUSIG[myind]->partial_sig[ind],psig) == 0 )
return(cclib_error(result,"error parsing partialsig"));
result.push_back(Pair("added_index",ind));
//fprintf(stderr, "SIG: struct_size.%li using_struct.%i added_index.%i\n",MUSIG.size(), myind, ind);
MUSIG[myind]->numpartials++;
if ( MUSIG[myind]->numpartials >= MUSIG[myind]->num && secp256k1_musig_partial_sig_combine(ctx,&MUSIG[myind]->session,&sig,MUSIG[myind]->partial_sig,MUSIG[myind]->num) > 0 )
{
if ( secp256k1_schnorrsig_serialize(ctx,out64,&sig) > 0 )
{
result.push_back(Pair("result","success"));
for (i=0; i<64; i++)
sprintf(&str[i<<1],"%02x",out64[i]);
str[128] = 0;
result.push_back(Pair("combinedsig",str));
} else return(cclib_error(result,"error serializing combinedsig"));
}
else
{
if ( secp256k1_musig_partial_signature_serialize(ctx,psig,&MUSIG[myind]->partial_sig[MUSIG[myind]->myind]) > 0 )
{
result.push_back(Pair("myind",ind));
for (i=0; i<32; i++)
sprintf(&str[i<<1],"%02x",psig[i]);
str[64] = 0;
result.push_back(Pair("partialsig",str));
result.push_back(Pair("result","success"));
result.push_back(Pair("status","need more partialsigs"));
} else return(cclib_error(result,"error generating my partialsig"));
}
return(result);
} else return(cclib_error(result,"wrong number of params, need 3: pkhash, ind, partialsig"));
}
//int testmain(void);
UniValue musig_verify(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
static secp256k1_context *ctx;
UniValue result(UniValue::VOBJ); int32_t i,n; uint8_t msg[32],musig64[64]; secp256k1_pubkey combined_pk; secp256k1_schnorrsig musig; char str[129];
//testmain();
if ( ctx == 0 )
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
if ( params != 0 && (n= cJSON_GetArraySize(params)) == 3 )
{
if ( cclib_parsehash(msg,jitem(params,0),32) < 0 )
return(cclib_error(result,"error parsing pkhash"));
else if ( musig_parsepubkey(ctx,combined_pk,jitem(params,1)) < 0 )
return(cclib_error(result,"error parsing combined_pk"));
else if ( cclib_parsehash(musig64,jitem(params,2),64) < 0 )
return(cclib_error(result,"error parsing musig64"));
for (i=0; i<32; i++)
sprintf(&str[i*2],"%02x",msg[i]);
str[64] = 0;
result.push_back(Pair("msg",str));
result.push_back(Pair("combined_pk",jstr(jitem(params,1),0)));
for (i=0; i<64; i++)
sprintf(&str[i*2],"%02x",musig64[i]);
str[128] = 0;
result.push_back(Pair("combinedsig",str));
if ( secp256k1_schnorrsig_parse(ctx,&musig,&musig64[0]) > 0 )
{
if ( secp256k1_schnorrsig_verify(ctx,&musig,msg,&combined_pk) > 0 )
{
result.push_back(Pair("result","success"));
return(result);
} else return(cclib_error(result,"musig didnt verify"));
} else return(cclib_error(result,"couldnt parse musig64"));
} else return(cclib_error(result,"wrong number of params, need 3: msg, combined_pk, combinedsig"));
}
// helpers for rpc calls that generate/validate onchain tx
UniValue musig_rawtxresult(UniValue &result,std::string rawtx)
{
CTransaction tx;
if ( rawtx.size() > 0 )
{
result.push_back(Pair("hex",rawtx));
if ( DecodeHexTx(tx,rawtx) != 0 )
{
//if ( broadcastflag != 0 && myAddtomempool(tx) != 0 )
// RelayTransaction(tx);
result.push_back(Pair("txid",tx.GetHash().ToString()));
result.push_back(Pair("result","success"));
} else result.push_back(Pair("error","decode hex"));
} else result.push_back(Pair("error","couldnt finalize CCtx"));
return(result);
}
UniValue musig_send(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
UniValue result(UniValue::VOBJ); int32_t n; char *hexstr; std::string rawtx; int64_t amount; CPubKey musigpk,mypk;
if ( txfee == 0 )
txfee = MUSIG_TXFEE;
mypk = pubkey2pk(Mypubkey());
musigpk = GetUnspendable(cp,0);
if ( params != 0 && (n= cJSON_GetArraySize(params)) > 0 )
{
if ( n == 2 && (hexstr= jstr(jitem(params,0),0)) != 0 && is_hexstr(hexstr,0) == 66 )
{
CPubKey pk(ParseHex(hexstr));
amount = jdouble(jitem(params,1),0) * COIN + 0.0000000049;
if ( amount >= 3*txfee && AddNormalinputs(mtx,mypk,amount+2*txfee,64) >= amount+2*txfee )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount+txfee,musigpk));
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,musig_sendopret('x',pk));
return(musig_rawtxresult(result,rawtx));
} else return(cclib_error(result,"couldnt find funds or less than 0.0003"));
} else return(cclib_error(result,"must have 2 params: pk, amount"));
} else return(cclib_error(result,"not enough parameters"));
}
UniValue musig_spend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
static secp256k1_context *ctx;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
UniValue result(UniValue::VOBJ); std::string rawtx; CPubKey mypk,pk; secp256k1_pubkey combined_pk; char *scriptstr,*musigstr; uint8_t msg[32]; CTransaction vintx; uint256 prevhash,hashBlock; int32_t i,n,numvouts; char str[129]; CTxOut vout; secp256k1_schnorrsig musig;
if ( ctx == 0 )
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
if ( params != 0 && (n= cJSON_GetArraySize(params)) > 0 )
{
if ( n == 3 )
{
prevhash = juint256(jitem(params,0));
scriptstr = jstr(jitem(params,1),0);
musigstr = jstr(jitem(params,2),0);
if ( is_hexstr(scriptstr,0) != 0 && is_hexstr(musigstr,0) == 128 )
{
if ( txfee == 0 )
txfee = MUSIG_TXFEE;
mypk = pubkey2pk(Mypubkey());
std::vector<uint8_t> musig64(ParseHex(musigstr));
CScript scriptPubKey;
scriptPubKey.resize(strlen(scriptstr)/2);
decode_hex(&scriptPubKey[0],strlen(scriptstr)/2,scriptstr);
if ( myGetTransaction(prevhash,vintx,hashBlock) != 0 && (numvouts= vintx.vout.size()) > 1 )
{
vout.nValue = vintx.vout[0].nValue - txfee;
vout.scriptPubKey = scriptPubKey;
if ( musig_sendopretdecode(pk,vintx.vout[numvouts-1].scriptPubKey) == 'x' )
{
if ( secp256k1_schnorrsig_parse((const secp256k1_context *)ctx,&musig,(const uint8_t *)&musig64[0]) > 0 &&
secp256k1_ec_pubkey_parse(ctx,&combined_pk,pk.begin(),33) > 0 )
{
musig_prevoutmsg(msg,prevhash,vout.scriptPubKey);
{
for (i=0; i<32; i++)
sprintf(&str[i*2],"%02x",msg[i]);
str[64] = 0;
result.push_back(Pair("msg",str));
for (i=0; i<33; i++)
sprintf(&str[i*2],"%02x",((uint8_t *)pk.begin())[i]);
str[66] = 0;
result.push_back(Pair("combined_pk",str));
for (i=0; i<64; i++)
sprintf(&str[i*2],"%02x",musig64[i]);
str[128] = 0;
result.push_back(Pair("combinedsig",str));
}
if ( !secp256k1_schnorrsig_verify((const secp256k1_context *)ctx,&musig,(const uint8_t *)msg,(const secp256k1_pubkey *)&combined_pk) )
{
return(cclib_error(result,"musig didnt validate"));
}
mtx.vin.push_back(CTxIn(prevhash,MUSIG_PREVN));
mtx.vout.push_back(vout);
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,musig_spendopret('y',pk,musig64));
return(musig_rawtxresult(result,rawtx));
} else return(cclib_error(result,"couldnt parse pk or musig"));
} else return(cclib_error(result,"couldnt decode send opret"));
} else return(cclib_error(result,"couldnt find vin0"));
} else return(cclib_error(result,"script or musig is not hex"));
} else return(cclib_error(result,"need to have exactly 3 params sendtxid, scriptPubKey, musig"));
} else return(cclib_error(result,"params parse error"));
}
bool musig_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx)
{
static secp256k1_context *ctx;
secp256k1_pubkey combined_pk; CPubKey pk,checkpk; secp256k1_schnorrsig musig; uint256 hashBlock; CTransaction vintx; int32_t numvouts; std::vector<uint8_t> musig64; uint8_t msg[32];
if ( ctx == 0 )
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
if ( tx.vout.size() != 2 )
return eval->Invalid("numvouts != 2");
else if ( tx.vin.size() != 1 )
return eval->Invalid("numvins != 1");
else if ( IsCCInput(tx.vin[0].scriptSig) == 0 )
return eval->Invalid("illegal normal vin0");
else if ( myGetTransaction(tx.vin[0].prevout.hash,vintx,hashBlock) != 0 && (numvouts= vintx.vout.size()) > 1 )
{
if ( musig_sendopretdecode(pk,vintx.vout[numvouts-1].scriptPubKey) == 'x' )
{
if ( musig_spendopretdecode(checkpk,musig64,tx.vout[tx.vout.size()-1].scriptPubKey) == 'y' )
{
if ( pk == checkpk )
{
if ( secp256k1_schnorrsig_parse((const secp256k1_context *)ctx,&musig,(const uint8_t *)&musig64[0]) > 0 &&
secp256k1_ec_pubkey_parse(ctx,&combined_pk,pk.begin(),33) > 0 )
{
musig_prevoutmsg(msg,tx.vin[0].prevout.hash,tx.vout[0].scriptPubKey);
if ( !secp256k1_schnorrsig_verify((const secp256k1_context *)ctx,&musig,(const uint8_t *)msg,(const secp256k1_pubkey *)&combined_pk) )
return eval->Invalid("failed schnorrsig_verify");
else return(true);
} else return eval->Invalid("couldnt parse pk or musig");
} else return eval->Invalid("combined_pk didnt match send opret");
} else return eval->Invalid("failed decode musig spendopret");
} else return eval->Invalid("couldnt decode send opret");
} else return eval->Invalid("couldnt find vin0 tx");
}

View File

@@ -28,8 +28,8 @@ CC = @CC@
#CFLAGS=-O2
CFLAGS= @CFLAGS@ -fPIC
#LIBS=-lcurses
LIBS = @LIBS@
LIBS=-lcurses -lcurl
#LIBS = @LIBS@
#RM=rm -f
RM = rm -f
@@ -128,9 +128,11 @@ MISC = Makefile.std LICENSE.TXT rogue54.sln rogue54.vcproj rogue.spec \
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $*.c
#$(RM) rogue.so ; $(CC) -shared -o rogue.so cursesd.c $(OBJS1) $(OBJS2); $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
$(PROGRAM): $(HDRS) $(OBJS)
$(RM) rogue.so ; $(CC) -shared -o rogue.so $(OBJS1) $(OBJS2) -lcurses; $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
clean:
$(RM) $(OBJS1); $(RM) main.$(O) ; $(RM) rogue.so

222
src/cc/rogue/Makefile_win Normal file
View File

@@ -0,0 +1,222 @@
###############################################################################
#
# Makefile for rogue
#
# Rogue: Exploring the Dungeons of Doom
# Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
# All rights reserved.
#
# See the file LICENSE.TXT for full copyright and licensing information.
#
###############################################################################
###############################################################################
# Site configuration occurs beneath this comment
# Typically ./configure (autoconf tools) configures this section
# This section could be manually configured if autoconf/configure fails
###############################################################################
DISTNAME=rogue5.4.4
PACKAGE_TARNAME = rogue-5.4.4
PROGRAM=rogue
O=o
#CC=gcc
CC = x86_64-w64-mingw32-gcc
#CFLAGS=-O2
CFLAGS= -g -O2 -I./ncurses/include -I./ncurses/include/ncursesw -I../../../depends/x86_64-w64-mingw32/include
#LIBS=-lcurses
LIBS = -L./ncurses/lib -lncursesw -lcurl
#RM=rm -f
RM = rm -f
#GROFF=groff
GROFF = groff
#NROFF=nroff
NROFF = nroff
#TBL=tbl
TBL = tbl
#COLCRT=colcrt
COLCRT = colcrt
#SED=sed
SED = sed
#SCOREFILE=rogue54.scr
SCOREFILE = rogue.scr
#LOCKFILE=rogue54.lck
LOCKFILE = rogue.lck
#GROUPOWNER=games
GROUPOWNER =
#CPPFLAGS=-DHAVE_CONFIG_H
CPPFLAGS =-DHAVE_CONFIG_H
#DISTFILE = $(PROGRAM)
DISTFILE = $(DISTNAME)-x86_64-w64-mingw32
INSTALL=./install-sh
#INSTGROUP=-g games
INSTGROUP=
#INSTOWNER=-u root
INSTOWNER=
CHGRP=chgrp
MKDIR=mkdir
TOUCH=touch
RMDIR=rmdir
CHMOD=chmod
DESTDIR=
prefix=/usr/local
exec_prefix=${prefix}
datarootdir=${prefix}/share
datadir=${datarootdir}
bindir=${exec_prefix}/bin
mandir=${datarootdir}/man
docdir=${datarootdir}/doc/${PACKAGE_TARNAME}
man6dir = $(mandir)/man6
###############################################################################
# Site configuration occurs above this comment
# It should not be necessary to change anything below this comment
###############################################################################
HDRS = rogue.h extern.h score.h
OBJS1 = vers.$(O) extern.$(O) armor.$(O) chase.$(O) command.$(O) \
daemon.$(O) daemons.$(O) fight.$(O) init.$(O) io.$(O) list.$(O) \
mach_dep.$(O) rogue.$(O) mdport.$(O) misc.$(O) monsters.$(O) \
move.$(O) new_level.$(O)
OBJS2 = options.$(O) pack.$(O) passages.$(O) potions.$(O) rings.$(O) \
rip.$(O) rooms.$(O) save.$(O) scrolls.$(O) state.$(O) sticks.$(O) \
things.$(O) weapons.$(O) wizard.$(O) xcrypt.$(O)
OBJS = main.$(O) $(OBJS1) $(OBJS2)
CFILES = vers.c extern.c armor.c chase.c command.c daemon.c \
daemons.c fight.c init.c io.c list.c mach_dep.c \
main.c mdport.c misc.c monsters.c move.c new_level.c \
options.c pack.c passages.c potions.c rings.c rip.c \
rooms.c save.c scrolls.c state.c sticks.c things.c \
weapons.c wizard.c xcrypt.c
MISC_C = findpw.c scedit.c scmisc.c
DOCSRC = rogue.me.in rogue.6.in rogue.doc.in rogue.html.in rogue.cat.in
DOCS = $(PROGRAM).doc $(PROGRAM).html $(PROGRAM).cat $(PROGRAM).me \
$(PROGRAM).6
AFILES = configure Makefile.in configure.ac config.h.in config.sub config.guess \
install-sh rogue.6.in rogue.me.in rogue.html.in rogue.doc.in rogue.cat.in
MISC = Makefile.std LICENSE.TXT rogue54.sln rogue54.vcproj rogue.spec \
rogue.png rogue.desktop
.SUFFIXES: .obj
.c.obj:
$(CC) $(CFLAGS) $(CPPFLAGS) /c $*.c
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $*.c
#$(RM) rogue.so ; $(CC) -shared -o rogue.so cursesd.c $(OBJS1) $(OBJS2); $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
$(PROGRAM): $(HDRS) $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@.exe
clean:
$(RM) $(OBJS1); $(RM) main.$(O) ; $(RM) rogue.so
$(RM) $(OBJS2)
$(RM) core a.exe a.out a.exe.stackdump $(PROGRAM) $(PROGRAM).exe
$(RM) $(PROGRAM).tar $(PROGRAM).tar.gz $(PROGRAM).zip
$(RM) $(DISTNAME)/*
-rmdir $(DISTNAME)
maintainer-clean:
$(RM) config.h
$(RM) Makefile
$(RM) config.status
$(RM) -r autom4te.cache
$(RM) config.log
$(RM) $(PROGRAM).scr $(PROGRAM).lck
stddocs:
sed -e 's/rogue/rogue/' -e 's/rogue.scr/rogue.scr/' rogue.6.in > rogue.6
sed -e 's/rogue/rogue/' -e 's/rogue.scr/rogue.scr/' rogue.me.in > rogue.me
sed -e 's/rogue/rogue/' -e 's/rogue.scr/rogue.scr/' rogue.html.in > rogue,html
sed -e 's/rogue/rogue/' -e 's/rogue.scr/rogue.scr/' rogue.doc.in > rogue.doc
sed -e 's/rogue/rogue/' -e 's/rogue.scr/rogue.scr/' rogue.cat.in > rogue.cat
dist.src:
$(MAKE) $(MAKEFILE) clean
mkdir $(DISTNAME)
cp $(CFILES) $(HDRS) $(MISC) $(AFILES) $(DISTNAME)
tar cf $(DISTNAME)-src.tar $(DISTNAME)
gzip -f $(DISTNAME)-src.tar
rm -fr $(DISTNAME)
findpw: findpw.c xcrypt.o mdport.o xcrypt.o
$(CC) -s -o findpw findpw.c xcrypt.o mdport.o -lcurses
scedit: scedit.o scmisc.o vers.o mdport.o xcrypt.o
$(CC) -s -o scedit vers.o scedit.o scmisc.o mdport.o xcrypt.o -lcurses
scmisc.o scedit.o:
$(CC) -O -c $(SF) $*.c
$(PROGRAM).doc: rogue.me
if test "x$(GROFF)" != "x" -a "x$(SED)" != "x" ; then \
$(GROFF) -P-c -t -me -Tascii rogue.me | $(SED) -e 's/.\x08//g' > $(PROGRAM).doc ;\
elif test "x$(NROFF)" != "x" -a "x$(TBL)" != "x" -a "x$(COLCRT)" != "x" ; then \
tbl rogue.me | $(NROFF) -me | colcrt - > $(PROGRAM).doc ;\
fi
$(PROGRAM).cat: rogue.6
if test "x$(GROFF)" != "x" -a "x$(SED)" != "x" ; then \
$(GROFF) -Tascii -man rogue.6 | $(SED) -e 's/.\x08//g' > $(PROGRAM).cat ;\
elif test "x$(NROFF)" != "x" -a "x$(TBL)" != "x" -a "x$(COLCRT)" != "x" ; then \
$(NROFF) -man rogue.6 | $(COLCRT) - > $(PROGRAM).cat ;\
fi
dist: clean $(PROGRAM)
tar cf $(DISTFILE).tar $(PROGRAM) LICENSE.TXT $(DOCS)
gzip -f $(DISTFILE).tar
install: $(PROGRAM)
-$(TOUCH) test
-if test ! -f $(DESTDIR)$(SCOREFILE) ; then $(INSTALL) -m 0664 test $(DESTDIR)$(SCOREFILE) ; fi
-$(INSTALL) -m 0755 $(PROGRAM) $(DESTDIR)$(bindir)/$(PROGRAM)
-if test "x$(GROUPOWNER)" != "x" ; then \
$(CHGRP) $(GROUPOWNER) $(DESTDIR)$(SCOREFILE) ; \
$(CHGRP) $(GROUPOWNER) $(DESTDIR)$(bindir)/$(PROGRAM) ; \
$(CHMOD) 02755 $(DESTDIR)$(bindir)/$(PROGRAM) ; \
$(CHMOD) 0464 $(DESTDIR)$(SCOREFILE) ; \
fi
-if test -d $(man6dir) ; then $(INSTALL) -m 0644 rogue.6 $(DESTDIR)$(man6dir)/$(PROGRAM).6 ; fi
-if test ! -d $(man6dir) ; then $(INSTALL) -m 0644 rogue.6 $(DESTDIR)$(mandir)/$(PROGRAM).6 ; fi
-$(INSTALL) -m 0644 rogue.doc $(DESTDIR)$(docdir)/$(PROGRAM).doc
-$(INSTALL) -m 0644 rogue.html $(DESTDIR)$(docdir)/$(PROGRAM).html
-$(INSTALL) -m 0644 rogue.cat $(DESTDIR)$(docdir)/$(PROGRAM).cat
-$(INSTALL) -m 0644 LICENSE.TXT $(DESTDIR)$(docdir)/LICENSE.TXT
-$(INSTALL) -m 0644 rogue.me $(DESTDIR)$(docdir)/$(PROGRAM).me
-if test ! -f $(DESTDIR)$(LOCKFILE) ; then $(INSTALL) -m 0666 test $(DESTDIR)$(LOCKFILE) ; $(RM) $(DESTDIR)$(LOCKFILE) ; fi
-$(RM) test
uninstall:
-$(RM) $(DESTDIR)$(bindir)/$(PROGRAM)
-$(RM) $(DESTDIR)$(man6dir)/$(PROGRAM).6
-$(RM) $(DESTDIR)$(docdir)$(PROGRAM)/$(PROGRAM).doc
-$(RM) $(DESTDIR)$(LOCKFILE)
-$(RMDIR) $(DESTDIR)$(docdir)$(PROGRAM)
reinstall: uninstall install

View File

@@ -1,270 +0,0 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define if scorefile is top scores, not top players */
#define ALLSCORES 1
/* Define if checktime feature should be enabled */
/* #undef CHECKTIME */
/* Define to group owner of setgid executable */
/* #undef GROUPOWNER */
/* Define to 1 if you have the `alarm' function. */
#define HAVE_ALARM 1
/* Define to 1 if you have the <arpa/inet.h> header file. */
#define HAVE_ARPA_INET_H 1
/* Define to 1 if libcurses is requested */
#define HAVE_CURSES_H 1
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
/* #undef HAVE_DOPRNT */
/* Define to 1 if you have the `erasechar' function. */
#define HAVE_ERASECHAR 1
/* Define if ncurses has ESCDELAY variable */
#define HAVE_ESCDELAY 1
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define to 1 if you have the `fork' function. */
#define HAVE_FORK 1
/* Define to 1 if you have the `getgid' function. */
#define HAVE_GETGID 1
/* Define to 1 if you have the `getloadavg' function. */
#define HAVE_GETLOADAVG 1
/* Define to 1 if you have the `getpass' function. */
#define HAVE_GETPASS 1
/* Define to 1 if you have the `getpwuid' function. */
#define HAVE_GETPWUID 1
/* Define to 1 if you have the `getuid' function. */
#define HAVE_GETUID 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `killchar' function. */
#define HAVE_KILLCHAR 1
/* Define to 1 if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define to 1 if you have the `loadav' function. */
/* #undef HAVE_LOADAV */
/* Define to 1 if `lstat' has the bug that it succeeds when given the
zero-length file name argument. */
/* #undef HAVE_LSTAT_EMPTY_STRING_BUG */
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `memset' function. */
#define HAVE_MEMSET 1
/* Define to 1 if libncurses is requested */
/* #undef HAVE_NCURSES_H */
/* Define to 1 if you have the <ncurses/term.h> header file. */
/* #undef HAVE_NCURSES_TERM_H */
/* Define to 1 if you have the `nlist' function. */
/* #undef HAVE_NLIST */
/* Define to 1 if you have the <nlist.h> header file. */
#define HAVE_NLIST_H 1
/* Define to 1 if you have the <process.h> header file. */
/* #undef HAVE_PROCESS_H */
/* Define to 1 if you have the <pwd.h> header file. */
#define HAVE_PWD_H 1
/* Define to 1 if you have the `setenv' function. */
#define HAVE_SETENV 1
/* Define to 1 if you have the `setgid' function. */
#define HAVE_SETGID 1
/* Define to 1 if you have the `setregid' function. */
#define HAVE_SETREGID 1
/* Define to 1 if you have the `setresgid' function. */
/* #undef HAVE_SETRESGID */
/* Define to 1 if you have the `setresuid' function. */
/* #undef HAVE_SETRESUID */
/* Define to 1 if you have the `setreuid' function. */
#define HAVE_SETREUID 1
/* Define to 1 if you have the `setuid' function. */
#define HAVE_SETUID 1
/* Define to 1 if you have the `spawnl' function. */
/* #undef HAVE_SPAWNL */
/* Define to 1 if `stat' has the bug that it succeeds when given the
zero-length file name argument. */
/* #undef HAVE_STAT_EMPTY_STRING_BUG */
/* Define to 1 if stdbool.h conforms to C99. */
#define HAVE_STDBOOL_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strchr' function. */
#define HAVE_STRCHR 1
/* Define to 1 if you have the `strerror' function. */
#define HAVE_STRERROR 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#define HAVE_SYS_IOCTL_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <sys/utsname.h> header file. */
#define HAVE_SYS_UTSNAME_H 1
/* Define to 1 if you have the <termios.h> header file. */
#define HAVE_TERMIOS_H 1
/* Define to 1 if you have the <term.h> header file. */
#define HAVE_TERM_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the <utmp.h> header file. */
#define HAVE_UTMP_H 1
/* Define to 1 if you have the `vfork' function. */
#define HAVE_VFORK 1
/* Define to 1 if you have the <vfork.h> header file. */
/* #undef HAVE_VFORK_H */
/* Define to 1 if you have the `vprintf' function. */
#define HAVE_VPRINTF 1
/* Define to 1 if `fork' works. */
#define HAVE_WORKING_FORK 1
/* Define to 1 if `vfork' works. */
#define HAVE_WORKING_VFORK 1
/* Define to 1 if the system has the type `_Bool'. */
#define HAVE__BOOL 1
/* Define to 1 if you have the `_spawnl' function. */
/* #undef HAVE__SPAWNL */
/* define if we should use program's load average function instead of system
*/
/* #undef LOADAV */
/* Define to file to use for scoreboard lockfile */
#define LOCKFILE "rogue.lck"
/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
slash. */
/* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */
/* Define to include wizard mode */
/* #undef MASTER */
/* Define if maxusers feature should be enabled */
/* #undef MAXLOAD */
/* Define if maxusers feature should be enabled */
/* #undef MAXUSERS */
/* kernel file to pass to nlist() when reading load average (unlikely to work)
*/
/* #undef NAMELIST */
/* word for the number of scores to store in scoreboard */
#define NUMNAME "Ten"
/* number of scores to store in scoreboard */
#define NUMSCORES 10
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "yendor@rogueforge.net"
/* Define to the full name of this package. */
#define PACKAGE_NAME "Rogue"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "Rogue 5.4.4"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "rogue"
/* Define to the version of this package. */
#define PACKAGE_VERSION "5.4.4"
/* Define crypt(3) wizard mode password */
/* #undef PASSWD */
/* Define as the return type of signal handlers (`int' or `void'). */
#define RETSIGTYPE void
/* Define to file to use for scoreboard */
#define SCOREFILE "rogue.scr"
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
/* #undef TM_IN_SYS_TIME */
/* define if we should use program's user counting function instead of
system's */
/* #undef UCOUNT */
/* utmp like file to pass to ucount() when counting online users (unlikely to
work) */
/* #undef UTMP */
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef gid_t */
/* Define to `int' if <sys/types.h> does not define. */
/* #undef pid_t */
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef uid_t */
/* Define as `fork' if `vfork' does not work. */
/* #undef vfork */

View File

@@ -410,11 +410,13 @@ int32_t wgetnstr(WINDOW *win, char *str, int32_t n) // stub
return(0);
}
#ifndef __MINGW32__
int32_t getch(void)
{
fprintf(stderr,"unexpected and unsupported call to getch\n");
return(0);
}
#endif
int32_t md_readchar(void)
{
@@ -422,3 +424,9 @@ int32_t md_readchar(void)
return(0);
}
char *unctrl(char c)
{
static char ctrlstr[5];
sprintf(ctrlstr,"^%%%02x",c);
return(ctrlstr);
}

View File

@@ -48,7 +48,10 @@ extern WINDOW *stdscr,*curscr;
extern int32_t ESCDELAY;
typedef char chtype;
#ifndef __MINGW32__
int32_t getch(void); // stub
#endif
int32_t md_readchar(void); // stub
WINDOW *initscr(void);
@@ -123,9 +126,10 @@ int32_t wprintw(WINDOW *win,char *fmt,...);
int32_t mvprintw(int32_t y,int32_t x,char *fmt,...);
int32_t mvwprintw(WINDOW *win,int32_t y,int32_t x,char *fmt,...);
char *unctrl(char c);
#define A_CHARTEXT 0xff
#define baudrate() 9600
#define unctrl(a) "^x"
#define getmaxx(a) COLS
#define getmaxy(a) LINES
#define getyx(win,_argfory,_argforx) _argfory = win->y, _argforx = win->x

View File

@@ -22,11 +22,19 @@
*/
void rogue_restoreobject(THING *o,struct rogue_packitem *item);
int32_t rogue_total(THING *o)
{
if ( (o->o_flags & ISMANY) != 0 )
return(1);
else return(o->o_count);
}
void restore_player(struct rogue_state *rs)
{
int32_t i; THING *obj;
int32_t i,total = 0; THING *obj;
//rs->P.gold = purse;
max_hp = rs->P.hitpoints;
//pstats.s_hpt = max_hp;
pstats.s_str = rs->P.strength & 0xffff;
if ( (max_stats.s_str= (rs->P.strength >> 16) & 0xffff) == 0 )
max_stats.s_str = 16;
@@ -34,10 +42,13 @@ void restore_player(struct rogue_state *rs)
pstats.s_str = max_stats.s_str;
pstats.s_lvl = rs->P.level;
pstats.s_exp = rs->P.experience;
for (i=0; i<rs->P.packsize; i++)
for (i=0; i<rs->P.packsize&&i<MAXPACK; i++)
{
obj = new_item();
rogue_restoreobject(obj,&rs->P.roguepack[i]);
total += rogue_total(obj);
if ( total > ROGUE_MAXTOTAL )
break;
add_pack(rs,obj,TRUE);
}
}

View File

@@ -160,6 +160,18 @@ readchar(struct rogue_state *rs)
if ( rs->ind < rs->numkeys )
{
c = rs->keystrokes[rs->ind++];
if ( 0 )
{
static FILE *fp; static int32_t counter;
if ( fp == 0 )
fp = fopen("log","wb");
if ( fp != 0 )
{
fprintf(fp,"%d: (%c) hp.%d\n",counter,c,pstats.s_hpt);
fflush(fp);
counter++;
}
}
while ( c == 'Q' && rs->ind < rs->numkeys )
{
//fprintf(stderr,"Got 'Q' next (%c)\n",rs->keystrokes[rs->ind]); sleep(2);

View File

@@ -20,10 +20,17 @@
#include <memory.h>
#include <string.h>
#include <unistd.h>
#include <curl/curl.h>
#include <curl/easy.h>
char USERPASS[8192]; uint16_t ROGUE_PORT;
extern char Gametxidstr[67];
#define SMALLVAL 0.000000000000001
#define SATOSHIDEN ((uint64_t)100000000L)
#define dstr(x) ((double)(x) / SATOSHIDEN)
#define KOMODO_ASSETCHAIN_MAXLEN 65
char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],IPADDRESS[100];
#ifndef _BITS256
#define _BITS256
@@ -31,6 +38,19 @@ union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uin
typedef union _bits256 bits256;
#endif
double OS_milliseconds()
{
struct timeval tv; double millis;
#ifdef __MINGW32__
mingw_gettimeofday(&tv,NULL);
#else
gettimeofday(&tv,NULL);
#endif
millis = ((double)tv.tv_sec * 1000. + (double)tv.tv_usec / 1000.);
//printf("tv_sec.%ld usec.%d %f\n",tv.tv_sec,tv.tv_usec,millis);
return(millis);
}
int32_t _unhex(char c)
{
if ( c >= '0' && c <= '9' )
@@ -167,6 +187,23 @@ char *clonestr(char *str)
strcpy(clone,str);
return(clone);
}
char *parse_conf_line(char *line,char *field)
{
line += strlen(field);
for (; *line!='='&&*line!=0; line++)
break;
if ( *line == 0 )
return(0);
if ( *line == '=' )
line++;
while ( line[strlen(line)-1] == '\r' || line[strlen(line)-1] == '\n' || line[strlen(line)-1] == ' ' )
line[strlen(line)-1] = 0;
//printf("LINE.(%s)\n",line);
_stripwhite(line,0);
return(clonestr(line));
}
int32_t safecopy(char *dest,char *src,long len)
{
int32_t i = -1;
@@ -246,9 +283,538 @@ uint8_t *OS_fileptr(long *allocsizep,char *fname)
return((uint8_t *)retptr);
}
struct MemoryStruct { char *memory; size_t size; };
struct return_string { char *ptr; size_t len; };
// return data from the server
#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32)
#define CURL_GLOBAL_SSL (1<<0)
#define CURL_GLOBAL_WIN32 (1<<1)
/************************************************************************
*
* Initialize the string handler so that it is thread safe
*
************************************************************************/
void init_string(struct return_string *s)
{
s->len = 0;
s->ptr = (char *)calloc(1,s->len+1);
if ( s->ptr == NULL )
{
fprintf(stderr,"init_string malloc() failed\n");
exit(-1);
}
s->ptr[0] = '\0';
}
/************************************************************************
*
* Use the "writer" to accumulate text until done
*
************************************************************************/
size_t accumulatebytes(void *ptr,size_t size,size_t nmemb,struct return_string *s)
{
size_t new_len = s->len + size*nmemb;
s->ptr = (char *)realloc(s->ptr,new_len+1);
if ( s->ptr == NULL )
{
fprintf(stderr, "accumulate realloc() failed\n");
exit(-1);
}
memcpy(s->ptr+s->len,ptr,size*nmemb);
s->ptr[new_len] = '\0';
s->len = new_len;
return(size * nmemb);
}
/************************************************************************
*
* return the current system time in milliseconds
*
************************************************************************/
#define EXTRACT_BITCOIND_RESULT // if defined, ensures error is null and returns the "result" field
#ifdef EXTRACT_BITCOIND_RESULT
/************************************************************************
*
* perform post processing of the results
*
************************************************************************/
char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *params)
{
long i,j,len; char *retstr = 0; cJSON *json,*result,*error;
//printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr);
if ( command == 0 || rpcstr == 0 || rpcstr[0] == 0 )
{
if ( strcmp(command,"signrawtransaction") != 0 )
printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr);
return(rpcstr);
}
json = cJSON_Parse(rpcstr);
if ( json == 0 )
{
printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s can't parse.(%s) params.(%s)\n",debugstr,command,rpcstr,params);
free(rpcstr);
return(0);
}
result = cJSON_GetObjectItem(json,"result");
error = cJSON_GetObjectItem(json,"error");
if ( error != 0 && result != 0 )
{
if ( (error->type&0xff) == cJSON_NULL && (result->type&0xff) != cJSON_NULL )
{
retstr = cJSON_Print(result);
len = strlen(retstr);
if ( retstr[0] == '"' && retstr[len-1] == '"' )
{
for (i=1,j=0; i<len-1; i++,j++)
retstr[j] = retstr[i];
retstr[j] = 0;
}
}
else if ( (error->type&0xff) != cJSON_NULL || (result->type&0xff) != cJSON_NULL )
{
if ( strcmp(command,"signrawtransaction") != 0 )
printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC (%s) error.%s\n",debugstr,command,rpcstr);
}
free(rpcstr);
} else retstr = rpcstr;
free_json(json);
//fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: postprocess returns.(%s)\n",retstr);
return(retstr);
}
#endif
/************************************************************************
*
* perform the query
*
************************************************************************/
char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params)
{
static int didinit,count,count2; static double elapsedsum,elapsedsum2;
struct curl_slist *headers = NULL; struct return_string s; CURLcode res; CURL *curl_handle;
char *bracket0,*bracket1,*databuf = 0; long len; int32_t specialcase,numretries; double starttime;
if ( didinit == 0 )
{
didinit = 1;
curl_global_init(CURL_GLOBAL_ALL); //init the curl session
}
numretries = 0;
if ( debugstr != 0 && strcmp(debugstr,"BTCD") == 0 && command != 0 && strcmp(command,"SuperNET") == 0 )
specialcase = 1;
else specialcase = 0;
if ( url[0] == 0 )
strcpy(url,"http://127.0.0.1:7876/nxt");
if ( specialcase != 0 && 0 )
printf("<<<<<<<<<<< bitcoind_RPC: debug.(%s) url.(%s) command.(%s) params.(%s)\n",debugstr,url,command,params);
try_again:
if ( retstrp != 0 )
*retstrp = 0;
starttime = OS_milliseconds();
curl_handle = curl_easy_init();
init_string(&s);
headers = curl_slist_append(0,"Expect:");
curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )");
curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl_handle,CURLOPT_URL, url);
curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION, (void *)accumulatebytes); // send all data to this function
curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback
curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL, 1L); // supposed to fix "Alarm clock" and long jump crash
curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback
if ( strncmp(url,"https",5) == 0 )
{
curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0);
curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYHOST,0);
}
if ( userpass != 0 )
curl_easy_setopt(curl_handle,CURLOPT_USERPWD, userpass);
databuf = 0;
if ( params != 0 )
{
if ( command != 0 && specialcase == 0 )
{
len = strlen(params);
if ( len > 0 && params[0] == '[' && params[len-1] == ']' ) {
bracket0 = bracket1 = (char *)"";
}
else
{
bracket0 = (char *)"[";
bracket1 = (char *)"]";
}
databuf = (char *)malloc(256 + strlen(command) + strlen(params));
sprintf(databuf,"{\"id\":\"jl777\",\"method\":\"%s\",\"params\":%s%s%s}",command,bracket0,params,bracket1);
//printf("url.(%s) userpass.(%s) databuf.(%s)\n",url,userpass,databuf);
//
} //else if ( specialcase != 0 ) fprintf(stderr,"databuf.(%s)\n",params);
curl_easy_setopt(curl_handle,CURLOPT_POST,1L);
if ( databuf != 0 )
curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,databuf);
else curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,params);
}
//laststart = milliseconds();
res = curl_easy_perform(curl_handle);
curl_slist_free_all(headers);
curl_easy_cleanup(curl_handle);
if ( databuf != 0 ) // clean up temporary buffer
{
free(databuf);
databuf = 0;
}
if ( res != CURLE_OK )
{
numretries++;
if ( specialcase != 0 )
{
printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res);
free(s.ptr);
return(0);
}
else if ( numretries >= 1 )
{
//printf("Maximum number of retries exceeded!\n");
free(s.ptr);
return(0);
}
if ( (rand() % 1000) == 0 )
printf( "curl_easy_perform() failed: %s %s.(%s %s), retries: %d\n",curl_easy_strerror(res),debugstr,url,command,numretries);
free(s.ptr);
sleep((1<<numretries));
goto try_again;
}
else
{
if ( command != 0 && specialcase == 0 )
{
count++;
elapsedsum += (OS_milliseconds() - starttime);
if ( (count % 1000000) == 0)
printf("%d: ave %9.6f | elapsed %.3f millis | bitcoind_RPC.(%s) url.(%s)\n",count,elapsedsum/count,(OS_milliseconds() - starttime),command,url);
if ( retstrp != 0 )
{
*retstrp = s.ptr;
return(s.ptr);
}
return(post_process_bitcoind_RPC(debugstr,command,s.ptr,params));
}
else
{
if ( 0 && specialcase != 0 )
fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: BTCD.(%s) -> (%s)\n",params,s.ptr);
count2++;
elapsedsum2 += (OS_milliseconds() - starttime);
if ( (count2 % 10000) == 0)
printf("%d: ave %9.6f | elapsed %.3f millis | NXT calls.(%s) cmd.(%s)\n",count2,elapsedsum2/count2,(double)(OS_milliseconds() - starttime),url,command);
return(s.ptr);
}
}
printf("bitcoind_RPC: impossible case\n");
free(s.ptr);
return(0);
}
static size_t WriteMemoryCallback(void *ptr,size_t size,size_t nmemb,void *data)
{
size_t realsize = (size * nmemb);
struct MemoryStruct *mem = (struct MemoryStruct *)data;
mem->memory = (char *)((ptr != 0) ? realloc(mem->memory,mem->size + realsize + 1) : malloc(mem->size + realsize + 1));
if ( mem->memory != 0 )
{
if ( ptr != 0 )
memcpy(&(mem->memory[mem->size]),ptr,realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
}
//printf("got %d bytes\n",(int32_t)(size*nmemb));
return(realsize);
}
char *curl_post(CURL **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3)
{
struct MemoryStruct chunk; CURL *cHandle; long code; struct curl_slist *headers = 0;
if ( (cHandle= *cHandlep) == NULL )
*cHandlep = cHandle = curl_easy_init();
else curl_easy_reset(cHandle);
//#ifdef DEBUG
//curl_easy_setopt(cHandle,CURLOPT_VERBOSE, 1);
//#endif
curl_easy_setopt(cHandle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )");
curl_easy_setopt(cHandle,CURLOPT_SSL_VERIFYPEER,0);
//curl_easy_setopt(cHandle,CURLOPT_SSLVERSION,1);
curl_easy_setopt(cHandle,CURLOPT_URL,url);
curl_easy_setopt(cHandle,CURLOPT_CONNECTTIMEOUT,10);
if ( userpass != 0 && userpass[0] != 0 )
curl_easy_setopt(cHandle,CURLOPT_USERPWD,userpass);
if ( postfields != 0 && postfields[0] != 0 )
{
curl_easy_setopt(cHandle,CURLOPT_POST,1);
curl_easy_setopt(cHandle,CURLOPT_POSTFIELDS,postfields);
}
if ( hdr0 != NULL && hdr0[0] != 0 )
{
//printf("HDR0.(%s) HDR1.(%s) HDR2.(%s) HDR3.(%s)\n",hdr0!=0?hdr0:"",hdr1!=0?hdr1:"",hdr2!=0?hdr2:"",hdr3!=0?hdr3:"");
headers = curl_slist_append(headers,hdr0);
if ( hdr1 != 0 && hdr1[0] != 0 )
headers = curl_slist_append(headers,hdr1);
if ( hdr2 != 0 && hdr2[0] != 0 )
headers = curl_slist_append(headers,hdr2);
if ( hdr3 != 0 && hdr3[0] != 0 )
headers = curl_slist_append(headers,hdr3);
} //headers = curl_slist_append(0,"Expect:");
if ( headers != 0 )
curl_easy_setopt(cHandle,CURLOPT_HTTPHEADER,headers);
//res = curl_easy_perform(cHandle);
memset(&chunk,0,sizeof(chunk));
curl_easy_setopt(cHandle,CURLOPT_WRITEFUNCTION,WriteMemoryCallback);
curl_easy_setopt(cHandle,CURLOPT_WRITEDATA,(void *)&chunk);
curl_easy_perform(cHandle);
curl_easy_getinfo(cHandle,CURLINFO_RESPONSE_CODE,&code);
if ( headers != 0 )
curl_slist_free_all(headers);
if ( code != 200 )
printf("(%s) server responded with code %ld (%s)\n",url,code,chunk.memory);
return(chunk.memory);
}
uint16_t _komodo_userpass(char *username, char *password, FILE *fp)
{
char *rpcuser,*rpcpassword,*str,*ipaddress,line[8192]; uint16_t port = 0;
rpcuser = rpcpassword = 0;
username[0] = password[0] = 0;
while ( fgets(line,sizeof(line),fp) != 0 )
{
if ( line[0] == '#' )
continue;
//printf("line.(%s) %p %p\n",line,strstr(line,(char *)"rpcuser"),strstr(line,(char *)"rpcpassword"));
if ( (str= strstr(line,(char *)"rpcuser")) != 0 )
rpcuser = parse_conf_line(str,(char *)"rpcuser");
else if ( (str= strstr(line,(char *)"rpcpassword")) != 0 )
rpcpassword = parse_conf_line(str,(char *)"rpcpassword");
else if ( (str= strstr(line,(char *)"rpcport")) != 0 )
{
port = atoi(parse_conf_line(str,(char *)"rpcport"));
//fprintf(stderr,"rpcport.%u in file\n",port);
}
else if ( (str= strstr(line,(char *)"ipaddress")) != 0 )
{
ipaddress = parse_conf_line(str,(char *)"ipaddress");
strcpy(IPADDRESS,ipaddress);
}
}
if ( rpcuser != 0 && rpcpassword != 0 )
{
strcpy(username,rpcuser);
strcpy(password,rpcpassword);
}
//printf("rpcuser.(%s) rpcpassword.(%s) %u ipaddress.%s\n",rpcuser,rpcpassword,port,ipaddress);
if ( rpcuser != 0 )
free(rpcuser);
if ( rpcpassword != 0 )
free(rpcpassword);
return(port);
}
/*void komodo_statefname(char *fname,char *symbol,char *str)
{
int32_t n,len;
sprintf(fname,"%s",getDataDir());
if ( (n= (int32_t)strlen(ASSETCHAINS_SYMBOL)) != 0 )
{
len = (int32_t)strlen(fname);
if ( strcmp(ASSETCHAINS_SYMBOL,&fname[len - n]) == 0 )
fname[len - n] = 0;
else
{
printf("unexpected fname.(%s) vs %s [%s] n.%d len.%d (%s)\n",fname,symbol,ASSETCHAINS_SYMBOL,n,len,&fname[len - n]);
return;
}
}
else
{
#ifdef _WIN32
strcat(fname,"\\");
#else
strcat(fname,"/");
#endif
}
if ( symbol != 0 && symbol[0] != 0 && strcmp("KMD",symbol) != 0 )
{
strcat(fname,symbol);
//printf("statefname.(%s) -> (%s)\n",symbol,fname);
#ifdef _WIN32
strcat(fname,"\\");
#else
strcat(fname,"/");
#endif
}
strcat(fname,str);
//printf("test.(%s) -> [%s] statename.(%s) %s\n",test,ASSETCHAINS_SYMBOL,symbol,fname);
}*/
uint16_t komodo_userpass(char *userpass,char *symbol)
{
FILE *fp; uint16_t port = 0; char fname[512],username[512],password[512],confname[KOMODO_ASSETCHAIN_MAXLEN];
userpass[0] = 0;
if ( strcmp("KMD",symbol) == 0 )
{
#ifdef __APPLE__
sprintf(confname,"Komodo.conf");
#else
sprintf(confname,"komodo.conf");
#endif
}
else sprintf(confname,"%s.conf",symbol);
//komodo_statefname(fname,symbol,confname);
if ( (fp= fopen(confname,"rb")) != 0 )
{
port = _komodo_userpass(username,password,fp);
sprintf(userpass,"%s:%s",username,password);
if ( strcmp(symbol,ASSETCHAINS_SYMBOL) == 0 )
strcpy(USERPASS,userpass);
fclose(fp);
}
return(port);
}
#define is_cJSON_True(json) ((json) != 0 && ((json)->type & 0xff) == cJSON_True)
char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port)
{
//static void *cHandle;
char url[512],*retstr=0,*retstr2=0,postdata[8192];
if ( params == 0 || params[0] == 0 )
params = (char *)"[]";
if ( strlen(params) < sizeof(postdata)-128 )
{
sprintf(url,(char *)"http://%s:%u",IPADDRESS,port);
sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params);
//printf("[%s] (%s) postdata.(%s) params.(%s) USERPASS.(%s)\n",ASSETCHAINS_SYMBOL,url,postdata,params,USERPASS);
retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,userpass,method,params);
//retstr = curl_post(&cHandle,url,USERPASS,postdata,0,0,0,0);
}
return(retstr2);
}
#include "rogue.h"
void rogue_progress(struct rogue_state *rs,uint64_t seed,char *keystrokes,int32_t num)
{
char cmd[16384],hexstr[16384],params[32768],*retstr; int32_t i;
if ( rs->guiflag != 0 && Gametxidstr[0] != 0 )
{
for (i=0; i<num; i++)
sprintf(&hexstr[i<<1],"%02x",keystrokes[i]&0xff);
hexstr[i<<1] = 0;
if ( 0 )
{
sprintf(cmd,"./komodo-cli -ac_name=ROGUE cclib keystrokes 17 \\\"[%%22%s%%22,%%22%s%%22]\\\" >> keystrokes.log",Gametxidstr,hexstr);
if ( system(cmd) != 0 )
fprintf(stderr,"error issuing (%s)\n",cmd);
}
else
{
static FILE *fp;
if ( fp == 0 )
fp = fopen("keystrokes.log","a");
sprintf(params,"[\"keystrokes\",\"17\",\"[%%22%s%%22,%%22%s%%22]\"]",Gametxidstr,hexstr);
if ( (retstr= komodo_issuemethod(USERPASS,"cclib",params,ROGUE_PORT)) != 0 )
{
if ( fp != 0 )
{
fprintf(fp,"%s\n",params);
fprintf(fp,"%s\n",retstr);
fflush(fp);
}
free(retstr);
}
sleep(1);
}
}
}
int32_t rogue_setplayerdata(struct rogue_state *rs,char *gametxidstr)
{
char cmd[32768]; int32_t i,n,retval=-1; char params[1024],*filestr=0,*pname,*statusstr,*datastr,fname[128]; long allocsize; cJSON *retjson,*array,*item,*resultjson;
if ( rs->guiflag == 0 )
return(-1);
if ( gametxidstr == 0 || *gametxidstr == 0 )
return(retval);
if ( 0 )
{
sprintf(fname,"%s.gameinfo",gametxidstr);
sprintf(cmd,"./komodo-cli -ac_name=ROGUE cclib gameinfo 17 \\\"[%%22%s%%22]\\\" > %s",gametxidstr,fname);
if ( system(cmd) != 0 )
fprintf(stderr,"error issuing (%s)\n",cmd);
else filestr = (char *)OS_fileptr(&allocsize,fname);
}
else
{
sprintf(params,"[\"gameinfo\",\"17\",\"[%%22%s%%22]\"]",gametxidstr);
filestr = komodo_issuemethod(USERPASS,"cclib",params,ROGUE_PORT);
}
if ( filestr != 0 )
{
if ( (retjson= cJSON_Parse(filestr)) != 0 && (resultjson= jobj(retjson,"result")) != 0 )
{
//fprintf(stderr,"gameinfo.(%s)\n",jprint(resultjson,0));
if ( (array= jarray(&n,resultjson,"players")) != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
if ( is_cJSON_True(jobj(item,"ismine")) != 0 && (statusstr= jstr(item,"status")) != 0 )
{
if ( strcmp(statusstr,"registered") == 0 )
{
retval = 0;
if ( (item= jobj(item,"player")) != 0 && (datastr= jstr(item,"data")) != 0 )
{
if ( (pname= jstr(item,"pname")) != 0 && strlen(pname) < MAXSTR-1 )
strcpy(whoami,pname);
decode_hex((uint8_t *)&rs->P,(int32_t)strlen(datastr)/2,datastr);
fprintf(stderr,"set pname[%s] %s\n",pname==0?"":pname,jprint(item,0));
rs->restoring = 1;
}
}
}
}
}
free_json(retjson);
}
free(filestr);
}
return(retval);
}
int main(int argc, char **argv, char **envp)
{
uint64_t seed; FILE *fp = 0;
uint64_t seed; FILE *fp = 0; int32_t i,j,c; char userpass[8192];
for (i=j=0; argv[0][i]!=0&&j<sizeof(ASSETCHAINS_SYMBOL); i++)
{
c = argv[0][i];
if ( c == '\\' || c == '/' )
{
j = 0;
continue;
}
ASSETCHAINS_SYMBOL[j++] = toupper(c);
}
ASSETCHAINS_SYMBOL[j++] = 0;
ROGUE_PORT = komodo_userpass(userpass,ASSETCHAINS_SYMBOL);
if ( IPADDRESS[0] == 0 )
strcpy(IPADDRESS,"127.0.0.1");
printf("ASSETCHAINS_SYMBOL.(%s) port.%u (%s) IPADDRESS.%s \n",ASSETCHAINS_SYMBOL,ROGUE_PORT,USERPASS,IPADDRESS); sleep(1);
if ( argc == 2 && (fp=fopen(argv[1],"rb")) == 0 )
{
seed = atol(argv[1]);
@@ -259,8 +825,11 @@ int main(int argc, char **argv, char **envp)
{
if ( fp != 0 )
fclose(fp);
if ( ROGUE_PORT == 0 )
{
printf("you must copy ROGUE.conf from ~/.komodo/ROGUE/ROGUE.conf (or equivalent location) to current dir\n");
return(-1);
}
return(rogue(argc,argv,envp));
}
}

View File

@@ -33,14 +33,14 @@
#include <string.h>
#if defined(_WIN32)
#include <Windows.h>
#include <Lmcons.h>
#include <windows.h>
#include <lmcons.h>
#include <io.h>
#include <conio.h>
#pragma warning( disable: 4201 )
#include <shlobj.h>
#pragma warning( default: 4201 )
#include <Shlwapi.h>
#include <shlwapi.h>
#undef MOUSE_MOVED
#endif
@@ -705,7 +705,9 @@ md_erasechar()
#elif defined(VERASE)
return(_tty.c_cc[VERASE]); /* process erase character */
#else
#ifndef __MINGW32__
return(_tty.sg_erase); /* process erase character */
#endif
#endif
}
@@ -717,7 +719,9 @@ md_killchar()
#elif defined(VKILL)
return(_tty.c_cc[VKILL]);
#else
#ifndef __MINGW32__
return(_tty.sg_kill);
#endif
#endif
}

View File

@@ -157,37 +157,57 @@ out:
}
}
int32_t num_packitems(struct rogue_state *rs)
{
THING *list = pack;
int32_t type = 0,n = 0,total = 0;
for (; list != NULL; list = next(list))
{
if ( list->o_packch != 0 )
{
n++;
total += rogue_total(list);
}
}
if ( rs->guiflag != 0 )
{
char str[MAXSTR];
sprintf(str,"strength*2 %d vs total.%d vs %d inventory letters\n",ROGUE_MAXTOTAL,total,n);
add_line(rs,"%s",str);
}
if ( total > ROGUE_MAXTOTAL )
return(MAXPACK);
return(n);
}
/*
* pack_room:
* See if there's room in the pack. If not, print out an
* appropriate message
*/
bool
pack_room(struct rogue_state *rs,bool from_floor, THING *obj)
bool pack_room(struct rogue_state *rs,bool from_floor, THING *obj)
{
inpack = num_packitems();
if (++inpack > MAXPACK)
inpack = num_packitems(rs);
if ( ++inpack > MAXPACK )
{
if (!terse)
addmsg(rs,"there's ");
addmsg(rs,"no room");
if (!terse)
addmsg(rs," in your pack");
endmsg(rs);
if (from_floor)
move_msg(rs,obj);
inpack = MAXPACK;
return FALSE;
if (!terse)
addmsg(rs,"there's ");
addmsg(rs,"no room");
if (!terse)
addmsg(rs," in your pack");
endmsg(rs);
if (from_floor)
move_msg(rs,obj);
inpack = MAXPACK;
return FALSE;
}
//fprintf(stderr,"inpack.%d vs MAX.%d\n",inpack,MAXPACK), sleep(2);
if (from_floor)
if ( from_floor != 0 )
{
detach(lvl_obj, obj);
mvaddch(hero.y, hero.x, floor_ch());
chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
detach(lvl_obj, obj);
mvaddch(hero.y, hero.x, floor_ch());
chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
}
return TRUE;
}
@@ -247,22 +267,11 @@ pack_char()
* the given type.
*/
int32_t num_packitems()
{
THING *list = pack;
int32_t type = 0,n = 0;
for (; list != NULL; list = next(list))
{
if (!list->o_packch)
n++;
}
return(n);
}
bool
inventory(struct rogue_state *rs,THING *list, int type)
{
static char inv_temp[MAXSTR];
char inv_temp[MAXSTR];
n_objs = 0;
for (; list != NULL; list = next(list))
@@ -401,59 +410,63 @@ get_item(struct rogue_state *rs,char *purpose, int type)
{
THING *obj;
char ch;
if (pack == NULL)
msg(rs,"you aren't carrying anything");
msg(rs,"you aren't carrying anything");
else if (again)
if (last_pick)
return last_pick;
else
msg(rs,"you ran out");
else
{
for (;;)
{
if (!terse)
addmsg(rs,"which object do you want to ");
addmsg(rs,purpose);
if (terse)
addmsg(rs," what");
msg(rs,"? (* for list): ");
ch = readchar(rs);
mpos = 0;
/*
* Give the poor player a chance to abort the command
*/
if (ch == ESCAPE)
{
reset_last();
after = FALSE;
msg(rs,"");
return NULL;
}
n_objs = 1; /* normal case: person types one char */
if (ch == '*')
{
mpos = 0;
if (inventory(rs,pack, type) == 0)
{
after = FALSE;
return NULL;
}
continue;
}
for (obj = pack; obj != NULL; obj = next(obj))
if (obj->o_packch == ch)
break;
if (obj == NULL)
{
msg(rs,"'%s' is not a valid item",unctrl(ch));
continue;
}
else
return obj;
}
}
if (last_pick)
return last_pick;
else
msg(rs,"you ran out");
else
{
for (;;)
{
if (!terse)
addmsg(rs,"which object do you want to ");
addmsg(rs,purpose);
if (terse)
addmsg(rs," what");
msg(rs,"? (* for list): ");
ch = readchar(rs);
mpos = 0;
/*
* Give the poor player a chance to abort the command
*/
if (ch == ESCAPE)
{
reset_last();
after = FALSE;
msg(rs,"");
return NULL;
}
n_objs = 1; /* normal case: person types one char */
if (ch == '*')
{
mpos = 0;
if (inventory(rs,pack, type) == 0)
{
after = FALSE;
return NULL;
}
continue;
}
for (obj = pack; obj != NULL; obj = next(obj))
if (obj->o_packch == ch)
break;
if (obj == NULL)
{
//msg(rs,"'%s' is not a valid item",unctrl(ch));
//continue;
reset_last();
after = FALSE;
msg(rs,"'%s' is not a valid item",unctrl(ch));
return NULL;
}
else
return obj;
}
}
return NULL;
}

View File

@@ -238,7 +238,7 @@ death(struct rogue_state *rs,char monst)
//struct tm *localtime(const time_t *);
if ( rs->guiflag == 0 )
{
fprintf(stderr,"death during replay\n");
fprintf(stderr,"death during replay by (%c)\n",monst); //sleep(3);
rs->replaydone = (uint32_t)time(NULL);
return;
}

View File

@@ -25,8 +25,8 @@
* The main program, of course
*/
struct rogue_state globalR;
void garbage_collect();
char Gametxidstr[67];
void garbage_collect();
void purge_obj_guess(struct obj_info *array,int32_t n)
{
@@ -152,71 +152,24 @@ int32_t flushkeystrokes(struct rogue_state *rs)
}
#else
uint8_t *OS_fileptr(long *allocsizep,char *fname);
#define is_cJSON_True(json) ((json) != 0 && ((json)->type & 0xff) == cJSON_True)
#ifdef BUILD_ROGUE
// stubs for inside daemon
void rogue_progress(struct rogue_state *rs,uint64_t seed,char *keystrokes,int32_t num)
{
}
int32_t rogue_setplayerdata(struct rogue_state *rs,char *gametxidstr)
{
char cmd[32768]; int32_t i,n,retval=-1; char *filestr,*pname,*statusstr,*datastr,fname[128]; long allocsize; cJSON *retjson,*array,*item;
if ( gametxidstr == 0 || *gametxidstr == 0 )
return(retval);
sprintf(fname,"%s.gameinfo",gametxidstr);
sprintf(cmd,"./komodo-cli -ac_name=ROGUE cclib gameinfo 17 \\\"[%%22%s%%22]\\\" > %s",gametxidstr,fname);
if ( system(cmd) != 0 )
fprintf(stderr,"error issuing (%s)\n",cmd);
else
{
filestr = (char *)OS_fileptr(&allocsize,fname);
if ( (retjson= cJSON_Parse(filestr)) != 0 )
{
if ( (array= jarray(&n,retjson,"players")) != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
if ( is_cJSON_True(jobj(item,"ismine")) != 0 && (statusstr= jstr(item,"status")) != 0 )
{
if ( strcmp(statusstr,"registered") == 0 )
{
retval = 0;
if ( (item= jobj(item,"player")) != 0 && (datastr= jstr(item,"data")) != 0 )
{
if ( (pname= jstr(item,"pname")) != 0 && strlen(pname) < MAXSTR-1 )
strcpy(whoami,pname);
decode_hex((uint8_t *)&rs->P,(int32_t)strlen(datastr)/2,datastr);
fprintf(stderr,"set pname[%s] %s\n",pname==0?"":pname,jprint(item,0));
rs->restoring = 1;
}
}
}
}
}
free_json(retjson);
}
free(filestr);
}
return(retval);
}
void rogue_progress(uint64_t seed,char *keystrokes,int32_t num)
{
char cmd[16384],hexstr[16384]; int32_t i;
if ( Gametxidstr[0] != 0 )
{
for (i=0; i<num; i++)
sprintf(&hexstr[i<<1],"%02x",keystrokes[i]);
hexstr[i<<1] = 0;
sprintf(cmd,"./komodo-cli -ac_name=ROGUE cclib keystrokes 17 \\\"[%%22%s%%22,%%22%s%%22]\\\" >> keystrokes.log",Gametxidstr,hexstr);
if ( system(cmd) != 0 )
fprintf(stderr,"error issuing (%s)\n",cmd);
}
return(-1);
}
#endif
int32_t flushkeystrokes(struct rogue_state *rs)
{
if ( rs->num > 0 )
{
rogue_progress(rs->seed,rs->buffered,rs->num);
rogue_progress(rs,rs->seed,rs->buffered,rs->num);
memset(rs->buffered,0,sizeof(rs->buffered));
rs->counter++;
rs->num = 0;
@@ -230,15 +183,15 @@ void rogue_bailout(struct rogue_state *rs)
flushkeystrokes(rs);
//sleep(5);
return;
fprintf(stderr,"bailing out\n");
/*fprintf(stderr,"bailing out\n");
sprintf(cmd,"./komodo-cli -ac_name=ROGUE cclib bailout 17 \\\"[%%22%s%%22]\\\" >> bailout.log",Gametxidstr);
if ( system(cmd) != 0 )
fprintf(stderr,"error issuing (%s)\n",cmd);
fprintf(stderr,"error issuing (%s)\n",cmd);*/
}
int32_t rogue_replay2(uint8_t *newdata,uint64_t seed,char *keystrokes,int32_t num,struct rogue_player *player,int32_t sleepmillis)
{
struct rogue_state *rs; FILE *fp; int32_t i;
struct rogue_state *rs; FILE *fp; int32_t i,n;
rs = (struct rogue_state *)calloc(1,sizeof(*rs));
rs->seed = seed;
rs->keystrokes = keystrokes;
@@ -249,6 +202,8 @@ int32_t rogue_replay2(uint8_t *newdata,uint64_t seed,char *keystrokes,int32_t nu
rs->P = *player;
rs->restoring = 1;
//fprintf(stderr,"restore player packsize.%d HP.%d\n",rs->P.packsize,rs->P.hitpoints);
if ( rs->P.packsize > MAXPACK )
rs->P.packsize = MAXPACK;
}
globalR = *rs;
uint32_t starttime = (uint32_t)time(NULL);
@@ -278,8 +233,9 @@ int32_t rogue_replay2(uint8_t *newdata,uint64_t seed,char *keystrokes,int32_t nu
if ( newdata != 0 && rs->playersize > 0 )
memcpy(newdata,rs->playerdata,rs->playersize);
}
n = rs->playersize;
free(rs);
return(rs->playersize);
return(n);
}
#endif
@@ -353,6 +309,8 @@ int rogue(int argc, char **argv, char **envp)
{
char *env; int lowtime; struct rogue_state *rs = &globalR;
memset(rs,0,sizeof(*rs));
rs->guiflag = 1;
rs->sleeptime = 1; // non-zero to allow refresh()
if ( argc == 3 && strlen(argv[2]) == 64 )
{
rs->seed = atol(argv[1]);
@@ -363,8 +321,6 @@ int rogue(int argc, char **argv, char **envp)
return(-1);
}
} else rs->seed = 777;
rs->guiflag = 1;
rs->sleeptime = 1; // non-zero to allow refresh()
md_init();
#ifdef MASTER
@@ -545,13 +501,13 @@ tstp(int ignored)
getyx(curscr, y, x);
mvcur(y, x, oy, ox);
fflush(stdout);
//wmove(curscr,oy,ox);
#ifndef __APPLE__
wmove(curscr,oy,ox);
/*#ifndef __APPLE__
#ifndef BUILD_ROGUE
curscr->_cury = oy;
curscr->_curx = ox;
#endif
#endif
#endif*/
}
/*
@@ -604,13 +560,15 @@ playit(struct rogue_state *rs)
}
else
{
if ( rs->needflush != 0 && rs->num > 1024 )
if ( rs->needflush != 0 && rs->num > 1000 )
{
if ( flushkeystrokes(rs) == 0 )
rs->needflush = 0;
}
}
}
if ( rs->guiflag != 0 )
flushkeystrokes(rs);
endit(0);
}
@@ -647,7 +605,7 @@ int32_t _quit()
}
else
{
fprintf(stderr,"'Q' answer (%c)\n",c);
//fprintf(stderr,"'Q' answer (%c)\n",c);
move(0, 0);
clrtoeol();
status(rs);

View File

@@ -371,7 +371,6 @@ struct rogue_state
};
extern struct rogue_state globalR;
int rogue(int argc, char **argv, char **envp);
void rogueiterate(struct rogue_state *rs);
int32_t roguefname(char *fname,uint64_t seed,int32_t counter);
@@ -380,6 +379,10 @@ int32_t rogue_restorepack(struct rogue_state *rs);
void restore_player(struct rogue_state *rs);
int32_t rogue_replay2(uint8_t *newdata,uint64_t seed,char *keystrokes,int32_t num,struct rogue_player *player,int32_t sleepmillis);
void rogue_bailout(struct rogue_state *rs);
void rogue_progress(struct rogue_state *rs,uint64_t seed,char *keystrokes,int32_t num);
int32_t rogue_setplayerdata(struct rogue_state *rs,char *gametxidstr);
#define ROGUE_MAXTOTAL (pstats.s_str*2)
/*
* Help list
@@ -802,7 +805,8 @@ THING *leave_pack(struct rogue_state *rs,THING *obj, bool newobj, bool all);
THING *new_item(void);
THING *new_thing(struct rogue_state *rs);
void end_line(struct rogue_state *rs);
int32_t num_packitems();
int32_t num_packitems(struct rogue_state *rs);
int32_t rogue_total(THING *o);
void runners(struct rogue_state *rs,int);
void land(struct rogue_state *rs,int);

View File

@@ -25,7 +25,7 @@ struct rogue_packitem
};
struct rogue_player
{
int32_t gold,hitpoints,strength,level,experience,packsize,dungeonlevel,pad;
int32_t gold,hitpoints,strength,level,experience,packsize,dungeonlevel,amulet;
struct rogue_packitem roguepack[MAXPACK];
};
int32_t rogue_replay2(uint8_t *newdata,uint64_t seed,char *keystrokes,int32_t num,struct rogue_player *player,int32_t sleepmillis);

View File

@@ -1432,7 +1432,7 @@ rs_write_object(struct rogue_state *rs,FILE *savef, THING *o)
if ( o->_o._o_packch != 0 )
{
item = &rs->P.roguepack[rs->P.packsize];
if ( pstats.s_hpt <= 0 )
if ( 1 && pstats.s_hpt <= 0 )
{
//fprintf(stderr,"KILLED\n");
rs->P.gold = -1;
@@ -1452,6 +1452,7 @@ rs_write_object(struct rogue_state *rs,FILE *savef, THING *o)
rs->P.level = pstats.s_lvl;
rs->P.experience = pstats.s_exp;
rs->P.dungeonlevel = level;
rs->P.amulet = amulet;
//fprintf(stderr,"%ld gold.%d hp.%d strength.%d/%d level.%d exp.%d %d\n",ftell(savef),purse,max_hp,pstats.s_str,max_stats.s_str,pstats.s_lvl,pstats.s_exp,level);
}
//fprintf(stderr,"object (%s) x.%d y.%d type.%d pack.(%c:%d)\n",inv_name(o,FALSE),o->_o._o_pos.x,o->_o._o_pos.y,o->_o._o_type,o->_o._o_packch,o->_o._o_packch);

View File

@@ -265,7 +265,7 @@ int32_t rogue_iamregistered(int32_t maxplayers,uint256 gametxid,CTransaction tx,
vout = i+1;
if ( myIsutxo_spent(spenttxid,gametxid,vout) >= 0 )
{
if ( GetTransaction(spenttxid,spenttx,hashBlock,false) != 0 && spenttx.vout.size() > 0 )
if ( myGetTransaction(spenttxid,spenttx,hashBlock) != 0 && spenttx.vout.size() > 0 )
{
Getscriptaddress(destaddr,spenttx.vout[0].scriptPubKey);
if ( strcmp(myrogueaddr,destaddr) == 0 )
@@ -296,7 +296,7 @@ int32_t rogue_playersalive(int32_t &numplayers,uint256 gametxid,int32_t maxplaye
uint64_t rogue_gamefields(UniValue &obj,int64_t maxplayers,int64_t buyin,uint256 gametxid,char *myrogueaddr)
{
CBlockIndex *pindex; int32_t ht,delay,numplayers; uint256 hashBlock; uint64_t seed=0; char cmd[512]; CTransaction tx;
if ( GetTransaction(gametxid,tx,hashBlock,false) != 0 && (pindex= komodo_blockindex(hashBlock)) != 0 )
if ( myGetTransaction(gametxid,tx,hashBlock) != 0 && (pindex= komodo_blockindex(hashBlock)) != 0 )
{
ht = pindex->GetHeight();
delay = ROGUE_REGISTRATION * (maxplayers > 1);
@@ -325,18 +325,26 @@ uint64_t rogue_gamefields(UniValue &obj,int64_t maxplayers,int64_t buyin,uint256
return(seed);
}
int32_t rogue_isvalidgame(struct CCcontract_info *cp,int32_t &gameheight,CTransaction &tx,int64_t &buyin,int32_t &maxplayers,uint256 txid)
int32_t rogue_isvalidgame(struct CCcontract_info *cp,int32_t &gameheight,CTransaction &tx,int64_t &buyin,int32_t &maxplayers,uint256 txid,int32_t unspentv0)
{
uint256 hashBlock; int32_t i,numvouts; char coinaddr[64]; CPubKey roguepk; uint64_t txfee = 10000;
buyin = maxplayers = 0;
if ( GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 1 )
if ( (txid == zeroid || myGetTransaction(txid,tx,hashBlock) != 0) && (numvouts= tx.vout.size()) > 1 )
{
gameheight = komodo_blockheight(hashBlock);
if ( IsCClibvout(cp,tx,0,cp->unspendableCCaddr) >= txfee && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,0) == 0 )
if ( txid != zeroid )
gameheight = komodo_blockheight(hashBlock);
else
{
txid = tx.GetHash();
//fprintf(stderr,"set txid %s %llu\n",txid.GetHex().c_str(),(long long)CCgettxout(txid,0,1));
}
if ( IsCClibvout(cp,tx,0,cp->unspendableCCaddr) == txfee && (unspentv0 == 0 || CCgettxout(txid,0,1) == txfee) )
{
if ( rogue_newgameopreturndecode(buyin,maxplayers,tx.vout[numvouts-1].scriptPubKey) == 'G' )
{
if ( numvouts > maxplayers+1 )
if ( maxplayers < 1 || maxplayers > ROGUE_MAXPLAYERS || buyin < 0 )
return(-6);
if ( numvouts > 2*maxplayers+1 )
{
for (i=0; i<maxplayers; i++)
{
@@ -346,10 +354,11 @@ int32_t rogue_isvalidgame(struct CCcontract_info *cp,int32_t &gameheight,CTransa
break;
}
if ( i == maxplayers )
{
// dimxy: make sure no vouts to any address other than main CC and 0.0001 faucet
return(0);
else return(-5);
}
else return(-4);
} else return(-5);
} else return(-4);
} else return(-3);
} else return(-2);
} else return(-1);
@@ -434,20 +443,20 @@ int32_t rogue_iterateplayer(uint256 &registertxid,uint256 firsttxid,int32_t firs
int32_t rogue_playerdata(struct CCcontract_info *cp,uint256 &origplayergame,uint256 &tokenid,CPubKey &pk,std::vector<uint8_t> &playerdata,std::string &symbol,std::string &pname,uint256 playertxid)
{
uint256 origplayertxid,hashBlock,gametxid,registertxid; CTransaction gametx,playertx,highlandertx; std::vector<uint8_t> vopret; uint8_t *script,e,f; int32_t i,regslot,gameheight,numvouts,maxplayers; int64_t buyin;
if ( GetTransaction(playertxid,playertx,hashBlock,false) != 0 && (numvouts= playertx.vout.size()) > 0 )
if ( myGetTransaction(playertxid,playertx,hashBlock) != 0 && (numvouts= playertx.vout.size()) > 0 )
{
if ( (f= rogue_highlanderopretdecode(gametxid,tokenid,regslot,pk,playerdata,symbol,pname,playertx.vout[numvouts-1].scriptPubKey)) == 'H' || f == 'Q' )
{
if ( tokenid != zeroid )
{
playertxid = tokenid;
if ( GetTransaction(playertxid,playertx,hashBlock,false) == 0 || (numvouts= playertx.vout.size()) <= 0 )
if ( myGetTransaction(playertxid,playertx,hashBlock) == 0 || (numvouts= playertx.vout.size()) <= 0 )
{
fprintf(stderr,"couldnt get tokenid.%s\n",playertxid.GetHex().c_str());
return(-2);
}
}
if ( rogue_isvalidgame(cp,gameheight,gametx,buyin,maxplayers,gametxid) == 0 )
if ( rogue_isvalidgame(cp,gameheight,gametx,buyin,maxplayers,gametxid,0) == 0 )
{
//fprintf(stderr,"playertxid.%s got vin.%s/v%d gametxid.%s iterate.%d\n",playertxid.ToString().c_str(),playertx.vin[1].prevout.hash.ToString().c_str(),(int32_t)playertx.vin[1].prevout.n-maxplayers,gametxid.ToString().c_str(),rogue_iterateplayer(registertxid,gametxid,playertx.vin[1].prevout.n-maxplayers,playertxid));
if ( (tokenid != zeroid || playertx.vin[1].prevout.hash == gametxid) && rogue_iterateplayer(registertxid,gametxid,playertx.vin[1].prevout.n-maxplayers,playertxid) == 0 )
@@ -463,12 +472,25 @@ int32_t rogue_playerdata(struct CCcontract_info *cp,uint256 &origplayergame,uint
int32_t rogue_playerdataspend(CMutableTransaction &mtx,uint256 playertxid,int32_t vout,uint256 origplayergame)
{
int64_t txfee = 10000;
int64_t txfee = 10000; CTransaction tx; uint256 hashBlock;
if ( CCgettxout(playertxid,vout,1) == 1 ) // not sure if this is enough validation
{
mtx.vin.push_back(CTxIn(playertxid,vout,CScript()));
return(0);
} else return(-1);
}
else
{
vout = 0;
if ( myGetTransaction(playertxid,tx,hashBlock) != 0 && tx.vout[vout].nValue == 1 && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 )
{
if ( CCgettxout(playertxid,vout,1) == 1 ) // not sure if this is enough validation
{
mtx.vin.push_back(CTxIn(playertxid,vout,CScript()));
return(0);
}
}
return(-1);
}
}
int32_t rogue_findbaton(struct CCcontract_info *cp,uint256 &playertxid,char **keystrokesp,int32_t &numkeys,int32_t &regslot,std::vector<uint8_t> &playerdata,uint256 &batontxid,int32_t &batonvout,int64_t &batonvalue,int32_t &batonht,uint256 gametxid,CTransaction gametx,int32_t maxplayers,char *destaddr,int32_t &numplayers,std::string &symbol,std::string &pname)
@@ -478,9 +500,10 @@ int32_t rogue_findbaton(struct CCcontract_info *cp,uint256 &playertxid,char **ke
playertxid = zeroid;
for (i=0; i<maxplayers; i++)
{
//fprintf(stderr,"findbaton.%d of %d\n",i,maxplayers);
if ( myIsutxo_spent(spenttxid,gametxid,i+1) >= 0 )
{
if ( GetTransaction(spenttxid,spenttx,hashBlock,false) != 0 && spenttx.vout.size() > 0 )
if ( myGetTransaction(spenttxid,spenttx,hashBlock) != 0 && spenttx.vout.size() > 0 )
{
numplayers++;
Getscriptaddress(ccaddr,spenttx.vout[0].scriptPubKey);
@@ -495,7 +518,7 @@ int32_t rogue_findbaton(struct CCcontract_info *cp,uint256 &playertxid,char **ke
}
if ( matches == 1 )
{
if ( myIsutxo_spent(spenttxid,gametxid,maxplayers+i+1) < 0 )
if ( 1 || myIsutxo_spent(spenttxid,gametxid,maxplayers+i+1) < 0 )
{
numvouts = matchtx.vout.size();
//fprintf(stderr,"matchtxid.%s matches.%d numvouts.%d\n",matchtx.GetHash().GetHex().c_str(),matches,numvouts);
@@ -522,9 +545,10 @@ int32_t rogue_findbaton(struct CCcontract_info *cp,uint256 &playertxid,char **ke
return(-2);
}
txid = spenttxid;
//fprintf(stderr,"next txid.%s/v%d\n",txid.GetHex().c_str(),spentvini);
if ( spentvini != 0 )
return(-3);
if ( keystrokesp != 0 && GetTransaction(spenttxid,spenttx,hashBlock,false) != 0 && spenttx.vout.size() >= 2 )
if ( keystrokesp != 0 && myGetTransaction(spenttxid,spenttx,hashBlock) != 0 && spenttx.vout.size() >= 2 )
{
uint256 g,b; CPubKey p; std::vector<uint8_t> k;
if ( rogue_keystrokesopretdecode(g,b,p,k,spenttx.vout[spenttx.vout.size()-1].scriptPubKey) == 'K' )
@@ -541,13 +565,14 @@ int32_t rogue_findbaton(struct CCcontract_info *cp,uint256 &playertxid,char **ke
fprintf(stderr,"rogue_findbaton n.%d, seems something is wrong\n",n);
return(-5);
}
//fprintf(stderr,"n.%d txid.%s\n",n,txid.GetHex().c_str());
}
//fprintf(stderr,"set baton %s\n",txid.GetHex().c_str());
batontxid = txid;
batonvout = 0; // not vini
// how to detect timeout, bailedout, highlander
hashBlock = zeroid;
if ( GetTransaction(batontxid,batontx,hashBlock,false) != 0 && batontx.vout.size() > 0 )
if ( myGetTransaction(batontxid,batontx,hashBlock) != 0 && batontx.vout.size() > 0 )
{
if ( hashBlock == zeroid )
batonht = komodo_nextheight();
@@ -555,16 +580,16 @@ int32_t rogue_findbaton(struct CCcontract_info *cp,uint256 &playertxid,char **ke
return(-4);
else batonht = pindex->GetHeight();
batonvalue = batontx.vout[0].nValue;
//printf("keystrokes[%d]\n",numkeys);
//printf("batonht.%d keystrokes[%d]\n",batonht,numkeys);
return(0);
}
}
} else fprintf(stderr,"couldnt find baton\n");
} else fprintf(stderr,"error with playerdata\n");
} else fprintf(stderr,"findbaton opret error\n");
}
else
{
fprintf(stderr,"already played\n");
return(-5);
return(-6);
}
}
return(-1);
@@ -577,7 +602,7 @@ void rogue_gameplayerinfo(struct CCcontract_info *cp,UniValue &obj,uint256 gamet
destaddr[0] = 0;
if ( myIsutxo_spent(spenttxid,gametxid,vout) >= 0 )
{
if ( GetTransaction(spenttxid,spenttx,hashBlock,false) != 0 && spenttx.vout.size() > 0 )
if ( myGetTransaction(spenttxid,spenttx,hashBlock) != 0 && spenttx.vout.size() > 0 )
Getscriptaddress(destaddr,spenttx.vout[0].scriptPubKey);
}
obj.push_back(Pair("slot",(int64_t)vout-1));
@@ -585,7 +610,7 @@ void rogue_gameplayerinfo(struct CCcontract_info *cp,UniValue &obj,uint256 gamet
{
if ( CCgettxout(gametxid,maxplayers+vout,1) == 10000 )
{
if ( GetTransaction(batontxid,batontx,hashBlock,false) != 0 && batontx.vout.size() > 1 )
if ( myGetTransaction(batontxid,batontx,hashBlock) != 0 && batontx.vout.size() > 1 )
{
if ( rogue_registeropretdecode(gtxid,tokenid,ptxid,batontx.vout[batontx.vout.size()-1].scriptPubKey) == 'R' && ptxid == playertxid && gtxid == gametxid )
obj.push_back(Pair("status","registered"));
@@ -646,7 +671,7 @@ UniValue rogue_newgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
UniValue result(UniValue::VOBJ); std::string rawtx; CPubKey roguepk,mypk; char *jsonstr; uint64_t inputsum,change,required,buyin=0; int32_t i,n,maxplayers = 1;
if ( txfee == 0 )
txfee = 10000;
if ( (params= cclib_reparse(&n,params)) != 0 )
if ( params != 0 && (n= cJSON_GetArraySize(params)) > 0 )
{
if ( n > 0 )
{
@@ -682,7 +707,7 @@ UniValue rogue_playerinfo(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
UniValue result(UniValue::VOBJ); std::vector<uint8_t> playerdata; uint256 playertxid,tokenid,origplayergame;int32_t n; CPubKey pk; bits256 t; std::string symbol,pname;
result.push_back(Pair("result","success"));
rogue_univalue(result,"playerinfo",-1,-1);
if ( (params= cclib_reparse(&n,params)) != 0 )
if ( params != 0 && (n= cJSON_GetArraySize(params)) > 0 )
{
if ( n > 0 )
{
@@ -712,12 +737,12 @@ UniValue rogue_register(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
roguepk = GetUnspendable(cp,0);
rogue_univalue(result,"register",-1,-1);
playertxid = tokenid = zeroid;
if ( (params= cclib_reparse(&n,params)) != 0 )
if ( params != 0 && (n= cJSON_GetArraySize(params)) > 0 )
{
if ( n > 0 )
{
gametxid = juint256(jitem(params,0));
if ( (err= rogue_isvalidgame(cp,gameheight,tx,buyin,maxplayers,gametxid)) == 0 )
if ( (err= rogue_isvalidgame(cp,gameheight,tx,buyin,maxplayers,gametxid,1)) == 0 )
{
if ( n > 1 )
{
@@ -758,7 +783,7 @@ UniValue rogue_register(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
if ( playertxid != zeroid )
{
voutPubkeysEmpty.push_back(burnpk);
if ( GetTransaction(playertxid,playertx,hashBlock,false) != 0 )
if ( myGetTransaction(playertxid,playertx,hashBlock) != 0 )
{
if ( (funcid= DecodeTokenOpRet(playertx.vout.back().scriptPubKey, e, tid, voutPubkeys, vopretExtra)) != 0)
{ // if token in the opret
@@ -792,7 +817,7 @@ UniValue rogue_keystrokes(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
if ( txfee == 0 )
txfee = 10000;
rogue_univalue(result,"keystrokes",-1,-1);
if ( (params= cclib_reparse(&n,params)) != 0 && n == 2 && (keystrokestr= jstr(jitem(params,1),0)) != 0 )
if ( params != 0 && (n= cJSON_GetArraySize(params)) == 2 && (keystrokestr= jstr(jitem(params,1),0)) != 0 )
{
gametxid = juint256(jitem(params,0));
result.push_back(Pair("gametxid",gametxid.GetHex()));
@@ -801,7 +826,7 @@ UniValue rogue_keystrokes(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
mypk = pubkey2pk(Mypubkey());
roguepk = GetUnspendable(cp,0);
GetCCaddress1of2(cp,destaddr,roguepk,mypk);
if ( rogue_isvalidgame(cp,gameheight,tx,buyin,maxplayers,gametxid) == 0 )
if ( rogue_isvalidgame(cp,gameheight,tx,buyin,maxplayers,gametxid,1) == 0 )
{
if ( rogue_findbaton(cp,playertxid,0,numkeys,regslot,playerdata,batontxid,batonvout,batonvalue,batonht,gametxid,tx,maxplayers,destaddr,numplayers,symbol,pname) == 0 )
{
@@ -809,7 +834,7 @@ UniValue rogue_keystrokes(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
result.push_back(Pair("playertxid",playertxid.GetHex()));
if ( maxplayers == 1 || nextheight <= batonht+ROGUE_MAXKEYSTROKESGAP )
{
mtx.vin.push_back(CTxIn(batontxid,batonvout,CScript()));
mtx.vin.push_back(CTxIn(batontxid,batonvout,CScript())); //this validates user if pk
mtx.vout.push_back(MakeCC1of2vout(cp->evalcode,batonvalue-txfee,roguepk,mypk));
Myprivkey(mypriv);
CCaddr1of2set(cp,roguepk,mypk,mypriv,destaddr);
@@ -822,40 +847,45 @@ UniValue rogue_keystrokes(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
} else return(cclib_error(result,"couldnt reparse params"));
}
char *rogue_extractgame(char *str,int32_t *numkeysp,std::vector<uint8_t> &newdata,uint64_t &seed,uint256 &playertxid,struct CCcontract_info *cp,uint256 gametxid,char *rogueaddr)
char *rogue_extractgame(int32_t makefiles,char *str,int32_t *numkeysp,std::vector<uint8_t> &newdata,uint64_t &seed,uint256 &playertxid,struct CCcontract_info *cp,uint256 gametxid,char *rogueaddr)
{
CPubKey roguepk; int32_t i,num,maxplayers,gameheight,batonht,batonvout,numplayers,regslot,numkeys,err; std::string symbol,pname; CTransaction gametx; int64_t buyin,batonvalue; char fname[64],*keystrokes = 0; std::vector<uint8_t> playerdata; uint256 batontxid; FILE *fp; uint8_t newplayer[10000]; struct rogue_player P,endP;
roguepk = GetUnspendable(cp,0);
*numkeysp = 0;
seed = 0;
if ( (err= rogue_isvalidgame(cp,gameheight,gametx,buyin,maxplayers,gametxid)) == 0 )
num = numkeys = 0;
playertxid = zeroid;
if ( (err= rogue_isvalidgame(cp,gameheight,gametx,buyin,maxplayers,gametxid,0)) == 0 )
{
if ( rogue_findbaton(cp,playertxid,&keystrokes,numkeys,regslot,playerdata,batontxid,batonvout,batonvalue,batonht,gametxid,gametx,maxplayers,rogueaddr,numplayers,symbol,pname) == 0 )
{
UniValue obj;
seed = rogue_gamefields(obj,maxplayers,buyin,gametxid,rogueaddr);
//fprintf(stderr,"(%s) found baton %s numkeys.%d seed.%llu playerdata.%d\n",pname.size()!=0?pname.c_str():Rogue_pname.c_str(),batontxid.ToString().c_str(),numkeys,(long long)seed,(int32_t)playerdata.size());
//fprintf(stderr,"(%s) found baton %s numkeys.%d seed.%llu playerdata.%d playertxid.%s\n",pname.size()!=0?pname.c_str():Rogue_pname.c_str(),batontxid.ToString().c_str(),numkeys,(long long)seed,(int32_t)playerdata.size(),playertxid.GetHex().c_str());
memset(&P,0,sizeof(P));
if ( playerdata.size() > 0 )
{
for (i=0; i<playerdata.size(); i++)
((uint8_t *)&P)[i] = playerdata[i];
}
if ( keystrokes != 0 )
if ( keystrokes != 0 && numkeys != 0 )
{
sprintf(fname,"rogue.%llu.0",(long long)seed);
if ( (fp= fopen(fname,"wb")) != 0 )
if ( makefiles != 0 )
{
if ( fwrite(keystrokes,1,numkeys,fp) != numkeys )
fprintf(stderr,"error writing %s\n",fname);
fclose(fp);
}
sprintf(fname,"rogue.%llu.player",(long long)seed);
if ( (fp= fopen(fname,"wb")) != 0 )
{
if ( fwrite(&playerdata[0],1,(int32_t)playerdata.size(),fp) != playerdata.size() )
fprintf(stderr,"error writing %s\n",fname);
fclose(fp);
sprintf(fname,"rogue.%llu.0",(long long)seed);
if ( (fp= fopen(fname,"wb")) != 0 )
{
if ( fwrite(keystrokes,1,numkeys,fp) != numkeys )
fprintf(stderr,"error writing %s\n",fname);
fclose(fp);
}
sprintf(fname,"rogue.%llu.player",(long long)seed);
if ( (fp= fopen(fname,"wb")) != 0 )
{
if ( fwrite(&playerdata[0],1,(int32_t)playerdata.size(),fp) != playerdata.size() )
fprintf(stderr,"error writing %s\n",fname);
fclose(fp);
}
}
num = rogue_replay2(newplayer,seed,keystrokes,numkeys,playerdata.size()==0?0:&P,0);
newdata.resize(num);
@@ -866,16 +896,34 @@ char *rogue_extractgame(char *str,int32_t *numkeysp,std::vector<uint8_t> &newdat
}
if ( endP.gold <= 0 || endP.hitpoints <= 0 || (endP.strength&0xffff) <= 0 || endP.level <= 0 || endP.experience <= 0 || endP.dungeonlevel <= 0 )
{
fprintf(stderr,"zero value character was killed -> no playerdata\n");
//fprintf(stderr,"zero value character was killed -> no playerdata\n");
newdata.resize(0);
//P.gold = (P.gold * 8) / 10;
if ( keystrokes != 0 )
{
free(keystrokes);
keystrokes = 0;
*numkeysp = 0;
}
}
else
{
sprintf(str,"extracted $$$gold.%d hp.%d strength.%d/%d level.%d exp.%d dl.%d",endP.gold,endP.hitpoints,endP.strength&0xffff,endP.strength>>16,endP.level,endP.experience,endP.dungeonlevel);
fprintf(stderr,"%s\n",str);
*numkeysp = numkeys;
return(keystrokes);
}
sprintf(str,"extracted $$$gold.%d hp.%d strength.%d/%d level.%d exp.%d dl.%d\n",endP.gold,endP.hitpoints,endP.strength&0xffff,endP.strength>>16,endP.level,endP.experience,endP.dungeonlevel);
fprintf(stderr,"%s\n",str);
} else num = 0;
}
}
*numkeysp = numkeys;
return(keystrokes);
else
{
fprintf(stderr,"extractgame: couldnt find baton keystrokes.%p\n",keystrokes);
if ( keystrokes != 0 )
free(keystrokes), keystrokes = 0;
}
} else fprintf(stderr,"extractgame: invalid game\n");
//fprintf(stderr,"extract %s\n",gametxid.GetHex().c_str());
return(0);
}
UniValue rogue_extract(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
@@ -885,7 +933,7 @@ UniValue rogue_extract(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
roguepk = GetUnspendable(cp,0);
result.push_back(Pair("name","rogue"));
result.push_back(Pair("method","extract"));
if ( (params= cclib_reparse(&n,params)) != 0 )
if ( params != 0 && (n= cJSON_GetArraySize(params)) > 0 )
{
if ( n > 0 )
{
@@ -903,7 +951,7 @@ UniValue rogue_extract(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
GetCCaddress1of2(cp,rogueaddr,roguepk,pk);
result.push_back(Pair("rogueaddr",rogueaddr));
str[0] = 0;
if ( (keystrokes= rogue_extractgame(str,&numkeys,newdata,seed,playertxid,cp,gametxid,rogueaddr)) != 0 )
if ( (keystrokes= rogue_extractgame(1,str,&numkeys,newdata,seed,playertxid,cp,gametxid,rogueaddr)) != 0 )
{
result.push_back(Pair("status","success"));
flag = 1;
@@ -922,6 +970,77 @@ UniValue rogue_extract(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
return(result);
}
int32_t rogue_playerdata_validate(int64_t *cashoutp,uint256 &playertxid,struct CCcontract_info *cp,std::vector<uint8_t> playerdata,uint256 gametxid,CPubKey pk)
{
static uint32_t good,bad; static uint256 prevgame;
char str[512],*keystrokes,rogueaddr[64],str2[67]; int32_t i,dungeonlevel,numkeys; std::vector<uint8_t> newdata; uint64_t seed,mult = 10; CPubKey roguepk; struct rogue_player P;
*cashoutp = 0;
roguepk = GetUnspendable(cp,0);
GetCCaddress1of2(cp,rogueaddr,roguepk,pk);
//fprintf(stderr,"call extractgame\n");
if ( (keystrokes= rogue_extractgame(0,str,&numkeys,newdata,seed,playertxid,cp,gametxid,rogueaddr)) != 0 )
{
//fprintf(stderr,"numkeys.%d rogue_extractgame %s\n",numkeys,gametxid.GetHex().c_str());
free(keystrokes);
//fprintf(stderr,"extracted.(%s)\n",str);
for (i=0; i<playerdata.size(); i++)
((uint8_t *)&P)[i] = playerdata[i];
if ( P.amulet != 0 )
mult *= 5;
dungeonlevel = P.dungeonlevel;
if ( P.amulet != 0 && dungeonlevel < 21 )
dungeonlevel = 21;
*cashoutp = (uint64_t)P.gold * P.gold * mult * dungeonlevel;
if ( newdata == playerdata )
{
if ( gametxid != prevgame )
{
prevgame = gametxid;
good++;
fprintf(stderr,"%s good.%d bad.%d\n",gametxid.GetHex().c_str(),good,bad);
}
return(0);
}
newdata[10] = newdata[11] = playerdata[10] = playerdata[11] = 0;
if ( newdata == playerdata )
{
if ( gametxid != prevgame )
{
prevgame = gametxid;
good++;
fprintf(stderr,"%s matched after clearing maxstrength good.%d bad.%d\n",gametxid.GetHex().c_str(),good,bad);
}
return(0);
}
if ( P.gold <= 0 || P.hitpoints <= 0 || (P.strength&0xffff) <= 0 || P.level <= 0 || P.experience <= 0 || P.dungeonlevel <= 0 )
{
//P.gold = (P.gold * 8) / 10;
//for (i=0; i<playerdata.size(); i++)
// playerdata[i] = ((uint8_t *)&P)[i];
if ( newdata.size() == 0 )
{
if ( gametxid != prevgame )
{
prevgame = gametxid;
good++;
fprintf(stderr,"zero value character was killed -> no playerdata, good.%d bad.%d\n",good,bad);
}
*cashoutp = 0;
return(0);
}
}
if ( gametxid != prevgame )
{
prevgame = gametxid;
bad++;
fprintf(stderr,"%s playerdata: gold.%d hp.%d strength.%d/%d level.%d exp.%d dl.%d\n",gametxid.GetHex().c_str(),P.gold,P.hitpoints,P.strength&0xffff,P.strength>>16,P.level,P.experience,P.dungeonlevel);
fprintf(stderr,"newdata[%d] != playerdata[%d], numkeys.%d %s pub.%s playertxid.%s good.%d bad.%d\n",(int32_t)newdata.size(),(int32_t)playerdata.size(),numkeys,rogueaddr,pubkey33_str(str2,(uint8_t *)&pk),playertxid.GetHex().c_str(),good,bad);
}
}
//fprintf(stderr,"no keys rogue_extractgame %s\n",gametxid.GetHex().c_str());
return(-1);
}
UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *params,char *method)
{
//vin0 -> highlander vout from creategame TCBOO
@@ -936,7 +1055,7 @@ UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
// vout0 -> 1% ingame gold
// get any playerdata, get all keystrokes, replay game and compare final state
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
UniValue result(UniValue::VOBJ); std::string rawtx,symbol,pname; CTransaction gametx; uint64_t seed,mult; int64_t buyin,batonvalue,inputsum,cashout,CCchange=0; int32_t i,err,gameheight,tmp,numplayers,regslot,n,num,numkeys,maxplayers,batonht,batonvout; char myrogueaddr[64],*keystrokes = 0; std::vector<uint8_t> playerdata,newdata,nodata; uint256 batontxid,playertxid,gametxid; CPubKey mypk,roguepk; uint8_t player[10000],mypriv[32],funcid;
UniValue result(UniValue::VOBJ); std::string rawtx,symbol,pname; CTransaction gametx; uint64_t seed,mult; int64_t buyin,batonvalue,inputsum,cashout,CCchange=0; int32_t i,err,gameheight,tmp,numplayers,regslot,n,num,dungeonlevel,numkeys,maxplayers,batonht,batonvout; char myrogueaddr[64],*keystrokes = 0; std::vector<uint8_t> playerdata,newdata,nodata; uint256 batontxid,playertxid,gametxid; CPubKey mypk,roguepk; uint8_t player[10000],mypriv[32],funcid;
struct CCcontract_info *cpTokens, tokensC;
if ( txfee == 0 )
@@ -950,20 +1069,20 @@ UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
if ( strcmp(method,"bailout") == 0 )
{
funcid = 'Q';
mult = 100000;
mult = 10; //100000;
}
else
{
funcid = 'H';
mult = 1000000;
mult = 20; //200000;
}
if ( (params= cclib_reparse(&n,params)) != 0 )
if ( params != 0 && (n= cJSON_GetArraySize(params)) > 0 )
{
if ( n > 0 )
{
gametxid = juint256(jitem(params,0));
result.push_back(Pair("gametxid",gametxid.GetHex()));
if ( (err= rogue_isvalidgame(cp,gameheight,gametx,buyin,maxplayers,gametxid)) == 0 )
if ( (err= rogue_isvalidgame(cp,gameheight,gametx,buyin,maxplayers,gametxid,1)) == 0 )
{
if ( rogue_findbaton(cp,playertxid,&keystrokes,numkeys,regslot,playerdata,batontxid,batonvout,batonvalue,batonht,gametxid,gametx,maxplayers,myrogueaddr,numplayers,symbol,pname) == 0 )
{
@@ -980,7 +1099,7 @@ UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
{
num = rogue_replay2(player,seed,keystrokes,numkeys,playerdata.size()==0?0:&P,0);
if ( keystrokes != 0 )
free(keystrokes);
free(keystrokes), keystrokes = 0;
} else num = 0;
mtx.vin.push_back(CTxIn(batontxid,batonvout,CScript()));
mtx.vin.push_back(CTxIn(gametxid,1+maxplayers+regslot,CScript()));
@@ -994,23 +1113,29 @@ UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
newdata[i] = player[i];
((uint8_t *)&P)[i] = player[i];
}
if ( P.gold <= 0 || P.hitpoints <= 0 || (P.strength&0xffff) <= 0 || P.level <= 0 || P.experience <= 0 || P.dungeonlevel <= 0 )
if ( (P.gold <= 0 || P.hitpoints <= 0 || (P.strength&0xffff) <= 0 || P.level <= 0 || P.experience <= 0 || P.dungeonlevel <= 0) )
{
fprintf(stderr,"zero value character was killed -> no playerdata\n");
//fprintf(stderr,"zero value character was killed -> no playerdata\n");
newdata.resize(0);
//P.gold = (P.gold * 8) / 10;
}
else
{
if ( maxplayers == 1 )
mult /= 2;
//if ( maxplayers == 1 )
// mult /= 2;
cpTokens = CCinit(&tokensC, EVAL_TOKENS);
mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, txfee, GetUnspendable(cpTokens,NULL))); // marker to token cc addr, burnable and validated
mtx.vout.push_back(MakeTokensCC1vout(cp->evalcode,1,mypk));
fprintf(stderr,"\nextracted $$$gold.%d hp.%d strength.%d/%d level.%d exp.%d dl.%d n.%d size.%d\n",P.gold,P.hitpoints,P.strength&0xffff,P.strength>>16,P.level,P.experience,P.dungeonlevel,n,(int32_t)sizeof(P));
cashout = (uint64_t)P.gold * mult;
if ( P.amulet != 0 )
mult *= 5;
dungeonlevel = P.dungeonlevel;
if ( P.amulet != 0 && dungeonlevel < 21 )
dungeonlevel = 21;
cashout = (uint64_t)P.gold * P.gold * mult * dungeonlevel;
fprintf(stderr,"\nextracted $$$gold.%d -> %.8f ROGUE hp.%d strength.%d/%d level.%d exp.%d dl.%d n.%d amulet.%d\n",P.gold,(double)cashout/COIN,P.hitpoints,P.strength&0xffff,P.strength>>16,P.level,P.experience,P.dungeonlevel,n,P.amulet);
if ( funcid == 'H' && maxplayers > 1 )
{
if ( numplayers != maxplayers || (numplayers - rogue_playersalive(tmp,gametxid,maxplayers)) > 1 && (P.dungeonlevel > 1 || P.gold < 10000 || P.level < 20) )
if ( (numplayers != maxplayers || (numplayers - rogue_playersalive(tmp,gametxid,maxplayers)) > 1) && P.amulet == 0 )
return(cclib_error(result,"highlander must be a winner or last one standing"));
cashout += numplayers * buyin;
}
@@ -1023,7 +1148,6 @@ UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
}
}
mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange + (batonvalue-3*txfee),roguepk));
Myprivkey(mypriv);
CCaddr1of2set(cp,roguepk,mypk,mypriv,myrogueaddr);
CScript opret;
@@ -1065,16 +1189,16 @@ UniValue rogue_highlander(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
UniValue rogue_gameinfo(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
UniValue result(UniValue::VOBJ),a(UniValue::VARR); int32_t i,n,gameheight,maxplayers,numvouts; uint256 txid; CTransaction tx; int64_t buyin; bits256 t; char myrogueaddr[64]; CPubKey mypk,roguepk;
UniValue result(UniValue::VOBJ),a(UniValue::VARR); int32_t i,n,gameheight,maxplayers,numvouts; uint256 txid; CTransaction tx; int64_t buyin; uint64_t seed; bits256 t; char myrogueaddr[64]; CPubKey mypk,roguepk;
result.push_back(Pair("name","rogue"));
result.push_back(Pair("method","gameinfo"));
if ( (params= cclib_reparse(&n,params)) != 0 )
if ( params != 0 && (n= cJSON_GetArraySize(params)) > 0 )
{
if ( n > 0 )
{
txid = juint256(jitem(params,0));
result.push_back(Pair("gametxid",txid.GetHex()));
if ( rogue_isvalidgame(cp,gameheight,tx,buyin,maxplayers,txid) == 0 )
if ( rogue_isvalidgame(cp,gameheight,tx,buyin,maxplayers,txid,0) == 0 )
{
result.push_back(Pair("result","success"));
result.push_back(Pair("gameheight",(int64_t)gameheight));
@@ -1082,7 +1206,8 @@ UniValue rogue_gameinfo(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
roguepk = GetUnspendable(cp,0);
GetCCaddress1of2(cp,myrogueaddr,roguepk,mypk);
//fprintf(stderr,"myrogueaddr.%s\n",myrogueaddr);
rogue_gamefields(result,maxplayers,buyin,txid,myrogueaddr);
seed = rogue_gamefields(result,maxplayers,buyin,txid,myrogueaddr);
result.push_back(Pair("seed",(int64_t)seed));
for (i=0; i<maxplayers; i++)
{
if ( CCgettxout(txid,i+1,1) < 0 )
@@ -1114,7 +1239,7 @@ UniValue rogue_pending(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
//char str[65]; fprintf(stderr,"%s check %s/v%d %.8f\n",coinaddr,uint256_str(str,txid),vout,(double)it->second.satoshis/COIN);
if ( it->second.satoshis != txfee || vout != 0 ) // reject any that are not highlander markers
continue;
if ( rogue_isvalidgame(cp,gameheight,tx,buyin,maxplayers,txid) == 0 && nextheight <= gameheight+ROGUE_MAXKEYSTROKESGAP )
if ( rogue_isvalidgame(cp,gameheight,tx,buyin,maxplayers,txid,1) == 0 && nextheight <= gameheight+ROGUE_MAXKEYSTROKESGAP )
{
rogue_playersalive(numplayers,txid,maxplayers);
if ( numplayers < maxplayers )
@@ -1174,11 +1299,11 @@ UniValue rogue_games(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
//char str[65]; fprintf(stderr,"%s check %s/v%d %.8f\n",coinaddr,uint256_str(str,txid),vout,(double)it->second.satoshis/COIN);
if ( vout == 0 )
{
if ( GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 1 )
if ( myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 1 )
{
if ( rogue_registeropretdecode(gametxid,tokenid,playertxid,tx.vout[numvouts-1].scriptPubKey) == 'R' )
{
if ( rogue_isvalidgame(cp,gameheight,gametx,buyin,maxplayers,gametxid) == 0 )
if ( rogue_isvalidgame(cp,gameheight,gametx,buyin,maxplayers,gametxid,0) == 0 )
{
if ( CCgettxout(txid,vout,1) < 0 )
b.push_back(gametxid.GetHex());
@@ -1198,7 +1323,7 @@ UniValue rogue_setname(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
UniValue result(UniValue::VOBJ); int32_t n; char *namestr = 0;
rogue_univalue(result,"setname",-1,-1);
if ( (params= cclib_reparse(&n,params)) != 0 )
if ( params != 0 && (n= cJSON_GetArraySize(params)) > 0 )
{
if ( n > 0 )
{
@@ -1218,9 +1343,12 @@ UniValue rogue_setname(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
bool rogue_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx)
{
CScript scriptPubKey; std::vector<uint8_t> vopret; uint8_t *script,e,f,funcid; int32_t i,ind,errflag,dispflag,score,numvouts; CTransaction vintx; uint256 hashBlock;
CScript scriptPubKey; std::vector<uint8_t> vopret; uint8_t *script,e,f,funcid,tokentx=0; int32_t i,maxplayers,decoded=0,regslot,ind,err,dispflag,gameheight,score,numvouts; CTransaction vintx,gametx; CPubKey pk; uint256 hashBlock,gametxid,txid,tokenid,batontxid,playertxid,ptxid; int64_t buyin,cashout; std::vector<uint8_t> playerdata,keystrokes; std::string symbol,pname;
if ( strcmp(ASSETCHAINS_SYMBOL,"ROGUE") == 0 && height < 21274 )
return(true);
if ( (numvouts= tx.vout.size()) > 1 )
{
txid = tx.GetHash();
scriptPubKey = tx.vout[numvouts-1].scriptPubKey;
GetOpReturnData(scriptPubKey,vopret);
if ( vopret.size() > 2 )
@@ -1229,27 +1357,96 @@ bool rogue_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const C
funcid = script[1];
if ( (e= script[0]) == EVAL_TOKENS )
{
if ( script[1] == 'c' )
tokentx = 1;
if ( (funcid= rogue_highlanderopretdecode(gametxid,tokenid,regslot,pk,playerdata,symbol,pname,scriptPubKey)) == 0 )
{
e = EVAL_ROGUE;
funcid = 'Q';
}
else if ( script[1] == 't' )
{
e = EVAL_ROGUE;
funcid = 'Q';
} else return eval->Invalid("illegal tokens funcid");
if ( (funcid= rogue_registeropretdecode(gametxid,tokenid,playertxid,scriptPubKey)) == 0 )
{
fprintf(stderr,"ht.%d couldnt decode tokens opret (%c)\n",height,script[1]);
} else e = EVAL_ROGUE, decoded = 1;
} else e = EVAL_ROGUE, decoded = 1;
}
if ( e == EVAL_ROGUE )
{
//fprintf(stderr,"ht.%d rogue.(%c)\n",height,script[1]);
if ( decoded == 0 )
{
switch ( funcid )
{
case 'G': // seems just need to make sure no vout abuse is left to do
gametx = tx;
gametxid = tx.GetHash();
gameheight = height;
if ( (err= rogue_isvalidgame(cp,gameheight,gametx,buyin,maxplayers,zeroid,0)) != 0 )
{
fprintf(stderr,"height.%d %s rogue_isvalidgame error.%d\n",height,gametxid.GetHex().c_str(),err);
return eval->Invalid("invalid gametxid");
}
//fprintf(stderr,"height.%d %s rogue_isvalidgame\n",height,gametxid.GetHex().c_str());
return(true);
break;
case 'R':
if ( (funcid= rogue_registeropretdecode(gametxid,tokenid,playertxid,scriptPubKey)) != 'R' )
{
//fprintf(stderr,"height.%d couldnt decode register opret\n",height);
//if ( height > 20000 )
return eval->Invalid("couldnt decode register opret");
}
// baton is created
// validation is done below
break;
case 'K':
if ( (funcid= rogue_keystrokesopretdecode(gametxid,batontxid,pk,keystrokes,scriptPubKey)) != 'K' )
{
//fprintf(stderr,"height.%d couldnt decode keystrokes opret\n",height);
//if ( height > 20000 )
return eval->Invalid("couldnt decode keystrokes opret");
}
// spending the baton proves it is the user if the pk is the signer
return(true);
break;
case 'H': case 'Q':
if ( (f= rogue_highlanderopretdecode(gametxid,tokenid,regslot,pk,playerdata,symbol,pname,scriptPubKey)) != funcid )
{
//fprintf(stderr,"height.%d couldnt decode H/Q opret\n",height);
//if ( height > 20000 )
return eval->Invalid("couldnt decode H/Q opret");
}
// spending the baton proves it is the user if the pk is the signer
// rest of validation is done below
break;
default:
return eval->Invalid("illegal rogue non-decoded funcid");
break;
}
}
switch ( funcid )
{
case 'G': // newgame
case 'R': // register
case 'K': // keystrokes
// verify vout amounts are as they should be and no vins that shouldnt be
return(true);
case 'H': // win
case 'Q': // bailout
fprintf(stderr,"ht.%d rogue.(%c)\n",height,script[1]);
// verify pk belongs to this tx
if ( playerdata.size() > 0 )
{
if ( rogue_playerdata_validate(&cashout,ptxid,cp,playerdata,gametxid,pk) < 0 )
{
fprintf(stderr,"ht.%d gametxid.%s player.%s invalid playerdata[%d]\n",height,gametxid.GetHex().c_str(),ptxid.GetHex().c_str(),(int32_t)playerdata.size());
}
if ( funcid == 'H' )
cashout *= 2;
if ( tx.vout.size() > 3 ) // orig of 't' has 0 cashout
fprintf(stderr,"ht.%d txid.%s cashout %.8f vs vout2 %.8f\n",height,txid.GetHex().c_str(),(double)cashout/COIN,(double)tx.vout[2].nValue/COIN);
}
if ( funcid == 'Q' )
{
// verify vin/vout
}
else // 'H'
{
// verify vin/vout and proper payouts
}
return(true);
break;
default:

View File

@@ -2817,7 +2817,7 @@ UniValue sudoku_solution(uint64_t txfee,struct CCcontract_info *cp,cJSON *params
good = 0;
if ( params != 0 )
{
if ( (params= cclib_reparse(&n,params)) != 0 )
if ( params != 0 && (n= cJSON_GetArraySize(params)) > 0 )
{
if ( n > 2 && n <= (sizeof(timestamps)/sizeof(*timestamps))+2 )
{
@@ -3049,3 +3049,4 @@ bool sudoku_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const
return eval->Invalid("not enough vouts");
}