diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp index cc8340fb4..8ab0d1875 100644 --- a/src/cc/prices.cpp +++ b/src/cc/prices.cpp @@ -592,6 +592,13 @@ int64_t prices_syntheticprice(std::vector vec, int32_t height, int32_t uint16_t opcode; int64_t *pricedata, pricestack[4], price, den, a, b, c; + mpz_t mpzA, mpzB, mpzC, mpzResult; + + mpz_init(mpzA); + mpz_init(mpzB); + mpz_init(mpzC); + mpz_init(mpzResult); + pricedata = (int64_t *)calloc(sizeof(*pricedata) * 3, 1 + PRICES_DAYWINDOW * 2 + PRICES_SMOOTHWIDTH); price = den = depth = errcode = 0; @@ -599,7 +606,10 @@ int64_t prices_syntheticprice(std::vector vec, int32_t height, int32_t { opcode = vec[i]; value = (opcode & (KOMODO_MAXPRICES - 1)); // index or weight - std::cerr << "prices_syntheticprice" << " i=" << i << " price=" << price << " value=" << value << " depth=" << depth << std::endl; + + mpz_set_ui(mpzResult, 0); // clear result to test overflow (see below) + + std::cerr << "prices_syntheticprice" << " i=" << i << " price=" << price << " value=" << value << " depth=" << depth << " opcode&KOMODO_PRICEMASK=" << (opcode & KOMODO_PRICEMASK) < vec, int32_t height, int32_t errcode = -2; break; - case PRICES_MULT: + case PRICES_MULT: // "*" if (depth >= 2) { b = pricestack[--depth]; a = pricestack[--depth]; - pricestack[depth++] = (a * b) / PRICES_NORMFACTOR; + // pricestack[depth++] = (a * b) / SATOSHIDEN; + mpz_set_si(mpzA, a); + mpz_set_si(mpzB, b); + mpz_mul(mpzResult, mpzA, mpzB); + mpz_tdiv_q_ui(mpzResult, mpzResult, SATOSHIDEN); + pricestack[depth++] = mpz_get_si(mpzResult); + } else errcode = -3; break; - case PRICES_DIV: + case PRICES_DIV: // "/" if (depth >= 2) { b = pricestack[--depth]; a = pricestack[--depth]; - pricestack[depth++] = (a * PRICES_NORMFACTOR) / b; + // pricestack[depth++] = (a * SATOSHIDEN) / b; + mpz_set_si(mpzA, a); + mpz_set_si(mpzB, b); + mpz_mul_ui(mpzResult, mpzA, SATOSHIDEN); + mpz_tdiv_q(mpzResult, mpzResult, mpzB); + pricestack[depth++] = mpz_get_si(mpzResult); } else errcode = -4; break; - case PRICES_INV: + case PRICES_INV: // "1/price" if (depth >= 1) { a = pricestack[--depth]; - pricestack[depth++] = (PRICES_NORMFACTOR * PRICES_NORMFACTOR) / a; + // pricestack[depth++] = (SATOSHIDEN * SATOSHIDEN) / a; + mpz_set_si(mpzA, a); + mpz_set_ui(mpzResult, SATOSHIDEN); + mpz_mul_ui(mpzResult, mpzResult, SATOSHIDEN); + mpz_tdiv_q(mpzResult, mpzResult, mpzA); + pricestack[depth++] = mpz_get_si(mpzResult); } else errcode = -5; break; - case PRICES_MDD: + case PRICES_MDD: // "*//" if (depth >= 3) { c = pricestack[--depth]; b = pricestack[--depth]; a = pricestack[--depth]; - pricestack[depth++] = (((a * PRICES_NORMFACTOR) / b) * PRICES_NORMFACTOR) / c; + // pricestack[depth++] = (((a * SATOSHIDEN) / b) * SATOSHIDEN) / c; + mpz_set_si(mpzA, a); + mpz_set_si(mpzB, b); + mpz_set_si(mpzC, c); + mpz_mul_ui(mpzResult, mpzA, SATOSHIDEN); + mpz_tdiv_q(mpzResult, mpzResult, mpzB); + mpz_mul_ui(mpzResult, mpzA, SATOSHIDEN); + mpz_tdiv_q(mpzResult, mpzResult, mpzC); + pricestack[depth++] = mpz_get_si(mpzResult); } else errcode = -6; break; - case PRICES_MMD: + case PRICES_MMD: // "**/" if (depth >= 3) { c = pricestack[--depth]; b = pricestack[--depth]; a = pricestack[--depth]; - pricestack[depth++] = (a * b) / c; + // pricestack[depth++] = (a * b) / c; + mpz_set_si(mpzA, a); + mpz_set_si(mpzB, b); + mpz_set_si(mpzC, c); + mpz_mul(mpzResult, mpzA, mpzB); + mpz_tdiv_q(mpzResult, mpzResult, mpzC); + pricestack[depth++] = mpz_get_si(mpzResult); } else errcode = -7; break; - case PRICES_MMM: + case PRICES_MMM: // "***" if (depth >= 3) { c = pricestack[--depth]; b = pricestack[--depth]; a = pricestack[--depth]; - pricestack[depth++] = ((a * b) / PRICES_NORMFACTOR) * c; + // pricestack[depth++] = ((a * b) / SATOSHIDEN) * c; + mpz_set_si(mpzA, a); + mpz_set_si(mpzB, b); + mpz_set_si(mpzC, c); + mpz_mul(mpzResult, mpzA, mpzB); + mpz_tdiv_q_ui(mpzResult, mpzResult, SATOSHIDEN); + mpz_mul(mpzResult, mpzResult, mpzC); + pricestack[depth++] = mpz_get_si(mpzResult); } else errcode = -8; break; - - case PRICES_DDD: + + case PRICES_DDD: // "///" if (depth >= 3) { c = pricestack[--depth]; b = pricestack[--depth]; a = pricestack[--depth]; - pricestack[depth++] = (((((PRICES_NORMFACTOR * PRICES_NORMFACTOR) / a) * PRICES_NORMFACTOR) / b) * PRICES_NORMFACTOR) / c; + //pricestack[depth++] = (((((SATOSHIDEN * SATOSHIDEN) / a) * SATOSHIDEN) / b) * SATOSHIDEN) / c; + mpz_set_si(mpzA, a); + mpz_set_si(mpzB, b); + mpz_set_si(mpzC, c); + mpz_set_ui(mpzResult, SATOSHIDEN); + mpz_mul_ui(mpzResult, mpzResult, SATOSHIDEN); + mpz_tdiv_q(mpzResult, mpzResult, mpzA); + mpz_mul_ui(mpzResult, mpzResult, SATOSHIDEN); + mpz_tdiv_q(mpzResult, mpzResult, mpzB); + mpz_mul_ui(mpzResult, mpzResult, SATOSHIDEN); + mpz_tdiv_q(mpzResult, mpzResult, mpzC); + pricestack[depth++] = mpz_get_si(mpzResult); } else errcode = -9; @@ -716,19 +774,36 @@ int64_t prices_syntheticprice(std::vector vec, int32_t height, int32_t errcode = -10; break; } + + std::cerr << "prices_syntheticprice test mpzResult=" << mpz_get_si(mpzResult) << std::endl; + // check overflow: + if (mpz_cmp_si(mpzResult, std::numeric_limits::max()) > 0) { + errcode = -13; + break; + } + if (errcode != 0) break; if( depth > 0 ) - std::cerr << "top pricestack[depth-1=" << depth-1 << "]=" << pricestack[depth-1] << std::endl; + std::cerr << "prices_syntheticprice top pricestack[depth-1=" << depth-1 << "]=" << pricestack[depth-1] << std::endl; else - std::cerr << "pricestack empty" << std::endl; + std::cerr << "prices_syntheticprice pricestack empty" << std::endl; } free(pricedata); + mpz_clear(mpzResult); + mpz_clear(mpzA); + mpz_clear(mpzB); + mpz_clear(mpzC); if (errcode != 0) - std::cerr << "prices_syntheticprice warning: errcode in switch=" << errcode << std::endl; + std::cerr << "prices_syntheticprice errcode in switch=" << errcode << std::endl; + + if (errcode == -13) { + std::cerr << "prices_syntheticprice overflow in price" << std::endl; + return errcode; + } if (den == 0) { std::cerr << "prices_syntheticprice den==0 return err=-11" << std::endl; @@ -819,29 +894,26 @@ int32_t prices_syntheticprofits(int64_t &costbasis, int32_t firstheight, int32_t mpz_t mpzCostbasis; mpz_t mpzPrice; mpz_t mpzLeverage; - mpz_t mpzRemainder; mpz_init(mpzProfits); mpz_init(mpzCostbasis); mpz_init(mpzPrice); mpz_init(mpzLeverage); - mpz_init(mpzRemainder); - mpz_set_ui(mpzCostbasis, costbasis); - mpz_set_ui(mpzPrice, price); + mpz_set_si(mpzCostbasis, costbasis); + mpz_set_si(mpzPrice, price); mpz_mul_ui(mpzPrice, mpzPrice, SATOSHIDEN); // (price*SATOSHIDEN) - mpz_tdiv_qr(mpzProfits, mpzRemainder, mpzPrice, mpzCostbasis); // profits = (price*SATOSHIDEN)/costbasis // normalization + mpz_tdiv_q(mpzProfits, mpzPrice, mpzCostbasis); // profits = (price*SATOSHIDEN)/costbasis // normalization mpz_sub_ui(mpzProfits, mpzProfits, SATOSHIDEN); // profits -= SATOSHIDEN mpz_set_si(mpzLeverage, leverage); mpz_mul(mpzProfits, mpzProfits, mpzLeverage); // profits *= leverage mpz_mul_ui(mpzProfits, mpzProfits, positionsize); // profits *= positionsize - mpz_tdiv_qr_ui(mpzProfits, mpzRemainder, mpzProfits, SATOSHIDEN); // profits /= SATOSHIDEN // de-normalization + mpz_tdiv_q_ui(mpzProfits, mpzProfits, SATOSHIDEN); // profits /= SATOSHIDEN // de-normalization profits = mpz_get_si(mpzProfits); - mpz_clear(mpzRemainder); mpz_clear(mpzLeverage); mpz_clear(mpzProfits); mpz_clear(mpzCostbasis); @@ -988,6 +1060,7 @@ UniValue PricesBet(int64_t txfee, int64_t amount, int16_t leverage, std::vector< //GetCCaddress(cp, myaddr, mypk); if (prices_syntheticvec(vec, synthetic) < 0 || (firstprice = prices_syntheticprice(vec, nextheight - 1, 1, leverage)) < 0 || vec.size() == 0 || vec.size() > 4096) { + std::cerr << "PricesBet() firstprice=" << firstprice << (firstprice < 0 ? "error or overflow" : "") << std::endl; result.push_back(Pair("result", "error")); result.push_back(Pair("error", "invalid synthetic")); return(result);