Browse Source

fix: iguana autosplit / acsplit issue

this was a most hard to find and hard to debug issue, bcz sometimes
iguana did splitfunds correctly and sometimes not. nobody tried to
help me to catch the "wrong state" in which it fails, despite all
provided instructions. i spent all night along to catch the state
of utxos in which splitfunds guarantee fails. so, i have only wallet.dat
state and just every acsplit try fails on it. this was a half of victory.

second stage was debugging iguana and komodod sources, adding printouts
for preimage calculation, printouts for hashes, printouts for everything,
launching gdb under VSCode and other things. and after spent ~24 hours
of continuous work i found root of the issue.

it was in spendamount (!) ... i found that dpow_gettxout returns
34.26707593 in "value" field. but after conversion to uint_64 it becomes
34.26707592 . for non-sapling enabled chains seems nothing hurts, but
since sapling activated in KMD and assetchains it's significantly.
bcz according to zip-243 https://github.com/zcash/zips/blob/master/zip-0243.rst
amount field is a part of preimage calculation. and as we have
wrong spendamount we have a wrong sighash when calc crypto_generichash_blake2b_salt_personal
with sig_hash_personal = ZCASH_SIG_HASH_SAPLING_PERSONALIZATION .

Look at the "Test vector 3" in ZIP-243 and amount field in preimage and
you will understand the bug.

Sometimes double -> uint64_t was fine and splitfunds is success, but
sometimes (depends on double representation of value) it was wrong and
splitfunds fails. That's why it was so hard to catch and fix.

But now, seems the issue is fixed!
blackjok3r
DeckerSU 6 years ago
parent
commit
37bbdbe52a
  1. 24
      iguana/iguana_sign.c

24
iguana/iguana_sign.c

@ -33,6 +33,24 @@ const unsigned char ZCASH_SIG_HASH_SAPLING_PERSONALIZATION[16] =
const unsigned char ZCASH_SIG_HASH_OVERWINTER_PERSONALIZATION[16] =
{ 'Z','c','a','s','h','S','i','g','H','a','s','h', '\x19', '\x1B', '\xA8', '\x5B' };
uint64_t amountfromvalue(double value) {
// http://c-faq.com/fp/round.html
/* double frac = value - (uint64_t)value;
double whole = value - frac;
char frac_str[64], whole_str[64], *stopstring;
snprintf(frac_str, sizeof(frac_str), "%.8f", frac);
snprintf(whole_str, sizeof(whole_str), "%.8f", whole);
frac = strtod(frac_str, &stopstring);
whole = strtod(whole_str, &stopstring);
frac = frac * SATOSHIDEN;
whole = whole * SATOSHIDEN;
return (uint64_t)whole + (uint64_t)frac;
*/
return (uint64_t)(value * SATOSHIDEN + 0.5);
}
int32_t iguana_rwjoinsplit(int32_t rwflag,uint8_t *serialized,struct iguana_msgjoinsplit *msg, uint32_t proof_size); // defined in iguana_msg.c
@ -1033,7 +1051,8 @@ int32_t iguana_rwmsgtx(struct iguana_info *coin,int32_t height,int32_t rwflag,cJ
struct supernet_info *myinfo = SuperNET_MYINFO(0); cJSON *jtxout = 0;
jtxout = dpow_gettxout(0, coin, msg->vins[i].prev_hash, msg->vins[i].prev_vout);
spendamount = jdouble(jtxout, "value") * SATOSHIDEN;
//spendamount = jdouble(jtxout, "value") * SATOSHIDEN;
spendamount = amountfromvalue(jdouble(jtxout, "value"));
//printf("JSON (txout): %s\n", cJSON_Print(jtxout));
//printf("spendamount = %.8f\n", dstr(spendamount));
free(jtxout);
@ -1355,7 +1374,8 @@ int32_t bitcoin_verifyvins(struct iguana_info *coin,int32_t height,bits256 *sign
struct supernet_info *myinfo = SuperNET_MYINFO(0); cJSON *jtxout = 0;
jtxout = dpow_gettxout(0, coin, msgtx->vins[vini].prev_hash, msgtx->vins[vini].prev_vout);
spendamount = jdouble(jtxout, "value") * SATOSHIDEN;
//spendamount = jdouble(jtxout, "value") * SATOSHIDEN;
spendamount = amountfromvalue(jdouble(jtxout, "value"));
//printf("JSON (txout): %s\n", cJSON_Print(jtxout));
//printf("spendamount = %.8f\n", dstr(spendamount));
free(jtxout);

Loading…
Cancel
Save