diff --git a/iguana/exchanges/CMakeLists.txt b/iguana/exchanges/CMakeLists.txt index 5d9baa819..2aa749888 100644 --- a/iguana/exchanges/CMakeLists.txt +++ b/iguana/exchanges/CMakeLists.txt @@ -1,5 +1,5 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -set(MM_SOURCES mm.c ../mini-gmp.c ../groestl.c ../segwit_addr.c ../keccak.c) +set(MM_SOURCES mm.c ../mini-gmp.c ../groestl.c ../segwit_addr.c ../keccak.c LP_etomic.c) set(MM_LIBS ${NANOMSG_LIBRARY} curl pthread libcrypto777 libjpeg libsecp256k1) add_executable(marketmaker-testnet ${MM_SOURCES}) add_executable(marketmaker-mainnet ${MM_SOURCES}) diff --git a/iguana/exchanges/LP_commands.c b/iguana/exchanges/LP_commands.c index 894f89393..3a87c751d 100644 --- a/iguana/exchanges/LP_commands.c +++ b/iguana/exchanges/LP_commands.c @@ -578,6 +578,14 @@ jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\ } return(clonestr("{\"error\":\"cant find coind\"}")); } +#ifndef NOTETOMIC + else if ( strcmp(method,"eth_withdraw") == 0 ) + { + if ( (ptr= LP_coinsearch(coin)) != 0 ) { + return LP_eth_withdraw(ptr, argjson); + } + } +#endif else if ( strcmp(method,"setconfirms") == 0 ) { int32_t n; diff --git a/iguana/exchanges/LP_etomic.c b/iguana/exchanges/LP_etomic.c index d5539f6c5..c18d0c28c 100644 --- a/iguana/exchanges/LP_etomic.c +++ b/iguana/exchanges/LP_etomic.c @@ -21,9 +21,7 @@ // // Created by artem on 24.01.18. // -#include "etomicswap/etomiclib.h" -#include "etomicswap/etomiccurl.h" -#include +#include "LP_etomic.h" int32_t LP_etomic_wait_for_confirmation(char *txId) { @@ -36,9 +34,9 @@ char *LP_etomicalice_send_fee(struct basilisk_swap *swap) satoshisToWei(amount, swap->myfee.I.amount); uint8arrayToHex(secretKey, swap->persistent_privkey.bytes, 32); if (strcmp(swap->I.alicestr,"ETH") == 0 ) { - return(sendEth(ETH_FEE_ACCEPTOR, amount, secretKey)); + return(sendEth(ETH_FEE_ACCEPTOR, amount, secretKey, 1)); } else { - return(sendErc20(swap->I.alicetomic, ETH_FEE_ACCEPTOR, amount, secretKey)); + return(sendErc20(swap->I.alicetomic, ETH_FEE_ACCEPTOR, amount, secretKey, 1)); } } @@ -136,12 +134,10 @@ char *LP_etomicalice_send_payment(struct basilisk_swap *swap) uint8_t LP_etomic_verify_alice_payment(struct basilisk_swap *swap, char *txId) { - /* if (waitForConfirmation(txId) < 0) { printf("Alice payment %s does not exist\n", txId); return(0); } - */ EthTxData data = getEthTxData(txId); if (strcmp(data.to, ETOMIC_ALICECONTRACT) != 0) { printf("Alice payment %s was sent to wrong address %s\n", txId, data.to); diff --git a/iguana/exchanges/LP_etomic.h b/iguana/exchanges/LP_etomic.h new file mode 100644 index 000000000..0e2927211 --- /dev/null +++ b/iguana/exchanges/LP_etomic.h @@ -0,0 +1,52 @@ +// +// Created by artem on 13.03.18. +// + +#ifndef SUPERNET_LP_ETOMIC_H +#define SUPERNET_LP_ETOMIC_H +#include "etomicswap/etomiclib.h" +#include "etomicswap/etomiccurl.h" +#include +#include "LP_include.h" + +int32_t LP_etomic_wait_for_confirmation(char *txId); + +char *LP_etomicalice_send_fee(struct basilisk_swap *swap); + +uint8_t LP_etomic_verify_alice_fee(struct basilisk_swap *swap); + +char *LP_etomicalice_send_payment(struct basilisk_swap *swap); + +uint8_t LP_etomic_verify_alice_payment(struct basilisk_swap *swap, char *txId); + +char *LP_etomicalice_reclaims_payment(struct LP_swap_remember *swap); + +char *LP_etomicbob_spends_alice_payment(struct LP_swap_remember *swap); + +char *LP_etomicbob_sends_deposit(struct basilisk_swap *swap); + +uint8_t LP_etomic_verify_bob_deposit(struct basilisk_swap *swap, char *txId); + +char *LP_etomicbob_refunds_deposit(struct LP_swap_remember *swap); + +char *LP_etomicbob_sends_payment(struct basilisk_swap *swap); + +uint8_t LP_etomic_verify_bob_payment(struct basilisk_swap *swap, char *txId); + +char *LP_etomicbob_reclaims_payment(struct LP_swap_remember *swap); + +char *LP_etomicalice_spends_bob_payment(struct LP_swap_remember *swap); + +char *LP_etomicalice_claims_bob_deposit(struct LP_swap_remember *swap); + +char *sendEthTx(struct basilisk_swap *swap, struct basilisk_rawtx *rawtx); + +int32_t LP_etomic_priv2addr(char *coinaddr,bits256 privkey); + +int32_t LP_etomic_priv2pub(uint8_t *pub64,bits256 privkey); + +int32_t LP_etomic_pub2addr(char *coinaddr,uint8_t pub64[64]); + +uint8_t LP_etomic_is_empty_tx_id(char *txId); + +#endif //SUPERNET_LP_ETOMIC_H diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index e2f454f9c..0b5b96092 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -266,7 +266,7 @@ struct basilisk_swapinfo #define BASILISK_ALICERECLAIM 9 #define BASILISK_ALICECLAIM 10 //0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0 -char *txnames[] = { "alicespend", "bobspend", "bobpayment", "alicepayment", "bobdeposit", "otherfee", "myfee", "bobrefund", "bobreclaim", "alicereclaim", "aliceclaim" }; +static char *txnames[] = { "alicespend", "bobspend", "bobpayment", "alicepayment", "bobdeposit", "otherfee", "myfee", "bobrefund", "bobreclaim", "alicereclaim", "aliceclaim" }; struct LP_swap_remember { @@ -577,5 +577,6 @@ int bech32_convert_bits(uint8_t *out,int32_t *outlen,int outbits,const uint8_t * int bech32_decode(char *hrp,uint8_t *data,int32_t *data_len,const char *input); int bech32_encode(char *output,const char *hrp,const uint8_t *data,int32_t data_len); void HashGroestl(void * buf, const void * pbegin, int len); +bits256 LP_privkey(char *symbol,char *coinaddr,uint8_t taddr); #endif diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index 9b6e346af..d4f39960a 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -85,6 +85,11 @@ void LP_millistats_update(struct LP_millistats *mp) } #include "LP_include.h" + +#ifndef NOTETOMIC +#include "LP_etomic.h" +#endif + portable_mutex_t LP_peermutex,LP_UTXOmutex,LP_utxomutex,LP_commandmutex,LP_cachemutex,LP_swaplistmutex,LP_forwardmutex,LP_pubkeymutex,LP_networkmutex,LP_psockmutex,LP_coinmutex,LP_messagemutex,LP_portfoliomutex,LP_electrummutex,LP_butxomutex,LP_reservedmutex,LP_nanorecvsmutex,LP_tradebotsmutex,LP_gcmutex,LP_inusemutex,LP_cJSONmutex,LP_logmutex,LP_statslogmutex,LP_tradesmutex,LP_commandQmutex,LP_blockinit_mutex,LP_pendswap_mutex,LP_listmutex; int32_t LP_canbind; char *Broadcaststr,*Reserved_msgs[2][1000]; diff --git a/iguana/exchanges/LP_swap.c b/iguana/exchanges/LP_swap.c index ae7274a65..fd6bffc64 100644 --- a/iguana/exchanges/LP_swap.c +++ b/iguana/exchanges/LP_swap.c @@ -107,8 +107,7 @@ depositspent.(f34e04ad74e290f63f3d0bccb7d0d50abfa54eea58de38816fdc596a19767add) alice.1 bob.0 */ - -#define TX_WAIT_TIMEOUT 180 +#define TX_WAIT_TIMEOUT 1800 uint32_t LP_atomic_locktime(char *base,char *rel) { @@ -735,7 +734,7 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3 sendbuf[sendlen++] = rawtx->I.datalen & 0xff; sendbuf[sendlen++] = (rawtx->I.datalen >> 8) & 0xff; sendbuf[sendlen++] = rawtx->I.redeemlen; - if ( rawtx->I.ethTxid[0] != 0 && strlen(rawtx->I.ethTxid) == 66 ) + if ( rawtx->I.ethTxid[0] != 0 && strlen(rawtx->I.ethTxid) == 66 ) { uint8_t ethTxidBytes[32]; // ETH txid always starts with 0x diff --git a/iguana/exchanges/LP_transaction.c b/iguana/exchanges/LP_transaction.c index 0547aca7d..20fae0156 100644 --- a/iguana/exchanges/LP_transaction.c +++ b/iguana/exchanges/LP_transaction.c @@ -1515,6 +1515,31 @@ char *LP_withdraw(struct iguana_info *coin,cJSON *argjson) return(jprint(retjson,1)); } +#ifndef NOTETOMIC + +char *LP_eth_withdraw(struct iguana_info *coin,cJSON *argjson) +{ + cJSON *retjson = cJSON_CreateObject(); + char *dest_addr, *tx_id, privkey_str[70], amount_str[100]; + int64_t amount; + bits256 privkey; + + dest_addr = jstr(argjson, "to"); + amount = get_cJSON_int(argjson, "amount"); + privkey = LP_privkey(coin->symbol, coin->smartaddr, coin->taddr); + uint8arrayToHex(privkey_str, privkey.bytes, 32); + satoshisToWei(amount_str, amount); + if (strcmp(coin->symbol, "ETH") == 0) { + tx_id = sendEth(dest_addr, amount_str, privkey_str, 0); + } else { + tx_id = sendErc20(coin->etomic, dest_addr, amount_str, privkey_str, 0); + } + jaddstr(retjson, "tx_id", tx_id); + return(jprint(retjson,1)); +} + +#endif + int32_t basilisk_rawtx_gen(void *ctx,char *str,uint32_t swapstarted,uint8_t *pubkey33,int32_t iambob,int32_t lockinputs,struct basilisk_rawtx *rawtx,uint32_t locktime,uint8_t *script,int32_t scriptlen,int64_t txfee,int32_t minconf,int32_t delay,bits256 privkey,uint8_t *changermd160,char *vinaddr) { struct iguana_info *coin; int32_t len,retval=-1; char *retstr,*hexstr; cJSON *argjson,*outputs,*item,*retjson,*obj; @@ -2054,10 +2079,6 @@ void basilisk_alicepayment(struct basilisk_swap *swap,struct iguana_info *coin,s basilisk_rawtx_gen(swap->ctx,"alicepayment",swap->I.started,swap->persistent_pubkey33,0,1,alicepayment,alicepayment->I.locktime,alicepayment->spendscript,alicepayment->I.spendlen,swap->I.Atxfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr); } -#ifndef NOTETOMIC -#include "LP_etomic.c" -#endif - int32_t basilisk_alicetxs(int32_t pairsock,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) { char coinaddr[64],alicestr[65],alicetomic[128]; int32_t retval = -1; struct iguana_info *coin; diff --git a/iguana/exchanges/LP_utxo.c b/iguana/exchanges/LP_utxo.c index 5f3d80008..a3d1aa482 100644 --- a/iguana/exchanges/LP_utxo.c +++ b/iguana/exchanges/LP_utxo.c @@ -620,6 +620,15 @@ cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electr { cJSON *array,*retjson,*item; bits256 zero; int32_t i,n; uint64_t balance = 0; memset(zero.bytes,0,sizeof(zero)); +#ifndef NOTETOMIC + if (coin->etomic[0] != 0) { + if (strcmp(coin->symbol, "ETH") == 0) { + balance = getEthBalance(coinaddr); + } else { + balance = getErc20BalanceSatoshi(coinaddr, coin->etomic); + } + } else +#endif if ( coin->electrum == 0 ) { if ( (array= LP_listunspent(coin->symbol,coinaddr,zero,zero)) != 0 ) diff --git a/iguana/exchanges/etomicswap/etomiccurl.c b/iguana/exchanges/etomicswap/etomiccurl.c index 2bc48201a..5d92ba320 100644 --- a/iguana/exchanges/etomicswap/etomiccurl.c +++ b/iguana/exchanges/etomicswap/etomiccurl.c @@ -106,7 +106,7 @@ cJSON *sendRpcRequest(char *method, cJSON *params) return result; } -char* sendRawTx(char* rawTx) +char* sendRawTxWaitConfirm(char* rawTx) { cJSON *params = cJSON_CreateArray(); cJSON_AddItemToArray(params, cJSON_CreateString(rawTx)); @@ -125,6 +125,23 @@ char* sendRawTx(char* rawTx) return txId; } +char* sendRawTx(char* rawTx) +{ + cJSON *params = cJSON_CreateArray(); + cJSON_AddItemToArray(params, cJSON_CreateString(rawTx)); + cJSON *resultJson = sendRpcRequest("eth_sendRawTransaction", params); + cJSON_Delete(params); + char *txId = NULL; + if (resultJson != NULL && is_cJSON_String(resultJson) && resultJson->valuestring != NULL) { + char* tmp = resultJson->valuestring; + txId = (char *) malloc(strlen(tmp) + 1); + strcpy(txId, tmp); + } + cJSON_Delete(resultJson); + pthread_mutex_unlock(&sendTxMutex); + return txId; +} + int64_t getNonce(char* address) { // we should lock this mutex and unlock it only when transaction was already sent. diff --git a/iguana/exchanges/etomicswap/etomiccurl.h b/iguana/exchanges/etomicswap/etomiccurl.h index 584ce00e1..6e5c87d47 100644 --- a/iguana/exchanges/etomicswap/etomiccurl.h +++ b/iguana/exchanges/etomicswap/etomiccurl.h @@ -37,6 +37,7 @@ typedef struct } EthTxData; char* sendRawTx(char* rawTx); +char* sendRawTxWaitConfirm(char* rawTx); char* ethCall(char* to, const char* data); int64_t getNonce(char* address); char* getEthBalanceRequest(char* address); diff --git a/iguana/exchanges/etomicswap/etomiclib.cpp b/iguana/exchanges/etomicswap/etomiclib.cpp index 368fbb3fc..f1f717038 100644 --- a/iguana/exchanges/etomicswap/etomiclib.cpp +++ b/iguana/exchanges/etomicswap/etomiclib.cpp @@ -59,7 +59,7 @@ char *approveErc20(ApproveErc20Input input) << toHex(toBigEndian(jsToU256(input.amount))); tx.data = jsToBytes(ss.str()); char* rawTx = signTx(tx, input.secret); - char* result = sendRawTx(rawTx); + char* result = sendRawTxWaitConfirm(rawTx); free(rawTx); return result; } @@ -84,7 +84,7 @@ char* aliceSendsEthPayment(AliceSendsEthPaymentInput input, BasicTxData txData) std::stringstream ss = aliceSendsEthPaymentData(input); tx.data = jsToBytes(ss.str()); char *rawTx = signTx(tx, txData.secretKey); - char *result = sendRawTx(rawTx); + char *result = sendRawTxWaitConfirm(rawTx); free(rawTx); return result; } @@ -127,7 +127,7 @@ char* aliceSendsErc20Payment(AliceSendsErc20PaymentInput input, BasicTxData txDa std::stringstream ss = aliceSendsErc20PaymentData(input); tx.data = jsToBytes(ss.str()); char* rawTx = signTx(tx, txData.secretKey); - char* result = sendRawTx(rawTx); + char* result = sendRawTxWaitConfirm(rawTx); free(rawTx); return result; } @@ -168,7 +168,7 @@ char* aliceReclaimsAlicePayment(AliceReclaimsAlicePaymentInput input, BasicTxDat << toHex(jsToBytes(input.bobSecret)); tx.data = jsToBytes(ss.str()); char* rawTx = signTx(tx, txData.secretKey); - char* result = sendRawTx(rawTx); + char* result = sendRawTxWaitConfirm(rawTx); free(rawTx); return result; } @@ -199,7 +199,7 @@ char* bobSpendsAlicePayment(BobSpendsAlicePaymentInput input, BasicTxData txData << toHex(jsToBytes(input.aliceSecret)); tx.data = jsToBytes(ss.str()); char* rawTx = signTx(tx, txData.secretKey); - char* result = sendRawTx(rawTx); + char* result = sendRawTxWaitConfirm(rawTx); free(rawTx); return result; } @@ -263,7 +263,7 @@ char* bobSendsErc20Deposit(BobSendsErc20DepositInput input, BasicTxData txData) std::stringstream ss = bobSendsErc20DepositData(input); tx.data = jsToBytes(ss.str()); char* rawTx = signTx(tx, txData.secretKey); - char* result = sendRawTx(rawTx); + char* result = sendRawTxWaitConfirm(rawTx); free(rawTx); return result; } @@ -303,7 +303,7 @@ char* bobRefundsDeposit(BobRefundsDepositInput input, BasicTxData txData) << toHex(jsToBytes(input.bobSecret)); tx.data = jsToBytes(ss.str()); char* rawTx = signTx(tx, txData.secretKey); - char* result = sendRawTx(rawTx); + char* result = sendRawTxWaitConfirm(rawTx); free(rawTx); return result; } @@ -332,7 +332,7 @@ char* aliceClaimsBobDeposit(AliceClaimsBobDepositInput input, BasicTxData txData << "000000000000000000000000"; tx.data = jsToBytes(ss.str()); char* rawTx = signTx(tx, txData.secretKey); - char* result = sendRawTx(rawTx); + char* result = sendRawTxWaitConfirm(rawTx); free(rawTx); return result; } @@ -355,7 +355,7 @@ char* bobSendsEthPayment(BobSendsEthPaymentInput input, BasicTxData txData) std::stringstream ss = bobSendsEthPaymentData(input); tx.data = jsToBytes(ss.str()); char* rawTx = signTx(tx, txData.secretKey); - char* result = sendRawTx(rawTx); + char* result = sendRawTxWaitConfirm(rawTx); free(rawTx); return result; } @@ -396,7 +396,7 @@ char* bobSendsErc20Payment(BobSendsErc20PaymentInput input, BasicTxData txData) std::stringstream ss = bobSendsErc20PaymentData(input); tx.data = jsToBytes(ss.str()); char* rawTx = signTx(tx, txData.secretKey); - char* result = sendRawTx(rawTx); + char* result = sendRawTxWaitConfirm(rawTx); free(rawTx); return result; } @@ -435,7 +435,7 @@ char* bobReclaimsBobPayment(BobReclaimsBobPaymentInput input, BasicTxData txData << "000000000000000000000000"; tx.data = jsToBytes(ss.str()); char* rawTx = signTx(tx, txData.secretKey); - char* result = sendRawTx(rawTx); + char* result = sendRawTxWaitConfirm(rawTx); free(rawTx); return result; } @@ -465,7 +465,7 @@ char* aliceSpendsBobPayment(AliceSpendsBobPaymentInput input, BasicTxData txData << toHex(jsToBytes(input.aliceSecret)); tx.data = jsToBytes(ss.str()); char* rawTx = signTx(tx, txData.secretKey); - char* result = sendRawTx(rawTx); + char* result = sendRawTxWaitConfirm(rawTx); free(rawTx); return result; } @@ -582,10 +582,10 @@ uint64_t weiToSatoshi(char *wei) return static_cast(satoshi); } -char *sendEth(char *to, char *amount, char *privKey) +char *sendEth(char *to, char *amount, char *privKey, uint8_t waitConfirm) { TransactionSkeleton tx; - char *from = privKey2Addr(privKey); + char *from = privKey2Addr(privKey), *result; tx.from = jsToAddress(from); tx.to = jsToAddress(to); tx.value = jsToU256(amount); @@ -595,7 +595,11 @@ char *sendEth(char *to, char *amount, char *privKey) free(from); char *rawTx = signTx(tx, privKey); - char *result = sendRawTx(rawTx); + if (waitConfirm == 0) { + result = sendRawTx(rawTx); + } else { + result = sendRawTxWaitConfirm(rawTx); + } free(rawTx); return result; } @@ -616,10 +620,10 @@ std::stringstream getErc20TransferData(char *tokenAddress, char *to, char *amoun return ss; } -char *sendErc20(char *tokenAddress, char *to, char *amount, char *privKey) +char *sendErc20(char *tokenAddress, char *to, char *amount, char *privKey, uint8_t waitConfirm) { TransactionSkeleton tx; - char *from = privKey2Addr(privKey); + char *from = privKey2Addr(privKey), *result; tx.from = jsToAddress(from); tx.to = jsToAddress(tokenAddress); tx.value = 0; @@ -632,7 +636,11 @@ char *sendErc20(char *tokenAddress, char *to, char *amount, char *privKey) tx.data = jsToBytes(ss.str()); char *rawTx = signTx(tx, privKey); - char *result = sendRawTx(rawTx); + if (waitConfirm == 0) { + result = sendRawTx(rawTx); + } else { + result = sendRawTxWaitConfirm(rawTx); + } free(rawTx); return result; } diff --git a/iguana/exchanges/etomicswap/etomiclib.h b/iguana/exchanges/etomicswap/etomiclib.h index fdc64ae59..9c476c5a9 100644 --- a/iguana/exchanges/etomicswap/etomiclib.h +++ b/iguana/exchanges/etomicswap/etomiclib.h @@ -178,8 +178,8 @@ void uint8arrayToHex(char *dest, uint8_t *input, int len); void satoshisToWei(char *dest, uint64_t input); uint64_t weiToSatoshi(char *wei); -char *sendEth(char *to, char *amount, char *privKey); -char *sendErc20(char *tokenAddress, char *to, char *amount, char *privKey); +char *sendEth(char *to, char *amount, char *privKey, uint8_t waitConfirm); +char *sendErc20(char *tokenAddress, char *to, char *amount, char *privKey, uint8_t waitConfirm); uint8_t verifyAliceErc20FeeData(char* tokenAddress, char *to, char *amount, char *data); // Your prototype or Definition