You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1016 lines
52 KiB
1016 lines
52 KiB
/******************************************************************************
|
|
* Copyright © 2014-2015 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. *
|
|
* *
|
|
******************************************************************************/
|
|
#ifdef later
|
|
|
|
#ifdef DEFINES_ONLY
|
|
#ifndef quotes777_h
|
|
#define quotes777_h
|
|
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <memory.h>
|
|
#include "../iguana777.h"
|
|
#include "serdes777.c"
|
|
#include "peggy777.c"
|
|
|
|
#endif
|
|
#else
|
|
#ifndef quotes777_c
|
|
#define quotes777_c
|
|
|
|
#ifndef quotes777_h
|
|
#define DEFINES_ONLY
|
|
#include "quotes777.c"
|
|
//#include "serdes777.c"
|
|
#undef DEFINES_ONLY
|
|
#endif
|
|
|
|
//////////// must be consensus safe
|
|
#define PEGGY_GENESIS "6aef504158ec0014fee05dc20a0006048ed63e523f6d1062feb23622da928cf23ddcc3b53f23566bc6cab5ebd77cfbf8f0bccb34bff73c55d742dd232994bfbffe1cbab7119ab3d653a256b02d5b6f56c05b8817799f0d242f48c26d35c992ebfff14acdefbe253345d394e84d975334cd55f7d6cbad5a7bd9425b1d5db44944d40be5304b7b62ba0dbc20d3323d2b35f05f654bc95a5a2fdb5a30e46c6fd33b5ea078255f7cad9fd0dbd2fa5031ada4474cbba7b2ee64ef35df06bf3fd3eef6cd3f48339f3c0e080158a92862bbf20bc6702018effbaee525502eb463c74f7ca0dff4ae7cb55ee55ef7cb1c915e655649"
|
|
|
|
//#define PEGGY_GENESIS "6aef504547ec00143e3028ba0a000604800d0560da5a55fbb56121b403e9dfbbd99f6b05c9af5683676bdda7f39636c579515174afebe5ad659c44567df9f02eb1dc5e30b4cc1a96a0dab18b2e55e5fd771032f2ee3d34de9313d9ea2813d70e6995a2fe7d7b2854a6032c9d022d676a9ae0ed573ab57e4887761a85688b20b417ad099686a67a2b82cca6104698a254c5ca5fe95ab874649513bae9e4bcbc7e868497c3a9d6da3ad82d625f12078d50c48a2e492bd6665e9f86e3fbe4bf6ee1758a9461fee35068851562b3b68082645c92a8f35a61a2de5652478b441fc53aa96aaf169feaedaef7bf1472fb3542ee04"
|
|
//#define PEGGY_GENESIS "6af2504547ef00147eb3ccb70a0006f49b65bed5a3b5f867565be8feb53b1c694b1bd8bcf1039696d8b968a7ae93168e745c6737fe9b6ab079152a3cabeee24e4d48f9ade6b1b41a39fc3abe2a5ae6f9254de6cbf679ad6e338cdfd7b1b4b1e2689c555648a4087cd94aa44869ab48a65b1295f6f75f8bf760a42966bbf2c1d8d6811379d17916e99abdb6c5246a2a192969f101ae3cc9679d98c5abedb64b6d9ea3a5ee485fe3ea467b77e5add9c1fa2d0d0dc781a5046b686b5c3bcdd91b8abb6ed33c8c556e05c4778b0e6b30bd6d6f41cc381d50e7f5a565bd64e78ff696de8a9517ee5ec79f531c594510abdd25ac44e62a"
|
|
|
|
uint64_t peggy_smooth_coeffs[PEGGY_NUMCOEFFS] = // numprimes.13
|
|
{
|
|
962714545, 962506087, 962158759, 961672710, 961048151, 960285354, 959384649, 958346426, 957171134, // x.8
|
|
955859283, 954411438, 952828225, 951110328, 949258485, 947273493, 945156207, 942907532, 940528434, // x.17
|
|
938019929, 935383089, 932619036, 929728945, 926714044, 923575608, 920314964, 916933485, 913432593, // x.26
|
|
909813756, 906078486, 902228342, 898264923, 894189872, 890004874, 885711650, 881311964, 876807614, // x.35
|
|
872200436, 867492300, 862685110, 857780804, 852781347, 847688737, 842505000, 837232189, 831872382, // x.44
|
|
826427681, 820900212, 815292123, 809605581, 803842772, 798005901, 792097186, 786118864, 780073180, // x.53
|
|
773962395, 767788778, 761554609, 755262175, 748913768, 742511686, 736058231, 729555707, 723006417, // x.62
|
|
716412665, 709776755, 703100984, 696387648, 689639036, 682857428, 676045100, 669204315, 662337327, // x.71
|
|
655446378, 648533696, 641601496, 634651978, 627687325, 620709702, 613721256, 606724115, 599720386, // x.80
|
|
592712154, 585701482, 578690411, 571680955, 564675105, 557674825, 550682053, 543698699, 536726645, // x.89
|
|
529767743, 522823816, 515896658, 508988029, 502099660, 495233249, 488390461, 481572928, 474782249, // x.98
|
|
468019988, 461287675, 454586804, 447918836, 441285195, 434687268, 428126409, 421603932, 415121117, // x.107
|
|
408679208, 402279408, 395922888, 389610779, 383344175, 377124134, 370951677, 364827785, 358753406, // x.116
|
|
352729449, 346756785, 340836251, 334968645, 329154729, 323395230, 317690838, 312042206, 306449955, // x.125
|
|
300914667, 295436891, 290017141, 284655897, 279353604, 274110676, 268927490, 263804394, 258741701, // x.134
|
|
253739694, 248798623, 243918709, 239100140, 234343077, 229647649, 225013957, 220442073, 215932043, // x.143
|
|
211483883, 207097585, 202773112, 198510404, 194309373, 190169909, 186091877, 182075118, 178119452, // x.152
|
|
174224676, 170390565, 166616873, 162903335, 159249664, 155655556, 152120688, 148644718, 145227287, // x.161
|
|
141868021, 138566528, 135322401, 132135218, 129004542, 125929924, 122910901, 119946997, 117037723, // x.170
|
|
114182582, 111381062, 108632643, 105936795, 103292978, 100700645, 98159238, 95668194, 93226942, // x.179
|
|
90834903, 88491495, 86196126, 83948203, 81747126, 79592292, 77483092, 75418916, 73399150, // x.188
|
|
71423178, 69490383, 67600142, 65751837, 63944844, 62178541, 60452305, 58765515, 57117547, // x.197
|
|
55507781, 53935597, 52400377, 50901505, 49438366, 48010349, 46616844, 45257246, 43930951, // x.206
|
|
42637360, 41375878, 40145912, 38946876, 37778185, 36639262, 35529533, 34448428, 33395384, // x.215
|
|
32369842, 31371249, 30399057, 29452725, 28531717, 27635503, 26763558, 25915365, 25090413, // x.224
|
|
24288196, 23508216, 22749980, 22013003, 21296806, 20600917, 19924870, 19268206, 18630475, // x.233
|
|
18011231, 17410035, 16826458, 16260073, 15710466, 15177224, 14659944, 14158231, 13671694, // x.242
|
|
13199950, 12742625, 12299348, 11869759, 11453500, 11050225, 10659590, 10281262, 9914910, // x.251
|
|
9560213, 9216856, 8884529, 8562931, 8251764, 7950739, 7659571, 7377984, 7105706, // x.260
|
|
6842471, 6588020, 6342099, 6104460, 5874861, 5653066, 5438844, 5231969, 5032221, // x.269
|
|
4839386, 4653254, 4473620, 4300287, 4133059, 3971747, 3816167, 3666139, 3521488, // x.278
|
|
3382043, 3247640, 3118115, 2993313, 2873079, 2757266, 2645728, 2538325, 2434919, // x.287
|
|
2335380, 2239575, 2147382, 2058677, 1973342, 1891262, 1812325, 1736424, 1663453, // x.296
|
|
1593311, 1525898, 1461118, 1398879, 1339091, 1281666, 1226519, 1173569, 1122736, // x.305
|
|
1073944, 1027117, 982185, 939076, 897725, 858065, 820033, 783568, 748612, // x.314
|
|
715108, 682999, 652233, 622759, 594527, 567488, 541597, 516808, 493079, // x.323
|
|
470368, 448635, 427841, 407948, 388921, 370725, 353326, 336692, 320792, // x.332
|
|
305596, 291075, 277202, 263950, 251292, 239204, 227663, 216646, 206130, // x.341
|
|
196094, 186517, 177381, 168667, 160356, 152430, 144874, 137671, 130806, // x.350
|
|
124264, 118031, 112093, 106437, 101050, 95921, 91039, 86391, 81968, // x.359
|
|
77759, 73755, 69945, 66322, 62877, 59602, 56488, 53528, 50716, // x.368
|
|
48043, 45505, 43093, 40803, 38629, 36564, 34604, 32745, 30980, // x.377
|
|
29305, 27717, 26211, 24782, 23428, 22144, 20927, 19774, 18681, // x.386
|
|
17646, 16665, 15737, 14857, 14025, 13237, 12491, 11786, 11118, // x.395
|
|
10487, 9890, 9325, 8791, 8287, 7810, 7359, 6933, 6531, // x.404
|
|
6151, 5792, 5453, 5133, 4831, 4547, 4278, 4024, 3785, // x.413
|
|
3560, 3347, 3147, 2958, 2779, 2612, 2454, 2305, 2164, // x.422
|
|
2032, 1908, 1791, 1681, 1577, 1480, 1388, 1302, 1221, // x.431
|
|
1145, 1073, 1006, 942, 883, 827, 775, 725, 679, // x.440
|
|
636, 595, 557, 521, 487, 456, 426, 399, 373, // x.449
|
|
348, 325, 304, 284, 265, 248, 231, 216, 202, // x.458
|
|
188, 175, 164, 153, 142, 133, 124, 115, 107, // x.467
|
|
100, 93, 87, 81, 75, 70, 65, 61, 56, // x.476
|
|
53, 49, 45, 42, 39, 36, 34, 31, 29, // x.485
|
|
27, 25, 23, 22, 20, 19, 17, 16, 15, // x.494
|
|
14, 13, 12, 11, 10, 9, 9, 8, 7, // x.503
|
|
7, 6, 6, 5, 5, 5, 4, 4, 4, // x.512
|
|
3, 3, 3, 3, 2, 2, 2, 2, 2, // x.521
|
|
2, 2, 1, 1, 1, 1, 1, 1, 1, // x.530
|
|
1, 1, 1, 1, 1, 1, 0, 0, // isum 100000000000
|
|
};
|
|
|
|
int32_t Peggy_inds[539] = {289, 404, 50, 490, 59, 208, 87, 508, 366, 288, 13, 38, 159, 440, 120, 480, 361, 104, 534, 195, 300, 362, 489, 108, 143, 220, 131, 244, 133, 473, 315, 439, 210, 456, 219, 352, 153, 444, 397, 491, 286, 479, 519, 384, 126, 369, 155, 427, 373, 360, 135, 297, 256, 506, 322, 425, 501, 251, 75, 18, 420, 537, 443, 438, 407, 145, 173, 78, 340, 240, 422, 160, 329, 32, 127, 128, 415, 495, 372, 522, 60, 238, 129, 364, 471, 140, 171, 215, 378, 292, 432, 526, 252, 389, 459, 350, 233, 408, 433, 51, 423, 19, 62, 115, 211, 22, 247, 197, 530, 7, 492, 5, 53, 318, 313, 283, 169, 464, 224, 282, 514, 385, 228, 175, 494, 237, 446, 105, 150, 338, 346, 510, 6, 348, 89, 63, 536, 442, 414, 209, 216, 227, 380, 72, 319, 259, 305, 334, 236, 103, 400, 176, 267, 355, 429, 134, 257, 527, 111, 287, 386, 15, 392, 535, 405, 23, 447, 399, 291, 112, 74, 36, 435, 434, 330, 520, 335, 201, 478, 17, 162, 483, 33, 130, 436, 395, 93, 298, 498, 511, 66, 487, 218, 65, 309, 419, 48, 214, 377, 409, 462, 139, 349, 4, 513, 497, 394, 170, 307, 241, 185, 454, 29, 367, 465, 194, 398, 301, 229, 212, 477, 303, 39, 524, 451, 116, 532, 30, 344, 85, 186, 202, 517, 531, 515, 230, 331, 466, 147, 426, 234, 304, 64, 100, 416, 336, 199, 383, 200, 166, 258, 95, 188, 246, 136, 90, 68, 45, 312, 354, 184, 314, 518, 326, 401, 269, 217, 512, 81, 88, 272, 14, 413, 328, 393, 198, 226, 381, 161, 474, 353, 337, 294, 295, 302, 505, 137, 207, 249, 46, 98, 27, 458, 482, 262, 253, 71, 25, 0, 40, 525, 122, 341, 107, 80, 165, 243, 168, 250, 375, 151, 503, 124, 52, 343, 371, 206, 178, 528, 232, 424, 163, 273, 191, 149, 493, 177, 144, 193, 388, 1, 412, 265, 457, 255, 475, 223, 41, 430, 76, 102, 132, 96, 97, 316, 472, 213, 263, 3, 317, 324, 274, 396, 486, 254, 205, 285, 101, 21, 279, 58, 467, 271, 92, 538, 516, 235, 332, 117, 500, 529, 113, 445, 390, 358, 79, 34, 488, 245, 83, 509, 203, 476, 496, 347, 280, 12, 84, 485, 323, 452, 10, 146, 391, 293, 86, 94, 523, 299, 91, 164, 363, 402, 110, 321, 181, 138, 192, 469, 351, 276, 308, 277, 428, 182, 260, 55, 152, 157, 382, 121, 507, 225, 61, 431, 31, 106, 327, 154, 16, 49, 499, 73, 70, 449, 460, 187, 24, 248, 311, 275, 158, 387, 125, 67, 284, 35, 463, 190, 179, 266, 376, 221, 42, 26, 290, 357, 268, 43, 167, 99, 374, 242, 156, 239, 403, 339, 183, 320, 180, 306, 379, 441, 20, 481, 141, 77, 484, 69, 410, 502, 172, 417, 118, 461, 261, 47, 333, 450, 296, 453, 368, 359, 437, 421, 264, 504, 281, 270, 114, 278, 56, 406, 448, 411, 521, 418, 470, 123, 455, 148, 356, 468, 109, 204, 533, 365, 8, 345, 174, 370, 28, 57, 11, 2, 231, 310, 196, 119, 82, 325, 44, 342, 37, 189, 142, 222, 9, 54, };
|
|
|
|
char *peggy_contracts[64] =
|
|
{
|
|
"BTCD", "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", // major currencies
|
|
"CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK",
|
|
"BTCUSD", "NXTBTC", "SuperNET", "ETHBTC", "LTCBTC", "XMRBTC", "BTSBTC", "XCPBTC", // BTC priced
|
|
"XAUUSD", "XAGUSD", "XPTUSD", "XPDUSD", "Copper", "NGAS", "UKOil", "USOil", // USD priced
|
|
"Bund", "NAS100", "SPX500", "US30", "EUSTX50", "UK100", "JPN225", "GER30", "SUI30", "AUS200", "HKG33", "XAUUSD", "BTCRUB", "BTCCNY", "BTCUSD" // abstract
|
|
};
|
|
|
|
uint32_t peggy_mils(int32_t i)
|
|
{
|
|
uint32_t minmils = 0;
|
|
if ( i == 0 )
|
|
return(1000000);
|
|
else if ( i <= 32 )
|
|
minmils = 10 * prices777_mindenomination(i-1);
|
|
else if ( i >= 64 )
|
|
return(10000);
|
|
else if ( peggy_contracts[i] != 0 )
|
|
{
|
|
if ( is_decimalstr(peggy_contracts[i]+strlen(peggy_contracts[i])-2) != 0 || strcmp(peggy_contracts[i],"BTCRUB") == 0 )
|
|
minmils = 1;
|
|
else if ( strncmp(peggy_contracts[i],"XAU",3) == 0 || strcmp(peggy_contracts[i],"BTCCNY") == 0 || strcmp(peggy_contracts[i],"BTCUSD") == 0 || strncmp(peggy_contracts[i],"XPD",3) == 0 || strncmp(peggy_contracts[i],"XPT",3) == 0 )
|
|
minmils = 10;
|
|
else if ( strcmp(peggy_contracts[i],"Bund") == 0 || strcmp(peggy_contracts[i],"UKOil") == 0 || strcmp(peggy_contracts[i],"USOil") == 0 )
|
|
minmils = 100;
|
|
else if ( strncmp(peggy_contracts[i],"LTC",3) == 0 || strcmp(peggy_contracts[i],"SuperNET") == 0 || strncmp(peggy_contracts[i],"XAG",3) == 0 || strncmp(peggy_contracts[i],"ETH",3) == 0 || strncmp(peggy_contracts[i],"XCP",3) == 0 )
|
|
minmils = 1000;
|
|
else if ( strncmp(peggy_contracts[i],"XMR",3) == 0 )
|
|
minmils = 10000;
|
|
else if ( strncmp(peggy_contracts[i],"NXT",3) == 0 || strncmp(peggy_contracts[i],"BTS",3) == 0 )
|
|
minmils = 1000000;
|
|
else if ( strncmp(peggy_contracts[i],"DOGE",3) == 0 )
|
|
minmils = 100000000;
|
|
else minmils = 10000;
|
|
}
|
|
return(minmils);
|
|
}
|
|
|
|
int32_t peggy_setprice(struct peggy *PEG,struct price_resolution price,int32_t minute)
|
|
{
|
|
if ( PEG->name.hasprice != 0 )
|
|
{
|
|
if ( price.Pval > PRICE_RESOLUTION_MAXPVAL )
|
|
{
|
|
printf("peggy_setdayprice clip.%lld with %lld\n",(long long)price.Pval,(long long)PRICE_RESOLUTION_MAXPVAL);
|
|
price.Pval = PRICE_RESOLUTION_MAXPVAL;
|
|
}
|
|
else if ( price.Pval <= 0 )
|
|
{
|
|
printf("peggy_setdayprice illegal negative of zeroprice %lld %s\n",(long long)price.Pval,PEG->name.name);
|
|
price.Pval = 0;
|
|
}
|
|
if ( PEG->baseprices[minute] != 0 )
|
|
price.Pval = (uint32_t)(price.Pval + PEG->baseprices[minute]) >> 1;
|
|
else if ( minute > PEG->RTminute )
|
|
PEG->RTminute = minute;
|
|
PEG->baseprices[minute] = (uint32_t)price.Pval;
|
|
while ( --minute > 0 && PEG->baseprices[minute] == 0 )
|
|
PEG->baseprices[minute] = (uint32_t)price.Pval;
|
|
}
|
|
return(minute);
|
|
}
|
|
|
|
struct price_resolution peggy_shortprice(struct peggy *PEG,struct price_resolution price)
|
|
{
|
|
struct price_resolution shortprice;
|
|
memset(&shortprice,0,sizeof(shortprice));
|
|
if ( price.Pval != 0 )
|
|
shortprice.Pval = ((PRICE_RESOLUTION * PEG->genesisprice.Pval) / price.Pval);
|
|
return(shortprice);
|
|
}
|
|
|
|
struct price_resolution peggy_price(struct peggy *PEG,int32_t minute)
|
|
{
|
|
struct price_resolution relprice,price;
|
|
memset(&price,0,sizeof(price));
|
|
if ( minute == PEG->RTminute )
|
|
minute--;
|
|
while ( (price.Pval= PEG->baseprices[minute]) == 0 && minute >= 0 )
|
|
minute--;
|
|
if ( PEG->name.hasprice == 0 )
|
|
{
|
|
relprice.Pval = PEG->relprices[minute];
|
|
if ( relprice.Pval != 0 )
|
|
{
|
|
if ( price.Pval < PRICE_RESOLUTION_MAXPVAL )
|
|
price.Pval = (PRICE_RESOLUTION * price.Pval) / relprice.Pval;
|
|
else price.Pval = PRICE_RESOLUTION_ROOT * ((PRICE_RESOLUTION_ROOT * price.Pval) / relprice.Pval);
|
|
} else price.Pval = 0;
|
|
}
|
|
return(price);
|
|
}
|
|
|
|
struct price_resolution peggy_aveprice(struct peggy *PEG,int32_t day,int32_t width)
|
|
{
|
|
int32_t i,n; struct price_resolution price,aveprice;
|
|
aveprice.Pval = 0;
|
|
for (i=n=0; i<width; i++,day++)
|
|
{
|
|
price.Pval = PEG->dayprices[day];
|
|
if ( price.Pval != 0 )
|
|
aveprice.Pval += price.Pval, n++;
|
|
}
|
|
if ( n != 0 )
|
|
aveprice.Pval /= n;
|
|
return(aveprice);
|
|
}
|
|
|
|
// init time
|
|
void peggy_descriptions(struct peggy_info *PEGS,struct peggy_description *P,char *name,char *base,char *rel)
|
|
{
|
|
int32_t emptyslot;
|
|
strcpy(P->name,name), strcpy(P->base,base);
|
|
if ( rel != 0 )
|
|
strcpy(P->rel,rel);
|
|
P->assetbits = peggy_assetbits(name), P->basebits = stringbits(base), P->relbits = stringbits(P->rel);
|
|
P->baseid = add_uint64(PEGS->basebits,sizeof(PEGS->basebits)/sizeof(*PEGS->basebits),P->basebits);
|
|
P->relid = add_uint64(PEGS->basebits,sizeof(PEGS->basebits)/sizeof(*PEGS->basebits),P->relbits);
|
|
if ( find_uint64(&emptyslot,PEGS->basebits,sizeof(PEGS->basebits)/sizeof(*PEGS->basebits),P->basebits) != P->baseid )
|
|
printf("(%s) (%s) (%s) error cant find baseid.%d for %llx\n",name,base,P->rel,P->baseid,(long long)P->basebits);
|
|
if ( P->relbits != 0 && find_uint64(&emptyslot,PEGS->basebits,sizeof(PEGS->basebits)/sizeof(*PEGS->basebits),P->relbits) != P->relid )
|
|
printf("(%s) (%s) (%s) error cant find relid.%d for %llx\n",name,base,P->rel,P->relid,(long long)P->relbits);
|
|
}
|
|
|
|
/*int32_t peggy_timeframes(struct peggy_limits *limits,int64_t *scales,uint32_t *timeframes,int32_t numtimeframes,uint64_t maxsupply,uint64_t maxnetbalance)
|
|
{
|
|
int32_t i;
|
|
memset(limits,0,sizeof(*limits));
|
|
limits->maxsupply = maxsupply, limits->maxnetbalance = maxnetbalance;
|
|
if ( limits->maxsupply < 0 || limits->maxnetbalance < 0 )
|
|
{
|
|
printf("peggy_check_limits: maxnetbalance %lld > %d\n",(long long)limits->maxnetbalance,(int32_t)PRICE_RESOLUTION);
|
|
return(-1);
|
|
}
|
|
limits->numtimeframes = (numtimeframes <= MAX_TIMEFRAMES) ? numtimeframes : MAX_TIMEFRAMES;
|
|
for (i=0; i<limits->numtimeframes; i++)
|
|
{
|
|
limits->scales[i] = scales[i];
|
|
if ( (limits->timeframes[i]= PEGGY_DAYTICKS * timeframes[i]) > MAX_TIMEFRAME || (i > 0 && limits->timeframes[i] <= limits->timeframes[i-1]) )
|
|
{
|
|
printf("createpeg: illegal timeframe.%d: %d %d vs %d\n",i,timeframes[i],limits->timeframes[i],MAX_TIMEFRAME);
|
|
getchar(); return(-1);
|
|
}
|
|
}
|
|
limits->timeframes[0] = 0;
|
|
return(0);
|
|
}*/
|
|
|
|
int32_t peggy_lockparms(struct peggy_lock *dest,int32_t peg,struct peggy_lock *lockparms)
|
|
{
|
|
if ( lockparms->minlockdays > lockparms->maxlockdays )
|
|
{
|
|
printf("peggy_check_lockparms: minlockdays %d > %d maxlockdays\n",lockparms->minlockdays,lockparms->maxlockdays);
|
|
return(-1);
|
|
}
|
|
if ( lockparms->mixrange == 0 )
|
|
lockparms->mixrange = PEGGY_MIXRANGE;
|
|
if ( lockparms->extralockdays < PEGGY_MINEXTRADAYS * 2 )
|
|
lockparms->extralockdays = PEGGY_MINEXTRADAYS * 2;
|
|
*dest = *lockparms, dest->peg = peg;
|
|
return(0);
|
|
}
|
|
|
|
int32_t peggy_setvars(struct peggy_info *PEGS,struct peggy *PEG,int16_t baseid,int16_t relid,int32_t peg,uint64_t maxsupply,uint64_t maxnetbalance,struct peggy_lock *lockparms,uint32_t unitincr,int32_t dailyrate,struct price_resolution *initialprices,int32_t numprices,int32_t hasprice)
|
|
{
|
|
int32_t i;
|
|
PEG->name.id = peg, PEG->name.hasprice = hasprice;
|
|
//if ( peggy_timeframes(&PEG->limits,limits->scales,limits->timeframes,limits->numtimeframes,limits->maxsupply,limits->maxnetbalance) < 0 )
|
|
// return(-1);
|
|
if ( peggy_lockparms(&PEG->lockparms,peg,lockparms) < 0 )
|
|
return(-1);
|
|
PEG->unitincr = unitincr;
|
|
PEG->maxdailyrate = dailyrate;
|
|
PEG->maxsupply = maxsupply, PEG->maxnetbalance = maxnetbalance;
|
|
|
|
if ( initialprices != 0 )
|
|
{
|
|
if ( numprices > 0 )
|
|
{
|
|
//if ( initialprices[0].Pval >= PRICE_RESOLUTION_MAXPVAL )
|
|
// initialprices[0].Pval = PRICE_RESOLUTION_MAXPVAL;
|
|
PEG->genesisprice = PEG->dayprice = PEG->price = initialprices[0];
|
|
for (i=0; i<numprices; i++)
|
|
peggy_setprice(PEG,initialprices[i],i);
|
|
}
|
|
else if ( peg != 0 )
|
|
return(-1);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
struct price_resolution peggy_scaleprice(struct price_resolution price,int64_t peggymils)
|
|
{
|
|
price.Pval = (10000 * price.Pval) / peggymils;
|
|
return(price);
|
|
}
|
|
|
|
struct peggy *peggy_createpair(struct peggy_info *PEGS,int64_t quorum,int64_t decisionthreshold,char *name,char *base,char *rel,uint64_t maxsupply,uint64_t maxnetbalance,struct peggy_lock *lockparms,uint32_t unitincr,int32_t maxdailyrate,uint32_t firsttimestamp,struct price_resolution *initialprices,int32_t numprices,struct price_resolution spread,uint16_t maxmargin,struct price_resolution mindenomination,int32_t contractnum,int32_t hasprice,int32_t peggymils)
|
|
{
|
|
struct peggy *PEG; char *maincurrency; uint64_t assetbits,mainunitsize; int32_t i;
|
|
maincurrency = PEGS->maincurrency, mainunitsize = PEGS->mainunitsize;
|
|
if ( lockparms == 0 )
|
|
lockparms = &PEGS->default_lockparms;
|
|
//if ( limits == 0 )
|
|
// limits = &PEGS->default_limits;
|
|
if ( (PEGS->numpegs == 0 && stringbits(base) != PEGS->mainbits) || maxmargin > PEGGY_MARGINMAX )
|
|
{
|
|
printf("peggy_create: numpegs.%d mismatched maincurrency.(%s) || illegal maxmargin.%d vs %d\n",PEGS->numpegs,maincurrency,maxmargin,PEGGY_MARGINMAX);
|
|
return(0);
|
|
}
|
|
if ( firsttimestamp + (numprices-1)*PEGGY_DAYTICKS > time(NULL) )
|
|
{
|
|
printf("peggy_createpair latest price must be in the past: 1st.%u + numprices.%d -> %u vs %u\n",firsttimestamp,numprices,firsttimestamp + (numprices-1)*PEGGY_DAYTICKS,(uint32_t)time(NULL));
|
|
return(0);
|
|
}
|
|
if ( quorum == 0 )
|
|
quorum = PEGS->quorum;
|
|
if ( decisionthreshold == 0 )
|
|
decisionthreshold = PEGS->decisionthreshold;
|
|
assetbits = peggy_assetbits(name);
|
|
if ( PEGS->numpegs > 0 )
|
|
{
|
|
for (i=0; i<PEGS->numpegs; i++)
|
|
if ( PEGS->contracts[i]->name.assetbits == assetbits )
|
|
{
|
|
printf("peggy_create: cant create duplicate peggy.(%s) base.(%s) rel.(%s)\n",name,base,rel);
|
|
return(0);
|
|
}
|
|
}
|
|
if ( hasprice != 0 )
|
|
PEG = &PEGS->pricedpegs[PEGS->numpricedpegs].PEG;
|
|
else PEG = &PEGS->pairedpegs[PEGS->numpairedpegs];
|
|
memset(PEG,0,sizeof(*PEG));
|
|
peggy_descriptions(PEGS,&PEG->name,name,base,rel);
|
|
PEG->pool.quorum = (quorum != 0) ? quorum : PEGS->quorum, PEG->pool.decisionthreshold = (decisionthreshold != 0) ? decisionthreshold : PEGS->decisionthreshold;
|
|
PEG->pool.mainunitsize = PEGS->mainunitsize, PEG->pool.mainbits = PEGS->mainbits;
|
|
PEG->genesistime = firsttimestamp, PEG->name.id = PEGS->numpegs;
|
|
PEG->spread = spread, PEG->lockparms.margin = maxmargin, PEG->mindenomination = mindenomination;
|
|
if ( hasprice == 0 )
|
|
PEG->baseprices = PEGS->pricedpegs[PEG->name.baseid].prices, PEG->relprices = PEGS->pricedpegs[PEG->name.relid].prices;
|
|
else PEG->baseprices = PEGS->pricedpegs[PEG->name.id].prices, PEG->relprices = 0;
|
|
if ( peggy_setvars(PEGS,PEG,PEG->name.baseid,PEG->name.relid,PEGS->numpegs,maxsupply,maxnetbalance,lockparms,unitincr,maxdailyrate,initialprices,numprices,hasprice) < 0 )
|
|
{
|
|
printf("peggy_create: error init peggy.(%s) base.(%s) rel.(%s)\n",name,base,rel);
|
|
return(0);
|
|
}
|
|
//printf("PEG.%p num.%d priced.%d paired.%d\n",PEG,PEGS->numpegs,PEGS->numpricedpegs,PEGS->numpairedpegs);
|
|
if ( hasprice != 0 )
|
|
PEGS->numpricedpegs++;
|
|
else PEGS->numpairedpegs++;
|
|
PEGS->contracts[PEGS->numpegs++] = PEG;
|
|
PEG->peggymils = peggymils;
|
|
PEG->name.enabled = 1;
|
|
return(PEG);
|
|
}
|
|
|
|
struct peggy_info *peggy_init(char *path,int32_t maxdays,char *maincurrency,uint64_t maincurrencyunitsize,uint64_t quorum,uint64_t decisionthreshold,struct price_resolution spread,uint32_t dailyrate,int32_t interesttenths,int32_t posboost,int32_t negpenalty,int32_t feediv,int32_t feemult,uint32_t firsttimestamp,uint32_t BTCD_price0)
|
|
{
|
|
//struct peggy_limits limits = { { PERCENTAGE(10), PERCENTAGE(25), PERCENTAGE(33), PERCENTAGE(50) }, SATOSHIDEN * 10000, SATOSHIDEN * 1000, { 0, 30, 90, 180 }, 4 };
|
|
struct peggy_lock default_lockparms = { 7, 365, 7, 0, 180, 0, -1 };
|
|
struct price_resolution mindenom,price; struct peggy_info *PEGS = calloc(1,sizeof(*PEGS));
|
|
//if ( default_limits != 0 )
|
|
// limits = *default_limits;
|
|
spread.Pval = PERCENTAGE(1);
|
|
ensure_directory(path);
|
|
strcpy(PEGS->maincurrency,maincurrency);
|
|
PEGS->mainbits = stringbits(maincurrency), PEGS->mainunitsize = maincurrencyunitsize, PEGS->quorum = quorum, PEGS->decisionthreshold = decisionthreshold;
|
|
PEGS->default_lockparms = default_lockparms, PEGS->default_lockparms.maxlockdays = maxdays;
|
|
//PEGS->default_limits = limits,
|
|
PEGS->default_spread = spread, PEGS->default_dailyrate = dailyrate;
|
|
PEGS->interesttenths = interesttenths, PEGS->posboost = posboost, PEGS->negpenalty = negpenalty, PEGS->feediv = feediv, PEGS->feemult = feemult;
|
|
mindenom.Pval = PRICE_RESOLUTION;
|
|
PEGS->genesistime = firsttimestamp;
|
|
price.Pval = PEGS->BTCD_price0 = BTCD_price0;
|
|
printf("set genesistime.%u BTCD0.%u\n",firsttimestamp,BTCD_price0);
|
|
peggy_createpair(PEGS,0,0,"BTCD","BTCD",0,SATOSHIDEN*1000000,SATOSHIDEN*100000,0,SATOSHIDEN,PEGGY_RATE_777,firsttimestamp,&price,1,spread,0,mindenom,0,1,peggy_mils(0));
|
|
PEGS->accts = accts777_init(path,0);
|
|
return(PEGS);
|
|
}
|
|
//////////// end of consensus safe
|
|
|
|
int32_t peggy_prices(struct price_resolution prices[64],double btcusd,double btcdbtc,char *contracts[],int32_t num,double *cprices,double *basevals)
|
|
{
|
|
int32_t prices777_contractnum(char *base,char *rel);
|
|
double btcdusd,price_in_btcd,dprice,usdcny,usdrub,btccny,btcrub,xauusd,usdprice=0.,usdval,btcprice=0.; int32_t contractnum,base,nonz = 0;
|
|
if ( btcusd > SMALLVAL && btcdbtc > SMALLVAL && (usdval= basevals[0]) > SMALLVAL )
|
|
{
|
|
xauusd = usdcny = usdrub = btccny = btcrub = 0.;
|
|
for (contractnum=0; contractnum<num; contractnum++)
|
|
if ( strcmp(contracts[contractnum],"XAUUSD") == 0 )
|
|
{
|
|
xauusd = cprices[contractnum];
|
|
break;
|
|
}
|
|
if ( basevals[8] > SMALLVAL )
|
|
{
|
|
usdcny = (basevals[0] * peggy_mils(8)) / (basevals[8] * peggy_mils(0));
|
|
btccny = 1000 * btcusd * usdcny;
|
|
}
|
|
if ( basevals[9] > SMALLVAL )
|
|
{
|
|
usdrub = (basevals[0] * peggy_mils(9)) / (basevals[9] * peggy_mils(0));
|
|
btcrub = 1000 * btcusd * usdrub;
|
|
}
|
|
btcdusd = (btcusd * btcdbtc);
|
|
printf("xauusd %f usdval %f %f %f usdcny %f usdrub %f btcusd %f btcdbtc %f btcdusd %f btccny %f btcrub %f\n",xauusd,usdval,basevals[8],basevals[9],usdcny,usdrub,btcusd,btcdbtc,btcdusd,btccny,btcrub);
|
|
prices[0].Pval = (PRICE_RESOLUTION * 100. * btcdbtc);
|
|
for (base=0,contractnum=1; base<32; base++,contractnum++)
|
|
{
|
|
if ( strcmp(contracts[contractnum],CURRENCIES[base]) == 0 )
|
|
{
|
|
if ( (dprice= basevals[base]) > SMALLVAL )
|
|
{
|
|
nonz++;
|
|
if ( base == 0 )
|
|
usdprice = price_in_btcd = (1. / btcdusd);
|
|
else price_in_btcd = (dprice / (btcdusd * usdval));
|
|
prices[contractnum].Pval = (PRICE_RESOLUTION * price_in_btcd);
|
|
}
|
|
} else printf("unexpected list entry %s vs %s at %d\n",contracts[contractnum],CURRENCIES[base],contractnum);
|
|
}
|
|
if ( strcmp(contracts[contractnum],"BTCUSD") != 0 )
|
|
printf("unexpected contract (%s) at %d\n",contracts[contractnum],contractnum);
|
|
btcprice = (1. / btcdbtc);
|
|
prices[contractnum++].Pval = (PRICE_RESOLUTION / btcdbtc) / 1000.;
|
|
printf("btcprice %f = 1/%f %llu\n",btcprice,1./btcdbtc,(long long)prices[contractnum-1].Pval);
|
|
for (; contractnum<64; contractnum++)
|
|
{
|
|
//dprice = 0;
|
|
if ( contractnum == 63 && strcmp(contracts[contractnum],"BTCUSD") == 0 )
|
|
dprice = btcusd;
|
|
else if ( contractnum == 62 && strcmp(contracts[contractnum],"BTCCNY") == 0 )
|
|
dprice = btccny;
|
|
else if ( contractnum == 61 && strcmp(contracts[contractnum],"BTCRUB") == 0 )
|
|
dprice = btcrub;
|
|
else if ( contractnum == 60 && strcmp(contracts[contractnum],"XAUUSD") == 0 )
|
|
dprice = xauusd;
|
|
else
|
|
{
|
|
dprice = cprices[contractnum];
|
|
if ( dprice > SMALLVAL && strlen(contracts[contractnum]) > 3 )
|
|
{
|
|
if ( strcmp(contracts[contractnum]+strlen(contracts[contractnum])-3,"USD") == 0 || strcmp(contracts[contractnum],"Copper") == 0 || strcmp(contracts[contractnum],"NGAS") == 0 || strcmp(contracts[contractnum],"UKOil") == 0 || strcmp(contracts[contractnum],"USOil") == 0 )
|
|
dprice *= usdprice;
|
|
else if ( strcmp(contracts[contractnum],"SuperNET") == 0 )
|
|
{
|
|
printf("SuperNET %f -> %f\n",dprice,dprice*btcprice);
|
|
dprice *= btcprice;
|
|
}
|
|
else if ( strcmp(contracts[contractnum]+strlen(contracts[contractnum])-3,"BTC") == 0 )
|
|
dprice *= btcprice;
|
|
}
|
|
}
|
|
prices[contractnum].Pval = (uint64_t)((PRICE_RESOLUTION * dprice) * ((double)peggy_mils(contractnum) / 10000.));
|
|
//if ( Debuglevel > 2 )
|
|
{
|
|
struct price_resolution tmp;
|
|
tmp = peggy_scaleprice(prices[contractnum],peggy_mils(contractnum));
|
|
printf("%.8f btcprice %.6f %f -->>> %s %.6f -> %llu %.6f mils.%d\n",cprices[contractnum],btcprice,cprices[contractnum]*btcprice,contracts[contractnum],Pval(&tmp),(long long)prices[contractnum].Pval,Pval(&prices[contractnum]),peggy_mils(contractnum));
|
|
}
|
|
}
|
|
}
|
|
return(nonz);
|
|
}
|
|
|
|
char *peggy_emitprices(int32_t *nonzp,struct peggy_info *PEGS,uint32_t blocktimestamp,int32_t maxlockdays)
|
|
{
|
|
double matrix[32][32],RTmatrix[32][32],cprices[64],basevals[64]; struct price_resolution prices[256];
|
|
cJSON *json,*array; char *jsonstr,*opreturnstr = 0; int32_t i,nonz = 0;
|
|
memset(cprices,0,sizeof(cprices));
|
|
//printf("peggy_emitprices\n");
|
|
if ( prices777_getmatrix(basevals,&PEGS->btcusd,&PEGS->btcdbtc,matrix,cprices+1,peggy_contracts+1,sizeof(peggy_contracts)/sizeof(*peggy_contracts)-1,blocktimestamp) > 0 )
|
|
{
|
|
cprices[0] = PEGS->btcdbtc;
|
|
/*for (i=0; i<32; i++)
|
|
printf("%f ",basevals[i]);
|
|
printf("basevals\n");
|
|
for (i=0; i<64; i++)
|
|
printf("%f ",cprices[i]);
|
|
printf("cprices\n");*/
|
|
json = cJSON_CreateObject(), array = cJSON_CreateArray();
|
|
memset(prices,0,sizeof(prices));
|
|
memset(matrix,0,sizeof(matrix));
|
|
memset(RTmatrix,0,sizeof(RTmatrix));
|
|
peggy_prices(prices,PEGS->btcusd,PEGS->btcdbtc,peggy_contracts,sizeof(peggy_contracts)/sizeof(*peggy_contracts),cprices,basevals);
|
|
for (i=0; i<sizeof(peggy_contracts)/sizeof(*peggy_contracts); i++)
|
|
{
|
|
jaddinum(array,prices[i].Pval);
|
|
if ( prices[i].Pval != 0 )
|
|
nonz++;
|
|
if ( Debuglevel > 2 )
|
|
printf("{%s %.6f %u}.%d ",peggy_contracts[i],Pval(&prices[i]),(uint32_t)prices[i].Pval,peggy_mils(i));
|
|
}
|
|
jaddnum(json,"txtype",PEGGY_TXPRICES);
|
|
//jaddnum(json,"btcusd",btc.Pval);
|
|
if ( maxlockdays != 0 )
|
|
{
|
|
jaddnum(json,"timestamp",blocktimestamp);
|
|
jaddnum(json,"maxlockdays",maxlockdays);
|
|
}
|
|
//jaddstr(json,"privkey","1259ec21d31a30898d7cd1609f80d9668b4778e3d97e941044b39f0c44d2e51b");
|
|
jadd(json,"details",array);
|
|
jsonstr = jprint(json,1);
|
|
//printf("%s\n",jsonstr);
|
|
opreturnstr = peggy_tx(jsonstr);
|
|
free(jsonstr);
|
|
} else printf("pricematrix returned null\n");
|
|
*nonzp = nonz;
|
|
//printf("nonz.%d\n",nonz);
|
|
return(opreturnstr);
|
|
}
|
|
|
|
uint64_t peggy_basebits(char *name)
|
|
{
|
|
int32_t i; char basebuf[64],relbuf[64];
|
|
for (i=0; i<64; i++)
|
|
{
|
|
if ( strcmp(name,peggy_contracts[i]) == 0 )
|
|
{
|
|
peggy_mapname(basebuf,relbuf,i);
|
|
return(stringbits(basebuf));
|
|
}
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
uint64_t peggy_relbits(char *name)
|
|
{
|
|
int32_t i; char basebuf[64],relbuf[64];
|
|
for (i=0; i<64; i++)
|
|
{
|
|
if ( strcmp(name,peggy_contracts[i]) == 0 )
|
|
{
|
|
peggy_mapname(basebuf,relbuf,i);
|
|
return(stringbits(relbuf));
|
|
}
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
struct peggy_info *peggy_genesis(int32_t lookbacks[OPRETURNS_CONTEXTS],struct peggy_info *PEGS,char *path,uint32_t firsttimestamp,char *opreturnstr)
|
|
{
|
|
//struct peggy_limits limits = { { PERCENTAGE(10), PERCENTAGE(25), PERCENTAGE(33), PERCENTAGE(50) }, SATOSHIDEN * 10000, SATOSHIDEN * 1000, { 0, 30, 90, 180 }, 4 };
|
|
char name[64],base[64],rel[64]; uint8_t opret[1024]; struct peggy_tx Ptx; struct peggy *PEG;
|
|
struct price_resolution mindenom,spread,price; uint64_t len; long offset; uint64_t maxsupply=0,maxnetbalance=0;
|
|
int32_t i,c,baseid,relid,peggymils=0,signedcount,datalen,n=0,maxmargin=0,numprices,err=-1; uint32_t pval = 0;
|
|
numprices = 1;
|
|
datalen = (int32_t)strlen(opreturnstr) / 2;
|
|
decode_hex(opret,datalen,opreturnstr);
|
|
printf("peggy_genesis(%s)\n",opreturnstr);
|
|
if ( opret[0] == OP_RETURN_OPCODE )
|
|
{
|
|
offset = hdecode_varint(&len,opret,1,sizeof(opret));
|
|
if ( opret[offset] == 'P' && opret[offset+1] == 'A' && opret[offset+2] == 'X' )
|
|
{
|
|
printf("deser\n");
|
|
if ( (n= serdes777_deserialize(&signedcount,&Ptx,firsttimestamp,opret+offset+3,(int32_t)len-3)) > 0 )
|
|
{
|
|
err = 0;
|
|
for (i=0; i<Ptx.details.price.num; i++)
|
|
if ( Ptx.details.price.feed[i] == 0 )
|
|
break;
|
|
if ( i == Ptx.details.price.num )
|
|
{
|
|
printf("GENESIS.(%s)\n",opreturnstr);
|
|
for (i=0; i<Ptx.details.price.num; i++)
|
|
printf("%u ",Ptx.details.price.feed[i]);
|
|
printf("prices\n");
|
|
lookbacks[0] = 0, lookbacks[1] = 1000;
|
|
if ( PEGS == 0 )
|
|
{
|
|
spread.Pval = PERCENTAGE(1);
|
|
PEGS = peggy_init(path,PEGGY_MAXLOCKDAYS,"BTCD",SATOSHIDEN/100,1,1,spread,PEGGY_RATE_777,40,10,2,5,2,Ptx.timestamp,Ptx.details.price.feed[0]);
|
|
PEGS->accts = accts777_init(path,0);
|
|
PEGS->genesis = opreturnstr, opreturnstr = 0;
|
|
}
|
|
} else printf("i.%d vs %d\n",i,Ptx.details.price.num);
|
|
} else printf("deser got n.%d\n",n);
|
|
} else printf("illegal opret.(%c%c%c)\n",opret[offset],opret[offset+1],opret[offset+2]);
|
|
} else printf("opret[0] %d\n",opret[0]);
|
|
if ( err < 0 || PEGS == 0 )
|
|
return(0);
|
|
mindenom.Pval = PRICE_RESOLUTION;
|
|
spread.Pval = PERCENTAGE(1);
|
|
for (i=1; i<sizeof(peggy_contracts)/sizeof(*peggy_contracts)+28; i++)
|
|
{
|
|
price.Pval = 0;
|
|
if ( i < sizeof(peggy_contracts)/sizeof(*peggy_contracts) )
|
|
{
|
|
if ( peggy_contracts[i] == 0 )
|
|
continue;
|
|
peggy_mapname(base,rel,i);
|
|
price.Pval = Ptx.details.price.feed[i];
|
|
if ( i <= 8 )
|
|
maxmargin = 25;
|
|
else if ( i < 16 )
|
|
maxmargin = 15;
|
|
else maxmargin = 10;
|
|
peggymils = peggy_mils(i);
|
|
if ( (mindenom.Pval= ((double)PRICE_RESOLUTION * peggymils) / 10000.) == 0 )
|
|
mindenom.Pval = PRICE_RESOLUTION;
|
|
strcpy(name,base);
|
|
if ( strcmp(rel,"BTCD") != 0 && is_decimalstr(base+strlen(base)-2) == 0 && strncmp(rel,"yield",5) != 0 && strcmp(base,"Copper") != 0 && strcmp(base,"NGAS") != 0 && strcmp(base,"UKOil") != 0 && strcmp(base,"USOil") != 0 )
|
|
strcat(name,rel);
|
|
maxsupply = SATOSHIDEN * 10000, maxnetbalance = SATOSHIDEN * 1000;
|
|
if ( strcmp(base,"BTC") == 0 || strcmp(base,"NXT") == 0 || strcmp(base,"USD") == 0 || strcmp(base,"CNY") == 0 )
|
|
maxsupply *= 10, maxnetbalance *= 10;
|
|
price.Pval = Ptx.details.price.feed[i];
|
|
peggy_mapname(base,rel,i);
|
|
pval = Ptx.details.price.feed[i];
|
|
}
|
|
else if ( i-sizeof(peggy_contracts)/sizeof(*peggy_contracts) < PEGGY_MAXPAIREDPEGS )
|
|
{
|
|
extern short Contract_base[],Contract_rel[];
|
|
maxsupply = SATOSHIDEN * 10000, maxnetbalance = SATOSHIDEN * 1000;
|
|
mindenom.Pval = PRICE_RESOLUTION * 10;
|
|
c = i - (int32_t)(sizeof(peggy_contracts)/sizeof(*peggy_contracts));
|
|
strcpy(base,CURRENCIES[Contract_base[c]]), strcpy(rel,CURRENCIES[Contract_rel[c]]);
|
|
strcpy(name,base), strcat(name,rel);
|
|
baseid = Contract_base[c]+1, relid = Contract_rel[c]+1;
|
|
peggymils = (PEGS->contracts[baseid]->peggymils * 10000) / PEGS->contracts[relid]->peggymils;
|
|
if ( strcmp(PEGS->contracts[baseid]->name.base,base) == 0 && strcmp(PEGS->contracts[relid]->name.base,rel) == 0 )
|
|
price.Pval = (PRICE_RESOLUTION * Ptx.details.price.feed[baseid]) / Ptx.details.price.feed[relid];
|
|
else printf("mismatched %p base.(%s) baseid.%d (%s) or %p rel.(%s) relid.%d (%s)\n",PEGS->contracts[baseid],PEGS->contracts[baseid]->name.base,baseid,base,PEGS->contracts[relid],PEGS->contracts[relid]->name.base,relid,rel);
|
|
pval = (uint32_t)price.Pval;
|
|
} else printf("peggy_genesis RAN out of space\n");
|
|
if ( (PEG= peggy_createpair(PEGS,0,0,name,base,rel,maxsupply,maxnetbalance,0,SATOSHIDEN*10,PEGGY_RATE_777,firsttimestamp,&price,numprices,spread,maxmargin,mindenom,i,i<sizeof(peggy_contracts)/sizeof(*peggy_contracts),peggymils)) != 0 )
|
|
{
|
|
price = peggy_scaleprice(price,peggymils);
|
|
struct price_resolution x = peggy_price(PEG,0);
|
|
printf("%9s.(%-8s %5s) %17.10f %.10f %-10d maxmargin %2dx maxsupply %6.0f BTCD maxdiff %7.0f spread %.3f denom %-10.6f mils.%d\n",PEG->name.name,PEG->name.base,PEG->name.rel,Pval(&price),Pval(&x),pval,maxmargin,dstr(maxsupply),dstr(maxnetbalance),Pval(&spread),Pval(&mindenom),PEG->peggymils);
|
|
n++;
|
|
}
|
|
}
|
|
printf("genesis prices t%u vs %u\n",Ptx.timestamp,firsttimestamp);
|
|
return(PEGS);
|
|
}
|
|
|
|
char *peggybase(uint32_t blocknum,uint32_t blocktimestamp)
|
|
{
|
|
int32_t nonz; struct peggy_info *PEGS = opreturns_context("peggy",0);
|
|
if ( PEGS != 0 )
|
|
return(peggy_emitprices(&nonz,PEGS,blocktimestamp,PEGS->genesis != 0 ? 0 : PEGGY_MAXLOCKDAYS));
|
|
return(0);
|
|
}
|
|
|
|
char *peggypayments(uint32_t blocknum,uint32_t blocktimestamp)
|
|
{
|
|
int32_t peggy_payments(queue_t *PaymentsQ,struct opreturn_payment *payments,int32_t max,uint32_t currentblocknum,uint32_t blocknum,uint32_t blocktimestamp);
|
|
struct opreturn_payment payments[8192]; cJSON *json;
|
|
int32_t i,n; struct peggy_info *PEGS = opreturns_context("peggy",0);
|
|
memset(payments,0,sizeof(payments));
|
|
if ( PEGS != 0 && PEGS->accts != 0 && (n= peggy_payments(&PEGS->accts->PaymentsQ,payments,sizeof(payments)/sizeof(*payments),blocknum,blocknum,blocktimestamp)) > 0 )
|
|
{
|
|
json = cJSON_CreateObject();
|
|
for (i=0; i<n; i++)
|
|
jaddnum(json,payments[i].coinaddr,payments[i].value);
|
|
return(jprint(json,1));
|
|
}
|
|
return(clonestr("{}"));
|
|
}
|
|
|
|
int32_t peggyblock(char *jsonstr)
|
|
{
|
|
printf("got peggyblock.(%s)\n",jsonstr);
|
|
return(0);
|
|
}
|
|
|
|
void peggy()
|
|
{
|
|
int32_t lookbacks[OPRETURNS_CONTEXTS],nonz,num,peggylen; uint32_t timestamp;// = (uint32_t)time(0);
|
|
FILE *fp; uint8_t opret[8192]; char fname[512],*opreturnstr; struct peggy_info *PEGS = opreturns_context("peggy",0);
|
|
if ( 0 && PEGS != 0 )
|
|
{
|
|
opreturnstr = peggy_emitprices(&nonz,PEGS,timestamp,PEGS->genesis != 0 ? 0 : PEGGY_MAXLOCKDAYS);
|
|
if ( opreturnstr != 0 )
|
|
{
|
|
printf("OPRETURN.(%s)\n",opreturnstr);
|
|
if ( Debuglevel > 2 )
|
|
printf("update.%d opreturns.(%s) t%u\n",PEGS->numopreturns,opreturnstr,timestamp);
|
|
sprintf(fname,"opreturns/%d",PEGS->numopreturns);
|
|
if ( (fp= fopen(fname,"wb")) != 0 )
|
|
{
|
|
fwrite(opreturnstr,1,strlen(opreturnstr)+1,fp);
|
|
fclose(fp);
|
|
}
|
|
if ( nonz == 64 && PEGS->genesis == 0 )
|
|
peggy_genesis(lookbacks,PEGS,PEGS->path,timestamp,opreturnstr);
|
|
else
|
|
{
|
|
num = 1;
|
|
peggylen = (int32_t)strlen(opreturnstr) / 2;
|
|
decode_hex(opret,peggylen,opreturnstr);
|
|
opreturns_process(1,PEGS->numopreturns,PEGS->numopreturns,timestamp,0,0,opret,peggylen);
|
|
free(opreturnstr);
|
|
PEGS->numopreturns++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
uint64_t map_apr(uint64_t *spreadp,int32_t maxdays,double apr)
|
|
{
|
|
int64_t bestdiff,diff; int32_t i; uint64_t rate,bestsatoshis,satoshis,bestrate = 0,target;
|
|
target = PRICE_RESOLUTION * (1. + apr/100.);
|
|
bestrate = ((PRICE_RESOLUTION * log(apr)/10) / (365-1));
|
|
satoshis = peggy_compound(0,PRICE_RESOLUTION,bestrate,365);
|
|
bestdiff = (satoshis - target);
|
|
if ( bestdiff < 0 )
|
|
bestdiff = -bestdiff;
|
|
//err = ((double)bestdiff / target);
|
|
//n = (int32_t)(err * 4. * bestrate);
|
|
//if ( n < 1000 )
|
|
// n = 1000;
|
|
//printf("err %f %d: new bestdiff %llu, bestrate %llu, satoshis %.8f target %.8f\n",err,n,(long long)bestdiff,(long long)bestrate,(double)satoshis/PRICE_RESOLUTION,(double)target/PRICE_RESOLUTION);
|
|
//for (i=0,rate=bestrate-n; rate<=bestrate+2*n; rate++,i++)
|
|
for (i=0,rate=1; rate<PRICE_RESOLUTION/100; rate++,i++)
|
|
{
|
|
satoshis = peggy_compound(0,PRICE_RESOLUTION,rate,365);
|
|
diff = (satoshis - target);
|
|
if ( diff < 0 )
|
|
diff = -diff;
|
|
if ( diff < bestdiff )
|
|
{
|
|
//printf("i.%d of %d: new bestdiff %llu -> %llu, rate %llu -> %llu, satoshis %.8f target %.8f\n",i,n,(long long)bestdiff,(long long)diff,(long long)bestrate,(long long)rate,(double)satoshis/PRICE_RESOLUTION,(double)target/PRICE_RESOLUTION);
|
|
bestdiff = diff, bestrate = rate, bestsatoshis = satoshis;
|
|
if ( diff == 0 )
|
|
break;
|
|
}
|
|
}
|
|
//printf("\nnew bestdiff %llu rate %llu, satoshis %.8f target %.8f\n",(long long)bestdiff,(long long)bestrate,(double)bestsatoshis/PRICE_RESOLUTION,(double)target/PRICE_RESOLUTION);
|
|
*spreadp = PERCENTAGE((apr * maxdays)/365);
|
|
return(bestrate);
|
|
}
|
|
|
|
uint64_t peggy_dailyrates()
|
|
{
|
|
//struct peggy_limits limits = { { PERCENTAGE(10), PERCENTAGE(25), PERCENTAGE(33), PERCENTAGE(50) }, SATOSHIDEN * 10000, SATOSHIDEN * 1000, { 0, 30, 90, 180 }, 4 };
|
|
extern int32_t dailyrates[];
|
|
uint64_t satoshis,maxspread; int64_t err,errsum; int32_t i,milliperc;
|
|
dailyrates[0] = (int32_t)map_apr(&maxspread,PEGGY_MAXLOCKDAYS,(double)7770/1000);
|
|
satoshis = peggy_compound(0,SATOSHIDEN,dailyrates[0],365);
|
|
printf("%.2f%% %d %llu -> %llu %.2f%%\n",(double)7770/1000,dailyrates[0],(long long)SATOSHIDEN,(long long)satoshis,100. * ((double)(satoshis-SATOSHIDEN)/SATOSHIDEN));
|
|
for (errsum=i=0; i<=100; i++)
|
|
{
|
|
satoshis = peggy_compound(0,SATOSHIDEN,dailyrates[i],365);
|
|
//printf("%.1f%%: %d %llu -> %llu %.3f%%\n",(double)i*.1,dailyrates[i],(long long)PRICE_RESOLUTION,(long long)satoshis,100. * (double)satoshis/PRICE_RESOLUTION - 100.);
|
|
printf("%.2f%% ",100. * (double)satoshis/SATOSHIDEN - 100.);
|
|
err = (satoshis - SATOSHIDEN) - (i == 0 ? 7770000 : i*100000);
|
|
errsum += err < 0 ? -err : err;
|
|
//printf("i.%d err %lld sum %lld\n",i,(long long)err,(long long)errsum);
|
|
}
|
|
errsum /= 101;
|
|
printf("dailyrate check errsum %lld %f%% ave err\n",(long long)errsum,100*dstr(errsum));
|
|
if ( errsum > 10000 )
|
|
{
|
|
//int32_t dailyrates[101];
|
|
for (milliperc=100; milliperc<=10000; milliperc+=100)
|
|
{
|
|
dailyrates[milliperc/100] = (int32_t)map_apr(&maxspread,PEGGY_MAXLOCKDAYS,(double)milliperc/1000);
|
|
satoshis = peggy_compound(0,SATOSHIDEN,dailyrates[milliperc/100],365);
|
|
printf("%.2f%% %d %llu -> %llu %.3f%%\n",(double)milliperc/1000,dailyrates[milliperc/100],(long long)SATOSHIDEN,(long long)satoshis,100. * ((double)(satoshis-SATOSHIDEN)/SATOSHIDEN));
|
|
}
|
|
for (i=0; i<=100; i++)
|
|
printf("%d, ",dailyrates[i]);
|
|
printf("dailyrates in 0.1%% incr\n");
|
|
printf("root.%lld resolution.%lld squared.%llu maxPval.%llu maxunits.%d\n",(long long)PRICE_RESOLUTION_ROOT,(long long)PRICE_RESOLUTION,(long long)PRICE_RESOLUTION2,(long long)PRICE_RESOLUTION_MAXPVAL,PRICE_RESOLUTION_MAXUNITS);
|
|
}
|
|
return(errsum);
|
|
}
|
|
|
|
void *peggy_replay(char *path,struct txinds777_info *opreturns,void *_PEGS,uint32_t blocknum,char *opreturnstr,uint8_t *data,int32_t datalen)
|
|
{
|
|
int32_t lookbacks[OPRETURNS_CONTEXTS]; uint64_t allocsize,len; int32_t n,signedcount,valid=0; long offset; struct price_resolution tmp;
|
|
char fname[512]; uint8_t opret[8192]; struct peggy_tx Ptx; struct peggy_info *PEGS = _PEGS;
|
|
if ( blocknum == 0 )
|
|
opreturnstr = PEGGY_GENESIS;
|
|
//printf("replay genesis.%p opreturnstr.%p data.%p\n",PEGGY_GENESIS,opreturnstr,data);
|
|
if ( data == 0 )
|
|
{
|
|
data = opret;
|
|
if ( opreturnstr == 0 )
|
|
{
|
|
sprintf(fname,"%s/%d",path,blocknum);
|
|
if ( (opreturnstr= loadfile(&allocsize,fname)) != 0 )
|
|
{
|
|
//printf("loaded.(%s) %s\n",fname,opreturnstr);
|
|
if ( is_hexstr(opreturnstr) != 0 )
|
|
valid = 1;
|
|
} //else printf("couldnt find.(%s)\n",fname);
|
|
} else valid = 1;
|
|
if ( valid != 0 )
|
|
{
|
|
datalen = (int32_t)strlen(opreturnstr) / 2;
|
|
decode_hex(opret,datalen,opreturnstr);
|
|
} else return(0);
|
|
}
|
|
if ( data != 0 && data[0] == OP_RETURN_OPCODE )
|
|
{
|
|
offset = hdecode_varint(&len,data,1,sizeof(opret));
|
|
if ( data[offset] == 'P' && data[offset+1] == 'A' && data[offset+2] == 'X' )
|
|
{
|
|
if ( (n= serdes777_deserialize(&signedcount,&Ptx,0,&data[offset+3],(int32_t)(len - 3))) < 0 )
|
|
printf("peggy_process.%d peggy_deserialize error datalen.%d t%d\n",blocknum,datalen,Ptx.timestamp);
|
|
else
|
|
{
|
|
int32_t j,nonz = 0;
|
|
for (j=0; j<Ptx.details.price.num; j++)
|
|
{
|
|
if ( Ptx.details.price.feed[j] != 0 )
|
|
{
|
|
tmp.Pval = Ptx.details.price.feed[j];
|
|
tmp = peggy_scaleprice(tmp,peggy_mils(j));
|
|
nonz++;
|
|
fprintf(stderr,"(%s %u %.6f) ",peggy_contracts[j],Ptx.details.price.feed[j],Pval(&tmp));
|
|
}
|
|
}
|
|
//fprintf(stderr,"%d ",nonz);
|
|
printf("PEGS.%p PEGGY type.%d %u num.%d nonz.%d\n",PEGS,Ptx.txtype,Ptx.timestamp,Ptx.details.price.num,nonz);
|
|
if ( PEGS == 0 && nonz == Ptx.details.price.num )
|
|
PEGS = peggy_genesis(lookbacks,PEGS,path,Ptx.timestamp,opreturnstr);
|
|
else if ( PEGS != 0 && Ptx.timestamp > PEGS->genesistime )
|
|
{
|
|
Ptx.flags |= PEGGY_FLAGS_PEGGYBASE;
|
|
if ( peggy_process(PEGS,1,&Ptx.funding.src.coinaddr,Ptx.funding.amount,&data[offset+3],(int32_t)len-3,blocknum,Ptx.timestamp,blocknum) < 0 )
|
|
{
|
|
printf("error processing blocknum.%u Ptx.blocknum %u\n",blocknum,blocknum);
|
|
}
|
|
}
|
|
if ( PEGS != 0 )
|
|
PEGS->numopreturns++;
|
|
}
|
|
} else printf("illegal.(%c%c%c)\n",data[offset],data[offset+1],data[offset+2]);
|
|
} else printf("missing OP_RETURN_OPCODE [%02x]\n",data[0]);
|
|
return(PEGS);
|
|
}
|
|
|
|
uint32_t peggy_currentblock(void *_PEGS) { struct peggy_info *PEGS; if ( (PEGS= _PEGS) != 0 ) return(PEGS->numopreturns); return(0); }
|
|
|
|
struct peggy_info *peggy_lchain(struct txinds777_info *opreturns,char *path)
|
|
{
|
|
double startmilli; int32_t i; struct peggy_info *tmp,*PEGS = 0;
|
|
startmilli = milliseconds();
|
|
printf("about to replay\n");
|
|
for (i=0; i<1000000; i++)
|
|
{
|
|
if ( PEGS == 0 && (PEGS= peggy_replay(path,opreturns,PEGS,0,0,0,0)) == 0 )
|
|
break;
|
|
else if ( (tmp= peggy_replay(path,opreturns,PEGS,i,0,0,0)) != PEGS )
|
|
break;
|
|
}
|
|
if ( PEGS != 0 )
|
|
printf("loaded %d in %.3f millis per opreturn\n",PEGS->numopreturns,(milliseconds() - startmilli)/PEGS->numopreturns);// getchar();
|
|
return(PEGS);
|
|
}
|
|
|
|
void norm_smooth_wts(int32_t j,double *smoothwts,int32_t n)
|
|
{
|
|
double wt; int32_t iter,i;
|
|
for (iter=0; iter<13; iter++)
|
|
{
|
|
wt = 0.;
|
|
for (i=0; i<n; i++)
|
|
wt += smoothwts[i];
|
|
//printf("wtsum.j%d %.40f ",j,wt);
|
|
for (i=0; i<n; i++)
|
|
smoothwts[i] /= wt;
|
|
}
|
|
//printf("\n");
|
|
}
|
|
|
|
void calc_smooth_code(int32_t smoothwidth,int32_t _maxprimes)
|
|
{
|
|
double _coeffs[5000],sum,coeffs[60][10000],smoothbuf[10000]; int32_t x,p,prime,numprimes; uint64_t val,isum = 0;
|
|
_maxprimes = MIN((int32_t)(sizeof(coeffs)/(sizeof(double)*10000))-1,_maxprimes);
|
|
smoothwidth = MIN((int32_t)(sizeof(_coeffs)/sizeof(*_coeffs)),smoothwidth);
|
|
x = 5000;
|
|
memset(smoothbuf,0,sizeof(smoothbuf));
|
|
coeffs[0][x-2] = coeffs[0][x] = coeffs[0][x+2] = 1./3.;
|
|
for (numprimes=_maxprimes; numprimes>=3; numprimes--)
|
|
{
|
|
for (p=1; p<numprimes; p++)
|
|
{
|
|
memcpy(coeffs[p],coeffs[p-1],sizeof(coeffs[p]));
|
|
prime = smallprimes[p];
|
|
for (x=0; x<10000; x++)
|
|
{
|
|
coeffs[p][x] += (coeffs[p-1][x - prime] / 3.);
|
|
coeffs[p][x] += (coeffs[p-1][x] / 3.);
|
|
coeffs[p][x] += (coeffs[p-1][x + prime] / 3.);
|
|
}
|
|
}
|
|
memcpy(smoothbuf,coeffs[numprimes-1],sizeof(smoothbuf));
|
|
memset(coeffs,0,sizeof(coeffs));
|
|
sum = 0.;
|
|
for (x=0; x<10000; x++)
|
|
{
|
|
if ( smoothbuf[x] != 0. )
|
|
{
|
|
sum += smoothbuf[x];
|
|
//printf("(%d %f) ",x-5000,smoothbuf[x]);
|
|
}
|
|
}
|
|
//printf("maxprimes.%d\n",maxprimes);
|
|
for (x=0; x<10000; x++)
|
|
coeffs[0][x] = (smoothbuf[x] / sum);
|
|
}
|
|
sum = 0.;
|
|
for (x=0; x<10000; x++)
|
|
sum += smoothbuf[x];
|
|
memset(coeffs,0,sizeof(coeffs));
|
|
if ( sum != 0. )
|
|
{
|
|
printf("double Smooth_coeffs[%d] = // numprimes.%d\n{\n",smoothwidth,_maxprimes);
|
|
for (x=0; x<10000; x++)
|
|
{
|
|
if ( smoothbuf[x] != 0. )
|
|
{
|
|
smoothbuf[x] = (1000000. * 1000000. * smoothbuf[x]) / sum;
|
|
//printf("(%d %f) ",x-5000,smoothbuf[x]);
|
|
}
|
|
}
|
|
_coeffs[0] = smoothbuf[5000];
|
|
for (x=1; x<=smoothwidth; x++)
|
|
{
|
|
if ( fabs(smoothbuf[5000 - x] - smoothbuf[5000 + x]) > SMALLVAL )
|
|
printf("x.%d error %.20f != %.20f [%.20f]\n",x,smoothbuf[5000 - x],smoothbuf[5000 + x],smoothbuf[5000 - x] - smoothbuf[5000 + x]);
|
|
_coeffs[x-1] = (smoothbuf[5000 - x] + smoothbuf[5000 + x]) / 2.;
|
|
}
|
|
sum = 0.;
|
|
for (x=0; x<smoothwidth; x++)
|
|
sum += _coeffs[x];
|
|
if ( sum != 0. )
|
|
{
|
|
for (x=0; x<smoothwidth; x++)
|
|
{
|
|
val = ((SATOSHIDEN * 1000. * _coeffs[x] + sum*.4825) / sum);
|
|
printf("%lld, ",(long long)val);
|
|
isum += val;
|
|
//printf("%.0f, ",SATOSHIDEN*1000*_coeffs[x]/sum);
|
|
if ( (x%9) == 8 )
|
|
printf("// x.%d\n",x);
|
|
}
|
|
printf("// isum %lld\n",(long long)isum);
|
|
}
|
|
}
|
|
printf("\n}; // %llu\n",(long long)isum);
|
|
//printf("_Constants size %d\n",(int)__constant_size);
|
|
}
|
|
|
|
void peggy_geninds()
|
|
{
|
|
int32_t inds[PEGGY_NUMCOEFFS],tmp,i,n = PEGGY_NUMCOEFFS;
|
|
for (i=0; i<n; i++)
|
|
inds[i] = i;
|
|
printf("int32_t Peggy_inds[%d] = {",PEGGY_NUMCOEFFS);
|
|
while ( n > 0 )
|
|
{
|
|
i = ((rand() >> 8) % n);
|
|
//printf("(n.%d [%d] i.%d [%d]) ",n,inds[n],i,inds[i]);
|
|
n--;
|
|
tmp = inds[n];
|
|
inds[n] = inds[i];
|
|
inds[i] = tmp;
|
|
}
|
|
for (i=0; i<PEGGY_NUMCOEFFS; i++)
|
|
printf("%d, ",inds[i]);
|
|
printf("};\n");
|
|
}
|
|
|
|
int32_t peggy_init_contexts(struct txinds777_info *opreturns,uint32_t RTblocknum,uint32_t RTblocktimestamp,char *path,void *globals[OPRETURNS_CONTEXTS],int32_t lookbacks[OPRETURNS_CONTEXTS],int32_t maxcontexts)
|
|
{
|
|
double startmilli; char buf[512]; struct price_resolution spread; struct peggy_info *PEGS=0,*PEGS2=0;
|
|
if ( maxcontexts != 2 )
|
|
{
|
|
printf("peggy needs 2 contexts\n");
|
|
exit(-1);
|
|
}
|
|
//calc_smooth_code(539,13);
|
|
if ( sizeof(Peggy_inds)/sizeof(*Peggy_inds) != PEGGY_NUMCOEFFS )
|
|
{
|
|
peggy_geninds();
|
|
printf("need to update Peggy_inds with above\n");
|
|
exit(-1);
|
|
}
|
|
peggy_dailyrates();
|
|
spread.Pval = PERCENTAGE(1);
|
|
if ( (PEGS= peggy_lchain(opreturns,"opreturns")) == 0 )
|
|
PEGS = peggy_init(path,PEGGY_MAXLOCKDAYS,"BTCD",SATOSHIDEN/100,100,10,spread,PEGGY_RATE_777,40,10,2,5,2,0,0);
|
|
globals[0] = PEGS;
|
|
sprintf(buf,"%s_PERM",path);
|
|
globals[1] = PEGS2 = peggy_init(buf,PEGGY_MAXLOCKDAYS,"BTCD",SATOSHIDEN/100,1,1,spread,PEGGY_RATE_777,40,10,2,5,2,PEGS->genesistime,PEGS->BTCD_price0);
|
|
startmilli = milliseconds();
|
|
peggy_clone(buf,PEGS2,PEGS);
|
|
printf("cloned %d in %.3f millis per opreturn\n",PEGS->numopreturns,(milliseconds() - startmilli)/PEGS->numopreturns); sleep(3);
|
|
return(2);
|
|
}
|
|
|
|
#endif
|
|
#endif
|
|
#include <stdint.h>
|
|
extern int32_t Debuglevel;
|
|
|
|
#endif
|
|
|