Browse Source

send RPC

release/v0.1
jl777 9 years ago
parent
commit
c7771a4fcb
  1. 17
      crypto777/SaM.c
  2. 882
      deprecated/iguana_secp_old.c
  3. 4
      iguana/iguana777.c
  4. 9
      iguana/iguana777.h
  5. 234
      iguana/iguana_payments.c
  6. 2
      iguana/iguana_realtime.c
  7. 293
      iguana/iguana_secp.c
  8. 25
      iguana/iguana_sign.c
  9. 52
      iguana/iguana_unspents.c
  10. 97
      iguana/iguana_volatiles.c
  11. 91
      iguana/iguana_wallet.c
  12. 2
      iguana/tests/decoderawtransaction
  13. 2
      iguana/tests/sendrawtransaction

17
crypto777/SaM.c

@ -242,13 +242,25 @@ int32_t bitweight(uint64_t x);
#define GETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] & (1 << ((bitoffset) & 7)))
#define CLEARBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] &= ~(1 << ((bitoffset) & 7)))
double OS_milliseconds();
int32_t SaM_test()
{
int32_t i,j,wt,iter,totalset,totalclr,setcount[48*8],clrcount[48*8],histo[16]; bits256 seed;
struct SaM_info state;
uint8_t buf[4096*2],bits[2][10][48];
double startmilli = time(NULL) * 1000;
uint8_t buf[4096*2],bits[2][10][48]; char trits[243];
double startmilli = OS_milliseconds();
for (i=0; i<sizeof(trits); i++)
trits[i] = (rand() % 3) - 1;
SaM_Initialize(&state);
for (i=0; i<100000; i++)
{
_SaM_Absorb(&state,(void *)trits,sizeof(trits));
}
SaM_emit(&state);
printf("per SaM %.3f\n",(OS_milliseconds() - startmilli) / i);
getchar();
for (i=0; i<1000; i++)
{
_SaM_test("A",InputA,0,OutputA);
@ -378,7 +390,6 @@ uint64_t SaM_threshold(int32_t leverage)
uint32_t SaM_nonce(void *data,int32_t datalen,int32_t leverage,int32_t maxmillis,uint32_t nonce)
{
double OS_milliseconds();
uint64_t hit,threshold; bits384 sig; double endmilli;
if ( leverage != 0 )
{

882
deprecated/iguana_secp_old.c

@ -0,0 +1,882 @@
/******************************************************************************
* 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. *
* *
******************************************************************************/
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "../includes/curve25519.h"
#include "secp256k1/include/secp256k1.h"
#include "secp256k1/include/secp256k1_ecdh.h"
#include "secp256k1/include/secp256k1_schnorr.h"
#include "secp256k1/include/secp256k1_rangeproof.h"
#include "secp256k1/include/secp256k1_recovery.h"
SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_rfc6979;
#define bits256_nonz(a) (((a).ulongs[0] | (a).ulongs[1] | (a).ulongs[2] | (a).ulongs[3]) != 0)
#define SECP_ENSURE_CTX int32_t flag = 0; if ( ctx == 0 ) { ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); secp256k1_pedersen_context_initialize(ctx); secp256k1_rangeproof_context_initialize(ctx); flag++; } else flag = 0; if ( ctx != 0 )
#define ENDSECP_ENSURE_CTX if ( flag != 0 ) secp256k1_context_destroy(ctx);
bits256 bitcoin_randkey(secp256k1_context *ctx)
{
int32_t i; bits256 privkey;
SECP_ENSURE_CTX
{
for (i=0; i<100; i++)
{
privkey = rand256(0);
if ( secp256k1_ec_seckey_verify(ctx,privkey.bytes) > 0 )
{
ENDSECP_ENSURE_CTX
return(privkey);
}
}
ENDSECP_ENSURE_CTX
}
fprintf(stderr,"couldnt generate valid bitcoin privkey. something is REALLY wrong. exiting\n");
exit(-1);
}
bits256 bitcoin_pubkey33(secp256k1_context *ctx,uint8_t *data,bits256 privkey)
{
size_t plen; bits256 pubkey; secp256k1_pubkey secppub;
memset(pubkey.bytes,0,sizeof(pubkey));
SECP_ENSURE_CTX
{
if ( secp256k1_ec_seckey_verify(ctx,privkey.bytes) == 0 )
{
printf("bitcoin_sign illegal privkey\n");
return(pubkey);
}
if ( secp256k1_ec_pubkey_create(ctx,&secppub,privkey.bytes) > 0 )
{
plen = 33;
secp256k1_ec_pubkey_serialize(ctx,data,&plen,&secppub,SECP256K1_EC_COMPRESSED);
if ( plen == 33 )
memcpy(pubkey.bytes,data+1,sizeof(pubkey));
}
ENDSECP_ENSURE_CTX
}
return(pubkey);
}
int32_t bitcoin_sign(void *ctx,char *symbol,uint8_t *sig,bits256 txhash2,bits256 privkey,int32_t recoverflag)
{
int32_t fCompressed = 1;
secp256k1_ecdsa_signature SIG; secp256k1_ecdsa_recoverable_signature rSIG; bits256 extra_entropy,seed; int32_t recid,retval = -1; size_t siglen = 72; secp256k1_pubkey SECPUB,CHECKPUB;
seed = rand256(0);
extra_entropy = rand256(0);
SECP_ENSURE_CTX
{
if ( secp256k1_ec_seckey_verify(ctx,privkey.bytes) == 0 )
{
printf("bitcoin_sign illegal privkey\n");
return(-1);
}
if ( secp256k1_context_randomize(ctx,seed.bytes) > 0 )
{
if ( recoverflag != 0 )
{
if ( secp256k1_ecdsa_sign_recoverable(ctx,&rSIG,txhash2.bytes,privkey.bytes,secp256k1_nonce_function_rfc6979,extra_entropy.bytes) > 0 )
{
recid = -1;
secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx,sig+1,&recid,&rSIG);
if ( secp256k1_ecdsa_recover(ctx,&SECPUB,&rSIG,txhash2.bytes) > 0 )
{
if ( secp256k1_ec_pubkey_create(ctx,&CHECKPUB,privkey.bytes) > 0 )
{
if ( memcmp(&SECPUB,&CHECKPUB,sizeof(SECPUB)) == 0 )
{
sig[0] = 27 + recid + (fCompressed != 0 ? 4 : 0);
retval = 64 + 1;
}
else printf("secpub mismatch\n");
} else printf("pubkey create error\n");
} else printf("recover error\n");
} else printf("secp256k1_ecdsa_sign_recoverable error\n");
}
else
{
if ( secp256k1_ecdsa_sign(ctx,&SIG,txhash2.bytes,privkey.bytes,secp256k1_nonce_function_rfc6979,extra_entropy.bytes) > 0 )
{
if ( secp256k1_ecdsa_signature_serialize_der(ctx,sig,&siglen,&SIG) > 0 )
retval = (int32_t)siglen;
}
}
}
ENDSECP_ENSURE_CTX
}
return(retval);
}
int32_t bitcoin_recoververify(void *ctx,char *symbol,uint8_t *sig65,bits256 messagehash2,uint8_t *pubkey)
{
int32_t retval = -1; size_t plen; secp256k1_pubkey PUB; secp256k1_ecdsa_signature SIG; secp256k1_ecdsa_recoverable_signature rSIG;
pubkey[0] = 0;
SECP_ENSURE_CTX
{
plen = (sig65[0] <= 31) ? 65 : 33;
secp256k1_ecdsa_recoverable_signature_parse_compact(ctx,&rSIG,sig65 + 1,0);
secp256k1_ecdsa_recoverable_signature_convert(ctx,&SIG,&rSIG);
if ( secp256k1_ecdsa_recover(ctx,&PUB,&rSIG,messagehash2.bytes) > 0 )
{
secp256k1_ec_pubkey_serialize(ctx,pubkey,&plen,&PUB,plen == 65 ? SECP256K1_EC_UNCOMPRESSED : SECP256K1_EC_COMPRESSED);
if ( secp256k1_ecdsa_verify(ctx,&SIG,messagehash2.bytes,&PUB) > 0 )
retval = 0;
else printf("secp256k1_ecdsa_verify error\n");
} else printf("secp256k1_ecdsa_recover error\n");
ENDSECP_ENSURE_CTX
}
return(retval);
}
int32_t bitcoin_verify(void *ctx,uint8_t *sig,int32_t siglen,bits256 txhash2,uint8_t *pubkey,int32_t plen)
{
int32_t retval = -1; secp256k1_pubkey PUB; secp256k1_ecdsa_signature SIG;
SECP_ENSURE_CTX
{
if ( secp256k1_ec_pubkey_parse(ctx,&PUB,pubkey,plen) > 0 )
{
secp256k1_ecdsa_signature_parse_der(ctx,&SIG,sig,siglen);
if ( secp256k1_ecdsa_verify(ctx,&SIG,txhash2.bytes,&PUB) > 0 )
retval = 0;
}
ENDSECP_ENSURE_CTX
}
return(retval);
}
bits256 bitcoin_sharedsecret(void *ctx,bits256 privkey,uint8_t *pubkey,int32_t plen)
{
int32_t retval = -1; bits256 shared; secp256k1_pubkey PUB;
memset(shared.bytes,0,sizeof(shared));
SECP_ENSURE_CTX
{
if ( secp256k1_ec_pubkey_parse(ctx,&PUB,pubkey,plen) > 0 )
{
if ( secp256k1_ecdh(ctx,shared.bytes,&PUB,privkey.bytes) > 0 )
retval = 0;
else memset(shared.bytes,0,sizeof(shared));
}
ENDSECP_ENSURE_CTX
}
return(shared);
}
int32_t bitcoin_schnorr_sign(void *ctx,uint8_t *sig64,bits256 txhash2,bits256 privkey)
{
int32_t retval = -1; bits256 seed;
SECP_ENSURE_CTX
{
seed = rand256(0);
if ( secp256k1_schnorr_sign(ctx,sig64,txhash2.bytes,privkey.bytes,secp256k1_nonce_function_rfc6979,seed.bytes) > 0 )
retval = 0;
ENDSECP_ENSURE_CTX
}
return(retval);
}
int32_t bitcoin_schnorr_verify(void *ctx,uint8_t *sig64,bits256 txhash2,uint8_t *pubkey,int32_t plen)
{
int32_t retval = -1; secp256k1_pubkey PUB;
SECP_ENSURE_CTX
{
if ( secp256k1_ec_pubkey_parse(ctx,&PUB,pubkey,plen) > 0 )
{
if ( secp256k1_schnorr_verify(ctx,sig64,txhash2.bytes,&PUB) > 0 )
retval = 0;
}
ENDSECP_ENSURE_CTX
}
return(retval);
}
int32_t bitcoin_schnorr_recover(void *ctx,uint8_t *pubkey,uint8_t *sig64,bits256 txhash2)
{
int32_t retval = -1; secp256k1_pubkey PUB; size_t plen;
SECP_ENSURE_CTX
{
if ( secp256k1_schnorr_recover(ctx,&PUB,sig64,txhash2.bytes) > 0 )
{
plen = 33;
secp256k1_ec_pubkey_serialize(ctx,pubkey,&plen,&PUB,SECP256K1_EC_COMPRESSED);
retval = 0;
}
ENDSECP_ENSURE_CTX
}
return(retval);
}
bits256 bitcoin_schnorr_noncepair(void *ctx,uint8_t *pubnonce,bits256 txhash2,bits256 privkey) //exchange
{
int32_t retval = -1; size_t plen; secp256k1_pubkey PUB; bits256 privnonce,seed;
memset(privnonce.bytes,0,sizeof(privnonce));
pubnonce[0] = 0;
SECP_ENSURE_CTX
{
seed = rand256(0);
if ( secp256k1_schnorr_generate_nonce_pair(ctx,&PUB,privnonce.bytes,txhash2.bytes,privkey.bytes,secp256k1_nonce_function_rfc6979,seed.bytes) > 0 )
{
plen = 33;
secp256k1_ec_pubkey_serialize(ctx,pubnonce,&plen,&PUB,SECP256K1_EC_COMPRESSED);
retval = 0;
}
ENDSECP_ENSURE_CTX
}
return(privnonce);
}
int32_t bitcoin_schnorr_partialsign(void *ctx,uint8_t *sig64,uint8_t *combined_pub,bits256 txhash2,bits256 privkey,bits256 privnonce,uint8_t *pubptrs[],int32_t n) // generate and exchange
{
int32_t bitcoin_pubkeylen(const uint8_t *pubkey);
int32_t i,retval = -1; secp256k1_pubkey PUBall,**PUBptrs; size_t plen;
SECP_ENSURE_CTX
{
PUBptrs = calloc(n,sizeof(*PUBptrs));
for (i=0; i<n; i++)
{
PUBptrs[i] = calloc(1,sizeof(secp256k1_pubkey));
if ( secp256k1_ec_pubkey_parse(ctx,PUBptrs[i],pubptrs[i],bitcoin_pubkeylen(pubptrs[i])) == 0 )
break;
}
if ( n > 0 && secp256k1_ec_pubkey_combine(ctx,&PUBall,(void *)PUBptrs,n) > 0 )
{
plen = 33;
if ( secp256k1_schnorr_partial_sign(ctx,sig64,txhash2.bytes,privkey.bytes,&PUBall,privnonce.bytes) > 0 )
{
secp256k1_ec_pubkey_serialize(ctx,combined_pub,&plen,&PUBall,SECP256K1_EC_COMPRESSED);
retval = 0;
}
}
free(PUBptrs);
ENDSECP_ENSURE_CTX
}
return(retval);
}
int32_t bitcoin_schnorr_combine(void *ctx,uint8_t *sig64,uint8_t *allpub,uint8_t **sigs,int32_t n,bits256 txhash2)
{
int32_t rc,retval = -1;
SECP_ENSURE_CTX
{
if ( (rc= secp256k1_schnorr_partial_combine(ctx,sig64,(void *)sigs,n)) > 0 )
{
if ( bitcoin_schnorr_recover(ctx,allpub,sig64,txhash2) == 0 )
{
if ( bitcoin_schnorr_verify(ctx,sig64,txhash2,allpub,33) == 0 )
retval = 0;
}
}
ENDSECP_ENSURE_CTX
}
return(retval);
}
int32_t bitcoin_pederson_commit(void *ctx,uint8_t *commit,bits256 blind,uint64_t value)
{
int32_t retval = -1;
SECP_ENSURE_CTX
{
if ( secp256k1_pedersen_commit(ctx,commit,blind.bytes,value) > 0 )
retval = 0;
ENDSECP_ENSURE_CTX
}
return(retval);
}
bits256 bitcoin_pederson_blindsum(void *ctx,bits256 **blindptrs,int32_t n,int32_t numpos)
{
bits256 blind_out;
memset(blind_out.bytes,0,sizeof(blind_out));
SECP_ENSURE_CTX
{
if ( secp256k1_pedersen_blind_sum(ctx,blind_out.bytes,(void *)blindptrs,n,numpos) == 0 )
memset(blind_out.bytes,0,sizeof(blind_out));
ENDSECP_ENSURE_CTX
}
return(blind_out);
}
int32_t bitcoin_pederson_tally(void *ctx,uint8_t **commits,int32_t n,int32_t numpos,int64_t excess)
{
int32_t retval = -1;
SECP_ENSURE_CTX
{
if ( secp256k1_pedersen_verify_tally(ctx,(void *)commits,numpos,(void *)&commits[numpos],n - numpos,excess) > 0 )
retval = 0;
ENDSECP_ENSURE_CTX
}
return(retval);
}
int32_t bitcoin_rangeproof_message(void *ctx,uint8_t *blind_out,uint8_t *message,uint64_t *valuep,bits256 nonce,uint64_t *min_valuep,uint64_t *max_valuep,uint8_t *commit,uint8_t *proof,int32_t prooflen)
{
int32_t outlen = 0,retval = -1;
SECP_ENSURE_CTX
{
if ( secp256k1_rangeproof_rewind(ctx,blind_out,valuep,message,&outlen,nonce.bytes,min_valuep,max_valuep,commit,proof,prooflen) > 0 )
retval = outlen;
ENDSECP_ENSURE_CTX
}
return(retval);
}
uint64_t bitcoin_rangeverify(void *ctx,int32_t *exponentp,int32_t *mantissap,uint64_t *min_valuep,uint8_t *commit,uint8_t *proof,int32_t prooflen)
{
uint64_t max_value,retval = 0;
max_value = *min_valuep = *exponentp = *mantissap = 0;
if ( secp256k1_rangeproof_info(ctx,exponentp,mantissap,min_valuep,&max_value,proof,prooflen) > 0 )
{
if ( commit != 0 )
{
if ( secp256k1_rangeproof_verify(ctx,min_valuep,&max_value,commit,proof,prooflen) > 0 )
retval = max_value;
} else retval = max_value;
}
return(retval);
}
int32_t bitcoin_rangeproof(void *ctx,uint8_t *proof,uint8_t *commit,bits256 blind,bits256 nonce,uint64_t value,uint64_t min_value,int32_t exponent,int32_t min_bits)
{
int32_t prooflen=0 ,retval = -1;
SECP_ENSURE_CTX
{
if ( secp256k1_rangeproof_sign(ctx,proof,&prooflen,min_value,commit,blind.bytes,nonce.bytes,exponent,min_bits,value) > 0 )
retval = prooflen;
ENDSECP_ENSURE_CTX
}
return(retval);
}
/*
* The intended procedure for creating a multiparty signature is:
* - Each signer S[i] with private key x[i] and public key Q[i] runs
* secp256k1_schnorr_generate_nonce_pair to produce a pair (k[i],R[i]) of private/public nonces.
* - All signers communicate their public nonces to each other (revealing your
* private nonce can lead to discovery of your private key, so it should be considered secret).
* - All signers combine all the public nonces they received (excluding their
* own) using secp256k1_ec_pubkey_combine to obtain an Rall[i] = sum(R[0..i-1,i+1..n]).
* - All signers produce a partial signature using
* secp256k1_schnorr_partial_sign, passing in their own private key x[i],
* their own private nonce k[i], and the sum of the others' public nonces Rall[i].
* - All signers communicate their partial signatures to each other.
* - Someone combines all partial signatures using secp256k1_schnorr_partial_combine, to obtain a full signature.
* - The resulting signature is validatable using secp256k1_schnorr_verify, with
* public key equal to the result of secp256k1_ec_pubkey_combine of the signers' public keys (sum(Q[0..n])).
*
* Note that secp256k1_schnorr_partial_combine and secp256k1_ec_pubkey_combine
* function take their arguments in any order, and it is possible to
* pre-combine several inputs already with one call, and add more inputs later
* by calling the function again (they are commutative and associative).
*/
#ifdef test_schnorr
#include "secp256k1/src/util.h"
#include "secp256k1/src/hash_impl.h"
#include "secp256k1/src/testrand_impl.h"
void test_schnorr_threshold(void *ctx) {
unsigned char msg[32];
unsigned char sec[5][32];
secp256k1_pubkey pub[5];
unsigned char nonce[5][32];
secp256k1_pubkey pubnonce[5];
unsigned char sig[5][64];
const unsigned char* sigs[5];
unsigned char allsig[64];
const secp256k1_pubkey* pubs[5];
secp256k1_pubkey allpub;
int n, i;
int damage;
int ret = 0;
damage = secp256k1_rand_bits(1) ? (1 + secp256k1_rand_int(4)) : 0;
secp256k1_rand256_test(msg);
n = 2 + secp256k1_rand_int(4);
for (i = 0; i < n; i++) {
do {
secp256k1_rand256_test(sec[i]);
} while (!secp256k1_ec_seckey_verify(ctx, sec[i]));
CHECK(secp256k1_ec_pubkey_create(ctx, &pub[i], sec[i]));
CHECK(secp256k1_schnorr_generate_nonce_pair(ctx, &pubnonce[i], nonce[i], msg, sec[i], NULL, NULL));
pubs[i] = &pub[i];
}
if (damage == 1) {
nonce[secp256k1_rand_int(n)][secp256k1_rand_int(32)] ^= 1 + secp256k1_rand_int(255);
} else if (damage == 2) {
sec[secp256k1_rand_int(n)][secp256k1_rand_int(32)] ^= 1 + secp256k1_rand_int(255);
}
for (i = 0; i < n; i++) {
secp256k1_pubkey allpubnonce;
const secp256k1_pubkey *pubnonces[4];
int j;
for (j = 0; j < i; j++) {
pubnonces[j] = &pubnonce[j];
}
for (j = i + 1; j < n; j++) {
pubnonces[j - 1] = &pubnonce[j];
}
CHECK(secp256k1_ec_pubkey_combine(ctx, &allpubnonce, pubnonces, n - 1));
ret |= (secp256k1_schnorr_partial_sign(ctx, sig[i], msg, sec[i], &allpubnonce, nonce[i]) != 1) * 1;
sigs[i] = sig[i];
}
if (damage == 3) {
sig[secp256k1_rand_int(n)][secp256k1_rand_bits(6)] ^= 1 + secp256k1_rand_int(255);
}
ret |= (secp256k1_ec_pubkey_combine(ctx, &allpub, pubs, n) != 1) * 2;
if ((ret & 1) == 0) {
ret |= (secp256k1_schnorr_partial_combine(ctx, allsig, sigs, n) != 1) * 4;
}
if (damage == 4) {
allsig[secp256k1_rand_int(32)] ^= 1 + secp256k1_rand_int(255);
}
if ((ret & 7) == 0) {
ret |= (secp256k1_schnorr_verify(ctx, allsig, msg, &allpub) != 1) * 8;
}
CHECK((ret == 0) == (damage == 0));
}
#endif
int32_t iguana_pederson_test(void *ctx)
{
uint8_t commits[100][33],*commitptrs[100],proofs[100][5138]; uint16_t vouts[100]; int64_t min_value,values[100],totalpos,totalneg; bits256 txids[100],nonces[100],blinds[100],*blindptrs[100],blindsum; int32_t prooflens[100],i,r,pos,neg,numpos,exponent,min_bits,n,N = 100;
srand(100);
for (i=numpos=n=0; i<N; i++)
{
values[i] = rand();
vouts[i] = (rand() % 300);
txids[i] = rand256(0);
nonces[i] = rand256(0);
blinds[i] = rand256(0);
if ( bitcoin_pederson_commit(ctx,commits[i],blinds[i],values[i]) < 0 )
break;
if ( ((r= rand()) % 2) == 0 )
values[i] = -values[i];
else
{
exponent = 0;
min_bits = 64;
min_value = 0;
prooflens[i] = bitcoin_rangeproof(ctx,proofs[i],commits[i],blinds[i],nonces[i],values[i],min_value,exponent,min_bits);
printf("%d ",prooflens[i]);
numpos++;
}
n++;
}
if ( i != N )
{
printf("commit failure i.%d of N.%d\n",i,N);
return(-1);
}
for (totalpos=i=pos=0; i<N; i++)
{
if ( values[i] > 0 )
{
commitptrs[pos] = commits[i];
blindptrs[pos] = &blinds[i];
totalpos += values[i];
pos++;
}
}
if ( pos != numpos )
{
printf("pos.%d != numpos.%d\n",pos,numpos);
return(-1);
}
for (totalneg=i=neg=0; i<N; i++)
{
if ( values[i] < 0 )
{
commitptrs[numpos + neg] = commits[i];
blindptrs[numpos + neg] = &blinds[i];
totalneg -= values[i];
neg++;
}
}
if ( numpos+neg != N )
{
printf("numpos.%d + neg.%d != N.%d\n",numpos,neg,N);
return(-1);
}
blindsum = bitcoin_pederson_blindsum(ctx,blindptrs,N,numpos);
if ( bits256_nonz(blindsum) == 0 )
{
printf("error doing blindsum numpos.%d N.%d\n",numpos,N);
return(-2);
}
if ( bitcoin_pederson_tally(ctx,commitptrs,N,numpos,totalneg - totalpos) == 0 )
{
printf("error doing pederson tally\n");
return(-3);
} else printf("pederson tally matches\n");
return(0);
}
int32_t iguana_schnorr_test(void *ctx)
{
bits256 privnonces[100],privkeys[100],txhash2; uint8_t *sigs[100],allpub[100][33],sig64[100][64],allsig64[100][64],combined_pub[100][33],pubnonces[100][33],*pubptrs[100]; int32_t i,j,N,n,errs = 0;
iguana_pederson_test(ctx);
SECP_ENSURE_CTX
{
N = 100;
txhash2 = rand256(0);
for (i=0; i<N; i++)
{
privkeys[i] = bitcoin_randkey(ctx);
privnonces[i] = bitcoin_schnorr_noncepair(ctx,pubnonces[i],txhash2,privkeys[i]);
}
if ( i != N )
{
printf("error getting nonce pair\n");
exit(-1);
}
for (i=0; i<N; i++)
{
for (j=n=0; j<N; j++)
if ( j != i )
pubptrs[n++] = pubnonces[j];
if ( N > 1 )
{
if ( bitcoin_schnorr_partialsign(ctx,sig64[i],combined_pub[i],txhash2,privkeys[i],privnonces[i],pubptrs,N-1) < 0 )
errs++;
}
else
{
if ( bitcoin_schnorr_sign(ctx,sig64[0],txhash2,privkeys[0]) < 0 )
errs++;
}
}
if ( errs != 0 )
printf("partialsign errs.%d\n",errs);
for (i=0; i<N; i++)
{
sigs[i] = sig64[i];
continue;
for (j=0; j<64; j++)
printf("%02x",sig64[i][j]);
printf(" sig[%d]\n",i);
}
for (i=0; i<N; i++)
{
if ( bitcoin_schnorr_combine(ctx,allsig64[i],allpub[i],sigs,N,txhash2) < 0 )
errs++;
else if ( memcmp(allpub[i],allpub[0],33) != 0 )
errs++;
else if ( memcmp(allsig64[i],allsig64[0],33) != 0 )
errs++;
}
if ( errs != 0 )
printf("combine errs.%d\n",errs);
if ( bitcoin_schnorr_verify(ctx,allsig64[0],txhash2,allpub[0],33) < 0 )
errs++;
printf("schnorr errs.%d\n",errs);
ENDSECP_ENSURE_CTX
}
return(errs);
}
#ifdef oldway
#include "../includes/openssl/ec.h"
#include "../includes/openssl/ecdsa.h"
#include "../includes/openssl/obj_mac.h"
static const char base58_chars[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
struct bp_key { EC_KEY *k; };
EC_KEY *oldbitcoin_privkeyset(uint8_t *oddevenp,bits256 *pubkeyp,bits256 privkey)
{
BIGNUM *bn; BN_CTX *ctx = NULL; uint8_t *ptr,tmp[33]; EC_POINT *pub_key = NULL; const EC_GROUP *group;
EC_KEY *KEY = EC_KEY_new_by_curve_name(NID_secp256k1);
*oddevenp = 0;
EC_KEY_set_conv_form(KEY,POINT_CONVERSION_COMPRESSED);
{
if ( (group= EC_KEY_get0_group(KEY)) != 0 && (ctx= BN_CTX_new()) != 0 )
{
if ( (pub_key= EC_POINT_new(group)) != 0 )
{
if ( (bn= BN_bin2bn(privkey.bytes,sizeof(privkey),BN_new())) != 0 )
{
if ( EC_POINT_mul(group,pub_key,bn,NULL,NULL,ctx) > 0 )
{
EC_KEY_set_private_key(KEY,bn);
EC_KEY_set_public_key(KEY,pub_key);
ptr = tmp;
i2o_ECPublicKey(KEY,&ptr);
*oddevenp = tmp[0];
memcpy(pubkeyp->bytes,&tmp[1],sizeof(*pubkeyp));
}
BN_clear_free(bn);
}
EC_POINT_free(pub_key);
}
BN_CTX_free(ctx);
}
}
return(KEY);
}
int32_t oldbitcoin_verify(uint8_t *sig,int32_t siglen,uint8_t *data,int32_t datalen,uint8_t *pubkey,int32_t len)
{
ECDSA_SIG *esig; int32_t retval = -1; uint8_t tmp[33],*ptr,*sigptr = sig; EC_KEY *KEY = 0;
if ( len < 0 )
return(-1);
if ( (esig= ECDSA_SIG_new()) != 0 )
{
if ( d2i_ECDSA_SIG(&esig,(const uint8_t **)&sigptr,siglen) != 0 )
{
if ( (KEY= EC_KEY_new_by_curve_name(NID_secp256k1)) != 0 )
{
EC_KEY_set_conv_form(KEY,POINT_CONVERSION_COMPRESSED);
if ( len == 32 )
{
memcpy(tmp+1,pubkey,len);
for (tmp[0]=2; tmp[0]<=3; tmp[0]++)
{
ptr = tmp;
o2i_ECPublicKey(&KEY,(const uint8_t **)&ptr,33);
if ( ECDSA_do_verify(data,datalen,esig,KEY) > 0 )
{
retval = 0;
break;
}
}
}
else
{
ptr = pubkey;
o2i_ECPublicKey(&KEY,(const uint8_t **)&ptr,len);
if ( ECDSA_do_verify(data,datalen,esig,KEY) > 0 )
retval = 0;
}
EC_KEY_free(KEY);
}
}
ECDSA_SIG_free(esig);
}
return(retval);
}
int32_t oldbitcoin_sign(uint8_t *sig,int32_t maxlen,uint8_t *data,int32_t datalen,bits256 privkey)
{
EC_KEY *KEY; uint8_t oddeven; bits256 pubkey; uint8_t *ptr; int32_t siglen,retval = -1;
ECDSA_SIG *SIG; BN_CTX *ctx; const EC_GROUP *group; BIGNUM *order,*halforder;
if ( (KEY= oldbitcoin_privkeyset(&oddeven,&pubkey,privkey)) != 0 )
{
if ( (SIG= ECDSA_do_sign(data,datalen,KEY)) != 0 )
{
ctx = BN_CTX_new();
BN_CTX_start(ctx);
group = EC_KEY_get0_group(KEY);
order = BN_CTX_get(ctx);
halforder = BN_CTX_get(ctx);
EC_GROUP_get_order(group,order,ctx);
BN_rshift1(halforder,order);
if ( BN_cmp(SIG->s,halforder) > 0 )
{
// enforce low S values, by negating the value (modulo the order) if above order/2.
BN_sub(SIG->s,order,SIG->s);
}
ptr = 0;
siglen = i2d_ECDSA_SIG(SIG,&ptr);
if ( ptr != 0 )
{
if ( siglen > 0 )
{
memcpy(sig,ptr,siglen);
retval = siglen;
}
free(ptr);
}
BN_CTX_end(ctx);
BN_CTX_free(ctx);
ECDSA_SIG_free(SIG);
}
//if ( ECDSA_sign(0,data,datalen,sig,&siglen,KEY) > 0 && siglen <= maxlen )
// retval = siglen;
EC_KEY_free(KEY);
}
return(retval);
}
bits256 oldbitcoin_pubkey33(void *_ctx,uint8_t *data,bits256 privkey)
{
uint8_t oddeven,data2[65]; size_t plen; bits256 pubkey; secp256k1_pubkey secppub; secp256k1_context *ctx;
EC_KEY *KEY;
if ( (KEY= oldbitcoin_privkeyset(&oddeven,&pubkey,privkey)) != 0 )
{
data[0] = oddeven;
memcpy(data+1,pubkey.bytes,sizeof(pubkey));
EC_KEY_free(KEY);
if ( (ctx= secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)) != 0 )
{
if ( secp256k1_ec_pubkey_create(ctx,&secppub,privkey.bytes) > 0 )
{
plen = 33;
secp256k1_ec_pubkey_serialize(ctx,data2,&plen,&secppub,1);
if ( memcmp(data2,data,plen) != 0 )
printf("pubkey compare error plen.%d\n",(int32_t)plen);
else printf("pubkey verified\n");
} //else printf("error secp256k1_ec_pubkey_create\n");
secp256k1_context_destroy(ctx);
}
} else memset(pubkey.bytes,0,sizeof(pubkey));
return(pubkey);
}
void bn_mpi2bn(BIGNUM *vo,uint8_t *data,int32_t datalen)
{
uint8_t vch2[64 + 4]; uint32_t i,vch2_len = (int32_t)datalen + 4;
if ( datalen < sizeof(vch2) )
{
vch2[0] = (datalen >> 24) & 0xff;
vch2[1] = (datalen >> 16) & 0xff;
vch2[2] = (datalen >> 8) & 0xff;
vch2[3] = (datalen >> 0) & 0xff;
for (i=0; i<datalen; i++)
vch2[4 + datalen - i - 1] = data[i];
BN_mpi2bn(vch2,vch2_len,vo);
}
}
int32_t bn_bn2mpi(uint8_t *data,const BIGNUM *v)
{
uint8_t s_be[64]; int32_t i,sz = BN_bn2mpi(v,NULL);
if ( sz >= 4 && sz < sizeof(s_be) ) // get MPI format size
{
BN_bn2mpi(v,s_be);
// copy-swap MPI to little endian, sans 32-bit size prefix
sz -= 4;
for (i=0; i<sz; i++)
data[sz - i - 1] = s_be[i + 4];
}
return(sz);
}
int32_t oldbitcoin_base58decode(uint8_t *data,char *coinaddr)
{
int32_t bitcoin_base58decode_mpz(uint8_t *data,char *coinaddr);
uint32_t zeroes,be_sz=0,i,len; const char *p,*p1; BIGNUM bn58,bn,bnChar; uint8_t revdata[64]; BN_CTX *ctx;
ctx = BN_CTX_new();
BN_init(&bn58), BN_init(&bn), BN_init(&bnChar);
BN_set_word(&bn58,58), BN_set_word(&bn,0);
while ( isspace((uint32_t)(*coinaddr & 0xff)) )
coinaddr++;
for (p=coinaddr; *p; p++)
{
p1 = strchr(base58_chars,*p);
if ( p1 == 0 )
{
while (isspace((uint32_t)*p))
p++;
if ( *p != '\0' )
goto out;
break;
}
BN_set_word(&bnChar,(int32_t)(p1 - base58_chars));
if ( BN_mul(&bn,&bn,&bn58,ctx) == 0 || BN_add(&bn,&bn,&bnChar) == 0 )
goto out;
}
len = bn_bn2mpi(revdata,&bn);
if ( len >= 2 && revdata[len - 1] == 0 && revdata[len - 2] >= 0x80 )
len--;
zeroes = 0;
for (p=coinaddr; *p==base58_chars[0]; p++)
zeroes++;
be_sz = (uint32_t)len + (uint32_t)zeroes;
memset(data,0,be_sz);
for (i=0; i<len; i++)
data[i+zeroes] = revdata[len - 1 - i];
//printf("len.%d be_sz.%d zeroes.%d data[0] %02x\n",len,be_sz,zeroes,data[0]);
out:
BN_clear_free(&bn58), BN_clear_free(&bn), BN_clear_free(&bnChar);
BN_CTX_free(ctx);
{
int32_t checkval; uint8_t data2[256];
if ( (checkval= bitcoin_base58decode_mpz(data2,coinaddr)) != be_sz )
printf("base58 decode error checkval.%d != be_sz.%d\n",checkval,be_sz);
else if ( memcmp(data2,data,be_sz) != 0 )
{
for (i=0; i<be_sz; i++)
printf("%02x",data[i]);
printf(" data[%d]\n",be_sz);
for (i=0; i<be_sz; i++)
printf("%02x",data2[i]);
printf(" data\n");
printf("base58 decode data error\n");
}
else printf("base58 decode match\n");
}
return(be_sz);
}
char *oldbitcoin_base58encode(char *coinaddr,uint8_t *data_,int32_t datalen)
{
BIGNUM bn58,bn0,bn,dv,rem; BN_CTX *ctx; uint32_t i,n,flag=0; uint8_t swapbuf[512],rs[512];
const uint8_t *data = (void *)data_;
rs[0] = 0;
n = 0;
if ( datalen < (sizeof(swapbuf) >> 1) )
{
ctx = BN_CTX_new();
BN_init(&bn58), BN_init(&bn0), BN_init(&bn), BN_init(&dv), BN_init(&rem);
BN_set_word(&bn58,58);
BN_set_word(&bn0,0);
for (i=0; i<datalen; i++)
swapbuf[datalen - i - 1] = data[i];
swapbuf[datalen] = 0;
bn_mpi2bn(&bn,swapbuf,datalen+1);
while ( BN_cmp(&bn,&bn0) > 0 )
{
if ( BN_div(&dv,&rem,&bn,&bn58,ctx) == 0 )
{
flag = -1;
break;
}
BN_copy(&bn,&dv);
rs[n++] = base58_chars[BN_get_word(&rem)];
}
if ( flag == 0 )
{
for (i=0; i<datalen; i++)
{
if ( data[i] == 0 )
rs[n++] = base58_chars[0];
else break;
}
for (i=0; i<n; i++)
coinaddr[n - i - 1] = rs[i];
coinaddr[n] = 0;
}
BN_clear_free(&bn58), BN_clear_free(&bn0), BN_clear_free(&bn), BN_clear_free(&dv), BN_clear_free(&rem);
BN_CTX_free(ctx);
{
char *bitcoin_base58encode_mpz(char *coinaddr,uint8_t *data,int32_t datalen);
char checkaddr[64];
bitcoin_base58encode_mpz(checkaddr,data_,datalen);
if ( strcmp(checkaddr,coinaddr) != 0 )
printf("mpz base58 error (%s) vs (%s)\n",checkaddr,coinaddr);
else printf("mpz matches\n");
}
return(coinaddr);
}
return(0);
}
#endif

4
iguana/iguana777.c

@ -752,6 +752,10 @@ struct iguana_info *iguana_setcoin(char *symbol,void *launched,int32_t maxpeers,
coin->mapflags = mapflags;
mult = (strcmp("BTC",coin->symbol) != 0) ? 8 : 8;
maxval = IGUANA_MAXPENDBUNDLES;
if ( (coin->txfee= jdouble(json,"txfee") * SATOSHIDEN) == 0 )
coin->txfee = 10000;
if ( (coin->txfee_perkb= j64bits(json,"txfee_perkb")) < coin->txfee/8 )
coin->txfee_perkb = coin->txfee / 8;
coin->MAXMEM = juint(json,"RAM");
if ( jobj(json,"prefetchlag") != 0 )
coin->PREFETCHLAG = jint(json,"prefetchlag");

9
iguana/iguana777.h

@ -505,6 +505,7 @@ struct iguana_info
portable_mutex_t peers_mutex,blocks_mutex;
//portable_mutex_t scripts_mutex[2]; FILE *scriptsfp[2]; void *scriptsptr[2]; long scriptsfilesize[2];
//struct scriptinfo *scriptstable[2];
char changeaddr[64];
struct iguana_bundle *bundles[IGUANA_MAXBUNDLES],*current,*lastpending;
struct iguana_ramchain RTramchain; struct OS_memspace RTmem,RThashmem; bits256 RThash1;
int32_t numremain,numpendings,zcount,recvcount,bcount,pcount,lastbundle,numsaved,pendbalances,numverified,blockdepth;
@ -512,7 +513,7 @@ struct iguana_info
double bandwidth,maxbandwidth,backstopmillis; bits256 backstophash2; int64_t spaceused;
int32_t initialheight,mapflags,minconfirms,numrecv,bindsock,isRT,backstop,blocksrecv,merging,polltimeout,numreqtxids,allhashes,balanceflush; bits256 reqtxids[64];
void *launched,*started,*rpcloop;
uint64_t bloomsearches,bloomhits,bloomfalse,collisions,txfee_perkb;
uint64_t bloomsearches,bloomhits,bloomfalse,collisions,txfee_perkb,txfee;
uint8_t blockspace[IGUANA_MAXPACKETSIZE + 8192]; struct OS_memspace blockMEM;
struct iguana_blocks blocks; bits256 APIblockhash,APItxid; char *APIblockstr;
struct iguana_hhutxo *utxotable; struct iguana_hhaccount *accountstable; char lastdispstr[2048];
@ -953,6 +954,12 @@ bits256 bitcoin_randkey(void *ctx);
int32_t bitcoin_recoververify(void *ctx,char *symbol,uint8_t *sig64,bits256 messagehash2,uint8_t *pubkey);
int32_t bitcoin_assembler(struct iguana_info *coin,uint8_t script[IGUANA_MAXSCRIPTSIZE],cJSON *scriptobj,int32_t interpret,int64_t nLockTime,struct vin_info *V);
cJSON *iguana_spendasm(struct iguana_info *coin,uint8_t *spendscript,int32_t spendlen);
int64_t iguana_unspentavail(struct iguana_info *coin,uint64_t hdrsi_unspendind,int32_t minconf,int32_t maxconf);
struct iguana_utxo iguana_utxofind(struct iguana_info *coin,int16_t spent_hdrsi,uint32_t spent_unspentind,int32_t *RTspendflagp,int32_t lockflag);
int32_t iguana_signrawtransaction(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_msgtx *msgtx,char **signedtxp,bits256 *signedtxidp,struct vin_info *V,int32_t numinputs,char *rawtx,cJSON *vins,cJSON *privkeys);
cJSON *iguana_privkeysjson(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *vins);
char *iguana_inputaddress(struct iguana_info *coin,char *coinaddr,cJSON *vinobj);
struct iguana_waddress *iguana_getaccountaddress(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *json,char *remoteaddr,char *coinaddr,char *account);
extern int32_t HDRnet,netBLOCKS;

234
iguana/iguana_payments.c

@ -158,34 +158,238 @@ cJSON *iguana_scriptobj(struct iguana_info *coin,uint8_t rmd160[20],char *coinad
return(scriptobj);
}
char *sendtoaddress(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr,uint64_t satoshis,char *comment,char *comment2,int32_t minconf,char *account)
int32_t iguana_bestunspent(struct iguana_info *coin,int32_t *aboveip,int64_t *abovep,int32_t *belowip,int64_t *belowp,uint64_t *unspents,int32_t numunspents,uint64_t value)
{
uint8_t addrtype,rmd160[20]; int32_t i,j,numwaddrs,numunspents=0; struct iguana_waddress **waddrs,*waddr; uint64_t *unspents; //struct iguana_msgtx msgtx; char *rawtx=0,*signedtx = 0; bits256 signedtxid; cJSON *vins=0,*privkeys=0;
int32_t i,abovei,belowi; int64_t above,below,gap,atx_value;
abovei = belowi = -1;
for (above=below=i=0; i<numunspents; i++)
{
if ( (atx_value= unspents[(i << 1) + 1]) <= 0 )
continue;
//printf("(%.8f vs %.8f)\n",dstr(atx_value),dstr(value));
if ( atx_value == value )
{
*aboveip = *belowip = i;
*abovep = *belowp = 0;
return(i);
}
else if ( atx_value > value )
{
gap = (atx_value - value);
if ( above == 0 || gap < above )
{
above = gap;
abovei = i;
}
}
gap = (value - atx_value);
if ( below == 0 || gap < below )
{
below = gap;
belowi = i;
}
}
*aboveip = abovei;
*abovep = above;
*belowip = belowi;
*belowp = below;
return(abovei >= 0 ? abovei : belowi);
}
cJSON *iguana_inputsjson(struct supernet_info *myinfo,struct iguana_info *coin,int64_t *totalp,uint64_t amount,uint64_t *unspents,int32_t num)
{
cJSON *item,*vins; uint8_t spendscript[IGUANA_MAXSCRIPTSIZE]; struct iguana_txid *T; struct iguana_unspent *U,*u; struct iguana_bundle *bp; struct iguana_ramchain *ramchain; char coinaddr[64],hexstr[IGUANA_MAXSCRIPTSIZE*2+1]; int32_t height,abovei,belowi,i,spendlen,ind,hdrsi; uint32_t txidind,unspentind; int64_t value,above,below,total = 0; int64_t remains = amount;
*totalp = 0;
vins = cJSON_CreateArray();
for (i=0; i<num; i++)
{
below = above = 0;
if ( iguana_bestunspent(coin,&abovei,&above,&belowi,&below,unspents,num,remains) < 0 )
{
printf("error finding unspent i.%d of %d, %.8f vs %.8f\n",i,num,dstr(remains),dstr(amount));
free_json(vins);
return(0);
}
if ( belowi < 0 || (num == 0 && abovei >= 0) )
ind = abovei;
else ind = belowi;
hdrsi = (int16_t)(unspents[(ind << 1)] >> 32);
unspentind = (uint32_t)unspents[(ind << 1)];
value = unspents[(ind << 1) + 1];
unspents[(ind << 1) + 1] = -1;
if ( (bp= coin->bundles[hdrsi]) == 0 )
{
printf("no bundle.[%d]\n",hdrsi);
free_json(vins);
return(0);
}
ramchain = &bp->ramchain;
U = RAMCHAIN_PTR(ramchain->H.data,Uoffset);
T = RAMCHAIN_PTR(ramchain->H.data,Toffset);
if ( unspentind > 0 && unspentind < ramchain->H.data->numunspents )
{
u = &U[unspentind];
if ( (txidind= u->txidind) > 0 && txidind < ramchain->H.data->numtxids )
{
if ( iguana_unspentindfind(coin,coinaddr,spendscript,&spendlen,&amount,&height,T[txidind].txid,u->vout,coin->bundlescount-1) == unspentind && spendlen > 0 )
{
init_hexbytes_noT(hexstr,spendscript,spendlen);
item = cJSON_CreateObject();
jaddbits256(item,"txid",T[txidind].txid);
jaddnum(item,"vout",u->vout);
jaddstr(item,"scriptPubKey",hexstr);
jaddi(vins,item);
total += value;
remains -= value;
printf("value %.8f -> remains %.8f\n",dstr(value),dstr(remains));
if ( remains <= 0 )
break;
}
else
{
char str[65];printf("couldnt get script for %s.%d\n",bits256_str(str,T[txidind].txid),u->vout);
free_json(vins);
return(0);
}
}
else
{
printf("illegal txidind.%d [%d]\n",txidind,hdrsi);
free_json(vins);
return(0);
}
}
else
{
printf("illegal unspentind.u%d [%d]\n",unspentind,hdrsi);
free_json(vins);
return(0);
}
}
*totalp = total;
return(vins);
}
char *iguana_signunspents(struct supernet_info *myinfo,struct iguana_info *coin,int32_t *completedp,char *coinaddr,uint64_t satoshis,char *changeaddr,uint64_t txfee,uint64_t *unspents,int32_t num)
{
uint8_t addrtype,rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE]; uint32_t locktime = 0; int32_t spendlen,numinputs,i,RTspentflag; struct iguana_msgtx msgtx; char *rawtx=0,*signedtx = 0; bits256 txid,signedtxid; cJSON *txobj,*vins=0,*privkeys=0; struct vin_info *V; int64_t value,total,change; char changeaddress[64]; struct iguana_waddress *waddr;
*completedp = 0;
if ( (vins= iguana_inputsjson(myinfo,coin,&total,satoshis + txfee,unspents,num)) != 0 )
{
if ( total < (satoshis + txfee) )
{
free_json(vins);
printf("insufficient total %.8f vs (%.8f + %.8f)\n",dstr(total),dstr(satoshis),dstr(txfee));
return(0);
}
if ( (change= (total - (satoshis + txfee))) > 0 )
{
if ( changeaddr == 0 || changeaddr[0] == 0 )
{
if ( (waddr= iguana_getaccountaddress(myinfo,coin,0,0,changeaddress,"change")) == 0 )
{
free_json(vins);
return(0);
}
strcpy(changeaddress,waddr->coinaddr);
changeaddr = changeaddress;
}
}
if ( (privkeys= iguana_privkeysjson(myinfo,coin,vins)) != 0 )
{
if ( (txobj= bitcoin_txcreate(coin,locktime)) != 0 )
{
iguana_createvins(myinfo,coin,txobj,vins);
if ( iguana_addressvalidate(coin,&addrtype,rmd160,coinaddr) < 0 )
{
free_json(vins), free_json(privkeys), free_json(txobj);
printf("illegal destination address.(%s)\n",coinaddr);
return(0);
}
spendlen = bitcoin_standardspend(spendscript,0,rmd160);
bitcoin_txoutput(coin,txobj,spendscript,spendlen,satoshis);
if ( change > 0 )
{
if ( iguana_addressvalidate(coin,&addrtype,rmd160,changeaddr) < 0 )
{
free_json(vins), free_json(privkeys), free_json(txobj);
printf("illegal destination address.(%s)\n",changeaddr);
return(0);
}
spendlen = bitcoin_standardspend(spendscript,0,rmd160);
bitcoin_txoutput(coin,txobj,spendscript,spendlen,change);
}
if ( (rawtx= bitcoin_json2hex(myinfo,coin,&txid,txobj,0)) != 0 )
{
if ( (numinputs= cJSON_GetArraySize(vins)) > 0 && (V= calloc(numinputs,sizeof(*V))) != 0 )
{
memset(&msgtx,0,sizeof(msgtx));
if ( iguana_signrawtransaction(myinfo,coin,&msgtx,&signedtx,&signedtxid,V,numinputs,rawtx,vins,privkeys) > 0 )
{
for (i=0; i<num; i++)
{
value = unspents[(i << 1) + 1];
if ( value == -1 )
iguana_utxofind(coin,(int32_t)(unspents[i << 1] >> 32),(uint32_t)unspents[i << 1],&RTspentflag,1);
}
*completedp = 1;
}
else printf("signrawtransaction incomplete\n");
free(V);
}
free(rawtx);
}
free_json(txobj);
}
free_json(privkeys);
}
free_json(vins);
}
return(signedtx);
}
char *sendtoaddress(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr,uint64_t satoshis,uint64_t txfee,char *comment,char *comment2,int32_t minconf,char *account)
{
uint8_t addrtype,rmd160[20]; int32_t i,j,num,completed,numwaddrs; struct iguana_waddress **waddrs,*waddr; uint64_t *unspents,value,avail=0; char *signedtx = 0; cJSON *retjson;
//sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to] <amount> is a real and is rounded to 8 decimal places. Returns the transaction ID <txid> if successful. Y
if ( coinaddr != 0 && coinaddr[0] != 0 && satoshis != 0 )
{
if ( iguana_addressvalidate(coin,&addrtype,rmd160,coinaddr) < 0 )
return(clonestr("{\"error\":\"invalid coin address\"}"));
waddrs = (struct iguana_waddress **)coin->blockspace;
numwaddrs = iguana_unspentslists(myinfo,coin,waddrs,(int32_t)(sizeof(coin->blockspace)/sizeof(*waddrs)),satoshis,minconf,0);
numwaddrs = iguana_unspentslists(myinfo,coin,waddrs,(int32_t)(sizeof(coin->blockspace)/sizeof(*waddrs)),(uint64_t)1 << 62,minconf,account);
if ( numwaddrs > 0 )
{
unspents = (uint64_t *)((long)coin->blockspace + sizeof(*waddrs)*numwaddrs);
for (i=0; i<numwaddrs; i++)
for (i=num=0; i<numwaddrs; i++)
{
if ( (waddr= waddrs[i]) != 0 && waddr->numunspents > 0 )
{
for (j=0; j<waddr->numunspents; j++)
printf("([%d].u%u) ",(uint32_t)(unspents[i]>>32),(uint32_t)unspents[i]);
{
if ( (value= iguana_unspentavail(coin,waddr->unspents[j],minconf,coin->longestchain)) != 0 )
{
unspents[num << 1] = waddr->unspents[j];
unspents[(num << 1) + 1] = value;
num++;
avail += value;
printf("([%d].u%u) ",(uint32_t)(waddr->unspents[j]>>32),(uint32_t)waddr->unspents[j]);
}
}
printf("(%s %.8f)\n",waddr->coinaddr,dstr(waddr->balance));
}
}
}
printf("need to generate send %.8f to %s [%s] [%s] using numaddrs.%d numunspents.%d\n",dstr(satoshis),coinaddr,comment!=0?comment:"",comment2!=0?comment2:"",numwaddrs,numunspents);
/*if ( iguana_signrawtransaction(myinfo,coin,&msgtx,&signedtx,&signedtxid,struct vin_info *V,int32_t numinputs,rawtx,vins,privkeys) > 0 )
{
}*/
if ( avail < satoshis+txfee )
return(clonestr("{\"error\":\"not enough funds\"}"));
else if ( (signedtx= iguana_signunspents(myinfo,coin,&completed,coinaddr,satoshis,coin->changeaddr,txfee,unspents,num)) != 0 )
{
retjson = cJSON_CreateObject();
jaddstr(retjson,"result",signedtx);
jadd(retjson,"complete",completed != 0 ? jtrue() : jfalse());
free(signedtx);
return(jprint(retjson,1));
} else return(clonestr("{\"error\":\"couldnt create signedtx\"}"));
} else return(clonestr("{\"error\":\"no funded wallet addresses\"}"));
}
return(clonestr("{\"error\":\"need address and amount\"}"));
}
@ -373,7 +577,7 @@ HASH_AND_TWOINTS(bitcoinrpc,gettxout,txid,vout,mempool)
{
if ( height >= 0 && height < coin->longestchain && (bp= coin->bundles[height / coin->chain->bundlesize]) != 0 )
{
ramchain = (bp == coin->current) ? &coin->RTramchain : &bp->ramchain;
ramchain = &bp->ramchain;
if ( (rdata= ramchain->H.data) != 0 )
{
U = RAMCHAIN_PTR(rdata,Uoffset);
@ -774,7 +978,7 @@ S_D_SS(bitcoinrpc,sendtoaddress,address,amount,comment,comment2)
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
iguana_unspentset(myinfo,coin);
return(sendtoaddress(myinfo,coin,address,amount * SATOSHIDEN,comment,comment2,coin->minconfirms,0));
return(sendtoaddress(myinfo,coin,address,amount * SATOSHIDEN,coin->txfee,comment,comment2,coin->minconfirms,0));
}
SS_D_I_SS(bitcoinrpc,sendfrom,fromaccount,toaddress,amount,minconf,comment,comment2)
@ -785,7 +989,7 @@ SS_D_I_SS(bitcoinrpc,sendfrom,fromaccount,toaddress,amount,minconf,comment,comme
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
iguana_unspentset(myinfo,coin);
return(sendtoaddress(myinfo,coin,toaddress,amount * SATOSHIDEN,comment,comment2,minconf,fromaccount));
return(sendtoaddress(myinfo,coin,toaddress,amount * SATOSHIDEN,coin->txfee,comment,comment2,minconf,fromaccount));
}
S_A_I_S(bitcoinrpc,sendmany,fromaccount,payments,minconf,comment)
@ -806,7 +1010,7 @@ S_A_I_S(bitcoinrpc,sendmany,fromaccount,payments,minconf,comment)
amount = jdouble(item,0);
val = amount * SATOSHIDEN;
printf("(%s %.8f) ",coinaddr,dstr(val));
if ( (str= sendtoaddress(myinfo,coin,coinaddr,val,comment,"",minconf,fromaccount)) != 0 )
if ( (str= sendtoaddress(myinfo,coin,coinaddr,val,coin->txfee,comment,"",minconf,fromaccount)) != 0 )
{
free(str);
}

2
iguana/iguana_realtime.c

@ -319,7 +319,7 @@ int32_t iguana_realtime_update(struct iguana_info *coin)
flag++;
coin->blocks.RO[bp->bundleheight+bundlei] = block->RO;
coin->RTheight++;
printf(">>>> RT.%d hwm.%d L.%d T.%d U.%d S.%d P.%d X.%d -> size.%ld\n",coin->RTheight,coin->blocks.hwmchain.height,coin->longestchain,dest->H.txidind,dest->H.unspentind,dest->H.spendind,dest->pkind,dest->externalind,(long)dest->H.data->allocsize);
//printf(">>>> RT.%d hwm.%d L.%d T.%d U.%d S.%d P.%d X.%d -> size.%ld\n",coin->RTheight,coin->blocks.hwmchain.height,coin->longestchain,dest->H.txidind,dest->H.unspentind,dest->H.spendind,dest->pkind,dest->externalind,(long)dest->H.data->allocsize);
if ( coin->RTramchain.H.data != 0 )
coin->RTramchain.H.data->numblocks = bundlei + 1;
else break;

293
iguana/iguana_secp.c

@ -362,7 +362,7 @@ int32_t bitcoin_rangeproof(void *ctx,uint8_t *proof,uint8_t *commit,bits256 blin
return(retval);
}
/*
/*
* The intended procedure for creating a multiparty signature is:
* - Each signer S[i] with private key x[i] and public key Q[i] runs
* secp256k1_schnorr_generate_nonce_pair to produce a pair (k[i],R[i]) of private/public nonces.
@ -589,294 +589,3 @@ int32_t iguana_schnorr_test(void *ctx)
return(errs);
}
#ifdef oldway
#include "../includes/openssl/ec.h"
#include "../includes/openssl/ecdsa.h"
#include "../includes/openssl/obj_mac.h"
static const char base58_chars[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
struct bp_key { EC_KEY *k; };
EC_KEY *oldbitcoin_privkeyset(uint8_t *oddevenp,bits256 *pubkeyp,bits256 privkey)
{
BIGNUM *bn; BN_CTX *ctx = NULL; uint8_t *ptr,tmp[33]; EC_POINT *pub_key = NULL; const EC_GROUP *group;
EC_KEY *KEY = EC_KEY_new_by_curve_name(NID_secp256k1);
*oddevenp = 0;
EC_KEY_set_conv_form(KEY,POINT_CONVERSION_COMPRESSED);
{
if ( (group= EC_KEY_get0_group(KEY)) != 0 && (ctx= BN_CTX_new()) != 0 )
{
if ( (pub_key= EC_POINT_new(group)) != 0 )
{
if ( (bn= BN_bin2bn(privkey.bytes,sizeof(privkey),BN_new())) != 0 )
{
if ( EC_POINT_mul(group,pub_key,bn,NULL,NULL,ctx) > 0 )
{
EC_KEY_set_private_key(KEY,bn);
EC_KEY_set_public_key(KEY,pub_key);
ptr = tmp;
i2o_ECPublicKey(KEY,&ptr);
*oddevenp = tmp[0];
memcpy(pubkeyp->bytes,&tmp[1],sizeof(*pubkeyp));
}
BN_clear_free(bn);
}
EC_POINT_free(pub_key);
}
BN_CTX_free(ctx);
}
}
return(KEY);
}
int32_t oldbitcoin_verify(uint8_t *sig,int32_t siglen,uint8_t *data,int32_t datalen,uint8_t *pubkey,int32_t len)
{
ECDSA_SIG *esig; int32_t retval = -1; uint8_t tmp[33],*ptr,*sigptr = sig; EC_KEY *KEY = 0;
if ( len < 0 )
return(-1);
if ( (esig= ECDSA_SIG_new()) != 0 )
{
if ( d2i_ECDSA_SIG(&esig,(const uint8_t **)&sigptr,siglen) != 0 )
{
if ( (KEY= EC_KEY_new_by_curve_name(NID_secp256k1)) != 0 )
{
EC_KEY_set_conv_form(KEY,POINT_CONVERSION_COMPRESSED);
if ( len == 32 )
{
memcpy(tmp+1,pubkey,len);
for (tmp[0]=2; tmp[0]<=3; tmp[0]++)
{
ptr = tmp;
o2i_ECPublicKey(&KEY,(const uint8_t **)&ptr,33);
if ( ECDSA_do_verify(data,datalen,esig,KEY) > 0 )
{
retval = 0;
break;
}
}
}
else
{
ptr = pubkey;
o2i_ECPublicKey(&KEY,(const uint8_t **)&ptr,len);
if ( ECDSA_do_verify(data,datalen,esig,KEY) > 0 )
retval = 0;
}
EC_KEY_free(KEY);
}
}
ECDSA_SIG_free(esig);
}
return(retval);
}
int32_t oldbitcoin_sign(uint8_t *sig,int32_t maxlen,uint8_t *data,int32_t datalen,bits256 privkey)
{
EC_KEY *KEY; uint8_t oddeven; bits256 pubkey; uint8_t *ptr; int32_t siglen,retval = -1;
ECDSA_SIG *SIG; BN_CTX *ctx; const EC_GROUP *group; BIGNUM *order,*halforder;
if ( (KEY= oldbitcoin_privkeyset(&oddeven,&pubkey,privkey)) != 0 )
{
if ( (SIG= ECDSA_do_sign(data,datalen,KEY)) != 0 )
{
ctx = BN_CTX_new();
BN_CTX_start(ctx);
group = EC_KEY_get0_group(KEY);
order = BN_CTX_get(ctx);
halforder = BN_CTX_get(ctx);
EC_GROUP_get_order(group,order,ctx);
BN_rshift1(halforder,order);
if ( BN_cmp(SIG->s,halforder) > 0 )
{
// enforce low S values, by negating the value (modulo the order) if above order/2.
BN_sub(SIG->s,order,SIG->s);
}
ptr = 0;
siglen = i2d_ECDSA_SIG(SIG,&ptr);
if ( ptr != 0 )
{
if ( siglen > 0 )
{
memcpy(sig,ptr,siglen);
retval = siglen;
}
free(ptr);
}
BN_CTX_end(ctx);
BN_CTX_free(ctx);
ECDSA_SIG_free(SIG);
}
//if ( ECDSA_sign(0,data,datalen,sig,&siglen,KEY) > 0 && siglen <= maxlen )
// retval = siglen;
EC_KEY_free(KEY);
}
return(retval);
}
bits256 oldbitcoin_pubkey33(void *_ctx,uint8_t *data,bits256 privkey)
{
uint8_t oddeven,data2[65]; size_t plen; bits256 pubkey; secp256k1_pubkey secppub; secp256k1_context *ctx;
EC_KEY *KEY;
if ( (KEY= oldbitcoin_privkeyset(&oddeven,&pubkey,privkey)) != 0 )
{
data[0] = oddeven;
memcpy(data+1,pubkey.bytes,sizeof(pubkey));
EC_KEY_free(KEY);
if ( (ctx= secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)) != 0 )
{
if ( secp256k1_ec_pubkey_create(ctx,&secppub,privkey.bytes) > 0 )
{
plen = 33;
secp256k1_ec_pubkey_serialize(ctx,data2,&plen,&secppub,1);
if ( memcmp(data2,data,plen) != 0 )
printf("pubkey compare error plen.%d\n",(int32_t)plen);
else printf("pubkey verified\n");
} //else printf("error secp256k1_ec_pubkey_create\n");
secp256k1_context_destroy(ctx);
}
} else memset(pubkey.bytes,0,sizeof(pubkey));
return(pubkey);
}
void bn_mpi2bn(BIGNUM *vo,uint8_t *data,int32_t datalen)
{
uint8_t vch2[64 + 4]; uint32_t i,vch2_len = (int32_t)datalen + 4;
if ( datalen < sizeof(vch2) )
{
vch2[0] = (datalen >> 24) & 0xff;
vch2[1] = (datalen >> 16) & 0xff;
vch2[2] = (datalen >> 8) & 0xff;
vch2[3] = (datalen >> 0) & 0xff;
for (i=0; i<datalen; i++)
vch2[4 + datalen - i - 1] = data[i];
BN_mpi2bn(vch2,vch2_len,vo);
}
}
int32_t bn_bn2mpi(uint8_t *data,const BIGNUM *v)
{
uint8_t s_be[64]; int32_t i,sz = BN_bn2mpi(v,NULL);
if ( sz >= 4 && sz < sizeof(s_be) ) // get MPI format size
{
BN_bn2mpi(v,s_be);
// copy-swap MPI to little endian, sans 32-bit size prefix
sz -= 4;
for (i=0; i<sz; i++)
data[sz - i - 1] = s_be[i + 4];
}
return(sz);
}
int32_t oldbitcoin_base58decode(uint8_t *data,char *coinaddr)
{
int32_t bitcoin_base58decode_mpz(uint8_t *data,char *coinaddr);
uint32_t zeroes,be_sz=0,i,len; const char *p,*p1; BIGNUM bn58,bn,bnChar; uint8_t revdata[64]; BN_CTX *ctx;
ctx = BN_CTX_new();
BN_init(&bn58), BN_init(&bn), BN_init(&bnChar);
BN_set_word(&bn58,58), BN_set_word(&bn,0);
while ( isspace((uint32_t)(*coinaddr & 0xff)) )
coinaddr++;
for (p=coinaddr; *p; p++)
{
p1 = strchr(base58_chars,*p);
if ( p1 == 0 )
{
while (isspace((uint32_t)*p))
p++;
if ( *p != '\0' )
goto out;
break;
}
BN_set_word(&bnChar,(int32_t)(p1 - base58_chars));
if ( BN_mul(&bn,&bn,&bn58,ctx) == 0 || BN_add(&bn,&bn,&bnChar) == 0 )
goto out;
}
len = bn_bn2mpi(revdata,&bn);
if ( len >= 2 && revdata[len - 1] == 0 && revdata[len - 2] >= 0x80 )
len--;
zeroes = 0;
for (p=coinaddr; *p==base58_chars[0]; p++)
zeroes++;
be_sz = (uint32_t)len + (uint32_t)zeroes;
memset(data,0,be_sz);
for (i=0; i<len; i++)
data[i+zeroes] = revdata[len - 1 - i];
//printf("len.%d be_sz.%d zeroes.%d data[0] %02x\n",len,be_sz,zeroes,data[0]);
out:
BN_clear_free(&bn58), BN_clear_free(&bn), BN_clear_free(&bnChar);
BN_CTX_free(ctx);
{
int32_t checkval; uint8_t data2[256];
if ( (checkval= bitcoin_base58decode_mpz(data2,coinaddr)) != be_sz )
printf("base58 decode error checkval.%d != be_sz.%d\n",checkval,be_sz);
else if ( memcmp(data2,data,be_sz) != 0 )
{
for (i=0; i<be_sz; i++)
printf("%02x",data[i]);
printf(" data[%d]\n",be_sz);
for (i=0; i<be_sz; i++)
printf("%02x",data2[i]);
printf(" data\n");
printf("base58 decode data error\n");
}
else printf("base58 decode match\n");
}
return(be_sz);
}
char *oldbitcoin_base58encode(char *coinaddr,uint8_t *data_,int32_t datalen)
{
BIGNUM bn58,bn0,bn,dv,rem; BN_CTX *ctx; uint32_t i,n,flag=0; uint8_t swapbuf[512],rs[512];
const uint8_t *data = (void *)data_;
rs[0] = 0;
n = 0;
if ( datalen < (sizeof(swapbuf) >> 1) )
{
ctx = BN_CTX_new();
BN_init(&bn58), BN_init(&bn0), BN_init(&bn), BN_init(&dv), BN_init(&rem);
BN_set_word(&bn58,58);
BN_set_word(&bn0,0);
for (i=0; i<datalen; i++)
swapbuf[datalen - i - 1] = data[i];
swapbuf[datalen] = 0;
bn_mpi2bn(&bn,swapbuf,datalen+1);
while ( BN_cmp(&bn,&bn0) > 0 )
{
if ( BN_div(&dv,&rem,&bn,&bn58,ctx) == 0 )
{
flag = -1;
break;
}
BN_copy(&bn,&dv);
rs[n++] = base58_chars[BN_get_word(&rem)];
}
if ( flag == 0 )
{
for (i=0; i<datalen; i++)
{
if ( data[i] == 0 )
rs[n++] = base58_chars[0];
else break;
}
for (i=0; i<n; i++)
coinaddr[n - i - 1] = rs[i];
coinaddr[n] = 0;
}
BN_clear_free(&bn58), BN_clear_free(&bn0), BN_clear_free(&bn), BN_clear_free(&dv), BN_clear_free(&rem);
BN_CTX_free(ctx);
{
char *bitcoin_base58encode_mpz(char *coinaddr,uint8_t *data,int32_t datalen);
char checkaddr[64];
bitcoin_base58encode_mpz(checkaddr,data_,datalen);
if ( strcmp(checkaddr,coinaddr) != 0 )
printf("mpz base58 error (%s) vs (%s)\n",checkaddr,coinaddr);
else printf("mpz matches\n");
}
return(coinaddr);
}
return(0);
}
#endif

25
iguana/iguana_sign.c

@ -643,10 +643,10 @@ int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **
sig[siglen++] = sighash;
vp->signers[j].siglen = siglen;
/*for (i=0; i<siglen; i++)
printf("%02x",sig[i]);
printf(" sig, ");
for (i=0; i<plen; i++)
printf("%02x",vp->signers[j].pubkey[i]);*/
printf("%02x",sig[i]);
printf(" sig, ");
for (i=0; i<plen; i++)
printf("%02x",vp->signers[j].pubkey[i]);*/
// s2 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1;
char str[65]; printf(" SIGNEDTX.[%02x] siglen.%d sigtxid.%s\n",sig[siglen-1],siglen,bits256_str(str,sigtxid));
}
@ -844,14 +844,14 @@ int32_t iguana_vininfo_create(struct supernet_info *myinfo,struct iguana_info *c
}
}
/*for (i=0; i<msgtx->tx_out; i++)
{
if ( msgtx->vouts[i].pk_script != 0 )
{
for (j=0; j<msgtx->vouts[i].pk_scriptlen; j++)
printf("%02x",msgtx->vouts[i].pk_script[j]);
printf(" pk_script[%d]\n",i);
}
}*/
{
if ( msgtx->vouts[i].pk_script != 0 )
{
for (j=0; j<msgtx->vouts[i].pk_scriptlen; j++)
printf("%02x",msgtx->vouts[i].pk_script[j]);
printf(" pk_script[%d]\n",i);
}
}*/
return(len);
}
@ -1178,6 +1178,7 @@ int32_t iguana_signrawtransaction(struct supernet_info *myinfo,struct iguana_inf
}
}
}
free(serialized), free(serialized2), free(serialized3);
} else return(-1);
if ( txobj != 0 )
free_json(txobj);

52
iguana/iguana_unspents.c

@ -54,6 +54,19 @@ int32_t iguana_unspentindfind(struct iguana_info *coin,char *coinaddr,uint8_t *s
return(unspentind);
}
char *iguana_inputaddress(struct iguana_info *coin,char *coinaddr,cJSON *vinobj)
{
bits256 txid; int32_t vout,checkind,height;
if ( jobj(vinobj,"txid") != 0 && jobj(vinobj,"vout") != 0 )
{
txid = jbits256(vinobj,"txid");
vout = jint(vinobj,"vout");
if ( (checkind= iguana_unspentindfind(coin,coinaddr,0,0,0,&height,txid,vout,coin->bundlescount-1)) != 0 )
return(coinaddr);
}
return(0);
}
cJSON *ramchain_unspentjson(struct iguana_unspent *up,uint32_t unspentind)
{
cJSON *item = cJSON_CreateObject();
@ -137,7 +150,7 @@ struct iguana_pkhash *iguana_pkhashfind(struct iguana_info *coin,struct iguana_r
*ramchainp = ramchain;
*depositsp = ACCTS[pkind].total;
*lastunspentindp = ACCTS[pkind].lastunspentind;
printf("[%d] return pkind.%u of %u P.%p %.8f last.%u ACCTS.%p %p\n",i,pkind,numpkinds,P,dstr(*depositsp),*lastunspentindp,ACCTS,ramchain->A);
//printf("[%d] return pkind.%u of %u P.%p %.8f last.%u ACCTS.%p %p\n",i,pkind,numpkinds,P,dstr(*depositsp),*lastunspentindp,ACCTS,ramchain->A);
if ( P != 0 )
*p = P[pkind];
return(p);
@ -268,7 +281,7 @@ int32_t iguana_pkhasharray(struct supernet_info *myinfo,struct iguana_info *coin
}
if ( numunspentsp != 0 )
*numunspentsp = numunspents;
printf("numunspents.%d max.%d\n",numunspents,maxunspents);
//printf("numunspents.%d max.%d\n",numunspents,maxunspents);
*totalp += total;
return(n);
}
@ -359,17 +372,17 @@ int64_t iguana_unspentset(struct supernet_info *myinfo,struct iguana_info *coin)
}
}
}
printf("available %.8f\n",dstr(sum));
//printf("available %.8f\n",dstr(sum));
return(sum);
}
int32_t iguana_unspentslists(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waddress **waddrs,int32_t maxwaddrs,int64_t required,int32_t minconf,char *account)
{
int64_t remains; int32_t num = 0; struct iguana_waccount *wacct,*tmp; struct iguana_waddress *waddr,*tmp2;
remains = required * 1.1;
remains = required * 1.1 + coin->txfee;
HASH_ITER(hh,myinfo->wallet,wacct,tmp)
{
if ( account != 0 && strcmp(account,wacct->account) != 0 )
if ( account != 0 && strcmp(account,"*") != 0 && strcmp(account,wacct->account) != 0 )
continue;
HASH_ITER(hh,wacct->waddr,waddr,tmp2)
{
@ -389,3 +402,32 @@ int32_t iguana_unspentslists(struct supernet_info *myinfo,struct iguana_info *co
return(num);
}
int64_t iguana_unspentavail(struct iguana_info *coin,uint64_t hdrsi_unspentind,int32_t minconf,int32_t maxconf)
{
struct iguana_ramchain *ramchain; struct iguana_bundle *bp; int64_t RTspend; int32_t hdrsi,spentheight,spentflag; struct iguana_unspent *U,*u; uint32_t unspentind;
if ( (bp= coin->bundles[hdrsi_unspentind>>32]) == 0 )
return(-1);
hdrsi = (int16_t)(hdrsi_unspentind >> 32);
unspentind = (uint32_t)hdrsi_unspentind;
ramchain = (bp == coin->current) ? &coin->RTramchain : &bp->ramchain;
if ( (spentflag= iguana_spentflag(coin,&RTspend,&spentheight,ramchain,hdrsi,unspentind,0,minconf,maxconf,0)) > 0 )
{
printf("[%d].u%d was already spent ht.%d\n",hdrsi,(uint32_t)unspentind,spentheight);
return(-1);
}
else if ( spentflag == 0 )
{
U = RAMCHAIN_PTR(ramchain->H.data,Uoffset);
if ( unspentind > 0 && unspentind < ramchain->H.data->numunspents )
{
u = &U[unspentind];
return(u->value);
}
else
{
printf("illegal unspentind.%u vs %u [%d]\n",unspentind,ramchain->H.data->numunspents,bp->hdrsi);
return(-2);
}
}
else return(0);
}

97
iguana/iguana_volatiles.c

@ -31,7 +31,6 @@ struct iguana_hhaccount *iguana_hhaccountfind(struct iguana_info *coin,uint64_t
int32_t iguana_utxoupdate(struct iguana_info *coin,int16_t spent_hdrsi,uint32_t spent_unspentind,uint32_t spent_pkind,uint64_t spent_value,uint32_t spendind,uint32_t fromheight)
{
//static struct iguana_hhutxo *HHUTXO; static struct iguana_hhaccount *HHACCT; static uint32_t numHHUTXO,maxHHUTXO,numHHACCT,maxHHACCT;
struct iguana_hhutxo *hhutxo,*tmputxo; struct iguana_hhaccount *hhacct,*tmpacct; uint64_t uval,pval;
if ( spent_hdrsi < 0 )
{
@ -40,37 +39,20 @@ int32_t iguana_utxoupdate(struct iguana_info *coin,int16_t spent_hdrsi,uint32_t
{
HASH_ITER(hh,coin->utxotable,hhutxo,tmputxo)
{
//HASH_DEL(coin->utxotable,hhutxo);
hhutxo->u.lockedflag = 0;
hhutxo->u.spentflag = 0;
hhutxo->u.fromheight = 0;
hhutxo->u.prevunspentind = 0;
//free(hhutxo);
}
//coin->utxotable = 0;
}
if ( coin->accountstable != 0 )
{
HASH_ITER(hh,coin->accountstable,hhacct,tmpacct)
{
//HASH_DEL(coin->accountstable,hhacct);
hhacct->a.lastunspentind = 0;
hhacct->a.total = 0;
//free(hhacct);
}
//coin->accountstable = 0;
}
/*if ( HHUTXO != 0 )
{
free(HHUTXO);
maxHHUTXO = numHHUTXO = 0;
HHUTXO = 0;
}
if ( HHACCT != 0 )
{
free(HHACCT);
maxHHACCT = numHHACCT = 0;
HHACCT = 0;
}*/
return(0);
}
uval = ((uint64_t)spent_hdrsi << 32) | spent_unspentind;
@ -80,65 +62,84 @@ int32_t iguana_utxoupdate(struct iguana_info *coin,int16_t spent_hdrsi,uint32_t
printf("hhutxo.%p spentflag.%d\n",hhutxo,hhutxo->u.spentflag);
return(-1);
}
/*if ( 0 && numHHUTXO+1 >= maxHHUTXO )
{
maxHHUTXO += 1;
HHUTXO = realloc(HHUTXO,sizeof(*HHUTXO) * maxHHUTXO);
}*/
hhutxo = calloc(1,sizeof(*hhutxo));//&HHUTXO[numHHUTXO++], memset(hhutxo,0,sizeof(*hhutxo));
hhutxo = calloc(1,sizeof(*hhutxo));
hhutxo->uval = uval;
HASH_ADD_KEYPTR(hh,coin->utxotable,&hhutxo->uval,sizeof(hhutxo->uval),hhutxo);
if ( (hhacct= iguana_hhaccountfind(coin,pval)) == 0 )
{
/*if ( 0 && numHHACCT+1 >= maxHHACCT )
{
maxHHACCT += 1;
HHACCT = realloc(HHACCT,sizeof(*HHACCT) * maxHHACCT);
}*/
hhacct = calloc(1,sizeof(*hhacct)); // &HHACCT[numHHACCT++], memset(hhacct,0,sizeof(*hhacct));
hhacct = calloc(1,sizeof(*hhacct));
hhacct->pval = pval;
HASH_ADD_KEYPTR(hh,coin->accountstable,&hhacct->pval,sizeof(hhacct->pval),hhacct);
}
//printf("create hhutxo.%p hhacct.%p from.%d\n",hhutxo,hhacct,fromheight);
hhutxo->u.spentflag = 1;
hhutxo->u.lockedflag = 0;
hhutxo->u.fromheight = fromheight;
hhutxo->u.prevunspentind = hhacct->a.lastunspentind;
hhacct->a.lastunspentind = spent_unspentind;
hhacct->a.total += spent_value;
/*if ( iguana_hhutxofind(coin,uval) == 0 || iguana_hhaccountfind(coin,pval) == 0 )
{
printf("null hh find.(%ld %ld) %p %p\n",(long)uval,(long)pval,iguana_hhutxofind(coin,uval),iguana_hhaccountfind(coin,pval));
}*/
return(0);
}
int32_t iguana_spentflag(struct iguana_info *coin,int64_t *RTspendp,int32_t *spentheightp,struct iguana_ramchain *ramchain,int16_t spent_hdrsi,uint32_t spent_unspentind,int32_t height,int32_t minconf,int32_t maxconf,uint64_t amount)
struct iguana_utxo iguana_utxofind(struct iguana_info *coin,int16_t spent_hdrsi,uint32_t spent_unspentind,int32_t *RTspendflagp,int32_t lockflag)
{
uint32_t numunspents; struct iguana_hhutxo *hhutxo; struct iguana_utxo utxo; uint64_t confs,val,RTspend = 0;
*spentheightp = 0;
numunspents = ramchain->H.data->numunspents;
uint64_t val,uval; struct iguana_hhutxo *hhutxo; struct iguana_utxo utxo; struct iguana_ramchain *ramchain; struct iguana_bundle *bp;
*RTspendflagp = 0;
memset(&utxo,0,sizeof(utxo));
if ( (bp= coin->bundles[spent_hdrsi]) == 0 )
return(utxo);
ramchain = &bp->ramchain;
val = ((uint64_t)spent_hdrsi << 32) | spent_unspentind;
if ( spent_unspentind != 0 && spent_unspentind < numunspents )
if ( spent_unspentind > 0 && spent_unspentind < ramchain->H.data->numunspents )
{
if ( ramchain->Uextras != 0 )
{
utxo = ramchain->Uextras[spent_unspentind];
if ( lockflag != 0 )
{
if ( (hhutxo= iguana_hhutxofind(coin,val)) == 0 )
{
uval = ((uint64_t)spent_hdrsi << 32) | spent_unspentind;
if ( (hhutxo= iguana_hhutxofind(coin,uval)) != 0 && hhutxo->u.spentflag != 0 )
{
printf("iguana_hhutxofind warning: hhutxo.%p spentflag.%d\n",hhutxo,hhutxo->u.spentflag);
memset(&utxo,0,sizeof(utxo));
return(utxo);
}
hhutxo = calloc(1,sizeof(*hhutxo));
hhutxo->uval = uval;
HASH_ADD_KEYPTR(hh,coin->utxotable,&hhutxo->uval,sizeof(hhutxo->uval),hhutxo);
}
}
}
if ( ramchain->Uextras == 0 || utxo.spentflag == 0 )
{
//printf("check hhutxo [%d] u%u %p\n",spent_hdrsi,spent_unspentind,iguana_hhutxofind(coin,((uint64_t)202<<32)|3909240));
if ( (hhutxo= iguana_hhutxofind(coin,val)) != 0 )
{
if ( lockflag != 0 )
{
if ( hhutxo->u.lockedflag == 0 )
hhutxo->u.lockedflag = 1;
else printf("iguana_hhutxofind warning: locking already locked [%d].%u\n",spent_hdrsi,spent_unspentind);
}
utxo = hhutxo->u;
if ( utxo.spentflag != 0 )
RTspend = amount;
if ( utxo.spentflag != 0 || utxo.lockedflag != 0 )
*RTspendflagp = 1;
}
}
}
else
{
printf("illegal unspentind.%u vs %u hdrs.%d\n",spent_unspentind,numunspents,spent_hdrsi);
return(-1);
}
} else printf("illegal unspentind.%u vs %u hdrs.%d\n",spent_unspentind,ramchain->H.data->numunspents,spent_hdrsi);
return(utxo);
}
int32_t iguana_spentflag(struct iguana_info *coin,int64_t *RTspendp,int32_t *spentheightp,struct iguana_ramchain *ramchain,int16_t spent_hdrsi,uint32_t spent_unspentind,int32_t height,int32_t minconf,int32_t maxconf,uint64_t amount)
{
uint32_t numunspents; int32_t RTspentflag; struct iguana_utxo utxo; uint64_t confs,RTspend = 0;
*spentheightp = 0;
numunspents = ramchain->H.data->numunspents;
utxo = iguana_utxofind(coin,spent_hdrsi,spent_unspentind,&RTspentflag,0);
if ( RTspentflag != 0 )
*RTspendp = (amount == 0) ? coin->txfee : amount;
if ( utxo.spentflag != 0 && utxo.fromheight == 0 )
{
printf("illegal unspentind.%u vs %u hdrs.%d zero fromheight?\n",spent_unspentind,numunspents,spent_hdrsi);

91
iguana/iguana_wallet.c

@ -771,6 +771,35 @@ int64_t iguana_waccountbalance(struct supernet_info *myinfo,struct iguana_info *
return(balance);
}
cJSON *iguana_privkeysjson(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *vins)
{
int32_t i,j,n,numinputs; struct iguana_waddress *waddr; struct iguana_waccount *wacct; char *addresses,*address,coinaddr[64]; cJSON *privkeys = cJSON_CreateArray();
if ( (numinputs= cJSON_GetArraySize(vins)) > 0 )
{
addresses = calloc(numinputs,64);
for (i=n=0; i<numinputs; i++)
{
if ( (address= iguana_inputaddress(coin,coinaddr,jitem(vins,i))) != 0 )
{
for (j=0; j<n; j++)
{
if ( strcmp(&addresses[64 * j],address) == 0 )
break;
}
if ( j == n )
strcpy(&addresses[64 * n++],address);
}
}
for (i=0; i<n; i++)
{
if ( (waddr= iguana_waddresssearch(myinfo,coin,&wacct,&addresses[i * 64])) != 0 )
jaddistr(privkeys,waddr->wifstr);
}
free(addresses);
}
return(privkeys);
}
#include "../includes/iguana_apidefs.h"
#include "../includes/iguana_apideclares.h"
@ -863,6 +892,7 @@ ZERO_ARGS(bitcoinrpc,getinfo)
jaddstr(retjson,"result","success");
jaddnum(retjson,"protocolversion",PROTOCOL_VERSION);
jaddnum(retjson,"kbfee",dstr(coin->txfee_perkb));
jaddnum(retjson,"txfee",dstr(coin->txfee));
jaddnum(retjson,"blocks",coin->blocks.hwmchain.height);
jaddnum(retjson,"longestchain",coin->longestchain);
jaddnum(retjson,"port",coin->chain->portp2p);
@ -911,9 +941,38 @@ STRING_ARG(bitcoinrpc,getnewaddress,account)
else return(clonestr("{\"error\":\"no wallet payload\"}"));
}
struct iguana_waddress *iguana_getaccountaddress(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *json,char *remoteaddr,char *coinaddr,char *account)
{
char *newstr,*retstr; struct iguana_waccount *wacct; struct iguana_waddress *waddr=0;
coinaddr[0] = 0;
if ( (wacct= iguana_waccountfind(myinfo,coin,account)) == 0 )
wacct = iguana_waccountcreate(myinfo,coin,account);
if ( wacct != 0 )
{
if ( (waddr= wacct->current) == 0 )
{
if ( (retstr= SuperNET_login(IGUANA_CALLARGS,myinfo->handle,myinfo->secret,myinfo->permanentfile,0)) != 0 )
{
free(retstr);
retstr = myinfo->decryptstr, myinfo->decryptstr = 0;
newstr = getnewaddress(myinfo,&waddr,coin,account,retstr);
if ( retstr != 0 )
scrubfree(retstr);
retstr = newstr;
} else return(0);
}
}
if ( waddr != 0 )
{
strcpy(coinaddr,waddr->coinaddr);
return(waddr);
}
return(0);
}
STRING_ARG(bitcoinrpc,getaccountaddress,account)
{
char *retstr,*newstr; struct iguana_waccount *wacct; struct iguana_waddress *waddr=0; cJSON *retjson;
char coinaddr[64]; struct iguana_waddress *waddr=0; cJSON *retjson;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
@ -921,30 +980,12 @@ STRING_ARG(bitcoinrpc,getaccountaddress,account)
myinfo->expiration++;
if ( account != 0 && account[0] != 0 )
{
if ( (wacct= iguana_waccountfind(myinfo,coin,account)) == 0 )
wacct = iguana_waccountcreate(myinfo,coin,account);
if ( wacct != 0 )
{
if ( (waddr= wacct->current) == 0 )
{
if ( (retstr= SuperNET_login(IGUANA_CALLARGS,myinfo->handle,myinfo->secret,myinfo->permanentfile,0)) != 0 )
{
free(retstr);
retstr = myinfo->decryptstr, myinfo->decryptstr = 0;
printf("loginstr.(%s)\n",retstr);
newstr = getnewaddress(myinfo,&waddr,coin,account,retstr);
if ( retstr != 0 )
scrubfree(retstr);
retstr = newstr;
} else return(clonestr("{\"error\":\"no wallet payload\"}"));
}
if ( waddr != 0 )
retjson = iguana_waddressjson(0,waddr);
else return(clonestr("{\"error\":\"couldnt create address\"}"));
jaddstr(retjson,"account",account);
jaddstr(retjson,"result","success");
return(jprint(retjson,1));
} else return(clonestr("{\"error\":\"cant find account\"}"));
if ( (waddr= iguana_getaccountaddress(myinfo,coin,json,remoteaddr,coinaddr,account)) != 0 )
retjson = iguana_waddressjson(0,waddr);
else return(clonestr("{\"error\":\"couldnt create address\"}"));
jaddstr(retjson,"account",account);
jaddstr(retjson,"result","success");
return(jprint(retjson,1));
}
return(clonestr("{\"error\":\"no account specified\"}"));
}

2
iguana/tests/decoderawtransaction

@ -1 +1 @@
curl --url "http://127.0.0.1:7778" --data "{\"method\":\"decoderawtransaction\",\"params\":[\"0100000095f4265701f6d17d847b7096cdd9b79e4df4b74aabb9ac34b7abd4f9fce19d761e97cca0e8000000006b483045022100929efad52915fc1033f5266eb7e9b7b8d55422894aabba1a0d5deda8ccf591d10220674776a3c760b3ad6972f42fb355bc0552df9f7c95d04ef9977b825171c94d37012102d14a195654f536df6dfe5a38278d1b470d00f17de78eeb5ce9e9eea9edb2c212ffffffff0240420f00000000001976a91410acba3a841fae68aba4b5ff162714c493bcc04e88acd0300e00000000001976a914d8b8c039206af6cec82bca950f592801e62808cb88ac00000000\"]}"
curl --url "http://127.0.0.1:7778" --data "{\"method\":\"decoderawtransaction\",\"params\":[\"0100000030e82f570100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0210270000000000001976a91410acba3a841fae68aba4b5ff162714c493bcc04e88ac44c71d00000000001976a9141af1412c5e9f9ec862c91d55318330df1a02c64388ac00000000\"]}"

2
iguana/tests/sendrawtransaction

@ -1,2 +1,2 @@
curl --url "http://127.0.0.1:7778" --data "{\"method\":\"sendrawtransaction\",\"params\":[\"0100000095f4265701f6d17d847b7096cdd9b79e4df4b74aabb9ac34b7abd4f9fce19d761e97cca0e800000000484730440220657fca67d3bbcb2e798de2119dc809e2245501a70fd97305dab958d0e69a4bc402205309c7f5eb7fa4e1c796eba9b2bba6c898eb8132be96bb05a6592126861fadee01ffffffff0240420f00000000001976a91410acba3a841fae68aba4b5ff162714c493bcc04e88acd0300e00000000001976a914d8b8c039206af6cec82bca950f592801e62808cb88ac00000000\"]}"
curl --url "http://127.0.0.1:7778" --data "{\"method\":\"sendrawtransaction\",\"params\":[\"0100000064003057018e12b0b843b0dd8315d64c99988704fa04f056cbbc32ce2c495751a123569374010000006b483045022100ebf6e4ee261c373f877df38f562bd88366e466746c1b6556b1f58949bd7908aa022048220045986bc49564437cbce908463823d3cbda40914c0bc26474900277b16d012103f0953c6e2c2dfaf7c1da9c548b7b63e245b1666c7433156e659c666b4b7f768affffffff0210270000000000001976a91410acba3a841fae68aba4b5ff162714c493bcc04e88ac24791d00000000001976a9141af1412c5e9f9ec862c91d55318330df1a02c64388ac00000000\"]}"

Loading…
Cancel
Save