Merge pull request #39 from jl777/dPoW

DPoW
This commit is contained in:
jl777
2016-10-25 11:29:20 -03:00
committed by GitHub
18 changed files with 6514 additions and 739 deletions

View File

@@ -16,532 +16,28 @@
#ifndef H_KOMODO_H
#define H_KOMODO_H
// Todo: handle reorg: clear all entries above reorged height
#include <stdint.h>
#include <stdio.h>
#include <pthread.h>
#include <ctype.h>
#include "uthash.h"
#include "komodo_interest.h"
#define KOMODO_TESTNET_EXPIRATION 60000
#define KOMODO_ELECTION_GAP 1000
#define KOMODO_PUBKEYS_HEIGHT(height) ((int32_t)(((((height)+KOMODO_ELECTION_GAP*.5)/KOMODO_ELECTION_GAP) + 1) * KOMODO_ELECTION_GAP))
int32_t NUM_PRICES,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,NOTARIZED_HEIGHT,Num_nutxos,KOMODO_NUMNOTARIES = 64;
std::string NOTARY_PUBKEY;
uint8_t NOTARY_PUBKEY33[33];
uint256 NOTARIZED_HASH,NOTARIZED_BTCTXID;
pthread_mutex_t komodo_mutex;
uint32_t *PVALS;
struct nutxo_entry { UT_hash_handle hh; uint256 txhash; uint64_t voutmask; int32_t notaryid,height; } *NUTXOS;
struct knotary_entry { UT_hash_handle hh; uint8_t pubkey[33],notaryid; };
struct knotaries_entry { int32_t height,numnotaries; struct knotary_entry *Notaries; } Pubkeys[10000];
struct notarized_checkpoint { uint256 notarized_hash,notarized_btctxid; int32_t nHeight,notarized_height; } *NPOINTS; int32_t NUM_NPOINTS;
#include "komodo_utils.h"
int32_t komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals);
// add opreturn funcid
// pricefeeds
void komodo_init();
int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp);
#define CRYPTO777_PUBSECPSTR "020e46e79a2a8d12b9b5d12c7a91adb4e454edfae43c0a0cb805427d2ac7613fd9"
int32_t NOTARIZED_HEIGHT,Num_nutxos;
uint256 NOTARIZED_HASH,NOTARIZED_DESTTXID;
pthread_mutex_t komodo_mutex;
#define MAX_CURRENCIES 32
char CURRENCIES[][8] = { "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",
"KMD" };
uint32_t MINDENOMS[] = { 1000, 1000, 100000, 1000, 1000, 1000, 1000, 1000, // major currencies
10000, 100000, 10000, 1000, 100000, 10000, 1000, 10000, 1000, 10000, 10000, 10000, 10000, 100000, 1000, 1000000, 1000, 10000, 1000, 1000, 10000, 1000, 10000000, 10000, // end of currencies
};
/*uint32_t PAX_val32(double val)
{
uint32_t val32 = 0; struct price_resolution price;
if ( (price.Pval= val*1000000000) != 0 )
{
if ( price.Pval > 0xffffffff )
printf("Pval overflow error %lld\n",(long long)price.Pval);
else val32 = (uint32_t)price.Pval;
}
return(val32);
}*/
double PAX_val(uint32_t pval,int32_t baseid)
{
//printf("PAX_val baseid.%d pval.%u\n",baseid,pval);
if ( baseid >= 0 && baseid < MAX_CURRENCIES )
return(((double)pval / 1000000000.) / MINDENOMS[baseid]);
return(0.);
}
const char *Notaries[][2] =
{
{ "jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" },
{ "jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" },
{ "pondsea_SH", "02209073bc0943451498de57f802650311b1f12aa6deffcd893da198a544c04f36" },
{ "crackers_EU", "0340c66cf2c41c41efb420af57867baa765e8468c12aa996bfd816e1e07e410728" },
{ "pondsea_EU", "0225aa6f6f19e543180b31153d9e6d55d41bc7ec2ba191fd29f19a2f973544e29d" },
{ "locomb_EU", "025c6d26649b9d397e63323d96db42a9d3caad82e1d6076970efe5056c00c0779b" },
{ "fullmoon_AE", "0204a908350b8142698fdb6fabefc97fe0e04f537adc7522ba7a1e8f3bec003d4a" },
{ "movecrypto_EU", "021ab53bc6cf2c46b8a5456759f9d608966eff87384c2b52c0ac4cc8dd51e9cc42" },
{ "badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" },
{ "crackers_NA", "029e1c01131974f4cd3f564cc0c00eb87a0f9721043fbc1ca60f9bd0a1f73f64a1" },
{ "proto_EU", "03681ffdf17c8f4f0008cefb7fa0779c5e888339cdf932f0974483787a4d6747c1" },
{ "jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" },
{ "farl4web_EU", "035caa40684ace968677dca3f09098aa02b70e533da32390a7654c626e0cf908e1" },
{ "nxtswe_EU", "032fb104e5eaa704a38a52c126af8f67e870d70f82977e5b2f093d5c1c21ae5899" },
{ "traderbill_EU", "03196e8de3e2e5d872f31d79d6a859c8704a2198baf0af9c7b21e29656a7eb455f" },
{ "vanbreuk_EU", "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" },
{ "titomane_EU", "03517fcac101fed480ae4f2caf775560065957930d8c1facc83e30077e45bdd199" },
{ "supernet_AE", "029d93ef78197dc93892d2a30e5a54865f41e0ca3ab7eb8e3dcbc59c8756b6e355" },
{ "supernet_EU", "02061c6278b91fd4ac5cab4401100ffa3b2d5a277e8f71db23401cc071b3665546" },
{ "supernet_NA", "033c073366152b6b01535e15dd966a3a8039169584d06e27d92a69889b720d44e1" },
{ "yassin_EU", "033fb7231bb66484081952890d9a03f91164fb27d392d9152ec41336b71b15fbd0" },
{ "durerus_EU", "02bcbd287670bdca2c31e5d50130adb5dea1b53198f18abeec7211825f47485d57" },
{ "badass_SH", "026b49dd3923b78a592c1b475f208e23698d3f085c4c3b4906a59faf659fd9530b" },
{ "badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" },
{ "pondsea_NA", "031bcfdbb62268e2ff8dfffeb9ddff7fe95fca46778c77eebff9c3829dfa1bb411" },
{ "rnr_EU", "0287aa4b73988ba26cf6565d815786caf0d2c4af704d7883d163ee89cd9977edec" },
{ "crackers_SH", "02313d72f9a16055737e14cfc528dcd5d0ef094cfce23d0348fe974b6b1a32e5f0" },
{ "grewal_SH", "03212a73f5d38a675ee3cdc6e82542a96c38c3d1c79d25a1ed2e42fcf6a8be4e68" },
{ "polycryptoblock_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" },
{ "titomane_NA", "0387046d9745414fb58a0fa3599078af5073e10347e4657ef7259a99cb4f10ad47" },
{ "titomane_AE", "03cda6ca5c2d02db201488a54a548dbfc10533bdc275d5ea11928e8d6ab33c2185" },
{ "kolo_EU", "03f5c08dadffa0ffcafb8dd7ffc38c22887bd02702a6c9ac3440deddcf2837692b" },
{ "artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" },
{ "eclips_EU", "0339369c1f5a2028d44be7be6f8ec3b907fdec814f87d2dead97cab4edb71a42e9" },
{ "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" },
};
static const uint32_t crc32_tab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
uint32_t calc_crc32(uint32_t crc,const void *buf,size_t size)
{
const uint8_t *p;
p = (const uint8_t *)buf;
crc = crc ^ ~0U;
while (size--)
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
return crc ^ ~0U;
}
int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp)
{
int32_t i; uint64_t x;
if ( rwflag == 0 )
{
x = 0;
for (i=len-1; i>=0; i--)
{
x <<= 8;
x |= serialized[i];
}
switch ( len )
{
case 1: *(uint8_t *)endianedp = (uint8_t)x; break;
case 2: *(uint16_t *)endianedp = (uint16_t)x; break;
case 4: *(uint32_t *)endianedp = (uint32_t)x; break;
case 8: *(uint64_t *)endianedp = (uint64_t)x; break;
}
}
else
{
x = 0;
switch ( len )
{
case 1: x = *(uint8_t *)endianedp; break;
case 2: x = *(uint16_t *)endianedp; break;
case 4: x = *(uint32_t *)endianedp; break;
case 8: x = *(uint64_t *)endianedp; break;
}
for (i=0; i<len; i++,x >>= 8)
serialized[i] = (uint8_t)(x & 0xff);
}
return(len);
}
int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp)
{
int32_t i;
if ( rwflag == 0 )
{
for (i=0; i<len; i++)
endianedp[i] = serialized[i];
}
else
{
for (i=0; i<len; i++)
serialized[i] = endianedp[i];
}
return(len);
}
int32_t dpow_readprices(uint8_t *data,uint32_t *timestampp,double *KMDBTCp,double *BTCUSDp,double *CNYUSDp,uint32_t *pvals)
{
uint32_t kmdbtc,btcusd,cnyusd; int32_t i,n,len = 0;
len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)timestampp);
len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&n);
len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&kmdbtc); // /= 1000
len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&btcusd); // *= 1000
len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&cnyusd);
*KMDBTCp = ((double)kmdbtc / (1000000000. * 1000.));
*BTCUSDp = ((double)btcusd / (1000000000. / 1000.));
*CNYUSDp = ((double)cnyusd / 1000000000.);
for (i=0; i<n-3; i++)
{
len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&pvals[i]);
//printf("%u ",pvals[i]);
}
pvals[i++] = kmdbtc;
pvals[i++] = btcusd;
pvals[i++] = cnyusd;
//printf("OP_RETURN prices\n");
return(n);
}
int32_t _unhex(char c)
{
if ( c >= '0' && c <= '9' )
return(c - '0');
else if ( c >= 'a' && c <= 'f' )
return(c - 'a' + 10);
else if ( c >= 'A' && c <= 'F' )
return(c - 'A' + 10);
return(-1);
}
int32_t is_hexstr(char *str,int32_t n)
{
int32_t i;
if ( str == 0 || str[0] == 0 )
return(0);
for (i=0; str[i]!=0; i++)
{
if ( n > 0 && i >= n )
break;
if ( _unhex(str[i]) < 0 )
break;
}
if ( n == 0 )
return(i);
return(i == n);
}
int32_t unhex(char c)
{
int32_t hex;
if ( (hex= _unhex(c)) < 0 )
{
//printf("unhex: illegal hexchar.(%c)\n",c);
}
return(hex);
}
unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])); }
int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex)
{
int32_t adjust,i = 0;
//printf("decode.(%s)\n",hex);
if ( is_hexstr(hex,n) == 0 )
{
memset(bytes,0,n);
return(n);
}
if ( n == 0 || (hex[n*2+1] == 0 && hex[n*2] != 0) )
{
if ( n > 0 )
{
bytes[0] = unhex(hex[0]);
printf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex));
}
bytes++;
hex++;
adjust = 1;
} else adjust = 0;
if ( n > 0 )
{
for (i=0; i<n; i++)
bytes[i] = _decode_hex(&hex[i*2]);
}
//bytes[i] = 0;
return(n + adjust);
}
int32_t komodo_threshold(int32_t height,uint64_t signedmask)
{
int32_t numnotaries,i,wt = 0;
numnotaries = Pubkeys[height / KOMODO_ELECTION_GAP].numnotaries;
for (i=0; i<numnotaries; i++)
if ( ((1LL << i) & signedmask) != 0 )
wt++;
if ( wt > (numnotaries >> 1) || (wt > 7 && (signedmask & 3) != 0) )
return(1); // N/2+1 || N/3 + devsig
else return(0);
}
uint32_t komodo_txtime(uint256 hash)
{
CTransaction tx;
uint256 hashBlock;
if (!GetTransaction(hash, tx, hashBlock, true))
{
//printf("null GetTransaction\n");
return(tx.nLockTime);
}
return(0);
}
void komodo_nutxoadd(int32_t addflag,int32_t height,int32_t notaryid,uint256 txhash,uint64_t voutmask,int32_t numvouts)
{
struct nutxo_entry *np;
if ( numvouts > 1 && notaryid < 64 ) // change to ADD_HASH() and file based
{
pthread_mutex_lock(&komodo_mutex);
np = (struct nutxo_entry *)calloc(1,sizeof(*np));
np->height = height;
np->txhash = txhash;
np->voutmask = voutmask;
np->notaryid = notaryid;
HASH_ADD_KEYPTR(hh,NUTXOS,&np->txhash,sizeof(np->txhash),np);
printf("Add NUTXO[%d] <- %s notaryid.%d t%u %s %llx\n",Num_nutxos,Notaries[notaryid][0],notaryid,komodo_txtime(txhash),txhash.ToString().c_str(),(long long)voutmask);
if ( addflag != 0 )
komodo_stateupdate(height,0,0,notaryid,txhash,voutmask,numvouts,0,0);
Num_nutxos++;
pthread_mutex_unlock(&komodo_mutex);
}
}
int32_t komodo_nutxofind(int32_t height,uint256 txhash,int32_t vout) // change to HASH_FIND()
{
struct nutxo_entry *np;
pthread_mutex_lock(&komodo_mutex);
HASH_FIND(hh,NUTXOS,&txhash,sizeof(txhash),np);
pthread_mutex_unlock(&komodo_mutex);
if ( np != 0 && ((1LL << vout) & np->voutmask) != 0 )
return(np->notaryid);
return(-1);
}
void komodo_notarysinit(int32_t height,uint8_t pubkeys[64][33],int32_t num)
{
int32_t k,i,htind; struct knotary_entry *kp; struct knotaries_entry N;
memset(&N,0,sizeof(N));
pthread_mutex_lock(&komodo_mutex);
for (k=0; k<num; k++)
{
kp = (struct knotary_entry *)calloc(1,sizeof(*kp));
memcpy(kp->pubkey,pubkeys[k],33);
kp->notaryid = k;
HASH_ADD_KEYPTR(hh,N.Notaries,kp->pubkey,33,kp);
for (i=0; i<33; i++)
printf("%02x",pubkeys[k][i]);
printf(" notarypubs.[%d]\n",k);
}
N.numnotaries = num;
htind = KOMODO_PUBKEYS_HEIGHT(height) / KOMODO_ELECTION_GAP;
if ( htind == 1 )
htind = 0;
for (i=htind; i<sizeof(Pubkeys)/sizeof(*Pubkeys); i++)
{
Pubkeys[i] = N;
Pubkeys[i].height = i * KOMODO_ELECTION_GAP;
}
pthread_mutex_unlock(&komodo_mutex);
}
int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33)
{
// -1 if not notary, 0 if notary, 1 if special notary
struct knotary_entry *kp; int32_t numnotaries,modval = -1;
*notaryidp = -1;
pthread_mutex_lock(&komodo_mutex);
HASH_FIND(hh,Pubkeys[height/KOMODO_ELECTION_GAP].Notaries,pubkey33,33,kp);
pthread_mutex_unlock(&komodo_mutex);
if ( kp != 0 )
{
if ( (numnotaries= Pubkeys[height/KOMODO_ELECTION_GAP].numnotaries) > 0 )
{
*notaryidp = kp->notaryid;
modval = ((height % numnotaries) == kp->notaryid);
//printf("found notary.%d ht.%d modval.%d\n",kp->notaryid,height,modval);
} else printf("unexpected zero notaries at height.%d\n",height);
}
//int32_t i; for (i=0; i<33; i++)
// printf("%02x",pubkey33[i]);
//printf(" ht.%d notary.%d special.%d\n",height,*notaryidp,modval);
return(modval);
}
void komodo_notarized_update(int32_t nHeight,int32_t notarized_height,uint256 notarized_hash,uint256 notarized_btctxid)
{
struct notarized_checkpoint *np;
if ( notarized_height > nHeight )
{
printf("komodo_notarized_update REJECT notarized_height %d > %d nHeight\n",notarized_height,nHeight);
return;
}
NPOINTS = (struct notarized_checkpoint *)realloc(NPOINTS,(NUM_NPOINTS+1) * sizeof(*NPOINTS));
np = &NPOINTS[NUM_NPOINTS++];
memset(np,0,sizeof(*np));
np->nHeight = nHeight;
np->notarized_height = notarized_height;
np->notarized_hash = notarized_hash;
np->notarized_btctxid = notarized_btctxid;
}
int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_btctxidp)
{
struct notarized_checkpoint *np = 0; int32_t i;
if ( NUM_NPOINTS > 0 )
{
for (i=0; i<NUM_NPOINTS; i++)
{
if ( NPOINTS[i].nHeight >= nHeight )
break;
np = &NPOINTS[i];
}
}
if ( np != 0 )
{
*notarized_hashp = np->notarized_hash;
*notarized_btctxidp = np->notarized_btctxid;
return(np->notarized_height);
}
memset(notarized_hashp,0,sizeof(*notarized_hashp));
return(0);
}
void komodo_pvals(int32_t height,uint32_t *pvals,uint8_t numpvals)
{
int32_t i,nonz; double KMDBTC,BTCUSD,CNYUSD; uint32_t kmdbtc,btcusd,cnyusd;
if ( numpvals >= 35 )
{
for (nonz=i=0; i<32; i++)
{
if ( pvals[i] != 0 )
nonz++;
printf("%u ",pvals[i]);
}
if ( nonz == 32 )
{
kmdbtc = pvals[i++];
btcusd = pvals[i++];
cnyusd = pvals[i++];
KMDBTC = ((double)kmdbtc / (1000000000. * 1000.));
BTCUSD = ((double)btcusd / (1000000000. / 1000.));
CNYUSD = ((double)cnyusd / 1000000000.);
PVALS = (uint32_t *)realloc(PVALS,(NUM_PRICES+1) * sizeof(*PVALS) * 36);
PVALS[36 * NUM_PRICES] = height;
memcpy(&PVALS[36 * NUM_PRICES + 1],pvals,sizeof(*pvals) * 35);
NUM_PRICES++;
printf("OP_RETURN.%d KMD %.8f BTC %.6f CNY %.6f NUM_PRICES.%d\n",height,KMDBTC,BTCUSD,CNYUSD,NUM_PRICES);
}
}
}
int32_t komodo_baseid(char *origbase)
{
int32_t i; char base[64];
for (i=0; origbase[i]!=0&&i<sizeof(base); i++)
base[i] = toupper((int32_t)(origbase[i] & 0xff));
base[i] = 0;
for (i=0; i<=MAX_CURRENCIES; i++)
if ( strcmp(CURRENCIES[i],base) == 0 )
return(i);
printf("illegal base.(%s) %s\n",origbase,base);
return(-1);
}
#define USD 0
uint64_t komodo_paxprice(int32_t height,char *base,char *rel,uint64_t volume)
{
int32_t baseid=-1,relid=-1,i,ht; uint32_t kmdbtc,btcusd,pvalb,pvalr,*ptr; double usdval,baseval,relval,KMDBTC,BTCUSD,KMDUSD;
if ( (baseid= komodo_baseid(base)) >= 0 && (relid= komodo_baseid(rel)) >= 0 )
{
for (i=NUM_PRICES-1; i>=0; i--)
{
ptr = &PVALS[36 * i];
if ( *ptr < height )
{
if ( (pvalb= ptr[1 + baseid]) != 0 )
{
baseval = PAX_val(pvalb,baseid);
if ( relid == MAX_CURRENCIES )
{
kmdbtc = ptr[1 + MAX_CURRENCIES];
btcusd = ptr[1 + MAX_CURRENCIES + 1];
if ( ptr[1 + USD] != 0 && kmdbtc != 0 && btcusd != 0 )
{
usdval = PAX_val(ptr[1 + USD],USD);
KMDBTC = ((double)kmdbtc / (1000000000. * 1000.));
BTCUSD = ((double)btcusd / (1000000000. / 1000.));
KMDUSD = (KMDBTC * BTCUSD);
printf("base -> USD %f, BTC %f KMDUSD %f\n",baseval/usdval,BTCUSD,KMDUSD);
return(volume * (baseval / usdval) / KMDUSD);
}
}
else if ( (pvalr= ptr[1 + relid]) != 0 )
{
relval = PAX_val(pvalr,relid);
printf("ht.%d [%d] base.(%u %f) rel.(%u %f) -> %llu\n",height,*ptr,pvalb,baseval,pvalr,relval,(long long)(COIN * (baseval / relval)));
return(volume * (baseval / relval));
}
}
return(0);
}
}
} else printf("paxprice invalid base.%s %d, rel.%s %d\n",base,baseid,rel,relid);
return(0);
}
#include "komodo_bitcoind.h"
#include "komodo_interest.h"
#ifdef KOMODO_PAX
#include "komodo_pax.h"
#endif
#include "komodo_notary.h"
int32_t komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals)
{
@@ -580,10 +76,10 @@ int32_t komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numno
errs++;
if ( fread(&NOTARIZED_HASH,1,sizeof(NOTARIZED_HASH),fp) != sizeof(NOTARIZED_HASH) )
errs++;
if ( fread(&NOTARIZED_BTCTXID,1,sizeof(NOTARIZED_BTCTXID),fp) != sizeof(NOTARIZED_BTCTXID) )
if ( fread(&NOTARIZED_DESTTXID,1,sizeof(NOTARIZED_DESTTXID),fp) != sizeof(NOTARIZED_DESTTXID) )
errs++;
printf("load NOTARIZED %d %s\n",NOTARIZED_HEIGHT,NOTARIZED_HASH.ToString().c_str());
komodo_notarized_update(ht,NOTARIZED_HEIGHT,NOTARIZED_HASH,NOTARIZED_BTCTXID);
komodo_notarized_update(ht,NOTARIZED_HEIGHT,NOTARIZED_HASH,NOTARIZED_DESTTXID);
}
else if ( func == 'U' )
{
@@ -595,12 +91,13 @@ int32_t komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numno
errs++;
if ( fread(&hash,1,sizeof(hash),fp) != sizeof(hash) )
errs++;
komodo_nutxoadd(0,ht,nid,hash,mask,n);
komodo_nutxoadd(ht,nid,hash,mask,n);
}
else if ( func == 'D' )
{
//printf("D[%d]\n",ht);
}
#ifdef KOMODO_PAX
else if ( func == 'V' )
{
int32_t numpvals; uint32_t pvals[128];
@@ -608,15 +105,16 @@ int32_t komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numno
if ( numpvals*sizeof(uint32_t) <= sizeof(pvals) && fread(pvals,sizeof(uint32_t),numpvals,fp) == numpvals )
{
komodo_pvals(ht,pvals,numpvals);
printf("load pvals ht.%d numpvals.%d\n",ht,numpvals);
//printf("load pvals ht.%d numpvals.%d\n",ht,numpvals);
} else printf("error loading pvals[%d]\n",numpvals);
}
#endif
else printf("illegal func.(%d %c)\n",func,func);
}
} else fp = fopen(fname,"wb+");
printf("fname.(%s) fpos.%ld\n",fname,ftell(fp));
}
if ( fp != 0 )
if ( fp != 0 ) // write out funcid, height, other fields, call side effect function
{
if ( height < 0 )
{
@@ -635,6 +133,7 @@ int32_t komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numno
fputc(numnotaries,fp);
if ( fwrite(notarypubs,33,numnotaries,fp) != numnotaries )
errs++;
komodo_notarysinit(height,notarypubs,numnotaries);
}
else if ( voutmask != 0 && numvouts > 0 )
{
@@ -648,7 +147,9 @@ int32_t komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numno
errs++;
if ( fwrite(&txhash,1,sizeof(txhash),fp) != sizeof(txhash) )
errs++;
komodo_nutxoadd(height,notaryid,txhash,voutmask,numvouts);
}
#ifdef KOMODO_PAX
else if ( pvals != 0 && numpvals > 0 )
{
fputc('V',fp);
@@ -658,8 +159,9 @@ int32_t komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numno
if ( fwrite(pvals,sizeof(uint32_t),numpvals,fp) != numpvals )
errs++;
komodo_pvals(height,pvals,numpvals);
printf("save pvals height.%d numpvals.%d\n",height,numpvals);
//printf("save pvals height.%d numpvals.%d\n",height,numpvals);
}
#endif
else if ( height != 0 )
{
//printf("func N ht.%d errs.%d\n",NOTARIZED_HEIGHT,errs);
@@ -670,38 +172,17 @@ int32_t komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numno
errs++;
if ( fwrite(&NOTARIZED_HASH,1,sizeof(NOTARIZED_HASH),fp) != sizeof(NOTARIZED_HASH) )
errs++;
if ( fwrite(&NOTARIZED_BTCTXID,1,sizeof(NOTARIZED_BTCTXID),fp) != sizeof(NOTARIZED_BTCTXID) )
if ( fwrite(&NOTARIZED_DESTTXID,1,sizeof(NOTARIZED_DESTTXID),fp) != sizeof(NOTARIZED_DESTTXID) )
errs++;
komodo_notarized_update(height,NOTARIZED_HEIGHT,NOTARIZED_HASH,NOTARIZED_BTCTXID);
komodo_notarized_update(height,NOTARIZED_HEIGHT,NOTARIZED_HASH,NOTARIZED_DESTTXID);
}
fflush(fp);
}
}
void komodo_init()
{
static int didinit; uint256 zero; int32_t k; uint8_t pubkeys[64][33];
if ( didinit == 0 )
{
didinit = 1;
pthread_mutex_init(&komodo_mutex,NULL);
decode_hex(NOTARY_PUBKEY33,33,(char *)NOTARY_PUBKEY.c_str());
KOMODO_NUMNOTARIES = (int32_t)(sizeof(Notaries)/sizeof(*Notaries));
for (k=0; k<KOMODO_NUMNOTARIES; k++)
{
if ( Notaries[k][0] == 0 || Notaries[k][1] == 0 || Notaries[k][0][0] == 0 || Notaries[k][1][0] == 0 )
break;
decode_hex(pubkeys[k],33,(char *)Notaries[k][1]);
}
komodo_notarysinit(0,pubkeys,KOMODO_NUMNOTARIES);
memset(&zero,0,sizeof(zero));
komodo_stateupdate(0,0,0,0,zero,0,0,0,0);
}
}
int32_t komodo_voutupdate(int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i,int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp)
{
static uint256 zero; int32_t k,opretlen,nid,len = 0; uint256 kmdtxid,btctxid; uint8_t crypto777[33];
static uint256 zero; int32_t k,opretlen,nid,len = 0; uint256 kmdtxid,desttxid; uint8_t crypto777[33];
if ( scriptlen == 35 && scriptbuf[0] == 33 && scriptbuf[34] == 0xac )
{
decode_hex(crypto777,33,(char *)CRYPTO777_PUBSECPSTR);
@@ -745,30 +226,32 @@ int32_t komodo_voutupdate(int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,
opretlen = scriptbuf[len++];
opretlen = (opretlen << 8) + scriptbuf[len++];
}
if ( opretlen >= 32*2+4 && strcmp("KMD",(char *)&scriptbuf[len+32*2+4]) == 0 )
if ( opretlen >= 32*2+4 && strcmp(KOMODO_SOURCE,(char *)&scriptbuf[len+32*2+4]) == 0 )
{
len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&kmdtxid);
len += iguana_rwnum(0,&scriptbuf[len],4,(uint8_t *)notarizedheightp);
len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&btctxid);
len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&desttxid);
//for (k=0; k<scriptlen; k++)
// printf("%02x",scriptbuf[k]);
//printf(" <- script ht.%d i.%d j.%d\n",height,i,j);
if ( *notarizedheightp > NOTARIZED_HEIGHT && *notarizedheightp < height )
{
printf("ht.%d NOTARIZED.%d KMD.%s BTCTXID.%s (%s)\n",height,*notarizedheightp,kmdtxid.ToString().c_str(),btctxid.ToString().c_str(),(char *)&scriptbuf[len]);
printf("ht.%d NOTARIZED.%d KMD.%s BTCTXID.%s (%s)\n",height,*notarizedheightp,kmdtxid.ToString().c_str(),desttxid.ToString().c_str(),(char *)&scriptbuf[len]);
NOTARIZED_HEIGHT = *notarizedheightp;
NOTARIZED_HASH = kmdtxid;
NOTARIZED_BTCTXID = btctxid;
NOTARIZED_DESTTXID = desttxid;
komodo_stateupdate(height,0,0,0,zero,0,0,0,0);
} else printf("reject ht.%d NOTARIZED.%d KMD.%s BTCTXID.%s (%s)\n",height,*notarizedheightp,kmdtxid.ToString().c_str(),btctxid.ToString().c_str(),(char *)&scriptbuf[len]);
} else printf("reject ht.%d NOTARIZED.%d %s.%s DESTTXID.%s (%s)\n",height,*notarizedheightp,KOMODO_SOURCE,kmdtxid.ToString().c_str(),desttxid.ToString().c_str(),(char *)&scriptbuf[len]);
}
#ifdef KOMODO_PAX
else if ( i == 0 && scriptbuf[len] == 'P' )
{
double KMDBTC,BTCUSD,CNYUSD; uint32_t numpvals,timestamp,pvals[128];
numpvals = dpow_readprices(&scriptbuf[++len],&timestamp,&KMDBTC,&BTCUSD,&CNYUSD,pvals);
komodo_stateupdate(height,0,0,0,zero,0,0,pvals,numpvals);
printf("vout OP_RETURN.%d prices numpvals.%d opretlen.%d\n",height,numpvals,opretlen);
//printf("vout OP_RETURN.%d prices numpvals.%d opretlen.%d\n",height,numpvals,opretlen);
}
#endif
}
return(notaryid);
}
@@ -805,8 +288,11 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
}
}
}
if ( notaryid >= 0 && notaryid < 64 && voutmask != 0 )
komodo_nutxoadd(1,height,notaryid,txhash,voutmask,numvouts);
if ( i != 0 && notaryid >= 0 && notaryid < 64 && voutmask != 0 )
{
komodo_stateupdate(height,0,0,notaryid,txhash,voutmask,numvouts,0,0);
//komodo_nutxoadd(height,notaryid,txhash,voutmask,numvouts);
}
signedmask = 0;
numvins = block.vtx[i].vin.size();
for (j=0; j<numvins; j++)
@@ -819,7 +305,7 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
if ( signedmask != 0 && (notarizedheight != 0 || specialtx != 0) )
{
printf("NOTARY SIGNED.%llx numvins.%d ht.%d txi.%d notaryht.%d specialtx.%d\n",(long long)signedmask,numvins,height,i,notarizedheight,specialtx);
if ( specialtx != 0 && numvouts > 2 && komodo_threshold(height,signedmask) > 0 )
if ( specialtx != 0 && numvouts > 2 && komodo_ratify_threshold(height,signedmask) > 0 )
{
numvalid = 0;
memset(pubkeys,0,sizeof(pubkeys));
@@ -850,132 +336,5 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
} else printf("komodo_connectblock: unexpected null pindex\n");
}
void komodo_disconnect(CBlockIndex *pindex,CBlock& block)
{
komodo_init();
//uint256 zero;
//printf("disconnect ht.%d\n",pindex->nHeight);
//memset(&zero,0,sizeof(zero));
//komodo_stateupdate(-pindex->nHeight,0,0,0,zero,0,0,0,0);
}
int32_t komodo_block2height(CBlock *block)
{
int32_t i,n,height = 0; uint8_t *ptr = (uint8_t *)block->vtx[0].vin[0].scriptSig.data();
komodo_init();
if ( block->vtx[0].vin[0].scriptSig.size() > 5 )
{
//for (i=0; i<6; i++)
// printf("%02x",ptr[i]);
n = ptr[0];
for (i=0; i<n; i++)
{
//03bb81000101(bb 187) (81 48001) (00 12288256) <- coinbase.6 ht.12288256
height += ((uint32_t)ptr[i+1] << (i*8));
//printf("(%02x %x %d) ",ptr[i+1],((uint32_t)ptr[i+1] << (i*8)),height);
}
//printf(" <- coinbase.%d ht.%d\n",(int32_t)block->vtx[0].vin[0].scriptSig.size(),height);
}
return(height);
}
void komodo_block2pubkey33(uint8_t *pubkey33,CBlock& block)
{
uint8_t *ptr = (uint8_t *)block.vtx[0].vout[0].scriptPubKey.data();
komodo_init();
memcpy(pubkey33,ptr+1,33);
}
void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height)
{
CBlock block;
komodo_init();
memset(pubkey33,0,33);
if ( pindex != 0 )
{
if ( ReadBlockFromDisk(block,(const CBlockIndex *)pindex) != 0 )
{
komodo_block2pubkey33(pubkey33,block);
}
}
else
{
// height -> pubkey33
//printf("extending chaintip komodo_index2pubkey33 height.%d need to get pubkey33\n",height);
}
}
int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen)
{
int32_t offset = 0;
script[offset++] = 0x6a;
opretlen++;
if ( opretlen >= 0x4c )
{
if ( opretlen > 0xff )
{
script[offset++] = 0x4d;
script[offset++] = opretlen & 0xff;
script[offset++] = (opretlen >> 8) & 0xff;
}
else
{
script[offset++] = 0x4c;
script[offset++] = opretlen;
}
} else script[offset++] = opretlen;
script[offset++] = type;
memcpy(&script[offset],opret,opretlen);
return(opretlen + offset);
}
int32_t komodo_opreturn(uint8_t *opret,int32_t maxsize)
{
static uint32_t lastcrc;
FILE *fp; char fname[512]; uint32_t crc32,check,timestamp; int32_t i,n,retval,fsize,len=0; uint8_t data[8192];
#ifdef WIN32
sprintf(fname,"%s\\%s",GetDataDir(false).string().c_str(),(char *)"komodofeed");
#else
sprintf(fname,"%s/%s",GetDataDir(false).string().c_str(),(char *)"komodofeed");
#endif
if ( (fp= fopen(fname,"rb")) != 0 )
{
fseek(fp,0,SEEK_END);
fsize = (int32_t)ftell(fp);
rewind(fp);
if ( fsize <= maxsize-4 && fsize <= sizeof(data) && fsize > sizeof(crc32) )
{
if ( (retval= (int32_t)fread(data,1,fsize,fp)) == fsize )
{
len = iguana_rwnum(0,data,sizeof(crc32),(void *)&crc32);
check = calc_crc32(0,data+sizeof(crc32),(int32_t)(fsize-sizeof(crc32)));
if ( check == crc32 )
{
double KMDBTC,BTCUSD,CNYUSD; uint32_t pvals[128];
dpow_readprices(&data[len],&timestamp,&KMDBTC,&BTCUSD,&CNYUSD,pvals);
if ( 0 && lastcrc != crc32 )
{
for (i=0; i<32; i++)
printf("%u ",pvals[i]);
printf("t%u n.%d KMD %f BTC %f CNY %f (%f)\n",timestamp,n,KMDBTC,BTCUSD,CNYUSD,CNYUSD!=0?1./CNYUSD:0);
}
if ( timestamp > time(NULL)-600 )
{
n = komodo_opreturnscript(opret,'P',data+sizeof(crc32),(int32_t)(fsize-sizeof(crc32)));
if ( 0 && lastcrc != crc32 )
{
for (i=0; i<n; i++)
printf("%02x",opret[i]);
printf(" coinbase opret[%d] crc32.%u:%u\n",n,crc32,check);
}
} else printf("t%u too old for %u\n",timestamp,(uint32_t)time(NULL));
lastcrc = crc32;
} else printf("crc32 %u mismatch %u\n",crc32,check);
} else printf("fread.%d error != fsize.%d\n",retval,fsize);
} else printf("fsize.%d > maxsize.%d or data[%d]\n",fsize,maxsize,(int32_t)sizeof(data));
fclose(fp);
}
return(n);
}
#endif

109
src/komodo_bitcoind.h Normal file
View File

@@ -0,0 +1,109 @@
/******************************************************************************
* Copyright © 2014-2016 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. *
* *
******************************************************************************/
// komodo functions that interact with bitcoind C++
uint32_t komodo_txtime(uint256 hash)
{
CTransaction tx;
uint256 hashBlock;
if (!GetTransaction(hash, tx, hashBlock, true))
{
//printf("null GetTransaction\n");
return(tx.nLockTime);
}
return(0);
}
void komodo_disconnect(CBlockIndex *pindex,CBlock& block)
{
komodo_init();
//uint256 zero;
//printf("disconnect ht.%d\n",pindex->nHeight);
//memset(&zero,0,sizeof(zero));
//komodo_stateupdate(-pindex->nHeight,0,0,0,zero,0,0,0,0);
}
int32_t komodo_block2height(CBlock *block)
{
int32_t i,n,height = 0; uint8_t *ptr = (uint8_t *)block->vtx[0].vin[0].scriptSig.data();
komodo_init();
if ( block->vtx[0].vin[0].scriptSig.size() > 5 )
{
//for (i=0; i<6; i++)
// printf("%02x",ptr[i]);
n = ptr[0];
for (i=0; i<n; i++)
{
//03bb81000101(bb 187) (81 48001) (00 12288256) <- coinbase.6 ht.12288256
height += ((uint32_t)ptr[i+1] << (i*8));
//printf("(%02x %x %d) ",ptr[i+1],((uint32_t)ptr[i+1] << (i*8)),height);
}
//printf(" <- coinbase.%d ht.%d\n",(int32_t)block->vtx[0].vin[0].scriptSig.size(),height);
}
return(height);
}
void komodo_block2pubkey33(uint8_t *pubkey33,CBlock& block)
{
uint8_t *ptr = (uint8_t *)block.vtx[0].vout[0].scriptPubKey.data();
komodo_init();
memcpy(pubkey33,ptr+1,33);
}
void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height)
{
CBlock block;
komodo_init();
memset(pubkey33,0,33);
if ( pindex != 0 )
{
if ( ReadBlockFromDisk(block,(const CBlockIndex *)pindex) != 0 )
{
komodo_block2pubkey33(pubkey33,block);
}
}
else
{
// height -> pubkey33
//printf("extending chaintip komodo_index2pubkey33 height.%d need to get pubkey33\n",height);
}
}
int32_t komodo_checkpoint(int32_t *notarized_heightp,int32_t nHeight,uint256 hash)
{
int32_t notarized_height; uint256 notarized_hash,notarized_desttxid; CBlockIndex *notary;
notarized_height = komodo_notarizeddata(chainActive.Tip()->nHeight,&notarized_hash,&notarized_desttxid);
*notarized_heightp = notarized_height;
if ( notarized_height >= 0 && notarized_height <= chainActive.Tip()->nHeight && (notary= mapBlockIndex[notarized_hash]) != 0 )
{
//printf("nHeight.%d -> (%d %s)\n",chainActive.Tip()->nHeight,notarized_height,notarized_hash.ToString().c_str());
if ( notary->nHeight == notarized_height ) // if notarized_hash not in chain, reorg
{
if ( nHeight < notarized_height )
{
fprintf(stderr,"nHeight.%d < NOTARIZED_HEIGHT.%d\n",nHeight,notarized_height);
return(-1);
}
else if ( nHeight == notarized_height && memcmp(&hash,&notarized_hash,sizeof(hash)) != 0 )
{
fprintf(stderr,"nHeight.%d == NOTARIZED_HEIGHT.%d, diff hash\n",nHeight,notarized_height);
return(-1);
}
} else fprintf(stderr,"unexpected error notary_hash %s ht.%d at ht.%d\n",notarized_hash.ToString().c_str(),notarized_height,notary->nHeight);
} else if ( notarized_height > 0 )
fprintf(stderr,"couldnt find notary_hash %s ht.%d\n",notarized_hash.ToString().c_str(),notarized_height);
return(0);
}

View File

@@ -1,7 +1,19 @@
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
//#define KOMODO_ENABLE_INTEREST
#define KOMODO_INTEREST ((uint64_t)(0.05 * COIN))
#define KOMODO_INTEREST ((uint64_t)(0.05 * COIN)) // 5%
#define dstr(x) ((double)(x)/COIN)
uint64_t komodo_accrued_interest(int32_t height,int64_t paidinterest)
@@ -55,7 +67,7 @@ uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uin
if ( denominator == 0 )
denominator = 1; // max KOMODO_INTEREST per transfer, do it at least annually!
interest = (numerator / denominator) / COIN;
fprintf(stderr,"komodo_interest %lld %.8f nLockTime.%u tiptime.%u minutes.%d interest %lld %.8f (%llu / %llu)\n",(long long)nValue,dstr(nValue),nLockTime,tiptime,minutes,(long long)interest,dstr(interest),(long long)numerator,(long long)denominator);
//fprintf(stderr,"komodo_interest %lld %.8f nLockTime.%u tiptime.%u minutes.%d interest %lld %.8f (%llu / %llu)\n",(long long)nValue,dstr(nValue),nLockTime,tiptime,minutes,(long long)interest,dstr(interest),(long long)numerator,(long long)denominator);
}
}
return(interest);

214
src/komodo_notary.h Normal file
View File

@@ -0,0 +1,214 @@
/******************************************************************************
* Copyright © 2014-2016 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. *
* *
******************************************************************************/
const char *Notaries[][2] =
{
{ "jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" },
{ "jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" },
{ "pondsea_SH", "02209073bc0943451498de57f802650311b1f12aa6deffcd893da198a544c04f36" },
{ "crackers_EU", "0340c66cf2c41c41efb420af57867baa765e8468c12aa996bfd816e1e07e410728" },
{ "pondsea_EU", "0225aa6f6f19e543180b31153d9e6d55d41bc7ec2ba191fd29f19a2f973544e29d" },
{ "locomb_EU", "025c6d26649b9d397e63323d96db42a9d3caad82e1d6076970efe5056c00c0779b" },
{ "fullmoon_AE", "0204a908350b8142698fdb6fabefc97fe0e04f537adc7522ba7a1e8f3bec003d4a" },
{ "movecrypto_EU", "021ab53bc6cf2c46b8a5456759f9d608966eff87384c2b52c0ac4cc8dd51e9cc42" },
{ "badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" },
{ "crackers_NA", "029e1c01131974f4cd3f564cc0c00eb87a0f9721043fbc1ca60f9bd0a1f73f64a1" },
{ "proto_EU", "03681ffdf17c8f4f0008cefb7fa0779c5e888339cdf932f0974483787a4d6747c1" },
{ "jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" },
{ "farl4web_EU", "035caa40684ace968677dca3f09098aa02b70e533da32390a7654c626e0cf908e1" },
{ "nxtswe_EU", "032fb104e5eaa704a38a52c126af8f67e870d70f82977e5b2f093d5c1c21ae5899" },
{ "traderbill_EU", "03196e8de3e2e5d872f31d79d6a859c8704a2198baf0af9c7b21e29656a7eb455f" },
{ "vanbreuk_EU", "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" },
{ "titomane_EU", "03517fcac101fed480ae4f2caf775560065957930d8c1facc83e30077e45bdd199" },
{ "supernet_AE", "029d93ef78197dc93892d2a30e5a54865f41e0ca3ab7eb8e3dcbc59c8756b6e355" },
{ "supernet_EU", "02061c6278b91fd4ac5cab4401100ffa3b2d5a277e8f71db23401cc071b3665546" },
{ "supernet_NA", "033c073366152b6b01535e15dd966a3a8039169584d06e27d92a69889b720d44e1" },
{ "yassin_EU", "033fb7231bb66484081952890d9a03f91164fb27d392d9152ec41336b71b15fbd0" },
{ "durerus_EU", "02bcbd287670bdca2c31e5d50130adb5dea1b53198f18abeec7211825f47485d57" },
{ "badass_SH", "026b49dd3923b78a592c1b475f208e23698d3f085c4c3b4906a59faf659fd9530b" },
{ "badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" },
{ "pondsea_NA", "031bcfdbb62268e2ff8dfffeb9ddff7fe95fca46778c77eebff9c3829dfa1bb411" },
{ "rnr_EU", "0287aa4b73988ba26cf6565d815786caf0d2c4af704d7883d163ee89cd9977edec" },
{ "crackers_SH", "02313d72f9a16055737e14cfc528dcd5d0ef094cfce23d0348fe974b6b1a32e5f0" },
{ "grewal_SH", "03212a73f5d38a675ee3cdc6e82542a96c38c3d1c79d25a1ed2e42fcf6a8be4e68" },
{ "polycryptoblock_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" },
{ "titomane_NA", "0387046d9745414fb58a0fa3599078af5073e10347e4657ef7259a99cb4f10ad47" },
{ "titomane_AE", "03cda6ca5c2d02db201488a54a548dbfc10533bdc275d5ea11928e8d6ab33c2185" },
{ "kolo_EU", "03f5c08dadffa0ffcafb8dd7ffc38c22887bd02702a6c9ac3440deddcf2837692b" },
{ "artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" },
{ "eclips_EU", "0339369c1f5a2028d44be7be6f8ec3b907fdec814f87d2dead97cab4edb71a42e9" },
{ "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" },
};
#define KOMODO_ELECTION_GAP 1000
#define KOMODO_PUBKEYS_HEIGHT(height) ((int32_t)(((((height)+KOMODO_ELECTION_GAP*.5)/KOMODO_ELECTION_GAP) + 1) * KOMODO_ELECTION_GAP))
struct nutxo_entry { UT_hash_handle hh; uint256 txhash; uint64_t voutmask; int32_t notaryid,height; } *NUTXOS;
struct knotary_entry { UT_hash_handle hh; uint8_t pubkey[33],notaryid; };
struct knotaries_entry { int32_t height,numnotaries; struct knotary_entry *Notaries; } Pubkeys[10000];
struct notarized_checkpoint { uint256 notarized_hash,notarized_desttxid; int32_t nHeight,notarized_height; } *NPOINTS; int32_t NUM_NPOINTS;
int32_t komodo_ratify_threshold(int32_t height,uint64_t signedmask)
{
int32_t numnotaries,i,wt = 0;
numnotaries = Pubkeys[height / KOMODO_ELECTION_GAP].numnotaries;
for (i=0; i<numnotaries; i++)
if ( ((1LL << i) & signedmask) != 0 )
wt++;
if ( wt > (numnotaries >> 1) || (wt > 7 && (signedmask & 3) != 0) )
return(1); // N/2+1 || N/3 + devsig
else return(0);
}
void komodo_nutxoadd(int32_t height,int32_t notaryid,uint256 txhash,uint64_t voutmask,int32_t numvouts)
{
struct nutxo_entry *np;
if ( numvouts > 1 && notaryid < 64 )
{
pthread_mutex_lock(&komodo_mutex);
np = (struct nutxo_entry *)calloc(1,sizeof(*np));
np->height = height;
np->txhash = txhash;
np->voutmask = voutmask;
np->notaryid = notaryid;
HASH_ADD_KEYPTR(hh,NUTXOS,&np->txhash,sizeof(np->txhash),np);
printf("Add NUTXO[%d] <- %s notaryid.%d t%u %s %llx\n",Num_nutxos,Notaries[notaryid][0],notaryid,komodo_txtime(txhash),txhash.ToString().c_str(),(long long)voutmask);
//if ( addflag != 0 )
// komodo_stateupdate(height,0,0,notaryid,txhash,voutmask,numvouts,0,0);
Num_nutxos++;
pthread_mutex_unlock(&komodo_mutex);
}
}
int32_t komodo_nutxofind(int32_t height,uint256 txhash,int32_t vout)
{
struct nutxo_entry *np;
pthread_mutex_lock(&komodo_mutex);
HASH_FIND(hh,NUTXOS,&txhash,sizeof(txhash),np);
pthread_mutex_unlock(&komodo_mutex);
if ( np != 0 && ((1LL << vout) & np->voutmask) != 0 )
return(np->notaryid);
return(-1);
}
void komodo_notarysinit(int32_t height,uint8_t pubkeys[64][33],int32_t num)
{
int32_t k,i,htind; struct knotary_entry *kp; struct knotaries_entry N;
memset(&N,0,sizeof(N));
pthread_mutex_lock(&komodo_mutex);
for (k=0; k<num; k++)
{
kp = (struct knotary_entry *)calloc(1,sizeof(*kp));
memcpy(kp->pubkey,pubkeys[k],33);
kp->notaryid = k;
HASH_ADD_KEYPTR(hh,N.Notaries,kp->pubkey,33,kp);
for (i=0; i<33; i++)
printf("%02x",pubkeys[k][i]);
printf(" notarypubs.[%d]\n",k);
}
N.numnotaries = num;
htind = KOMODO_PUBKEYS_HEIGHT(height) / KOMODO_ELECTION_GAP;
if ( htind == 1 )
htind = 0;
for (i=htind; i<sizeof(Pubkeys)/sizeof(*Pubkeys); i++)
{
Pubkeys[i] = N;
Pubkeys[i].height = i * KOMODO_ELECTION_GAP;
}
pthread_mutex_unlock(&komodo_mutex);
}
int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33)
{
// -1 if not notary, 0 if notary, 1 if special notary
struct knotary_entry *kp; int32_t numnotaries,modval = -1;
*notaryidp = -1;
pthread_mutex_lock(&komodo_mutex);
HASH_FIND(hh,Pubkeys[height/KOMODO_ELECTION_GAP].Notaries,pubkey33,33,kp);
pthread_mutex_unlock(&komodo_mutex);
if ( kp != 0 )
{
if ( (numnotaries= Pubkeys[height/KOMODO_ELECTION_GAP].numnotaries) > 0 )
{
*notaryidp = kp->notaryid;
modval = ((height % numnotaries) == kp->notaryid);
//printf("found notary.%d ht.%d modval.%d\n",kp->notaryid,height,modval);
} else printf("unexpected zero notaries at height.%d\n",height);
}
//int32_t i; for (i=0; i<33; i++)
// printf("%02x",pubkey33[i]);
//printf(" ht.%d notary.%d special.%d\n",height,*notaryidp,modval);
return(modval);
}
void komodo_notarized_update(int32_t nHeight,int32_t notarized_height,uint256 notarized_hash,uint256 notarized_desttxid)
{
struct notarized_checkpoint *np;
if ( notarized_height > nHeight )
{
printf("komodo_notarized_update REJECT notarized_height %d > %d nHeight\n",notarized_height,nHeight);
return;
}
NPOINTS = (struct notarized_checkpoint *)realloc(NPOINTS,(NUM_NPOINTS+1) * sizeof(*NPOINTS));
np = &NPOINTS[NUM_NPOINTS++];
memset(np,0,sizeof(*np));
np->nHeight = nHeight;
np->notarized_height = notarized_height;
np->notarized_hash = notarized_hash;
np->notarized_desttxid = notarized_desttxid;
}
int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp)
{
struct notarized_checkpoint *np = 0; int32_t i;
if ( NUM_NPOINTS > 0 )
{
for (i=0; i<NUM_NPOINTS; i++)
{
if ( NPOINTS[i].nHeight >= nHeight )
break;
np = &NPOINTS[i];
}
}
if ( np != 0 )
{
*notarized_hashp = np->notarized_hash;
*notarized_desttxidp = np->notarized_desttxid;
return(np->notarized_height);
}
memset(notarized_hashp,0,sizeof(*notarized_hashp));
return(0);
}
void komodo_init()
{
static int didinit; uint256 zero; int32_t k,n; uint8_t pubkeys[64][33];
if ( didinit == 0 )
{
didinit = 1;
pthread_mutex_init(&komodo_mutex,NULL);
decode_hex(NOTARY_PUBKEY33,33,(char *)NOTARY_PUBKEY.c_str());
n = (int32_t)(sizeof(Notaries)/sizeof(*Notaries));
for (k=0; k<n; k++)
{
if ( Notaries[k][0] == 0 || Notaries[k][1] == 0 || Notaries[k][0][0] == 0 || Notaries[k][1][0] == 0 )
break;
decode_hex(pubkeys[k],33,(char *)Notaries[k][1]);
}
komodo_notarysinit(0,pubkeys,k);
memset(&zero,0,sizeof(zero));
komodo_stateupdate(0,0,0,0,zero,0,0,0,0);
}
}

305
src/komodo_pax.h Normal file
View File

@@ -0,0 +1,305 @@
/******************************************************************************
* Copyright © 2014-2016 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. *
* *
******************************************************************************/
int32_t NUM_PRICES; uint32_t *PVALS;
#define USD 0
#define MAX_CURRENCIES 32
char CURRENCIES[][8] = { "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",
"KMD" };
uint64_t M1SUPPLY[] = { 3317900000000, 6991604000000, 667780000000000, 1616854000000, 331000000000, 861909000000, 584629000000, 46530000000, // major currencies
45434000000000, 16827000000000, 3473357229000, 306435000000, 27139000000000, 2150641000000, 347724099000, 1469583000000, 749543000000, 1826110000000, 2400434000000, 1123925000000, 3125276000000, 13975000000000, 317657000000, 759706000000000, 354902000000, 2797061000000, 162189000000, 163745000000, 1712000000000, 39093000000, 1135490000000000, 80317000000,
100000000 };
#define MIND 1000
uint32_t MINDENOMS[] = { MIND, MIND, 100*MIND, MIND, MIND, MIND, MIND, MIND, // major currencies
10*MIND, 100*MIND, 10*MIND, MIND, 100*MIND, 10*MIND, MIND, 10*MIND, MIND, 10*MIND, 10*MIND, 10*MIND, 10*MIND, 100*MIND, MIND, 1000*MIND, MIND, 10*MIND, MIND, MIND, 10*MIND, MIND, 10000*MIND, 10*MIND, // end of currencies
10*MIND,
};
uint64_t komodo_paxvol(uint64_t volume,uint64_t price)
{
if ( volume < 10000000000 )
return((volume * price) / 1000000000);
else if ( volume < (uint64_t)10 * 10000000000 )
return((volume * (price / 10)) / 100000000);
else if ( volume < (uint64_t)100 * 10000000000 )
return(((volume / 10) * (price / 10)) / 10000000);
else if ( volume < (uint64_t)1000 * 10000000000 )
return(((volume / 10) * (price / 100)) / 1000000);
else if ( volume < (uint64_t)10000 * 10000000000 )
return(((volume / 100) * (price / 100)) / 100000);
else if ( volume < (uint64_t)100000 * 10000000000 )
return(((volume / 100) * (price / 1000)) / 10000);
else if ( volume < (uint64_t)1000000 * 10000000000 )
return(((volume / 1000) * (price / 1000)) / 1000);
else if ( volume < (uint64_t)10000000 * 10000000000 )
return(((volume / 1000) * (price / 10000)) / 100);
else return(((volume / 10000) * (price / 10000)) / 10);
}
void pax_rank(uint64_t *ranked,uint32_t *pvals)
{
int32_t i; uint64_t vals[32],sum = 0;
for (i=0; i<32; i++)
{
vals[i] = komodo_paxvol(M1SUPPLY[i] / MINDENOMS[i],pvals[i]);
sum += vals[i];
}
for (i=0; i<32; i++)
{
ranked[i] = (vals[i] * 1000000000) / sum;
//printf("%.6f ",(double)ranked[i]/1000000000.);
}
//printf("sum %llu\n",(long long)sum);
};
int32_t dpow_readprices(uint8_t *data,uint32_t *timestampp,double *KMDBTCp,double *BTCUSDp,double *CNYUSDp,uint32_t *pvals)
{
uint32_t kmdbtc,btcusd,cnyusd; int32_t i,n,len = 0;
len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)timestampp);
len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&n);
len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&kmdbtc); // /= 1000
len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&btcusd); // *= 1000
len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&cnyusd);
*KMDBTCp = ((double)kmdbtc / (1000000000. * 1000.));
*BTCUSDp = ((double)btcusd / (1000000000. / 1000.));
*CNYUSDp = ((double)cnyusd / 1000000000.);
for (i=0; i<n-3; i++)
{
len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&pvals[i]);
//printf("%u ",pvals[i]);
}
pvals[i++] = kmdbtc;
pvals[i++] = btcusd;
pvals[i++] = cnyusd;
//printf("OP_RETURN prices\n");
return(n);
}
int32_t komodo_pax_opreturn(uint8_t *opret,int32_t maxsize)
{
static uint32_t lastcrc;
FILE *fp; char fname[512]; uint32_t crc32,check,timestamp; int32_t i,n,retval,fsize,len=0; uint8_t data[8192];
#ifdef WIN32
sprintf(fname,"%s\\%s",GetDataDir(false).string().c_str(),(char *)"komodofeed");
#else
sprintf(fname,"%s/%s",GetDataDir(false).string().c_str(),(char *)"komodofeed");
#endif
if ( (fp= fopen(fname,"rb")) != 0 )
{
fseek(fp,0,SEEK_END);
fsize = (int32_t)ftell(fp);
rewind(fp);
if ( fsize <= maxsize-4 && fsize <= sizeof(data) && fsize > sizeof(crc32) )
{
if ( (retval= (int32_t)fread(data,1,fsize,fp)) == fsize )
{
len = iguana_rwnum(0,data,sizeof(crc32),(void *)&crc32);
check = calc_crc32(0,data+sizeof(crc32),(int32_t)(fsize-sizeof(crc32)));
if ( check == crc32 )
{
double KMDBTC,BTCUSD,CNYUSD; uint32_t pvals[128];
dpow_readprices(&data[len],&timestamp,&KMDBTC,&BTCUSD,&CNYUSD,pvals);
if ( 0 && lastcrc != crc32 )
{
for (i=0; i<32; i++)
printf("%u ",pvals[i]);
printf("t%u n.%d KMD %f BTC %f CNY %f (%f)\n",timestamp,n,KMDBTC,BTCUSD,CNYUSD,CNYUSD!=0?1./CNYUSD:0);
}
if ( timestamp > time(NULL)-600 )
{
n = komodo_opreturnscript(opret,'P',data+sizeof(crc32),(int32_t)(fsize-sizeof(crc32)));
if ( 0 && lastcrc != crc32 )
{
for (i=0; i<n; i++)
printf("%02x",opret[i]);
printf(" coinbase opret[%d] crc32.%u:%u\n",n,crc32,check);
}
} //else printf("t%u too old for %u\n",timestamp,(uint32_t)time(NULL));
lastcrc = crc32;
} else printf("crc32 %u mismatch %u\n",crc32,check);
} else printf("fread.%d error != fsize.%d\n",retval,fsize);
} else printf("fsize.%d > maxsize.%d or data[%d]\n",fsize,maxsize,(int32_t)sizeof(data));
fclose(fp);
}
return(n);
}
/*uint32_t PAX_val32(double val)
{
uint32_t val32 = 0; struct price_resolution price;
if ( (price.Pval= val*1000000000) != 0 )
{
if ( price.Pval > 0xffffffff )
printf("Pval overflow error %lld\n",(long long)price.Pval);
else val32 = (uint32_t)price.Pval;
}
return(val32);
}*/
int32_t PAX_pubkey(uint8_t *pubkey33,uint8_t addrtype,uint8_t rmd160[20],char fiat[4],uint8_t shortflag,int32_t fiatoshis)
{
memset(pubkey33,0,33);
pubkey33[0] = 0x02 | (shortflag != 0);
memcpy(&pubkey33[1],fiat,3);
iguana_rwnum(1,&pubkey33[4],sizeof(fiatoshis),(void *)&fiatoshis);
pubkey33[12] = addrtype;
memcpy(&pubkey33[13],rmd160,20);
}
double PAX_val(uint32_t pval,int32_t baseid)
{
//printf("PAX_val baseid.%d pval.%u\n",baseid,pval);
if ( baseid >= 0 && baseid < MAX_CURRENCIES )
return(((double)pval / 1000000000.) / MINDENOMS[baseid]);
return(0.);
}
void komodo_pvals(int32_t height,uint32_t *pvals,uint8_t numpvals)
{
int32_t i,nonz; double KMDBTC,BTCUSD,CNYUSD; uint32_t kmdbtc,btcusd,cnyusd;
if ( numpvals >= 35 )
{
for (nonz=i=0; i<32; i++)
{
if ( pvals[i] != 0 )
nonz++;
//printf("%u ",pvals[i]);
}
if ( nonz == 32 )
{
kmdbtc = pvals[i++];
btcusd = pvals[i++];
cnyusd = pvals[i++];
KMDBTC = ((double)kmdbtc / (1000000000. * 1000.));
BTCUSD = ((double)btcusd / (1000000000. / 1000.));
CNYUSD = ((double)cnyusd / 1000000000.);
PVALS = (uint32_t *)realloc(PVALS,(NUM_PRICES+1) * sizeof(*PVALS) * 36);
PVALS[36 * NUM_PRICES] = height;
memcpy(&PVALS[36 * NUM_PRICES + 1],pvals,sizeof(*pvals) * 35);
NUM_PRICES++;
//printf("OP_RETURN.%d KMD %.8f BTC %.6f CNY %.6f NUM_PRICES.%d\n",height,KMDBTC,BTCUSD,CNYUSD,NUM_PRICES);
}
}
}
int32_t komodo_baseid(char *origbase)
{
int32_t i; char base[64];
for (i=0; origbase[i]!=0&&i<sizeof(base); i++)
base[i] = toupper((int32_t)(origbase[i] & 0xff));
base[i] = 0;
for (i=0; i<=MAX_CURRENCIES; i++)
if ( strcmp(CURRENCIES[i],base) == 0 )
return(i);
printf("illegal base.(%s) %s\n",origbase,base);
return(-1);
}
uint64_t komodo_paxcalc(uint32_t *pvals,int32_t baseid,int32_t relid,uint64_t basevolume)
{
uint32_t pvalb,pvalr,kmdbtc,btcusd; uint64_t usdvol,baseusd,usdkmd,baserel,sum,ranked[32]; int32_t i;
if ( basevolume > 1000000*COIN )
return(0);
if ( (pvalb= pvals[baseid]) != 0 )
{
if ( relid == MAX_CURRENCIES )
{
kmdbtc = pvals[MAX_CURRENCIES];
btcusd = pvals[MAX_CURRENCIES + 1];
if ( pvals[USD] != 0 && kmdbtc != 0 && btcusd != 0 )
{
baseusd = ((uint64_t)pvalb * 1000000000) / pvals[USD];
usdvol = komodo_paxvol(basevolume,baseusd) / MINDENOMS[baseid];
usdkmd = ((uint64_t)btcusd * 1000000000) / kmdbtc;
//printf("base -> USD %llu, BTC %llu KMDUSD %llu\n",(long long)baseusd,(long long)btcusd,(long long)kmdusd);
printf("usdkmd.%llu basevolume.%llu baseusd.%llu paxvol.%llu usdvol.%llu\n",(long long)usdkmd,(long long)basevolume,(long long)baseusd,(long long)komodo_paxvol(basevolume,baseusd),(long long)usdvol);
return(MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd));
}
}
else if ( baseid == relid )
{
if ( baseid != MAX_CURRENCIES )
{
pax_rank(ranked,pvals);
return(10 * ranked[baseid]); // map to percentage
}
}
else if ( (pvalr= pvals[relid]) != 0 )
{
baserel = ((uint64_t)pvalb * 1000000000) / pvalr;
return(komodo_paxvol(basevolume,baserel));
}
}
return(0);
}
uint64_t komodo_paxprice(int32_t height,char *base,char *rel,uint64_t basevolume)
{
int32_t baseid=-1,relid=-1,i,ht; uint32_t *ptr;
if ( (baseid= komodo_baseid(base)) >= 0 && (relid= komodo_baseid(rel)) >= 0 )
{
for (i=NUM_PRICES-1; i>=0; i--)
{
ptr = &PVALS[36 * i];
if ( *ptr < height )
return(komodo_paxcalc(&ptr[1],baseid,relid,basevolume));
}
} else printf("paxprice invalid base.%s %d, rel.%s %d\n",base,baseid,rel,relid);
return(0);
}
int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel)
{
int32_t baseid=-1,relid=-1,i,ht,num = 0; uint32_t *ptr;
if ( (baseid= komodo_baseid(base)) >= 0 && (relid= komodo_baseid(rel)) >= 0 )
{
for (i=NUM_PRICES-1; i>=0; i--)
{
ptr = &PVALS[36 * i];
heights[num] = *ptr;
prices[num] = komodo_paxcalc(&ptr[1],baseid,relid,COIN);
num++;
if ( num >= max )
return(num);
}
}
return(num);
}
uint64_t PAX_fiatdest(char *fiatbuf,char *destaddr,uint8_t pubkey33[33],char *coinaddr,int32_t height,char *origbase,int64_t fiatoshis)
{
uint8_t shortflag = 0; char base[4]; int32_t i,baseid,relid; uint8_t addrtype,rmd160[20]; uint64_t komodoshis = 0;
fiatbuf[0] = 0;
if ( strcmp(base,(char *)"KMD") == 0 || strcmp(base,(char *)"kmd") == 0 )
return(0);
for (i=0; i<3; i++)
base[i] = toupper(origbase[i]);
base[i] = 0;
if ( fiatoshis < 0 )
shortflag = 1, fiatoshis = -fiatoshis;
komodoshis = komodo_paxprice(height,base,(char *)"KMD",(uint64_t)fiatoshis);
if ( bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr) == 20 )
{
// put JSON into fiatbuf enough to replicate/validate
PAX_pubkey(pubkey33,addrtype,rmd160,base,shortflag,fiatoshis);
bitcoin_address(destaddr,KOMODO_PUBTYPE,pubkey33,33);
}
return(komodoshis);
}

908
src/komodo_utils.h Normal file
View File

@@ -0,0 +1,908 @@
/******************************************************************************
* Copyright © 2014-2016 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. *
* *
******************************************************************************/
union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; };
typedef union _bits256 bits256;
#include "mini-gmp.c"
#include "uthash.h"
#define CRYPTO777_PUBSECPSTR "020e46e79a2a8d12b9b5d12c7a91adb4e454edfae43c0a0cb805427d2ac7613fd9"
#define CRYPTO777_KMDADDR "RXL3YXG2ceaB6C5hfJcN4fvmLH2C34knhA"
#define KOMODO_PUBTYPE 60
struct sha256_vstate { uint64_t length; uint32_t state[8],curlen; uint8_t buf[64]; };
struct rmd160_vstate { uint64_t length; uint8_t buf[64]; uint32_t curlen, state[5]; };
// following is ported from libtom
#define STORE32L(x, y) \
{ (y)[3] = (uint8_t)(((x)>>24)&255); (y)[2] = (uint8_t)(((x)>>16)&255); \
(y)[1] = (uint8_t)(((x)>>8)&255); (y)[0] = (uint8_t)((x)&255); }
#define LOAD32L(x, y) \
{ x = (uint32_t)(((uint64_t)((y)[3] & 255)<<24) | \
((uint32_t)((y)[2] & 255)<<16) | \
((uint32_t)((y)[1] & 255)<<8) | \
((uint32_t)((y)[0] & 255))); }
#define STORE64L(x, y) \
{ (y)[7] = (uint8_t)(((x)>>56)&255); (y)[6] = (uint8_t)(((x)>>48)&255); \
(y)[5] = (uint8_t)(((x)>>40)&255); (y)[4] = (uint8_t)(((x)>>32)&255); \
(y)[3] = (uint8_t)(((x)>>24)&255); (y)[2] = (uint8_t)(((x)>>16)&255); \
(y)[1] = (uint8_t)(((x)>>8)&255); (y)[0] = (uint8_t)((x)&255); }
#define LOAD64L(x, y) \
{ x = (((uint64_t)((y)[7] & 255))<<56)|(((uint64_t)((y)[6] & 255))<<48)| \
(((uint64_t)((y)[5] & 255))<<40)|(((uint64_t)((y)[4] & 255))<<32)| \
(((uint64_t)((y)[3] & 255))<<24)|(((uint64_t)((y)[2] & 255))<<16)| \
(((uint64_t)((y)[1] & 255))<<8)|(((uint64_t)((y)[0] & 255))); }
#define STORE32H(x, y) \
{ (y)[0] = (uint8_t)(((x)>>24)&255); (y)[1] = (uint8_t)(((x)>>16)&255); \
(y)[2] = (uint8_t)(((x)>>8)&255); (y)[3] = (uint8_t)((x)&255); }
#define LOAD32H(x, y) \
{ x = (uint32_t)(((uint64_t)((y)[0] & 255)<<24) | \
((uint32_t)((y)[1] & 255)<<16) | \
((uint32_t)((y)[2] & 255)<<8) | \
((uint32_t)((y)[3] & 255))); }
#define STORE64H(x, y) \
{ (y)[0] = (uint8_t)(((x)>>56)&255); (y)[1] = (uint8_t)(((x)>>48)&255); \
(y)[2] = (uint8_t)(((x)>>40)&255); (y)[3] = (uint8_t)(((x)>>32)&255); \
(y)[4] = (uint8_t)(((x)>>24)&255); (y)[5] = (uint8_t)(((x)>>16)&255); \
(y)[6] = (uint8_t)(((x)>>8)&255); (y)[7] = (uint8_t)((x)&255); }
#define LOAD64H(x, y) \
{ x = (((uint64_t)((y)[0] & 255))<<56)|(((uint64_t)((y)[1] & 255))<<48) | \
(((uint64_t)((y)[2] & 255))<<40)|(((uint64_t)((y)[3] & 255))<<32) | \
(((uint64_t)((y)[4] & 255))<<24)|(((uint64_t)((y)[5] & 255))<<16) | \
(((uint64_t)((y)[6] & 255))<<8)|(((uint64_t)((y)[7] & 255))); }
// Various logical functions
#define RORc(x, y) ( ((((uint32_t)(x)&0xFFFFFFFFUL)>>(uint32_t)((y)&31)) | ((uint32_t)(x)<<(uint32_t)(32-((y)&31)))) & 0xFFFFFFFFUL)
#define Ch(x,y,z) (z ^ (x & (y ^ z)))
#define Maj(x,y,z) (((x | y) & z) | (x & y))
#define S(x, n) RORc((x),(n))
#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
#define MIN(x, y) ( ((x)<(y))?(x):(y) )
static inline int32_t sha256_vcompress(struct sha256_vstate * md,uint8_t *buf)
{
uint32_t S[8],W[64],t0,t1,i;
for (i=0; i<8; i++) // copy state into S
S[i] = md->state[i];
for (i=0; i<16; i++) // copy the state into 512-bits into W[0..15]
LOAD32H(W[i],buf + (4*i));
for (i=16; i<64; i++) // fill W[16..63]
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
#define RND(a,b,c,d,e,f,g,h,i,ki) \
t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \
t1 = Sigma0(a) + Maj(a, b, c); \
d += t0; \
h = t0 + t1;
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2);
#undef RND
for (i=0; i<8; i++) // feedback
md->state[i] = md->state[i] + S[i];
return(0);
}
#undef RORc
#undef Ch
#undef Maj
#undef S
#undef R
#undef Sigma0
#undef Sigma1
#undef Gamma0
#undef Gamma1
static inline void sha256_vinit(struct sha256_vstate * md)
{
md->curlen = 0;
md->length = 0;
md->state[0] = 0x6A09E667UL;
md->state[1] = 0xBB67AE85UL;
md->state[2] = 0x3C6EF372UL;
md->state[3] = 0xA54FF53AUL;
md->state[4] = 0x510E527FUL;
md->state[5] = 0x9B05688CUL;
md->state[6] = 0x1F83D9ABUL;
md->state[7] = 0x5BE0CD19UL;
}
static inline int32_t sha256_vprocess(struct sha256_vstate *md,const uint8_t *in,uint64_t inlen)
{
uint64_t n; int32_t err;
if ( md->curlen > sizeof(md->buf) )
return(-1);
while ( inlen > 0 )
{
if ( md->curlen == 0 && inlen >= 64 )
{
if ( (err= sha256_vcompress(md,(uint8_t *)in)) != 0 )
return(err);
md->length += 64 * 8, in += 64, inlen -= 64;
}
else
{
n = MIN(inlen,64 - md->curlen);
memcpy(md->buf + md->curlen,in,(size_t)n);
md->curlen += n, in += n, inlen -= n;
if ( md->curlen == 64 )
{
if ( (err= sha256_vcompress(md,md->buf)) != 0 )
return(err);
md->length += 8*64;
md->curlen = 0;
}
}
}
return(0);
}
static inline int32_t sha256_vdone(struct sha256_vstate *md,uint8_t *out)
{
int32_t i;
if ( md->curlen >= sizeof(md->buf) )
return(-1);
md->length += md->curlen * 8; // increase the length of the message
md->buf[md->curlen++] = (uint8_t)0x80; // append the '1' bit
// if len > 56 bytes we append zeros then compress. Then we can fall back to padding zeros and length encoding like normal.
if ( md->curlen > 56 )
{
while ( md->curlen < 64 )
md->buf[md->curlen++] = (uint8_t)0;
sha256_vcompress(md,md->buf);
md->curlen = 0;
}
while ( md->curlen < 56 ) // pad upto 56 bytes of zeroes
md->buf[md->curlen++] = (uint8_t)0;
STORE64H(md->length,md->buf+56); // store length
sha256_vcompress(md,md->buf);
for (i=0; i<8; i++) // copy output
STORE32H(md->state[i],out+(4*i));
return(0);
}
void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len)
{
struct sha256_vstate md;
sha256_vinit(&md);
sha256_vprocess(&md,src,len);
sha256_vdone(&md,hash);
}
bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen)
{
bits256 hash,hash2; int32_t i;
vcalc_sha256(0,hash.bytes,data,datalen);
vcalc_sha256(0,hash2.bytes,hash.bytes,sizeof(hash));
for (i=0; i<sizeof(hash); i++)
hash.bytes[i] = hash2.bytes[sizeof(hash) - 1 - i];
return(hash);
}
// rmd160: the five basic functions F(), G() and H()
#define F(x, y, z) ((x) ^ (y) ^ (z))
#define G(x, y, z) (((x) & (y)) | (~(x) & (z)))
#define H(x, y, z) (((x) | ~(y)) ^ (z))
#define I(x, y, z) (((x) & (z)) | ((y) & ~(z)))
#define J(x, y, z) ((x) ^ ((y) | ~(z)))
#define ROLc(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
/* the ten basic operations FF() through III() */
#define FF(a, b, c, d, e, x, s) \
(a) += F((b), (c), (d)) + (x);\
(a) = ROLc((a), (s)) + (e);\
(c) = ROLc((c), 10);
#define GG(a, b, c, d, e, x, s) \
(a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\
(a) = ROLc((a), (s)) + (e);\
(c) = ROLc((c), 10);
#define HH(a, b, c, d, e, x, s) \
(a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\
(a) = ROLc((a), (s)) + (e);\
(c) = ROLc((c), 10);
#define II(a, b, c, d, e, x, s) \
(a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\
(a) = ROLc((a), (s)) + (e);\
(c) = ROLc((c), 10);
#define JJ(a, b, c, d, e, x, s) \
(a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\
(a) = ROLc((a), (s)) + (e);\
(c) = ROLc((c), 10);
#define FFF(a, b, c, d, e, x, s) \
(a) += F((b), (c), (d)) + (x);\
(a) = ROLc((a), (s)) + (e);\
(c) = ROLc((c), 10);
#define GGG(a, b, c, d, e, x, s) \
(a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\
(a) = ROLc((a), (s)) + (e);\
(c) = ROLc((c), 10);
#define HHH(a, b, c, d, e, x, s) \
(a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\
(a) = ROLc((a), (s)) + (e);\
(c) = ROLc((c), 10);
#define III(a, b, c, d, e, x, s) \
(a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\
(a) = ROLc((a), (s)) + (e);\
(c) = ROLc((c), 10);
#define JJJ(a, b, c, d, e, x, s) \
(a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\
(a) = ROLc((a), (s)) + (e);\
(c) = ROLc((c), 10);
static int32_t rmd160_vcompress(struct rmd160_vstate *md,uint8_t *buf)
{
uint32_t aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,X[16];
int i;
/* load words X */
for (i = 0; i < 16; i++){
LOAD32L(X[i], buf + (4 * i));
}
/* load state */
aa = aaa = md->state[0];
bb = bbb = md->state[1];
cc = ccc = md->state[2];
dd = ddd = md->state[3];
ee = eee = md->state[4];
/* round 1 */
FF(aa, bb, cc, dd, ee, X[ 0], 11);
FF(ee, aa, bb, cc, dd, X[ 1], 14);
FF(dd, ee, aa, bb, cc, X[ 2], 15);
FF(cc, dd, ee, aa, bb, X[ 3], 12);
FF(bb, cc, dd, ee, aa, X[ 4], 5);
FF(aa, bb, cc, dd, ee, X[ 5], 8);
FF(ee, aa, bb, cc, dd, X[ 6], 7);
FF(dd, ee, aa, bb, cc, X[ 7], 9);
FF(cc, dd, ee, aa, bb, X[ 8], 11);
FF(bb, cc, dd, ee, aa, X[ 9], 13);
FF(aa, bb, cc, dd, ee, X[10], 14);
FF(ee, aa, bb, cc, dd, X[11], 15);
FF(dd, ee, aa, bb, cc, X[12], 6);
FF(cc, dd, ee, aa, bb, X[13], 7);
FF(bb, cc, dd, ee, aa, X[14], 9);
FF(aa, bb, cc, dd, ee, X[15], 8);
/* round 2 */
GG(ee, aa, bb, cc, dd, X[ 7], 7);
GG(dd, ee, aa, bb, cc, X[ 4], 6);
GG(cc, dd, ee, aa, bb, X[13], 8);
GG(bb, cc, dd, ee, aa, X[ 1], 13);
GG(aa, bb, cc, dd, ee, X[10], 11);
GG(ee, aa, bb, cc, dd, X[ 6], 9);
GG(dd, ee, aa, bb, cc, X[15], 7);
GG(cc, dd, ee, aa, bb, X[ 3], 15);
GG(bb, cc, dd, ee, aa, X[12], 7);
GG(aa, bb, cc, dd, ee, X[ 0], 12);
GG(ee, aa, bb, cc, dd, X[ 9], 15);
GG(dd, ee, aa, bb, cc, X[ 5], 9);
GG(cc, dd, ee, aa, bb, X[ 2], 11);
GG(bb, cc, dd, ee, aa, X[14], 7);
GG(aa, bb, cc, dd, ee, X[11], 13);
GG(ee, aa, bb, cc, dd, X[ 8], 12);
/* round 3 */
HH(dd, ee, aa, bb, cc, X[ 3], 11);
HH(cc, dd, ee, aa, bb, X[10], 13);
HH(bb, cc, dd, ee, aa, X[14], 6);
HH(aa, bb, cc, dd, ee, X[ 4], 7);
HH(ee, aa, bb, cc, dd, X[ 9], 14);
HH(dd, ee, aa, bb, cc, X[15], 9);
HH(cc, dd, ee, aa, bb, X[ 8], 13);
HH(bb, cc, dd, ee, aa, X[ 1], 15);
HH(aa, bb, cc, dd, ee, X[ 2], 14);
HH(ee, aa, bb, cc, dd, X[ 7], 8);
HH(dd, ee, aa, bb, cc, X[ 0], 13);
HH(cc, dd, ee, aa, bb, X[ 6], 6);
HH(bb, cc, dd, ee, aa, X[13], 5);
HH(aa, bb, cc, dd, ee, X[11], 12);
HH(ee, aa, bb, cc, dd, X[ 5], 7);
HH(dd, ee, aa, bb, cc, X[12], 5);
/* round 4 */
II(cc, dd, ee, aa, bb, X[ 1], 11);
II(bb, cc, dd, ee, aa, X[ 9], 12);
II(aa, bb, cc, dd, ee, X[11], 14);
II(ee, aa, bb, cc, dd, X[10], 15);
II(dd, ee, aa, bb, cc, X[ 0], 14);
II(cc, dd, ee, aa, bb, X[ 8], 15);
II(bb, cc, dd, ee, aa, X[12], 9);
II(aa, bb, cc, dd, ee, X[ 4], 8);
II(ee, aa, bb, cc, dd, X[13], 9);
II(dd, ee, aa, bb, cc, X[ 3], 14);
II(cc, dd, ee, aa, bb, X[ 7], 5);
II(bb, cc, dd, ee, aa, X[15], 6);
II(aa, bb, cc, dd, ee, X[14], 8);
II(ee, aa, bb, cc, dd, X[ 5], 6);
II(dd, ee, aa, bb, cc, X[ 6], 5);
II(cc, dd, ee, aa, bb, X[ 2], 12);
/* round 5 */
JJ(bb, cc, dd, ee, aa, X[ 4], 9);
JJ(aa, bb, cc, dd, ee, X[ 0], 15);
JJ(ee, aa, bb, cc, dd, X[ 5], 5);
JJ(dd, ee, aa, bb, cc, X[ 9], 11);
JJ(cc, dd, ee, aa, bb, X[ 7], 6);
JJ(bb, cc, dd, ee, aa, X[12], 8);
JJ(aa, bb, cc, dd, ee, X[ 2], 13);
JJ(ee, aa, bb, cc, dd, X[10], 12);
JJ(dd, ee, aa, bb, cc, X[14], 5);
JJ(cc, dd, ee, aa, bb, X[ 1], 12);
JJ(bb, cc, dd, ee, aa, X[ 3], 13);
JJ(aa, bb, cc, dd, ee, X[ 8], 14);
JJ(ee, aa, bb, cc, dd, X[11], 11);
JJ(dd, ee, aa, bb, cc, X[ 6], 8);
JJ(cc, dd, ee, aa, bb, X[15], 5);
JJ(bb, cc, dd, ee, aa, X[13], 6);
/* parallel round 1 */
JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8);
JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9);
JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9);
JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11);
JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13);
JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15);
JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15);
JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5);
JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7);
JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7);
JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8);
JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11);
JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14);
JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14);
JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12);
JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6);
/* parallel round 2 */
III(eee, aaa, bbb, ccc, ddd, X[ 6], 9);
III(ddd, eee, aaa, bbb, ccc, X[11], 13);
III(ccc, ddd, eee, aaa, bbb, X[ 3], 15);
III(bbb, ccc, ddd, eee, aaa, X[ 7], 7);
III(aaa, bbb, ccc, ddd, eee, X[ 0], 12);
III(eee, aaa, bbb, ccc, ddd, X[13], 8);
III(ddd, eee, aaa, bbb, ccc, X[ 5], 9);
III(ccc, ddd, eee, aaa, bbb, X[10], 11);
III(bbb, ccc, ddd, eee, aaa, X[14], 7);
III(aaa, bbb, ccc, ddd, eee, X[15], 7);
III(eee, aaa, bbb, ccc, ddd, X[ 8], 12);
III(ddd, eee, aaa, bbb, ccc, X[12], 7);
III(ccc, ddd, eee, aaa, bbb, X[ 4], 6);
III(bbb, ccc, ddd, eee, aaa, X[ 9], 15);
III(aaa, bbb, ccc, ddd, eee, X[ 1], 13);
III(eee, aaa, bbb, ccc, ddd, X[ 2], 11);
/* parallel round 3 */
HHH(ddd, eee, aaa, bbb, ccc, X[15], 9);
HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7);
HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15);
HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11);
HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8);
HHH(ddd, eee, aaa, bbb, ccc, X[14], 6);
HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6);
HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14);
HHH(aaa, bbb, ccc, ddd, eee, X[11], 12);
HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13);
HHH(ddd, eee, aaa, bbb, ccc, X[12], 5);
HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14);
HHH(bbb, ccc, ddd, eee, aaa, X[10], 13);
HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13);
HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7);
HHH(ddd, eee, aaa, bbb, ccc, X[13], 5);
/* parallel round 4 */
GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15);
GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5);
GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8);
GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11);
GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14);
GGG(ccc, ddd, eee, aaa, bbb, X[11], 14);
GGG(bbb, ccc, ddd, eee, aaa, X[15], 6);
GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14);
GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6);
GGG(ddd, eee, aaa, bbb, ccc, X[12], 9);
GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12);
GGG(bbb, ccc, ddd, eee, aaa, X[13], 9);
GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12);
GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5);
GGG(ddd, eee, aaa, bbb, ccc, X[10], 15);
GGG(ccc, ddd, eee, aaa, bbb, X[14], 8);
/* parallel round 5 */
FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8);
FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5);
FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12);
FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9);
FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12);
FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5);
FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14);
FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6);
FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8);
FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13);
FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6);
FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5);
FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15);
FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13);
FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11);
FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11);
/* combine results */
ddd += cc + md->state[1]; /* final result for md->state[0] */
md->state[1] = md->state[2] + dd + eee;
md->state[2] = md->state[3] + ee + aaa;
md->state[3] = md->state[4] + aa + bbb;
md->state[4] = md->state[0] + bb + ccc;
md->state[0] = ddd;
return 0;
}
/**
Initialize the hash state
@param md The hash state you wish to initialize
@return 0 if successful
*/
int rmd160_vinit(struct rmd160_vstate * md)
{
md->state[0] = 0x67452301UL;
md->state[1] = 0xefcdab89UL;
md->state[2] = 0x98badcfeUL;
md->state[3] = 0x10325476UL;
md->state[4] = 0xc3d2e1f0UL;
md->curlen = 0;
md->length = 0;
return 0;
}
#define HASH_PROCESS(func_name, compress_name, state_var, block_size) \
int func_name (struct rmd160_vstate * md, const unsigned char *in, unsigned long inlen) \
{ \
unsigned long n; \
int err; \
if (md->curlen > sizeof(md->buf)) { \
return -1; \
} \
while (inlen > 0) { \
if (md->curlen == 0 && inlen >= block_size) { \
if ((err = compress_name (md, (unsigned char *)in)) != 0) { \
return err; \
} \
md->length += block_size * 8; \
in += block_size; \
inlen -= block_size; \
} else { \
n = MIN(inlen, (block_size - md->curlen)); \
memcpy(md->buf + md->curlen, in, (size_t)n); \
md->curlen += n; \
in += n; \
inlen -= n; \
if (md->curlen == block_size) { \
if ((err = compress_name (md, md->buf)) != 0) { \
return err; \
} \
md->length += 8*block_size; \
md->curlen = 0; \
} \
} \
} \
return 0; \
}
/**
Process a block of memory though the hash
@param md The hash state
@param in The data to hash
@param inlen The length of the data (octets)
@return 0 if successful
*/
HASH_PROCESS(rmd160_vprocess, rmd160_vcompress, rmd160, 64)
/**
Terminate the hash to get the digest
@param md The hash state
@param out [out] The destination of the hash (20 bytes)
@return 0 if successful
*/
int rmd160_vdone(struct rmd160_vstate * md, unsigned char *out)
{
int i;
if (md->curlen >= sizeof(md->buf)) {
return -1;
}
/* increase the length of the message */
md->length += md->curlen * 8;
/* append the '1' bit */
md->buf[md->curlen++] = (unsigned char)0x80;
/* if the length is currently above 56 bytes we append zeros
* then compress. Then we can fall back to padding zeros and length
* encoding like normal.
*/
if (md->curlen > 56) {
while (md->curlen < 64) {
md->buf[md->curlen++] = (unsigned char)0;
}
rmd160_vcompress(md, md->buf);
md->curlen = 0;
}
/* pad upto 56 bytes of zeroes */
while (md->curlen < 56) {
md->buf[md->curlen++] = (unsigned char)0;
}
/* store length */
STORE64L(md->length, md->buf+56);
rmd160_vcompress(md, md->buf);
/* copy output */
for (i = 0; i < 5; i++) {
STORE32L(md->state[i], out+(4*i));
}
return 0;
}
void calc_rmd160(char deprecated[41],uint8_t buf[20],uint8_t *msg,int32_t len)
{
struct rmd160_vstate md;
rmd160_vinit(&md);
rmd160_vprocess(&md,msg,len);
rmd160_vdone(&md, buf);
}
static const uint32_t crc32_tab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
uint32_t calc_crc32(uint32_t crc,const void *buf,size_t size)
{
const uint8_t *p;
p = (const uint8_t *)buf;
crc = crc ^ ~0U;
while (size--)
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
return crc ^ ~0U;
}
void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen)
{
bits256 hash;
vcalc_sha256(0,hash.bytes,data,datalen);
calc_rmd160(0,rmd160,hash.bytes,sizeof(hash));
}
int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr)
{
bits256 hash; uint8_t *buf,_buf[25]; int32_t len;
memset(rmd160,0,20);
*addrtypep = 0;
buf = _buf;
if ( (len= bitcoin_base58decode(buf,coinaddr)) >= 4 )
{
// validate with trailing hash, then remove hash
hash = bits256_doublesha256(0,buf,21);
*addrtypep = *buf;
memcpy(rmd160,buf+1,20);
if ( (buf[21]&0xff) == hash.bytes[31] && (buf[22]&0xff) == hash.bytes[30] &&(buf[23]&0xff) == hash.bytes[29] && (buf[24]&0xff) == hash.bytes[28] )
{
//printf("coinaddr.(%s) valid checksum addrtype.%02x\n",coinaddr,*addrtypep);
return(20);
}
else
{
int32_t i;
if ( len > 20 )
{
hash = bits256_doublesha256(0,buf,len);
}
for (i=0; i<len; i++)
printf("%02x ",buf[i]);
char str[65]; printf("\nhex checkhash.(%s) len.%d mismatch %02x %02x %02x %02x vs %02x %02x %02x %02x\n",coinaddr,len,buf[len-1]&0xff,buf[len-2]&0xff,buf[len-3]&0xff,buf[len-4]&0xff,hash.bytes[31],hash.bytes[30],hash.bytes[29],hash.bytes[28]);
}
}
return(0);
}
char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len)
{
int32_t i; uint8_t data[25]; bits256 hash;// char checkaddr[65];
if ( len != 20 )
calc_rmd160_sha256(data+1,pubkey_or_rmd160,len);
else memcpy(data+1,pubkey_or_rmd160,20);
//btc_convrmd160(checkaddr,addrtype,data+1);
data[0] = addrtype;
hash = bits256_doublesha256(0,data,21);
for (i=0; i<4; i++)
data[21+i] = hash.bytes[31-i];
if ( (coinaddr= bitcoin_base58encode(coinaddr,data,25)) != 0 )
{
//uint8_t checktype,rmd160[20];
//bitcoin_addr2rmd160(&checktype,rmd160,coinaddr);
//if ( strcmp(checkaddr,coinaddr) != 0 )
// printf("checkaddr.(%s) vs coinaddr.(%s) %02x vs [%02x] memcmp.%d\n",checkaddr,coinaddr,addrtype,checktype,memcmp(rmd160,data+1,20));
}
return(coinaddr);
}
int32_t _unhex(char c)
{
if ( c >= '0' && c <= '9' )
return(c - '0');
else if ( c >= 'a' && c <= 'f' )
return(c - 'a' + 10);
else if ( c >= 'A' && c <= 'F' )
return(c - 'A' + 10);
return(-1);
}
int32_t is_hexstr(char *str,int32_t n)
{
int32_t i;
if ( str == 0 || str[0] == 0 )
return(0);
for (i=0; str[i]!=0; i++)
{
if ( n > 0 && i >= n )
break;
if ( _unhex(str[i]) < 0 )
break;
}
if ( n == 0 )
return(i);
return(i == n);
}
int32_t unhex(char c)
{
int32_t hex;
if ( (hex= _unhex(c)) < 0 )
{
//printf("unhex: illegal hexchar.(%c)\n",c);
}
return(hex);
}
unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])); }
int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex)
{
int32_t adjust,i = 0;
//printf("decode.(%s)\n",hex);
if ( is_hexstr(hex,n) == 0 )
{
memset(bytes,0,n);
return(n);
}
if ( n == 0 || (hex[n*2+1] == 0 && hex[n*2] != 0) )
{
if ( n > 0 )
{
bytes[0] = unhex(hex[0]);
printf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex));
}
bytes++;
hex++;
adjust = 1;
} else adjust = 0;
if ( n > 0 )
{
for (i=0; i<n; i++)
bytes[i] = _decode_hex(&hex[i*2]);
}
//bytes[i] = 0;
return(n + adjust);
}
int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp)
{
int32_t i; uint64_t x;
if ( rwflag == 0 )
{
x = 0;
for (i=len-1; i>=0; i--)
{
x <<= 8;
x |= serialized[i];
}
switch ( len )
{
case 1: *(uint8_t *)endianedp = (uint8_t)x; break;
case 2: *(uint16_t *)endianedp = (uint16_t)x; break;
case 4: *(uint32_t *)endianedp = (uint32_t)x; break;
case 8: *(uint64_t *)endianedp = (uint64_t)x; break;
}
}
else
{
x = 0;
switch ( len )
{
case 1: x = *(uint8_t *)endianedp; break;
case 2: x = *(uint16_t *)endianedp; break;
case 4: x = *(uint32_t *)endianedp; break;
case 8: x = *(uint64_t *)endianedp; break;
}
for (i=0; i<len; i++,x >>= 8)
serialized[i] = (uint8_t)(x & 0xff);
}
return(len);
}
int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp)
{
int32_t i;
if ( rwflag == 0 )
{
for (i=0; i<len; i++)
endianedp[i] = serialized[i];
}
else
{
for (i=0; i<len; i++)
serialized[i] = endianedp[i];
}
return(len);
}
int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen)
{
int32_t offset = 0;
script[offset++] = 0x6a;
opretlen++;
if ( opretlen >= 0x4c )
{
if ( opretlen > 0xff )
{
script[offset++] = 0x4d;
script[offset++] = opretlen & 0xff;
script[offset++] = (opretlen >> 8) & 0xff;
}
else
{
script[offset++] = 0x4c;
script[offset++] = opretlen;
}
} else script[offset++] = opretlen;
script[offset] = type; // covered by opretlen
memcpy(&script[offset],opret,opretlen);
return(opretlen + offset);
}

View File

@@ -546,6 +546,16 @@ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& loc
CCoinsViewCache *pcoinsTip = NULL;
CBlockTreeDB *pblocktree = NULL;
// Komodo globals
int32_t IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY;
std::string NOTARY_PUBKEY;
uint8_t NOTARY_PUBKEY33[33];
#define KOMODO_TESTNET_EXPIRATION 60000
//#define KOMODO_ENABLE_INTEREST enabling this is a hardfork
#define KOMODO_SOURCE "KMD"
#define KOMODO_PAX
#include "komodo.h"
//////////////////////////////////////////////////////////////////////////////
@@ -665,14 +675,16 @@ bool IsStandardTx(const CTransaction& tx, string& reason)
}
}
unsigned int nDataOut = 0;
unsigned int v=0,nDataOut = 0;
txnouttype whichType;
BOOST_FOREACH(const CTxOut& txout, tx.vout) {
BOOST_FOREACH(const CTxOut& txout, tx.vout)
{
if (!::IsStandard(txout.scriptPubKey, whichType)) {
reason = "scriptpubkey";
fprintf(stderr,"vout.%d nDataout.%d\n",v,nDataOut);
return false;
}
if (whichType == TX_NULL_DATA)
nDataOut++;
else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
@@ -682,6 +694,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason)
reason = "dust";
return false;
}
v++;
}
// only one OP_RETURN txout is permitted
@@ -1138,7 +1151,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
if (!view.HaveCoins(txin.prevout.hash)) {
if (pfMissingInputs)
*pfMissingInputs = true;
fprintf(stderr,"do all inputs exist?\n");
fprintf(stderr,"missing inputs\n");
return false;
}
}
@@ -3096,31 +3109,11 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
// Don't accept any forks from the main chain prior to last checkpoint
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(chainParams.Checkpoints());
int32_t notarized_height;
if (pcheckpoint && nHeight < pcheckpoint->nHeight)
return state.DoS(100, error("%s: forked chain older than last checkpoint (height %d) vs %d", __func__, nHeight,pcheckpoint->nHeight));
else
{
int32_t notarized_height; uint256 notarized_hash,notarized_btctxid; CBlockIndex *notary;
notarized_height = komodo_notarizeddata(chainActive.Tip()->nHeight,&notarized_hash,&notarized_btctxid);
if ( (notary= mapBlockIndex[notarized_hash]) != 0 )
{
//printf("nHeight.%d -> (%d %s)\n",chainActive.Tip()->nHeight,notarized_height,notarized_hash.ToString().c_str());
if ( notary->nHeight == notarized_height ) // if notarized_hash not in chain, reorg
{
if ( nHeight < notarized_height )
{
fprintf(stderr,"nHeight.%d < NOTARIZED_HEIGHT.%d\n",nHeight,notarized_height);
return state.DoS(100, error("%s: forked chain older than last notarized (height %d) vs %d", __func__,nHeight, notarized_height));
}
else if ( nHeight == notarized_height && memcmp(&hash,&notarized_hash,sizeof(hash)) != 0 )
{
fprintf(stderr,"nHeight.%d == NOTARIZED_HEIGHT.%d, diff hash\n",nHeight,notarized_height);
return state.DoS(100, error("%s: forked chain at notarized (height %d) with different hash", __func__, notarized_height));
}
} else fprintf(stderr,"notary_hash %s ht.%d at ht.%d\n",notarized_hash.ToString().c_str(),notarized_height,notary->nHeight);
} else if ( notarized_height > 0 )
fprintf(stderr,"couldnt find notary_hash %s ht.%d\n",notarized_hash.ToString().c_str(),notarized_height);
}
else if ( komodo_checkpoint(&notarized_height,nHeight,hash) < 0 )
return state.DoS(100, error("%s: forked chain %d older than last notarized (height %d) vs %d", __func__,nHeight, notarized_height));
}
// Reject block.nVersion < 4 blocks

View File

@@ -96,7 +96,7 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams,
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
}
int32_t komodo_opreturn(uint8_t *opret,int32_t maxsize);
int32_t komodo_pax_opreturn(uint8_t *opret,int32_t maxsize);
CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
{
@@ -336,7 +336,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
txNew.vin.resize(1);
txNew.vin[0].prevout.SetNull();
int32_t i,opretlen; uint8_t opret[8192],*ptr;
if ( (opretlen= komodo_opreturn(opret,sizeof(opret))) > 0 )
if ( (opretlen= komodo_pax_opreturn(opret,sizeof(opret))) > 0 )
{
txNew.vout.resize(2);
txNew.vout[1].scriptPubKey.resize(opretlen);
@@ -454,6 +454,7 @@ static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& rese
}
extern uint8_t NOTARY_PUBKEY33[33];
uint32_t Mining_start;
int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33);
void static BitcoinMiner(CWallet *pwallet)
@@ -503,7 +504,7 @@ void static BitcoinMiner(CWallet *pwallet)
//
// Create new block
//
uint32_t starttime = (uint32_t)time(NULL);
Mining_start = (uint32_t)time(NULL);
unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
CBlockIndex* pindexPrev = chainActive.Tip();
@@ -523,12 +524,13 @@ void static BitcoinMiner(CWallet *pwallet)
//
int32_t notaryid; uint32_t savebits; int64_t nStart = GetTime();
savebits = pblock->nBits;
arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
if ( komodo_chosennotary(&notaryid,pindexPrev->nHeight+1,NOTARY_PUBKEY33) > 0 )
{
pblock->nBits = KOMODO_MINDIFF_NBITS;
hashTarget = arith_uint256().SetCompact(KOMODO_MINDIFF_NBITS);
Mining_start = (uint32_t)time(NULL);
//fprintf(stderr,"I am the chosen one for ht.%d\n",pindexPrev->nHeight+1);
}
arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
} else Mining_start = 0;
while (true)
{
@@ -565,8 +567,11 @@ void static BitcoinMiner(CWallet *pwallet)
if (UintToArith256(pblock->GetHash()) > hashTarget) {
return false;
}
/* if ( pblock->nBits == KOMODO_MINDIFF_NBITS && time(NULL) < starttime+50 )
sleep(starttime+50-time(NULL));*/
if ( Mining_start != 0 && time(NULL) < Mining_start+50 )
{
printf("Round robin diff sleep %d\n",(int32_t)(Mining_start+50-time(NULL)));
sleep(Mining_start+50-time(NULL));
}
// Found a solution
SetThreadPriority(THREAD_PRIORITY_NORMAL);

4453
src/mini-gmp.c Normal file

File diff suppressed because it is too large Load Diff

300
src/mini-gmp.h Normal file
View File

@@ -0,0 +1,300 @@
/* mini-gmp, a minimalistic implementation of a GNU GMP subset.
Copyright 2011-2015 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
/* About mini-gmp: This is a minimal implementation of a subset of the
GMP interface. It is intended for inclusion into applications which
have modest bignums needs, as a fallback when the real GMP library
is not installed.
This file defines the public interface. */
#ifndef __MINI_GMP_H__
#define __MINI_GMP_H__
/* For size_t */
#include <stddef.h>
#include <limits.h>
#include <stdint.h>
#if defined (__cplusplus)
extern "C" {
#endif
void mp_set_memory_functions (void *(*) (size_t),
void *(*) (void *, size_t, size_t),
void (*) (void *, size_t));
void mp_get_memory_functions (void *(**) (size_t),
void *(**) (void *, size_t, size_t),
void (**) (void *, size_t));
typedef uint64_t mp_limb_t;
typedef int64_t mp_size_t;
typedef uint64_t mp_bitcnt_t;
typedef mp_limb_t *mp_ptr;
typedef const mp_limb_t *mp_srcptr;
typedef struct
{
int32_t _mp_alloc; /* Number of *limbs* allocated and pointed
to by the _mp_d field. */
int32_t _mp_size; /* abs(_mp_size) is the number of limbs the
last field points to. If _mp_size is
negative this is a negative number. */
mp_limb_t *_mp_d; /* Pointer to the limbs. */
} __mpz_struct;
typedef __mpz_struct mpz_t[1];
typedef __mpz_struct *mpz_ptr;
typedef const __mpz_struct *mpz_srcptr;
extern const int32_t mp_bits_per_limb;
void mpn_copyi (mp_ptr, mp_srcptr, mp_size_t);
void mpn_copyd (mp_ptr, mp_srcptr, mp_size_t);
void mpn_zero (mp_ptr, mp_size_t);
int32_t mpn_cmp (mp_srcptr, mp_srcptr, mp_size_t);
int32_t mpn_zero_p (mp_srcptr, mp_size_t);
mp_limb_t mpn_add_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
mp_limb_t mpn_add_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t);
mp_limb_t mpn_add (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t);
mp_limb_t mpn_sub_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
mp_limb_t mpn_sub_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t);
mp_limb_t mpn_sub (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t);
mp_limb_t mpn_mul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
mp_limb_t mpn_addmul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
mp_limb_t mpn_submul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
mp_limb_t mpn_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t);
void mpn_mul_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t);
void mpn_sqr (mp_ptr, mp_srcptr, mp_size_t);
int32_t mpn_perfect_square_p (mp_srcptr, mp_size_t);
mp_size_t mpn_sqrtrem (mp_ptr, mp_ptr, mp_srcptr, mp_size_t);
mp_limb_t mpn_lshift (mp_ptr, mp_srcptr, mp_size_t, uint32_t);
mp_limb_t mpn_rshift (mp_ptr, mp_srcptr, mp_size_t, uint32_t);
mp_bitcnt_t mpn_scan0 (mp_srcptr, mp_bitcnt_t);
mp_bitcnt_t mpn_scan1 (mp_srcptr, mp_bitcnt_t);
mp_bitcnt_t mpn_popcount (mp_srcptr, mp_size_t);
mp_limb_t mpn_invert_3by2 (mp_limb_t, mp_limb_t);
#define mpn_invert_limb(x) mpn_invert_3by2 ((x), 0)
size_t mpn_get_str (uint8_t *, int32_t, mp_ptr, mp_size_t);
mp_size_t mpn_set_str (mp_ptr, const uint8_t *, size_t, int32_t);
void mpz_init (mpz_t);
void mpz_init2 (mpz_t, mp_bitcnt_t);
void mpz_clear (mpz_t);
#define mpz_odd_p(z) (((z)->_mp_size != 0) & (int32_t) (z)->_mp_d[0])
#define mpz_even_p(z) (! mpz_odd_p (z))
int32_t mpz_sgn (const mpz_t);
int32_t mpz_cmp_si (const mpz_t, int64_t);
int32_t mpz_cmp_ui (const mpz_t, uint64_t);
int32_t mpz_cmp (const mpz_t, const mpz_t);
int32_t mpz_cmpabs_ui (const mpz_t, uint64_t);
int32_t mpz_cmpabs (const mpz_t, const mpz_t);
int32_t mpz_cmp_d (const mpz_t, double);
int32_t mpz_cmpabs_d (const mpz_t, double);
void mpz_abs (mpz_t, const mpz_t);
void mpz_neg (mpz_t, const mpz_t);
void mpz_swap (mpz_t, mpz_t);
void mpz_add_ui (mpz_t, const mpz_t, uint64_t);
void mpz_add (mpz_t, const mpz_t, const mpz_t);
void mpz_sub_ui (mpz_t, const mpz_t, uint64_t);
void mpz_ui_sub (mpz_t, uint64_t, const mpz_t);
void mpz_sub (mpz_t, const mpz_t, const mpz_t);
void mpz_mul_si (mpz_t, const mpz_t, int64_t);
void mpz_mul_ui (mpz_t, const mpz_t, uint64_t);
void mpz_mul (mpz_t, const mpz_t, const mpz_t);
void mpz_mul_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
void mpz_addmul_ui (mpz_t, const mpz_t, uint64_t);
void mpz_addmul (mpz_t, const mpz_t, const mpz_t);
void mpz_submul_ui (mpz_t, const mpz_t, uint64_t);
void mpz_submul (mpz_t, const mpz_t, const mpz_t);
void mpz_cdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t);
void mpz_fdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t);
void mpz_tdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t);
void mpz_cdiv_q (mpz_t, const mpz_t, const mpz_t);
void mpz_fdiv_q (mpz_t, const mpz_t, const mpz_t);
void mpz_tdiv_q (mpz_t, const mpz_t, const mpz_t);
void mpz_cdiv_r (mpz_t, const mpz_t, const mpz_t);
void mpz_fdiv_r (mpz_t, const mpz_t, const mpz_t);
void mpz_tdiv_r (mpz_t, const mpz_t, const mpz_t);
void mpz_cdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
void mpz_fdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
void mpz_tdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
void mpz_cdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
void mpz_fdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
void mpz_tdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
void mpz_mod (mpz_t, const mpz_t, const mpz_t);
void mpz_divexact (mpz_t, const mpz_t, const mpz_t);
int32_t mpz_divisible_p (const mpz_t, const mpz_t);
int32_t mpz_congruent_p (const mpz_t, const mpz_t, const mpz_t);
uint64_t mpz_cdiv_qr_ui (mpz_t, mpz_t, const mpz_t, uint64_t);
uint64_t mpz_fdiv_qr_ui (mpz_t, mpz_t, const mpz_t, uint64_t);
uint64_t mpz_tdiv_qr_ui (mpz_t, mpz_t, const mpz_t, uint64_t);
uint64_t mpz_cdiv_q_ui (mpz_t, const mpz_t, uint64_t);
uint64_t mpz_fdiv_q_ui (mpz_t, const mpz_t, uint64_t);
uint64_t mpz_tdiv_q_ui (mpz_t, const mpz_t, uint64_t);
uint64_t mpz_cdiv_r_ui (mpz_t, const mpz_t, uint64_t);
uint64_t mpz_fdiv_r_ui (mpz_t, const mpz_t, uint64_t);
uint64_t mpz_tdiv_r_ui (mpz_t, const mpz_t, uint64_t);
uint64_t mpz_cdiv_ui (const mpz_t, uint64_t);
uint64_t mpz_fdiv_ui (const mpz_t, uint64_t);
uint64_t mpz_tdiv_ui (const mpz_t, uint64_t);
uint64_t mpz_mod_ui (mpz_t, const mpz_t, uint64_t);
void mpz_divexact_ui (mpz_t, const mpz_t, uint64_t);
int32_t mpz_divisible_ui_p (const mpz_t, uint64_t);
uint64_t mpz_gcd_ui (mpz_t, const mpz_t, uint64_t);
void mpz_gcd (mpz_t, const mpz_t, const mpz_t);
void mpz_gcdext (mpz_t, mpz_t, mpz_t, const mpz_t, const mpz_t);
void mpz_lcm_ui (mpz_t, const mpz_t, uint64_t);
void mpz_lcm (mpz_t, const mpz_t, const mpz_t);
int32_t mpz_invert (mpz_t, const mpz_t, const mpz_t);
void mpz_sqrtrem (mpz_t, mpz_t, const mpz_t);
void mpz_sqrt (mpz_t, const mpz_t);
int32_t mpz_perfect_square_p (const mpz_t);
void mpz_pow_ui (mpz_t, const mpz_t, uint64_t);
void mpz_ui_pow_ui (mpz_t, uint64_t, uint64_t);
void mpz_powm (mpz_t, const mpz_t, const mpz_t, const mpz_t);
void mpz_powm_ui (mpz_t, const mpz_t, uint64_t, const mpz_t);
void mpz_rootrem (mpz_t, mpz_t, const mpz_t, uint64_t);
int32_t mpz_root (mpz_t, const mpz_t, uint64_t);
void mpz_fac_ui (mpz_t, uint64_t);
void mpz_bin_uiui (mpz_t, uint64_t, uint64_t);
int32_t mpz_probab_prime_p (const mpz_t, int32_t);
int32_t mpz_tstbit (const mpz_t, mp_bitcnt_t);
void mpz_setbit (mpz_t, mp_bitcnt_t);
void mpz_clrbit (mpz_t, mp_bitcnt_t);
void mpz_combit (mpz_t, mp_bitcnt_t);
void mpz_com (mpz_t, const mpz_t);
void mpz_and (mpz_t, const mpz_t, const mpz_t);
void mpz_ior (mpz_t, const mpz_t, const mpz_t);
void mpz_xor (mpz_t, const mpz_t, const mpz_t);
mp_bitcnt_t mpz_popcount (const mpz_t);
mp_bitcnt_t mpz_hamdist (const mpz_t, const mpz_t);
mp_bitcnt_t mpz_scan0 (const mpz_t, mp_bitcnt_t);
mp_bitcnt_t mpz_scan1 (const mpz_t, mp_bitcnt_t);
int32_t mpz_fits_slong_p (const mpz_t);
int32_t mpz_fits_ulong_p (const mpz_t);
int64_t mpz_get_si (const mpz_t);
uint64_t mpz_get_ui (const mpz_t);
double mpz_get_d (const mpz_t);
size_t mpz_size (const mpz_t);
mp_limb_t mpz_getlimbn (const mpz_t, mp_size_t);
void mpz_realloc2 (mpz_t, mp_bitcnt_t);
mp_srcptr mpz_limbs_read (mpz_srcptr);
mp_ptr mpz_limbs_modify (mpz_t, mp_size_t);
mp_ptr mpz_limbs_write (mpz_t, mp_size_t);
void mpz_limbs_finish (mpz_t, mp_size_t);
mpz_srcptr mpz_roinit_n (mpz_t, mp_srcptr, mp_size_t);
#define MPZ_ROINIT_N(xp, xs) {{0, (xs),(xp) }}
void mpz_set_si (mpz_t, int64_t);
void mpz_set_ui (mpz_t, uint64_t);
void mpz_set (mpz_t, const mpz_t);
void mpz_set_d (mpz_t, double);
void mpz_init_set_si (mpz_t, int64_t);
void mpz_init_set_ui (mpz_t, uint64_t);
void mpz_init_set (mpz_t, const mpz_t);
void mpz_init_set_d (mpz_t, double);
size_t mpz_sizeinbase (const mpz_t, int32_t);
char *mpz_get_str (char *, int32_t, const mpz_t);
int32_t mpz_set_str (mpz_t, const char *, int32_t);
int32_t mpz_init_set_str (mpz_t, const char *, int32_t);
/* This long list taken from gmp.h. */
/* For reference, "defined(EOF)" cannot be used here. In g++ 2.95.4,
<iostream> defines EOF but not FILE. */
#if defined (FILE) \
|| defined (H_STDIO) \
|| defined (_H_STDIO) /* AIX */ \
|| defined (_STDIO_H) /* glibc, Sun, SCO */ \
|| defined (_STDIO_H_) /* BSD, OSF */ \
|| defined (__STDIO_H) /* Borland */ \
|| defined (__STDIO_H__) /* IRIX */ \
|| defined (_STDIO_INCLUDED) /* HPUX */ \
|| defined (__dj_include_stdio_h_) /* DJGPP */ \
|| defined (_FILE_DEFINED) /* Microsoft */ \
|| defined (__STDIO__) /* Apple MPW MrC */ \
|| defined (_MSL_STDIO_H) /* Metrowerks */ \
|| defined (_STDIO_H_INCLUDED) /* QNX4 */ \
|| defined (_ISO_STDIO_ISO_H) /* Sun C++ */ \
|| defined (__STDIO_LOADED) /* VMS */
size_t mpz_out_str (FILE *, int32_t, const mpz_t);
#endif
void mpz_import (mpz_t, size_t, int32_t, size_t, int32_t, size_t, const void *);
void *mpz_export (void *, size_t *, int32_t, size_t, int32_t, size_t, const mpz_t);
#define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT)
#define GMP_NAIL_BITS 0
#define GMP_NUMB_BITS (GMP_LIMB_BITS - GMP_NAIL_BITS)
#if defined (__cplusplus)
}
#endif
#endif /* __MINI_GMP_H__ */

View File

@@ -383,32 +383,75 @@ Value gettxoutsetinfo(const Array& params, bool fHelp)
uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime);
uint32_t komodo_txtime(uint256 hash);
uint64_t komodo_paxprice(int32_t height,char *base,char *rel,uint64_t basevolume);
int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel);
Value paxprice(const Array& params, bool fHelp)
{
if ( fHelp || params.size() < 3 || params.size() > 4 )
throw runtime_error("paxprice \"base\" \"rel\" height\n");
LOCK(cs_main);
Object ret; uint64_t pricetoshis,basevolume=0,relvolume;
Object ret; uint64_t basevolume=0,relvolume;
std::string base = params[0].get_str();
std::string rel = params[1].get_str();
int32_t height = atoi(params[2].get_str().c_str());
if ( params.size() == 4 )
basevolume = AmountFromValue(params[3]);
if ( basevolume == 0 )
if ( (basevolume= COIN * atof(params[3].get_str().c_str())) == 0 )
basevolume = COIN;
relvolume = komodo_paxprice(height,(char *)base.c_str(),(char *)rel.c_str(),basevolume);
ret.push_back(Pair("base", base));
ret.push_back(Pair("rel", rel));
ret.push_back(Pair("height", height));
if ( basevolume != 0 )
if ( height < 0 || height > chainActive.Height() )
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
else
{
ret.push_back(Pair("price",((double)relvolume / (double)basevolume)));
ret.push_back(Pair("relvolume", ValueFromAmount(relvolume)));
CBlockIndex *pblockindex = chainActive[height];
ret.push_back(Pair("timestamp", (int64_t)pblockindex->nTime));
if ( basevolume != 0 && relvolume != 0 )
{
ret.push_back(Pair("price",((double)relvolume / (double)basevolume)));
ret.push_back(Pair("invprice",((double)basevolume / (double)relvolume)));
ret.push_back(Pair("basevolume", ValueFromAmount(basevolume)));
ret.push_back(Pair("relvolume", ValueFromAmount(relvolume)));
} else ret.push_back(Pair("error", "overflow or error in one or more of parameters"));
}
return ret;
}
Value paxprices(const Array& params, bool fHelp)
{
if ( fHelp || params.size() != 3 )
throw runtime_error("paxprices \"base\" \"rel\" maxsamples\n");
LOCK(cs_main);
Object ret; uint64_t relvolume,prices[4096]; uint32_t i,n; int32_t heights[sizeof(prices)/sizeof(*prices)];
std::string base = params[0].get_str();
std::string rel = params[1].get_str();
int32_t maxsamples = atoi(params[2].get_str().c_str());
if ( maxsamples < 1 )
maxsamples = 1;
else if ( maxsamples > sizeof(heights)/sizeof(*heights) )
maxsamples = sizeof(heights)/sizeof(*heights);
ret.push_back(Pair("base", base));
ret.push_back(Pair("rel", rel));
n = komodo_paxprices(heights,prices,maxsamples,(char *)base.c_str(),(char *)rel.c_str());
Array a;
for (i=0; i<n; i++)
{
Object item;
if ( heights[i] < 0 || heights[i] > chainActive.Height() )
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
else
{
CBlockIndex *pblockindex = chainActive[heights[i]];
item.push_back(Pair("t", (int64_t)pblockindex->nTime));
item.push_back(Pair("p", (double)prices[i] / COIN));
a.push_back(item);
}
}
ret.push_back(Pair("array", a));
return ret;
}
Value gettxout(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 2 || params.size() > 3)

View File

@@ -106,7 +106,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "z_getoperationstatus", 0},
{ "z_getoperationresult", 0},
{ "z_importkey", 1 },
{ "paxprice", 3 },
{ "paxprice", 4 },
{ "paxprice2", 3 },
};
class CRPCConvertTable

View File

@@ -41,7 +41,7 @@ using namespace std;
**/
Value getinfo(const Array& params, bool fHelp)
{
extern uint256 NOTARIZED_HASH,NOTARIZED_BTCTXID;
extern uint256 NOTARIZED_HASH,NOTARIZED_DESTTXID;
extern int32_t NOTARIZED_HEIGHT;
if (fHelp || params.size() != 0)
throw runtime_error(
@@ -85,7 +85,7 @@ Value getinfo(const Array& params, bool fHelp)
obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
obj.push_back(Pair("notarized", NOTARIZED_HEIGHT));
obj.push_back(Pair("notarizedhash", NOTARIZED_HASH.ToString()));
obj.push_back(Pair("notarizedbtc", NOTARIZED_BTCTXID.ToString()));
obj.push_back(Pair("notarizedbtc", NOTARIZED_DESTTXID.ToString()));
#ifdef ENABLE_WALLET
if (pwalletMain) {
obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));

View File

@@ -301,6 +301,7 @@ static const CRPCCommand vRPCCommands[] =
{ "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true },
{ "blockchain", "verifychain", &verifychain, true },
{ "blockchain", "paxprice", &paxprice, true },
{ "blockchain", "paxprices", &paxprices, true },
/* Mining */
{ "mining", "getblocktemplate", &getblocktemplate, true },
@@ -398,7 +399,9 @@ static const CRPCCommand vRPCCommands[] =
{ "wallet", "z_exportkey", &z_exportkey, true },
{ "wallet", "z_importkey", &z_importkey, true },
{ "wallet", "z_exportwallet", &z_exportwallet, true },
{ "wallet", "z_importwallet", &z_importwallet, true }
{ "wallet", "z_importwallet", &z_importwallet, true },
{ "wallet", "paxdeposit", &paxdeposit, true }
#endif // ENABLE_WALLET
};

View File

@@ -244,6 +244,8 @@ extern json_spirit::Value getblock(const json_spirit::Array& params, bool fHelp)
extern json_spirit::Value gettxoutsetinfo(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value gettxout(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value paxprice(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value paxprices(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value paxdeposit(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value verifychain(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getchaintips(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value invalidateblock(const json_spirit::Array& params, bool fHelp);

View File

@@ -817,6 +817,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
}
break;
// script that takes PAXpubkey + real pubkey, verifies output is within acceptable range and sig is for real pubkey. adjust vin amount to fiatvalue
case OP_CHECKSIG:
case OP_CHECKSIGVERIFY:
{

View File

@@ -184,14 +184,20 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
{
vector<valtype> vSolutions;
if (!Solver(scriptPubKey, whichType, vSolutions))
{
int32_t i; uint8_t *ptr = (uint8_t *)scriptPubKey.data();
for (i=0; i<scriptPubKey.size(); i++)
fprintf(stderr,"%02x",ptr[i]);
fprintf(stderr," non-standard scriptPubKey\n");
return false;
}
if (whichType == TX_MULTISIG)
{
unsigned char m = vSolutions.front()[0];
unsigned char n = vSolutions.back()[0];
// Support up to x-of-3 multisig txns as standard
if (n < 1 || n > 3)
// Support up to x-of-9 multisig txns as standard
if (n < 1 || n > 9)
return false;
if (m < 1 || m > n)
return false;
@@ -211,7 +217,10 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
{
CPubKey pubKey(vSolutions[0]);
if (!pubKey.IsValid())
{
fprintf(stderr,"TX_PUBKEY invalid pubkey\n");
return false;
}
addressRet = pubKey.GetID();
return true;

View File

@@ -365,7 +365,7 @@ Value getaddressesbyaccount(const Array& params, bool fHelp)
return ret;
}
static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew)
static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew,uint8_t *opretbuf,int32_t opretlen,long int opretValue)
{
CAmount curBalance = pwalletMain->GetBalance();
@@ -387,6 +387,20 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr
int nChangePosRet = -1;
CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
vecSend.push_back(recipient);
if ( opretlen > 0 && opretbuf != 0 )
{
CScript opretpubkey; int32_t i; uint8_t *ptr;
opretpubkey.resize(opretlen);
ptr = (uint8_t *)opretpubkey.data();
for (i=0; i<opretlen; i++)
{
ptr[i] = opretbuf[i];
printf("%02x",ptr[i]);
}
printf(" opretbuf[%d]\n",opretlen);
CRecipient opret = { opretpubkey, opretValue, false };
vecSend.push_back(opret);
}
if (!pwalletMain->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError)) {
if (!fSubtractFeeFromAmount && nValue + nFeeRequired > pwalletMain->GetBalance())
strError = strprintf("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!", FormatMoney(nFeeRequired));
@@ -447,11 +461,55 @@ Value sendtoaddress(const Array& params, bool fHelp)
EnsureWalletIsUnlocked();
SendMoney(address.Get(), nAmount, fSubtractFeeFromAmount, wtx);
SendMoney(address.Get(), nAmount, fSubtractFeeFromAmount, wtx,0,0,0);
return wtx.GetHash().GetHex();
}
uint64_t PAX_fiatdest(char *fiatbuf,char *destaddr,uint8_t pubkey33[33],char *coinaddr,int32_t height,char *base,int64_t fiatoshis);
int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen);
#define CRYPTO777_KMDADDR "RXL3YXG2ceaB6C5hfJcN4fvmLH2C34knhA"
Value paxdeposit(const Array& params, bool fHelp)
{
uint64_t komodoshis = 0; char destaddr[64]; uint8_t i,pubkey33[33];
bool fSubtractFeeFromAmount = false;
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
if (fHelp || params.size() != 3)
throw runtime_error("paxdeposit \"address\" [-]fiatoshis \"base\"\nnegative fiatoshis means a short position, long position capped at 100% gain");
LOCK2(cs_main, pwalletMain->cs_wallet);
CBitcoinAddress address(params[0].get_str());
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
int64_t fiatoshis = atof(params[1].get_str().c_str()) * COIN;
std::string base = params[2].get_str();
std::string dest; char fiatbuf[1024];
komodoshis = PAX_fiatdest(fiatbuf,destaddr,pubkey33,(char *)params[0].get_str().c_str(),chainActive.Tip()->nHeight,(char *)base.c_str(),fiatoshis);
dest.append(destaddr);
CBitcoinAddress destaddress(CRYPTO777_KMDADDR);
if (!destaddress.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid dest Bitcoin address");
for (i=0; i<33; i++)
printf("%02x",pubkey33[i]);
printf(" ht.%d srcaddr.(%s) %s fiatoshis.%lld -> dest.(%s) komodoshis.%llu\n",chainActive.Tip()->nHeight,(char *)params[0].get_str().c_str(),(char *)base.c_str(),(long long)fiatoshis,destaddr,(long long)komodoshis);
EnsureWalletIsUnlocked();
CWalletTx wtx;
/*std::string account,paxstr,tmp;
account.append((char *)"account");
paxstr.append(fiatbuf);
tmp.append("PAX");
wtx.mapValue["PAX"] = paxstr;
pwalletMain->SetAddressBook(destaddress.Get(),account,tmp);*/
uint8_t opretbuf[64]; int32_t opretlen; uint64_t fee = komodoshis / 1000;
if ( fee < 10000 )
fee = 10000;
opretlen = komodo_opreturnscript(opretbuf,'D',pubkey33,33);
SendMoney(destaddress.Get(),fee,fSubtractFeeFromAmount,wtx,opretbuf,opretlen,komodoshis);
return wtx.GetHash().GetHex();
}
Value listaddressgroupings(const Array& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
@@ -921,7 +979,7 @@ Value sendfrom(const Array& params, bool fHelp)
if (nAmount > nBalance)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
SendMoney(address.Get(), nAmount, false, wtx);
SendMoney(address.Get(), nAmount, false, wtx,0,0,0);
return wtx.GetHash().GetHex();
}