Browse Source

Merge pull request #689 from artemii235/etomic

ERC20 integration working. Tested on mainnet.
patch-3
jl777 7 years ago
committed by GitHub
parent
commit
7713ca6323
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 20
      CMakeLists.txt
  2. 19
      README.md
  3. 15
      cmake/DownloadProject.CMakeLists.cmake.in
  4. 182
      cmake/DownloadProject.cmake
  5. 17
      iguana/exchanges/CMakeLists.txt
  6. 7
      iguana/exchanges/LP_coins.c
  7. 8
      iguana/exchanges/LP_commands.c
  8. 337
      iguana/exchanges/LP_etomic.c
  9. 54
      iguana/exchanges/LP_etomic.h
  10. 5
      iguana/exchanges/LP_include.h
  11. 8
      iguana/exchanges/LP_nativeDEX.c
  12. 8
      iguana/exchanges/LP_portfolio.c
  13. 37
      iguana/exchanges/LP_remember.c
  14. 39
      iguana/exchanges/LP_swap.c
  15. 54
      iguana/exchanges/LP_transaction.c
  16. 5
      iguana/exchanges/LP_utxo.c
  17. 15
      iguana/exchanges/etomicswap/CMakeLists.txt
  18. 199
      iguana/exchanges/etomicswap/bob.c
  19. 312
      iguana/exchanges/etomicswap/etomiccurl.c
  20. 38
      iguana/exchanges/etomicswap/etomiccurl.h
  21. 437
      iguana/exchanges/etomicswap/etomiclib.cpp
  22. 69
      iguana/exchanges/etomicswap/etomiclib.h
  23. 2
      iguana/secp256k1/CMakeLists.txt
  24. 78
      iguana/secp256k1/src/secp256k1.c

20
CMakeLists.txt

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.5.1)
cmake_minimum_required(VERSION 3.9.6)
include("cmake/HunterGate.cmake")
HunterGate(
URL "https://github.com/ruslo/hunter/archive/v0.19.173.tar.gz"
@ -6,6 +6,24 @@ HunterGate(
LOCAL
)
project(SuperNET)
set(DEPS_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_EXTENSIONS Off)
include(cmake/DownloadProject.cmake)
# Download and install nanomsg at CMake configure time
download_project(PROJ nanomsg
GIT_REPOSITORY https://github.com/nanomsg/nanomsg.git
GIT_TAG 1.1.2
GIT_SHALLOW 1
GIT_PROGRESS 1
CMAKE_ARGS "-DNN_STATIC_LIB=ON -DNN_ENABLE_DOC=OFF -DNN_TESTS=OFF -DNN_TOOLS=OFF -DNN_ENABLE_NANOCAT=OFF -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_PREFIX}"
UPDATE_DISCONNECTED 1
)
find_library(NANOMSG_LIBRARY NAMES nanomsg PATHS ${DEPS_INSTALL_PREFIX}/lib)
include_directories("${CMAKE_SOURCE_DIR}")
add_subdirectory(cpp-ethereum)
add_subdirectory(iguana/exchanges)

19
README.md

@ -257,13 +257,14 @@ Execute the OSX deploy script:
The iguana binary and its linked libraries are in ```$HOME/tmp/iguana```.
# Cmake build of marketmaker with linked etomic lib for ETH/ERC20 atomic swaps:
0. `make sure g++-7 ln to /usr/bin/g++`
1. `make sure g++-7 ln to /usr/bin/g++`
1. `cd ~/SuperNET`
2. `git checkout dev`
3. `git submodule update --init --recursive`
4. `mkdir build`
5. `cd build`
6. `cmake ..`
7. `cmake --build . --target marketmaker`
8. `cd build/iguana/exchanges`
9. `./marketmaker`
1. `git checkout dev`
1. `git submodule update --init --recursive`
1. `mkdir build`
1. `cd build`
1. `cmake ..`
1. `cmake --build . --target marketmaker-testnet` for Ropsten Ethereum testnet.
1. `cmake --build . --target marketmaker-mainnet` for Ethereum mainnet.
1. `cd build/iguana/exchanges`
1. `./marketmaker-testnet` or `./marketmaker-mainnet`

15
cmake/DownloadProject.CMakeLists.cmake.in

@ -0,0 +1,15 @@
# Distributed under the OSI-approved MIT License. See accompanying
# file LICENSE or https://github.com/Crascit/DownloadProject for details.
cmake_minimum_required(VERSION 2.8.2)
project(${DL_ARGS_PROJ}-download NONE)
include(ExternalProject)
ExternalProject_Add(${DL_ARGS_PROJ}-download
${DL_ARGS_UNPARSED_ARGUMENTS}
SOURCE_DIR "${DL_ARGS_SOURCE_DIR}"
BINARY_DIR "${DL_ARGS_BINARY_DIR}"
BUILD_COMMAND ""
TEST_COMMAND ""
)

182
cmake/DownloadProject.cmake

@ -0,0 +1,182 @@
# Distributed under the OSI-approved MIT License. See accompanying
# file LICENSE or https://github.com/Crascit/DownloadProject for details.
#
# MODULE: DownloadProject
#
# PROVIDES:
# download_project( PROJ projectName
# [PREFIX prefixDir]
# [DOWNLOAD_DIR downloadDir]
# [SOURCE_DIR srcDir]
# [BINARY_DIR binDir]
# [QUIET]
# ...
# )
#
# Provides the ability to download and unpack a tarball, zip file, git repository,
# etc. at configure time (i.e. when the cmake command is run). How the downloaded
# and unpacked contents are used is up to the caller, but the motivating case is
# to download source code which can then be included directly in the build with
# add_subdirectory() after the call to download_project(). Source and build
# directories are set up with this in mind.
#
# The PROJ argument is required. The projectName value will be used to construct
# the following variables upon exit (obviously replace projectName with its actual
# value):
#
# projectName_SOURCE_DIR
# projectName_BINARY_DIR
#
# The SOURCE_DIR and BINARY_DIR arguments are optional and would not typically
# need to be provided. They can be specified if you want the downloaded source
# and build directories to be located in a specific place. The contents of
# projectName_SOURCE_DIR and projectName_BINARY_DIR will be populated with the
# locations used whether you provide SOURCE_DIR/BINARY_DIR or not.
#
# The DOWNLOAD_DIR argument does not normally need to be set. It controls the
# location of the temporary CMake build used to perform the download.
#
# The PREFIX argument can be provided to change the base location of the default
# values of DOWNLOAD_DIR, SOURCE_DIR and BINARY_DIR. If all of those three arguments
# are provided, then PREFIX will have no effect. The default value for PREFIX is
# CMAKE_BINARY_DIR.
#
# The QUIET option can be given if you do not want to show the output associated
# with downloading the specified project.
#
# In addition to the above, any other options are passed through unmodified to
# ExternalProject_Add() to perform the actual download, patch and update steps.
# The following ExternalProject_Add() options are explicitly prohibited (they
# are reserved for use by the download_project() command):
#
# CONFIGURE_COMMAND
# BUILD_COMMAND
# INSTALL_COMMAND
# TEST_COMMAND
#
# Only those ExternalProject_Add() arguments which relate to downloading, patching
# and updating of the project sources are intended to be used. Also note that at
# least one set of download-related arguments are required.
#
# If using CMake 3.2 or later, the UPDATE_DISCONNECTED option can be used to
# prevent a check at the remote end for changes every time CMake is run
# after the first successful download. See the documentation of the ExternalProject
# module for more information. It is likely you will want to use this option if it
# is available to you. Note, however, that the ExternalProject implementation contains
# bugs which result in incorrect handling of the UPDATE_DISCONNECTED option when
# using the URL download method or when specifying a SOURCE_DIR with no download
# method. Fixes for these have been created, the last of which is scheduled for
# inclusion in CMake 3.8.0. Details can be found here:
#
# https://gitlab.kitware.com/cmake/cmake/commit/bdca68388bd57f8302d3c1d83d691034b7ffa70c
# https://gitlab.kitware.com/cmake/cmake/issues/16428
#
# If you experience build errors related to the update step, consider avoiding
# the use of UPDATE_DISCONNECTED.
#
# EXAMPLE USAGE:
#
# include(DownloadProject)
# download_project(PROJ googletest
# GIT_REPOSITORY https://github.com/google/googletest.git
# GIT_TAG master
# UPDATE_DISCONNECTED 1
# QUIET
# )
#
# add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR})
#
#========================================================================================
set(_DownloadProjectDir "${CMAKE_CURRENT_LIST_DIR}")
include(CMakeParseArguments)
function(download_project)
set(options QUIET)
set(oneValueArgs
PROJ
PREFIX
DOWNLOAD_DIR
SOURCE_DIR
BINARY_DIR
# Prevent the following from being passed through
CONFIGURE_COMMAND
BUILD_COMMAND
INSTALL_COMMAND
TEST_COMMAND
)
set(multiValueArgs "")
cmake_parse_arguments(DL_ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
# Hide output if requested
if (DL_ARGS_QUIET)
set(OUTPUT_QUIET "OUTPUT_QUIET")
else()
unset(OUTPUT_QUIET)
message(STATUS "Downloading/updating ${DL_ARGS_PROJ}")
endif()
# Set up where we will put our temporary CMakeLists.txt file and also
# the base point below which the default source and binary dirs will be.
# The prefix must always be an absolute path.
if (NOT DL_ARGS_PREFIX)
set(DL_ARGS_PREFIX "${CMAKE_BINARY_DIR}")
else()
get_filename_component(DL_ARGS_PREFIX "${DL_ARGS_PREFIX}" ABSOLUTE
BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
endif()
if (NOT DL_ARGS_DOWNLOAD_DIR)
set(DL_ARGS_DOWNLOAD_DIR "${DL_ARGS_PREFIX}/${DL_ARGS_PROJ}-download")
endif()
# Ensure the caller can know where to find the source and build directories
if (NOT DL_ARGS_SOURCE_DIR)
set(DL_ARGS_SOURCE_DIR "${DL_ARGS_PREFIX}/${DL_ARGS_PROJ}-src")
endif()
if (NOT DL_ARGS_BINARY_DIR)
set(DL_ARGS_BINARY_DIR "${DL_ARGS_PREFIX}/${DL_ARGS_PROJ}-build")
endif()
set(${DL_ARGS_PROJ}_SOURCE_DIR "${DL_ARGS_SOURCE_DIR}" PARENT_SCOPE)
set(${DL_ARGS_PROJ}_BINARY_DIR "${DL_ARGS_BINARY_DIR}" PARENT_SCOPE)
# The way that CLion manages multiple configurations, it causes a copy of
# the CMakeCache.txt to be copied across due to it not expecting there to
# be a project within a project. This causes the hard-coded paths in the
# cache to be copied and builds to fail. To mitigate this, we simply
# remove the cache if it exists before we configure the new project. It
# is safe to do so because it will be re-generated. Since this is only
# executed at the configure step, it should not cause additional builds or
# downloads.
file(REMOVE "${DL_ARGS_DOWNLOAD_DIR}/CMakeCache.txt")
# Create and build a separate CMake project to carry out the download.
# If we've already previously done these steps, they will not cause
# anything to be updated, so extra rebuilds of the project won't occur.
# Make sure to pass through CMAKE_MAKE_PROGRAM in case the main project
# has this set to something not findable on the PATH.
configure_file("${_DownloadProjectDir}/DownloadProject.CMakeLists.cmake.in"
"${DL_ARGS_DOWNLOAD_DIR}/CMakeLists.txt")
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}"
-D "CMAKE_MAKE_PROGRAM:FILE=${CMAKE_MAKE_PROGRAM}"
.
RESULT_VARIABLE result
${OUTPUT_QUIET}
WORKING_DIRECTORY "${DL_ARGS_DOWNLOAD_DIR}"
)
if(result)
message(FATAL_ERROR "CMake step for ${DL_ARGS_PROJ} failed: ${result}")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} --build .
RESULT_VARIABLE result
${OUTPUT_QUIET}
WORKING_DIRECTORY "${DL_ARGS_DOWNLOAD_DIR}"
)
if(result)
message(FATAL_ERROR "Build step for ${DL_ARGS_PROJ} failed: ${result}")
endif()
endfunction()

17
iguana/exchanges/CMakeLists.txt

@ -1,7 +1,14 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_executable(marketmaker mm.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})
include_directories(../../crypto777)
target_sources(marketmaker PRIVATE ../mini-gmp.c)
target_sources(marketmaker PRIVATE ../groestl.c)
target_sources(marketmaker PRIVATE ../segwit_addr.c)
target_link_libraries(marketmaker PRIVATE nanomsg curl pthread m libcrypto777 libjpeg libsecp256k1 "-Wl,--allow-multiple-definition" etomiclib)
target_compile_definitions(marketmaker-testnet PRIVATE ETOMIC_TESTNET USE_STATIC_NANOMSG)
target_compile_definitions(marketmaker-mainnet PRIVATE USE_STATIC_NANOMSG)
if(UNIX)
target_link_libraries(marketmaker-testnet m)
target_link_libraries(marketmaker-mainnet m)
endif()
target_link_libraries(marketmaker-testnet ${MM_LIBS} etomiclib-testnet)
target_link_libraries(marketmaker-mainnet ${MM_LIBS} etomiclib-mainnet)

7
iguana/exchanges/LP_coins.c

@ -236,6 +236,13 @@ cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif)
jaddnum(item,"balance",dstr(balance));
jaddnum(item,"KMDvalue",dstr(LP_KMDvalue(coin,balance)));
}
#ifndef NOTETOMIC
else if (coin->etomic[0] != 0) {
balance = LP_etomic_get_balance(coin, coin->smartaddr);
jaddnum(item,"height",-1);
jaddnum(item,"balance",dstr(balance));
}
#endif
else
{
jaddnum(item,"height",-1);

8
iguana/exchanges/LP_commands.c

@ -611,6 +611,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;

337
iguana/exchanges/LP_etomic.c

@ -21,9 +21,58 @@
//
// Created by artem on 24.01.18.
//
#include "etomicswap/etomiclib.h"
#include "etomicswap/etomiccurl.h"
#include <inttypes.h>
#include "LP_etomic.h"
int32_t LP_etomic_wait_for_confirmation(char *txId)
{
return(waitForConfirmation(txId));
}
char *LP_etomicalice_send_fee(struct basilisk_swap *swap)
{
char amount[100], secretKey[70];
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, 1));
} else {
return(sendErc20(swap->I.alicetomic, ETH_FEE_ACCEPTOR, amount, secretKey, 1));
}
}
uint8_t LP_etomic_verify_alice_fee(struct basilisk_swap *swap)
{
if (waitForConfirmation(swap->otherfee.I.ethTxid) < 0) {
printf("Alice fee tx %s does not exist", swap->otherfee.I.ethTxid);
return(0);
}
EthTxData data = getEthTxData(swap->otherfee.I.ethTxid);
if (strcmp(data.from, swap->I.etomicdest) != 0) {
printf("Alice fee tx %s was sent from wrong address %s\n", swap->otherfee.I.ethTxid, data.from);
return(0);
}
if ( strcmp(swap->I.alicestr,"ETH") == 0 ) {
if (strcmp(data.to, ETH_FEE_ACCEPTOR) != 0) {
printf("Alice fee %s was sent to wrong address %s\n", swap->otherfee.I.ethTxid, data.to);
return(0);
}
uint64_t txValue = weiToSatoshi(data.valueHex);
if (txValue != swap->otherfee.I.amount) {
printf("Alice fee %s amount %" PRIu64 " is not equal to expected %" PRIu64 "\n", swap->otherfee.I.ethTxid, txValue, swap->otherfee.I.amount);
return(0);
}
return(1);
} else {
if (strcmp(data.to, swap->I.alicetomic) != 0) {
printf("Alice ERC20 fee %s token address %s is not equal to expected %s\n", swap->otherfee.I.ethTxid, data.to, swap->I.alicetomic);
return(0);
}
char weiAmount[70];
satoshisToWei(weiAmount, swap->otherfee.I.amount);
return(verifyAliceErc20FeeData(swap->I.alicetomic, ETH_FEE_ACCEPTOR, weiAmount, data.input));
}
}
char *LP_etomicalice_send_payment(struct basilisk_swap *swap)
{
@ -49,23 +98,94 @@ char *LP_etomicalice_send_payment(struct basilisk_swap *swap)
else
{
memset(&input20,0,sizeof(input20));
strcpy(input20.bobAddress, swap->I.etomicdest);
strcpy(input20.bobAddress, swap->I.etomicsrc);
uint8arrayToHex(input20.bobHash, swap->I.secretBn, 20);
uint8arrayToHex(input20.aliceHash, swap->I.secretAm, 20);
uint8arrayToHex(input20.dealId, swap->alicepayment.utxotxid.bytes, 32);
uint8arrayToHex(input20.dealId, swap->alicepayment.I.actualtxid.bytes, 32);
strcpy(input20.tokenAddress, swap->I.alicetomic);
satoshisToWei(input20.amount, swap->I.alicesatoshis);
strcpy(txData.from, swap->I.etomicsrc);
strcpy(txData.from, swap->I.etomicdest);
strcpy(txData.to, ETOMIC_ALICECONTRACT);
strcpy(txData.amount, "0");
uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32);
uint64_t allowance = getErc20Allowance(swap->I.etomicdest, ETOMIC_ALICECONTRACT, swap->I.alicetomic);
if (allowance < swap->I.alicesatoshis) {
printf("Alice token allowance is too low, setting new allowance\n");
ApproveErc20Input approveErc20Input;
strcpy(approveErc20Input.tokenAddress, swap->I.alicetomic);
strcpy(approveErc20Input.owner, swap->I.etomicdest);
strcpy(approveErc20Input.spender, ETOMIC_ALICECONTRACT);
char *tokenBalance = getErc20BalanceHexWei(swap->I.etomicdest, swap->I.alicetomic);
strcpy(approveErc20Input.amount, tokenBalance);
free(tokenBalance);
strcpy(approveErc20Input.secret, txData.secretKey);
char *allowTxId = approveErc20(approveErc20Input);
LP_etomic_wait_for_confirmation(allowTxId);
free(allowTxId);
}
return(aliceSendsErc20Payment(input20,txData));
}
}
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);
return(0);
}
if (strcmp(data.from, swap->I.etomicdest) != 0) {
printf("Alice payment %s was done from wrong address %s\n", txId, data.from);
return(0);
}
AliceSendsEthPaymentInput input; AliceSendsErc20PaymentInput input20;
if ( strcmp(swap->I.alicestr,"ETH") == 0 ) {
uint64_t paymentAmount = weiToSatoshi(data.valueHex);
if (paymentAmount != swap->I.alicesatoshis) {
printf("Alice payment amount %" PRIu64 " does not match expected %" PRIu64 "\n", paymentAmount, swap->I.alicesatoshis);
return(0);
}
memset(&input,0,sizeof(input));
strcpy(input.bobAddress, swap->I.etomicsrc);
uint8arrayToHex(input.bobHash, swap->I.secretBn, 20);
uint8arrayToHex(input.aliceHash, swap->I.secretAm, 20);
uint8arrayToHex(input.dealId, swap->alicepayment.I.actualtxid.bytes, 32);
return(verifyAliceEthPaymentData(input, data.input));
} else {
memset(&input20,0,sizeof(input20));
strcpy(input20.bobAddress, swap->I.etomicsrc);
uint8arrayToHex(input20.bobHash, swap->I.secretBn, 20);
uint8arrayToHex(input20.aliceHash, swap->I.secretAm, 20);
uint8arrayToHex(input20.dealId, swap->alicepayment.I.actualtxid.bytes, 32);
strcpy(input20.tokenAddress, swap->I.alicetomic);
satoshisToWei(input20.amount, swap->I.alicesatoshis);
return(verifyAliceErc20PaymentData(input20, data.input));
}
}
char *LP_etomicalice_reclaims_payment(struct LP_swap_remember *swap)
{
if (waitForConfirmation(swap->alicePaymentEthTx) < 0) {
printf("Alice ETH payment %s is not found, can't reclaim\n", swap->alicePaymentEthTx);
return NULL;
}
EthTxReceipt receipt = getEthTxReceipt(swap->alicePaymentEthTx);
if (strcmp(receipt.status, "0x1") != 0) {
printf("Alice payment receipt status failed, can't reclaim\n");
return NULL;
}
AliceReclaimsAlicePaymentInput input;
BasicTxData txData;
memset(&txData,0,sizeof(txData));
@ -77,14 +197,14 @@ char *LP_etomicalice_reclaims_payment(struct LP_swap_remember *swap)
privkey = LP_privkey(ecoin->symbol, ecoin->smartaddr, ecoin->taddr);
uint8arrayToHex(input.dealId, swap->txids[BASILISK_ALICEPAYMENT].bytes, 32);
satoshisToWei(input.amount, swap->values[BASILISK_ALICEPAYMENT]);
satoshisToWei(input.amount, swap->destamount);
if (swap->alicetomic[0] != 0) {
strcpy(input.tokenAddress, swap->alicetomic);
} else {
strcpy(input.tokenAddress, "0x0000000000000000000000000000000000000000");
}
strcpy(input.bobAddress, swap->etomicdest);
strcpy(input.bobAddress, swap->etomicsrc);
uint8arrayToHex(input.aliceHash, swap->secretAm, 20);
bits256 invertedSecret;
int32_t i;
@ -93,7 +213,7 @@ char *LP_etomicalice_reclaims_payment(struct LP_swap_remember *swap)
}
uint8arrayToHex(input.bobSecret, invertedSecret.bytes, 32);
strcpy(txData.from, swap->etomicsrc);
strcpy(txData.from, swap->etomicdest);
strcpy(txData.to, ETOMIC_ALICECONTRACT);
strcpy(txData.amount, "0");
uint8arrayToHex(txData.secretKey, privkey.bytes, 32);
@ -102,6 +222,15 @@ char *LP_etomicalice_reclaims_payment(struct LP_swap_remember *swap)
char *LP_etomicbob_spends_alice_payment(struct LP_swap_remember *swap)
{
if (waitForConfirmation(swap->alicePaymentEthTx) < 0) {
printf("Alice ETH payment %s is not found, can't spend\n", swap->alicePaymentEthTx);
return NULL;
}
EthTxReceipt receipt = getEthTxReceipt(swap->alicePaymentEthTx);
if (strcmp(receipt.status, "0x1") != 0) {
printf("Alice payment receipt status failed, can't spend\n");
return NULL;
}
BobSpendsAlicePaymentInput input;
BasicTxData txData;
@ -149,6 +278,7 @@ char *LP_etomicbob_sends_deposit(struct basilisk_swap *swap)
uint8arrayToHex(input.depositId, swap->bobdeposit.I.actualtxid.bytes, 32);
strcpy(input.aliceAddress, swap->I.etomicdest);
uint8arrayToHex(input.bobHash, swap->I.secretBn, 20);
input.lockTime = swap->bobdeposit.I.locktime;
strcpy(txData.from, swap->I.etomicsrc);
strcpy(txData.to, ETOMIC_BOBCONTRACT);
@ -161,17 +291,84 @@ char *LP_etomicbob_sends_deposit(struct basilisk_swap *swap)
uint8arrayToHex(input20.bobHash, swap->I.secretBn, 20);
satoshisToWei(input20.amount, swap->bobdeposit.I.amount);
strcpy(input20.tokenAddress, swap->I.bobtomic);
input20.lockTime = swap->bobdeposit.I.locktime;
strcpy(txData.from, swap->I.etomicsrc);
strcpy(txData.to, ETOMIC_BOBCONTRACT);
strcpy(txData.amount, "0");
uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32);
uint64_t allowance = getErc20Allowance(swap->I.etomicsrc, ETOMIC_BOBCONTRACT, swap->I.bobtomic);
if (allowance < swap->bobdeposit.I.amount) {
printf("Bob token allowance is too low, setting new allowance\n");
ApproveErc20Input approveErc20Input;
strcpy(approveErc20Input.tokenAddress, swap->I.bobtomic);
strcpy(approveErc20Input.owner, swap->I.etomicsrc);
strcpy(approveErc20Input.spender, ETOMIC_BOBCONTRACT);
char *tokenBalance = getErc20BalanceHexWei(swap->I.etomicsrc, swap->I.bobtomic);
strcpy(approveErc20Input.amount, tokenBalance);
free(tokenBalance);
strcpy(approveErc20Input.secret, txData.secretKey);
char *allowTxId = approveErc20(approveErc20Input);
LP_etomic_wait_for_confirmation(allowTxId);
free(allowTxId);
}
return bobSendsErc20Deposit(input20, txData);
}
}
uint8_t LP_etomic_verify_bob_deposit(struct basilisk_swap *swap, char *txId)
{
if (waitForConfirmation(txId) < 0) {
printf("Bob deposit txid %s does not exist\n", txId);
return(0);
}
EthTxData data = getEthTxData(txId);
if (strcmp(data.to, ETOMIC_BOBCONTRACT) != 0) {
printf("Bob deposit txid %s was sent to wrong address %s\n", txId, data.to);
return(0);
}
if (strcmp(data.from, swap->I.etomicsrc) != 0) {
printf("Bob deposit txid %s was sent from wrong address %s\n", txId, data.from);
return(0);
}
BobSendsEthDepositInput input;
BobSendsErc20DepositInput input20;
memset(&input,0,sizeof(input));
memset(&input20,0,sizeof(input20));
if ( strcmp(swap->I.bobstr,"ETH") == 0 ) {
uint64_t depositAmount = weiToSatoshi(data.valueHex);
if (depositAmount != swap->bobdeposit.I.amount) {
printf("Bob deposit %s amount %" PRIu64 " != expected %" PRIu64 "\n", txId, depositAmount, swap->bobdeposit.I.amount);
return(0);
}
uint8arrayToHex(input.depositId, swap->bobdeposit.I.actualtxid.bytes, 32);
strcpy(input.aliceAddress, swap->I.etomicdest);
uint8arrayToHex(input.bobHash, swap->I.secretBn, 20);
input.lockTime = swap->bobdeposit.I.locktime;
return verifyBobEthDepositData(input, data.input);
} else {
uint8arrayToHex(input20.depositId, swap->bobdeposit.I.actualtxid.bytes, 32);
strcpy(input20.aliceAddress, swap->I.etomicdest);
uint8arrayToHex(input20.bobHash, swap->I.secretBn, 20);
satoshisToWei(input20.amount, swap->bobdeposit.I.amount);
strcpy(input20.tokenAddress, swap->I.bobtomic);
input20.lockTime = swap->bobdeposit.I.locktime;
return verifyBobErc20DepositData(input20, data.input);
}
}
char *LP_etomicbob_refunds_deposit(struct LP_swap_remember *swap)
{
if (waitForConfirmation(swap->bobDepositEthTx) < 0) {
printf("Bob deposit %s is not found, can't refund\n", swap->bobDepositEthTx);
return NULL;
}
BobRefundsDepositInput input;
BasicTxData txData;
memset(&txData,0,sizeof(txData));
@ -183,9 +380,12 @@ char *LP_etomicbob_refunds_deposit(struct LP_swap_remember *swap)
privkey = LP_privkey(ecoin->symbol, ecoin->smartaddr, ecoin->taddr);
EthTxReceipt receipt = getEthTxReceipt(swap->bobDepositEthTx);
if (strcmp(receipt.status, "0x1") != 0) {
printf("Bob deposit %s receipt status failed, can't refund\n", swap->bobDepositEthTx);
return NULL;
}
uint8arrayToHex(input.depositId, swap->txids[BASILISK_BOBDEPOSIT].bytes, 32);
strcpy(input.aliceAddress, swap->etomicdest);
sprintf(input.aliceCanClaimAfter, "%" PRIu64, receipt.blockNumber + 960);
bits256 invertedSecret;
int32_t i;
@ -221,6 +421,7 @@ char *LP_etomicbob_sends_payment(struct basilisk_swap *swap)
uint8arrayToHex(input.paymentId, swap->bobpayment.I.actualtxid.bytes, 32);
strcpy(input.aliceAddress, swap->I.etomicdest);
uint8arrayToHex(input.aliceHash, swap->I.secretAm, 20);
input.lockTime = swap->bobpayment.I.locktime;
strcpy(txData.from, swap->I.etomicsrc);
strcpy(txData.to, ETOMIC_BOBCONTRACT);
@ -233,17 +434,83 @@ char *LP_etomicbob_sends_payment(struct basilisk_swap *swap)
uint8arrayToHex(input20.aliceHash, swap->I.secretAm, 20);
satoshisToWei(input20.amount, swap->bobpayment.I.amount);
strcpy(input20.tokenAddress, swap->I.bobtomic);
input20.lockTime = swap->bobpayment.I.locktime;
strcpy(txData.from, swap->I.etomicsrc);
strcpy(txData.to, ETOMIC_BOBCONTRACT);
strcpy(txData.amount, "0");
uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32);
uint64_t allowance = getErc20Allowance(swap->I.etomicsrc, ETOMIC_BOBCONTRACT, swap->I.bobtomic);
if (allowance < swap->bobpayment.I.amount) {
printf("Bob token allowance is too low, setting new allowance\n");
ApproveErc20Input approveErc20Input;
strcpy(approveErc20Input.tokenAddress, swap->I.bobtomic);
strcpy(approveErc20Input.owner, swap->I.etomicsrc);
strcpy(approveErc20Input.spender, ETOMIC_BOBCONTRACT);
char *tokenBalance = getErc20BalanceHexWei(swap->I.etomicsrc, swap->I.bobtomic);
strcpy(approveErc20Input.amount, tokenBalance);
free(tokenBalance);
strcpy(approveErc20Input.secret, txData.secretKey);
char *allowTxId = approveErc20(approveErc20Input);
LP_etomic_wait_for_confirmation(allowTxId);
free(allowTxId);
}
return bobSendsErc20Payment(input20, txData);
}
}
uint8_t LP_etomic_verify_bob_payment(struct basilisk_swap *swap, char *txId)
{
if (waitForConfirmation(txId) < 0) {
printf("Bob payment %s is not found\n", txId);
return 0;
}
EthTxData data = getEthTxData(txId);
if (strcmp(data.to, ETOMIC_BOBCONTRACT) != 0) {
printf("Bob payment %s was sent to wrong address %s\n", txId, data.to);
}
if (strcmp(data.from, swap->I.etomicsrc) != 0) {
printf("Bob payment %s was sent from wrong address %s\n", txId, data.from);
}
BobSendsEthPaymentInput input;
BobSendsErc20PaymentInput input20;
memset(&input,0,sizeof(input));
memset(&input20,0,sizeof(input20));
if ( strcmp(swap->I.bobstr,"ETH") == 0 ) {
uint64_t paymentAmount = weiToSatoshi(data.valueHex);
if (paymentAmount != swap->bobpayment.I.amount) {
printf("Bob payment %s amount %" PRIu64 " != expected %" PRIu64 "\n", txId, paymentAmount, swap->bobpayment.I.amount);
return(0);
}
uint8arrayToHex(input.paymentId, swap->bobpayment.I.actualtxid.bytes, 32);
strcpy(input.aliceAddress, swap->I.etomicdest);
uint8arrayToHex(input.aliceHash, swap->I.secretAm, 20);
input.lockTime = swap->bobpayment.I.locktime;
return verifyBobEthPaymentData(input, data.input);
} else {
uint8arrayToHex(input20.paymentId, swap->bobpayment.I.actualtxid.bytes, 32);
strcpy(input20.aliceAddress, swap->I.etomicdest);
uint8arrayToHex(input20.aliceHash, swap->I.secretAm, 20);
satoshisToWei(input20.amount, swap->bobpayment.I.amount);
strcpy(input20.tokenAddress, swap->I.bobtomic);
input20.lockTime = swap->bobpayment.I.locktime;
return verifyBobErc20PaymentData(input20, data.input);
}
}
char *LP_etomicbob_reclaims_payment(struct LP_swap_remember *swap)
{
if (waitForConfirmation(swap->bobPaymentEthTx) < 0) {
printf("Bob payment %s is not found, can't reclaim\n", swap->bobPaymentEthTx);
return NULL;
}
BobReclaimsBobPaymentInput input;
BasicTxData txData;
memset(&txData,0,sizeof(txData));
@ -255,9 +522,12 @@ char *LP_etomicbob_reclaims_payment(struct LP_swap_remember *swap)
privkey = LP_privkey(ecoin->symbol, ecoin->smartaddr, ecoin->taddr);
EthTxReceipt receipt = getEthTxReceipt(swap->bobPaymentEthTx);
if (strcmp(receipt.status, "0x1") != 0) {
printf("Bob payment receipt status failed, can't reclaim\n");
return NULL;
}
uint8arrayToHex(input.paymentId, swap->txids[BASILISK_BOBPAYMENT].bytes, 32);
strcpy(input.aliceAddress, swap->etomicdest);
sprintf(input.bobCanClaimAfter, "%" PRIu64, receipt.blockNumber + 480);
uint8arrayToHex(input.aliceHash, swap->secretAm, 20);
if (swap->bobtomic[0] != 0) {
@ -276,13 +546,20 @@ char *LP_etomicbob_reclaims_payment(struct LP_swap_remember *swap)
char *LP_etomicalice_spends_bob_payment(struct LP_swap_remember *swap)
{
if (waitForConfirmation(swap->bobPaymentEthTx) < 0) {
printf("Bob payment %s is not found, can't spend\n", swap->bobPaymentEthTx);
return NULL;
}
AliceSpendsBobPaymentInput input;
BasicTxData txData;
memset(&txData,0,sizeof(txData));
memset(&input,0,sizeof(input));
EthTxReceipt receipt = getEthTxReceipt(swap->bobPaymentEthTx);
if (strcmp(receipt.status, "0x1") != 0) {
printf("Bob payment %s receipt status failed, can't spend\n", swap->bobPaymentEthTx);
return NULL;
}
struct iguana_info *ecoin;
bits256 privkey;
ecoin = LP_coinfind("ETOMIC");
@ -290,7 +567,6 @@ char *LP_etomicalice_spends_bob_payment(struct LP_swap_remember *swap)
uint8arrayToHex(input.paymentId, swap->txids[BASILISK_BOBPAYMENT].bytes, 32);
satoshisToWei(input.amount, swap->values[BASILISK_BOBPAYMENT]);
sprintf(input.bobCanClaimAfter, "%" PRIu64, receipt.blockNumber + 480);
if (swap->bobtomic[0] != 0) {
strcpy(input.tokenAddress, swap->bobtomic);
@ -315,12 +591,20 @@ char *LP_etomicalice_spends_bob_payment(struct LP_swap_remember *swap)
char *LP_etomicalice_claims_bob_deposit(struct LP_swap_remember *swap)
{
if (waitForConfirmation(swap->bobDepositEthTx) < 0) {
printf("Bob deposit %s is not found, can't claim\n", swap->bobDepositEthTx);
return NULL;
}
AliceClaimsBobDepositInput input;
BasicTxData txData;
memset(&txData,0,sizeof(txData));
memset(&input,0,sizeof(input));
EthTxReceipt receipt = getEthTxReceipt(swap->bobDepositEthTx);
if (strcmp(receipt.status, "0x1") != 0) {
printf("Bob deposit receipt status failed, can't claim\n");
return NULL;
}
struct iguana_info *ecoin;
bits256 privkey;
@ -329,7 +613,6 @@ char *LP_etomicalice_claims_bob_deposit(struct LP_swap_remember *swap)
uint8arrayToHex(input.depositId, swap->txids[BASILISK_BOBDEPOSIT].bytes, 32);
satoshisToWei(input.amount, swap->values[BASILISK_BOBDEPOSIT]);
sprintf(input.aliceCanClaimAfter, "%" PRIu64, receipt.blockNumber + 960);
if (swap->bobtomic[0] != 0) {
strcpy(input.tokenAddress, swap->bobtomic);
@ -355,9 +638,11 @@ char *sendEthTx(struct basilisk_swap *swap, struct basilisk_rawtx *rawtx)
return LP_etomicbob_sends_deposit(swap);
} else if (rawtx == &swap->bobpayment && swap->I.bobtomic[0] != 0) {
return LP_etomicbob_sends_payment(swap);
} else if (swap->I.iambob == 0 && rawtx == &swap->myfee && swap->I.alicetomic[0] != 0) {
return LP_etomicalice_send_fee(swap);
} else {
char *result = malloc(67);
strcpy(result, "0x0000000000000000000000000000000000000000000000000000000000000000");
strcpy(result, EMPTY_ETH_TX_ID);
return result;
}
}
@ -404,3 +689,25 @@ int32_t LP_etomic_pub2addr(char *coinaddr,uint8_t pub64[64])
}
return(-1);
}
uint8_t LP_etomic_is_empty_tx_id(char *txId)
{
if (strcmp(txId, EMPTY_ETH_TX_ID) == 0) {
return 1;
}
return 0;
}
uint64_t LP_etomic_get_balance(struct iguana_info *coin, char *coinaddr)
{
if (coin->etomic[0] == 0) {
printf("Trying to get etomic balance for non-etomic coin %s!", coin->symbol);
return 0;
}
if (strcmp(coin->symbol, "ETH") == 0) {
return getEthBalance(coinaddr);
} else {
return getErc20BalanceSatoshi(coinaddr, coin->etomic);
}
}

54
iguana/exchanges/LP_etomic.h

@ -0,0 +1,54 @@
//
// 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 <inttypes.h>
#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);
uint64_t LP_etomic_get_balance(struct iguana_info *coin, char *coinaddr);
#endif //SUPERNET_LP_ETOMIC_H

5
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
{
@ -276,7 +276,7 @@ struct LP_swap_remember
uint32_t finishtime,tradeid,requestid,quoteid,plocktime,dlocktime,expiration,state,otherstate;
int32_t iambob,finishedflag,origfinishedflag,Predeemlen,Dredeemlen,sentflags[sizeof(txnames)/sizeof(*txnames)];
uint8_t secretAm[20],secretAm256[32],secretBn[20],secretBn256[32],Predeemscript[1024],Dredeemscript[1024],pubkey33[33],other33[33];
char Agui[65],Bgui[65],gui[65],src[65],dest[65],bobtomic[128],alicetomic[128],etomicsrc[65],etomicdest[65],destaddr[64],Adestaddr[64],Sdestaddr[64],alicepaymentaddr[64],bobpaymentaddr[64],bobdepositaddr[64],alicecoin[65],bobcoin[65],*txbytes[sizeof(txnames)/sizeof(*txnames)],bobDepositEthTx[75],bobPaymentEthTx[75];
char Agui[65],Bgui[65],gui[65],src[65],dest[65],bobtomic[128],alicetomic[128],etomicsrc[65],etomicdest[65],destaddr[64],Adestaddr[64],Sdestaddr[64],alicepaymentaddr[64],bobpaymentaddr[64],bobdepositaddr[64],alicecoin[65],bobcoin[65],*txbytes[sizeof(txnames)/sizeof(*txnames)],bobDepositEthTx[75],bobPaymentEthTx[75],alicePaymentEthTx[75];
};
struct LP_outpoint
@ -579,5 +579,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

8
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];
@ -178,9 +183,6 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_
#include "LP_prices.c"
#include "LP_scan.c"
#include "LP_transaction.c"
#ifndef NOTETOMIC
#include "LP_etomic.c"
#endif
#include "LP_stats.c"
#include "LP_remember.c"
#include "LP_instantdex.c"

8
iguana/exchanges/LP_portfolio.c

@ -95,6 +95,14 @@ uint64_t LP_balance(uint64_t *valuep,int32_t iambob,char *symbol,char *coinaddr)
cJSON *array,*item; bits256 zero; int32_t i,n; uint64_t valuesum,satoshisum,value;
valuesum = satoshisum = 0;
memset(zero.bytes,0,sizeof(zero));
/*
#ifndef NOTETOMIC
struct iguana_info *coin = LP_coinfind(symbol);
if (coin->etomic[0] != 0) {
valuesum = LP_etomic_get_balance(coin, coinaddr);
} else
#endif
*/
if ( (array= LP_listunspent(symbol,coinaddr,zero,zero)) != 0 )
{
if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 )

37
iguana/exchanges/LP_remember.c

@ -75,6 +75,9 @@ void basilisk_dontforget(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx
if (swap->bobpayment.I.ethTxid[0] != 0) {
fprintf(fp,",\"bobPaymentEthTx\":\"%s\"", swap->bobpayment.I.ethTxid);
}
if (swap->alicepayment.I.ethTxid[0] != 0) {
fprintf(fp,",\"alicePaymentEthTx\":\"%s\"", swap->alicepayment.I.ethTxid);
}
fprintf(fp,",\"alicecoin\":\"%s\"",swap->I.alicestr);
if ( swap->I.alicetomic[0] != 0 )
@ -901,6 +904,10 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap,int32_t forceflag)
strcpy(rswap->bobPaymentEthTx, jstr(txobj,"bobPaymentEthTx"));
}
if (jstr(txobj,"alicePaymentEthTx") != 0) {
strcpy(rswap->alicePaymentEthTx, jstr(txobj,"alicePaymentEthTx"));
}
if (jstr(txobj,"bobtomic") != 0) {
strcpy(rswap->bobtomic, jstr(txobj,"bobtomic"));
}
@ -1256,7 +1263,11 @@ cJSON *basilisk_remember(int32_t fastflag,int64_t *KMDtotals,int64_t *BTCtotals,
if ( rswap.bobtomic[0] != 0 )
{
char *aliceSpendEthTxId = LP_etomicalice_spends_bob_payment(&rswap);
free(aliceSpendEthTxId);
if (aliceSpendEthTxId != NULL) {
free(aliceSpendEthTxId);
} else {
printf("Alice spend ETH tx send failed!\n");
}
}
#endif
}
@ -1301,7 +1312,11 @@ cJSON *basilisk_remember(int32_t fastflag,int64_t *KMDtotals,int64_t *BTCtotals,
if ( rswap.bobtomic[0] != 0 )
{
char *aliceClaimsEthTxId = LP_etomicalice_claims_bob_deposit(&rswap);
free(aliceClaimsEthTxId);
if (aliceClaimsEthTxId != NULL) {
free(aliceClaimsEthTxId);
} else {
printf("Alice Bob deposit claim ETH tx failed!\n");
}
}
#endif
}
@ -1373,7 +1388,11 @@ cJSON *basilisk_remember(int32_t fastflag,int64_t *KMDtotals,int64_t *BTCtotals,
if ( rswap.alicetomic[0] != 0 )
{
char *bobSpendEthTx = LP_etomicbob_spends_alice_payment(&rswap);
free(bobSpendEthTx);
if (bobSpendEthTx != NULL) {
free(bobSpendEthTx);
} else {
printf("Bob spends Alice payment ETH tx send failed!\n");
}
}
#endif
//printf("bobspend.(%s)\n",rswap.txbytes[BASILISK_BOBSPEND]);
@ -1406,7 +1425,11 @@ cJSON *basilisk_remember(int32_t fastflag,int64_t *KMDtotals,int64_t *BTCtotals,
if ( rswap.bobtomic[0] != 0 )
{
char *bobReclaimEthTx = LP_etomicbob_reclaims_payment(&rswap);
free(bobReclaimEthTx);
if (bobReclaimEthTx != NULL) {
free(bobReclaimEthTx);
} else {
printf("Bob reclaims payment ETH tx send failed!\n");
}
}
#endif
//int32_t z;
@ -1448,7 +1471,11 @@ cJSON *basilisk_remember(int32_t fastflag,int64_t *KMDtotals,int64_t *BTCtotals,
if ( rswap.bobtomic[0] != 0 )
{
char *bobRefundsEthTx = LP_etomicbob_refunds_deposit(&rswap);
free(bobRefundsEthTx);
if (bobRefundsEthTx != NULL) {
free(bobRefundsEthTx);
} else {
printf("Bob refunds deposit ETH tx send failed!\n");
}
}
#endif
//printf("pubB1.(%s) bobrefund.(%s)\n",bits256_str(str,rswap.pubB1),rswap.txbytes[BASILISK_BOBREFUND]);

39
iguana/exchanges/LP_swap.c

@ -107,7 +107,7 @@
depositspent.(f34e04ad74e290f63f3d0bccb7d0d50abfa54eea58de38816fdc596a19767add) alice.1 bob.0
*/
#define TX_WAIT_TIMEOUT 1800
uint32_t LP_atomic_locktime(char *base,char *rel)
{
@ -721,15 +721,20 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3
if ( swap->I.bobtomic[0] != 0 || swap->I.alicetomic[0] != 0 )
{
char *ethTxId = sendEthTx(swap, rawtx);
strcpy(rawtx->I.ethTxid, ethTxId);
free(ethTxId);
if (ethTxId != NULL) {
strcpy(rawtx->I.ethTxid, ethTxId);
free(ethTxId);
} else {
printf("Error sending ETH tx\n");
return(-1);
}
}
#endif
sendlen = 0;
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
@ -857,7 +862,7 @@ void LP_bobloop(void *_swap)
//LP_swapsfp_update(&swap->I.req);
LP_swap_critical = (uint32_t)time(NULL);
LP_unavailableset(swap->bobdeposit.utxotxid,swap->bobdeposit.utxovout,(uint32_t)time(NULL)+60,swap->I.otherhash);
if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT*10,LP_verify_otherfee) < 0 )
if ( LP_waitfor(swap->N.pair,swap,TX_WAIT_TIMEOUT,LP_verify_otherfee) < 0 )
{
error = 1;
err = -2004, printf("error waiting for alicefee\n");
@ -871,7 +876,7 @@ void LP_bobloop(void *_swap)
}
}
LP_unavailableset(swap->bobpayment.utxotxid,swap->bobpayment.utxovout,(uint32_t)time(NULL)+60,swap->I.otherhash);
if ( error == 0 && LP_waitfor(swap->N.pair,swap,1800,LP_verify_alicepayment) < 0 )
if ( error == 0 && LP_waitfor(swap->N.pair,swap,TX_WAIT_TIMEOUT,LP_verify_alicepayment) < 0 )
{
error = 1;
err = -2006, printf("error waiting for alicepayment\n");
@ -945,7 +950,7 @@ void LP_aliceloop(void *_swap)
LP_swap_critical = (uint32_t)time(NULL);
if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x80,data,maxlen,&swap->myfee,0x40,0) == 0 )
err = -1004, printf("error sending alicefee\n");
else if ( LP_waitfor(swap->N.pair,swap,1800,LP_verify_bobdeposit) < 0 )
else if ( LP_waitfor(swap->N.pair,swap,TX_WAIT_TIMEOUT,LP_verify_bobdeposit) < 0 )
err = -1005, printf("error waiting for bobdeposit\n");
else
{
@ -970,7 +975,7 @@ void LP_aliceloop(void *_swap)
}
//swap->sentflag = 1;
LP_swap_critical = (uint32_t)time(NULL);
if ( LP_waitfor(swap->N.pair,swap,1800,LP_verify_bobpayment) < 0 )
if ( LP_waitfor(swap->N.pair,swap,TX_WAIT_TIMEOUT,LP_verify_bobpayment) < 0 )
err = -1007, printf("error waiting for bobpayment\n");
else
{
@ -1222,10 +1227,20 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256
swap->I.bobconfirms = swap->I.bobmaxconfirms;
if ( swap->I.aliceconfirms > swap->I.alicemaxconfirms )
swap->I.aliceconfirms = swap->I.alicemaxconfirms;
if ( bobcoin->isassetchain != 0 )
swap->I.bobconfirms = BASILISK_DEFAULT_MAXCONFIRMS/2;
if ( alicecoin->isassetchain != 0 )
swap->I.aliceconfirms = BASILISK_DEFAULT_MAXCONFIRMS/2;
if ( bobcoin->isassetchain != 0 ) {
if (strcmp(bobstr, "ETOMIC") != 0) {
swap->I.bobconfirms = BASILISK_DEFAULT_MAXCONFIRMS / 2;
} else {
swap->I.bobconfirms = 1;
}
}
if ( alicecoin->isassetchain != 0 ) {
if (strcmp(alicestr, "ETOMIC") != 0) {
swap->I.aliceconfirms = BASILISK_DEFAULT_MAXCONFIRMS / 2;
} else {
swap->I.aliceconfirms = 1;
}
}
if ( strcmp("BAY",swap->I.req.src) != 0 && strcmp("BAY",swap->I.req.dest) != 0 )
{
swap->I.bobconfirms *= !swap->I.bobistrusted;

54
iguana/exchanges/LP_transaction.c

@ -13,7 +13,6 @@
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
//
// LP_transaction.c
// marketmaker
@ -1647,6 +1646,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 = jdouble(argjson, "amount") * 100000000;
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;
@ -2259,6 +2283,13 @@ int32_t LP_verify_otherfee(struct basilisk_swap *swap,uint8_t *data,int32_t data
//printf("dexfee verified\n");
}
else printf("locktime mismatch in otherfee, reject %u vs %u\n",swap->otherfee.I.locktime,swap->I.started+1);
#ifndef NOTETOMIC
if (swap->otherfee.I.ethTxid[0] != 0 && LP_etomic_is_empty_tx_id(swap->otherfee.I.ethTxid) == 0) {
if (LP_etomic_wait_for_confirmation(swap->otherfee.I.ethTxid) < 0 || LP_etomic_verify_alice_fee(swap) == 0) {
return(-1);
}
}
#endif
return(0);
} else printf("destaddress mismatch in other fee, reject (%s) vs (%s)\n",swap->otherfee.I.destaddr,swap->otherfee.p2shaddr);
}
@ -2336,6 +2367,13 @@ int32_t LP_verify_bobdeposit(struct basilisk_swap *swap,uint8_t *data,int32_t da
printf("%02x",swap->aliceclaim.txbytes[i]);
printf(" <- aliceclaim\n");*/
//basilisk_txlog(swap,&swap->aliceclaim,swap->I.putduration+swap->I.callduration);
#ifndef NOTETOMIC
if (swap->bobdeposit.I.ethTxid[0] != 0 && LP_etomic_is_empty_tx_id(swap->bobdeposit.I.ethTxid) == 0) {
if (LP_etomic_wait_for_confirmation(swap->bobdeposit.I.ethTxid) < 0 || LP_etomic_verify_bob_deposit(swap, swap->bobdeposit.I.ethTxid) == 0) {
return(-1);
}
}
#endif
return(LP_waitmempool(coin->symbol,swap->bobdeposit.I.destaddr,swap->bobdeposit.I.signedtxid,0,60));
} else printf("error signing aliceclaim suppress.%d vin.(%s)\n",swap->aliceclaim.I.suppress_pubkeys,swap->bobdeposit.I.destaddr);
}
@ -2359,6 +2397,13 @@ int32_t LP_verify_alicepayment(struct basilisk_swap *swap,uint8_t *data,int32_t
if ( bits256_nonz(swap->alicepayment.I.signedtxid) != 0 )
swap->aliceunconf = 1;
basilisk_dontforget_update(swap,&swap->alicepayment);
#ifndef NOTETOMIC
if (swap->alicepayment.I.ethTxid[0] != 0 && LP_etomic_is_empty_tx_id(swap->alicepayment.I.ethTxid) == 0) {
if (LP_etomic_verify_alice_payment(swap, swap->alicepayment.I.ethTxid) == 0) {
return(-1);
}
}
#endif
return(LP_waitmempool(coin->symbol,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,0,60));
//printf("import alicepayment address.(%s)\n",swap->alicepayment.p2shaddr);
//LP_importaddress(coin->symbol,swap->alicepayment.p2shaddr);
@ -2411,6 +2456,13 @@ int32_t LP_verify_bobpayment(struct basilisk_swap *swap,uint8_t *data,int32_t da
memcpy(swap->alicespend.I.pubkey33,swap->persistent_pubkey33,33);
bitcoin_address(coin->symbol,swap->alicespend.I.destaddr,coin->taddr,coin->pubtype,swap->persistent_pubkey33,33);
//char str[65],str2[65]; printf("bobpaid privAm.(%s) myprivs[0].(%s)\n",bits256_str(str,swap->I.privAm),bits256_str(str2,swap->I.myprivs[0]));
#ifndef NOTETOMIC
if (swap->bobpayment.I.ethTxid[0] != 0 && LP_etomic_is_empty_tx_id(swap->bobpayment.I.ethTxid) == 0) {
if (LP_etomic_wait_for_confirmation(swap->bobpayment.I.ethTxid) < 0 || LP_etomic_verify_bob_payment(swap, swap->bobpayment.I.ethTxid) == 0) {
return(-1);
}
}
#endif
if ( (retval= basilisk_rawtx_sign(coin->symbol,coin->wiftaddr,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,swap,&swap->alicespend,&swap->bobpayment,swap->I.myprivs[0],0,userdata,len,1,swap->changermd160,swap->bobpayment.I.destaddr,coin->zcash)) == 0 )
{
/*for (i=0; i<swap->bobpayment.I.datalen; i++)

5
iguana/exchanges/LP_utxo.c

@ -626,6 +626,11 @@ 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) {
balance = LP_etomic_get_balance(coin, coinaddr);
} else
#endif
if ( coin->electrum == 0 )
{
if ( (array= LP_listunspent(coin->symbol,coinaddr,zero,zero)) != 0 )

15
iguana/exchanges/etomicswap/CMakeLists.txt

@ -1,10 +1,11 @@
cmake_minimum_required(VERSION 2.8.9)
add_library(etomiclib etomiclib.cpp)
add_library(etomiccurl etomiccurl.c)
cmake_minimum_required(VERSION 3.5.1)
add_library(etomiclib-testnet etomiclib.cpp etomiccurl.c)
add_library(etomiclib-mainnet etomiclib.cpp etomiccurl.c)
target_compile_definitions(etomiclib-testnet PRIVATE ETOMIC_TESTNET)
add_executable(alice alice.c)
add_executable(bob bob.c)
include_directories("${CMAKE_SOURCE_DIR}/cpp-ethereum")
target_link_libraries(etomiccurl PUBLIC curl libcrypto777)
target_link_libraries(etomiclib PUBLIC ethcore devcrypto devcore etomiccurl)
target_link_libraries(alice PUBLIC etomiclib)
target_link_libraries(bob PUBLIC etomiclib etomiccurl)
target_link_libraries(etomiclib-testnet PUBLIC curl libcrypto777 ethcore devcrypto devcore pthread)
target_link_libraries(etomiclib-mainnet PUBLIC curl libcrypto777 ethcore devcrypto devcore pthread)
target_link_libraries(alice PUBLIC etomiclib-testnet)
target_link_libraries(bob PUBLIC etomiclib-testnet)

199
iguana/exchanges/etomicswap/bob.c

@ -11,9 +11,14 @@
char* bobContractAddress = "0x9387Fd3a016bB0205e4e131Dde886B9d2BC000A2";
char* aliceAddress = "0x485d2cc2d13a9e12E4b53D606DB1c8adc884fB8a";
char* bobAddress = "0xA7EF3f65714AE266414C9E58bB4bAa4E6FB82B41";
char* bobAddress = "0xbAB36286672fbdc7B250804bf6D14Be0dF69fa29";
char* tokenAddress = "0xc0eb7AeD740E1796992A08962c15661bDEB58003";
void *erc20ApproveThread(ApproveErc20Input *input) {
char *result = approveErc20(*input);
free(result);
}
int main(int argc, char** argv)
{
enum {
@ -28,7 +33,8 @@ int main(int argc, char** argv)
BOB_APPROVES_ERC20,
BOB_ETH_BALANCE,
BOB_ERC20_BALANCE,
TX_RECEIPT
TX_RECEIPT,
TX_DATA
};
if (argc < 2) {
return 1;
@ -51,8 +57,12 @@ int main(int argc, char** argv)
strcpy(input.bobHash, argv[3]);
result = bobSendsEthDeposit(input, txData);
printf("%s\n", result);
free(result);
if (result != NULL) {
printf("%s\n", result);
free(result);
} else {
printf("Tx send result was NULL\n");
}
break;
case BOB_ERC20_DEPOSIT:
strcpy(txData.amount, "0");
@ -70,7 +80,12 @@ int main(int argc, char** argv)
strcpy(input1.tokenAddress, tokenAddress);
result = bobSendsErc20Deposit(input1, txData);
printf("%s\n", result);
if (result != NULL) {
printf("%s\n", result);
free(result);
} else {
printf("Tx send result was NULL\n");
}
free(result);
break;
case BOB_CLAIMS_DEPOSIT:
@ -84,11 +99,15 @@ int main(int argc, char** argv)
strcpy(input2.amount, "1000000000000000000");
strcpy(input2.aliceAddress, aliceAddress);
strcpy(input2.tokenAddress, argv[3]);
strcpy(input2.aliceCanClaimAfter, argv[4]);
strcpy(input2.bobSecret, argv[5]);
result = bobRefundsDeposit(input2, txData);
printf("%s\n", result);
if (result != NULL) {
printf("%s\n", result);
free(result);
} else {
printf("Tx send result was NULL\n");
}
free(result);
break;
case ALICE_CLAIMS_DEPOSIT:
@ -102,11 +121,15 @@ int main(int argc, char** argv)
strcpy(input3.amount, "1000000000000000000");
strcpy(input3.bobAddress, bobAddress);
strcpy(input3.tokenAddress, argv[3]);
strcpy(input3.aliceCanClaimAfter, argv[4]);
strcpy(input3.bobHash, argv[5]);
result = aliceClaimsBobDeposit(input3, txData);
printf("%s\n", result);
if (result != NULL) {
printf("%s\n", result);
free(result);
} else {
printf("Tx send result was NULL\n");
}
free(result);
break;
case BOB_ETH_PAYMENT:
@ -121,7 +144,12 @@ int main(int argc, char** argv)
strcpy(input4.aliceAddress, aliceAddress);
result = bobSendsEthPayment(input4, txData);
printf("%s\n", result);
if (result != NULL) {
printf("%s\n", result);
free(result);
} else {
printf("Tx send result was NULL\n");
}
free(result);
break;
case BOB_ERC20_PAYMENT:
@ -139,7 +167,12 @@ int main(int argc, char** argv)
strcpy(input5.aliceHash, argv[3]);
result = bobSendsErc20Payment(input5, txData);
printf("%s\n", result);
if (result != NULL) {
printf("%s\n", result);
free(result);
} else {
printf("Tx send result was NULL\n");
}
free(result);
break;
case BOB_CLAIMS_PAYMENT:
@ -154,11 +187,15 @@ int main(int argc, char** argv)
strcpy(input6.aliceAddress, aliceAddress);
strcpy(input6.amount, "1000000000000000000");
strcpy(input6.tokenAddress, argv[3]);
strcpy(input6.bobCanClaimAfter, argv[4]);
strcpy(input6.aliceHash, argv[5]);
result = bobReclaimsBobPayment(input6, txData);
printf("%s\n", result);
if (result != NULL) {
printf("%s\n", result);
free(result);
} else {
printf("Tx send result was NULL\n");
}
free(result);
break;
case ALICE_CLAIMS_PAYMENT:
@ -173,39 +210,127 @@ int main(int argc, char** argv)
strcpy(input7.bobAddress, bobAddress);
strcpy(input7.amount, "1000000000000000000");
strcpy(input7.tokenAddress, argv[3]);
strcpy(input7.bobCanClaimAfter, argv[4]);
strcpy(input7.aliceSecret, argv[5]);
result = aliceSpendsBobPayment(input7, txData);
printf("%s\n", result);
free(result);
if (result != NULL) {
printf("%s\n", result);
free(result);
} else {
printf("Tx send result was NULL\n");
}
break;
case BOB_APPROVES_ERC20:
result = approveErc20(
"10000000000000000000",
"0xA7EF3f65714AE266414C9E58bB4bAa4E6FB82B41",
getenv("BOB_PK")
);
printf("%s\n", result);
free(result);
printf("approving erc20\n");
ApproveErc20Input input8;
strcpy(input8.amount, "0");
strcpy(input8.spender, bobContractAddress);
strcpy(input8.owner, bobAddress);
strcpy(input8.tokenAddress, tokenAddress);
strcpy(input8.secret, getenv("BOB_PK"));
ApproveErc20Input input123;
strcpy(input123.amount, "100");
strcpy(input123.spender, bobContractAddress);
strcpy(input123.owner, bobAddress);
strcpy(input123.tokenAddress, tokenAddress);
strcpy(input123.secret, getenv("BOB_PK"));
pthread_t t1, t2;
pthread_create(&t1, NULL, erc20ApproveThread, &input8);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_create(&t2, NULL, erc20ApproveThread, &input123);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
/*result = approveErc20(input8);
if (result != NULL) {
printf("%s\n", result);
free(result);
} else {
printf("Tx send result was NULL\n");
}
result = approveErc20(&input8);
if (result != NULL) {
printf("%s\n", result);
free(result);
} else {
printf("Tx send result was NULL\n");
}
*/
break;
case BOB_ETH_BALANCE:
printf("%" PRIu64 "\n", getEthBalance(bobAddress));
break;
case BOB_ERC20_BALANCE:
printf("%" PRIu64 "\n", getErc20Balance(bobAddress, tokenAddress));
printf("%" PRIu64 "\n", getErc20BalanceSatoshi(bobAddress, tokenAddress));
break;
case TX_RECEIPT:
printf("getTxReceipt\n");
EthTxReceipt txReceipt;
txReceipt = getEthTxReceipt("0x82afa1b00f8a63e1a91430162e5cb2d4ebe915831ffd56e6e3227814913e23e6");
printf("%" PRIu64 "\n", txReceipt.blockNumber);
printf("%s\n", txReceipt.blockHash);
txReceipt = getEthTxReceipt("0xc337b9cfe76aaa9022d9399a9e4ecdc1b7044d65ef74e8911a4b47874bee60c6");
printf("blockNumber: %" PRIu64 "\n", txReceipt.blockNumber);
printf("blockHash: %s\n", txReceipt.blockHash);
printf("status: %s\n", txReceipt.status);
printf("confirmations: %" PRIu64 "\n", txReceipt.confirmations);
break;
case TX_DATA:
printf("getTxData\n");
EthTxData ethTxData;
ethTxData = getEthTxData("0xc337b9cfe76aaa9022d9399a9e4ecdc1b7044d65ef74e8911a4b47874bee60c6");
printf("from : %s\n", ethTxData.from);
printf("to: %s\n", ethTxData.to);
printf("value: %s\n", ethTxData.valueHex);
printf("input: %s\n", ethTxData.input);
printf("exists: %d\n", ethTxData.exists);
break;
default:
return 1;
}
/*
char *pubkey = getPubKeyFromPriv(getenv("BOB_PK"));
printf("pubkey: %s\n", pubkey);
free(pubkey);
@ -214,5 +339,23 @@ int main(int argc, char** argv)
char weiBuffer[100];
satoshisToWei(weiBuffer, satoshis);
printf("wei: %s\n", weiBuffer);
uint8_t decimals = getErc20Decimals(tokenAddress);
printf("decimals: %d\n", decimals);
uint64_t tokenAllowance = getErc20Allowance(bobAddress, bobContractAddress, tokenAddress);
printf("allowance: %" PRIu64 "\n", tokenAllowance);
char *sendEthTx = sendEth(bobAddress, "100000000000000", getenv("BOB_PK"));
printf("sent ETH: %s\n", sendEthTx);
free(sendEthTx);
char *sendErc20Tx = sendErc20(tokenAddress, bobAddress, "100000000000000", getenv("BOB_PK"));
printf("sent Erc20: %s\n", sendErc20Tx);
free(sendErc20Tx);
uint64_t gasPrice = getGasPriceFromStation();
printf("gasPrice: %" PRIu64 "\n", gasPrice);
*/
return 0;
}

312
iguana/exchanges/etomicswap/etomiccurl.c

@ -1,10 +1,8 @@
#include "etomiccurl.h"
#include <curl/curl.h>
#include <memory.h>
#include <stdlib.h>
#include "../../../includes/cJSON.h"
static char *ethRpcUrl = ETOMIC_URL;
pthread_mutex_t sendTxMutex = PTHREAD_MUTEX_INITIALIZER;
struct string {
char *ptr;
@ -36,6 +34,28 @@ size_t writefunc(void *ptr, size_t size, size_t nmemb, struct string *s)
return size*nmemb;
}
cJSON *parseEthRpcResponse(char *requestResult)
{
printf("Trying to parse ETH RPC response: %s\n", requestResult);
cJSON *json = cJSON_Parse(requestResult);
if (json == NULL) {
printf("ETH RPC response parse failed!\n");
return NULL;
}
cJSON *tmp = cJSON_GetObjectItem(json, "result");
cJSON *error = cJSON_GetObjectItem(json, "error");
cJSON *result = NULL;
if (!is_cJSON_Null(tmp)) {
result = cJSON_Duplicate(tmp, 1);
} else if (error != NULL && !is_cJSON_Null(error)) {
char *errorString = cJSON_PrintUnformatted(error);
printf("Got ETH rpc error: %s\n", errorString);
free(errorString);
}
cJSON_Delete(json);
return result;
}
char* sendRequest(char* request)
{
CURL *curl;
@ -69,128 +89,256 @@ char* sendRequest(char* request)
}
}
char* sendRawTx(char* rawTx)
cJSON *sendRpcRequest(char *method, cJSON *params)
{
char* string;
cJSON *request = cJSON_CreateObject();
cJSON *params = cJSON_CreateArray();
cJSON_AddItemToObject(request, "jsonrpc", cJSON_CreateString("2.0"));
cJSON_AddItemToObject(request, "method", cJSON_CreateString("eth_sendRawTransaction"));
cJSON_AddItemToArray(params, cJSON_CreateString(rawTx));
cJSON_AddItemToObject(request, "params", params);
cJSON_AddItemToObject(request, "id", cJSON_CreateNumber(2));
cJSON_AddStringToObject(request, "jsonrpc", "2.0");
cJSON_AddStringToObject(request, "method", method);
cJSON_AddItemToObject(request, "params", cJSON_Duplicate(params, 1));
cJSON_AddNumberToObject(request, "id", 1);
string = cJSON_PrintUnformatted(request);
char* requestResult = sendRequest(string);
cJSON *json = cJSON_Parse(requestResult);
free(string);
cJSON_Delete(request);
char* tmp = cJSON_GetObjectItem(json, "result")->valuestring;
char* txId = (char*)malloc(strlen(tmp) + 1);
strcpy(txId, tmp);
cJSON_Delete(json);
cJSON *result = parseEthRpcResponse(requestResult);
free(requestResult);
free(string);
return result;
}
char* sendRawTxWaitConfirm(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);
}
/*
if (resultJson != NULL && is_cJSON_String(resultJson) && resultJson->valuestring != NULL) {
char* tmp = resultJson->valuestring;
if (waitForConfirmation(tmp) > 0) {
txId = (char *) malloc(strlen(tmp) + 1);
strcpy(txId, tmp);
}
}
*/
cJSON_Delete(resultJson);
pthread_mutex_unlock(&sendTxMutex);
return txId;
}
int getNonce(char* address)
char* sendRawTx(char* rawTx)
{
char* string;
cJSON *request = cJSON_CreateObject();
cJSON *params = cJSON_CreateArray();
cJSON_AddItemToObject(request, "jsonrpc", cJSON_CreateString("2.0"));
cJSON_AddItemToObject(request, "method", cJSON_CreateString("eth_getTransactionCount"));
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.
// make sure that sendRawTx is called after getting a nonce!
if (pthread_mutex_lock(&sendTxMutex) != 0) {
printf("Nonce mutex lock failed\n");
};
cJSON *params = cJSON_CreateArray();
cJSON_AddItemToArray(params, cJSON_CreateString(address));
cJSON_AddItemToArray(params, cJSON_CreateString("pending"));
cJSON_AddItemToObject(request, "params", params);
cJSON_AddItemToObject(request, "id", cJSON_CreateNumber(2));
string = cJSON_PrintUnformatted(request);
char* requestResult = sendRequest(string);
cJSON_Delete(request);
cJSON *json = cJSON_Parse(requestResult);
int nonce = (int)strtol(cJSON_GetObjectItem(json, "result")->valuestring, NULL, 0);
cJSON_Delete(json);
free(requestResult);
free(string);
// cJSON_AddItemToArray(params, cJSON_CreateString("pending"));
int64_t nonce = -1;
cJSON *nonceJson = sendRpcRequest("parity_nextNonce", params);
cJSON_Delete(params);
if (nonceJson != NULL && is_cJSON_String(nonceJson) && nonceJson != NULL) {
nonce = (int64_t) strtol(nonceJson->valuestring, NULL, 0);
}
cJSON_Delete(nonceJson);
printf("Got ETH nonce %d\n", (int)nonce);
return nonce;
}
char* getEthBalanceRequest(char* address)
{
char* string;
cJSON *request = cJSON_CreateObject();
cJSON *params = cJSON_CreateArray();
cJSON_AddItemToObject(request, "jsonrpc", cJSON_CreateString("2.0"));
cJSON_AddItemToObject(request, "method", cJSON_CreateString("eth_getBalance"));
cJSON_AddItemToArray(params, cJSON_CreateString(address));
cJSON_AddItemToArray(params, cJSON_CreateString("latest"));
cJSON_AddItemToObject(request, "params", params);
cJSON_AddItemToObject(request, "id", cJSON_CreateNumber(2));
string = cJSON_PrintUnformatted(request);
char* requestResult = sendRequest(string);
cJSON_Delete(request);
cJSON *json = cJSON_Parse(requestResult);
char* tmp = cJSON_GetObjectItem(json, "result")->valuestring;
char* balance = (char*)malloc(strlen(tmp) + 1);
strcpy(balance, tmp);
cJSON_Delete(json);
free(requestResult);
free(string);
cJSON *balanceJson = sendRpcRequest("eth_getBalance", params);
cJSON_Delete(params);
char *balance = NULL;
if (balanceJson != NULL && is_cJSON_String(balanceJson) && balanceJson->valuestring != NULL) {
balance = (char *) malloc(strlen(balanceJson->valuestring) + 1);
strcpy(balance, balanceJson->valuestring);
}
cJSON_Delete(balanceJson);
return balance;
}
char* ethCall(char* to, const char* data)
{
char* string;
cJSON *request = cJSON_CreateObject();
cJSON *params = cJSON_CreateArray();
cJSON *txObject = cJSON_CreateObject();
cJSON_AddItemToObject(request, "jsonrpc", cJSON_CreateString("2.0"));
cJSON_AddItemToObject(request, "method", cJSON_CreateString("eth_call"));
cJSON_AddStringToObject(txObject, "to", to);
cJSON_AddStringToObject(txObject, "data", data);
cJSON_AddItemToArray(params, txObject);
cJSON_AddItemToArray(params, cJSON_CreateString("latest"));
cJSON_AddItemToObject(request, "params", params);
cJSON_AddItemToObject(request, "id", cJSON_CreateNumber(2));
string = cJSON_PrintUnformatted(request);
char* requestResult = sendRequest(string);
cJSON_Delete(request);
cJSON *json = cJSON_Parse(requestResult);
char* tmp = cJSON_GetObjectItem(json, "result")->valuestring;
char* result = (char*)malloc(strlen(tmp) + 1);
strcpy(result, tmp);
cJSON_Delete(json);
free(requestResult);
free(string);
cJSON *resultJson = sendRpcRequest("eth_call", params);
cJSON_Delete(params);
char* result = NULL;
if (resultJson != NULL && is_cJSON_String(resultJson) && resultJson->valuestring != NULL) {
result = (char *) malloc(strlen(resultJson->valuestring) + 1);
strcpy(result, resultJson->valuestring);
}
cJSON_Delete(resultJson);
return result;
}
EthTxReceipt getEthTxReceipt(char *txId)
{
EthTxReceipt result;
char* string;
cJSON *request = cJSON_CreateObject();
memset(&result, 0, sizeof(result));
cJSON *params = cJSON_CreateArray();
cJSON_AddItemToObject(request, "jsonrpc", cJSON_CreateString("2.0"));
cJSON_AddItemToObject(request, "method", cJSON_CreateString("eth_getTransactionReceipt"));
cJSON_AddItemToArray(params, cJSON_CreateString(txId));
cJSON_AddItemToObject(request, "params", params);
cJSON_AddItemToObject(request, "id", cJSON_CreateNumber(2));
string = cJSON_PrintUnformatted(request);
char *requestResult = sendRequest(string);
cJSON_Delete(request);
cJSON *json = cJSON_Parse(requestResult);
cJSON *tmp = cJSON_GetObjectItem(json, "result");
if (is_cJSON_Null(tmp)) {
cJSON *receiptJson = sendRpcRequest("eth_getTransactionReceipt", params);
cJSON_Delete(params);
if (receiptJson == NULL || is_cJSON_Null(cJSON_GetObjectItem(receiptJson, "blockHash")) || is_cJSON_Null(cJSON_GetObjectItem(receiptJson, "blockNumber"))) {
printf("ETH tx %s is not confirmed yet or does not exist at all\n", txId);
strcpy(result.blockHash, "0x0000000000000000000000000000000000000000000000000000000000000000");
result.blockNumber = 0;
} else {
strcpy(result.blockHash, cJSON_GetObjectItem(tmp, "blockHash")->valuestring);
result.blockNumber = (uint64_t) strtol(cJSON_GetObjectItem(tmp, "blockNumber")->valuestring, NULL, 0);
uint64_t currentBlockNumber = getEthBlockNumber();
strcpy(result.blockHash, cJSON_GetObjectItem(receiptJson, "blockHash")->valuestring);
strcpy(result.status, cJSON_GetObjectItem(receiptJson, "status")->valuestring);
result.blockNumber = (uint64_t) strtol(cJSON_GetObjectItem(receiptJson, "blockNumber")->valuestring, NULL, 0);
if (currentBlockNumber >= result.blockNumber) {
result.confirmations = currentBlockNumber - result.blockNumber + 1;
}
}
cJSON_Delete(json);
free(requestResult);
free(string);
cJSON_Delete(receiptJson);
return result;
}
uint64_t getEthBlockNumber()
{
uint64_t result = 0;
cJSON *params = cJSON_CreateArray();
cJSON *blockNumberJson = sendRpcRequest("eth_blockNumber", params);
cJSON_Delete(params);
if (blockNumberJson != NULL && is_cJSON_String(blockNumberJson) && blockNumberJson->valuestring != NULL) {
result = (uint64_t) strtol(blockNumberJson->valuestring, NULL, 0);
}
cJSON_Delete(blockNumberJson);
return result;
}
EthTxData getEthTxData(char *txId)
{
EthTxData result;
memset(&result, 0, sizeof(result));
cJSON *params = cJSON_CreateArray();
cJSON_AddItemToArray(params, cJSON_CreateString(txId));
cJSON *dataJson = sendRpcRequest("eth_getTransactionByHash", params);
cJSON_Delete(params);
if (dataJson == NULL) {
result.exists = 0;
printf("ETH tx %s get data error or txId does not exist\n", txId);
} else {
result.exists = 1;
strcpy(result.from, cJSON_GetObjectItem(dataJson, "from")->valuestring);
strcpy(result.to, cJSON_GetObjectItem(dataJson, "to")->valuestring);
strcpy(result.input, cJSON_GetObjectItem(dataJson, "input")->valuestring);
strcpy(result.valueHex, cJSON_GetObjectItem(dataJson, "value")->valuestring);
}
free(dataJson);
return result;
}
uint64_t getGasPriceFromStation()
{
CURL *curl;
CURLcode res;
struct curl_slist *headers = NULL;
curl = curl_easy_init();
if (curl) {
struct string s;
init_eth_string(&s);
headers = curl_slist_append(headers, "Accept: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
curl_easy_setopt(curl, CURLOPT_URL, "https://ethgasstation.info/json/ethgasAPI.json");
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if (res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
return DEFAULT_GAS_PRICE;
}
/* always cleanup */
curl_easy_cleanup(curl);
cJSON *resultJson = cJSON_Parse(s.ptr);
uint64_t result = DEFAULT_GAS_PRICE;
free(s.ptr);
if (resultJson == NULL) {
return result;
}
if (is_cJSON_Number(cJSON_GetObjectItem(resultJson, "average"))) {
#ifdef ETOMIC_TESTNET
result = (uint64_t)(cJSON_GetObjectItem(resultJson, "average")->valuedouble / 10) + 10;
#else
result = (uint64_t)(cJSON_GetObjectItem(resultJson, "average")->valuedouble / 10) + 1;
#endif
}
cJSON_Delete(resultJson);
return result;
} else {
return DEFAULT_GAS_PRICE;
}
}
int32_t waitForConfirmation(char *txId)
{
EthTxReceipt receipt;
EthTxData txData;
uint8_t retries = 0;
do {
receipt = getEthTxReceipt(txId);
if (receipt.confirmations < 1) {
txData = getEthTxData(txId);
if (txData.exists == 0) {
retries++;
if (retries >= 30) {
printf("Have not found ETH tx %s after 10 checks, aborting\n", txId);
return (-1);
}
}
} else {
break;
}
printf("waiting for ETH txId to be confirmed: %s\n", txId);
sleep(15);
} while (1);
if (strcmp(receipt.status, "0x1") != 0) {
printf("ETH txid %s receipt status failed\n", txId);
return(-1);
}
return((int32_t)receipt.confirmations);
}

38
iguana/exchanges/etomicswap/etomiccurl.h

@ -1,28 +1,54 @@
#ifndef ETOMIC_CURL_HEADER
#define ETOMIC_CURL_HEADER
#include <stdint.h>
#include <includes/cJSON.h>
#ifdef _WIN32
#include "../../../OSlibs/win/pthread.h"
#endif
#ifdef __cplusplus
extern "C"{
#endif
#define ETOMIC_TESTNET
#ifdef ETOMIC_TESTNET
#define ETOMIC_URL "https://ropsten.infura.io/y07GHxUyTgeN2mdfOonu"
#define ETOMIC_URL "http://195.201.0.6:8545"
#define DEFAULT_GAS_PRICE 100
#else
#define ETOMIC_URL "https://mainnet.infura.io/y07GHxUyTgeN2mdfOonu"
#define ETOMIC_URL "http://195.201.0.6:8555"
#define DEFAULT_GAS_PRICE 4
#endif
typedef struct
{
uint64_t blockNumber;
uint64_t confirmations;
char blockHash[75];
char status[10];
} EthTxReceipt;
typedef struct
{
char from[50];
char to[50];
char input[1000];
char valueHex[70];
uint8_t exists;
} EthTxData;
char* sendRawTx(char* rawTx);
char* sendRawTxWaitConfirm(char* rawTx);
char* ethCall(char* to, const char* data);
int getNonce(char* address);
int64_t getNonce(char* address);
char* getEthBalanceRequest(char* address);
EthTxReceipt getEthTxReceipt(char *txId);
EthTxData getEthTxData(char *txId);
uint64_t getEthBlockNumber();
uint64_t getGasPriceFromStation();
int32_t waitForConfirmation(char *txId);
#ifdef __cplusplus
}
#endif
#endif

437
iguana/exchanges/etomicswap/etomiclib.cpp

@ -12,7 +12,7 @@
using namespace dev;
using namespace dev::eth;
char* stringStreamToChar(std::stringstream& ss)
char *stringStreamToChar(std::stringstream& ss)
{
const std::string tmp = ss.str();
auto result = (char*)malloc(strlen(tmp.c_str()) + 1);
@ -26,13 +26,13 @@ TransactionSkeleton txDataToSkeleton(BasicTxData txData)
tx.from = jsToAddress(txData.from);
tx.to = jsToAddress(txData.to);
tx.value = jsToU256(txData.amount);
tx.gas = 300000;
tx.gasPrice = ETOMIC_GASMULT * exp10<9>();
tx.gas = 100000;
tx.gasPrice = getGasPriceFromStation() * boost::multiprecision::pow(u256(10), 9);
tx.nonce = getNonce(txData.from);
return tx;
}
char* signTx(TransactionSkeleton& tx, char* secret)
char *signTx(TransactionSkeleton& tx, char* secret)
{
Secret& secretKey = *(new Secret(secret));
auto baseTx = new TransactionBase(tx, secretKey);
@ -43,30 +43,29 @@ char* signTx(TransactionSkeleton& tx, char* secret)
return stringStreamToChar(ss);
}
char* approveErc20(char* amount, char* from, char* secret)
char *approveErc20(ApproveErc20Input input)
{
TransactionSkeleton tx;
tx.from = jsToAddress(from);
tx.to = jsToAddress("0xc0eb7AeD740E1796992A08962c15661bDEB58003");
tx.value = 0; // exp10<18>();
tx.from = jsToAddress(input.owner);
tx.to = jsToAddress(input.tokenAddress);
tx.value = 0;
tx.gas = 300000;
tx.gasPrice = ETOMIC_GASMULT * exp10<9>();
tx.nonce = getNonce(from);
tx.gasPrice = getGasPriceFromStation() * boost::multiprecision::pow(u256(10), 9);
tx.nonce = getNonce(input.owner);
std::stringstream ss;
ss << "0x095ea7b3"
<< "000000000000000000000000"
<< toHex(jsToAddress("0xe1D4236C5774D35Dc47dcc2E5E0CcFc463A3289c"))
<< toHex(toBigEndian(jsToU256(amount)));
<< toHex(jsToAddress(input.spender))
<< toHex(toBigEndian(jsToU256(input.amount)));
tx.data = jsToBytes(ss.str());
char* rawTx = signTx(tx, secret);
char* result = sendRawTx(rawTx);
char* rawTx = signTx(tx, input.secret);
char* result = sendRawTxWaitConfirm(rawTx);
free(rawTx);
return result;
}
char* aliceSendsEthPayment(AliceSendsEthPaymentInput input, BasicTxData txData)
std::stringstream aliceSendsEthPaymentData(AliceSendsEthPaymentInput input)
{
TransactionSkeleton tx = txDataToSkeleton(txData);
std::stringstream ss;
ss << "0x47c7b6e2"
<< toHex(jsToBytes(input.dealId))
@ -76,20 +75,41 @@ char* aliceSendsEthPayment(AliceSendsEthPaymentInput input, BasicTxData txData)
<< "000000000000000000000000"
<< toHex(jsToBytes(input.bobHash))
<< "000000000000000000000000";
return ss;
}
char* aliceSendsEthPayment(AliceSendsEthPaymentInput input, BasicTxData txData)
{
TransactionSkeleton tx = txDataToSkeleton(txData);
std::stringstream ss = aliceSendsEthPaymentData(input);
tx.data = jsToBytes(ss.str());
char* rawTx = signTx(tx, txData.secretKey);
char* result = sendRawTx(rawTx);
char *rawTx = signTx(tx, txData.secretKey);
char *result = sendRawTxWaitConfirm(rawTx);
free(rawTx);
return result;
}
char* aliceSendsErc20Payment(AliceSendsErc20PaymentInput input, BasicTxData txData)
uint8_t verifyAliceEthPaymentData(AliceSendsEthPaymentInput input, char *data)
{
TransactionSkeleton tx = txDataToSkeleton(txData);
std::stringstream ss = aliceSendsEthPaymentData(input);
if (strcmp(ss.str().c_str(), data) != 0) {
printf("Alice ETH payment data %s does not match expected %s\n", data, ss.str().c_str());
return 0;
}
return 1;
}
std::stringstream aliceSendsErc20PaymentData(AliceSendsErc20PaymentInput input)
{
uint8_t decimals = getErc20Decimals(input.tokenAddress);
u256 amount = jsToU256(input.amount);
if (decimals < 18) {
amount /= boost::multiprecision::pow(u256(10), 18 - decimals);
}
std::stringstream ss;
ss << "0x184db3bf"
<< toHex(jsToBytes(input.dealId))
<< toHex(toBigEndian(jsToU256(input.amount)))
<< toHex(toBigEndian(amount))
<< "000000000000000000000000"
<< toHex(jsToAddress(input.bobAddress))
<< toHex(jsToBytes(input.aliceHash))
@ -98,22 +118,47 @@ char* aliceSendsErc20Payment(AliceSendsErc20PaymentInput input, BasicTxData txDa
<< "000000000000000000000000"
<< "000000000000000000000000"
<< toHex(jsToAddress(input.tokenAddress));
return ss;
}
char* aliceSendsErc20Payment(AliceSendsErc20PaymentInput input, BasicTxData txData)
{
TransactionSkeleton tx = txDataToSkeleton(txData);
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;
}
uint8_t verifyAliceErc20PaymentData(AliceSendsErc20PaymentInput input, char *data)
{
std::stringstream ss = aliceSendsErc20PaymentData(input);
if (strcmp(ss.str().c_str(), data) != 0) {
printf("Alice ERC20 payment data %s is not equal to expected %s\n", data, ss.str().c_str());
return 0;
}
return 1;
}
char* aliceReclaimsAlicePayment(AliceReclaimsAlicePaymentInput input, BasicTxData txData)
{
TransactionSkeleton tx = txDataToSkeleton(txData);
std::stringstream ss;
u256 amount = jsToU256(input.amount);
dev::Address tokenAddress = jsToAddress(input.tokenAddress);
if (tokenAddress != ZeroAddress) {
uint8_t decimals = getErc20Decimals(input.tokenAddress);
if (decimals < 18) {
amount /= boost::multiprecision::pow(u256(10), 18 - decimals);
}
}
ss << "0x8b9a167a"
<< toHex(jsToBytes(input.dealId))
<< toHex(toBigEndian(jsToU256(input.amount)))
<< toHex(toBigEndian(amount))
<< "000000000000000000000000"
<< toHex(jsToAddress(input.tokenAddress))
<< toHex(tokenAddress)
<< "000000000000000000000000"
<< toHex(jsToAddress(input.bobAddress))
<< toHex(jsToBytes(input.aliceHash))
@ -123,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;
}
@ -132,11 +177,19 @@ char* bobSpendsAlicePayment(BobSpendsAlicePaymentInput input, BasicTxData txData
{
TransactionSkeleton tx = txDataToSkeleton(txData);
std::stringstream ss;
u256 amount = jsToU256(input.amount);
dev::Address tokenAddress = jsToAddress(input.tokenAddress);
if (tokenAddress != ZeroAddress) {
uint8_t decimals = getErc20Decimals(input.tokenAddress);
if (decimals < 18) {
amount /= boost::multiprecision::pow(u256(10), 18 - decimals);
}
}
ss << "0x392ec66b"
<< toHex(jsToBytes(input.dealId))
<< toHex(toBigEndian(jsToU256(input.amount)))
<< toHex(toBigEndian(amount))
<< "000000000000000000000000"
<< toHex(jsToAddress(input.tokenAddress))
<< toHex(tokenAddress)
<< "000000000000000000000000"
<< toHex(jsToAddress(input.aliceAddress))
<< toHex(jsToBytes(input.bobHash))
@ -146,21 +199,29 @@ 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;
}
char* bobSendsEthDeposit(BobSendsEthDepositInput input, BasicTxData txData)
std::stringstream bobSendsEthDepositData(BobSendsEthDepositInput input)
{
TransactionSkeleton tx = txDataToSkeleton(txData);
u256 lockTime = input.lockTime;
std::stringstream ss;
ss << "0xc2c5143f"
ss << "0xdd23795f"
<< toHex(jsToBytes(input.depositId))
<< "000000000000000000000000"
<< toHex(jsToAddress(input.aliceAddress))
<< toHex(jsToBytes(input.bobHash))
<< "000000000000000000000000";
<< "000000000000000000000000"
<< toHex(toBigEndian(lockTime));
return ss;
}
char* bobSendsEthDeposit(BobSendsEthDepositInput input, BasicTxData txData)
{
TransactionSkeleton tx = txDataToSkeleton(txData);
std::stringstream ss = bobSendsEthDepositData(input);
tx.data = jsToBytes(ss.str());
char* rawTx = signTx(tx, txData.secretKey);
char* result = sendRawTx(rawTx);
@ -168,44 +229,82 @@ char* bobSendsEthDeposit(BobSendsEthDepositInput input, BasicTxData txData)
return result;
}
char* bobSendsErc20Deposit(BobSendsErc20DepositInput input, BasicTxData txData)
uint8_t verifyBobEthDepositData(BobSendsEthDepositInput input, char *data)
{
TransactionSkeleton tx = txDataToSkeleton(txData);
std::stringstream ss = bobSendsEthDepositData(input);
if (strcmp(ss.str().c_str(), data) != 0) {
printf("Bob deposit data %s != expected %s\n", data, ss.str().c_str());
return 0;
}
return 1;
}
std::stringstream bobSendsErc20DepositData(BobSendsErc20DepositInput input)
{
uint8_t decimals = getErc20Decimals(input.tokenAddress);
u256 amount = jsToU256(input.amount);
u256 lockTime = input.lockTime;
if (decimals < 18) {
amount /= boost::multiprecision::pow(u256(10), 18 - decimals);
}
std::stringstream ss;
ss << "0xce8bbe4b"
ss << "0x5d567259"
<< toHex(jsToBytes(input.depositId))
<< toHex(toBigEndian(jsToU256(input.amount)))
<< toHex(toBigEndian(amount))
<< "000000000000000000000000"
<< toHex(jsToAddress(input.aliceAddress))
<< toHex(jsToBytes(input.bobHash))
<< "000000000000000000000000"
<< "000000000000000000000000"
<< toHex(jsToAddress(input.tokenAddress));
<< toHex(jsToAddress(input.tokenAddress))
<< toHex(toBigEndian(lockTime));
return ss;
}
char* bobSendsErc20Deposit(BobSendsErc20DepositInput input, BasicTxData txData)
{
TransactionSkeleton tx = txDataToSkeleton(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;
}
uint8_t verifyBobErc20DepositData(BobSendsErc20DepositInput input, char *data)
{
std::stringstream ss = bobSendsErc20DepositData(input);
if (strcmp(ss.str().c_str(), data) != 0) {
printf("Bob deposit data %s != expected %s\n", data, ss.str().c_str());
return 0;
}
return 1;
}
char* bobRefundsDeposit(BobRefundsDepositInput input, BasicTxData txData)
{
TransactionSkeleton tx = txDataToSkeleton(txData);
std::stringstream ss;
ss << "0x1dbe6508"
u256 amount = jsToU256(input.amount);
dev::Address tokenAddress = jsToAddress(input.tokenAddress);
if (tokenAddress != ZeroAddress) {
uint8_t decimals = getErc20Decimals(input.tokenAddress);
if (decimals < 18) {
amount /= boost::multiprecision::pow(u256(10), 18 - decimals);
}
}
ss << "0x1f7a72f7"
<< toHex(jsToBytes(input.depositId))
<< toHex(toBigEndian(jsToU256(input.amount)))
<< toHex(toBigEndian(jsToU256(input.aliceCanClaimAfter)))
<< toHex(toBigEndian(amount))
<< toHex(jsToBytes(input.bobSecret))
<< "000000000000000000000000"
<< toHex(jsToAddress(input.aliceAddress))
<< "000000000000000000000000"
<< toHex(jsToAddress(input.tokenAddress))
<< "00000000000000000000000000000000000000000000000000000000000000c0"
<< "0000000000000000000000000000000000000000000000000000000000000020"
<< toHex(jsToBytes(input.bobSecret));
<< toHex(tokenAddress);
tx.data = jsToBytes(ss.str());
char* rawTx = signTx(tx, txData.secretKey);
char* result = sendRawTx(rawTx);
char* result = sendRawTxWaitConfirm(rawTx);
free(rawTx);
return result;
}
@ -214,77 +313,132 @@ char* aliceClaimsBobDeposit(AliceClaimsBobDepositInput input, BasicTxData txData
{
TransactionSkeleton tx = txDataToSkeleton(txData);
std::stringstream ss;
ss << "0x960173b5"
u256 amount = jsToU256(input.amount);
dev::Address tokenAddress = jsToAddress(input.tokenAddress);
if (tokenAddress != ZeroAddress) {
uint8_t decimals = getErc20Decimals(input.tokenAddress);
if (decimals < 18) {
amount /= boost::multiprecision::pow(u256(10), 18 - decimals);
}
}
ss << "0x4b915a68"
<< toHex(jsToBytes(input.depositId))
<< toHex(toBigEndian(jsToU256(input.amount)))
<< toHex(toBigEndian(jsToU256(input.aliceCanClaimAfter)))
<< toHex(toBigEndian(amount))
<< "000000000000000000000000"
<< toHex(jsToAddress(input.bobAddress))
<< "000000000000000000000000"
<< toHex(jsToAddress(input.tokenAddress))
<< toHex(tokenAddress)
<< toHex(jsToBytes(input.bobHash))
<< "000000000000000000000000";
tx.data = jsToBytes(ss.str());
char* rawTx = signTx(tx, txData.secretKey);
char* result = sendRawTx(rawTx);
char* result = sendRawTxWaitConfirm(rawTx);
free(rawTx);
return result;
}
char* bobSendsEthPayment(BobSendsEthPaymentInput input, BasicTxData txData)
std::stringstream bobSendsEthPaymentData(BobSendsEthPaymentInput input)
{
TransactionSkeleton tx = txDataToSkeleton(txData);
u256 lockTime = input.lockTime;
std::stringstream ss;
ss << "0xcf36fe8e"
ss << "0x5ab30d95"
<< toHex(jsToBytes(input.paymentId))
<< "000000000000000000000000"
<< toHex(jsToAddress(input.aliceAddress))
<< toHex(jsToBytes(input.aliceHash))
<< "000000000000000000000000";
<< "000000000000000000000000"
<< toHex(toBigEndian(lockTime));
return ss;
}
char* bobSendsEthPayment(BobSendsEthPaymentInput input, BasicTxData txData)
{
TransactionSkeleton tx = txDataToSkeleton(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;
}
char* bobSendsErc20Payment(BobSendsErc20PaymentInput input, BasicTxData txData)
uint8_t verifyBobEthPaymentData(BobSendsEthPaymentInput input, char *data)
{
TransactionSkeleton tx = txDataToSkeleton(txData);
std::stringstream ss = bobSendsEthPaymentData(input);
if (strcmp(ss.str().c_str(), data) != 0) {
printf("Bob payment data %s != expected %s\n", data, ss.str().c_str());
return 0;
}
return 1;
}
std::stringstream bobSendsErc20PaymentData(BobSendsErc20PaymentInput input)
{
uint8_t decimals = getErc20Decimals(input.tokenAddress);
u256 amount = jsToU256(input.amount);
u256 lockTime = input.lockTime;
if (decimals < 18) {
amount /= boost::multiprecision::pow(u256(10), 18 - decimals);
}
std::stringstream ss;
ss << "0x34f64dfd"
ss << "0xb8a15b1d"
<< toHex(jsToBytes(input.paymentId))
<< toHex(toBigEndian(jsToU256(input.amount)))
<< toHex(toBigEndian(amount))
<< "000000000000000000000000"
<< toHex(jsToAddress(input.aliceAddress))
<< toHex(jsToBytes(input.aliceHash))
<< "000000000000000000000000"
<< "000000000000000000000000"
<< toHex(jsToAddress(input.tokenAddress));
<< toHex(jsToAddress(input.tokenAddress))
<< toHex(toBigEndian(lockTime));
return ss;
}
char* bobSendsErc20Payment(BobSendsErc20PaymentInput input, BasicTxData txData)
{
TransactionSkeleton tx = txDataToSkeleton(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;
}
uint8_t verifyBobErc20PaymentData(BobSendsErc20PaymentInput input, char *data)
{
std::stringstream ss = bobSendsErc20PaymentData(input);
if (strcmp(ss.str().c_str(), data) != 0) {
printf("Bob payment data %s != expected %s\n", data, ss.str().c_str());
return 0;
}
return 1;
}
char* bobReclaimsBobPayment(BobReclaimsBobPaymentInput input, BasicTxData txData)
{
TransactionSkeleton tx = txDataToSkeleton(txData);
std::stringstream ss;
ss << "0xb7cc2312"
u256 amount = jsToU256(input.amount);
dev::Address tokenAddress = jsToAddress(input.tokenAddress);
if (tokenAddress != ZeroAddress) {
uint8_t decimals = getErc20Decimals(input.tokenAddress);
if (decimals < 18) {
amount /= boost::multiprecision::pow(u256(10), 18 - decimals);
}
}
ss << "0xe45ef4ad"
<< toHex(jsToBytes(input.paymentId))
<< toHex(toBigEndian(jsToU256(input.amount)))
<< toHex(toBigEndian(jsToU256(input.bobCanClaimAfter)))
<< toHex(toBigEndian(amount))
<< "000000000000000000000000"
<< toHex(jsToAddress(input.aliceAddress))
<< "000000000000000000000000"
<< toHex(jsToAddress(input.tokenAddress))
<< toHex(tokenAddress)
<< toHex(jsToBytes(input.aliceHash))
<< "000000000000000000000000";
tx.data = jsToBytes(ss.str());
char* rawTx = signTx(tx, txData.secretKey);
char* result = sendRawTx(rawTx);
char* result = sendRawTxWaitConfirm(rawTx);
free(rawTx);
return result;
}
@ -293,20 +447,25 @@ char* aliceSpendsBobPayment(AliceSpendsBobPaymentInput input, BasicTxData txData
{
TransactionSkeleton tx = txDataToSkeleton(txData);
std::stringstream ss;
ss << "0x97004255"
u256 amount = jsToU256(input.amount);
dev::Address tokenAddress = jsToAddress(input.tokenAddress);
if (tokenAddress != ZeroAddress) {
uint8_t decimals = getErc20Decimals(input.tokenAddress);
if (decimals < 18) {
amount /= boost::multiprecision::pow(u256(10), 18 - decimals);
}
}
ss << "0x113ee583"
<< toHex(jsToBytes(input.paymentId))
<< toHex(toBigEndian(jsToU256(input.amount)))
<< toHex(toBigEndian(jsToU256(input.bobCanClaimAfter)))
<< toHex(toBigEndian(amount))
<< toHex(jsToBytes(input.aliceSecret))
<< "000000000000000000000000"
<< toHex(jsToAddress(input.bobAddress))
<< "000000000000000000000000"
<< toHex(jsToAddress(input.tokenAddress))
<< "00000000000000000000000000000000000000000000000000000000000000c0"
<< "0000000000000000000000000000000000000000000000000000000000000020"
<< toHex(jsToBytes(input.aliceSecret));
<< toHex(tokenAddress);
tx.data = jsToBytes(ss.str());
char* rawTx = signTx(tx, txData.secretKey);
char* result = sendRawTx(rawTx);
char* result = sendRawTxWaitConfirm(rawTx);
free(rawTx);
return result;
}
@ -339,12 +498,12 @@ uint64_t getEthBalance(char* address)
{
char* hexBalance = getEthBalanceRequest(address);
// convert wei to satoshi
u256 balance = jsToU256(hexBalance) / exp10<10>();
u256 balance = jsToU256(hexBalance) / boost::multiprecision::pow(u256(10), 10);
free(hexBalance);
return static_cast<uint64_t>(balance);
}
uint64_t getErc20Balance(char* address, char* tokenAddress)
uint64_t getErc20BalanceSatoshi(char *address, char *tokenAddress)
{
std::stringstream ss;
ss << "0x70a08231"
@ -353,11 +512,54 @@ uint64_t getErc20Balance(char* address, char* tokenAddress)
std::stringstream& resultStream = *(new std::stringstream);
char* hexBalance = ethCall(tokenAddress, ss.str().c_str());
// convert wei to satoshi
u256 balance = jsToU256(hexBalance) / exp10<10>();
uint8_t decimals = getErc20Decimals(tokenAddress);
u256 balance = jsToU256(hexBalance);
if (decimals < 18) {
balance *= boost::multiprecision::pow(u256(10), 18 - decimals);
}
balance /= boost::multiprecision::pow(u256(10), 10);
free(hexBalance);
return static_cast<uint64_t>(balance);
}
char *getErc20BalanceHexWei(char *address, char *tokenAddress)
{
std::stringstream ss;
ss << "0x70a08231"
<< "000000000000000000000000"
<< toHex(jsToAddress(address));
char *hexBalance = ethCall(tokenAddress, ss.str().c_str());
return hexBalance;
}
uint64_t getErc20Allowance(char *owner, char *spender, char *tokenAddress)
{
std::stringstream ss;
ss << "0xdd62ed3e"
<< "000000000000000000000000"
<< toHex(jsToAddress(owner))
<< "000000000000000000000000"
<< toHex(jsToAddress(spender));
char* hexAllowance = ethCall(tokenAddress, ss.str().c_str());
uint8_t decimals = getErc20Decimals(tokenAddress);
u256 allowance = jsToU256(hexAllowance);
if (decimals < 18) {
allowance *= boost::multiprecision::pow(u256(10), 18 - decimals);
}
// convert wei to satoshi
allowance /= boost::multiprecision::pow(u256(10), 10);
free(hexAllowance);
return static_cast<uint64_t>(allowance);
}
uint8_t getErc20Decimals(char *tokenAddress)
{
char* hexDecimals = ethCall(tokenAddress, "0x313ce567");
auto decimals = (uint8_t) strtol(hexDecimals, NULL, 0);
free(hexDecimals);
return decimals;
}
void uint8arrayToHex(char *dest, uint8_t *input, int len)
{
strcpy(dest, "0x");
@ -373,3 +575,82 @@ void satoshisToWei(char *dest, uint64_t input)
sprintf(dest, "%" PRIu64, input);
strcat(dest, "0000000000");
}
uint64_t weiToSatoshi(char *wei)
{
u256 satoshi = jsToU256(wei) / boost::multiprecision::pow(u256(10), 10);
return static_cast<uint64_t>(satoshi);
}
char *sendEth(char *to, char *amount, char *privKey, uint8_t waitConfirm)
{
TransactionSkeleton tx;
char *from = privKey2Addr(privKey), *result;
tx.from = jsToAddress(from);
tx.to = jsToAddress(to);
tx.value = jsToU256(amount);
tx.gas = 21000;
tx.gasPrice = getGasPriceFromStation() * boost::multiprecision::pow(u256(10), 9);
tx.nonce = getNonce(from);
free(from);
char *rawTx = signTx(tx, privKey);
if (waitConfirm == 0) {
result = sendRawTx(rawTx);
} else {
result = sendRawTxWaitConfirm(rawTx);
}
free(rawTx);
return result;
}
std::stringstream getErc20TransferData(char *tokenAddress, char *to, char *amount)
{
u256 amountWei = jsToU256(amount);
uint8_t decimals = getErc20Decimals(tokenAddress);
if (decimals < 18) {
amountWei /= boost::multiprecision::pow(u256(10), 18 - decimals);
}
// convert wei to satoshi
std::stringstream ss;
ss << "0xa9059cbb"
<< "000000000000000000000000"
<< toHex(jsToAddress(to))
<< toHex(toBigEndian(amountWei));
return ss;
}
char *sendErc20(char *tokenAddress, char *to, char *amount, char *privKey, uint8_t waitConfirm)
{
TransactionSkeleton tx;
char *from = privKey2Addr(privKey), *result;
tx.from = jsToAddress(from);
tx.to = jsToAddress(tokenAddress);
tx.value = 0;
tx.gas = 60000;
tx.gasPrice = getGasPriceFromStation() * boost::multiprecision::pow(u256(10), 9);
tx.nonce = getNonce(from);
free(from);
std::stringstream ss = getErc20TransferData(tokenAddress, to, amount);
tx.data = jsToBytes(ss.str());
char *rawTx = signTx(tx, privKey);
if (waitConfirm == 0) {
result = sendRawTx(rawTx);
} else {
result = sendRawTxWaitConfirm(rawTx);
}
free(rawTx);
return result;
}
uint8_t verifyAliceErc20FeeData(char* tokenAddress, char *to, char *amount, char *data)
{
std::stringstream ss = getErc20TransferData(tokenAddress, to, amount);
if (strcmp(ss.str().c_str(), data) != 0) {
printf("Alice ERC20 fee data %s is not equal to expected %s\n", data, ss.str().c_str());
return 0;
}
return 1;
}

69
iguana/exchanges/etomicswap/etomiclib.h

@ -6,19 +6,17 @@
#ifdef __cplusplus
extern "C" {
#endif
#define ETOMIC_TESTNET
#ifdef ETOMIC_TESTNET
#define ETOMIC_ALICECONTRACT "0xe1D4236C5774D35Dc47dcc2E5E0CcFc463A3289c"
#define ETOMIC_BOBCONTRACT "0x9387Fd3a016bB0205e4e131Dde886B9d2BC000A2"
#define ETOMIC_GASMULT 100
#define ETOMIC_ALICECONTRACT "0xe1d4236c5774d35dc47dcc2e5e0ccfc463a3289c"
#define ETOMIC_BOBCONTRACT "0x2a8e4f9ae69c86e277602c6802085febc4bd5986"
#else
#define ETOMIC_ALICECONTRACT "0x9bC5418CEdED51dB08467fc4b62F32C5D9EBdA55"
#define ETOMIC_BOBCONTRACT "0xB1Ad803ea4F57401639c123000C75F5B66E4D123"
#define ETOMIC_GASMULT 4
#define ETOMIC_ALICECONTRACT "0x9bc5418ceded51db08467fc4b62f32c5d9ebda55"
#define ETOMIC_BOBCONTRACT "0xfef736cfa3b884669a4e0efd6a081250cce228e7"
#endif
#define ETOMIC_SATOSHICAT "0000000000"
#define EMPTY_ETH_TX_ID "0x0000000000000000000000000000000000000000000000000000000000000000"
#define ETH_FEE_ACCEPTOR "0x485d2cc2d13a9e12e4b53d606db1c8adc884fb8a"
typedef struct {
char from[65];
@ -65,6 +63,7 @@ typedef struct {
char depositId[70];
char aliceAddress[65];
char bobHash[65];
uint64_t lockTime;
} BobSendsEthDepositInput;
typedef struct {
@ -73,6 +72,7 @@ typedef struct {
char tokenAddress[65];
char aliceAddress[65];
char bobHash[65];
uint64_t lockTime;
} BobSendsErc20DepositInput;
typedef struct {
@ -81,7 +81,6 @@ typedef struct {
char tokenAddress[65];
char aliceAddress[65];
char bobSecret[70];
char aliceCanClaimAfter[100];
} BobRefundsDepositInput;
typedef struct {
@ -90,13 +89,13 @@ typedef struct {
char tokenAddress[65];
char bobAddress[65];
char bobHash[65];
char aliceCanClaimAfter[100];
} AliceClaimsBobDepositInput;
typedef struct {
char paymentId[70];
char aliceAddress[65];
char aliceHash[65];
uint64_t lockTime;
} BobSendsEthPaymentInput;
typedef struct {
@ -105,6 +104,7 @@ typedef struct {
char tokenAddress[65];
char aliceAddress[65];
char aliceHash[65];
uint64_t lockTime;
} BobSendsErc20PaymentInput;
typedef struct {
@ -113,7 +113,6 @@ typedef struct {
char tokenAddress[65];
char aliceAddress[65];
char aliceHash[65];
char bobCanClaimAfter[100];
} BobReclaimsBobPaymentInput;
typedef struct {
@ -122,29 +121,67 @@ typedef struct {
char tokenAddress[65];
char aliceSecret[70];
char bobAddress[65];
char bobCanClaimAfter[100];
} AliceSpendsBobPaymentInput;
char* approveErc20(char amount[100], char* from, char* secret);
typedef struct {
char tokenAddress[65];
char owner[65];
char spender[65];
char amount[100];
char secret[70];
} ApproveErc20Input;
char *approveErc20(ApproveErc20Input input);
char* aliceSendsEthPayment(AliceSendsEthPaymentInput input, BasicTxData txData);
uint8_t verifyAliceEthPaymentData(AliceSendsEthPaymentInput input, char *data);
char* aliceSendsErc20Payment(AliceSendsErc20PaymentInput input, BasicTxData txData);
uint8_t verifyAliceErc20PaymentData(AliceSendsErc20PaymentInput input, char *data);
char* aliceReclaimsAlicePayment(AliceReclaimsAlicePaymentInput input, BasicTxData txData);
char* bobSpendsAlicePayment(BobSpendsAlicePaymentInput input, BasicTxData txData);
char* bobSendsEthDeposit(BobSendsEthDepositInput input, BasicTxData txData);
uint8_t verifyBobEthDepositData(BobSendsEthDepositInput input, char *data);
char* bobSendsErc20Deposit(BobSendsErc20DepositInput input, BasicTxData txData);
uint8_t verifyBobErc20DepositData(BobSendsErc20DepositInput input, char *data);
char* bobRefundsDeposit(BobRefundsDepositInput input, BasicTxData txData);
char* aliceClaimsBobDeposit(AliceClaimsBobDepositInput input, BasicTxData txData);
char* bobSendsEthPayment(BobSendsEthPaymentInput input, BasicTxData txData);
uint8_t verifyBobEthPaymentData(BobSendsEthPaymentInput input, char *data);
char* bobSendsErc20Payment(BobSendsErc20PaymentInput input, BasicTxData txData);
uint8_t verifyBobErc20PaymentData(BobSendsErc20PaymentInput input, char *data);
char* bobReclaimsBobPayment(BobReclaimsBobPaymentInput input, BasicTxData txData);
char* aliceSpendsBobPayment(AliceSpendsBobPaymentInput input, BasicTxData txData);
char* privKey2Addr(char* privKey);
char* pubKey2Addr(char* pubKey);
char* getPubKeyFromPriv(char* privKey);
// returns satoshis, not wei!
uint64_t getEthBalance(char* address);
uint64_t getErc20Balance(char* address, char tokenAddress[65]);
uint64_t getErc20BalanceSatoshi(char* address, char tokenAddress[65]);
char *getErc20BalanceHexWei(char* address, char tokenAddress[65]);
uint8_t getErc20Decimals(char *tokenAddress);
// returns satoshis, not wei!
uint64_t getErc20Allowance(char *owner, char *spender, char *tokenAddress);
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, 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
#ifdef __cplusplus
}

2
iguana/secp256k1/CMakeLists.txt

@ -1,5 +1,5 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
file(GLOB sources "src/secp256k1.c")
file(GLOB headers "src/*.h")
add_definitions(-DHAVE_CONFIG_H)
add_definitions(-DHAVE_CONFIG_H -DEXTERNAL_SECP256)
add_library(libsecp256k1 ${sources} ${headers})

78
iguana/secp256k1/src/secp256k1.c

@ -66,6 +66,8 @@ struct secp256k1_context_struct {
secp256k1_callback error_callback;
};
#ifndef EXTERNAL_SECP256
secp256k1_context* secp256k1_context_create(unsigned int flags) {
secp256k1_context* ret = (secp256k1_context*)checked_malloc(&default_error_callback, sizeof(secp256k1_context));
ret->illegal_callback = default_illegal_callback;
@ -137,39 +139,6 @@ void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(co
ctx->error_callback.data = data;
}
static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) {
if (sizeof(secp256k1_ge_storage) == 64) {
/* When the secp256k1_ge_storage type is exactly 64 byte, use its
* representation inside secp256k1_pubkey, as conversion is very fast.
* Note that secp256k1_pubkey_save must use the same representation. */
secp256k1_ge_storage s;
memcpy(&s, &pubkey->data[0], 64);
secp256k1_ge_from_storage(ge, &s);
} else {
/* Otherwise, fall back to 32-byte big endian for X and Y. */
secp256k1_fe x, y;
secp256k1_fe_set_b32(&x, pubkey->data);
secp256k1_fe_set_b32(&y, pubkey->data + 32);
secp256k1_ge_set_xy(ge, &x, &y);
}
ARG_CHECK(!secp256k1_fe_is_zero(&ge->x));
return 1;
}
static void secp256k1_pubkey_save(secp256k1_pubkey* pubkey, secp256k1_ge* ge) {
if (sizeof(secp256k1_ge_storage) == 64) {
secp256k1_ge_storage s;
secp256k1_ge_to_storage(&s, ge);
memcpy(&pubkey->data[0], &s, 64);
} else {
VERIFY_CHECK(!secp256k1_ge_is_infinity(ge));
secp256k1_fe_normalize_var(&ge->x);
secp256k1_fe_normalize_var(&ge->y);
secp256k1_fe_get_b32(pubkey->data, &ge->x);
secp256k1_fe_get_b32(pubkey->data + 32, &ge->y);
}
}
int secp256k1_ec_pubkey_parse(const secp256k1_context* ctx, secp256k1_pubkey* pubkey, const unsigned char *input, size_t inputlen) {
secp256k1_ge Q;
@ -577,14 +546,49 @@ int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *
# include "modules/ecdh/main_impl.h"
#endif
#ifdef ENABLE_MODULE_SCHNORR
# include "modules/schnorr/main_impl.h"
#endif
#ifdef ENABLE_MODULE_RECOVERY
# include "modules/recovery/main_impl.h"
#endif
#endif
static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) {
if (sizeof(secp256k1_ge_storage) == 64) {
/* When the secp256k1_ge_storage type is exactly 64 byte, use its
* representation inside secp256k1_pubkey, as conversion is very fast.
* Note that secp256k1_pubkey_save must use the same representation. */
secp256k1_ge_storage s;
memcpy(&s, &pubkey->data[0], 64);
secp256k1_ge_from_storage(ge, &s);
} else {
/* Otherwise, fall back to 32-byte big endian for X and Y. */
secp256k1_fe x, y;
secp256k1_fe_set_b32(&x, pubkey->data);
secp256k1_fe_set_b32(&y, pubkey->data + 32);
secp256k1_ge_set_xy(ge, &x, &y);
}
ARG_CHECK(!secp256k1_fe_is_zero(&ge->x));
return 1;
}
static void secp256k1_pubkey_save(secp256k1_pubkey* pubkey, secp256k1_ge* ge) {
if (sizeof(secp256k1_ge_storage) == 64) {
secp256k1_ge_storage s;
secp256k1_ge_to_storage(&s, ge);
memcpy(&pubkey->data[0], &s, 64);
} else {
VERIFY_CHECK(!secp256k1_ge_is_infinity(ge));
secp256k1_fe_normalize_var(&ge->x);
secp256k1_fe_normalize_var(&ge->y);
secp256k1_fe_get_b32(pubkey->data, &ge->x);
secp256k1_fe_get_b32(pubkey->data + 32, &ge->y);
}
}
#ifdef ENABLE_MODULE_SCHNORR
# include "modules/schnorr/main_impl.h"
#endif
#ifdef ENABLE_MODULE_RANGEPROOF
# include "modules/rangeproof/main_impl.h"
#endif

Loading…
Cancel
Save