diff --git a/crypto777/OS_portable.h b/crypto777/OS_portable.h index a90889279..23a051b01 100755 --- a/crypto777/OS_portable.h +++ b/crypto777/OS_portable.h @@ -359,6 +359,7 @@ void calc_base64_decodestr(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); void calc_hexstr(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); void calc_unhexstr(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); int32_t safecopy(char *dest,char *src,long len); +double dxblend(double *destp,double val,double decay); uint64_t calc_ipbits(char *ip_port); void expand_ipbits(char *ipaddr,uint64_t ipbits); diff --git a/crypto777/bitcoind_RPC.c b/crypto777/bitcoind_RPC.c index 2a4636801..975208ddd 100755 --- a/crypto777/bitcoind_RPC.c +++ b/crypto777/bitcoind_RPC.c @@ -137,7 +137,7 @@ char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char * if ( url[0] == 0 ) strcpy(url,"http://127.0.0.1:7776"); if ( specialcase != 0 && (0) ) - printf("<<<<<<<<<<< bitcoind_RPC: debug.(%s) url.(%s) command.(%s) params.(%s)\n",debugstr,url,command,params); + printf("<<<<<<<<<<< bitcoind_RPC: userpass.(%s) url.(%s) command.(%s) params.(%s)\n",userpass,url,command,params); try_again: if ( retstrp != 0 ) *retstrp = 0; diff --git a/iguana/coins/jumblr b/iguana/coins/jumblr new file mode 100755 index 000000000..5b52ce9a6 --- /dev/null +++ b/iguana/coins/jumblr @@ -0,0 +1,4 @@ +~/komodo/src/komodod -ac_name=JUMBLR -ac_supply=999999 -addnode=78.47.196.146 & + +curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"JUMBLR.conf\",\"path\":\"${HOME#"/"}/.komodo/JUMBLR\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"JUMBLR\",\"name\":\"JUMBLR\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"7223759e\",\"p2p\":15105,\"rpc\":15106,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}" + diff --git a/iguana/coins/jumblr_osx b/iguana/coins/jumblr_osx new file mode 100755 index 000000000..dd50b1842 --- /dev/null +++ b/iguana/coins/jumblr_osx @@ -0,0 +1,3 @@ +/Applications/komodoOSX.app/Contents/komodod -ac_name=JUMBLR -ac_supply=999999 -addnode=78.47.196.146 & +curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"JUMBLR.conf\",\"path\":\"/${HOME#"/"}/Library/Application\ Support/Komodo/JUMBLR\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"JUMBLR\",\"name\":\"JUMBLR\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"7223759e\",\"p2p\":15105,\"rpc\":15106,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}" + diff --git a/iguana/coins/mesh_7776 b/iguana/coins/mesh_7776 index 01d8dd737..bcccf8d8d 100755 --- a/iguana/coins/mesh_7776 +++ b/iguana/coins/mesh_7776 @@ -1 +1 @@ -curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"MESH.conf\",\"path\":\"${HOME#"/"}/.komodo/MESH\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"MESH\",\"name\":\"MESH\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"4d6bbfb6\",\"p2p\":8399,\"rpc\":8400,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}" +curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"MESH.conf\",\"path\":\"${HOME#"/"}/.komodo/MESH\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"MESH\",\"name\":\"MESH\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"4d6bbfb6\",\"p2p\":9454,\"rpc\":9455,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}" diff --git a/iguana/coins/revs b/iguana/coins/revs new file mode 100755 index 000000000..f2cf9ef72 --- /dev/null +++ b/iguana/coins/revs @@ -0,0 +1,3 @@ +./komodod -ac_name=REVS -ac_supply=1300000 -addnode=78.47.196.146 & +curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"REVS.conf\",\"path\":\"${HOME#"/"}/.komodo/REVS\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"REVS\",\"name\":\"REVS\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"905c3498\",\"p2p\":10195,\"rpc\":10196,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}" + diff --git a/iguana/coins/revs_osx b/iguana/coins/revs_osx new file mode 100755 index 000000000..c98b4fabb --- /dev/null +++ b/iguana/coins/revs_osx @@ -0,0 +1,3 @@ +/Applications/komodoOSX.app/Contents/komodod -ac_name=REVS -ac_supply=1300000 -addnode=78.47.196.146 & +curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"REVS.conf\",\"path\":\"/${HOME#"/"}/Library/Application\ Support/Komodo/REVS\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"REVS\",\"name\":\"REVS\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"905c3498\",\"p2p\":10195,\"rpc\":10196,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}" + diff --git a/iguana/exchanges/LP_bitcoin.c b/iguana/exchanges/LP_bitcoin.c index 078bc1d3f..c7ee8b218 100644 --- a/iguana/exchanges/LP_bitcoin.c +++ b/iguana/exchanges/LP_bitcoin.c @@ -18,6 +18,342 @@ // marketmaker // +union iguana_stacknum { int32_t val; int64_t val64; uint8_t rmd160[20]; bits256 hash2; uint8_t pubkey[33]; uint8_t sig[74]; }; +struct iguana_stackdata { uint8_t *data; uint16_t size; union iguana_stacknum U; }; + +char *bitcoin_base58encode(char *coinaddr,uint8_t *data,int32_t datalen); +int32_t bitcoin_base58decode(uint8_t *data,char *coinaddr); + +#define IGUANA_MAXSCRIPTSIZE 10001 +#define IGUANA_SEQUENCEID_FINAL 0xfffffffe + +#define IGUANA_SCRIPT_NULL 0 +#define IGUANA_SCRIPT_76AC 1 +#define IGUANA_SCRIPT_76A988AC 2 +#define IGUANA_SCRIPT_P2SH 3 +#define IGUANA_SCRIPT_OPRETURN 4 +#define IGUANA_SCRIPT_3of3 5 +#define IGUANA_SCRIPT_2of3 6 +#define IGUANA_SCRIPT_1of3 7 +#define IGUANA_SCRIPT_2of2 8 +#define IGUANA_SCRIPT_1of2 9 +#define IGUANA_SCRIPT_MSIG 10 +#define IGUANA_SCRIPT_DATA 11 +#define IGUANA_SCRIPT_AC 12 +#define IGUANA_SCRIPT_1of1 13 +#define IGUANA_SCRIPT_STRANGE 15 + +#define MAX_SCRIPT_ELEMENT_SIZE 520 +#define MAX_OPS_PER_SCRIPT 201 // Maximum number of non-push operations per script +#define MAX_PUBKEYS_PER_MULTISIG 20 // Maximum number of public keys per multisig + +#define IGUANA_MAXSTACKITEMS ((int32_t)(IGUANA_MAXSCRIPTSIZE / sizeof(uint32_t))) +#define IGUANA_MAXSTACKDEPTH 128 +struct iguana_interpreter +{ + int32_t active,ifdepth,elsedepth,codeseparator,stackdepth,altstackdepth,maxstackdepth; + int8_t lastpath[IGUANA_MAXSTACKDEPTH]; + cJSON *logarray; + struct iguana_stackdata stack[]; +}; +static struct bitcoin_opcode { UT_hash_handle hh; uint8_t opcode,flags,stackitems; int8_t extralen; } *OPTABLE; static char *OPCODES[0x100]; static int32_t OPCODELENS[0x100]; + +#define SIGHASH_ALL 1 +#define SIGHASH_NONE 2 +#define SIGHASH_SINGLE 3 +#define SIGHASH_ANYONECANPAY 0x80 + +#define SCRIPT_OP_NOP 0x00 +#define SCRIPT_OP_TRUE 0x51 +#define SCRIPT_OP_2 0x52 +#define SCRIPT_OP_3 0x53 +#define SCRIPT_OP_4 0x54 +#define SCRIPT_OP_IF 0x63 +#define SCRIPT_OP_ELSE 0x67 +#define SCRIPT_OP_RETURN 0x6a +#define SCRIPT_OP_DUP 0x76 +#define SCRIPT_OP_ENDIF 0x68 +#define SCRIPT_OP_DROP 0x75 +#define SCRIPT_OP_EQUALVERIFY 0x88 +#define SCRIPT_OP_SHA256 0xa8 +#define SCRIPT_OP_HASH160 0xa9 + +#define SCRIPT_OP_EQUAL 0x87 +#define SCRIPT_OP_CHECKSIG 0xac +#define SCRIPT_OP_CHECKMULTISIG 0xae +#define SCRIPT_OP_CHECKSEQUENCEVERIFY 0xb2 +#define SCRIPT_OP_CHECKLOCKTIMEVERIFY 0xb1 +#define IGUANA_OP_0 0x00 +#define IGUANA_OP_PUSHDATA1 0x4c +#define IGUANA_OP_PUSHDATA2 0x4d +#define IGUANA_OP_PUSHDATA4 0x4e +#define IGUANA_OP_1NEGATE 0x4f +#define IGUANA_OP_1 0x51 +#define IGUANA_OP_16 0x60 +#define IGUANA_OP_NOP 0x61 +#define IGUANA_OP_IF 0x63 +#define IGUANA_OP_NOTIF 0x64 +#define IGUANA_OP_ELSE 0x67 +#define IGUANA_OP_ENDIF 0x68 +#define IGUANA_OP_VERIFY 0x69 +#define IGUANA_OP_RETURN 0x6a + +#define IGUANA_OP_TOALTSTACK 0x6b +#define IGUANA_OP_FROMALTSTACK 0x6c +#define IGUANA_OP_2DROP 0x6d +#define IGUANA_OP_2DUP 0x6e +#define IGUANA_OP_3DUP 0x6f +#define IGUANA_OP_2OVER 0x70 +#define IGUANA_OP_2ROT 0x71 +#define IGUANA_OP_2SWAP 0x72 +#define IGUANA_OP_IFDUP 0x73 +#define IGUANA_OP_DEPTH 0x74 +#define IGUANA_OP_DROP 0x75 +#define IGUANA_OP_DUP 0x76 +#define IGUANA_OP_NIP 0x77 +#define IGUANA_OP_OVER 0x78 +#define IGUANA_OP_PICK 0x79 +#define IGUANA_OP_ROLL 0x7a +#define IGUANA_OP_ROT 0x7b +#define IGUANA_OP_SWAP 0x7c +#define IGUANA_OP_TUCK 0x7d + +#define IGUANA_OP_EQUAL 0x87 +#define IGUANA_OP_EQUALVERIFY 0x88 + +#define IGUANA_OP_1ADD 0x8b +#define IGUANA_OP_1SUB 0x8c +#define IGUANA_OP_NEGATE 0x8f +#define IGUANA_OP_ABS 0x90 +#define IGUANA_OP_NOT 0x91 +#define IGUANA_OP_0NOTEQUAL 0x92 +#define IGUANA_OP_ADD 0x93 +#define IGUANA_OP_SUB 0x94 + +#define IGUANA_OP_BOOLAND 0x9a +#define IGUANA_OP_BOOLOR 0x9b +#define IGUANA_OP_NUMEQUAL 0x9c +#define IGUANA_OP_NUMEQUALVERIFY 0x9d +#define IGUANA_OP_NUMNOTEQUAL 0x9e +#define IGUANA_OP_LESSTHAN 0x9f +#define IGUANA_OP_GREATERTHAN 0xa0 +#define IGUANA_OP_LESSTHANOREQUAL 0xa1 +#define IGUANA_OP_GREATERTHANOREQUAL 0xa2 +#define IGUANA_OP_MIN 0xa3 +#define IGUANA_OP_MAX 0xa4 +#define IGUANA_OP_WITHIN 0xa5 + +#define IGUANA_OP_RIPEMD160 0xa6 +#define IGUANA_OP_SHA1 0xa7 +#define IGUANA_OP_SHA256 0xa8 +#define IGUANA_OP_HASH160 0xa9 +#define IGUANA_OP_HASH256 0xaa +#define IGUANA_OP_CODESEPARATOR 0xab +#define IGUANA_OP_CHECKSIG 0xac +#define IGUANA_OP_CHECKSIGVERIFY 0xad +#define IGUANA_OP_CHECKMULTISIG 0xae +#define IGUANA_OP_CHECKMULTISIGVERIFY 0xaf + +#define IGUANA_OP_NOP1 0xb0 +#define IGUANA_OP_CHECKLOCKTIMEVERIFY 0xb1 +#define IGUANA_OP_CHECKSEQUENCEVERIFY 0xb2 +#define IGUANA_OP_NOP10 0xb9 + +#define IGUANA_OP_COMBINEPUBKEYS 0xc0 +#define IGUANA_OP_CHECKSCHNORR 0xc1 +#define IGUANA_OP_CHECKSCHNORRVERIFY 0xc2 + +// https://github.com/TierNolan/bips/blob/cpkv/bip-cprkv.mediawiki +#define IGUANA_OP_CHECKPRIVATEKEY 0xc3 +#define IGUANA_OP_CHECKPRIVATEKEYVERIFY 0xc4 + +#define IGUANA_NOPFLAG 1 +#define IGUANA_ALWAYSILLEGAL 2 +#define IGUANA_EXECUTIONILLEGAL 4 +#define IGUANA_POSTVERIFY 8 +#define IGUANA_CRYPTOFLAG 16 +#define IGUANA_MATHFLAG 32 +#define IGUANA_CONTROLFLAG 64 +#define IGUANA_STACKFLAG 128 + +enum opcodetype +{ + // push value + OP_0 = 0x00, + OP_FALSE = OP_0, + OP_PUSHDATA1 = 0x4c, + OP_PUSHDATA2 = 0x4d, + OP_PUSHDATA4 = 0x4e, + OP_1NEGATE = 0x4f, + OP_RESERVED = 0x50, + OP_1 = 0x51, + OP_TRUE=OP_1, + OP_2 = 0x52, + OP_3 = 0x53, + OP_4 = 0x54, + OP_5 = 0x55, + OP_6 = 0x56, + OP_7 = 0x57, + OP_8 = 0x58, + OP_9 = 0x59, + OP_10 = 0x5a, + OP_11 = 0x5b, + OP_12 = 0x5c, + OP_13 = 0x5d, + OP_14 = 0x5e, + OP_15 = 0x5f, + OP_16 = 0x60, + + // control + OP_NOP = 0x61, + OP_VER = 0x62, + OP_IF = 0x63, + OP_NOTIF = 0x64, + OP_VERIF = 0x65, + OP_VERNOTIF = 0x66, + OP_ELSE = 0x67, + OP_ENDIF = 0x68, + OP_VERIFY = 0x69, + OP_RETURN = 0x6a, + + // stack ops + OP_TOALTSTACK = 0x6b, + OP_FROMALTSTACK = 0x6c, + OP_2DROP = 0x6d, + OP_2DUP = 0x6e, + OP_3DUP = 0x6f, + OP_2OVER = 0x70, + OP_2ROT = 0x71, + OP_2SWAP = 0x72, + OP_IFDUP = 0x73, + OP_DEPTH = 0x74, + OP_DROP = 0x75, + OP_DUP = 0x76, + OP_NIP = 0x77, + OP_OVER = 0x78, + OP_PICK = 0x79, + OP_ROLL = 0x7a, + OP_ROT = 0x7b, + OP_SWAP = 0x7c, + OP_TUCK = 0x7d, + + // splice ops + OP_CAT = 0x7e, + OP_SUBSTR = 0x7f, + OP_LEFT = 0x80, + OP_RIGHT = 0x81, + OP_SIZE = 0x82, + + // bit logic + OP_INVERT = 0x83, + OP_AND = 0x84, + OP_OR = 0x85, + OP_XOR = 0x86, + OP_EQUAL = 0x87, + OP_EQUALVERIFY = 0x88, + OP_RESERVED1 = 0x89, + OP_RESERVED2 = 0x8a, + + // numeric + OP_1ADD = 0x8b, + OP_1SUB = 0x8c, + OP_2MUL = 0x8d, + OP_2DIV = 0x8e, + OP_NEGATE = 0x8f, + OP_ABS = 0x90, + OP_NOT = 0x91, + OP_0NOTEQUAL = 0x92, + + OP_ADD = 0x93, + OP_SUB = 0x94, + OP_MUL = 0x95, + OP_DIV = 0x96, + OP_MOD = 0x97, + OP_LSHIFT = 0x98, + OP_RSHIFT = 0x99, + + OP_BOOLAND = 0x9a, + OP_BOOLOR = 0x9b, + OP_NUMEQUAL = 0x9c, + OP_NUMEQUALVERIFY = 0x9d, + OP_NUMNOTEQUAL = 0x9e, + OP_LESSTHAN = 0x9f, + OP_GREATERTHAN = 0xa0, + OP_LESSTHANOREQUAL = 0xa1, + OP_GREATERTHANOREQUAL = 0xa2, + OP_MIN = 0xa3, + OP_MAX = 0xa4, + + OP_WITHIN = 0xa5, + + // crypto + OP_RIPEMD160 = 0xa6, + OP_SHA1 = 0xa7, + OP_SHA256 = 0xa8, + OP_HASH160 = 0xa9, + OP_HASH256 = 0xaa, + OP_CODESEPARATOR = 0xab, + OP_CHECKSIG = 0xac, + OP_CHECKSIGVERIFY = 0xad, + OP_CHECKMULTISIG = 0xae, + OP_CHECKMULTISIGVERIFY = 0xaf, + + // expansion + OP_NOP1 = 0xb0, + OP_CHECKLOCKTIMEVERIFY = 0xb1, + OP_CHECKSEQUENCEVERIFY = 0xb2, + OP_NOP4 = 0xb3, + OP_NOP5 = 0xb4, + OP_NOP6 = 0xb5, + OP_NOP7 = 0xb6, + OP_NOP8 = 0xb7, + OP_NOP9 = 0xb8, + OP_NOP10 = 0xb9, + + OP_COMBINEPUBKEYS = 0xc0, + OP_CHECKSCHNORR = 0xc1, + OP_CHECKSCHNORRVERIFY = 0xc2, + OP_CHECKPRIVATEKEY = 0xc3, + OP_CHECKPRIVATEKEYVERIFY = 0xc4, + + // template matching params + //OP_SMALLINTEGER = 0xfa, + //OP_PUBKEYS = 0xfb, + //OP_PUBKEYHASH = 0xfd, + //OP_PUBKEY = 0xfe, + + OP_INVALIDOPCODE = 0xff, +}; + +struct { bits256 privkey; uint8_t rmd160[20]; } LP_privkeys[100]; int32_t LP_numprivkeys; + +bits256 LP_privkeyfind(uint8_t rmd160[20]) +{ + int32_t i; static bits256 zero; + for (i=0; i no privkey\n"); + return(zero); +} + +int32_t LP_privkeyadd(bits256 privkey,uint8_t rmd160[20]) +{ + bits256 tmpkey; + tmpkey = LP_privkeyfind(rmd160); + if ( bits256_nonz(tmpkey) != 0 ) + return(-bits256_cmp(privkey,tmpkey)); + LP_privkeys[LP_numprivkeys].privkey = privkey; + memcpy(LP_privkeys[LP_numprivkeys].rmd160,rmd160,20); + //int32_t i; for (i=0; i<20; i++) + // printf("%02x",rmd160[i]); + //char str[65]; printf(" -> add privkey.(%s)\n",bits256_str(str,privkey)); + LP_numprivkeys++; + return(LP_numprivkeys); +} + int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp) { int32_t i; uint64_t x; @@ -366,6 +702,19 @@ void iguana_optableinit() } } +int32_t bitcoin_pubkeylen(const uint8_t *pubkey) +{ + if ( pubkey[0] == 2 || pubkey[0] == 3 ) + return(33); + else if ( pubkey[0] == 4 ) + return(65); + else + { + //printf("illegal pubkey.[%02x] %llx\n",pubkey[0],*(long long *)pubkey); + return(-1); + } +} + int32_t iguana_expandscript(char *asmstr,int32_t maxlen,uint8_t *script,int32_t scriptlen) { int32_t len,n,j,i = 0; uint8_t opcode; uint32_t val,extraflag; @@ -441,6 +790,1112 @@ int32_t iguana_expandscript(char *asmstr,int32_t maxlen,uint8_t *script,int32_t return(len); } +static inline int32_t is_delim(int32_t c) +{ + if ( c == 0 || c == ' ' || c == '\t' || c == '\r' || c == '\n' ) + return(1); + else return(0); +} + +static struct iguana_stackdata iguana_pop(struct iguana_interpreter *stacks) +{ + struct iguana_stackdata Snum; + Snum = stacks->stack[--stacks->stackdepth]; + memset(&stacks->stack[stacks->stackdepth],0,sizeof(Snum)); + return(Snum); +} + +static int32_t iguana_altpush(struct iguana_interpreter *stacks,struct iguana_stackdata Snum) +{ + stacks->stack[2*IGUANA_MAXSTACKITEMS - ++stacks->altstackdepth] = Snum; + return(stacks->altstackdepth); +} + +static struct iguana_stackdata iguana_altpop(struct iguana_interpreter *stacks) +{ + struct iguana_stackdata Snum,*ptr; + ptr = &stacks->stack[2*IGUANA_MAXSTACKITEMS - --stacks->altstackdepth]; + Snum = *ptr; + memset(ptr,0,sizeof(Snum)); + return(Snum); +} + +static struct iguana_stackdata iguana_clone(struct iguana_stackdata Snum) +{ + struct iguana_stackdata clone; + clone = Snum; + if ( Snum.data != 0 ) + { + clone.data = malloc(Snum.size); + memcpy(clone.data,Snum.data,Snum.size); + } + return(clone); +} + +static int32_t iguana_isnonz(struct iguana_stackdata Snum) +{ + uint8_t *buf; int32_t i; + if ( Snum.size == sizeof(int32_t) ) + return(Snum.U.val != 0); + else if ( Snum.size == sizeof(int64_t) ) + return(Snum.U.val64 != 0); + else if ( Snum.size == 20 ) + buf = Snum.U.rmd160; + else if ( Snum.size == sizeof(bits256) ) + buf = Snum.U.hash2.bytes; + else if ( Snum.size == 33 ) + buf = Snum.U.pubkey; + else if ( Snum.size < 74 ) + buf = Snum.U.sig; + else buf = Snum.data; + for (i=0; ilastpath[stacks->ifdepth] < 0 ) + return(0); + //printf("PUSH.(%lld %p %d)\n",(long long)num64,numbuf,numlen); + if ( stacks->maxstackdepth > 0 ) + { + if ( numbuf != 0 ) + { + int32_t i; for (i=0; istackdepth < stacks->maxstackdepth ) + { + if ( stacks->logarray != 0 ) + item = cJSON_CreateObject(); + memset(&Snum,0,sizeof(Snum)); + if ( numbuf != 0 ) + { + if ( numlen <= sizeof(int32_t) ) + { + iguana_rwnum(1,(void *)&num,numlen,numbuf); + numlen = sizeof(num); + Snum.U.val = num; + } + else if ( numlen <= sizeof(int64_t) ) + { + iguana_rwnum(1,(void *)&num64,numlen,numbuf); + numlen = sizeof(num64); + Snum.U.val64 = num64; + } + else if ( numlen == 20 ) + memcpy(Snum.U.rmd160,numbuf,20); + else if ( numlen == sizeof(bits256) ) + iguana_rwbignum(1,Snum.U.hash2.bytes,sizeof(Snum.U.hash2),numbuf); + else if ( numlen == 33 ) + memcpy(Snum.U.pubkey,numbuf,numlen); + else if ( numlen < 74 ) + memcpy(Snum.U.sig,numbuf,numlen); + else + { + Snum.data = malloc(numlen); + memcpy(Snum.data,numbuf,numlen); + if ( item != 0 ) + jaddnum(item,"push",numlen); + } + Snum.size = numlen; + if ( item != 0 ) + { + init_hexbytes_noT(tmpstr,numbuf,numlen); + jaddstr(item,"push",tmpstr); + } + } + else if ( num64 <= 0xffffffff ) // what about negative numbers? + { + Snum.U.val = num, Snum.size = sizeof(num); + if ( item != 0 ) + jaddnum(item,"push",Snum.U.val); + } + else + { + Snum.U.val64 = num64, Snum.size = sizeof(num64); + if ( item != 0 ) + jaddnum(item,"push",Snum.U.val64); + } + if ( item != 0 ) + { + jaddnum(item,"depth",stacks->stackdepth); + if ( stacks->logarray != 0 ) + jaddi(stacks->logarray,item); + } + stacks->stack[stacks->stackdepth++] = Snum; + } else return(-1); + } else stacks->stackdepth++; + return(0); +} + +int32_t iguana_databuf(uint8_t *databuf,struct iguana_stackdata Snum) +{ + if ( Snum.size == 4 ) + memcpy(databuf,&Snum.U.val,4); + else if ( Snum.size == 8 ) + memcpy(databuf,&Snum.U.val64,8); + else if ( Snum.size == 20 ) + memcpy(databuf,&Snum.U.rmd160,20); + else if ( Snum.size == 32 ) + memcpy(databuf,&Snum.U.hash2.bytes,32); + else if ( Snum.size == 33 ) + memcpy(databuf,&Snum.U.pubkey,33); + else if ( Snum.size < 74 ) + memcpy(databuf,&Snum.U.sig,Snum.size); + else memcpy(databuf,&Snum.data,Snum.size); + return(Snum.size); +} + +static int32_t iguana_cmp(struct iguana_stackdata *a,struct iguana_stackdata *b) +{ + if ( a->size == b->size ) + { + if ( a->size == 4 ) + return(a->U.val != b->U.val); + else if ( a->size == 8 ) + return(a->U.val64 != b->U.val64); + else if ( a->size == 20 ) + return(memcmp(a->U.rmd160,b->U.rmd160,sizeof(a->U.rmd160))); + else if ( a->size == 32 ) + return(memcmp(a->U.hash2.bytes,b->U.hash2.bytes,sizeof(a->U.hash2))); + else if ( a->size == 33 ) + return(memcmp(a->U.pubkey,b->U.pubkey,33)); + else if ( a->size < 74 ) + return(memcmp(a->U.sig,b->U.sig,a->size)); + else return(memcmp(a->data,b->data,sizeof(a->size))); + } + return(-1); +} + +static int32_t iguana_dataparse(struct iguana_interpreter *stacks,uint8_t *script,int32_t k,char *str,int32_t *lenp) +{ + int32_t n,c,len; char tmp[4]; + *lenp = 0; + c = str[0]; + n = is_hexstr(str,0); + if ( n > 0 ) + { + if ( (n & 1) != 0 ) + len = (n+1) >> 1; + else len = n >> 1; + if ( len > 0 && len < 76 ) + { + if ( len == 1 ) + { + if ( n == 1 ) + { + tmp[0] = '0'; + tmp[1] = c; + tmp[2] = 0; + decode_hex(&script[k],1,tmp), (*lenp) = 1; + iguana_pushdata(stacks,script[k],0,0); + if ( script[k] != 0 ) + script[k++] += (IGUANA_OP_1 - 1); + return(k); + } + else if ( n == 2 && c == '1' && str[1] == '0' && is_delim(str[2]) != 0 ) + { + script[k++] = (IGUANA_OP_1 - 1) + 0x10, (*lenp) = 2; + iguana_pushdata(stacks,0x10,0,0); + return(k); + } + else if ( n == 2 && c == '8' && is_delim(str[2]) != 0 ) + { + if ( str[1] == '1' ) + { + script[k++] = IGUANA_OP_1NEGATE, (*lenp) = 2; + iguana_pushdata(stacks,-1,0,0); + return(k); + } + else if ( str[1] == '0' ) + { + script[k++] = IGUANA_OP_0, (*lenp) = 2; + iguana_pushdata(stacks,0,0,0); + return(k); + } + } + } + if ( len != 0 ) + script[k++] = len; + } + else if ( len <= 0xff ) + { + script[k++] = IGUANA_OP_PUSHDATA1; + script[k++] = len; + } + else if ( len <= 0xffff ) + { + if ( len <= MAX_SCRIPT_ELEMENT_SIZE ) + { + script[k++] = IGUANA_OP_PUSHDATA2; + script[k++] = (len & 0xff); + script[k++] = ((len >> 8) & 0xff); + } + else + { + printf("len.%d > MAX_SCRIPT_ELEMENT_SIZE.%d, offset.%d\n",len,MAX_SCRIPT_ELEMENT_SIZE,k); + return(-1); + } + } + else + { + printf("len.%d > MAX_SCRIPT_ELEMENT_SIZE.%d, offset.%d\n",len,MAX_SCRIPT_ELEMENT_SIZE,k); + return(-1); + } + if ( len != 0 ) + { + uint8_t *numstart; int32_t numlen; + numstart = &script[k], numlen = len; + if ( (n & 1) != 0 ) + { + tmp[0] = '0'; + tmp[1] = c; + tmp[2] = 0; + decode_hex(&script[k++],1,tmp), *lenp = 1; + len--; + } + if ( len != 0 ) + { + decode_hex(&script[k],len,str), (*lenp) += (len << 1); + k += len; + } + iguana_pushdata(stacks,0,numstart,numlen); + } + return(k); + } + return(0); +} + +void iguana_stack(struct iguana_interpreter *stacks,struct iguana_stackdata *args,int32_t num,char *pushstr,char *clonestr) +{ + int32_t i,c; + while ( (c= *pushstr++) != 0 ) + stacks->stack[stacks->stackdepth++] = args[c - '0']; + while ( (c= *clonestr++) != 0 ) + stacks->stack[stacks->stackdepth++] = iguana_clone(args[c - '0']); + if ( num > 0 ) + { + for (i=0; i 0 && siglen > 0 && siglen < 74 ) + { + if ( (retval= (bitcoin_verify(ctx,sig,siglen-1,sigtxid,pubkey,plen) == 0)) == 0 ) + { + } + if ( (0) ) + { + int32_t i; char str[65]; + for (i=0; i 0 && privlen == 32 ) + { + bitcoin_pubkey33(ctx,checkpub,*(bits256 *)privkey); + return(memcmp(checkpub,pubkey,33) == 0); + } + return(0); +} + +int32_t iguana_checkschnorrsig(void *ctx,int64_t M,struct iguana_stackdata pubkeyarg,struct iguana_stackdata sigarg,bits256 sigtxid) +{ + /*uint8_t combined_pub[MAX_SCRIPT_ELEMENT_SIZE],sig[MAX_SCRIPT_ELEMENT_SIZE]; int32_t plen,siglen; + plen = iguana_databuf(combined_pub,pubkeyarg); + siglen = iguana_databuf(sig,sigarg); + if ( bitcoin_pubkeylen(combined_pub) == 33 && siglen == 64 ) + return(bitcoin_schnorr_verify(ctx,sig,sigtxid,combined_pub,33) == 0);*/ + return(0); +} + +int32_t iguana_checkmultisig(void *ctx,struct iguana_interpreter *stacks,int32_t M,int32_t N,bits256 txhash2) +{ + int32_t i,j=0,len,n,m,valid=0,numsigners = 0,siglens[MAX_PUBKEYS_PER_MULTISIG]; uint8_t pubkeys[MAX_PUBKEYS_PER_MULTISIG][MAX_SCRIPT_ELEMENT_SIZE],sigs[MAX_PUBKEYS_PER_MULTISIG][MAX_SCRIPT_ELEMENT_SIZE]; + if ( M <= N && N <= MAX_PUBKEYS_PER_MULTISIG ) + { + if ( stacks->stackdepth <= 0 ) + return(0); + n = (int32_t)iguana_num(iguana_pop(stacks)); + if ( n != N ) + { + printf("iguana_checkmultisig n.%d != N.%d\n",n,N); + return(0); + } + //printf("n.%d stackdepth.%d\n",n,stacks->stackdepth); + for (i=0; istackdepth <= 0 ) + return(0); + len = iguana_databuf(pubkeys[i],iguana_pop(stacks)); + if ( len == bitcoin_pubkeylen(pubkeys[i]) ) + { + numsigners++; + //for (j=0; j<33; j++) + // printf("%02x",pubkeys[i][j]); + //printf(" <- pubkey.[%d]\n",i); + } + else + { + printf("nonpubkey on stack\n"); + return(0); + memcpy(sigs[0],pubkeys[i],len); + siglens[0] = len; + break; + } + } + if ( stacks->stackdepth <= 0 ) + return(0); + m = (int32_t)iguana_num(iguana_pop(stacks)); + //printf("m.%d stackdepth.%d\n",m,stacks->stackdepth); + + if ( m != M ) + { + printf("iguana_checkmultisig m.%d != M.%d\n",m,M); + return(0); + } + for (i=0; istackdepth <= 0 ) + return(0); + siglens[i] = iguana_databuf(sigs[i],iguana_pop(stacks)); + if ( siglens[i] <= 0 || siglens[i] > 74 ) + break; + //for (j=0; jstackdepth,bits256_str(str,txhash2)); + if ( stacks->stackdepth > 0 ) + iguana_pop(stacks); // for backward compatibility + j = numsigners-1; + for (i=numsigners-1; i>=0; i--) + { + for (; j>=0; j--) + { + if ( bitcoin_verify(ctx,sigs[i],siglens[i]-1,txhash2,pubkeys[j],bitcoin_pubkeylen(pubkeys[j])) == 0 ) + { + if ( ++valid >= M ) + return(1); + j--; + break; + } + } + } + } + } + printf("checkmultisig: valid.%d j.%d M.%d N.%d numsigners.%d\n",valid,j,M,N,numsigners); + return(0); +} + +#define LOCKTIME_THRESHOLD 500000000 +int32_t iguana_checklocktimeverify(void *ctx,int64_t tx_lockval,uint32_t nSequence,struct iguana_stackdata Snum) +{ + int64_t nLockTime = iguana_num(Snum); + if ( nLockTime < 0 || tx_lockval < 0 ) + { + printf("CLTV.0 nLockTime.%lld tx_lockval.%lld\n",(long long)nLockTime,(long long)tx_lockval); + return(-1); + } + else if ( ((tx_lockval < LOCKTIME_THRESHOLD && nLockTime < LOCKTIME_THRESHOLD) || + (tx_lockval >= LOCKTIME_THRESHOLD && nLockTime >= LOCKTIME_THRESHOLD)) == 0 ) + { + printf("CLTV.1 nLockTime.%lld tx_lockval.%lld\n",(long long)nLockTime,(long long)tx_lockval); + return(-1); + } + else if ( nLockTime > tx_lockval ) + { + printf("CLTV.2 nLockTime.%lld tx_lockval.%lld\n",(long long)nLockTime,(long long)tx_lockval); + return(-1); + } + return(0); +} + +int32_t iguana_checksequenceverify(void *ctx,int64_t nLockTime,uint32_t nSequence,struct iguana_stackdata Snum) +{ + return(0); +} + +cJSON *iguana_spendasm(uint8_t *spendscript,int32_t spendlen) +{ + char asmstr[IGUANA_MAXSCRIPTSIZE*2+1]; cJSON *spendasm = cJSON_CreateObject(); + iguana_expandscript(asmstr,sizeof(asmstr),spendscript,spendlen); + //int32_t i; for (i=0; i (%s)\n",asmstr); + jaddstr(spendasm,"interpreter",asmstr); + return(spendasm); +} + +int32_t bitcoin_assembler(void *ctx,cJSON *logarray,uint8_t script[IGUANA_MAXSCRIPTSIZE],cJSON *interpreter,int32_t interpret,int64_t nLockTime,struct vin_info *V) +{ + struct bitcoin_opcode *op; cJSON *array = 0; struct iguana_interpreter STACKS,*stacks = &STACKS; + struct iguana_stackdata args[MAX_PUBKEYS_PER_MULTISIG]; + uint8_t databuf[MAX_SCRIPT_ELEMENT_SIZE]; char *asmstr,*str,*hexstr; cJSON *item; + int32_t c,numops,dlen,plen,numvars,numused,numargs=0,i,j,k,n=0,len,datalen,errs=0; int64_t val; + iguana_optableinit(); + if ( (asmstr= jstr(interpreter,"interpreter")) == 0 || asmstr[0] == 0 ) + return(0); + if ( (numvars= juint(interpreter,"numvars")) > 0 ) + { + if ( (array= jarray(&n,interpreter,"args")) == 0 || (interpret != 0 && n != numvars) ) + return(-2); + } + str = asmstr; + if ( interpret != 0 ) + { + stacks = calloc(1,sizeof(*stacks) + sizeof(*stacks->stack)*2*IGUANA_MAXSTACKITEMS); + stacks->maxstackdepth = IGUANA_MAXSTACKITEMS; + if ( (stacks->logarray= logarray) != 0 ) + item = cJSON_CreateObject(); + else item = 0; + if ( V->M == 0 && V->N == 0 ) + V->N = V->M = 1; + for (i=0; iN; i++) + { + if ( V->signers[i].siglen != 0 ) + { + iguana_pushdata(stacks,0,V->signers[i].sig,V->signers[i].siglen); + if ( bitcoin_pubkeylen(V->signers[i].pubkey) <= 0 ) + { + printf("missing pubkey.[%d]\n",i); + free(stacks); + return(-1); + } + //printf("pushdata siglen.%d depth.%d\n",V->signers[i].siglen,stacks->stackdepth); + } + } + for (i=0; iN; i++) + { + if ( V->signers[i].siglen != 0 ) + { + plen = bitcoin_pubkeylen(V->signers[i].pubkey); + if ( V->suppress_pubkeys == 0 && (V->spendscript[0] != plen || V->spendscript[V->spendlen - 1] != IGUANA_OP_CHECKSIG || bitcoin_pubkeylen(&V->spendscript[1]) <= 0) ) + { + iguana_pushdata(stacks,0,V->signers[i].pubkey,plen); + //printf(">>>>>>>>> suppress.%d pushdata [%02x %02x] plen.%d depth.%d\n",V->suppress_pubkeys,V->signers[i].pubkey[0],V->signers[i].pubkey[1],plen,stacks->stackdepth); + } // else printf("<<<<<<<<<< skip pubkey push %d script[0].%d spendlen.%d depth.%d\n",plen,V->spendscript[0],V->spendlen,stacks->stackdepth); + } + } + if ( V->userdatalen != 0 ) + { + len = 0; + while ( len < V->userdatalen ) + { + dlen = V->userdata[len++]; + if ( dlen > 0 && dlen < 76 ) + iguana_pushdata(stacks,0,&V->userdata[len],dlen), len += dlen; + else if ( dlen >= IGUANA_OP_1 && dlen <= IGUANA_OP_16 ) + { + dlen -= (IGUANA_OP_1 - 1); + iguana_pushdata(stacks,dlen,0,0); + } + else if ( dlen == IGUANA_OP_PUSHDATA1 ) + { + iguana_pushdata(stacks,V->userdata[len++],0,0); + } + else if ( dlen == IGUANA_OP_PUSHDATA2 ) + { + iguana_pushdata(stacks,V->userdata[len] + ((int32_t)V->userdata[len+1]<<8),0,0); + len += 2; + } + else if ( dlen == IGUANA_OP_0 ) + iguana_pushdata(stacks,0,0,0); + else if ( dlen == IGUANA_OP_1NEGATE ) + iguana_pushdata(stacks,-1,0,0); + else + { + printf("invalid data opcode %02x\n",dlen); + free(stacks); + return(-1); + } + //printf("user data stackdepth.%d dlen.%d\n",stacks->stackdepth,dlen); + } + if ( len != V->userdatalen ) + { + printf("mismatched userdatalen %d vs %d\n",len,V->userdatalen); + free(stacks); + return(-1); + } + } + if ( item != 0 && stacks->logarray != 0 ) + { + jaddstr(item,"spendasm",asmstr); + jaddi(stacks->logarray,item); + } + if ( V->extras != 0 ) + { + if ( (n= cJSON_GetArraySize(V->extras)) > 0 ) + { + for (i=0; iextras,i),0)) != 0 && (len= is_hexstr(hexstr,0)) > 0 ) + { + len >>= 1; + decode_hex(databuf,len,hexstr); + iguana_pushdata(stacks,0,databuf,len); + } + } + } + } + } else memset(stacks,0,sizeof(*stacks)); + stacks->lastpath[0] = 1; + k = numops = numused = 0; + script[k] = 0; + while ( (c= *str++) != 0 ) + { + if ( is_delim(c) != 0 ) + { + //if ( c == 0 ) + // break; + continue; + } + if ( c == '/' && *str == '/' ) // support // + break; + else if ( c == '-' && *str == '1' && is_delim(str[1]) != 0 ) + { + script[k++] = IGUANA_OP_1NEGATE, str += 3; // OP_1NEGATE; + iguana_pushdata(stacks,-1,0,0); + continue; + } + else if ( c == '%' && *str == 's' ) + { + str++; + if ( numused < numvars && (hexstr= jstr(jitem(array,numused++),0)) != 0 ) + { + if ( (n= iguana_dataparse(stacks,script,k,str,&len)) > 0 ) + { + k += n; + continue; + } + } + printf("dataparse error.%d, numused.%d >= numvars.%d\n",n,numused,numvars); + errs++; + break; + } + else + { + str--; + if ( (n= iguana_dataparse(stacks,script,k,str,&len)) > 0 ) + { + k = n; + str += len; + continue; + } + else if ( n < 0 ) + { + printf("dataparse negative n.%d\n",n); + errs++; + break; + } + } + for (j=0; j<32; j++) + if ( is_delim(str[j]) != 0 ) + break; + if ( j == 32 ) + { + printf("too long opcode.%s at offset.%ld\n",str,(long)str-(long)asmstr); + errs++; + break; + } + HASH_FIND(hh,OPTABLE,str,j,op); + printf("{%s}\n",str); + str += j; + if ( op != 0 ) + { + if ( numargs > 0 ) + { + for (i=0; iopcode; + if ( (op->flags & IGUANA_CONTROLFLAG) != 0 ) + { + //printf("control opcode depth.%d\n",stacks->stackdepth); + switch ( op->opcode ) + { + case IGUANA_OP_IF: case IGUANA_OP_NOTIF: + if ( stacks->ifdepth >= IGUANA_MAXSTACKDEPTH ) + { + printf("ifdepth.%d >= MAXSTACKDEPTH.%d\n",stacks->ifdepth,IGUANA_MAXSTACKDEPTH); + errs++; + } + else + { + if ( stacks->stackdepth <= 0 ) + { + printf("if invalid stackdepth %d\n",stacks->stackdepth); + errs++; + } + else + { + args[0] = iguana_pop(stacks); + if ( iguana_isnonz(args[0]) == (op->opcode == IGUANA_OP_IF) ) + { + val = 1; + //printf("OP_IF enabled depth.%d\n",stacks->stackdepth); + } + else + { + val = -1; + //printf("OP_IF disabled depth.%d\n",stacks->stackdepth); + } + stacks->lastpath[++stacks->ifdepth] = val; + } + } + break; + case IGUANA_OP_ELSE: + /*if ( stacks->stackdepth <= 0 ) + { + printf("else invalid stackdepth %d\n",stacks->stackdepth); + errs++; + } + else*/ + { + if ( stacks->ifdepth <= stacks->elsedepth ) + { + printf("unhandled opcode.%02x stacks->ifdepth %d <= %d stacks->elsedepth\n",op->opcode,stacks->ifdepth,stacks->elsedepth); + errs++; + } + stacks->lastpath[stacks->ifdepth] *= -1; + //printf("OP_ELSE status.%d depth.%d\n",stacks->lastpath[stacks->ifdepth],stacks->stackdepth); + } + break; + case IGUANA_OP_ENDIF: + if ( stacks->ifdepth <= 0 ) + { + printf("endif without if offset.%ld\n",(long)str-(long)asmstr); + errs++; + } + stacks->ifdepth--; + //printf("OP_ENDIF status.%d depth.%d\n",stacks->lastpath[stacks->ifdepth],stacks->stackdepth); + break; + case IGUANA_OP_VERIFY: + break; + case IGUANA_OP_RETURN: + iguana_pushdata(stacks,0,0,0); + errs++; + break; + } + if ( errs != 0 ) + break; + continue; + } + if ( stacks->lastpath[stacks->ifdepth] != 0 ) + { + if ( stacks->lastpath[stacks->ifdepth] < 0 ) + { + //printf("SKIP opcode.%02x depth.%d\n",op->opcode,stacks->stackdepth); + if ( stacks->logarray ) + jaddistr(stacks->logarray,"skip"); + continue; + } + //printf("conditional opcode.%02x stackdepth.%d\n",op->opcode,stacks->stackdepth); + } + if ( op->opcode <= IGUANA_OP_16 || ++numops <= MAX_OPS_PER_SCRIPT ) + { + if ( (op->flags & IGUANA_ALWAYSILLEGAL) != 0 ) + { + printf("disabled opcode.%s at offset.%ld\n",str,(long)str-(long)asmstr); + errs++; + break; + } + else if ( op->extralen > 0 ) + { + if ( is_delim(*str) != 0 ) + str++; + if ( is_hexstr(str,0) != (op->extralen<<1) ) + { + printf("expected extralen.%d of hex, got.(%s) at offset.%ld\n",op->extralen,str,(long)str-(long)asmstr); + errs++; + break; + } + decode_hex(&script[k],op->extralen,str), str += (op->extralen << 1); + if ( op->extralen == 1 ) + iguana_pushdata(stacks,script[k],0,0); + else if ( op->extralen == 2 ) + iguana_pushdata(stacks,script[k] + ((uint32_t)script[k]<<8),0,0); + k += op->extralen; + continue; + } + if ( interpret == 0 || V == 0 ) + continue; + if ( (op->flags & IGUANA_NOPFLAG) != 0 ) + continue; + if ( (numargs= op->stackitems) > 0 ) + { + if ( stacks->stackdepth < op->stackitems ) + { + //printf("stackdepth.%d needed.%d (%s) at offset.%ld\n",stacks->stackdepth,op->stackitems,str,(long)str-(long)asmstr); + errs++; + break; + } + for (i=0; iopcode,numargs,stacks->stackdepth); + if ( stacks->logarray != 0 ) + { + char tmpstr[1096]; + item = cJSON_CreateObject(); + array = cJSON_CreateArray(); + for (i=0; ihh.key,array); + jaddi(stacks->logarray,item); + } + if ( (op->flags & IGUANA_EXECUTIONILLEGAL) != 0 ) + { + printf("opcode not allowed to run.%s at %ld\n",(char *)op->hh.key,(long)str-(long)asmstr); + errs++; + break; + } + else if ( op->opcode == IGUANA_OP_EQUALVERIFY || op->opcode == IGUANA_OP_EQUAL ) + { + if ( iguana_cmp(&args[0],&args[1]) == 0 ) + iguana_pushdata(stacks,1,0,0); + else + { + iguana_pushdata(stacks,0,0,0); + for (i=0; iopcode,args[0].size,args[1].size); + } + } + else if ( (op->flags & IGUANA_CRYPTOFLAG) != 0 ) + { + uint8_t rmd160[20],revdatabuf[MAX_SCRIPT_ELEMENT_SIZE]; bits256 hash; + datalen = iguana_databuf(databuf,args[0]); + for (i=0; iopcode ) + { + case IGUANA_OP_RIPEMD160: + calc_rmd160(0,rmd160,databuf,datalen); + iguana_pushdata(stacks,0,rmd160,sizeof(rmd160)); + break; + case IGUANA_OP_SHA1: + calc_sha1(0,rmd160,databuf,datalen); + iguana_pushdata(stacks,0,rmd160,sizeof(rmd160)); + break; + case IGUANA_OP_HASH160: + /*if ( datalen == 32 ) + { + revcalc_rmd160_sha256(rmd160,*(bits256 *)databuf); + printf("SPECIAL CASE REVERSE\n"); + } else + for (i=0; i<32; i++) + printf("%02x",databuf[i]); + printf(" <- databuf\n"); + for (i=0; i<32; i++) + printf("%02x",revdatabuf[i]); + printf(" <- revdatabuf\n"); + calc_rmd160_sha256(rmd160,revdatabuf,datalen); + for (i=0; i<20; i++) + printf("%02x",rmd160[i]); + printf(" <- rmd160 revdatabuf\n"); + revcalc_rmd160_sha256(rmd160,*(bits256 *)databuf); + for (i=0; i<20; i++) + printf("%02x",rmd160[i]); + printf(" <- rmd160 special\n"); + calc_rmd160_sha256(rmd160,databuf,datalen); + for (i=0; i<20; i++) + printf("%02x",rmd160[i]); + printf(" <- rmd160 databuf\n");*/ + if ( datalen == 32 ) + calc_rmd160_sha256(rmd160,revdatabuf,datalen); + else calc_rmd160_sha256(rmd160,databuf,datalen); + iguana_pushdata(stacks,0,rmd160,sizeof(rmd160)); + break; + case IGUANA_OP_SHA256: + vcalc_sha256(0,hash.bytes,databuf,datalen); + for (i=0; i sha256 %s\n",bits256_str(str,hash)); + iguana_pushdata(stacks,0,hash.bytes,sizeof(hash)); + break; + case IGUANA_OP_HASH256: + hash = bits256_doublesha256(0,databuf,datalen); + iguana_pushdata(stacks,0,hash.bytes,sizeof(hash)); + break; + case IGUANA_OP_CHECKSIG: case IGUANA_OP_CHECKSIGVERIFY: + iguana_pushdata(stacks,iguana_checksig(ctx,args[1],args[0],V->sigtxid),0,0); + break; + case IGUANA_OP_CHECKMULTISIG: case IGUANA_OP_CHECKMULTISIGVERIFY: + iguana_pushdata(stacks,iguana_checkmultisig(ctx,stacks,V->M,V->N,V->sigtxid),0,0); + break; + case IGUANA_OP_CHECKSCHNORR: case IGUANA_OP_CHECKSCHNORRVERIFY: + iguana_pushdata(stacks,iguana_checkschnorrsig(ctx,iguana_num(args[2]),args[1],args[0],V->sigtxid),0,0); + break; + case IGUANA_OP_CHECKPRIVATEKEY: case IGUANA_OP_CHECKPRIVATEKEYVERIFY: + iguana_pushdata(stacks,iguana_checkprivatekey(ctx,args[1],args[0]),0,0); + break; + } + } + else if ( op->opcode == IGUANA_OP_CHECKLOCKTIMEVERIFY ) // former OP_NOP2 + { + if ( V->ignore_cltverr == 0 && iguana_checklocktimeverify(ctx,nLockTime,V->sequence,args[0]) < 0 ) + { + iguana_stack(stacks,args,1,"0",""); + errs++; + break; + } + iguana_stack(stacks,args,1,"0",""); + continue; + } + else if ( op->opcode == IGUANA_OP_CHECKSEQUENCEVERIFY ) // former OP_NOP3 + { + if ( iguana_checksequenceverify(ctx,nLockTime,V->sequence,args[0]) < 0 ) + { + iguana_stack(stacks,args,1,"0",""); + errs++; + break; + } + iguana_stack(stacks,args,1,"0",""); + continue; + } + else if ( (op->flags & IGUANA_STACKFLAG) != 0 ) + { + val = 0; + if ( op->opcode == IGUANA_OP_PICK || op->opcode == IGUANA_OP_ROLL ) + { + if ( interpret != 0 && stacks->stackdepth < (val= iguana_num(args[0])) ) + { + printf("stack not deep enough %d < %lld\n",stacks->stackdepth,(long long)iguana_num(args[0])); + errs++; + break; + } + if ( op->opcode == IGUANA_OP_PICK ) + { + stacks->stack[stacks->stackdepth] = iguana_clone(stacks->stack[stacks->stackdepth - 1 - val]); + stacks->stackdepth++; + } + else + { + args[1] = stacks->stack[stacks->stackdepth - 1 - val]; + for (i=(int32_t)(stacks->stackdepth-1-val); istackdepth-1; i++) + stacks->stack[i] = stacks->stack[i+1]; + stacks->stack[stacks->stackdepth - 1] = args[1]; + } + } + else + { + switch ( op->opcode ) + { + case IGUANA_OP_TOALTSTACK: + if ( stacks->altstackdepth < stacks->maxstackdepth ) + { + iguana_altpush(stacks,args[0]); + memset(&args[0],0,sizeof(args[0])); + } + else + { + printf("altstack overflow %d vs %d\n",stacks->altstackdepth,stacks->maxstackdepth); + errs++; + } + break; + case IGUANA_OP_FROMALTSTACK: + stacks->stack[stacks->stackdepth++] = iguana_altpop(stacks); + break; + case IGUANA_OP_DEPTH: iguana_pushdata(stacks,stacks->stackdepth,0,0); break; + case IGUANA_OP_DROP: case IGUANA_OP_2DROP: break; + case IGUANA_OP_3DUP: iguana_stack(stacks,args,3,"012","012"); break; + case IGUANA_OP_2OVER: iguana_stack(stacks,args,4,"0123","01"); break; + case IGUANA_OP_2ROT: iguana_stack(stacks,args,6,"234501",""); break; + case IGUANA_OP_2SWAP: iguana_stack(stacks,args,4,"2301",""); break; + case IGUANA_OP_IFDUP: + if ( iguana_isnonz(args[0]) != 0 ) + iguana_stack(stacks,args,0,"","0"); + iguana_stack(stacks,args,1,"0",""); + break; + case IGUANA_OP_DUP: iguana_stack(stacks,args,1,"0","0"); break; + case IGUANA_OP_2DUP: iguana_stack(stacks,args,2,"01","01"); break; + case IGUANA_OP_NIP: + if ( args[0].data != 0 ) + free(args[0].data); + iguana_stack(stacks,args,2,"1",""); + break; + case IGUANA_OP_OVER: iguana_stack(stacks,args,2,"01","0"); break; + case IGUANA_OP_ROT: iguana_stack(stacks,args,3,"120",""); break; + case IGUANA_OP_SWAP: iguana_stack(stacks,args,2,"10",""); break; + case IGUANA_OP_TUCK: iguana_stack(stacks,args,2,"10","1"); break; + } + } + } + else if ( (op->flags & IGUANA_MATHFLAG) != 0 ) + { + int64_t numA=0,numB=0,numC=0; + for (i=0; istackitems; i++) + { + if ( args[i].size != sizeof(int32_t) ) + break; + if ( i == 0 ) + numA = iguana_num(args[i]); + else if ( i == 1 ) + numB = iguana_num(args[i]); + else if ( i == 2 ) + numC = iguana_num(args[i]); + } + if ( i != op->stackitems ) + { + printf("math script non-int32_t arg[%d] of %d\n",i,op->stackitems); + errs++; + break; + } + switch ( op->opcode ) + { + case IGUANA_OP_1ADD: iguana_pushdata(stacks,numA + 1,0,0); break; + case IGUANA_OP_1SUB: iguana_pushdata(stacks,numA - 1,0,0); break; + case IGUANA_OP_NEGATE: iguana_pushdata(stacks,-numA,0,0); break; + case IGUANA_OP_ABS: iguana_pushdata(stacks,numA<0?-numA:numA,0,0); break; + case IGUANA_OP_NOT: iguana_pushdata(stacks,numA == 0,0,0); break; + case IGUANA_OP_0NOTEQUAL: iguana_pushdata(stacks,numA != 0,0,0); break; + case IGUANA_OP_ADD: iguana_pushdata(stacks,numA + numB,0,0); break; + case IGUANA_OP_SUB: iguana_pushdata(stacks,numA - numB,0,0); break; + case IGUANA_OP_BOOLAND:iguana_pushdata(stacks,numA != 0 && numB != 0,0,0); break; + case IGUANA_OP_BOOLOR: iguana_pushdata(stacks,numA != 0 || numB != 0,0,0); break; + case IGUANA_OP_NUMEQUAL: case IGUANA_OP_NUMEQUALVERIFY: + iguana_pushdata(stacks,numA == numB,0,0); break; + case IGUANA_OP_NUMNOTEQUAL:iguana_pushdata(stacks,numA != numB,0,0); break; + case IGUANA_OP_LESSTHAN: iguana_pushdata(stacks,numA < numB,0,0); break; + case IGUANA_OP_GREATERTHAN:iguana_pushdata(stacks,numA > numB,0,0); break; + case IGUANA_OP_LESSTHANOREQUAL:iguana_pushdata(stacks,numA <= numB,0,0); break; + case IGUANA_OP_GREATERTHANOREQUAL:iguana_pushdata(stacks,numA >= numB,0,0); break; + case IGUANA_OP_MIN: iguana_pushdata(stacks,numA <= numB ? numA : numB,0,0); break; + case IGUANA_OP_MAX: iguana_pushdata(stacks,numA >= numB ? numA : numB,0,0); break; + case IGUANA_OP_WITHIN: iguana_pushdata(stacks,numB <= numA && numA < numC,0,0); break; + } + } + else if ( op->opcode == IGUANA_OP_CODESEPARATOR ) + { + if ( stacks != 0 ) + stacks->codeseparator = k; + continue; + } + else + { + printf("unhandled opcode.%02x (%s)\n",op->opcode,str); + errs++; + break; + } + if ( (op->flags & IGUANA_POSTVERIFY) != 0 ) + { + if ( stacks->stackdepth < 1 ) + { + printf("empty stack at offset.%ld\n",(long)str - (long)asmstr); + errs++; + break; + } + if ( iguana_isnonz(stacks->stack[stacks->stackdepth-1]) == 0 ) + break; + iguana_pop(stacks); + } + } + else + { + printf("too many ops opcode.%s at offset.%ld\n",str,(long)str - (long)asmstr); + errs++; + break; + } + } + else + { + printf("unknown opcode.%s at offset.%ld\n",str,(long)str - (long)asmstr); + errs++; + break; + } + } + if ( stacks != &STACKS ) + { + if ( jobj(interpreter,"result") != 0 ) + jdelete(interpreter,"result"); + if ( stacks->stackdepth <= 0 ) + { + errs++; + printf("empty stack error\n"); + jaddstr(interpreter,"error","empty stack"); + jadd(interpreter,"result",jfalse()); + } + else if ( iguana_isnonz(stacks->stack[--stacks->stackdepth]) != 0 ) + { + //printf("Evaluate true, depth.%d errs.%d k.%d\n",stacks->stackdepth,errs,k); + if ( errs == 0 ) + jadd(interpreter,"result",jtrue()); + else jadd(interpreter,"result",jfalse()); + } + else + { + jadd(interpreter,"result",jfalse()); + printf("Evaluate FALSE, depth.%d errs.%d [0] size.%d val.%d\n",stacks->stackdepth,errs,stacks->stack[0].size,stacks->stack[0].U.val); + errs++; + if ( stacks->logarray != 0 ) + printf("LOG.(%s)\n\n",jprint(stacks->logarray,0)); + } + if ( numargs > 0 ) + { + for (i=0; isrchash = srchash; - rp->desthash = desthash; rp->srcamount = srcsatoshis; - rp->destamount = destsatoshis; rp->timestamp = timestamp; - rp->quotetime = quotetime; rp->DEXselector = DEXselector; safecopy(rp->src,src,sizeof(rp->src)); safecopy(rp->dest,dest,sizeof(rp->dest)); - rp->quoteid = basilisk_quoteid(rp); + R = *rp; rp->requestid = basilisk_requestid(rp); + rp->quotetime = quotetime; + rp->desthash = desthash; + rp->destamount = destsatoshis; + rp->quoteid = basilisk_quoteid(rp); return(rp); } -void LP_command(struct LP_peerinfo *mypeer,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin) +cJSON *LP_quotejson(struct LP_quoteinfo *qp) +{ + double price; cJSON *retjson = cJSON_CreateObject(); + jaddstr(retjson,"base",qp->srccoin); + jaddstr(retjson,"rel",qp->destcoin); + if ( qp->coinaddr[0] != 0 ) + jaddstr(retjson,"address",qp->coinaddr); + if ( qp->timestamp != 0 ) + jaddnum(retjson,"timestamp",qp->timestamp); + if ( bits256_nonz(qp->txid) != 0 ) + { + jaddbits256(retjson,"txid",qp->txid); + jaddnum(retjson,"vout",qp->vout); + } + if ( bits256_nonz(qp->srchash) != 0 ) + jaddbits256(retjson,"srchash",qp->srchash); + if ( qp->txfee != 0 ) + jadd64bits(retjson,"txfee",qp->txfee); + if ( qp->quotetime != 0 ) + jaddnum(retjson,"quotetime",qp->quotetime); + if ( qp->satoshis != 0 ) + { + jadd64bits(retjson,"satoshis",qp->satoshis); + price = (double)(qp->destsatoshis+qp->desttxfee) / qp->satoshis; + jaddnum(retjson,"price",price); + } + if ( bits256_nonz(qp->desthash) != 0 ) + jaddbits256(retjson,"desthash",qp->desthash); + if ( bits256_nonz(qp->txid2) != 0 ) + { + jaddbits256(retjson,"txid2",qp->txid2); + jaddnum(retjson,"vout2",qp->vout2); + if ( qp->satoshis2 != 0 ) + jadd64bits(retjson,"satoshis2",qp->satoshis2); + } + if ( bits256_nonz(qp->desttxid) != 0 ) + { + if ( qp->destaddr[0] != 0 ) + jaddstr(retjson,"destaddr",qp->destaddr); + jaddbits256(retjson,"desttxid",qp->desttxid); + jaddnum(retjson,"destvout",qp->destvout); + } + if ( bits256_nonz(qp->feetxid) != 0 ) + { + jaddbits256(retjson,"feetxid",qp->feetxid); + jaddnum(retjson,"feevout",qp->feevout); + } + if ( qp->destsatoshis != 0 ) + jadd64bits(retjson,"destsatoshis",qp->destsatoshis); + if ( qp->desttxfee != 0 ) + jadd64bits(retjson,"desttxfee",qp->desttxfee); + if ( qp->change != 0 ) + jaddnum(retjson,"change",dstr(qp->change)); + return(retjson); +} + +int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson) +{ + safecopy(qp->srccoin,jstr(argjson,"base"),sizeof(qp->srccoin)); + safecopy(qp->coinaddr,jstr(argjson,"address"),sizeof(qp->coinaddr)); + safecopy(qp->destcoin,jstr(argjson,"rel"),sizeof(qp->destcoin)); + safecopy(qp->destaddr,jstr(argjson,"destaddr"),sizeof(qp->destaddr)); + qp->timestamp = juint(argjson,"timestamp"); + qp->quotetime = juint(argjson,"quotetime"); + qp->txid = jbits256(argjson,"txid"); + qp->txid2 = jbits256(argjson,"txid2"); + qp->vout = jint(argjson,"vout"); + qp->vout2 = jint(argjson,"vout2"); + qp->feevout = jint(argjson,"feevout"); + qp->srchash = jbits256(argjson,"srchash"); + qp->desttxid = jbits256(argjson,"desttxid"); + qp->feetxid = jbits256(argjson,"feetxid"); + qp->destvout = jint(argjson,"destvout"); + qp->desthash = jbits256(argjson,"desthash"); + if ( (qp->satoshis= j64bits(argjson,"satoshis")) == 0 ) + qp->satoshis = j64bits(argjson,"value"); + if ( (qp->satoshis2= j64bits(argjson,"satoshis2")) == 0 ) + qp->satoshis2 = j64bits(argjson,"value2"); + qp->destsatoshis = j64bits(argjson,"destsatoshis"); + qp->change = SATOSHIDEN * jdouble(argjson,"change"); + qp->txfee = j64bits(argjson,"txfee"); + qp->desttxfee = j64bits(argjson,"desttxfee"); + return(0); +} + +int32_t LP_quoteinfoinit(struct LP_quoteinfo *qp,struct LP_utxoinfo *utxo,char *destcoin,double price) +{ + memset(qp,0,sizeof(*qp)); + qp->timestamp = (uint32_t)time(NULL); + safecopy(qp->destcoin,destcoin,sizeof(qp->destcoin)); + if ( (qp->txfee= LP_getestimatedrate(utxo->coin)*LP_AVETXSIZE) < 10000 ) + qp->txfee = 10000; + if ( qp->txfee >= utxo->satoshis || qp->txfee >= utxo->satoshis2 ) + return(-1); + qp->txid = utxo->txid; + qp->vout = utxo->vout; + qp->txid2 = utxo->txid2; + qp->vout2 = utxo->vout2; + qp->satoshis2 = utxo->satoshis2 - qp->txfee; + qp->satoshis = utxo->satoshis - qp->txfee; + qp->destsatoshis = qp->satoshis * price; + if ( (qp->desttxfee= LP_getestimatedrate(qp->destcoin) * LP_AVETXSIZE) < 10000 ) + qp->desttxfee = 10000; + if ( qp->desttxfee >= qp->destsatoshis ) + return(-2); + qp->destsatoshis -= qp->desttxfee; + safecopy(qp->srccoin,utxo->coin,sizeof(qp->srccoin)); + safecopy(qp->coinaddr,utxo->coinaddr,sizeof(qp->coinaddr)); + qp->srchash = LP_pubkey(LP_privkey(utxo->coinaddr)); + return(0); +} + +int32_t LP_quoteinfoset(struct LP_quoteinfo *qp,uint32_t timestamp,uint32_t quotetime,uint64_t value,uint64_t txfee,uint64_t destsatoshis,uint64_t desttxfee,bits256 desttxid,int32_t destvout,bits256 desthash,char *destaddr) +{ + if ( txfee != qp->txfee ) + { + if ( txfee >= value ) + return(-1); + qp->txfee = txfee; + qp->satoshis = value - txfee; + } + qp->timestamp = timestamp; + qp->quotetime = quotetime; + qp->destsatoshis = destsatoshis; + qp->desttxfee = desttxfee; + qp->desttxid = desttxid; + qp->destvout = destvout; + qp->desthash = desthash; + safecopy(qp->destaddr,destaddr,sizeof(qp->destaddr)); + return(0); +} + +char *LP_quotereceived(cJSON *argjson) +{ + struct LP_cacheinfo *ptr; double price; struct LP_quoteinfo Q; + LP_quoteparse(&Q,argjson); + price = (double)(Q.destsatoshis + Q.desttxfee) / (Q.satoshis + Q.txfee); + if ( (ptr= LP_cacheadd(Q.srccoin,Q.destcoin,Q.txid,Q.vout,price,&Q)) != 0 ) + { + ptr->Q = Q; + return(clonestr("{\"result\":\"updated\"}")); + } else return(clonestr("{\"error\":\"nullptr\"}")); +} + +double LP_query(char *method,struct LP_quoteinfo *qp,char *ipaddr,uint16_t port,char *base,char *rel,bits256 mypub) +{ + cJSON *reqjson; struct LP_peerinfo *peer; int32_t i,flag = 0,pushsock = -1; double price = 0.; + if ( ipaddr != 0 && port >= 1000 ) + { + if ( (peer= LP_peerfind((uint32_t)calc_ipbits(ipaddr),port)) == 0 ) + peer = LP_addpeer(1,0,-1,ipaddr,port,port+1,port+2,0,0,0); + if ( peer != 0 ) + { + if ( (pushsock= peer->pushsock) >= 0 ) + { + qp->desthash = mypub; + strcpy(qp->srccoin,base); + strcpy(qp->destcoin,rel); + if ( strcmp(method,"request") == 0 ) + qp->quotetime = (uint32_t)time(NULL); + reqjson = LP_quotejson(qp); + if ( bits256_nonz(qp->desthash) != 0 ) + flag = 1; + jaddstr(reqjson,"method",method); + LP_send(pushsock,jprint(reqjson,1),1); + for (i=0; i<30; i++) + { + if ( (price= LP_pricecache(qp,base,rel,qp->txid,qp->vout)) != 0. ) + { + if ( flag == 0 || bits256_nonz(qp->desthash) != 0 ) + { + //printf("break out of loop.%d price %.8f\n",i,price); + break; + } + } + usleep(100000); + } + } else printf("no pushsock for peer.%s:%u\n",ipaddr,port); + } else printf("cant find/create peer.%s:%u\n",ipaddr,port); + } + return(price); +} + +int32_t LP_sizematch(uint64_t mysatoshis,uint64_t othersatoshis) { - char *method,*base,*rel,*retstr,*pairstr; cJSON *retjson; double price; bits256 srchash,desthash,pubkey,privkey,txid,desttxid; struct LP_utxoinfo *utxo; uint32_t timestamp,quotetime; int32_t destvout,DEXselector = 0; uint64_t txfee,satoshis,desttxfee,destsatoshis,value; struct basilisk_request R; - if ( (method= jstr(argjson,"method")) != 0 ) + if ( mysatoshis >= othersatoshis ) + return(0); + else return(-1); +} + +cJSON *LP_tradecandidates(struct LP_utxoinfo *myutxo,char *base) +{ + struct LP_peerinfo *peer,*tmp; struct LP_quoteinfo Q; char *utxostr,coinstr[16]; cJSON *array,*icopy,*retarray=0,*item; int32_t i,n; double price; int64_t estimatedbase; + if ( (price= LP_price(base,myutxo->coin)) == .0 ) + { + printf("no LP_price (%s -> %s)\n",base,myutxo->coin); + return(0); + } + estimatedbase = myutxo->satoshis / price; + printf("%s -> %s price %.8f mysatoshis %llu estimated base %llu\n",base,myutxo->coin,price,(long long)myutxo->satoshis,(long long)estimatedbase); + if ( estimatedbase <= 0 ) + return(0); + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + if ( (utxostr= issue_LP_clientgetutxos(peer->ipaddr,peer->port,base,100)) != 0 ) + { + //printf("%s:%u %s\n",peer->ipaddr,peer->port,utxostr); + if ( (array= cJSON_Parse(utxostr)) != 0 ) + { + if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) + { + retarray = cJSON_CreateArray(); + for (i=0; icoin,jbits256(item,"txid"),jint(item,"vout"))) != 0. ) + { + if ( LP_sizematch(myutxo->satoshis,Q.destsatoshis) == 0 ) + icopy = jduplicate(item); + } else icopy = jduplicate(item); + if ( icopy != 0 ) + { + if ( price != 0. ) + jaddnum(icopy,"price",price); + jaddi(retarray,icopy); + } + } else printf("skip %s estimated %.8f vs %.8f\n",coinstr,dstr(estimatedbase),dstr(j64bits(item,"satoshis"))); + } + } + free_json(array); + } + free(utxostr); + } + if ( retarray != 0 ) + break; + } + return(retarray); +} + +cJSON *LP_autotrade(struct LP_utxoinfo *myutxo,char *base,double maxprice) +{ + static bits256 zero; + int32_t i,n,besti,DEXselector=0; cJSON *array,*item,*bestitem=0; struct basilisk_request R; double bestmetric,metric,bestprice=0.,price,prices[100]; struct LP_quoteinfo Q[sizeof(prices)/sizeof(*prices)]; + bestprice = 0.; + if ( maxprice == 0. ) + maxprice = LP_price(base,myutxo->coin) / 0.975; + if ( (array= LP_tradecandidates(myutxo,base)) != 0 ) + { + printf("candidates.(%s)\n",jprint(array,0)); + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + memset(prices,0,sizeof(prices)); + memset(Q,0,sizeof(Q)); + for (i=0; icoin,zero); + if ( Q[i].destsatoshis != 0 && (double)j64bits(item,"satoshis")/Q[i].destsatoshis > price ) + { + printf("adjustprice %.8f -> %.8f\n",price,(double)j64bits(item,"satoshis")/Q[i].destsatoshis); + price = (double)j64bits(item,"satoshis")/Q[i].destsatoshis; + } + } + if ( (prices[i]= price) != 0. && (bestprice == 0. || price < bestprice) ) + bestprice = price; + char str[65]; printf("i.%d of %d: (%s) -> txid.%s price %.8f best %.8f\n",i,n,jprint(item,0),bits256_str(str,Q[i].txid),price,bestprice); + } + if ( bestprice != 0. ) + { + bestmetric = 0.; + besti = -1; + for (i=0; i 0.9 ) + { + metric = Q[i].destsatoshis / metric * metric * metric; + printf("%f, ",metric); + if ( metric > bestmetric ) + { + besti = i; + bestmetric = metric; + } + } + } + } + printf("metrics, best %f\n",bestmetric); + if ( besti >= 0 )//&& bits256_cmp(myutxo->mypub,otherpubs[besti]) == 0 ) + { + i = besti; + bestprice = prices[i]; + item = jitem(array,i); + bestitem = LP_quotejson(&Q[i]); + printf("bestprice %f vs maxprice %f\n",bestprice,maxprice); + if ( maxprice == 0. || bestprice <= maxprice ) + { + Q[i].desttxid = myutxo->txid; + Q[i].destvout = myutxo->vout; + Q[i].feetxid = myutxo->txid2; + Q[i].feevout = myutxo->vout2; + strcpy(Q[i].destaddr,myutxo->coinaddr); + price = LP_query("request",&Q[i],jstr(item,"ipaddr"),jint(item,"port"),base,myutxo->coin,myutxo->mypub); + if ( jobj(bestitem,"price") != 0 ) + jdelete(bestitem,"price"); + jaddnum(bestitem,"price",prices[i]); + if ( price <= maxprice ) + { + Q[i].desttxid = myutxo->txid; + Q[i].destvout = myutxo->vout; + Q[i].feetxid = myutxo->txid2; + Q[i].feevout = myutxo->vout2; + strcpy(Q[i].destaddr,myutxo->coinaddr); + price = LP_query("connect",&Q[i],jstr(item,"ipaddr"),jint(item,"port"),base,myutxo->coin,myutxo->mypub); + LP_requestinit(&R,Q[i].srchash,Q[i].desthash,base,Q[i].satoshis,Q[i].destcoin,Q[i].destsatoshis,Q[i].timestamp,Q[i].quotetime,DEXselector); + jaddstr(bestitem,"status","connected"); + jaddnum(bestitem,"requestid",R.requestid); + jaddnum(bestitem,"quoteid",R.quoteid); + printf("Alice r.%u q.%u\n",R.requestid,R.quoteid); + } else jaddstr(bestitem,"status","too expensive"); + } + } + } + free_json(array); + } + } + if ( bestitem == 0 ) + return(cJSON_Parse("{\"error\":\"no match found\"}")); + return(bestitem); +} + +int32_t LP_priceping(int32_t pubsock,struct LP_utxoinfo *utxo,char *rel,double profitmargin) +{ + double price; uint32_t now; cJSON *retjson; struct LP_quoteinfo Q; char *retstr; + if ( (now= (uint32_t)time(NULL)) > utxo->swappending ) + utxo->swappending = 0; + if ( now > utxo->published+60 && utxo->swappending == 0 && utxo->pair < 0 && utxo->swap == 0 && (price= LP_price(utxo->coin,rel)) != 0. ) + { + price *= (1. + profitmargin); + if ( LP_quoteinfoinit(&Q,utxo,rel,price) < 0 ) + return(-1); + Q.timestamp = (uint32_t)time(NULL); + retjson = LP_quotejson(&Q); + jaddstr(retjson,"method","quote"); + retstr = jprint(retjson,1); + LP_send(pubsock,retstr,1); + utxo->published = now; + return(0); + } + return(-1); +} + +int32_t LP_command(struct LP_peerinfo *mypeer,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin) +{ + char *method,*base,*rel,*retstr,pairstr[512]; cJSON *retjson; double price; bits256 privkey,txid; struct LP_utxoinfo *utxo; int32_t retval = -1,DEXselector = 0; uint64_t destvalue; struct basilisk_request R; struct LP_quoteinfo Q; + if ( IAMCLIENT == 0 && (method= jstr(argjson,"method")) != 0 ) { txid = jbits256(argjson,"txid"); if ( (utxo= LP_utxofind(txid,jint(argjson,"vout"))) != 0 && strcmp(utxo->ipaddr,mypeer->ipaddr) == 0 && utxo->port == mypeer->port && (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 && strcmp(base,utxo->coin) == 0 ) { + //printf("LP_command.(%s)\n",jprint(argjson,0)); if ( time(NULL) > utxo->swappending ) utxo->swappending = 0; if ( strcmp(method,"price") == 0 || strcmp(method,"request") == 0 ) { - if ( utxo->swappending == 0 && utxo->pair < 0 ) + retval = 1; + if ( utxo->swappending == 0 ) { - if ( utxo->pair >= 0 ) + if ( strcmp(method,"request") == 0 && utxo->pair >= 0 ) nn_close(utxo->pair), utxo->pair = -1; if ( (price= LP_price(base,rel)) != 0. ) { price *= (1. + profitmargin); - retjson = cJSON_CreateObject(); - jaddstr(retjson,"base",base); - jaddstr(retjson,"rel",rel); - jaddnum(retjson,"timestamp",time(NULL)); - jaddnum(retjson,"price",price); - jaddbits256(retjson,"txid",txid); - pubkey = LP_pubkey(LP_privkey(utxo->coinaddr)); - jaddbits256(retjson,"srchash",pubkey); - txfee = LP_txfee(base); - jadd64bits(retjson,"txfee",txfee); - jadd64bits(retjson,"satoshis",utxo->satoshis - txfee); - jadd64bits(retjson,"destsatoshis",price * (utxo->satoshis-txfee)); + if ( LP_quoteinfoinit(&Q,utxo,rel,price) < 0 ) + return(-1); + if ( strcmp(method,"price") == 0 ) + Q.timestamp = (uint32_t)time(NULL); + retjson = LP_quotejson(&Q); if ( strcmp(method,"request") == 0 ) { - utxo->swappending = (uint32_t)(time(NULL) + 60); - utxo->otherpubkey = jbits256(argjson,"pubkey"); - jaddstr(retjson,"result","reserved"); + retval |= 2; + utxo->swappending = (uint32_t)(time(NULL) + LP_RESERVETIME); + utxo->otherpubkey = jbits256(argjson,"desthash"); + jaddnum(retjson,"quotetime",juint(argjson,"quotetime")); jaddnum(retjson,"pending",utxo->swappending); + jaddbits256(retjson,"desthash",utxo->otherpubkey); + jaddstr(retjson,"method","reserved"); } + else jaddstr(retjson,"method","quote"); retstr = jprint(retjson,1); LP_send(pubsock,retstr,1); - } - } + utxo->published = (uint32_t)time(NULL); + } else printf("null price\n"); + } else printf("swappending.%u pair.%d\n",utxo->swappending,utxo->pair); } else if ( strcmp(method,"connect") == 0 ) { + retval = 4; if ( utxo->pair < 0 ) { if ( (price= LP_price(base,rel)) != 0. ) { price *= (1. + profitmargin); - txfee = LP_txfee(base); - satoshis = j64bits(argjson,"satoshis"); - desttxfee = LP_txfee(rel); - desttxid = jbits256(argjson,"desttxid"); - destvout = jint(argjson,"destvout"); - timestamp = juint(argjson,"timestamp"); - quotetime = juint(argjson,"quotetime"); + if ( LP_quoteinfoinit(&Q,utxo,rel,price) < 0 ) + return(-1); + if ( LP_quoteparse(&Q,argjson) < 0 ) + return(-2); + //printf("connect with.(%s)\n",jprint(argjson,0)); privkey = LP_privkey(utxo->coinaddr); - pubkey = LP_pubkey(privkey); - srchash = jbits256(argjson,"srchash"); - value = j64bits(argjson,"destsatoshis"); - if ( timestamp == utxo->swappending-60 && quotetime >= timestamp && quotetime < utxo->swappending && bits256_cmp(pubkey,srchash) == 0 && (destsatoshis= LP_txvalue(rel,desttxid,destvout)) > price*(utxo->satoshis-txfee)+desttxfee && value <= destsatoshis-desttxfee ) + if ( bits256_nonz(utxo->mypub) == 0 ) + utxo->mypub = LP_pubkey(privkey); + if ( bits256_nonz(privkey) != 0 && Q.quotetime >= Q.timestamp-3 && Q.quotetime < utxo->swappending && bits256_cmp(utxo->mypub,Q.srchash) == 0 && (destvalue= LP_txvalue(rel,Q.desttxid,Q.destvout)) >= price*Q.satoshis+Q.desttxfee && destvalue >= Q.destsatoshis+Q.desttxfee ) { - destsatoshis = value; + Q.change = destvalue - (Q.destsatoshis+Q.desttxfee); + nanomsg_tcpname(pairstr,mypeer->ipaddr,10000+(rand() % 10000)); if ( (utxo->pair= nn_socket(AF_SP,NN_PAIR)) < 0 ) printf("error creating utxo->pair\n"); - else if ( (pairstr= jstr(argjson,"pair")) != 0 && nn_connect(utxo->pair,pairstr) >= 0 ) + else if ( nn_bind(utxo->pair,pairstr) >= 0 ) { - desthash = jbits256(argjson,"desthash"); - LP_requestinit(&R,srchash,desthash,base,satoshis,rel,destsatoshis,timestamp,quotetime,DEXselector); - if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_bobloop,(void *)utxo) != 0 ) + //char str[65]; printf("destsatoshis %.8f %s t%u\n",dstr(Q.destsatoshis),bits256_str(str,Q.desthash),Q.quotetime); + LP_requestinit(&R,Q.srchash,Q.desthash,base,Q.satoshis,rel,Q.destsatoshis,Q.timestamp,Q.quotetime,DEXselector); + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_bobloop,(void *)utxo) == 0 ) { - retjson = cJSON_CreateObject(); - jaddstr(retjson,"result","connected"); + retjson = LP_quotejson(&Q); + jaddstr(retjson,"method","connected"); + jaddstr(retjson,"pair",pairstr); jaddnum(retjson,"requestid",R.requestid); jaddnum(retjson,"quoteid",R.quoteid); retstr = jprint(retjson,1); LP_send(pubsock,retstr,1); - utxo->swap = LP_swapinit(1,0,privkey,&R); + utxo->swap = LP_swapinit(1,0,privkey,&R,&Q); } else { @@ -126,28 +490,117 @@ void LP_command(struct LP_peerinfo *mypeer,int32_t pubsock,cJSON *argjson,uint8_ } else { - if ( pairstr != 0 ) - printf("printf error nn_connect to %s\n",pairstr); - else printf("(%s) missing pair\n",jprint(argjson,0)); + printf("printf error nn_connect to %s\n",pairstr); nn_close(utxo->pair); utxo->pair = -1; } - } else printf("dest %.8f < required %.8f\n",dstr(value),dstr(price*(utxo->satoshis-txfee))); + } else printf("dest %.8f < required %.8f (%d %d %d %d %d %d) %.8f %.8f\n",dstr(Q.satoshis),dstr(price*(utxo->satoshis-Q.txfee)),bits256_nonz(privkey) != 0 ,Q.timestamp == utxo->swappending-LP_RESERVETIME ,Q.quotetime >= Q.timestamp ,Q.quotetime < utxo->swappending ,bits256_cmp(utxo->mypub,Q.srchash) == 0 , LP_txvalue(rel,Q.desttxid,Q.destvout) >= price*Q.satoshis+Q.desttxfee,dstr(LP_txvalue(rel,Q.desttxid,Q.destvout)),dstr(price*Q.satoshis+Q.desttxfee)); } else printf("no price for %s/%s\n",base,rel); } else printf("utxo->pair.%d when connect came in (%s)\n",utxo->pair,jprint(argjson,0)); } } } + return(retval); } +char *LP_connected(cJSON *argjson) +{ + cJSON *retjson; int32_t pairsock = -1; char *pairstr; struct LP_quoteinfo *qp; int32_t DEXselector = 0; + retjson = cJSON_CreateObject(); + if ( IAMCLIENT == 0 ) + jaddstr(retjson,"result","update stats"); + else + { + if ( (pairstr= jstr(argjson,"pair")) == 0 || (pairsock= nn_socket(AF_SP,NN_PAIR)) < 0 ) + jaddstr(retjson,"error","couldnt create pairsock"); + else if ( nn_connect(pairsock,pairstr) >= 0 ) + { + qp = calloc(1,sizeof(*qp)); + LP_quoteparse(qp,argjson); + qp->pair = pairsock; + qp->privkey = LP_privkey(qp->destaddr); + LP_requestinit(&qp->R,qp->srchash,qp->desthash,qp->srccoin,qp->satoshis,qp->destcoin,qp->destsatoshis,qp->timestamp,qp->quotetime,DEXselector); + printf("alice pairstr.(%s)\n",pairstr); + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_aliceloop,(void *)qp) == 0 ) + { + jaddstr(retjson,"result","success"); + jadd(retjson,"trade",LP_quotejson(qp)); + } else jaddstr(retjson,"error","couldnt aliceloop"); + } + } + return(jprint(retjson,1)); +} + +// addcoin api + char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port { - char *method,*ipaddr,*coin,*retstr = 0; uint16_t argport,pushport,subport; int32_t otherpeers,othernumutxos; struct LP_peerinfo *peer; cJSON *retjson; + char *method,*ipaddr,*userpass,*base,*rel,*coin,*retstr = 0; uint16_t argport,pushport,subport; int32_t amclient,otherpeers,othernumutxos; struct LP_peerinfo *peer; cJSON *retjson; if ( (method= jstr(argjson,"method")) == 0 ) return(clonestr("{\"error\":\"need method in request\"}")); - else + if ( USERPASS[0] != 0 && strcmp(remoteaddr,"127.0.0.1") == 0 && port != 0 ) + { + if ( USERPASS_COUNTER == 0 ) + { + USERPASS_COUNTER = 1; + retjson = cJSON_CreateObject(); + jaddstr(retjson,"userpass",USERPASS); + jaddstr(retjson,"BTC",BTCADDR); + jaddstr(retjson,"KMD",KMDADDR); + return(jprint(retjson,1)); + } + if ( (userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,USERPASS) != 0 ) + return(clonestr("{\"error\":\"authentication error\"}")); + if ( (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 ) + { + if ( strcmp(method,"setprice") == 0 ) + { + if ( LP_mypriceset(base,rel,jdouble(argjson,"price")) < 0 ) + return(clonestr("{\"error\":\"couldnt set price\"}")); + else return(clonestr("{\"result\":\"success\"}")); + } + else if ( strcmp(method,"myprice") == 0 ) + { + double bid,ask; + if ( LP_myprice(&bid,&ask,base,rel) != 0. ) + { + retjson = cJSON_CreateObject(); + jaddstr(retjson,"base",base); + jaddstr(retjson,"rel",rel); + jaddnum(retjson,"bid",bid); + jaddnum(retjson,"ask",ask); + return(jprint(retjson,1)); + } else return(clonestr("{\"error\":\"no price set\"}")); + } + } + else if ( (coin= jstr(argjson,"coin")) != 0 ) + { + if ( strcmp(method,"inventory") == 0 ) + { + LP_privkey_init(0,-1,coin,0,USERPASS_WIFSTR,1); + return(LP_inventory(coin)); + } + else if ( IAMCLIENT != 0 && (strcmp(method,"candidates") == 0 || strcmp(method,"autotrade") == 0) ) + { + bits256 txid; int32_t vout; struct LP_utxoinfo *utxo; + txid = jbits256(argjson,"txid"); + if ( bits256_nonz(txid) == 0 ) + return(clonestr("{\"error\":\"invalid or missing txid\"}")); + if ( jobj(argjson,"vout") == 0 ) + return(clonestr("{\"error\":\"missing vout\"}")); + vout = jint(argjson,"vout"); + if ( (utxo= LP_utxofind(txid,vout)) == 0 ) + return(clonestr("{\"error\":\"txid/vout not found\"}")); + if ( strcmp(method,"candidates") == 0 ) + return(jprint(LP_tradecandidates(utxo,coin),1)); + else return(jprint(LP_autotrade(utxo,coin,jdouble(argjson,"maxprice")),1)); + } + } + } + amclient = (LP_mypeer == 0); + if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 ) { - if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 ) + if ( strcmp(ipaddr,"127.0.0.1") != 0 && port >= 1000 ) { if ( (pushport= juint(argjson,"push")) == 0 ) pushport = argport + 1; @@ -155,32 +608,42 @@ char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port subport = argport + 2; if ( (peer= LP_peerfind((uint32_t)calc_ipbits(ipaddr),argport)) != 0 ) { - if ( (otherpeers= jint(argjson,"numpeers")) > peer->numpeers ) + if ( 0 && (otherpeers= jint(argjson,"numpeers")) > peer->numpeers ) peer->numpeers = otherpeers; - if ( (othernumutxos= jint(argjson,"numutxos")) > peer->numutxos ) + if ( 0 && (othernumutxos= jint(argjson,"numutxos")) > peer->numutxos ) { - printf("change.(%s) numutxos.%d -> %d mynumutxos.%d\n",peer->ipaddr,peer->numutxos,othernumutxos,LP_mypeer->numutxos); + printf("change.(%s) numutxos.%d -> %d mynumutxos.%d\n",peer->ipaddr,peer->numutxos,othernumutxos,LP_mypeer != 0 ? LP_mypeer->numutxos:0); peer->numutxos = othernumutxos; } //printf("peer.(%s) found (%d %d) (%d %d) (%s)\n",peer->ipaddr,peer->numpeers,peer->numutxos,otherpeers,othernumutxos,jprint(argjson,0)); - } else LP_addpeer(LP_mypeer,LP_mypubsock,ipaddr,argport,pushport,subport,jdouble(argjson,"profit"),jint(argjson,"numpeers"),jint(argjson,"numutxos")); - if ( strcmp(method,"getpeers") == 0 ) - retstr = LP_peers(); - else if ( strcmp(method,"getutxos") == 0 && (coin= jstr(argjson,"coin")) != 0 ) - retstr = LP_utxos(LP_mypeer,coin,jint(argjson,"lastn")); - else if ( strcmp(method,"notify") == 0 ) - retstr = clonestr("{\"result\":\"success\",\"notify\":\"received\"}"); - else if ( strcmp(method,"notifyutxo") == 0 ) - { - printf("utxonotify.(%s)\n",jprint(argjson,0)); - LP_addutxo(LP_mypeer,LP_mypubsock,jstr(argjson,"coin"),jbits256(argjson,"txid"),jint(argjson,"vout"),SATOSHIDEN * jdouble(argjson,"value"),jbits256(argjson,"deposit"),jint(argjson,"dvout"),SATOSHIDEN * jdouble(argjson,"dvalue"),jstr(argjson,"script"),jstr(argjson,"address"),ipaddr,argport,jdouble(argjson,"profit")); - retstr = clonestr("{\"result\":\"success\",\"notifyutxo\":\"received\"}"); - } - } else printf("malformed request.(%s)\n",jprint(argjson,0)); + } else LP_addpeer(amclient,LP_mypeer,LP_mypubsock,ipaddr,argport,pushport,subport,jdouble(argjson,"profit"),jint(argjson,"numpeers"),jint(argjson,"numutxos")); + } + } + //printf("CMD.(%s)\n",jprint(argjson,0)); + if ( strcmp(method,"quote") == 0 || strcmp(method,"reserved") == 0 ) + retstr = LP_quotereceived(argjson); + else if ( strcmp(method,"connected") == 0 ) + retstr = LP_connected(argjson); + else if ( strcmp(method,"getprice") == 0 ) + retstr = LP_pricestr(jstr(argjson,"base"),jstr(argjson,"rel")); + else if ( strcmp(method,"orderbook") == 0 ) + retstr = LP_orderbook(jstr(argjson,"base"),jstr(argjson,"rel")); + else if ( strcmp(method,"getpeers") == 0 ) + retstr = LP_peers(); + else if ( IAMCLIENT == 0 && strcmp(method,"getutxos") == 0 && (coin= jstr(argjson,"coin")) != 0 ) + retstr = LP_utxos(LP_mypeer,coin,jint(argjson,"lastn")); + else if ( IAMCLIENT == 0 && strcmp(method,"notify") == 0 ) + retstr = clonestr("{\"result\":\"success\",\"notify\":\"received\"}"); + else if ( IAMCLIENT == 0 && strcmp(method,"notifyutxo") == 0 ) + { + printf("utxonotify.(%s)\n",jprint(argjson,0)); + LP_addutxo(amclient,LP_mypeer,LP_mypubsock,jstr(argjson,"coin"),jbits256(argjson,"txid"),jint(argjson,"vout"),SATOSHIDEN * jdouble(argjson,"value"),jbits256(argjson,"txid2"),jint(argjson,"vout2"),SATOSHIDEN * jdouble(argjson,"value2"),jstr(argjson,"script"),jstr(argjson,"address"),jstr(argjson,"ipaddr"),juint(argjson,"port"),jdouble(argjson,"profit")); + retstr = clonestr("{\"result\":\"success\",\"notifyutxo\":\"received\"}"); } if ( retstr != 0 ) return(retstr); retjson = cJSON_CreateObject(); jaddstr(retjson,"error","unrecognized command"); + printf("ERROR.(%s)\n",jprint(argjson,0)); return(clonestr(jprint(retjson,1))); } diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index 965b2a7ae..9dc21ab9b 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -21,55 +21,6 @@ #ifndef LP_INCLUDE_H #define LP_INCLUDE_H -#define BASILISK_DISABLEWAITTX -#define BASILISK_DISABLESENDTX - -#define BASILISK_DEFAULT_NUMCONFIRMS 5 -#define DEX_SLEEP 3 -#define BASILISK_DEXDURATION 300 -#define BASILISK_MSGDURATION 30 -#define BASILISK_AUCTION_DURATION 5 - -#define BASILISK_MAXFUTUREBLOCK 60 -#define BASILISK_KEYSIZE ((int32_t)(2*sizeof(bits256)+sizeof(uint32_t)*2)) - -extern char GLOBAL_DBDIR[]; - -void *bitcoin_ctx(); -int32_t bitcoin_verify(void *ctx,uint8_t *sig,int32_t siglen,bits256 txhash2,uint8_t *pubkey,int32_t plen); -int32_t bitcoin_recoververify(void *ctx,char *symbol,uint8_t *sig,bits256 messagehash2,uint8_t *pubkey,size_t plen); -int32_t bitcoin_sign(void *ctx,char *symbol,uint8_t *sig,bits256 txhash2,bits256 privkey,int32_t recoverflag); -bits256 bitcoin_pubkey33(void *ctx,uint8_t *data,bits256 privkey); -bits256 bitcoin_pub256(void *ctx,bits256 *privkeyp,uint8_t odd_even); - -char *bitcoin_base58encode(char *coinaddr,uint8_t *data,int32_t datalen); -int32_t bitcoin_base58decode(uint8_t *data,char *coinaddr); - -#define IGUANA_MAXSCRIPTSIZE 10001 -#define IGUANA_SEQUENCEID_FINAL 0xfffffffe - -#define IGUANA_SCRIPT_NULL 0 -#define IGUANA_SCRIPT_76AC 1 -#define IGUANA_SCRIPT_76A988AC 2 -#define IGUANA_SCRIPT_P2SH 3 -#define IGUANA_SCRIPT_OPRETURN 4 -#define IGUANA_SCRIPT_3of3 5 -#define IGUANA_SCRIPT_2of3 6 -#define IGUANA_SCRIPT_1of3 7 -#define IGUANA_SCRIPT_2of2 8 -#define IGUANA_SCRIPT_1of2 9 -#define IGUANA_SCRIPT_MSIG 10 -#define IGUANA_SCRIPT_DATA 11 -#define IGUANA_SCRIPT_AC 12 -#define IGUANA_SCRIPT_1of1 13 -#define IGUANA_SCRIPT_STRANGE 15 - -#define BASILISK_TIMEOUT 3000 -#define BASILISK_MINFANOUT 8 -#define BASILISK_MAXFANOUT 64 -#define BASILISK_DEFAULTDIFF 0x1effffff -#define BASILISK_HDROFFSET ((int32_t)(sizeof(bits256)+sizeof(struct iguana_msghdr)+sizeof(uint32_t))) - #define INSTANTDEX_DECKSIZE 1000 #define INSTANTDEX_LOCKTIME (3600*2 + 300*2) #define INSTANTDEX_INSURANCEDIV 777 @@ -80,6 +31,20 @@ int32_t bitcoin_base58decode(uint8_t *data,char *coinaddr); #define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu" #define INSTANTDEX_BTCD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf" +#define BASILISK_DISABLEWAITTX +#define BASILISK_DISABLESENDTX + +#define LP_PROPAGATION_SLACK 10 // txid ordering is not enforced, so getting extra recent txid +#define LP_RESERVETIME 60 +#define LP_AVETXSIZE 200 +#define LP_CACHEDURATION 60 +#define BASILISK_DEFAULT_NUMCONFIRMS 5 +#define DEX_SLEEP 3 +#define BASILISK_KEYSIZE ((int32_t)(2*sizeof(bits256)+sizeof(uint32_t)*2)) + +extern char GLOBAL_DBDIR[],USERPASS[],USERPASS_WIFSTR[]; +extern int32_t IAMCLIENT,USERPASS_COUNTER; + struct iguana_msgvin { bits256 prev_hash; uint8_t *vinscript,*userdata,*spendscript,*redeemscript; uint32_t prev_vout,sequence; uint16_t scriptlen,p2shlen,userdatalen,spendlen; }; struct iguana_msgvout { uint64_t value; uint32_t pk_scriptlen; uint8_t *pk_script; }; @@ -102,7 +67,7 @@ struct vin_info struct iguana_msgvin vin; uint64_t amount; cJSON *extras; bits256 sigtxid; int32_t M,N,validmask,spendlen,type,p2shlen,numpubkeys,numsigs,height,hashtype,userdatalen,suppress_pubkeys,ignore_cltverr; uint32_t sequence,unspentind; struct vin_signer signers[16]; char coinaddr[65]; - uint8_t rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE],p2shscript[IGUANA_MAXSCRIPTSIZE],userdata[IGUANA_MAXSCRIPTSIZE]; + uint8_t rmd160[20],spendscript[10000],p2shscript[10000],userdata[10000]; }; struct basilisk_swapmessage @@ -171,10 +136,10 @@ struct basilisk_swapinfo struct iguana_info { - uint64_t txfee,estimatedfee; + uint64_t txfee; double estimatedrate; int32_t longestchain; uint8_t pubtype,p2shtype,isPoS,wiftype; - char symbol[16],changeaddr[64]; + char symbol[16],changeaddr[64],userpass[1024],serverport[128]; }; struct basilisk_swap @@ -190,280 +155,49 @@ struct basilisk_swap struct basilisk_swapmessage *messages; int32_t nummessages; char Bdeposit[64],Bpayment[64]; uint64_t otherdeck[INSTANTDEX_DECKSIZE][2],deck[INSTANTDEX_DECKSIZE][2]; - uint8_t persistent_pubkey33[33],pad[15],verifybuf[65536]; + uint8_t persistent_pubkey33[33],changermd160[20],pad[15],verifybuf[65536]; }; -static struct bitcoin_opcode { UT_hash_handle hh; uint8_t opcode,flags,stackitems; int8_t extralen; } *OPTABLE; static char *OPCODES[0x100]; static int32_t OPCODELENS[0x100]; - -#define SIGHASH_ALL 1 -#define SIGHASH_NONE 2 -#define SIGHASH_SINGLE 3 -#define SIGHASH_ANYONECANPAY 0x80 - -#define SCRIPT_OP_NOP 0x00 -#define SCRIPT_OP_TRUE 0x51 -#define SCRIPT_OP_2 0x52 -#define SCRIPT_OP_3 0x53 -#define SCRIPT_OP_4 0x54 -#define SCRIPT_OP_IF 0x63 -#define SCRIPT_OP_ELSE 0x67 -#define SCRIPT_OP_RETURN 0x6a -#define SCRIPT_OP_DUP 0x76 -#define SCRIPT_OP_ENDIF 0x68 -#define SCRIPT_OP_DROP 0x75 -#define SCRIPT_OP_EQUALVERIFY 0x88 -#define SCRIPT_OP_SHA256 0xa8 -#define SCRIPT_OP_HASH160 0xa9 - -#define SCRIPT_OP_EQUAL 0x87 -#define SCRIPT_OP_CHECKSIG 0xac -#define SCRIPT_OP_CHECKMULTISIG 0xae -#define SCRIPT_OP_CHECKSEQUENCEVERIFY 0xb2 -#define SCRIPT_OP_CHECKLOCKTIMEVERIFY 0xb1 -#define IGUANA_OP_0 0x00 -#define IGUANA_OP_PUSHDATA1 0x4c -#define IGUANA_OP_PUSHDATA2 0x4d -#define IGUANA_OP_PUSHDATA4 0x4e -#define IGUANA_OP_1NEGATE 0x4f -#define IGUANA_OP_1 0x51 -#define IGUANA_OP_16 0x60 -#define IGUANA_OP_NOP 0x61 -#define IGUANA_OP_IF 0x63 -#define IGUANA_OP_NOTIF 0x64 -#define IGUANA_OP_ELSE 0x67 -#define IGUANA_OP_ENDIF 0x68 -#define IGUANA_OP_VERIFY 0x69 -#define IGUANA_OP_RETURN 0x6a - -#define IGUANA_OP_TOALTSTACK 0x6b -#define IGUANA_OP_FROMALTSTACK 0x6c -#define IGUANA_OP_2DROP 0x6d -#define IGUANA_OP_2DUP 0x6e -#define IGUANA_OP_3DUP 0x6f -#define IGUANA_OP_2OVER 0x70 -#define IGUANA_OP_2ROT 0x71 -#define IGUANA_OP_2SWAP 0x72 -#define IGUANA_OP_IFDUP 0x73 -#define IGUANA_OP_DEPTH 0x74 -#define IGUANA_OP_DROP 0x75 -#define IGUANA_OP_DUP 0x76 -#define IGUANA_OP_NIP 0x77 -#define IGUANA_OP_OVER 0x78 -#define IGUANA_OP_PICK 0x79 -#define IGUANA_OP_ROLL 0x7a -#define IGUANA_OP_ROT 0x7b -#define IGUANA_OP_SWAP 0x7c -#define IGUANA_OP_TUCK 0x7d - -#define IGUANA_OP_EQUAL 0x87 -#define IGUANA_OP_EQUALVERIFY 0x88 - -#define IGUANA_OP_1ADD 0x8b -#define IGUANA_OP_1SUB 0x8c -#define IGUANA_OP_NEGATE 0x8f -#define IGUANA_OP_ABS 0x90 -#define IGUANA_OP_NOT 0x91 -#define IGUANA_OP_0NOTEQUAL 0x92 -#define IGUANA_OP_ADD 0x93 -#define IGUANA_OP_SUB 0x94 - -#define IGUANA_OP_BOOLAND 0x9a -#define IGUANA_OP_BOOLOR 0x9b -#define IGUANA_OP_NUMEQUAL 0x9c -#define IGUANA_OP_NUMEQUALVERIFY 0x9d -#define IGUANA_OP_NUMNOTEQUAL 0x9e -#define IGUANA_OP_LESSTHAN 0x9f -#define IGUANA_OP_GREATERTHAN 0xa0 -#define IGUANA_OP_LESSTHANOREQUAL 0xa1 -#define IGUANA_OP_GREATERTHANOREQUAL 0xa2 -#define IGUANA_OP_MIN 0xa3 -#define IGUANA_OP_MAX 0xa4 -#define IGUANA_OP_WITHIN 0xa5 - -#define IGUANA_OP_RIPEMD160 0xa6 -#define IGUANA_OP_SHA1 0xa7 -#define IGUANA_OP_SHA256 0xa8 -#define IGUANA_OP_HASH160 0xa9 -#define IGUANA_OP_HASH256 0xaa -#define IGUANA_OP_CODESEPARATOR 0xab -#define IGUANA_OP_CHECKSIG 0xac -#define IGUANA_OP_CHECKSIGVERIFY 0xad -#define IGUANA_OP_CHECKMULTISIG 0xae -#define IGUANA_OP_CHECKMULTISIGVERIFY 0xaf - -#define IGUANA_OP_NOP1 0xb0 -#define IGUANA_OP_CHECKLOCKTIMEVERIFY 0xb1 -#define IGUANA_OP_CHECKSEQUENCEVERIFY 0xb2 -#define IGUANA_OP_NOP10 0xb9 - -#define IGUANA_OP_COMBINEPUBKEYS 0xc0 -#define IGUANA_OP_CHECKSCHNORR 0xc1 -#define IGUANA_OP_CHECKSCHNORRVERIFY 0xc2 - -// https://github.com/TierNolan/bips/blob/cpkv/bip-cprkv.mediawiki -#define IGUANA_OP_CHECKPRIVATEKEY 0xc3 -#define IGUANA_OP_CHECKPRIVATEKEYVERIFY 0xc4 +struct LP_utxoinfo +{ + UT_hash_handle hh; + bits256 txid,txid2,feetxid,otherpubkey,mypub; + void *swap; + uint64_t satoshis,satoshis2; + uint8_t key[sizeof(bits256) + sizeof(int32_t)]; + int32_t vout,vout2,pair; + uint32_t lasttime,errors,swappending,published; + double profitmargin; + char ipaddr[64],coinaddr[64],spendscript[256],coin[16]; + uint16_t port; +}; -#define IGUANA_NOPFLAG 1 -#define IGUANA_ALWAYSILLEGAL 2 -#define IGUANA_EXECUTIONILLEGAL 4 -#define IGUANA_POSTVERIFY 8 -#define IGUANA_CRYPTOFLAG 16 -#define IGUANA_MATHFLAG 32 -#define IGUANA_CONTROLFLAG 64 -#define IGUANA_STACKFLAG 128 +struct LP_peerinfo +{ + UT_hash_handle hh; + uint64_t ip_port; + double profitmargin; + uint32_t ipbits,errortime,errors,numpeers,numutxos,lasttime,connected; + int32_t pushsock,subsock; + uint16_t port; + char ipaddr[64]; +}; -enum opcodetype +struct LP_quoteinfo { - // push value - OP_0 = 0x00, - OP_FALSE = OP_0, - OP_PUSHDATA1 = 0x4c, - OP_PUSHDATA2 = 0x4d, - OP_PUSHDATA4 = 0x4e, - OP_1NEGATE = 0x4f, - OP_RESERVED = 0x50, - OP_1 = 0x51, - OP_TRUE=OP_1, - OP_2 = 0x52, - OP_3 = 0x53, - OP_4 = 0x54, - OP_5 = 0x55, - OP_6 = 0x56, - OP_7 = 0x57, - OP_8 = 0x58, - OP_9 = 0x59, - OP_10 = 0x5a, - OP_11 = 0x5b, - OP_12 = 0x5c, - OP_13 = 0x5d, - OP_14 = 0x5e, - OP_15 = 0x5f, - OP_16 = 0x60, - - // control - OP_NOP = 0x61, - OP_VER = 0x62, - OP_IF = 0x63, - OP_NOTIF = 0x64, - OP_VERIF = 0x65, - OP_VERNOTIF = 0x66, - OP_ELSE = 0x67, - OP_ENDIF = 0x68, - OP_VERIFY = 0x69, - OP_RETURN = 0x6a, - - // stack ops - OP_TOALTSTACK = 0x6b, - OP_FROMALTSTACK = 0x6c, - OP_2DROP = 0x6d, - OP_2DUP = 0x6e, - OP_3DUP = 0x6f, - OP_2OVER = 0x70, - OP_2ROT = 0x71, - OP_2SWAP = 0x72, - OP_IFDUP = 0x73, - OP_DEPTH = 0x74, - OP_DROP = 0x75, - OP_DUP = 0x76, - OP_NIP = 0x77, - OP_OVER = 0x78, - OP_PICK = 0x79, - OP_ROLL = 0x7a, - OP_ROT = 0x7b, - OP_SWAP = 0x7c, - OP_TUCK = 0x7d, - - // splice ops - OP_CAT = 0x7e, - OP_SUBSTR = 0x7f, - OP_LEFT = 0x80, - OP_RIGHT = 0x81, - OP_SIZE = 0x82, - - // bit logic - OP_INVERT = 0x83, - OP_AND = 0x84, - OP_OR = 0x85, - OP_XOR = 0x86, - OP_EQUAL = 0x87, - OP_EQUALVERIFY = 0x88, - OP_RESERVED1 = 0x89, - OP_RESERVED2 = 0x8a, - - // numeric - OP_1ADD = 0x8b, - OP_1SUB = 0x8c, - OP_2MUL = 0x8d, - OP_2DIV = 0x8e, - OP_NEGATE = 0x8f, - OP_ABS = 0x90, - OP_NOT = 0x91, - OP_0NOTEQUAL = 0x92, - - OP_ADD = 0x93, - OP_SUB = 0x94, - OP_MUL = 0x95, - OP_DIV = 0x96, - OP_MOD = 0x97, - OP_LSHIFT = 0x98, - OP_RSHIFT = 0x99, - - OP_BOOLAND = 0x9a, - OP_BOOLOR = 0x9b, - OP_NUMEQUAL = 0x9c, - OP_NUMEQUALVERIFY = 0x9d, - OP_NUMNOTEQUAL = 0x9e, - OP_LESSTHAN = 0x9f, - OP_GREATERTHAN = 0xa0, - OP_LESSTHANOREQUAL = 0xa1, - OP_GREATERTHANOREQUAL = 0xa2, - OP_MIN = 0xa3, - OP_MAX = 0xa4, - - OP_WITHIN = 0xa5, - - // crypto - OP_RIPEMD160 = 0xa6, - OP_SHA1 = 0xa7, - OP_SHA256 = 0xa8, - OP_HASH160 = 0xa9, - OP_HASH256 = 0xaa, - OP_CODESEPARATOR = 0xab, - OP_CHECKSIG = 0xac, - OP_CHECKSIGVERIFY = 0xad, - OP_CHECKMULTISIG = 0xae, - OP_CHECKMULTISIGVERIFY = 0xaf, - - // expansion - OP_NOP1 = 0xb0, - OP_CHECKLOCKTIMEVERIFY = 0xb1, - OP_CHECKSEQUENCEVERIFY = 0xb2, - OP_NOP4 = 0xb3, - OP_NOP5 = 0xb4, - OP_NOP6 = 0xb5, - OP_NOP7 = 0xb6, - OP_NOP8 = 0xb7, - OP_NOP9 = 0xb8, - OP_NOP10 = 0xb9, - - OP_COMBINEPUBKEYS = 0xc0, - OP_CHECKSCHNORR = 0xc1, - OP_CHECKSCHNORRVERIFY = 0xc2, - OP_CHECKPRIVATEKEY = 0xc3, - OP_CHECKPRIVATEKEYVERIFY = 0xc4, - - // template matching params - //OP_SMALLINTEGER = 0xfa, - //OP_PUBKEYS = 0xfb, - //OP_PUBKEYHASH = 0xfd, - //OP_PUBKEY = 0xfe, - - OP_INVALIDOPCODE = 0xff, + struct basilisk_request R; + bits256 srchash,desthash,txid,txid2,desttxid,feetxid,privkey; + uint64_t satoshis,satoshis2,txfee,destsatoshis,desttxfee,change; + uint32_t timestamp,quotetime; int32_t vout,vout2,destvout,feevout,pair; + char srccoin[16],coinaddr[64],destcoin[16],destaddr[64]; }; + void basilisk_dontforget_update(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx); uint32_t basilisk_requestid(struct basilisk_request *rp); uint32_t basilisk_quoteid(struct basilisk_request *rp); +struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp); +char *bitcoind_passthru(char *coinstr,char *serverport,char *userpass,char *method,char *params); +uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx,uint32_t nextbits,int32_t suppress_swapsend); #endif diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index 0c2ecb51d..dbda8d683 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -17,673 +17,286 @@ // LP_nativeDEX.c // marketmaker // +// jl777: fix price calcs based on specific txfees #include #include "LP_include.h" #include "LP_network.c" -#define LP_PROPAGATION_SLACK 10 // txid ordering is not enforced, so getting extra recent txid +struct LP_utxoinfo *LP_utxoinfos; +struct LP_peerinfo *LP_peerinfos,*LP_mypeer; -char *default_LPnodes[] = { "5.9.253.195", "5.9.253.196", "5.9.253.197", "5.9.253.198", "5.9.253.199", "5.9.253.200", "5.9.253.201", "5.9.253.202", "5.9.253.203", "5.9.253.204" }; -portable_mutex_t LP_peermutex,LP_utxomutex,LP_commandmutex; -int32_t LP_mypubsock = -1; +char *activecoins[] = { "BTC", "KMD", "REVS", "JUMBLR" };//"LTC", "USD", }; +char GLOBAL_DBDIR[] = { "DB" }; +char USERPASS[65],USERPASS_WIFSTR[64],BTCADDR[64],KMDADDR[64],USERHOME[512] = { "/root" }; -struct LP_peerinfo -{ - UT_hash_handle hh; - uint64_t ip_port; - double profitmargin; - uint32_t ipbits,errortime,errors,numpeers,numutxos,lasttime,connected; - int32_t pushsock,subsock; - uint16_t port; - char ipaddr[64]; -} *LP_peerinfos,*LP_mypeer; +char *default_LPnodes[] = { "5.9.253.196", "5.9.253.197", "5.9.253.198", "5.9.253.199", "5.9.253.200", "5.9.253.201", "5.9.253.202", "5.9.253.203", "5.9.253.204" }; //"5.9.253.195", -struct LP_utxoinfo -{ - UT_hash_handle hh; - bits256 txid,deposittxid,otherpubkey; - void *swap; - uint64_t satoshis,depositsatoshis; - uint8_t key[sizeof(bits256) + sizeof(int32_t)]; - int32_t vout,depositvout,pair; uint32_t lasttime,errors,swappending; - double profitmargin; - char ipaddr[64],coinaddr[64],spendscript[256],coin[16]; - uint16_t port; -} *LP_utxoinfos; +portable_mutex_t LP_peermutex,LP_utxomutex,LP_commandmutex,LP_cachemutex; +int32_t LP_mypubsock = -1; +int32_t Client_connections; +int32_t USERPASS_COUNTER,IAMCLIENT = 0; +double LP_profitratio = 1.; -struct LP_peerinfo *LP_peerfind(uint32_t ipbits,uint16_t port) +// stubs +int32_t basilisk_istrustedbob(struct basilisk_swap *swap) { - struct LP_peerinfo *peer=0; uint64_t ip_port; - ip_port = ((uint64_t)port << 32) | ipbits; - portable_mutex_lock(&LP_peermutex); - HASH_FIND(hh,LP_peerinfos,&ip_port,sizeof(ip_port),peer); - portable_mutex_unlock(&LP_peermutex); - return(peer); + // for BTC and if trusted LP + return(0); } -struct LP_utxoinfo *LP_utxofind(bits256 txid,int32_t vout) +void tradebot_swap_balancingtrade(struct basilisk_swap *swap,int32_t iambob) { - struct LP_utxoinfo *utxo=0; uint8_t key[sizeof(txid) + sizeof(vout)]; - memcpy(key,txid.bytes,sizeof(txid)); - memcpy(&key[sizeof(txid)],&vout,sizeof(vout)); - portable_mutex_lock(&LP_utxomutex); - HASH_FIND(hh,LP_utxoinfos,key,sizeof(key),utxo); - portable_mutex_unlock(&LP_utxomutex); - return(utxo); + } -cJSON *LP_peerjson(struct LP_peerinfo *peer) +void tradebot_pendingadd(cJSON *tradejson,char *base,double basevolume,char *rel,double relvolume) { - cJSON *item = cJSON_CreateObject(); - jaddstr(item,"ipaddr",peer->ipaddr); - jaddnum(item,"port",peer->port); - jaddnum(item,"profit",peer->profitmargin); - return(item); + // add to trades } - -cJSON *LP_utxojson(struct LP_utxoinfo *utxo) +char *LP_getdatadir() { - cJSON *item = cJSON_CreateObject(); - jaddstr(item,"ipaddr",utxo->ipaddr); - jaddnum(item,"port",utxo->port); - jaddnum(item,"profit",utxo->profitmargin); - jaddstr(item,"coin",utxo->coin); - jaddstr(item,"address",utxo->coinaddr); - jaddstr(item,"script",utxo->spendscript); - jaddbits256(item,"txid",utxo->txid); - jaddnum(item,"vout",utxo->vout); - jaddnum(item,"value",dstr(utxo->satoshis)); - jaddbits256(item,"deposit",utxo->deposittxid); - jaddnum(item,"dvout",utxo->depositvout); - jaddnum(item,"dvalue",dstr(utxo->depositsatoshis)); - return(item); + return(USERHOME); } -char *LP_peers() +char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_t skip) { - struct LP_peerinfo *peer,*tmp; cJSON *peersjson = cJSON_CreateArray(); - HASH_ITER(hh,LP_peerinfos,peer,tmp) - { - jaddi(peersjson,LP_peerjson(peer)); - } - return(jprint(peersjson,1)); + return(0); } -char *LP_utxos(struct LP_peerinfo *mypeer,char *coin,int32_t lastn) +#include "LP_secp.c" +#include "LP_bitcoin.c" +#include "LP_coins.c" +#include "LP_rpc.c" +#include "LP_prices.c" +#include "LP_transaction.c" +#include "LP_remember.c" +#include "LP_swap.c" +#include "LP_peers.c" +#include "LP_utxos.c" +#include "LP_commands.c" + +void LP_mainloop(struct LP_peerinfo *mypeer,uint16_t mypubport,int32_t pubsock,int32_t pullsock,uint16_t myport,int32_t amclient,char *passphrase,double profitmargin) { - int32_t i,firsti; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray(); - i = 0; - if ( lastn >= mypeer->numutxos ) - firsti = -1; - else firsti = (mypeer->numutxos - lastn); - HASH_ITER(hh,LP_utxoinfos,utxo,tmp) + //static uint16_t tmpport; + char *retstr; uint8_t r; int32_t i,n,j,len,recvsize,counter=0,nonz,lastn; struct LP_peerinfo *peer,*tmp; struct LP_utxoinfo *utxo,*utmp; void *ptr; cJSON *argjson; + if ( amclient == 0 ) { - if ( i++ < firsti ) - continue; - if ( coin == 0 || coin[0] == 0 || strcmp(coin,utxo->coin) == 0 ) + for (i=0; i 25 ) + continue; + LP_peersquery(amclient,mypeer,pubsock,default_LPnodes[i],myport,mypeer->ipaddr,myport,profitmargin); } } - return(jprint(utxosjson,1)); -} - -struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char *ipaddr,uint16_t port,uint16_t pushport,uint16_t subport,double profitmargin,int32_t numpeers,int32_t numutxos) -{ - uint32_t ipbits; int32_t pushsock,subsock,timeout; char checkip[64],pushaddr[64],subaddr[64]; struct LP_peerinfo *peer = 0; - ipbits = (uint32_t)calc_ipbits(ipaddr); - expand_ipbits(checkip,ipbits); - if ( strcmp(checkip,ipaddr) == 0 ) + else { - //printf("LPaddpeer %s\n",ipaddr); - if ( (peer= LP_peerfind(ipbits,port)) != 0 ) - { - if ( peer->profitmargin == 0. ) - peer->profitmargin = profitmargin; - if ( numpeers > peer->numpeers ) - peer->numpeers = numpeers; - if ( numutxos > peer->numutxos ) - peer->numutxos = numutxos; - } - else + OS_randombytes((void *)&r,sizeof(r)); + for (j=0; jpushsock = peer->subsock = pushsock = subsock = -1; - strcpy(peer->ipaddr,ipaddr); - if ( pushport != 0 && subport != 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 ) - { - if ( (subsock= nn_socket(AF_SP,NN_SUB)) >= 0 ) - { - timeout = 1000; - nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); - timeout = 1; - nn_setsockopt(subsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); - nn_setsockopt(subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); - peer->pushsock = pushsock; - peer->subsock = subsock; - nanomsg_tcpname(pushaddr,peer->ipaddr,pushport); - nanomsg_tcpname(subaddr,peer->ipaddr,subport); - printf("adding (%s and %s) %d %d\n",pushaddr,subaddr,peer->pushsock,peer->subsock); - if ( nn_connect(peer->pushsock,pushaddr) >= 0 && nn_connect(peer->subsock,subaddr) >= 0 ) - peer->connected = (uint32_t)time(NULL); - } else nn_close(pushsock); - } - peer->profitmargin = profitmargin; - peer->ipbits = ipbits; - peer->port = port; - peer->ip_port = ((uint64_t)port << 32) | ipbits; - portable_mutex_lock(&LP_peermutex); - HASH_ADD(hh,LP_peerinfos,ip_port,sizeof(peer->ip_port),peer); - if ( mypeer != 0 ) - { - mypeer->numpeers++; - printf("_LPaddpeer %s -> numpeers.%d mypubsock.%d other.(%d %d)\n",ipaddr,mypeer->numpeers,mypubsock,numpeers,numutxos); - } else peer->numpeers = 1; // will become mypeer - portable_mutex_unlock(&LP_peermutex); - if ( mypubsock >= 0 ) - LP_send(mypubsock,jprint(LP_peerjson(peer),1),1); + i = (r + j) % (sizeof(default_LPnodes)/sizeof(*default_LPnodes)); + LP_peersquery(amclient,mypeer,pubsock,default_LPnodes[i],myport,"127.0.0.1",myport,profitmargin); } } - return(peer); -} - -struct LP_utxoinfo *LP_addutxo(struct LP_peerinfo *mypeer,int32_t mypubsock,char *coin,bits256 txid,int32_t vout,int64_t satoshis,bits256 deposittxid,int32_t depositvout,int64_t depositsatoshis,char *spendscript,char *coinaddr,char *ipaddr,uint16_t port,double profitmargin) -{ - struct LP_utxoinfo *utxo = 0; uint8_t key[sizeof(txid) + sizeof(vout)]; - if ( coin == 0 || coin[0] == 0 || spendscript == 0 || spendscript[0] == 0 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(deposittxid) == 0 || vout < 0 || depositvout < 0 || satoshis <= 0 || depositsatoshis <= 0 ) + //if ( amclient != 0 ) + // tmpport = myport + 10; + //else tmpport = myport; + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)stats_rpcloop,(void *)&myport) != 0 ) { - printf("malformed addutxo %d %d %d %d %d %d %d %d %d %d %d %d\n", coin == 0,coin[0] == 0,spendscript == 0,spendscript[0] == 0,coinaddr == 0,coinaddr[0] == 0,bits256_nonz(txid) == 0,bits256_nonz(deposittxid) == 0,vout < 0,depositvout < 0,satoshis <= 0,depositsatoshis <= 0); - return(0); + printf("error launching stats rpcloop for port.%u\n",myport); + exit(-1); } - if ( (utxo= LP_utxofind(txid,vout)) != 0 ) + for (i=0; itxid) != 0 || bits256_cmp(deposittxid,utxo->deposittxid) != 0 || vout != utxo->vout || satoshis != utxo->satoshis || depositvout != utxo->depositvout || depositsatoshis != utxo->depositsatoshis || strcmp(coin,utxo->coin) != 0 || strcmp(spendscript,utxo->spendscript) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || strcmp(ipaddr,utxo->ipaddr) != 0 || port != utxo->port ) - { - utxo->errors++; - char str[65]; printf("error on subsequent utxo add.(%s)\n",bits256_str(str,txid)); - } - else if ( profitmargin != 0. ) - utxo->profitmargin = profitmargin; + LP_coinfind(activecoins[i]); + LP_priceinfoadd(activecoins[i]); } - else + LP_privkey_updates(mypeer,pubsock,passphrase,amclient); + HASH_ITER(hh,LP_peerinfos,peer,tmp) { - utxo = calloc(1,sizeof(*utxo)); - utxo->pair = -1; - utxo->profitmargin = profitmargin; - strcpy(utxo->ipaddr,ipaddr); - utxo->port = port; - safecopy(utxo->coin,coin,sizeof(utxo->coin)); - safecopy(utxo->coinaddr,coinaddr,sizeof(utxo->coinaddr)); - safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript)); - utxo->txid = txid; - utxo->vout = vout; - utxo->satoshis = satoshis; - utxo->deposittxid = deposittxid; - utxo->depositvout = depositvout; - utxo->depositsatoshis = depositsatoshis; - memcpy(key,txid.bytes,sizeof(txid)); - memcpy(&key[sizeof(txid)],&vout,sizeof(vout)); - memcpy(utxo->key,key,sizeof(key)); - portable_mutex_lock(&LP_utxomutex); - HASH_ADD(hh,LP_utxoinfos,key,sizeof(key),utxo); - if ( mypeer != 0 ) - { - mypeer->numutxos++; - printf("%s:%u LP_addutxo.(%.8f %.8f) numutxos.%d\n",ipaddr,port,dstr(satoshis),dstr(depositsatoshis),mypeer->numutxos); - } - portable_mutex_unlock(&LP_utxomutex); - if ( mypubsock >= 0 ) - LP_send(mypubsock,jprint(LP_utxojson(utxo),1),1); + if ( strcmp(peer->ipaddr,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1") != 0 ) + LP_utxosquery(0,mypeer,pubsock,peer->ipaddr,peer->port,"",100,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1",myport,profitmargin); } - return(utxo); -} - -int32_t LP_peersparse(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now) -{ - struct LP_peerinfo *peer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; - if ( (array= cJSON_Parse(retstr)) != 0 ) + if ( amclient != 0 ) { - if ( (n= cJSON_GetArraySize(array)) > 0 ) + while ( 1 ) { - for (i=0; isubsock >= 0 && (recvsize= nn_recv(peer->subsock,&ptr,NN_MSG,0)) >= 0 ) { - if ( (pushport= juint(item,"push")) == 0 ) - pushport = argport + 1; - if ( (subport= juint(item,"sub")) == 0 ) - subport = argport + 2; - argipbits = (uint32_t)calc_ipbits(argipaddr); - if ( (peer= LP_peerfind(argipbits,argport)) == 0 ) - peer = LP_addpeer(mypeer,mypubsock,argipaddr,argport,pushport,subport,jdouble(item,"profit"),jint(item,"numpeers"),jint(item,"numutxos")); - if ( peer != 0 ) + nonz++; + if ( (argjson= cJSON_Parse((char *)ptr)) != 0 ) { - peer->lasttime = now; - if ( strcmp(argipaddr,destipaddr) == 0 && destport == argport && peer->numpeers < n ) - peer->numpeers = n; - } + portable_mutex_lock(&LP_commandmutex); + if ( (retstr= stats_JSON(argjson,"127.0.0.1",0)) != 0 ) + { + //printf("%s RECV.[%d] %s\n",peer->ipaddr,recvsize,(char *)ptr); + free(retstr); + } + portable_mutex_unlock(&LP_commandmutex); + //printf("subloop.(%s)\n",jprint(argjson,0)); + free_json(argjson); + } else printf("error parsing.(%s)\n",(char *)ptr); + if ( ptr != 0 ) + nn_freemsg(ptr), ptr = 0; } } + if ( nonz == 0 ) + usleep(100000); } - free_json(array); } - return(n); -} - -int32_t LP_utxosparse(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now) -{ - struct LP_peerinfo *peer,*destpeer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; bits256 txid; struct LP_utxoinfo *utxo; - if ( (array= cJSON_Parse(retstr)) != 0 ) + else { - if ( (n= cJSON_GetArraySize(array)) > 0 ) + while ( 1 ) { - for (i=0; iipaddr,mypeer->ipaddr) == 0 && utxo->port == mypeer->port ) { - txid = jbits256(item,"txid"); - utxo = LP_addutxo(mypeer,mypubsock,jstr(item,"coin"),txid,jint(item,"vout"),SATOSHIDEN*jdouble(item,"value"),jbits256(item,"deposit"),jint(item,"dvout"),SATOSHIDEN * jdouble(item,"dvalue"),jstr(item,"script"),jstr(item,"address"),argipaddr,argport,jdouble(item,"profit")); - if ( utxo != 0 ) - utxo->lasttime = now; + if ( strcmp(utxo->coin,"KMD") == 0 ) + LP_priceping(pubsock,utxo,"BTC",profitmargin); + else LP_priceping(pubsock,utxo,"KMD",profitmargin); } } } - if ( (destpeer= LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport)) != 0 ) + HASH_ITER(hh,LP_peerinfos,peer,tmp) { - if ( destpeer->numutxos < n ) + if ( peer->numpeers != mypeer->numpeers || (rand() % 10000) == 0 ) { - destpeer->numutxos = n; - printf("got.(%s) from %s numutxos.%d\n",retstr,destpeer->ipaddr,destpeer->numutxos); + if ( peer->numpeers != mypeer->numpeers ) + printf("%s num.%d vs %d\n",peer->ipaddr,peer->numpeers,mypeer->numpeers); + if ( strcmp(peer->ipaddr,mypeer->ipaddr) != 0 ) + LP_peersquery(amclient,mypeer,pubsock,peer->ipaddr,peer->port,mypeer->ipaddr,myport,profitmargin); + } + if ( peer->numutxos != mypeer->numutxos ) + { + lastn = peer->numutxos - mypeer->numutxos + LP_PROPAGATION_SLACK; + if ( lastn < LP_PROPAGATION_SLACK * 2 ) + lastn = LP_PROPAGATION_SLACK * 2; + printf("%s numutxos.%d vs %d lastn.%d\n",peer->ipaddr,peer->numutxos,mypeer->numutxos,lastn); + if ( strcmp(peer->ipaddr,mypeer->ipaddr) != 0 ) + LP_utxosquery(0,mypeer,pubsock,peer->ipaddr,peer->port,"",lastn,mypeer->ipaddr,myport,profitmargin); + } + while ( peer->subsock >= 0 && (recvsize= nn_recv(peer->subsock,&ptr,NN_MSG,0)) >= 0 ) + { + nonz++; + if ( (argjson= cJSON_Parse((char *)ptr)) != 0 ) + { + portable_mutex_lock(&LP_commandmutex); + if ( (retstr= stats_JSON(argjson,"127.0.0.1",0)) != 0 ) + { + //printf("%s RECV.[%d] %s\n",peer->ipaddr,recvsize,(char *)ptr); + free(retstr); + } + portable_mutex_unlock(&LP_commandmutex); + free_json(argjson); + } else printf("error parsing.(%s)\n",(char *)ptr); + if ( ptr != 0 ) + nn_freemsg(ptr), ptr = 0; } } - } - free_json(array); - } - return(n); -} - -char *issue_LP_getpeers(char *destip,uint16_t destport,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers,int32_t numutxos) -{ - char url[512]; - sprintf(url,"http://%s:%u/api/stats/getpeers?ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,profitmargin,numpeers,numutxos); - //printf("send.(%s)\n",url); - return(issue_curl(url)); -} - -char *issue_LP_getutxos(char *destip,uint16_t destport,char *coin,int32_t lastn,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers,int32_t numutxos) -{ - char url[512]; - sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,coin,lastn,ipaddr,port,profitmargin,numpeers,numutxos); - return(issue_curl(url)); -} - -char *issue_LP_notify(char *destip,uint16_t destport,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers,int32_t numutxos) -{ - char url[512]; - sprintf(url,"http://%s:%u/api/stats/notify?ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,profitmargin,numpeers,numutxos); - return(issue_curl(url)); -} - -char *issue_LP_notifyutxo(char *destip,uint16_t destport,struct LP_utxoinfo *utxo) -{ - char url[4096],str[65],str2[65]; - sprintf(url,"http://%s:%u/api/stats/notifyutxo?ipaddr=%s&port=%u&profit=%.6f&coin=%s&txid=%s&vout=%d&value=%.8f&deposit=%s&dvout=%d&dvalue=%.8f&script=%s&address=%s",destip,destport,utxo->ipaddr,utxo->port,utxo->profitmargin,utxo->coin,bits256_str(str,utxo->txid),utxo->vout,dstr(utxo->satoshis),bits256_str(str2,utxo->deposittxid),utxo->depositvout,dstr(utxo->depositsatoshis),utxo->spendscript,utxo->coinaddr); - if ( strlen(url) > 1024 ) - printf("WARNING long url.(%s)\n",url); - return(issue_curl(url)); -} - -void LP_peersquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *myipaddr,uint16_t myport,double myprofit) -{ - char *retstr; struct LP_peerinfo *peer,*tmp; uint32_t now,flag = 0; - peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); - if ( peer != 0 && peer->errors > 0 ) - return; - if ( (retstr= issue_LP_getpeers(destipaddr,destport,myipaddr,myport,myprofit,mypeer->numpeers,mypeer->numutxos)) != 0 ) - { - //printf("got.(%s)\n",retstr); - now = (uint32_t)time(NULL); - LP_peersparse(mypeer,mypubsock,destipaddr,destport,retstr,now); - free(retstr); - HASH_ITER(hh,LP_peerinfos,peer,tmp) - { - if ( peer->lasttime != now ) - { - printf("{%s:%u %.6f} ",peer->ipaddr,peer->port,peer->profitmargin); - flag++; - if ( (retstr= issue_LP_notify(destipaddr,destport,peer->ipaddr,peer->port,peer->profitmargin,peer->numpeers,0)) != 0 ) - free(retstr); - } - } - if ( flag != 0 ) - printf(" <- missing peers\n"); - } else if ( peer != 0 ) - peer->errors++; -} - -void LP_utxosquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *coin,int32_t lastn,char *myipaddr,uint16_t myport,double myprofit) -{ - char *retstr; struct LP_utxoinfo *utxo,*tmp; struct LP_peerinfo *peer; int32_t i,firsti; uint32_t now,flag = 0; - peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); - if ( (peer != 0 && peer->errors > 0) || mypeer == 0 ) - return; - if ( coin == 0 ) - coin = ""; - if ( (retstr= issue_LP_getutxos(destipaddr,destport,coin,lastn,myipaddr,myport,myprofit,mypeer->numpeers,mypeer->numutxos)) != 0 ) - { - now = (uint32_t)time(NULL); - LP_utxosparse(mypeer,mypubsock,destipaddr,destport,retstr,now); - free(retstr); - i = 0; - if ( lastn >= mypeer->numutxos ) - firsti = -1; - else firsti = (mypeer->numutxos - lastn); - HASH_ITER(hh,LP_utxoinfos,utxo,tmp) - { - if ( i++ < firsti ) - continue; - if ( utxo->lasttime != now ) - { - char str[65]; printf("{%s:%u %s} ",utxo->ipaddr,utxo->port,bits256_str(str,utxo->txid)); - flag++; - if ( (retstr= issue_LP_notifyutxo(destipaddr,destport,utxo)) != 0 ) - free(retstr); - } - } - if ( flag != 0 ) - printf(" <- missing utxos\n"); - } else if ( peer != 0 ) - peer->errors++; -} - -int32_t LP_maxvalue(uint64_t *values,int32_t n) -{ - int32_t i,maxi = -1; uint64_t maxval = 0; - for (i=0; i maxval ) - { - maxi = i; - maxval = values[i]; - } - return(maxi); -} - -int32_t LP_nearestvalue(uint64_t *values,int32_t n,uint64_t targetval) -{ - int32_t i,mini = -1; int64_t dist; uint64_t mindist = (1 << 31); - for (i=0; i= 0 && dist < mindist ) - { - mini = i; - mindist = dist; - } - } - return(mini); -} - -uint64_t LP_privkey_init(struct LP_peerinfo *mypeer,int32_t mypubsock,char *coin,uint8_t addrtype,char *passphrase,char *wifstr) -{ - char *retstr,coinaddr[64],*script; cJSON *array,*item; bits256 txid,deposittxid; int32_t used,i,n,vout,depositvout; uint64_t *values,satoshis,depositval,targetval,value,total = 0; bits256 privkey,pubkey; uint8_t pubkey33[33]; - if ( passphrase != 0 ) - conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); - else privkey = iguana_wif2privkey(wifstr); - iguana_priv2pub(pubkey33,coinaddr,privkey,addrtype); - retstr = iguana_listunspent(coin,coinaddr); - if ( retstr != 0 && retstr[0] == '[' && retstr[1] == ']' ) - free(retstr), retstr = 0; - if ( retstr == 0 ) - { - if ( (retstr= DEX_listunspent(coin,coinaddr)) == 0 ) - { - printf("null listunspent\n"); - return(0); - } - } - printf("LP_privkey_init.(%s)\n",retstr); - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) - { - values = calloc(n,sizeof(*values)); - for (i=0; i= 0 && (recvsize= nn_recv(pullsock,&ptr,NN_MSG,0)) >= 0 ) { - if ( (i= LP_maxvalue(values,n)) >= 0 ) + nonz++; + if ( (argjson= cJSON_Parse((char *)ptr)) != 0 ) { - item = jitem(array,i); - deposittxid = jbits256(item,"txid"); - depositvout = juint(item,"vout"); - script = jstr(item,"scriptPubKey"); - depositval = values[i]; - values[i] = 0, used++; - targetval = (depositval / 9) * 8; - printf("i.%d %.8f target %.8f\n",i,dstr(depositval),dstr(targetval)); - if ( (i= LP_nearestvalue(values,n,targetval)) >= 0 ) + len = (int32_t)strlen((char *)ptr) + 1; + portable_mutex_lock(&LP_commandmutex); + if ( LP_command(mypeer,pubsock,argjson,&((uint8_t *)ptr)[len],recvsize - len,profitmargin) == 0 ) { - item = jitem(array,i); - txid = jbits256(item,"txid"); - vout = juint(item,"vout"); - if ( jstr(item,"scriptPubKey") != 0 && strcmp(script,jstr(item,"scriptPubKey")) == 0 ) + if ( (retstr= stats_JSON(argjson,"127.0.0.1",0)) != 0 ) { - value = values[i]; - values[i] = 0, used++; - LP_addutxo(mypeer,mypubsock,coin,txid,vout,value,deposittxid,depositvout,depositval,script,coinaddr,LP_peerinfos[0].ipaddr,LP_peerinfos[0].port,LP_peerinfos[0].profitmargin); - total += value; + //printf("%s RECV.[%d] %s\n",peer->ipaddr,recvsize,(char *)ptr); + free(retstr); } } - } else break; + portable_mutex_unlock(&LP_commandmutex); + free_json(argjson); + } + if ( ptr != 0 ) + nn_freemsg(ptr), ptr = 0; } - free(values); + if ( nonz == 0 ) + usleep(50000); } - free_json(array); - } - free(retstr); - return(total); -} - - -int32_t basilisk_istrustedbob(struct basilisk_swap *swap) -{ - // for BTC and if trusted LP - return(0); -} - -struct iguana_info KMDcoin,BTCcoin,LTCcoin; - -struct iguana_info *LP_coinfind(char *symbol) -{ - struct iguana_info *coin; - if ( strcmp(symbol,"BTC") == 0 ) - return(&BTCcoin); - else if ( strcmp(symbol,"LTC") == 0 ) - return(<Ccoin); - else //if ( strcmp(symbol,"KMD") == 0 ) - { - coin = calloc(1,sizeof(*coin)); - *coin = KMDcoin; - strcpy(coin->symbol,symbol); - return(coin); } } -void tradebot_swap_balancingtrade(struct basilisk_swap *swap,int32_t iambob) -{ - -} - -void tradebot_pendingadd(cJSON *tradejson,char *base,double basevolume,char *rel,double relvolume) +void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profitmargin,char *passphrase,int32_t amclient,char *userhome) { - // add to trades -} - -char GLOBAL_DBDIR[] = "."; - -#include "LP_secp.c" -#include "LP_rpc.c" -#include "LP_bitcoin.c" -#include "LP_transaction.c" -#include "LP_remember.c" -#include "LP_statemachine.c" -#include "LP_swap.c" -#include "LP_commands.c" - -void LPinit(uint16_t myport,uint16_t mypull,uint16_t mypub,double profitmargin) -{ - char *myipaddr=0,*retstr; long filesize,n; int32_t len,timeout,maxsize,recvsize,nonz,i,lastn,pullsock=-1,pubsock=-1; struct LP_peerinfo *peer,*tmp,*mypeer=0; char pushaddr[128],subaddr[128]; void *ptr; cJSON *argjson; + char *myipaddr=0; long filesize,n; int32_t timeout,maxsize,pullsock=-1,pubsock=-1; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128]; + IAMCLIENT = amclient; + LP_profitratio += profitmargin; + OS_randombytes((void *)&n,sizeof(n)); + srand((int32_t)n); + if ( userhome != 0 && userhome[0] != 0 ) + safecopy(USERHOME,userhome,sizeof(USERHOME)); portable_mutex_init(&LP_peermutex); portable_mutex_init(&LP_utxomutex); portable_mutex_init(&LP_commandmutex); - if ( profitmargin == 0. ) + portable_mutex_init(&LP_cachemutex); + if ( amclient == 0 ) { - profitmargin = 0.01; - printf("default profit margin %f\n",profitmargin); - } - if ( system("curl -s4 checkip.amazonaws.com > /tmp/myipaddr") == 0 ) - { - if ( (myipaddr= OS_filestr(&filesize,"/tmp/myipaddr")) != 0 && myipaddr[0] != 0 ) + if ( profitmargin == 0. || profitmargin == 0.01 ) { - n = strlen(myipaddr); - if ( myipaddr[n-1] == '\n' ) - myipaddr[--n] = 0; - pullsock = pubsock = -1; - nanomsg_tcpname(pushaddr,myipaddr,mypull); - nanomsg_tcpname(subaddr,myipaddr,mypub); - printf(">>>>>>>>> myipaddr.%s (%s %s)\n",myipaddr,pushaddr,subaddr); - if ( (pullsock= nn_socket(AF_SP,NN_PULL)) >= 0 && (pubsock= nn_socket(AF_SP,NN_PUB)) >= 0 ) - { - if ( nn_bind(pullsock,pushaddr) >= 0 && nn_bind(pubsock,subaddr) >= 0 ) - { - timeout = 10; - nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); - timeout = 1; - nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); - timeout = 1; - maxsize = 1024 * 1024; - nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVBUF,&maxsize,sizeof(maxsize)); - } - else - { - printf("error binding to (%s).%d (%s).%d\n",pushaddr,pullsock,subaddr,pubsock); - if ( pullsock >= 0 ) - nn_close(pullsock), pullsock = -1; - if ( pubsock >= 0 ) - nn_close(pubsock), pubsock = -1; - } - } else printf("error getting sockets %d %d\n",pullsock,pubsock); - LP_mypubsock = pubsock; - LP_mypeer = mypeer = LP_addpeer(mypeer,pubsock,myipaddr,myport,0,0,profitmargin,0,0); - //printf("my ipaddr.(%s) peers.(%s)\n",ipaddr,retstr!=0?retstr:""); - for (i=0; i 25 ) - continue; - LP_peersquery(mypeer,pubsock,default_LPnodes[i],myport,myipaddr,myport,profitmargin); - } - } else printf("error getting myipaddr\n"); - } else printf("error issuing curl\n"); - if ( myipaddr == 0 || mypeer == 0 ) - { - printf("couldnt get myipaddr or null mypeer.%p\n",mypeer); - exit(-1); - } - if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)stats_rpcloop,(void *)&myport) != 0 ) - { - printf("error launching stats rpcloop for port.%u\n",myport); - exit(-1); - } - LP_privkey_init(mypeer,pubsock,"KMD",60,"test",""); - printf("utxos.(%s)\n",LP_utxos(mypeer,"",10000)); - while ( 1 ) - { - nonz = 0; - HASH_ITER(hh,LP_peerinfos,peer,tmp) + profitmargin = 0.01 + (double)(rand() % 100)/100000; + printf("default profit margin %f\n",profitmargin); + } + if ( system("curl -s4 checkip.amazonaws.com > /tmp/myipaddr") == 0 ) { - if ( peer->numpeers != mypeer->numpeers || (rand() % 10) == 0 ) - { - if ( peer->numpeers != mypeer->numpeers ) - printf("%s num.%d vs %d\n",peer->ipaddr,peer->numpeers,mypeer->numpeers); - if ( strcmp(peer->ipaddr,myipaddr) != 0 ) - LP_peersquery(mypeer,pubsock,peer->ipaddr,peer->port,myipaddr,myport,profitmargin); - } - if ( peer->numutxos != mypeer->numutxos ) + if ( (myipaddr= OS_filestr(&filesize,"/tmp/myipaddr")) != 0 && myipaddr[0] != 0 ) { - lastn = peer->numutxos - mypeer->numutxos + LP_PROPAGATION_SLACK; - if ( lastn < 0 ) - lastn = LP_PROPAGATION_SLACK * 2; - printf("%s numutxos.%d vs %d lastn.%d\n",peer->ipaddr,peer->numutxos,mypeer->numutxos,lastn); - if ( strcmp(peer->ipaddr,myipaddr) != 0 ) - LP_utxosquery(mypeer,pubsock,peer->ipaddr,peer->port,"",lastn,myipaddr,myport,profitmargin); - } - while ( peer->subsock >= 0 && (recvsize= nn_recv(peer->subsock,&ptr,NN_MSG,0)) >= 0 ) - { - nonz++; - if ( (argjson= cJSON_Parse((char *)ptr)) != 0 ) + n = strlen(myipaddr); + if ( myipaddr[n-1] == '\n' ) + myipaddr[--n] = 0; + pullsock = pubsock = -1; + nanomsg_tcpname(pushaddr,myipaddr,mypullport); + nanomsg_tcpname(subaddr,myipaddr,mypubport); + printf(">>>>>>>>> myipaddr.%s (%s %s)\n",myipaddr,pushaddr,subaddr); + if ( (pullsock= nn_socket(AF_SP,NN_PULL)) >= 0 && (pubsock= nn_socket(AF_SP,NN_PUB)) >= 0 ) { - portable_mutex_lock(&LP_commandmutex); - if ( (retstr= stats_JSON(argjson,"127.0.0.1",mypub)) != 0 ) + if ( nn_bind(pullsock,pushaddr) >= 0 && nn_bind(pubsock,subaddr) >= 0 ) { - printf("%s RECV.[%d] %s\n",peer->ipaddr,recvsize,(char *)ptr); - free(retstr); + timeout = 10; + nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); + timeout = 1; + nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); + timeout = 1; + maxsize = 1024 * 1024; + nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVBUF,&maxsize,sizeof(maxsize)); } - portable_mutex_unlock(&LP_commandmutex); - free_json(argjson); - } else printf("error parsing.(%s)\n",(char *)ptr); - if ( ptr != 0 ) - nn_freemsg(ptr), ptr = 0; - } - } - while ( pullsock >= 0 && (recvsize= nn_recv(pullsock,&ptr,NN_MSG,0)) >= 0 ) + else + { + printf("error binding to (%s).%d (%s).%d\n",pushaddr,pullsock,subaddr,pubsock); + if ( pullsock >= 0 ) + nn_close(pullsock), pullsock = -1; + if ( pubsock >= 0 ) + nn_close(pubsock), pubsock = -1; + } + } else printf("error getting sockets %d %d\n",pullsock,pubsock); + LP_mypubsock = pubsock; + LP_mypeer = mypeer = LP_addpeer(amclient,mypeer,pubsock,myipaddr,myport,0,0,profitmargin,0,0); + //printf("my ipaddr.(%s) peers.(%s)\n",ipaddr,retstr!=0?retstr:""); + } else printf("error getting myipaddr\n"); + } else printf("error issuing curl\n"); + if ( myipaddr == 0 || mypeer == 0 ) { - nonz++; - if ( (argjson= cJSON_Parse((char *)ptr)) != 0 ) - { - len = (int32_t)strlen((char *)ptr) + 1; - portable_mutex_lock(&LP_commandmutex); - LP_command(mypeer,mypub,argjson,&ptr[len],recvsize - len,profitmargin); - portable_mutex_unlock(&LP_commandmutex); - free_json(argjson); - } - if ( ptr != 0 ) - nn_freemsg(ptr), ptr = 0; + printf("couldnt get myipaddr or null mypeer.%p\n",mypeer); + exit(-1); } - if ( nonz == 0 ) - sleep(mypeer->numpeers + 1); + printf("utxos.(%s)\n",LP_utxos(mypeer,"",10000)); } + LP_mainloop(mypeer,mypubport,pubsock,pullsock,myport,amclient,passphrase,profitmargin); } -#ifdef __APPLE__ -int32_t nn_bind() { return(-1); } -int32_t nn_close() { return(-1); } -int32_t nn_connect() { return(-1); } -int32_t nn_freemsg() { return(-1); } -int32_t nn_poll() { return(-1); } -int32_t nn_recv() { return(-1); } -int32_t nn_send() { return(-1); } -int32_t nn_setsockopt() { return(-1); } -int32_t nn_socket() { return(-1); } -#endif diff --git a/iguana/exchanges/LP_network.c b/iguana/exchanges/LP_network.c index c32ded7f4..ff2e35c11 100644 --- a/iguana/exchanges/LP_network.c +++ b/iguana/exchanges/LP_network.c @@ -18,94 +18,6 @@ // marketmaker // -void basilisk_psockinit(struct basilisk_swap *swap,int32_t amlp) -{ -/* char keystr[64],databuf[1024],pubkeystr[128],*retstr,*retstr2,*datastr,*pushaddr=0,*subaddr=0; cJSON *retjson,*addrjson; uint8_t data[512]; int32_t datalen,timeout,pushsock = -1,subsock = -1; - if ( swap->connected == 1 ) - return; - if ( swap->pushsock < 0 && swap->subsock < 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 && (subsock= nn_socket(AF_SP,NN_SUB)) >= 0 ) - { - timeout = 1000; - nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); - timeout = 1; - nn_setsockopt(subsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); - nn_setsockopt(subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); - swap->pushsock = pushsock; - swap->subsock = subsock; - } - if ( (subsock= swap->subsock) < 0 || (pushsock= swap->pushsock) < 0 ) - { - printf("error getting nn_sockets\n"); - return; - } - sprintf(keystr,"%08x-%08x",swap->I.req.requestid,swap->I.req.quoteid); - if ( swap->connected == 0 && (retstr= _dex_kvsearch("KV",keystr)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( (datastr= jstr(retjson,"value")) != 0 ) - { - datalen = (int32_t)strlen(datastr) >> 1; - decode_hex((uint8_t *)databuf,datalen,datastr); - if ( (addrjson= cJSON_Parse(databuf)) != 0 ) - { - pushaddr = jstr(addrjson,"push"); - subaddr = jstr(addrjson,"sub"); - if ( pushaddr != 0 && subaddr != 0 ) - { - printf("KV decoded (%s and %s) %d %d\n",pushaddr,subaddr,swap->pushsock,swap->subsock); - if ( nn_connect(swap->pushsock,pushaddr) >= 0 && nn_connect(swap->subsock,subaddr) >= 0 ) - swap->connected = 1; - } - free_json(addrjson); - } - } - free_json(retjson); - } - printf("KVsearch.(%s) -> (%s) connected.%d socks.(%d %d) amlp.%d\n",keystr,retstr,swap->connected,swap->pushsock,swap->subsock,amlp); - free(retstr); - } - printf("connected.%d amlp.%d subsock.%d pushsock.%d\n",swap->connected,amlp,subsock,pushsock); - if ( swap->connected <= 0 && amlp != 0 && subsock >= 0 && pushsock >= 0 ) - { - if ( (retstr= _dex_psock("{}")) != 0 ) - { - printf("psock returns.(%s)\n",retstr); - // {"result":"success","pushaddr":"tcp://5.9.102.210:30002","subaddr":"tcp://5.9.102.210:30003","randipbits":3606291758,"coin":"KMD","tag":"6952562460568228137"} - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - pushaddr = jstr(retjson,"pushaddr"); - subaddr = jstr(retjson,"subaddr"); - if ( pushaddr != 0 && subaddr != 0 ) - { - if ( nn_connect(pushsock,pushaddr) >= 0 ) - { - printf("connected to %d pushaddr.(%s)\n",pushsock,pushaddr); - if ( nn_connect(subsock,subaddr) >= 0 ) - { - swap->connected = 1; - init_hexbytes_noT(pubkeystr,myinfo->persistent_pubkey33,33); - sprintf((char *)data,"{\"push\":\"%s\",\"sub\":\"%s\",\"trade\":[\"%s\", %.8f, \"%s\", %.8f],\"pub\":\"%s\"}",pushaddr,subaddr,swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount),pubkeystr); - datalen = (int32_t)strlen((char *)data) + 1; - printf("datalen.%d (%s)\n",datalen,(char *)data); - init_hexbytes_noT(databuf,data,datalen); - printf("%s -> %s\n",keystr,databuf); - if ( (retstr2= _dex_kvupdate("KV",keystr,databuf,1)) != 0 ) - { - printf("KVupdate.(%s)\n",retstr2); - free(retstr2); - } - } else printf("nn_connect error to %d subaddr.(%s)\n",subsock,subaddr); - } else printf("nn_connect error to %d pushaddr.(%s)\n",pushsock,pushaddr); - } - else printf("missing addr (%p) (%p) (%s)\n",pushaddr,subaddr,jprint(retjson,0)); - free_json(retjson); - } else printf("Error parsing psock.(%s)\n",retstr); - free(retstr); - } else printf("error issuing _dex_psock\n"); - }*/ -} - char *nanomsg_tcpname(char *str,char *ipaddr,uint16_t port) { sprintf(str,"tcp://%s:%u",ipaddr,port); @@ -115,6 +27,13 @@ char *nanomsg_tcpname(char *str,char *ipaddr,uint16_t port) int32_t LP_send(int32_t sock,char *msg,int32_t freeflag) { int32_t sentbytes,len,i; struct nn_pollfd pfd; + if ( sock < 0 ) + { + printf("LP_send.(%s) to illegal socket\n",msg); + if ( freeflag != 0 ) + free(msg); + return(-1); + } for (i=0; i<100; i++) { pfd.fd = sock; @@ -132,10 +51,12 @@ int32_t LP_send(int32_t sock,char *msg,int32_t freeflag) usleep(1000); } printf("error LP_send\n"); + if ( freeflag != 0 ) + free(msg); return(-1); } -uint32_t LP_swapsend(struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t datalen,uint32_t nextbits,uint32_t crcs[2]) +uint32_t LP_swapsend(int32_t pairsock,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t datalen,uint32_t nextbits,uint32_t crcs[2]) { uint8_t *buf; int32_t sentbytes,offset=0,i; buf = malloc(datalen + sizeof(msgbits) + sizeof(swap->I.req.quoteid) + sizeof(bits256)*2); @@ -147,161 +68,15 @@ uint32_t LP_swapsend(struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,i offset += iguana_rwnum(1,&buf[offset],sizeof(msgbits),&msgbits); if ( datalen > 0 ) memcpy(&buf[offset],data,datalen), offset += datalen; - if ( (sentbytes= nn_send(swap->pushsock,buf,offset,0)) != offset ) + if ( (sentbytes= nn_send(pairsock,buf,offset,0)) != offset ) { printf("sentbytes.%d vs offset.%d\n",sentbytes,offset); if ( sentbytes < 0 ) { - if ( swap->pushsock >= 0 ) - nn_close(swap->pushsock), swap->pushsock = -1; //, - if ( swap->subsock >= 0 ) // - nn_close(swap->subsock), swap->subsock = -1; - swap->connected = swap->I.iambob != 0 ? -1 : 0; - swap->aborted = (uint32_t)time(NULL); } } + printf("sent %d bytes\n",sentbytes); //else printf("send.[%d] %x offset.%d datalen.%d [%llx]\n",sentbytes,msgbits,offset,datalen,*(long long *)data); free(buf); return(nextbits); } - -void basilisk_swap_sendabort(struct basilisk_swap *swap) -{ - uint32_t msgbits = 0; uint8_t buf[sizeof(msgbits) + sizeof(swap->I.req.quoteid) + sizeof(bits256)*2]; int32_t sentbytes,offset=0; - memset(buf,0,sizeof(buf)); - offset += iguana_rwnum(1,&buf[offset],sizeof(swap->I.req.quoteid),&swap->I.req.quoteid); - offset += iguana_rwnum(1,&buf[offset],sizeof(msgbits),&msgbits); - if ( (sentbytes= nn_send(swap->pushsock,buf,offset,0)) != offset ) - { - if ( sentbytes < 0 ) - { - if ( swap->pushsock >= 0 ) // - nn_close(swap->pushsock), swap->pushsock = -1; - if ( swap->subsock >= 0 ) // - nn_close(swap->subsock), swap->subsock = -1; - swap->connected = 0; - } - } else printf("basilisk_swap_sendabort\n"); -} - -void basilisk_psockinit(struct basilisk_swap *swap,int32_t amlp); - -void basilisk_swapgotdata(struct basilisk_swap *swap,uint32_t crc32,bits256 srchash,bits256 desthash,uint32_t quoteid,uint32_t msgbits,uint8_t *data,int32_t datalen,int32_t reinit) -{ - int32_t i; struct basilisk_swapmessage *mp; - for (i=0; inummessages; i++) - if ( crc32 == swap->messages[i].crc32 && msgbits == swap->messages[i].msgbits && bits256_cmp(srchash,swap->messages[i].srchash) == 0 && bits256_cmp(desthash,swap->messages[i].desthash) == 0 ) - return; - //printf(" new message.[%d] datalen.%d Q.%x msg.%x [%llx]\n",swap->nummessages,datalen,quoteid,msgbits,*(long long *)data); - swap->messages = realloc(swap->messages,sizeof(*swap->messages) * (swap->nummessages + 1)); - mp = &swap->messages[swap->nummessages++]; - mp->crc32 = crc32; - mp->srchash = srchash; - mp->desthash = desthash; - mp->msgbits = msgbits; - mp->quoteid = quoteid; - mp->data = malloc(datalen); - mp->datalen = datalen; - memcpy(mp->data,data,datalen); - if ( reinit == 0 && swap->fp != 0 ) - { - fwrite(mp,1,sizeof(*mp),swap->fp); - fwrite(data,1,datalen,swap->fp); - fflush(swap->fp); - } -} - -int32_t basilisk_swapget(struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,int32_t (*basilisk_verify_func)(void *ptr,uint8_t *data,int32_t datalen)) -{ - uint8_t *ptr; bits256 srchash,desthash; uint32_t crc32,_msgbits,quoteid; int32_t i,size,offset,retval = -1; struct basilisk_swapmessage *mp = 0; - while ( (size= nn_recv(swap->subsock,&ptr,NN_MSG,0)) >= 0 ) - { - swap->lasttime = (uint32_t)time(NULL); - memset(srchash.bytes,0,sizeof(srchash)); - memset(desthash.bytes,0,sizeof(desthash)); - //printf("gotmsg.[%d] crc.%x\n",size,crc32); - offset = 0; - for (i=0; i<32; i++) - srchash.bytes[i] = ptr[offset++]; - for (i=0; i<32; i++) - desthash.bytes[i] = ptr[offset++]; - offset += iguana_rwnum(0,&ptr[offset],sizeof(uint32_t),"eid); - offset += iguana_rwnum(0,&ptr[offset],sizeof(uint32_t),&_msgbits); - if ( size > offset ) - { - crc32 = calc_crc32(0,&ptr[offset],size-offset); - if ( size > offset ) - { - //printf("size.%d offset.%d datalen.%d\n",size,offset,size-offset); - basilisk_swapgotdata(swap,crc32,srchash,desthash,quoteid,_msgbits,&ptr[offset],size-offset,0); - } - } - else if ( bits256_nonz(srchash) == 0 && bits256_nonz(desthash) == 0 ) - { - if ( swap->aborted == 0 ) - { - swap->aborted = (uint32_t)time(NULL); - printf("got abort signal from other side\n"); - } - } else printf("basilisk_swapget: got strange packet\n"); - if ( ptr != 0 ) - nn_freemsg(ptr), ptr = 0; - } - //char str[65],str2[65]; - for (i=0; inummessages; i++) - { - //printf("%d: %s vs %s\n",i,bits256_str(str,swap->messages[i].srchash),bits256_str(str2,swap->messages[i].desthash)); - if ( bits256_cmp(swap->messages[i].desthash,swap->I.myhash) == 0 ) - { - if ( swap->messages[i].msgbits == msgbits ) - { - if ( swap->I.iambob == 0 && swap->lasttime != 0 && time(NULL) > swap->lasttime+360 ) - { - printf("nothing received for a while from Bob, try new sockets\n"); - if ( swap->pushsock >= 0 ) // - nn_close(swap->pushsock), swap->pushsock = -1; - if ( swap->subsock >= 0 ) // - nn_close(swap->subsock), swap->subsock = -1; - swap->connected = 0; - basilisk_psockinit(swap,swap->I.iambob != 0); - } - mp = &swap->messages[i]; - if ( msgbits != 0x80000000 ) - break; - } - } - } - if ( mp != 0 ) - retval = (*basilisk_verify_func)(swap,mp->data,mp->datalen); - //printf("mine/other %s vs %s\n",bits256_str(str,swap->I.myhash),bits256_str(str2,swap->I.otherhash)); - return(retval); -} - -int32_t basilisk_messagekeyread(uint8_t *key,uint32_t *channelp,uint32_t *msgidp,bits256 *srchashp,bits256 *desthashp) -{ - int32_t keylen = 0; - keylen += iguana_rwnum(0,&key[keylen],sizeof(uint32_t),channelp); - keylen += iguana_rwnum(0,&key[keylen],sizeof(uint32_t),msgidp); - keylen += iguana_rwbignum(0,&key[keylen],sizeof(*srchashp),srchashp->bytes); - keylen += iguana_rwbignum(0,&key[keylen],sizeof(*desthashp),desthashp->bytes); - return(keylen); -} - -int32_t basilisk_messagekey(uint8_t *key,uint32_t channel,uint32_t msgid,bits256 srchash,bits256 desthash) -{ - int32_t keylen = 0; - keylen += iguana_rwnum(1,&key[keylen],sizeof(uint32_t),&channel); - keylen += iguana_rwnum(1,&key[keylen],sizeof(uint32_t),&msgid); - keylen += iguana_rwbignum(1,&key[keylen],sizeof(srchash),srchash.bytes); - keylen += iguana_rwbignum(1,&key[keylen],sizeof(desthash),desthash.bytes); - return(keylen); -} - -void LP_channelsend(bits256 srchash,bits256 desthash,uint32_t channel,uint32_t msgid,uint8_t *data,int32_t datalen) -{ - int32_t keylen; uint8_t key[BASILISK_KEYSIZE]; //char *retstr; - keylen = basilisk_messagekey(key,channel,msgid,srchash,desthash); - //if ( (retstr= _dex_reqsend(myinfo,"DEX",key,keylen,data,datalen)) != 0 ) - // free(retstr); -} - diff --git a/iguana/exchanges/LP_peers.c b/iguana/exchanges/LP_peers.c new file mode 100644 index 000000000..e7d83a93e --- /dev/null +++ b/iguana/exchanges/LP_peers.c @@ -0,0 +1,188 @@ + +/****************************************************************************** + * Copyright © 2014-2017 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ +// +// LP_peers.c +// marketmaker +// + +struct LP_peerinfo *LP_peerfind(uint32_t ipbits,uint16_t port) +{ + struct LP_peerinfo *peer=0; uint64_t ip_port; + ip_port = ((uint64_t)port << 32) | ipbits; + portable_mutex_lock(&LP_peermutex); + HASH_FIND(hh,LP_peerinfos,&ip_port,sizeof(ip_port),peer); + portable_mutex_unlock(&LP_peermutex); + return(peer); +} + +cJSON *LP_peerjson(struct LP_peerinfo *peer) +{ + cJSON *item = cJSON_CreateObject(); + jaddstr(item,"ipaddr",peer->ipaddr); + jaddnum(item,"port",peer->port); + jaddnum(item,"profit",peer->profitmargin); + return(item); +} + +char *LP_peers() +{ + struct LP_peerinfo *peer,*tmp; cJSON *peersjson = cJSON_CreateArray(); + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + jaddi(peersjson,LP_peerjson(peer)); + } + return(jprint(peersjson,1)); +} + +struct LP_peerinfo *LP_addpeer(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *ipaddr,uint16_t port,uint16_t pushport,uint16_t subport,double profitmargin,int32_t numpeers,int32_t numutxos) +{ + uint32_t ipbits; int32_t pushsock,subsock,timeout,enabled; char checkip[64],pushaddr[64],subaddr[64]; struct LP_peerinfo *peer = 0; + ipbits = (uint32_t)calc_ipbits(ipaddr); + expand_ipbits(checkip,ipbits); + if ( strcmp(checkip,ipaddr) == 0 ) + { + if ( (peer= LP_peerfind(ipbits,port)) != 0 ) + { + if ( peer->profitmargin == 0. ) + peer->profitmargin = profitmargin; + if ( numpeers > peer->numpeers ) + peer->numpeers = numpeers; + if ( numutxos > peer->numutxos ) + peer->numutxos = numutxos; + } + else + { + //printf("LPaddpeer %s\n",ipaddr); + peer = calloc(1,sizeof(*peer)); + peer->pushsock = peer->subsock = pushsock = subsock = -1; + strcpy(peer->ipaddr,ipaddr); + if ( amclient == 0 ) + enabled = 1; + else enabled = 1;//(rand() % (1 << Client_connections)) == 0; + if ( pushport != 0 && subport != 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 ) + { + timeout = 1000; + nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); + nanomsg_tcpname(pushaddr,peer->ipaddr,pushport); + if ( nn_connect(pushsock,pushaddr) >= 0 ) + { + printf("connected to push.(%s) %d\n",pushaddr,pushsock); + peer->connected = (uint32_t)time(NULL); + peer->pushsock = pushsock; + if ( enabled != 0 && (subsock= nn_socket(AF_SP,NN_SUB)) >= 0 ) + { + timeout = 1; + nn_setsockopt(subsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); + nn_setsockopt(subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); + nanomsg_tcpname(subaddr,peer->ipaddr,subport); + if ( nn_connect(subsock,subaddr) >= 0 ) + { + peer->subsock = subsock; + printf("connected to sub.(%s) %d\n",subaddr,peer->subsock); + Client_connections += amclient; + } else nn_close(subsock); + } + } + else + { + nn_close(pushsock); + printf("error connecting to push.(%s)\n",pushaddr); + } + } else printf("%s pushport.%u subport.%u pushsock.%d\n",ipaddr,pushport,subport,pushsock); + peer->profitmargin = profitmargin; + peer->ipbits = ipbits; + peer->port = port; + peer->ip_port = ((uint64_t)port << 32) | ipbits; + portable_mutex_lock(&LP_peermutex); + HASH_ADD(hh,LP_peerinfos,ip_port,sizeof(peer->ip_port),peer); + if ( mypeer != 0 ) + { + mypeer->numpeers++; + printf("_LPaddpeer %s -> numpeers.%d mypubsock.%d other.(%d %d)\n",ipaddr,mypeer->numpeers,mypubsock,numpeers,numutxos); + } else peer->numpeers = 1; // will become mypeer + portable_mutex_unlock(&LP_peermutex); + if ( mypubsock >= 0 ) + LP_send(mypubsock,jprint(LP_peerjson(peer),1),1); + } + } else printf("LP_addpeer: checkip.(%s) vs (%s)\n",checkip,ipaddr); + return(peer); +} + +int32_t LP_peersparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now) +{ + struct LP_peerinfo *peer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; + if ( (array= cJSON_Parse(retstr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; ilasttime = now; + if ( strcmp(argipaddr,destipaddr) == 0 && destport == argport && peer->numpeers != n ) + peer->numpeers = n; + } + } + } + } + free_json(array); + } + return(n); +} + +void LP_peersquery(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *myipaddr,uint16_t myport,double myprofit) +{ + char *retstr; struct LP_peerinfo *peer,*tmp; uint32_t now,flag = 0; + peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); + if ( peer != 0 && peer->errors > 0 ) + return; + if ( (retstr= issue_LP_getpeers(destipaddr,destport,myipaddr,myport,myprofit,mypeer!=0?mypeer->numpeers:0,mypeer!=0?mypeer->numutxos:0)) != 0 ) + { + //printf("got.(%s)\n",retstr); + now = (uint32_t)time(NULL); + LP_peersparse(amclient,mypeer,mypubsock,destipaddr,destport,retstr,now); + free(retstr); + if ( amclient == 0 ) + { + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + if ( peer->lasttime != now ) + { + printf("{%s:%u %.6f}.%d ",peer->ipaddr,peer->port,peer->profitmargin,peer->lasttime - now); + flag++; + if ( (retstr= issue_LP_notify(destipaddr,destport,peer->ipaddr,peer->port,peer->profitmargin,peer->numpeers,0)) != 0 ) + free(retstr); + } + } + if ( flag != 0 ) + printf(" <- missing peers\n"); + } + } else if ( peer != 0 ) + peer->errors++; +} diff --git a/iguana/exchanges/LP_prices.c b/iguana/exchanges/LP_prices.c index 691325cc4..11fe76813 100644 --- a/iguana/exchanges/LP_prices.c +++ b/iguana/exchanges/LP_prices.c @@ -18,24 +18,352 @@ // marketmaker // -double LP_kmdbtc; +#define LP_MAXPRICEINFOS 64 +struct LP_priceinfo +{ + char symbol[16]; + uint64_t coinbits; + int32_t ind,pad; + double diagval; + double relvals[LP_MAXPRICEINFOS]; + double myprices[LP_MAXPRICEINFOS]; +} LP_priceinfos[LP_MAXPRICEINFOS]; +int32_t LP_numpriceinfos; -// very, very simple for now +struct LP_cacheinfo +{ + UT_hash_handle hh; + struct LP_quoteinfo Q; + uint8_t key[sizeof(bits256)+sizeof(uint64_t)*2+sizeof(int32_t)]; + double price; + uint32_t timestamp; +} *LP_cacheinfos; -void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32]) +int32_t LP_cachekey(uint8_t *key,char *base,char *rel,bits256 txid,int32_t vout) { - if ( avebid > SMALLVAL && aveask > SMALLVAL && strcmp(base,"KMD") == 0 && strcmp(rel,"BTC") == 0 ) - LP_kmdbtc = (avebid + aveask) * 0.5; + uint64_t basebits,relbits; int32_t offset = 0; + basebits = stringbits(base); + relbits = stringbits(rel); + memcpy(&key[offset],&basebits,sizeof(basebits)), offset += sizeof(basebits); + memcpy(&key[offset],&relbits,sizeof(relbits)), offset += sizeof(relbits); + memcpy(&key[offset],&txid,sizeof(txid)), offset += sizeof(txid); + memcpy(&key[offset],&vout,sizeof(vout)), offset += sizeof(vout); + return(offset); } -double LP_price(char *base,char *rel) +struct LP_cacheinfo *LP_cachefind(char *base,char *rel,bits256 txid,int32_t vout) +{ + struct LP_cacheinfo *ptr=0; uint8_t key[sizeof(bits256)+sizeof(uint64_t)*2+sizeof(vout)]; + if ( LP_cachekey(key,base,rel,txid,vout) == sizeof(key) ) + { + portable_mutex_lock(&LP_cachemutex); + HASH_FIND(hh,LP_cacheinfos,key,sizeof(key),ptr); + portable_mutex_unlock(&LP_cachemutex); + } else printf("LP_cachefind keysize mismatch?\n"); + if ( 0 && ptr != 0 && ptr->timestamp != 0 && ptr->timestamp < time(NULL)-LP_CACHEDURATION ) + { + printf("expire price %.8f\n",ptr->price); + ptr->price = 0.; + ptr->timestamp = 0; + memset(&ptr->Q,0,sizeof(ptr->Q)); + } + return(ptr); +} + +double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,int32_t vout) { - if ( LP_kmdbtc != 0. ) + struct LP_cacheinfo *ptr; + if ( (ptr= LP_cachefind(base,rel,txid,vout)) != 0 ) { - if ( strcmp(base,"KMD") == 0 && strcmp(rel,"BTC") == 0 ) - return(LP_kmdbtc); - else if ( strcmp(rel,"KMD") == 0 && strcmp(base,"BTC") == 0 ) - return(1. / LP_kmdbtc); + if ( qp != 0 ) + (*qp) = ptr->Q; + if ( ptr->price == 0. && ptr->Q.satoshis != 0 ) + { + printf("null ptr->price? "); + ptr->price = (double)ptr->Q.destsatoshis / ptr->Q.satoshis; + } + //printf("found %s/%s %.8f\n",base,rel,ptr->price); + return(ptr->price); } + //char str[65]; printf("cachemiss %s/%s %s/v%d\n",base,rel,bits256_str(str,txid),vout); return(0.); } + +struct LP_priceinfo *LP_priceinfofind(char *symbol) +{ + int32_t i; struct LP_priceinfo *pp; uint64_t coinbits; + if ( LP_numpriceinfos > 0 ) + { + coinbits = stringbits(symbol); + pp = LP_priceinfos; + for (i=0; icoinbits == coinbits ) + return(pp); + } + return(0); +} + +struct LP_priceinfo *LP_priceinfoptr(int32_t *indp,char *base,char *rel) +{ + struct LP_priceinfo *basepp,*relpp; + if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) + { + *indp = relpp->ind; + return(basepp); + } + else + { + *indp = -1; + return(0); + } +} + +void LP_priceinfoupdate(char *base,char *rel,double price) +{ + struct LP_priceinfo *basepp,*relpp; + if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) + { + dxblend(&basepp->relvals[relpp->ind],price,0.9); + dxblend(&relpp->relvals[basepp->ind],1. / price,0.9); + } +} + +double LP_myprice(double *bidp,double *askp,char *base,char *rel) +{ + struct LP_priceinfo *basepp,*relpp; + if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) + { + *askp = basepp->myprices[relpp->ind]; + *bidp = relpp->myprices[basepp->ind]; + return((*askp + *bidp) * 0.5); + } else return(0.); +} + +int32_t LP_mypriceset(char *base,char *rel,double price) +{ + struct LP_priceinfo *basepp,*relpp; + if ( price != 0. && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) + { + basepp->myprices[relpp->ind] = price * LP_profitratio; // ask + relpp->myprices[basepp->ind] = (1. / price) * LP_profitratio; // bid + return(0); + } else return(-1); +} + +double LP_price(char *base,char *rel) +{ + struct LP_priceinfo *basepp; int32_t relind; double price = 0.; + if ( (basepp= LP_priceinfoptr(&relind,base,rel)) != 0 ) + { + if ( (price= basepp->myprices[relind]) == 0. ) + price = basepp->relvals[relind]; + } + return(price); +} + +cJSON *LP_priceinfomatrix(int32_t usemyprices) +{ + int32_t i,j,n,m; double total,sum,val; struct LP_priceinfo *pp; uint32_t now; struct LP_cacheinfo *ptr,*tmp; cJSON *vectorjson = cJSON_CreateObject(); + now = (uint32_t)time(NULL); + HASH_ITER(hh,LP_cacheinfos,ptr,tmp) + { + if ( ptr->timestamp < now-60 || ptr->price == 0. ) + continue; + LP_priceinfoupdate(ptr->Q.srccoin,ptr->Q.destcoin,ptr->price); + } + pp = LP_priceinfos; + total = m = 0; + for (i=0; idiagval = sum = n = 0; + for (j=0; jmyprices[j]) == 0. ) + val = pp->relvals[j]; + if ( val != 0. ) + { + sum += val; + n++; + } + } + if ( n > 0 ) + { + pp->diagval = sum / n; + total += pp->diagval, m++; + } + } + if ( m > 0 ) + { + pp = LP_priceinfos; + for (i=0; idiagval /= total; + jaddnum(vectorjson,pp->symbol,pp->diagval); + } + } + return(vectorjson); +} + +struct LP_priceinfo *LP_priceinfoadd(char *symbol) +{ + struct LP_priceinfo *pp; cJSON *retjson; + if ( LP_numpriceinfos >= sizeof(LP_priceinfos)/sizeof(*LP_priceinfos) ) + { + printf("cant add any more priceinfos\n"); + return(0); + } + pp = &LP_priceinfos[LP_numpriceinfos]; + memset(pp,0,sizeof(*pp)); + safecopy(pp->symbol,symbol,sizeof(pp->symbol)); + pp->coinbits = stringbits(symbol); + pp->ind = LP_numpriceinfos++; + /*pp->relvals = calloc(LP_numpriceinfos+1,sizeof(*pp->relvals)); + //pp->myprices = calloc(LP_numpriceinfos+1,sizeof(*pp->myprices)); + vecsize = sizeof(*LP_priceinfos[i].relvals) * (LP_numpriceinfos + 1); + for (i=0; ikey,base,rel,txid,vout) == sizeof(ptr->key) ) + { + portable_mutex_lock(&LP_cachemutex); + HASH_ADD(hh,LP_cacheinfos,key,sizeof(ptr->key),ptr); + portable_mutex_unlock(&LP_cachemutex); + } else printf("LP_cacheadd keysize mismatch?\n"); + } + ptr->Q = *qp; + ptr->timestamp = (uint32_t)time(NULL); + if ( price != ptr->price ) + { + ptr->price = price; + LP_priceinfoupdate(base,rel,price); + printf("updated %s/v%d %s/%s %llu price %.8f\n",bits256_str(str,txid),vout,base,rel,(long long)qp->satoshis,price); + } else ptr->price = price; + return(ptr); +} + +static int _cmp_orderbook(const void *a,const void *b) +{ +#define ptr_a ((struct LP_cacheinfo *)a)->price +#define ptr_b ((struct LP_cacheinfo *)b)->price + if ( ptr_b > ptr_a ) + return(1); + else if ( ptr_b < ptr_a ) + return(-1); + else + { +#undef ptr_a +#undef ptr_b +#define ptr_a ((struct LP_cacheinfo *)a)->Q.satoshis +#define ptr_b ((struct LP_cacheinfo *)b)->Q.satoshis + if ( ptr_b > ptr_a ) + return(1); + else if ( ptr_b < ptr_a ) + return(-1); + } + return(0); +#undef ptr_a +#undef ptr_b +} + +static int _cmp_orderbookrev(const void *a,const void *b) +{ + return(-_cmp_orderbook(a,b)); +} + +cJSON *LP_orderbookjson(struct LP_cacheinfo *ptr,int32_t polarity) +{ + double price; cJSON *item = cJSON_CreateObject(); + if ( ptr->Q.satoshis != 0 && ptr->Q.destsatoshis != 0 ) + { + price = (double)ptr->Q.destsatoshis / ptr->Q.satoshis; + jaddnum(item,"price",polarity > 0 ? price : 1. / price); + jaddnum(item,"volume",polarity > 0 ? dstr(ptr->Q.satoshis) : dstr(ptr->Q.destsatoshis)); + jaddbits256(item,"txid",ptr->Q.txid); + jaddnum(item,"vout",ptr->Q.vout); + } + return(item); +} + +char *LP_orderbook(char *base,char *rel) +{ + uint32_t now,i; struct LP_cacheinfo *ptr,*tmp,**bids = 0,**asks = 0; cJSON *retjson,*array; int32_t numbids=0,numasks=0; + now = (uint32_t)time(NULL); + HASH_ITER(hh,LP_cacheinfos,ptr,tmp) + { + if ( ptr->timestamp < now-60 || ptr->price == 0. ) + continue; + if ( strcmp(ptr->Q.srccoin,base) == 0 && strcmp(ptr->Q.destcoin,rel) == 0 ) + { + asks = realloc(asks,sizeof(*asks) * (numasks+1)); + asks[numasks++] = ptr; + } + else if ( strcmp(ptr->Q.srccoin,rel) == 0 && strcmp(ptr->Q.destcoin,base) == 0 ) + { + bids = realloc(bids,sizeof(*bids) * (numbids+1)); + bids[numbids++] = ptr; + } + } + retjson = cJSON_CreateObject(); + array = cJSON_CreateArray(); + if ( numbids > 1 ) + qsort(bids,numbids,sizeof(*bids),_cmp_orderbookrev); + for (i=0; i 1 ) + qsort(asks,numasks,sizeof(*asks),_cmp_orderbook); + for (i=0; iswapsfp= fopen(fname,"rb+")) != 0 ) - { - while ( fread(&requestid,1,sizeof(requestid),myinfo->swapsfp) == sizeof(requestid) && fread("eid,1,sizeof(quoteid),myinfo->swapsfp) == sizeof(quoteid) ) - { - sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname); - printf("%s\n",fname); - if ( (fp= fopen(fname,"rb+")) != 0 ) // check to see if completed - { - memset(&M,0,sizeof(M)); - swapcompleted = 1; - for (iter=0; iter<2; iter++) - { - if ( fread(privkey.bytes,1,sizeof(privkey),fp) == sizeof(privkey) && - fread(&R,1,sizeof(R),fp) == sizeof(R) && - fread(&statebits,1,sizeof(statebits),fp) == sizeof(statebits) && - fread(&optionduration,1,sizeof(optionduration),fp) == sizeof(optionduration) ) - { - while ( 0 && fread(&M,1,sizeof(M),fp) == sizeof(M) ) - { - M.data = 0; - //printf("entry iter.%d crc32.%x datalen.%d\n",iter,M.crc32,M.datalen); - if ( M.datalen < 100000 ) - { - M.data = malloc(M.datalen); - if ( fread(M.data,1,M.datalen,fp) == M.datalen ) - { - if ( calc_crc32(0,M.data,M.datalen) == M.crc32 ) - { - if ( iter == 1 ) - { - if ( swap == 0 ) - { - swap = basilisk_thread_start(privkey,&R,statebits,optionduration,1); - swap->I.choosei = swap->I.otherchoosei = -1; - } - if ( swap != 0 ) - basilisk_swapgotdata(swap,M.crc32,M.srchash,M.desthash,M.quoteid,M.msgbits,M.data,M.datalen,1); - } - } else printf("crc mismatch %x vs %x\n",calc_crc32(0,M.data,M.datalen),M.crc32); - } else printf("error reading M.datalen %d\n",M.datalen); - free(M.data), M.data = 0; - } - } - } - if ( swapcompleted != 0 ) - break; - rewind(fp); - } - } - } - } else myinfo->swapsfp = fopen(fname,"wb+"); -}*/ - -FILE *basilisk_swap_save(struct basilisk_swap *swap,bits256 privkey,struct basilisk_request *rp,uint32_t statebits,int32_t optionduration,int32_t reinit) -{ - FILE *fp=0; /*char fname[512]; - sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,rp->requestid,rp->quoteid), OS_compatible_path(fname); - if ( (fp= fopen(fname,"rb+")) == 0 ) - { - if ( (fp= fopen(fname,"wb+")) != 0 ) - { - fwrite(privkey.bytes,1,sizeof(privkey),fp); - fwrite(rp,1,sizeof(*rp),fp); - fwrite(&statebits,1,sizeof(statebits),fp); - fwrite(&optionduration,1,sizeof(optionduration),fp); - fflush(fp); - } - } - else if ( reinit != 0 ) - { - }*/ - return(fp); -} - -int32_t basilisk_swap_load(uint32_t requestid,uint32_t quoteid,bits256 *privkeyp,struct basilisk_request *rp,uint32_t *statebitsp,int32_t *optiondurationp) -{ - FILE *fp=0; char fname[512]; int32_t retval = -1; - sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname); - if ( (fp= fopen(fname,"rb+")) != 0 ) - { - if ( fread(privkeyp,1,sizeof(*privkeyp),fp) == sizeof(*privkeyp) && - fread(rp,1,sizeof(*rp),fp) == sizeof(*rp) && - fread(statebitsp,1,sizeof(*statebitsp),fp) == sizeof(*statebitsp) && - fread(optiondurationp,1,sizeof(*optiondurationp),fp) == sizeof(*optiondurationp) ) - retval = 0; - fclose(fp); - } - return(retval); -} - -void basilisk_swap_saveupdate(struct basilisk_swap *swap) -{ - FILE *fp; char fname[512]; - sprintf(fname,"%s/SWAPS/%u-%u.swap",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid), OS_compatible_path(fname); - if ( (fp= fopen(fname,"wb")) != 0 ) - { - fwrite(&swap->I,1,sizeof(swap->I),fp); - /*fwrite(&swap->bobdeposit,1,sizeof(swap->bobdeposit),fp); - fwrite(&swap->bobpayment,1,sizeof(swap->bobpayment),fp); - fwrite(&swap->alicepayment,1,sizeof(swap->alicepayment),fp); - fwrite(&swap->myfee,1,sizeof(swap->myfee),fp); - fwrite(&swap->otherfee,1,sizeof(swap->otherfee),fp); - fwrite(&swap->aliceclaim,1,sizeof(swap->aliceclaim),fp); - fwrite(&swap->alicespend,1,sizeof(swap->alicespend),fp); - fwrite(&swap->bobreclaim,1,sizeof(swap->bobreclaim),fp); - fwrite(&swap->bobspend,1,sizeof(swap->bobspend),fp); - fwrite(&swap->bobrefund,1,sizeof(swap->bobrefund),fp); - fwrite(&swap->alicereclaim,1,sizeof(swap->alicereclaim),fp);*/ - fwrite(swap->privkeys,1,sizeof(swap->privkeys),fp); - fwrite(swap->otherdeck,1,sizeof(swap->otherdeck),fp); - fwrite(swap->deck,1,sizeof(swap->deck),fp); - fclose(fp); - } -} - -/*int32_t basilisk_swap_loadtx(struct basilisk_rawtx *rawtx,FILE *fp,char *bobcoinstr,char *alicecoinstr) -{ - if ( fread(rawtx,1,sizeof(*rawtx),fp) == sizeof(*rawtx) ) - { - rawtx->coin = 0; - rawtx->vins = 0; - if ( strcmp(rawtx->I.coinstr,bobcoinstr) == 0 || strcmp(rawtx->I.coinstr,alicecoinstr) == 0 ) - { - rawtx->coin = LP_coinfind(rawtx->I.coinstr); - if ( rawtx->vinstr[0] != 0 ) - rawtx->vins = cJSON_Parse(rawtx->vinstr); - printf("loaded.%s len.%d\n",rawtx->name,rawtx->I.datalen); - return(0); - } - } - return(-1); -}*/ - void basilisk_dontforget_userdata(char *userdataname,FILE *fp,uint8_t *script,int32_t scriptlen) { int32_t i; char scriptstr[513]; @@ -169,7 +32,7 @@ void basilisk_dontforget_userdata(char *userdataname,FILE *fp,uint8_t *script,in void basilisk_dontforget(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx,int32_t locktime,bits256 triggertxid) { - char zeroes[32],fname[512],str[65],coinaddr[64],secretAmstr[41],secretAm256str[65],secretBnstr[41],secretBn256str[65],*tmp; FILE *fp; int32_t i,len; uint8_t redeemscript[256],script[256]; + char zeroes[32],fname[512],str[65],coinaddr[64],secretAmstr[41],secretAm256str[65],secretBnstr[41],secretBn256str[65]; FILE *fp; int32_t i,len; uint8_t redeemscript[256],script[256]; sprintf(fname,"%s/SWAPS/%u-%u.%s",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid,rawtx->name), OS_compatible_path(fname); coinaddr[0] = secretAmstr[0] = secretAm256str[0] = secretBnstr[0] = secretBn256str[0] = 0; memset(zeroes,0,sizeof(zeroes)); @@ -184,11 +47,10 @@ void basilisk_dontforget(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx fprintf(fp,"\",\"txid\":\"%s\"",bits256_str(str,bits256_doublesha256(0,rawtx->txbytes,rawtx->I.datalen))); if ( rawtx == &swap->bobdeposit || rawtx == &swap->bobpayment ) { - basilisk_swap_coinaddr(swap,&swap->bobcoin,coinaddr,rawtx->txbytes,rawtx->I.datalen); + LP_swap_coinaddr(swap,&swap->bobcoin,coinaddr,rawtx->txbytes,rawtx->I.datalen); if ( coinaddr[0] != 0 ) { - if ( (tmp= LP_importaddress(swap->bobcoin.symbol,coinaddr)) != 0 ) - free(tmp); + LP_importaddress(swap->bobcoin.symbol,coinaddr); if ( rawtx == &swap->bobdeposit ) safecopy(swap->Bdeposit,coinaddr,sizeof(swap->Bdeposit)); else safecopy(swap->Bpayment,coinaddr,sizeof(swap->Bpayment)); @@ -210,10 +72,15 @@ void basilisk_dontforget(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx if ( bits256_nonz(swap->I.pubAm) != 0 && bits256_nonz(swap->I.pubBn) != 0 ) { basilisk_alicescript(redeemscript,&len,script,0,coinaddr,swap->alicecoin.p2shtype,swap->I.pubAm,swap->I.pubBn); - if ( (tmp= LP_importaddress(swap->alicecoin.symbol,coinaddr)) != 0 ) - free(tmp); + LP_importaddress(swap->alicecoin.symbol,coinaddr); fprintf(fp,",\"Apayment\":\"%s\"",coinaddr); } + if ( rawtx->I.redeemlen > 0 ) + { + char scriptstr[2049]; + init_hexbytes_noT(scriptstr,rawtx->redeemscript,rawtx->I.redeemlen); + fprintf(fp,",\"redeem\":\"%s\"",scriptstr); + } /*basilisk_dontforget_userdata("Aclaim",fp,swap->I.userdata_aliceclaim,swap->I.userdata_aliceclaimlen); basilisk_dontforget_userdata("Areclaim",fp,swap->I.userdata_alicereclaim,swap->I.userdata_alicereclaimlen); basilisk_dontforget_userdata("Aspend",fp,swap->I.userdata_alicespend,swap->I.userdata_alicespendlen); @@ -346,8 +213,6 @@ void basilisk_dontforget_update(struct basilisk_swap *swap,struct basilisk_rawtx basilisk_dontforget(swap,&swap->bobreclaim,swap->bobpayment.I.locktime,triggertxid); } - - bits256 basilisk_swap_privbob_extract(char *symbol,bits256 spendtxid,int32_t vini,int32_t revflag) { bits256 privkey; int32_t i,scriptlen,siglen; uint8_t script[1024]; // from Bob refund of Bob deposit @@ -503,9 +368,10 @@ int32_t basilisk_swap_isfinished(int32_t iambob,bits256 *txids,int32_t *sentflag cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requestid,uint32_t quoteid) { static void *ctx; - FILE *fp; int32_t sentflags[sizeof(txnames)/sizeof(*txnames)],i,n,j,len,needflag,secretstart,redeemlen,addflag,origfinishedflag = 0,finishedflag = 0,iambob = -1; int64_t srcamount,destamount=0,value,values[sizeof(txnames)/sizeof(*txnames)]; uint8_t secretAm[20],secretAm256[32],secretBn[20],secretBn256[32],pubkey33[33],redeemscript[1024],userdata[1024]; uint32_t plocktime,dlocktime,expiration=0,r,q,state,otherstate; char *secretstr,*srcstr,*deststr,str[65],src[64],dest[64],fname[512],*fstr,*dest33,*symbol,*txname,*Adest,*Bdest,*AAdest,*ABdest,destaddr[64],Adestaddr[64],alicecoin[64],bobcoin[64],*txbytes[sizeof(txnames)/sizeof(*txnames)]; long fsize; cJSON *txobj,*item,*sentobj,*array; bits256 checktxid,txid,pubA0,pubB0,pubB1,privAm,privBn,paymentspent,Apaymentspent,depositspent,zero,privkey,rev,myprivs[2],txids[sizeof(txnames)/sizeof(*txnames)],signedtxid; struct iguana_info *bob=0,*alice=0; uint64_t txfee = 10000; + FILE *fp; int32_t sentflags[sizeof(txnames)/sizeof(*txnames)],i,n,j,len,needflag,secretstart,redeemlen,addflag,origfinishedflag = 0,finishedflag = 0,iambob = -1; int64_t srcamount,destamount=0,value,values[sizeof(txnames)/sizeof(*txnames)]; uint8_t secretAm[20],secretAm256[32],secretBn[20],secretBn256[32],pubkey33[33],redeemscript[1024],userdata[1024]; uint32_t plocktime,dlocktime,expiration=0,r,q,state,otherstate; char *secretstr,*srcstr,*deststr,str[65],src[64],dest[64],fname[512],*fstr,*dest33,*symbol,*txname,*Adest,*Bdest,*AAdest,*ABdest,destaddr[64],Adestaddr[64],alicepaymentaddr[64],bobpaymentaddr[64],bobdepositaddr[64],alicecoin[64],bobcoin[64],*txbytes[sizeof(txnames)/sizeof(*txnames)]; long fsize; cJSON *txobj,*item,*sentobj,*array; bits256 checktxid,txid,pubA0,pubB0,pubB1,privAm,privBn,paymentspent,Apaymentspent,depositspent,zero,privkey,rev,myprivs[2],txids[sizeof(txnames)/sizeof(*txnames)],signedtxid; struct iguana_info *bob=0,*alice=0; uint64_t txfee = 10000; if ( ctx == 0 ) ctx = bitcoin_ctx(); + bobpaymentaddr[0] = bobdepositaddr[0] = alicepaymentaddr[0] = 0; memset(values,0,sizeof(values)); memset(txids,0,sizeof(txids)); memset(secretAm,0,sizeof(secretAm)); @@ -561,13 +427,13 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti if ( bits256_nonz(privkey) != 0 ) { privAm = privkey; - //printf("set privAm <- %s\n",bits256_str(str,privAm)); + printf("set privAm <- %s\n",bits256_str(str,privAm)); } privkey = jbits256(item,"privBn"); if ( bits256_nonz(privkey) != 0 ) { privBn = privkey; - //printf("set privBn <- %s\n",bits256_str(str,privBn)); + printf("set privBn <- %s\n",bits256_str(str,privBn)); } expiration = juint(item,"expiration"); state = jint(item,"state"); @@ -642,6 +508,12 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti if ( bits256_nonz(txid) == 0 ) continue; txids[i] = txid; + if ( jstr(txobj,"Apayment") != 0 ) + strcpy(alicepaymentaddr,jstr(txobj,"Apayment")); + if ( jstr(txobj,"Bpayment") != 0 ) + strcpy(bobpaymentaddr,jstr(txobj,"Bpayment")); + if ( jstr(txobj,"Bdeposit") != 0 ) + strcpy(bobdepositaddr,jstr(txobj,"Bdeposit")); if ( jobj(txobj,"tx") != 0 ) { txbytes[i] = clonestr(jstr(txobj,"tx")); @@ -658,7 +530,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti safecopy(alicecoin,symbol,sizeof(alicecoin)); if ( finishedflag == 0 ) { - if ( (sentobj= LP_swapgettx(symbol,txid)) == 0 ) + if ( (sentobj= LP_gettx(symbol,txid)) == 0 ) { //printf("%s %s ready to broadcast\n",symbol,bits256_str(str2,txid)); } @@ -682,6 +554,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti } else if ( finishedflag == 0 ) printf("%s not finished\n",fname); } + printf("alicepayment.%s bobpayment.%s bobdeposit.%s\n",alicepaymentaddr,bobpaymentaddr,bobdepositaddr); //printf("iambob.%d src.%s dest.%s bob.%s alice.%s pubA0.(%s)\n",iambob,src,dest,bobcoin,alicecoin,bits256_str(str,pubA0)); Adestaddr[0] = destaddr[0] = 0; Adest = Bdest = AAdest = ABdest = 0; @@ -722,7 +595,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti printf("txbytes.%p Apayment.%s\n",txbytes[BASILISK_ALICEPAYMENT],bits256_str(str,txids[BASILISK_ALICEPAYMENT])); if ( txbytes[BASILISK_ALICEPAYMENT] != 0 ) sentflags[BASILISK_ALICEPAYMENT] = 1; - else if ( (sentobj= LP_swapgettx(alicecoin,txids[BASILISK_ALICEPAYMENT])) != 0 ) + else if ( (sentobj= LP_gettx(alicecoin,txids[BASILISK_ALICEPAYMENT])) != 0 ) { sentflags[BASILISK_ALICEPAYMENT] = 1; free_json(sentobj); @@ -745,18 +618,25 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti // alicespend for (j=0; j<32; j++) rev.bytes[j] = privAm.bytes[31 - j]; - revcalc_rmd160_sha256(secretAm,rev);//privAm); - vcalc_sha256(0,secretAm256,rev.bytes,sizeof(rev)); + //revcalc_rmd160_sha256(secretAm,rev);//privAm); + //vcalc_sha256(0,secretAm256,rev.bytes,sizeof(rev)); redeemlen = basilisk_swap_bobredeemscript(0,&secretstart,redeemscript,plocktime,pubA0,pubB0,pubB1,rev,privBn,secretAm,secretAm256,secretBn,secretBn256); len = basilisk_swapuserdata(userdata,rev,0,myprivs[0],redeemscript,redeemlen); - printf("alicespend len.%d redeemlen.%d\n",len,redeemlen); - if ( (txbytes[BASILISK_ALICESPEND]= basilisk_swap_bobtxspend(&signedtxid,txfee,"alicespend",bobcoin,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,pubkey33,1,expiration,&values[BASILISK_ALICESPEND])) != 0 ) + { + char privaddr[64]; uint8_t privpub33[33]; + bitcoin_pubkey33(ctx,privpub33,myprivs[0]); + bitcoin_address(privaddr,60,privpub33,33); + printf("alicespend len.%d redeemlen.%d priv0addr.(%s) priv0.(%s)\n",len,redeemlen,privaddr,bits256_str(str,myprivs[0])); + } + for (j=0; j<32; j++) + rev.bytes[j] = myprivs[0].bytes[31 - j]; + if ( (txbytes[BASILISK_ALICESPEND]= basilisk_swap_bobtxspend(&signedtxid,txfee,"alicespend",bobcoin,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,0,pubkey33,1,expiration,&values[BASILISK_ALICESPEND],0,0,bobpaymentaddr,1)) != 0 ) printf("alicespend.(%s)\n",txbytes[BASILISK_ALICESPEND]); } } if ( txbytes[BASILISK_ALICESPEND] != 0 ) { - txids[BASILISK_ALICESPEND] = basilisk_swap_sendrawtransaction("alicespend",bobcoin,txbytes[BASILISK_ALICESPEND]); + txids[BASILISK_ALICESPEND] = LP_broadcast("alicespend",bobcoin,txbytes[BASILISK_ALICESPEND]); if ( bits256_nonz(txids[BASILISK_ALICESPEND]) != 0 ) // tested { sentflags[BASILISK_ALICESPEND] = 1; @@ -775,13 +655,13 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti if ( redeemlen > 0 ) { len = basilisk_swapuserdata(userdata,zero,1,myprivs[0],redeemscript,redeemlen); - if ( (txbytes[BASILISK_ALICECLAIM]= basilisk_swap_bobtxspend(&signedtxid,txfee,"aliceclaim",bobcoin,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,pubkey33,0,expiration,&values[BASILISK_ALICECLAIM])) != 0 ) + if ( (txbytes[BASILISK_ALICECLAIM]= basilisk_swap_bobtxspend(&signedtxid,txfee,"aliceclaim",bobcoin,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,0,pubkey33,0,expiration,&values[BASILISK_ALICECLAIM],0,0,bobdepositaddr,1)) != 0 ) printf("privBn.(%s) aliceclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICECLAIM]); } } if ( txbytes[BASILISK_ALICECLAIM] != 0 ) { - txids[BASILISK_ALICECLAIM] = basilisk_swap_sendrawtransaction("aliceclaim",bobcoin,txbytes[BASILISK_ALICECLAIM]); + txids[BASILISK_ALICECLAIM] = LP_broadcast("aliceclaim",bobcoin,txbytes[BASILISK_ALICECLAIM]); if ( bits256_nonz(txids[BASILISK_ALICECLAIM]) != 0 ) // tested { sentflags[BASILISK_ALICECLAIM] = 1; @@ -797,13 +677,13 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti privBn = basilisk_swap_privBn_extract(&txids[BASILISK_BOBREFUND],bobcoin,txids[BASILISK_BOBDEPOSIT],privBn); if ( bits256_nonz(txids[BASILISK_ALICEPAYMENT]) != 0 && bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 ) { - if ( (txbytes[BASILISK_ALICERECLAIM]= basilisk_swap_Aspend("alicereclaim",alicecoin,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_ALICERECLAIM])) != 0 ) + if ( (txbytes[BASILISK_ALICERECLAIM]= basilisk_swap_Aspend("alicereclaim",alicecoin,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_ALICERECLAIM],alicepaymentaddr)) != 0 ) printf("privBn.(%s) alicereclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICERECLAIM]); } } if ( txbytes[BASILISK_ALICERECLAIM] != 0 ) { - txids[BASILISK_ALICERECLAIM] = basilisk_swap_sendrawtransaction("alicereclaim",alicecoin,txbytes[BASILISK_ALICERECLAIM]); + txids[BASILISK_ALICERECLAIM] = LP_broadcast("alicereclaim",alicecoin,txbytes[BASILISK_ALICERECLAIM]); if ( bits256_nonz(txids[BASILISK_ALICERECLAIM]) != 0 ) // tested { sentflags[BASILISK_ALICERECLAIM] = 1; @@ -827,13 +707,13 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti } if ( bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 ) { - if ( (txbytes[BASILISK_BOBSPEND]= basilisk_swap_Aspend("bobspend",alicecoin,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_BOBSPEND])) != 0 ) + if ( (txbytes[BASILISK_BOBSPEND]= basilisk_swap_Aspend("bobspend",alicecoin,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_BOBSPEND],alicepaymentaddr)) != 0 ) printf("bobspend.(%s)\n",txbytes[BASILISK_BOBSPEND]); } } if ( txbytes[BASILISK_BOBSPEND] != 0 ) { - txids[BASILISK_BOBSPEND] = basilisk_swap_sendrawtransaction("bobspend",alicecoin,txbytes[BASILISK_BOBSPEND]); + txids[BASILISK_BOBSPEND] = LP_broadcast("bobspend",alicecoin,txbytes[BASILISK_BOBSPEND]); if ( bits256_nonz(txids[BASILISK_BOBSPEND]) != 0 ) // tested { sentflags[BASILISK_BOBSPEND] = 1; @@ -851,7 +731,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti if ( redeemlen > 0 ) { len = basilisk_swapuserdata(userdata,zero,1,myprivs[1],redeemscript,redeemlen); - if ( (txbytes[BASILISK_BOBRECLAIM]= basilisk_swap_bobtxspend(&signedtxid,txfee,"bobrefund",bobcoin,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[1],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,pubkey33,0,expiration,&values[BASILISK_BOBRECLAIM])) != 0 ) + if ( (txbytes[BASILISK_BOBRECLAIM]= basilisk_swap_bobtxspend(&signedtxid,txfee,"bobrefund",bobcoin,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[1],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,0,pubkey33,0,expiration,&values[BASILISK_BOBRECLAIM],0,0,bobpaymentaddr,1)) != 0 ) { int32_t z; for (z=0; z<20; z++) @@ -862,7 +742,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti } if ( txbytes[BASILISK_BOBRECLAIM] != 0 ) { - txids[BASILISK_BOBRECLAIM] = basilisk_swap_sendrawtransaction("bobreclaim",bobcoin,txbytes[BASILISK_BOBRECLAIM]); + txids[BASILISK_BOBRECLAIM] = LP_broadcast("bobreclaim",bobcoin,txbytes[BASILISK_BOBRECLAIM]); if ( bits256_nonz(txids[BASILISK_BOBRECLAIM]) != 0 ) // tested { sentflags[BASILISK_BOBRECLAIM] = 1; @@ -881,12 +761,12 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti vcalc_sha256(0,secretBn256,privBn.bytes,sizeof(privBn)); redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,dlocktime,pubA0,pubB0,pubB1,privAm,privBn,secretAm,secretAm256,secretBn,secretBn256); len = basilisk_swapuserdata(userdata,privBn,0,myprivs[0],redeemscript,redeemlen); - if ( (txbytes[BASILISK_BOBREFUND]= basilisk_swap_bobtxspend(&signedtxid,txfee,"bobrefund",bobcoin,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,pubkey33,1,expiration,&values[BASILISK_BOBREFUND])) != 0 ) + if ( (txbytes[BASILISK_BOBREFUND]= basilisk_swap_bobtxspend(&signedtxid,txfee,"bobrefund",bobcoin,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,0,pubkey33,1,expiration,&values[BASILISK_BOBREFUND],0,0,bobdepositaddr,1)) != 0 ) printf("pubB1.(%s) bobrefund.(%s)\n",bits256_str(str,pubB1),txbytes[BASILISK_BOBREFUND]); } if ( txbytes[BASILISK_BOBREFUND] != 0 ) { - txids[BASILISK_BOBREFUND] = basilisk_swap_sendrawtransaction("bobrefund",bobcoin,txbytes[BASILISK_BOBREFUND]); + txids[BASILISK_BOBREFUND] = LP_broadcast("bobrefund",bobcoin,txbytes[BASILISK_BOBREFUND]); if ( bits256_nonz(txids[BASILISK_BOBREFUND]) != 0 ) // tested { sentflags[BASILISK_BOBREFUND] = 1; diff --git a/iguana/exchanges/LP_rpc.c b/iguana/exchanges/LP_rpc.c index be1108238..ed3784b55 100644 --- a/iguana/exchanges/LP_rpc.c +++ b/iguana/exchanges/LP_rpc.c @@ -17,489 +17,224 @@ // LP_rpc.c // marketmaker // - -cJSON *basilisk_nullretjson(cJSON *retjson) +char *issue_LP_getpeers(char *destip,uint16_t destport,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers,int32_t numutxos) { - char *outstr; - if ( retjson != 0 ) - { - outstr = jprint(retjson,0); - if ( strcmp(outstr,"{}") == 0 ) - { - free_json(retjson); - retjson = 0; - } - free(outstr); - } - return(retjson); + char url[512],*retstr; + sprintf(url,"http://%s:%u/api/stats/getpeers?ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,profitmargin,numpeers,numutxos); + //printf("send.(%s)\n",url); + retstr = issue_curl(url); + //printf("GETPEERS.(%s)\n",retstr); + return(retstr); } -void LP_unspentslock(char *symbol,cJSON *vins) +char *issue_LP_getutxos(char *destip,uint16_t destport,char *coin,int32_t lastn,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers,int32_t numutxos) { - + char url[512]; + sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,coin,lastn,ipaddr,port,profitmargin,numpeers,numutxos); + return(issue_curl(url)); } -void LP_unspents_mark(char *symbol,cJSON *vins) +char *issue_LP_clientgetutxos(char *destip,uint16_t destport,char *coin,int32_t lastn) { - + char url[512]; + sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=127.0.0.1&port=0",destip,destport,coin,lastn); + //printf("getutxos.(%s)\n",url); + return(issue_curl(url)); } -uint64_t LP_getestimatedfee(char *symbol) +char *issue_LP_notify(char *destip,uint16_t destport,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers,int32_t numutxos) { - return(200); + char url[512]; + sprintf(url,"http://%s:%u/api/stats/notify?ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,profitmargin,numpeers,numutxos); + return(issue_curl(url)); } -uint64_t LP_txfee(char *symbol) +char *issue_LP_notifyutxo(char *destip,uint16_t destport,struct LP_utxoinfo *utxo) { - return(10000); + char url[4096],str[65],str2[65]; + sprintf(url,"http://%s:%u/api/stats/notifyutxo?ipaddr=%s&port=%u&profit=%.6f&coin=%s&txid=%s&vout=%d&value=%.8f&txid2=%s&vout2=%d&value2=%.8f&script=%s&address=%s",destip,destport,utxo->ipaddr,utxo->port,utxo->profitmargin,utxo->coin,bits256_str(str,utxo->txid),utxo->vout,dstr(utxo->satoshis),bits256_str(str2,utxo->txid2),utxo->vout2,dstr(utxo->satoshis2),utxo->spendscript,utxo->coinaddr); + if ( strlen(url) > 1024 ) + printf("WARNING long url.(%s)\n",url); + return(issue_curl(url)); } -char *dpow_validateaddress(struct supernet_info *myinfo,struct iguana_info *coin,char *address) +cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params) { - char buf[128],*retstr=0; - if ( coin->FULLNODE < 0 ) + char *retstr; cJSON *retjson = 0; + if ( coin != 0 ) { - sprintf(buf,"\"%s\"",address); - retstr = bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"validateaddress",buf); - usleep(10000); - } - else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) - { - retstr = bitcoinrpc_validateaddress(myinfo,coin,0,0,address); - } - else - { - return(0); + //printf("issue.(%s, %s, %s, %s, %s)\n",coin->symbol,coin->serverport,coin->userpass,method,params); + retstr = bitcoind_passthru(coin->symbol,coin->serverport,coin->userpass,method,params); + if ( retstr != 0 && retstr[0] != 0 ) + { + //printf("%s: %s.%s -> (%s)\n",coin->symbol,method,params,retstr); + retjson = cJSON_Parse(retstr); + free(retstr); + } + //printf("dpow_gettxout.(%s)\n",retstr); } - return(retstr); + return(retjson); } -cJSON *dpow_gettxout(struct supernet_info *myinfo,struct iguana_info *coin,bits256 txid,int32_t vout) +void LP_unspents_mark(char *symbol,cJSON *vins) { - char buf[128],str[65],*retstr=0; cJSON *json = 0; - sprintf(buf,"\"%s\", %d",bits256_str(str,txid),vout); - if ( coin->FULLNODE < 0 ) - { - retstr = bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"gettxout",buf); - usleep(10000); - } - else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) - { - printf("need to test following call\n"); - retstr = bitcoinrpc_gettxout(myinfo,coin,0,buf,txid,1,0); // untested - } - else - { - return(0); - } - if ( retstr != 0 ) - { - json = cJSON_Parse(retstr); - free(retstr); - } - //printf("dpow_gettxout.(%s)\n",retstr); - return(json); + printf("LOCK (%s)\n",jprint(vins,0)); } -char *dpow_decoderawtransaction(struct supernet_info *myinfo,struct iguana_info *coin,char *rawtx) +cJSON *LP_getinfo(char *symbol) { - char *retstr,*paramstr; cJSON *array; - if ( coin->FULLNODE < 0 ) - { - array = cJSON_CreateArray(); - jaddistr(array,rawtx); - paramstr = jprint(array,1); - retstr = bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"decoderawtransaction",paramstr); - //printf("%s decoderawtransaction.(%s) <- (%s)\n",coin->symbol,retstr,paramstr); - free(paramstr); - usleep(10000); - } - else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) - { - retstr = bitcoinrpc_decoderawtransaction(myinfo,coin,0,0,rawtx,1); - } - else - { - return(0); - } - return(retstr); + struct iguana_info *coin = LP_coinfind(symbol); + return(bitcoin_json(coin,"getinfo","[]")); } -cJSON *dpow_gettransaction(struct supernet_info *myinfo,struct iguana_info *coin,bits256 txid) +cJSON *LP_gettxout(char *symbol,bits256 txid,int32_t vout) { - char buf[128],str[65],*retstr=0; cJSON *json = 0; - if ( coin->FULLNODE < 0 ) - { - sprintf(buf,"[\"%s\", 1]",bits256_str(str,txid)); - if ( (retstr= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"getrawtransaction",buf)) != 0 ) - { - } - usleep(10000); - } - else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) - { - retstr = bitcoinrpc_getrawtransaction(myinfo,coin,0,0,txid,1); - } - else - { - return(0); - } - if ( retstr != 0 ) - { - json = cJSON_Parse(retstr); - free(retstr); - } - return(json); + char buf[128],str[65]; struct iguana_info *coin = LP_coinfind(symbol); + sprintf(buf,"\"%s\", %d",bits256_str(str,txid),vout); + return(bitcoin_json(coin,"gettxout",buf)); } -cJSON *dpow_listunspent(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr) +cJSON *LP_gettx(char *symbol,bits256 txid) { - char buf[128],*retstr; cJSON *array,*json = 0; - if ( coin->FULLNODE < 0 ) - { - sprintf(buf,"0, 99999999, [\"%s\"]",coinaddr); - if ( (retstr= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"listunspent",buf)) != 0 ) - { - json = cJSON_Parse(retstr); - //printf("%s (%s) listunspent.(%s)\n",coin->symbol,buf,retstr); - free(retstr); - } else printf("%s null retstr from (%s)n",coin->symbol,buf); - } - else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) - { - array = cJSON_CreateArray(); - jaddistr(array,coinaddr); - json = iguana_listunspents(myinfo,coin,array,1,coin->longestchain,""); - free_json(array); - } - else - { - return(0); - } - return(json); + char buf[128],str[65]; struct iguana_info *coin = LP_coinfind(symbol); + sprintf(buf,"[\"%s\", 1]",bits256_str(str,txid)); + return(bitcoin_json(coin,"getrawtransaction",buf)); } -cJSON *dpow_listtransactions(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr,int32_t count,int32_t skip) +cJSON *LP_listunspent(char *symbol,char *coinaddr) { - char buf[128],*retstr; cJSON *json = 0; - if ( coin->FULLNODE < 0 ) - { - if ( count == 0 ) - count = 100; - sprintf(buf,"[\"%s\", %d, %d, true]",coinaddr,count,skip); - if ( (retstr= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"listtransactions",buf)) != 0 ) - { - //printf("LIST.(%s)\n",retstr); - json = cJSON_Parse(retstr); - free(retstr); - return(json); - } else printf("%s null retstr from (%s)n",coin->symbol,buf); - } - return(0); + char buf[128]; struct iguana_info *coin = LP_coinfind(symbol); + sprintf(buf,"0, 99999999, [\"%s\"]",coinaddr); + return(bitcoin_json(coin,"listunspent",buf)); } -char *dpow_signrawtransaction(struct supernet_info *myinfo,struct iguana_info *coin,char *rawtx,cJSON *vins) +cJSON *LP_listtransactions(char *symbol,char *coinaddr,int32_t count,int32_t skip) { - cJSON *array,*privkeys,*item; char *wifstr,*str,*paramstr,*retstr; uint8_t script[256]; int32_t i,n,len,hashtype; struct vin_info V; struct iguana_waddress *waddr; struct iguana_waccount *wacct; - if ( coin->FULLNODE < 0 ) - { - array = cJSON_CreateArray(); - jaddistr(array,rawtx); - jaddi(array,jduplicate(vins)); - paramstr = jprint(array,1); - //printf("signrawtransaction\n"); - retstr = bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"signrawtransaction",paramstr); - //printf("%s signrawtransaction.(%s) params.(%s)\n",coin->symbol,retstr,paramstr); - free(paramstr); - usleep(10000); - return(retstr); - } - else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) - { - privkeys = cJSON_CreateArray(); - if ( (n= cJSON_GetArraySize(vins)) > 0 ) - { - for (i=0; i 0 && strlen(str) < sizeof(script)*2 ) - { - len = (int32_t)strlen(str) >> 1; - decode_hex(script,len,str); - V.spendlen = len; - memcpy(V.spendscript,script,len); - if ( (hashtype= _iguana_calcrmd160(coin,&V)) >= 0 && V.coinaddr[0] != 0 ) - { - if ( (waddr= iguana_waddresssearch(myinfo,&wacct,V.coinaddr)) != 0 ) - { - if ( bits256_nonz(waddr->privkey) != 0 ) - { - if ( bitcoin_priv2wif(waddr->wifstr,waddr->privkey,coin->chain->wiftype) > 0 ) - { - wifstr = waddr->wifstr; - } - } - } - } - } - jaddistr(privkeys,wifstr); - } - } - retstr = bitcoinrpc_signrawtransaction(myinfo,coin,0,0,rawtx,vins,privkeys,"ALL"); - printf("call sign.(%s) vins.(%s) privs.(%s) -> (%s)\n",rawtx,jprint(vins,0),jprint(privkeys,0),retstr); - free_json(privkeys); - return(retstr); - } - else - { - return(0); - } + char buf[128]; struct iguana_info *coin = LP_coinfind(symbol); + if ( count == 0 ) + count = 100; + sprintf(buf,"[\"%s\", %d, %d, true]",coinaddr,count,skip); + return(bitcoin_json(coin,"listtransactions",buf)); } -char *dpow_sendrawtransaction(struct supernet_info *myinfo,struct iguana_info *coin,char *signedtx) +cJSON *LP_validateaddress(char *symbol,char *address) { - bits256 txid; cJSON *json,*array; char *paramstr,*retstr; - if ( coin->FULLNODE < 0 ) - { - array = cJSON_CreateArray(); - jaddistr(array,signedtx); - paramstr = jprint(array,1); - retstr = bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"sendrawtransaction",paramstr); - printf(">>>>>>>>>>> %s dpow_sendrawtransaction.(%s) -> (%s)\n",coin->symbol,paramstr,retstr); - free(paramstr); - return(retstr); - } - else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) - { - txid = iguana_sendrawtransaction(myinfo,coin,signedtx); - json = cJSON_CreateObject(); - jaddbits256(json,"result",txid); - return(jprint(json,1)); - } - else - { - return(0); - } + char buf[512]; struct iguana_info *coin = LP_coinfind(symbol); + sprintf(buf,"\"%s\"",address); + return(bitcoin_json(coin,"validateaddress",buf)); +} + +cJSON *LP_importprivkey(char *symbol,char *wifstr,char *label,int32_t flag) +{ + char buf[512]; struct iguana_info *coin = LP_coinfind(symbol); + sprintf(buf,"[\"%s\", \"%s\", %s]",wifstr,label,flag < 0 ? "false" : "true"); + return(bitcoin_json(coin,"importprivkey",buf)); } -char *LP_importaddress(char *symbol,char *address) +int32_t LP_importaddress(char *symbol,char *address) { - char buf[1024],*retstr; cJSON *validatejson; int32_t isvalid=0,doneflag = 0; - if ( (retstr= LP_validateaddress(symbol,address)) != 0 ) + char buf[1024],*retstr; cJSON *validatejson; int32_t isvalid=0,doneflag = 0; struct iguana_info *coin = LP_coinfind(symbol); + if ( coin == 0 ) + return(-2); + if ( (validatejson= LP_validateaddress(symbol,address)) != 0 ) { - if ( (validatejson= cJSON_Parse(retstr)) != 0 ) + if ( (isvalid= is_cJSON_True(jobj(validatejson,"isvalid")) != 0) != 0 ) { - if ( (isvalid= is_cJSON_True(jobj(validatejson,"isvalid")) != 0) != 0 ) - { - if ( is_cJSON_True(jobj(validatejson,"iswatchonly")) != 0 || is_cJSON_True(jobj(validatejson,"ismine")) != 0 ) - doneflag = 1; - } - free_json(validatejson); + if ( is_cJSON_True(jobj(validatejson,"iswatchonly")) != 0 || is_cJSON_True(jobj(validatejson,"ismine")) != 0 ) + doneflag = 1; } - free(retstr); - retstr = 0; + free_json(validatejson); } if ( isvalid == 0 ) - return(clonestr("{\"isvalid\":false}")); - update_alladdresses(myinfo,coin,address); + return(-1); if ( doneflag != 0 ) return(0); // success - if ( coin->FULLNODE < 0 ) + sprintf(buf,"[\"%s\", \"%s\", false]",address,address); + if ( (retstr= bitcoind_passthru(symbol,coin->serverport,coin->userpass,"importaddress",buf)) != 0 ) { - sprintf(buf,"[\"%s\", \"%s\", false]",address,address); - retstr = bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"importaddress",buf); - printf("%s importaddress.(%s) -> (%s)\n",coin->symbol,address,retstr); - return(retstr); - } - else return(0); -} - -char *LP_importaddress(char *symbol,char *coinaddr) -{ - return(0); -} - -char *LP_sendrawtransaction(char *symbol,char *signedtx) -{ - return(0); -} - -char *LP_signrawtx(char *symbol,bits256 *signedtxidp,int32_t *completedp,cJSON *vins,char *rawtxbytes,cJSON *privkeys,struct vin_info *V) -{ - return(0); -} - -cJSON *LP_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_t skip) -{ - return(0); -} - -char *dex_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_t skip) -{ - return(0); -} - -bits256 LP_privkey(char *coinaddr) -{ - bits256 privkey; - return(privkey); -} - -bits256 LP_pubkey(bits256 privkey) -{ - bits256 pubkey; - pubkey = curve25519(privkey,curve25519_basepoint9()); - return(pubkey); -} - -cJSON *LP_swapgettxout(char *symbol,bits256 trigger,int32_t vout) -{ - cJSON *retjson=0; //char *retstr; struct iguana_info *coin; - /*if ( ((coin= iguana_coinfind(symbol)) == 0 || coin->FULLNODE == 0) && iguana_isnotarychain(symbol) >= 0 ) - { - if ( (retstr= dex_gettxout(0,0,0,trigger,symbol,vout)) != 0 ) - { - //printf("dexgettxout.(%s)\n",retstr); - retjson = cJSON_Parse(retstr); - free(retstr); - } - if ( 0 && strcmp("BTC",symbol) == 0 ) - printf("%s gettxout.(%s)\n",symbol,jprint(retjson,0)); - } - else - { - retjson = dpow_gettxout(coin,trigger,vout); - //printf("need to verify passthru has this info\n"); - //printf("dpowgettxout.(%s)\n",jprint(retjson,0)); - }*/ - return(basilisk_nullretjson(retjson)); -} - -uint64_t LP_txvalue(char *symbol,bits256 txid,int32_t vout) -{ - uint64_t value = 0; - return(value); -} - -cJSON *LP_swapgettx(char *symbol,bits256 txid) -{ - cJSON *retjson=0; //char *retstr; struct iguana_info *coin; - /*if ( ((coin= iguana_coinfind(symbol)) == 0 || coin->FULLNODE == 0) && iguana_isnotarychain(symbol) >= 0 ) - { - if ( (retstr= dex_gettransaction(0,0,0,txid,symbol)) != 0 ) - { - retjson = cJSON_Parse(retstr); - free(retstr); - } - //if ( strcmp("BTC",symbol) == 0 ) - // printf("%s gettx.(%s)\n",symbol,jprint(retjson,0)); - } else retjson = dpow_gettransaction(coin,txid);*/ - return(basilisk_nullretjson(retjson)); + printf("importaddress.(%s %s) -> (%s)\n",symbol,address,retstr); + free(retstr); + } else printf("importaddress.(%s %s)\n",symbol,address); + return(1); } -bits256 basilisk_swap_sendrawtransaction(char *txname,char *symbol,char *txbytes) +double LP_getestimatedrate(char *symbol) { - char *retstr; bits256 txid; int32_t i,sentflag = 0; - memset(&txid,0,sizeof(txid)); - for (i=0; i<3; i++) + char buf[512],*retstr; double rate = 200; struct iguana_info *coin = LP_coinfind(symbol); + if ( coin != 0 ) { - if ( (retstr= LP_sendrawtransaction(symbol,txbytes)) != 0 ) + sprintf(buf,"[%d]",3); + if ( (retstr= bitcoind_passthru(symbol,coin->serverport,coin->userpass,"estimatefee",buf)) != 0 ) { - if ( is_hexstr(retstr,0) == 64 ) + if ( retstr[0] != '-' ) { - decode_hex(txid.bytes,32,retstr); - sentflag = 1; + rate = atof(retstr) / 1024.; + printf("estimated rate.(%s) %s -> %.8f\n",symbol,retstr,rate); } - char str[65]; printf("[%s] %s RETSTR.(%s) %s.%s\n",txname,txbytes,retstr,symbol,bits256_str(str,txid)); free(retstr); } - if ( sentflag != 0 ) - break; } - return(txid); + return(rate); } -bits256 LP_broadcast(char *name,char *symbol,uint8_t *data,int32_t datalen) +uint64_t LP_txfee(char *symbol) { - bits256 txid; char *signedtx,*retstr; int32_t i; - memset(txid.bytes,0,sizeof(txid)); - if ( data != 0 && datalen != 0 ) - { - char str[65]; -#ifdef BASILISK_DISABLESENDTX - txid = bits256_doublesha256(0,data,datalen); - printf("%s <- dont sendrawtransaction (%s)\n",name,bits256_str(str,txid)); - return(txid); -#endif - signedtx = malloc(datalen*2 + 1); - init_hexbytes_noT(signedtx,data,datalen); - for (i=0; i<3; i++) - { - if ( (retstr= LP_sendrawtransaction(symbol,signedtx)) != 0 ) - { - if ( is_hexstr(retstr,0) == 64 ) - { - decode_hex(txid.bytes,32,retstr); - free(retstr); - printf("sendrawtransaction.%s %s.(%s)\n",name,symbol,bits256_str(str,txid)); - break; - } - else - { - printf("sendrawtransaction.%s %s error.(%s)\n",name,symbol,retstr); - free(retstr); - } - } else printf("sendrawtransaction.%s %s got null return\n",name,symbol); - } - free(signedtx); - } - return(txid); + uint64_t txfee = 0; + if ( strcmp(symbol,"BTC") != 0 ) + txfee = 10000; + return(txfee); } -int32_t basilisk_confirmsobj(cJSON *item) +char *LP_sendrawtransaction(char *symbol,char *signedtx) { - int32_t height,numconfirms; - height = jint(item,"height"); - numconfirms = jint(item,"numconfirms"); - if ( height > 0 && numconfirms >= 0 ) - return(numconfirms); - printf("basilisk_confirmsobj height.%d numconfirms.%d (%s)\n",height,numconfirms,jprint(item,0)); - return(-1); + cJSON *array; char *paramstr,*retstr; struct iguana_info *coin = LP_coinfind(symbol); + if ( coin == 0 ) + return(0); + array = cJSON_CreateArray(); + jaddistr(array,signedtx); + paramstr = jprint(array,1); + retstr = bitcoind_passthru(symbol,coin->serverport,coin->userpass,"sendrawtransaction",paramstr); + printf(">>>>>>>>>>> %s dpow_sendrawtransaction.(%s) -> (%s)\n",coin->symbol,paramstr,retstr); + free(paramstr); + return(retstr); } -int32_t LP_numconfirms(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx) +char *LP_signrawtx(char *symbol,bits256 *signedtxidp,int32_t *completedp,cJSON *vins,char *rawtx,cJSON *privkeys,struct vin_info *V) { -#ifdef BASILISK_DISABLEWAITTX - return(100); -#endif - /*cJSON *argjson,*valuearray=0; char *valstr; int32_t i,n,retval = -1; - argjson = cJSON_CreateObject(); - jaddbits256(argjson,"txid",rawtx->I.actualtxid); - jaddnum(argjson,"vout",0); - jaddstr(argjson,"coin",rawtx->coin->symbol); - if ( (valstr= basilisk_value(rawtx->coin,0,0,swap->persistent_pubkey,argjson,0)) != 0 ) + cJSON *array,*json; int32_t len; uint8_t *data; char *paramstr,*retstr,*hexstr,*signedtx=0; struct iguana_info *coin = LP_coinfind(symbol); + memset(signedtxidp,0,sizeof(*signedtxidp)); + *completedp = 0; + if ( coin == 0 ) + { + printf("LP_signrawtx cant find coin.(%s)\n",symbol); + return(0); + } + array = cJSON_CreateArray(); + jaddistr(array,rawtx); + jaddi(array,jduplicate(vins)); + jaddi(array,jduplicate(privkeys)); + paramstr = jprint(array,1); + //printf("signrawtransaction\n"); + if ( (retstr= bitcoind_passthru(symbol,coin->serverport,coin->userpass,"signrawtransaction",paramstr)) != 0 ) { - char str[65]; printf("basilisk_numconfirms required.%d %s %s valstr.(%s)\n",rawtx->I.numconfirms,rawtx->name,bits256_str(str,rawtx->I.actualtxid),valstr); - //basilisk_numconfirms required.0 alicespend 29a2a6b4a61b1da82096d533c71b6762d61a82ca771a633269d97c0ccb94fe85 valstr.({"result":"success","numconfirms":0,"address":"1JGvZ67oTdM7kCya4J8kj1uErbSRAoq3wH","satoshis":"1413818","value":0.01413818,"height":462440,"txid":"29a2a6b4a61b1da82096d533c71b6762d61a82ca771a633269d97c0ccb94fe85","vout":0,"coin":"BTC"}) - - if ( (valuearray= cJSON_Parse(valstr)) != 0 ) + if ( (json= cJSON_Parse(retstr)) != 0 ) { - if ( valstr[0] == '[' && is_cJSON_Array(valuearray) != 0 ) + if ( (hexstr= jstr(json,"hex")) != 0 ) { - n = cJSON_GetArraySize(valuearray); - for (i=0; i= 0 ) - break; - } - } else retval = basilisk_confirmsobj(valuearray); - free_json(valuearray); - } else printf("parse error\n"); - free(valstr); + len = (int32_t)strlen(hexstr); + signedtx = calloc(1,len+1); + strcpy(signedtx,hexstr); + *completedp = is_cJSON_True(jobj(json,"complete")); + data = malloc(len >> 1); + decode_hex(data,len>>1,hexstr); + *signedtxidp = bits256_doublesha256(0,data,len >> 1); + } + //else + printf("%s signrawtransaction.(%s) params.(%s)\n",coin->symbol,retstr,paramstr); + free_json(json); + } + free(retstr); } - free_json(argjson); - printf("numconfirms.%d returned\n",retval); - return(retval);*/ + free(paramstr); + return(signedtx); } diff --git a/iguana/exchanges/LP_statemachine.c b/iguana/exchanges/LP_statemachine.c index 4cb663b99..dc0240c1b 100644 --- a/iguana/exchanges/LP_statemachine.c +++ b/iguana/exchanges/LP_statemachine.c @@ -18,6 +18,504 @@ // marketmaker // +/*void basilisk_swaps_init(struct supernet_info *myinfo) + { + char fname[512]; uint32_t iter,swapcompleted,requestid,quoteid,optionduration,statebits; FILE *fp; bits256 privkey;struct basilisk_request R; struct basilisk_swapmessage M; struct basilisk_swap *swap = 0; + sprintf(fname,"%s/SWAPS/list",GLOBAL_DBDIR), OS_compatible_path(fname); + if ( (myinfo->swapsfp= fopen(fname,"rb+")) != 0 ) + { + while ( fread(&requestid,1,sizeof(requestid),myinfo->swapsfp) == sizeof(requestid) && fread("eid,1,sizeof(quoteid),myinfo->swapsfp) == sizeof(quoteid) ) + { + sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname); + printf("%s\n",fname); + if ( (fp= fopen(fname,"rb+")) != 0 ) // check to see if completed + { + memset(&M,0,sizeof(M)); + swapcompleted = 1; + for (iter=0; iter<2; iter++) + { + if ( fread(privkey.bytes,1,sizeof(privkey),fp) == sizeof(privkey) && + fread(&R,1,sizeof(R),fp) == sizeof(R) && + fread(&statebits,1,sizeof(statebits),fp) == sizeof(statebits) && + fread(&optionduration,1,sizeof(optionduration),fp) == sizeof(optionduration) ) + { + while ( 0 && fread(&M,1,sizeof(M),fp) == sizeof(M) ) + { + M.data = 0; + //printf("entry iter.%d crc32.%x datalen.%d\n",iter,M.crc32,M.datalen); + if ( M.datalen < 100000 ) + { + M.data = malloc(M.datalen); + if ( fread(M.data,1,M.datalen,fp) == M.datalen ) + { + if ( calc_crc32(0,M.data,M.datalen) == M.crc32 ) + { + if ( iter == 1 ) + { + if ( swap == 0 ) + { + swap = basilisk_thread_start(privkey,&R,statebits,optionduration,1); + swap->I.choosei = swap->I.otherchoosei = -1; + } + if ( swap != 0 ) + basilisk_swapgotdata(swap,M.crc32,M.srchash,M.desthash,M.quoteid,M.msgbits,M.data,M.datalen,1); + } + } else printf("crc mismatch %x vs %x\n",calc_crc32(0,M.data,M.datalen),M.crc32); + } else printf("error reading M.datalen %d\n",M.datalen); + free(M.data), M.data = 0; + } + } + } + if ( swapcompleted != 0 ) + break; + rewind(fp); + } + } + } + } else myinfo->swapsfp = fopen(fname,"wb+"); + }*/ + +FILE *basilisk_swap_save(struct basilisk_swap *swap,bits256 privkey,struct basilisk_request *rp,uint32_t statebits,int32_t optionduration,int32_t reinit) +{ + FILE *fp=0; /*char fname[512]; + sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,rp->requestid,rp->quoteid), OS_compatible_path(fname); + if ( (fp= fopen(fname,"rb+")) == 0 ) + { + if ( (fp= fopen(fname,"wb+")) != 0 ) + { + fwrite(privkey.bytes,1,sizeof(privkey),fp); + fwrite(rp,1,sizeof(*rp),fp); + fwrite(&statebits,1,sizeof(statebits),fp); + fwrite(&optionduration,1,sizeof(optionduration),fp); + fflush(fp); + } + } + else if ( reinit != 0 ) + { + }*/ + return(fp); +} + +int32_t basilisk_swap_load(uint32_t requestid,uint32_t quoteid,bits256 *privkeyp,struct basilisk_request *rp,uint32_t *statebitsp,int32_t *optiondurationp) +{ + FILE *fp=0; char fname[512]; int32_t retval = -1; + sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname); + if ( (fp= fopen(fname,"rb+")) != 0 ) + { + if ( fread(privkeyp,1,sizeof(*privkeyp),fp) == sizeof(*privkeyp) && + fread(rp,1,sizeof(*rp),fp) == sizeof(*rp) && + fread(statebitsp,1,sizeof(*statebitsp),fp) == sizeof(*statebitsp) && + fread(optiondurationp,1,sizeof(*optiondurationp),fp) == sizeof(*optiondurationp) ) + retval = 0; + fclose(fp); + } + return(retval); +} + +void basilisk_swap_saveupdate(struct basilisk_swap *swap) +{ + FILE *fp; char fname[512]; + sprintf(fname,"%s/SWAPS/%u-%u.swap",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid), OS_compatible_path(fname); + if ( (fp= fopen(fname,"wb")) != 0 ) + { + fwrite(&swap->I,1,sizeof(swap->I),fp); + /*fwrite(&swap->bobdeposit,1,sizeof(swap->bobdeposit),fp); + fwrite(&swap->bobpayment,1,sizeof(swap->bobpayment),fp); + fwrite(&swap->alicepayment,1,sizeof(swap->alicepayment),fp); + fwrite(&swap->myfee,1,sizeof(swap->myfee),fp); + fwrite(&swap->otherfee,1,sizeof(swap->otherfee),fp); + fwrite(&swap->aliceclaim,1,sizeof(swap->aliceclaim),fp); + fwrite(&swap->alicespend,1,sizeof(swap->alicespend),fp); + fwrite(&swap->bobreclaim,1,sizeof(swap->bobreclaim),fp); + fwrite(&swap->bobspend,1,sizeof(swap->bobspend),fp); + fwrite(&swap->bobrefund,1,sizeof(swap->bobrefund),fp); + fwrite(&swap->alicereclaim,1,sizeof(swap->alicereclaim),fp);*/ + fwrite(swap->privkeys,1,sizeof(swap->privkeys),fp); + fwrite(swap->otherdeck,1,sizeof(swap->otherdeck),fp); + fwrite(swap->deck,1,sizeof(swap->deck),fp); + fclose(fp); + } +} + +/*int32_t basilisk_swap_loadtx(struct basilisk_rawtx *rawtx,FILE *fp,char *bobcoinstr,char *alicecoinstr) + { + if ( fread(rawtx,1,sizeof(*rawtx),fp) == sizeof(*rawtx) ) + { + rawtx->coin = 0; + rawtx->vins = 0; + if ( strcmp(rawtx->I.coinstr,bobcoinstr) == 0 || strcmp(rawtx->I.coinstr,alicecoinstr) == 0 ) + { + rawtx->coin = LP_coinfind(rawtx->I.coinstr); + if ( rawtx->vinstr[0] != 0 ) + rawtx->vins = cJSON_Parse(rawtx->vinstr); + printf("loaded.%s len.%d\n",rawtx->name,rawtx->I.datalen); + return(0); + } + } + return(-1); + }*/ + +void basilisk_swap_sendabort(struct basilisk_swap *swap) +{ + uint32_t msgbits = 0; uint8_t buf[sizeof(msgbits) + sizeof(swap->I.req.quoteid) + sizeof(bits256)*2]; int32_t sentbytes,offset=0; + memset(buf,0,sizeof(buf)); + offset += iguana_rwnum(1,&buf[offset],sizeof(swap->I.req.quoteid),&swap->I.req.quoteid); + offset += iguana_rwnum(1,&buf[offset],sizeof(msgbits),&msgbits); + if ( (sentbytes= nn_send(swap->pushsock,buf,offset,0)) != offset ) + { + if ( sentbytes < 0 ) + { + if ( swap->pushsock >= 0 ) // + nn_close(swap->pushsock), swap->pushsock = -1; + if ( swap->subsock >= 0 ) // + nn_close(swap->subsock), swap->subsock = -1; + swap->connected = 0; + } + } else printf("basilisk_swap_sendabort\n"); +} + +void basilisk_psockinit(struct basilisk_swap *swap,int32_t amlp); + +void basilisk_swapgotdata(struct basilisk_swap *swap,uint32_t crc32,bits256 srchash,bits256 desthash,uint32_t quoteid,uint32_t msgbits,uint8_t *data,int32_t datalen,int32_t reinit) +{ + int32_t i; struct basilisk_swapmessage *mp; + for (i=0; inummessages; i++) + if ( crc32 == swap->messages[i].crc32 && msgbits == swap->messages[i].msgbits && bits256_cmp(srchash,swap->messages[i].srchash) == 0 && bits256_cmp(desthash,swap->messages[i].desthash) == 0 ) + return; + //printf(" new message.[%d] datalen.%d Q.%x msg.%x [%llx]\n",swap->nummessages,datalen,quoteid,msgbits,*(long long *)data); + swap->messages = realloc(swap->messages,sizeof(*swap->messages) * (swap->nummessages + 1)); + mp = &swap->messages[swap->nummessages++]; + mp->crc32 = crc32; + mp->srchash = srchash; + mp->desthash = desthash; + mp->msgbits = msgbits; + mp->quoteid = quoteid; + mp->data = malloc(datalen); + mp->datalen = datalen; + memcpy(mp->data,data,datalen); + if ( reinit == 0 && swap->fp != 0 ) + { + fwrite(mp,1,sizeof(*mp),swap->fp); + fwrite(data,1,datalen,swap->fp); + fflush(swap->fp); + } +} + +int32_t basilisk_swapget(struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,int32_t (*basilisk_verify_func)(void *ptr,uint8_t *data,int32_t datalen)) +{ + uint8_t *ptr; bits256 srchash,desthash; uint32_t crc32,_msgbits,quoteid; int32_t i,size,offset,retval = -1; struct basilisk_swapmessage *mp = 0; + while ( (size= nn_recv(swap->subsock,&ptr,NN_MSG,0)) >= 0 ) + { + swap->lasttime = (uint32_t)time(NULL); + memset(srchash.bytes,0,sizeof(srchash)); + memset(desthash.bytes,0,sizeof(desthash)); + //printf("gotmsg.[%d] crc.%x\n",size,crc32); + offset = 0; + for (i=0; i<32; i++) + srchash.bytes[i] = ptr[offset++]; + for (i=0; i<32; i++) + desthash.bytes[i] = ptr[offset++]; + offset += iguana_rwnum(0,&ptr[offset],sizeof(uint32_t),"eid); + offset += iguana_rwnum(0,&ptr[offset],sizeof(uint32_t),&_msgbits); + if ( size > offset ) + { + crc32 = calc_crc32(0,&ptr[offset],size-offset); + if ( size > offset ) + { + //printf("size.%d offset.%d datalen.%d\n",size,offset,size-offset); + basilisk_swapgotdata(swap,crc32,srchash,desthash,quoteid,_msgbits,&ptr[offset],size-offset,0); + } + } + else if ( bits256_nonz(srchash) == 0 && bits256_nonz(desthash) == 0 ) + { + if ( swap->aborted == 0 ) + { + swap->aborted = (uint32_t)time(NULL); + printf("got abort signal from other side\n"); + } + } else printf("basilisk_swapget: got strange packet\n"); + if ( ptr != 0 ) + nn_freemsg(ptr), ptr = 0; + } + //char str[65],str2[65]; + for (i=0; inummessages; i++) + { + //printf("%d: %s vs %s\n",i,bits256_str(str,swap->messages[i].srchash),bits256_str(str2,swap->messages[i].desthash)); + if ( bits256_cmp(swap->messages[i].desthash,swap->I.myhash) == 0 ) + { + if ( swap->messages[i].msgbits == msgbits ) + { + if ( swap->I.iambob == 0 && swap->lasttime != 0 && time(NULL) > swap->lasttime+360 ) + { + printf("nothing received for a while from Bob, try new sockets\n"); + if ( swap->pushsock >= 0 ) // + nn_close(swap->pushsock), swap->pushsock = -1; + if ( swap->subsock >= 0 ) // + nn_close(swap->subsock), swap->subsock = -1; + swap->connected = 0; + basilisk_psockinit(swap,swap->I.iambob != 0); + } + mp = &swap->messages[i]; + if ( msgbits != 0x80000000 ) + break; + } + } + } + if ( mp != 0 ) + retval = (*basilisk_verify_func)(swap,mp->data,mp->datalen); + //printf("mine/other %s vs %s\n",bits256_str(str,swap->I.myhash),bits256_str(str2,swap->I.otherhash)); + return(retval); +} + +int32_t basilisk_messagekeyread(uint8_t *key,uint32_t *channelp,uint32_t *msgidp,bits256 *srchashp,bits256 *desthashp) +{ + int32_t keylen = 0; + keylen += iguana_rwnum(0,&key[keylen],sizeof(uint32_t),channelp); + keylen += iguana_rwnum(0,&key[keylen],sizeof(uint32_t),msgidp); + keylen += iguana_rwbignum(0,&key[keylen],sizeof(*srchashp),srchashp->bytes); + keylen += iguana_rwbignum(0,&key[keylen],sizeof(*desthashp),desthashp->bytes); + return(keylen); +} + +int32_t basilisk_messagekey(uint8_t *key,uint32_t channel,uint32_t msgid,bits256 srchash,bits256 desthash) +{ + int32_t keylen = 0; + keylen += iguana_rwnum(1,&key[keylen],sizeof(uint32_t),&channel); + keylen += iguana_rwnum(1,&key[keylen],sizeof(uint32_t),&msgid); + keylen += iguana_rwbignum(1,&key[keylen],sizeof(srchash),srchash.bytes); + keylen += iguana_rwbignum(1,&key[keylen],sizeof(desthash),desthash.bytes); + return(keylen); +} + +void LP_channelsend(bits256 srchash,bits256 desthash,uint32_t channel,uint32_t msgid,uint8_t *data,int32_t datalen) +{ + int32_t keylen; uint8_t key[BASILISK_KEYSIZE]; //char *retstr; + keylen = basilisk_messagekey(key,channel,msgid,srchash,desthash); + //if ( (retstr= _dex_reqsend(myinfo,"DEX",key,keylen,data,datalen)) != 0 ) + // free(retstr); +} + + +#ifdef adfafds +void iguana_ensure_privkey(struct iguana_info *coin,bits256 privkey) +{ + uint8_t pubkey33[33]; struct iguana_waccount *wacct; struct iguana_waddress *waddr,addr; char coinaddr[128]; + bitcoin_pubkey33(swap->ctx,pubkey33,privkey); + bitcoin_address(coinaddr,coin->pubtype,pubkey33,33); + //printf("privkey for (%s)\n",coinaddr); + if ( myinfo->expiration != 0 && ((waddr= iguana_waddresssearch(&wacct,coinaddr)) == 0 || bits256_nonz(waddr->privkey) == 0) ) + { + if ( waddr == 0 ) + { + memset(&addr,0,sizeof(addr)); + iguana_waddresscalc(coin->pubtype,coin->wiftype,&addr,privkey); + if ( (wacct= iguana_waccountfind("default")) != 0 ) + waddr = iguana_waddressadd(coin,wacct,&addr,0); + } + if ( waddr != 0 ) + { + waddr->privkey = privkey; + if ( bitcoin_priv2wif(waddr->wifstr,waddr->privkey,coin->wiftype) > 0 ) + { + if ( (0) && waddr->wiftype != coin->wiftype ) + printf("ensurepriv warning: mismatched wiftype %02x != %02x\n",waddr->wiftype,coin->wiftype); + if ( (0) && waddr->addrtype != coin->pubtype ) + printf("ensurepriv warning: mismatched addrtype %02x != %02x\n",waddr->addrtype,coin->pubtype); + } + } + } +} +#endif + + +int32_t basilisk_rawtx_return(struct basilisk_rawtx *rawtx,cJSON *item,int32_t lockinputs,struct vin_info *V) +{ + char *signedtx,*txbytes; cJSON *vins,*privkeyarray; int32_t i,n,retval = -1; + if ( (txbytes= jstr(item,"rawtx")) != 0 && (vins= jobj(item,"vins")) != 0 ) + { + privkeyarray = cJSON_CreateArray(); + jaddistr(privkeyarray,wifstr); + if ( (signedtx= LP_signrawtx(rawtx->coin->symbol,&rawtx->I.signedtxid,&rawtx->I.completed,vins,txbytes,privkeyarray,V)) != 0 ) + { + if ( lockinputs != 0 ) + { + //printf("lockinputs\n"); + LP_unspentslock(rawtx->coin->symbol,vins); + if ( (n= cJSON_GetArraySize(vins)) != 0 ) + { + bits256 txid; int32_t vout; + for (i=0; iI.datalen = (int32_t)strlen(signedtx) >> 1; + //rawtx->txbytes = calloc(1,rawtx->I.datalen); + decode_hex(rawtx->txbytes,rawtx->I.datalen,signedtx); + //printf("%s SIGNEDTX.(%s)\n",rawtx->name,signedtx); + free(signedtx); + retval = 0; + } else printf("error signrawtx\n"); //do a very short timeout so it finishes via local poll + free_json(privkeyarray); + } + return(retval); +} + +cJSON *LP_createvins(struct basilisk_rawtx *dest,struct vin_info *V,struct basilisk_rawtx *rawtx,uint8_t *userdata,int32_t userdatalen,uint32_t sequenceid) +{ + cJSON *vins,*item,*sobj; char hexstr[8192]; + vins = cJSON_CreateArray(); + item = cJSON_CreateObject(); + if ( userdata != 0 && userdatalen > 0 ) + { + memcpy(V[0].userdata,userdata,userdatalen); + V[0].userdatalen = userdatalen; + init_hexbytes_noT(hexstr,userdata,userdatalen); + jaddstr(item,"userdata",hexstr); +#ifdef DISABLE_CHECKSIG + needsig = 0; +#endif + } + //printf("rawtx B\n"); + if ( bits256_nonz(rawtx->I.actualtxid) != 0 ) + jaddbits256(item,"txid",rawtx->I.actualtxid); + else jaddbits256(item,"txid",rawtx->I.signedtxid); + jaddnum(item,"vout",0); + //sobj = cJSON_CreateObject(); + init_hexbytes_noT(hexstr,rawtx->spendscript,rawtx->I.spendlen); + //jaddstr(sobj,"hex",hexstr); + //jadd(item,"scriptPubKey",sobj); + jaddstr(item,"scriptPubKey",hexstr); + jaddnum(item,"suppress",dest->I.suppress_pubkeys); + jaddnum(item,"sequence",sequenceid); + if ( (dest->I.redeemlen= rawtx->I.redeemlen) != 0 ) + { + init_hexbytes_noT(hexstr,rawtx->redeemscript,rawtx->I.redeemlen); + memcpy(dest->redeemscript,rawtx->redeemscript,rawtx->I.redeemlen); + jaddstr(item,"redeemScript",hexstr); + } + jaddi(vins,item); + return(vins); +} + +int32_t _basilisk_rawtx_gen(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) +{ + char scriptstr[1024],wifstr[256],coinaddr[64],*signedtx,*rawtxbytes; uint32_t basilisktag; int32_t retval = -1; cJSON *vins,*privkeys,*addresses,*valsobj; struct vin_info *V; + //bitcoin_address(coinaddr,rawtx->coin->chain->pubtype,myinfo->persistent_pubkey33,33); + if ( rawtx->coin->changeaddr[0] == 0 ) + { + bitcoin_address(rawtx->coin->changeaddr,rawtx->coin->pubtype,pubkey33,33); + printf("set change address.(%s)\n",rawtx->coin->changeaddr); + } + init_hexbytes_noT(scriptstr,script,scriptlen); + basilisktag = (uint32_t)rand(); + valsobj = cJSON_CreateObject(); + jaddstr(valsobj,"coin",rawtx->coin->symbol); + jaddstr(valsobj,"spendscript",scriptstr); + jaddstr(valsobj,"changeaddr",rawtx->coin->changeaddr); + jadd64bits(valsobj,"satoshis",rawtx->I.amount); + if ( strcmp(rawtx->coin->symbol,"BTC") == 0 && txfee > 0 && txfee < 50000 ) + txfee = 50000; + jadd64bits(valsobj,"txfee",txfee); + jaddnum(valsobj,"minconf",minconf); + if ( locktime == 0 ) + locktime = (uint32_t)time(NULL) - 777; + jaddnum(valsobj,"locktime",locktime); + jaddnum(valsobj,"timeout",30000); + jaddnum(valsobj,"timestamp",swapstarted+delay); + addresses = cJSON_CreateArray(); + bitcoin_address(coinaddr,rawtx->coin->pubtype,pubkey33,33); + jaddistr(addresses,coinaddr); + jadd(valsobj,"addresses",addresses); + rawtx->I.locktime = locktime; + printf("%s locktime.%u\n",rawtx->name,locktime); + V = calloc(256,sizeof(*V)); + privkeys = cJSON_CreateArray(); + bitcoin_priv2wif(wifstr,privkey,rawtx->coin->wiftype); + jaddistr(privkeys,wifstr); + vins = LP_createvins(rawtx,V,rawtx,0,0,0xffffffff); + rawtx->vins = jduplicate(vins); + jdelete(valsobj,"vin"); + jadd(valsobj,"vin",vins); + if ( (rawtxbytes= bitcoin_json2hex(rawtx->coin->isPoS,&rawtx->I.txid,valsobj,V)) != 0 ) + { + //printf("rawtx.(%s) vins.%p\n",rawtxbytes,vins); + if ( (signedtx= LP_signrawtx(rawtx->coin->symbol,&rawtx->I.signedtxid,&rawtx->I.completed,vins,rawtxbytes,privkeys,V)) != 0 ) + { + rawtx->I.datalen = (int32_t)strlen(signedtx) >> 1; + if ( rawtx->I.datalen <= sizeof(rawtx->txbytes) ) + decode_hex(rawtx->txbytes,rawtx->I.datalen,signedtx); + else printf("DEX tx is too big %d vs %d\n",rawtx->I.datalen,(int32_t)sizeof(rawtx->txbytes)); + if ( signedtx != rawtxbytes ) + free(signedtx); + if ( rawtx->I.completed != 0 ) + retval = 0; + else printf("couldnt complete sign transaction %s\n",rawtx->name); + } else printf("error signing\n"); + free(rawtxbytes); + } else printf("error making rawtx\n"); + free_json(privkeys); + free_json(valsobj); + free(V); + return(retval); +} + +int32_t _basilisk_rawtx_sign(char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,struct basilisk_swap *swap,uint32_t timestamp,uint32_t locktime,uint32_t sequenceid,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen,int32_t ignore_cltverr) +{ + char *rawtxbytes=0,*signedtx=0,wifstr[128]; cJSON *txobj,*vins,*privkeys; int32_t needsig=1,retval = -1; struct vin_info *V; + V = calloc(256,sizeof(*V)); + V[0].signers[0].privkey = privkey; + bitcoin_pubkey33(swap->ctx,V[0].signers[0].pubkey,privkey); + privkeys = cJSON_CreateArray(); + bitcoin_priv2wif(wifstr,privkey,wiftype); + jaddistr(privkeys,wifstr); + if ( privkey2 != 0 ) + { + V[0].signers[1].privkey = *privkey2; + bitcoin_pubkey33(swap->ctx,V[0].signers[1].pubkey,*privkey2); + bitcoin_priv2wif(wifstr,*privkey2,wiftype); + jaddistr(privkeys,wifstr); + V[0].N = V[0].M = 2; + //char str[65]; printf("add second privkey.(%s) %s\n",jprint(privkeys,0),bits256_str(str,*privkey2)); + } else V[0].N = V[0].M = 1; + V[0].suppress_pubkeys = dest->I.suppress_pubkeys; + V[0].ignore_cltverr = ignore_cltverr; + if ( dest->I.redeemlen != 0 ) + memcpy(V[0].p2shscript,dest->redeemscript,dest->I.redeemlen), V[0].p2shlen = dest->I.redeemlen; + txobj = bitcoin_txcreate(symbol,isPoS,locktime,userdata == 0 ? 1 : 1,timestamp);//rawtx->coin->locktime_txversion); + vins = LP_createvins(dest,V,rawtx,userdata,userdatalen,sequenceid); + jdelete(txobj,"vin"); + jadd(txobj,"vin",vins); + //printf("basilisk_rawtx_sign locktime.%u/%u for %s spendscript.%s -> %s, suppress.%d\n",rawtx->I.locktime,dest->I.locktime,rawtx->name,hexstr,dest->name,dest->I.suppress_pubkeys); + txobj = bitcoin_txoutput(txobj,dest->spendscript,dest->I.spendlen,dest->I.amount); + if ( (rawtxbytes= bitcoin_json2hex(isPoS,&dest->I.txid,txobj,V)) != 0 ) + { + //printf("rawtx.(%s) vins.%p\n",rawtxbytes,vins); + if ( needsig == 0 ) + signedtx = rawtxbytes; + if ( signedtx != 0 || (signedtx= LP_signrawtx(symbol,&dest->I.signedtxid,&dest->I.completed,vins,rawtxbytes,privkeys,V)) != 0 ) + { + dest->I.datalen = (int32_t)strlen(signedtx) >> 1; + if ( dest->I.datalen <= sizeof(dest->txbytes) ) + decode_hex(dest->txbytes,dest->I.datalen,signedtx); + else printf("DEX tx is too big %d vs %d\n",dest->I.datalen,(int32_t)sizeof(dest->txbytes)); + if ( signedtx != rawtxbytes ) + free(signedtx); + if ( dest->I.completed != 0 ) + retval = 0; + else printf("couldnt complete sign transaction %s\n",rawtx->name); + } else printf("error signing\n"); + free(rawtxbytes); + } else printf("error making rawtx\n"); + free_json(privkeys); + free_json(txobj); + free(V); + return(retval); +} + int32_t basilisk_process_swapverify(void *ptr,int32_t (*internal_func)(void *ptr,uint8_t *data,int32_t datalen),uint32_t channel,uint32_t msgid,uint8_t *data,int32_t datalen,uint32_t expiration,uint32_t duration) { struct basilisk_swap *swap = ptr; @@ -26,8 +524,6 @@ int32_t basilisk_process_swapverify(void *ptr,int32_t (*internal_func)(void *ptr else return(0); } - - int32_t basilisk_priviextract(struct iguana_info *coin,char *name,bits256 *destp,uint8_t secret160[20],bits256 srctxid,int32_t srcvout) { /*bits256 txid; char str[65]; int32_t i,vini,scriptlen; uint8_t rmd160[20],scriptsig[IGUANA_MAXSCRIPTSIZE]; @@ -539,6 +1035,225 @@ cJSON *basilisk_privkeyarray(struct iguana_info *coin,cJSON *vins) #endif +#ifdef old +void basilisk_swaploop(void *_utxo) +{ + uint8_t *data; uint32_t expiration,savestatebits=0,saveotherbits=0; uint32_t channel; int32_t iters,retval=0,j,datalen,maxlen; struct basilisk_swap *swap; struct LP_utxoinfo *utxo = _utxo; + swap = utxo->swap; + fprintf(stderr,"start swap iambob.%d\n",swap->I.iambob); + maxlen = 1024*1024 + sizeof(*swap); + data = malloc(maxlen); + expiration = (uint32_t)time(NULL) + 300; + //myinfo->DEXactive = expiration; + channel = 'D' + ((uint32_t)'E' << 8) + ((uint32_t)'X' << 16); + while ( swap->aborted == 0 && (swap->I.statebits & (0x08|0x02)) != (0x08|0x02) && time(NULL) < expiration ) + { + LP_channelsend(swap->I.req.srchash,swap->I.req.desthash,channel,0x4000000,(void *)&swap->I.req.requestid,sizeof(swap->I.req.requestid)); //,60); + if ( swap->connected == 0 ) + basilisk_psockinit(swap,swap->I.iambob != 0); + if ( swap->connected > 0 ) + { + printf("A r%u/q%u swapstate.%x\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits); + basilisk_sendstate(swap,data,maxlen); + basilisk_sendpubkeys(swap,data,maxlen); // send pubkeys + if ( basilisk_checkdeck(swap,data,maxlen) == 0) // check for other deck 0x02 + basilisk_sendchoosei(swap,data,maxlen); + basilisk_waitchoosei(swap,data,maxlen); // wait for choosei 0x08 + if ( (swap->I.statebits & (0x08|0x02)) == (0x08|0x02) ) + break; + } + if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits ) + sleep(DEX_SLEEP + (swap->I.iambob == 0)*1); + savestatebits = swap->I.statebits; + saveotherbits = swap->I.otherstatebits; + } + if ( swap->connected == 0 ) + { + printf("couldnt establish connection\n"); + retval = -1; + } + while ( swap->aborted == 0 && retval == 0 && (swap->I.statebits & 0x20) == 0 ) + { + if ( swap->connected == 0 ) + basilisk_psockinit(swap,swap->I.iambob != 0); + printf("B r%u/q%u swapstate.%x\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits); + basilisk_sendstate(swap,data,maxlen); + basilisk_sendchoosei(swap,data,maxlen); + basilisk_sendmostprivs(swap,data,maxlen); + if ( basilisk_swapget(swap,0x20,data,maxlen,basilisk_verify_privkeys) == 0 ) + { + swap->I.statebits |= 0x20; + break; + } + if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits ) + sleep(DEX_SLEEP + (swap->I.iambob == 0)*1); + savestatebits = swap->I.statebits; + saveotherbits = swap->I.otherstatebits; + if ( time(NULL) > expiration ) + break; + } + //myinfo->DEXactive = swap->I.expiration; + if ( time(NULL) >= expiration ) + { + retval = -1; + //myinfo->DEXactive = 0; + } + if ( swap->aborted != 0 ) + { + printf("swap aborted before tx sent\n"); + retval = -1; + } + printf("C r%u/q%u swapstate.%x retval.%d\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits,retval); + iters = 0; + while ( swap->aborted == 0 && retval == 0 && (swap->I.statebits & 0x40) == 0 && iters++ < 10 ) // send fee + { + if ( swap->connected == 0 ) + basilisk_psockinit(swap,swap->I.iambob != 0); + //printf("sendstate.%x\n",swap->I.statebits); + basilisk_sendstate(swap,data,maxlen); + //printf("swapget\n"); + basilisk_swapget(swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits); + //printf("after swapget\n"); + if ( swap->I.iambob != 0 && swap->bobdeposit.I.datalen == 0 ) + { + printf("bobscripts set\n"); + if ( basilisk_bobscripts_set(swap,1,1) < 0 ) + { + sleep(DEX_SLEEP); + printf("bobscripts set error\n"); + continue; + } + } + if ( swap->I.iambob == 0 ) + { + /*for (i=0; i<20; i++) + printf("%02x",swap->secretAm[i]); + printf(" <- secretAm\n"); + for (i=0; i<32; i++) + printf("%02x",swap->secretAm256[i]); + printf(" <- secretAm256\n"); + for (i=0; i<32; i++) + printf("%02x",swap->pubAm.bytes[i]); + printf(" <- pubAm\n"); + for (i=0; i<20; i++) + printf("%02x",swap->secretBn[i]); + printf(" <- secretBn\n"); + for (i=0; i<32; i++) + printf("%02x",swap->secretBn256[i]); + printf(" <- secretBn256\n"); + for (i=0; i<32; i++) + printf("%02x",swap->pubBn.bytes[i]); + printf(" <- pubBn\n"); + for (i=0; i<32; i++) + printf("%02x",swap->pubA0.bytes[i]); + printf(" <- pubA0\n"); + for (i=0; i<32; i++) + printf("%02x",swap->pubA1.bytes[i]); + printf(" <- pubA1\n"); + for (i=0; i<32; i++) + printf("%02x",swap->pubB0.bytes[i]); + printf(" <- pubB0\n"); + for (i=0; i<32; i++) + printf("%02x",swap->pubB1.bytes[i]); + printf(" <- pubB1\n");*/ + if ( (retval= basilisk_alicetxs(swap,data,maxlen)) != 0 ) + { + printf("basilisk_alicetxs error\n"); + break; + } + } + } + if ( swap->I.iambob == 0 && (swap->I.statebits & 0x40) == 0 ) + { + printf("couldnt send fee\n"); + retval = -8; + } + if ( retval == 0 ) + { + if ( swap->I.iambob == 0 && (swap->myfee.I.datalen == 0 || swap->alicepayment.I.datalen == 0 || swap->alicepayment.I.datalen == 0) ) + { + printf("ALICE's error %d %d %d\n",swap->myfee.I.datalen,swap->alicepayment.I.datalen,swap->alicepayment.I.datalen); + retval = -7; + } + else if ( swap->I.iambob != 0 && swap->bobdeposit.I.datalen == 0 ) //swap->bobpayment.I.datalen == 0 + { + printf("BOB's error %d %d %d\n",swap->myfee.I.datalen,swap->bobpayment.I.datalen,swap->bobdeposit.I.datalen); + retval = -7; + } + } + while ( swap->aborted == 0 && retval == 0 && basilisk_swapiteration(swap,data,maxlen) == 0 ) + { + if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits ) + sleep(DEX_SLEEP + (swap->I.iambob == 0)*1); + savestatebits = swap->I.statebits; + saveotherbits = swap->I.otherstatebits; + basilisk_sendstate(swap,data,maxlen); + basilisk_swapget(swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits); + basilisk_swap_saveupdate(swap); + if ( time(NULL) > swap->I.expiration ) + break; + } + if ( swap->I.iambob != 0 && swap->bobdeposit.I.datalen != 0 && bits256_nonz(swap->bobdeposit.I.actualtxid) != 0 ) + { + printf("BOB waiting for confirm state.%x\n",swap->I.statebits); + sleep(60); // wait for confirm/propagation of msig + printf("BOB reclaims refund\n"); + basilisk_bobdeposit_refund(swap,0); + if ( LP_swapdata_rawtxsend(swap,0,data,maxlen,&swap->bobrefund,0x40000000,0) == 0 ) // use secretBn + { + printf("Bob submit error getting refund of deposit\n"); + } + else + { + // maybe wait for bobrefund to be confirmed + for (j=datalen=0; j<32; j++) + data[datalen++] = swap->I.privBn.bytes[j]; + LP_swapsend(swap,0x40000000,data,datalen,0x40000000,swap->I.crcs_mypriv); + } + basilisk_swap_saveupdate(swap); + } + if ( retval != 0 ) + basilisk_swap_sendabort(swap); + printf("end of atomic swap\n"); + if ( swapcompleted(swap) > 0 ) // only if swap completed + { + if ( swap->I.iambob != 0 ) + tradebot_pendingadd(swapjson(swap),swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount)); + else tradebot_pendingadd(swapjson(swap),swap->I.req.dest,dstr(swap->I.req.destamount),swap->I.req.src,dstr(swap->I.req.srcamount)); + } + printf("%s swap finished statebits %x\n",swap->I.iambob!=0?"BOB":"ALICE",swap->I.statebits); + //basilisk_swap_purge(swap); + free(data); +} +#endif + +int32_t bitcoin_coinptrs(bits256 pubkey,struct iguana_info **bobcoinp,struct iguana_info **alicecoinp,char *src,char *dest,bits256 srchash,bits256 desthash) +{ + struct iguana_info *coin = LP_coinfind(src); + if ( coin == 0 || LP_coinfind(dest) == 0 ) + return(0); + *bobcoinp = *alicecoinp = 0; + *bobcoinp = LP_coinfind(dest); + *alicecoinp = LP_coinfind(src); + if ( bits256_cmp(pubkey,srchash) == 0 ) + { + if ( strcmp(src,(*bobcoinp)->symbol) == 0 ) + return(1); + else if ( strcmp(dest,(*alicecoinp)->symbol) == 0 ) + return(-1); + else return(0); + } + else if ( bits256_cmp(pubkey,desthash) == 0 ) + { + if ( strcmp(src,(*bobcoinp)->symbol) == 0 ) + return(-1); + else if ( strcmp(dest,(*alicecoinp)->symbol) == 0 ) + return(1); + else return(0); + } + return(0); +} + /*void basilisk_swap_purge(struct basilisk_swap *swap) { int32_t i,n; diff --git a/iguana/exchanges/LP_swap.c b/iguana/exchanges/LP_swap.c index 2a1d96bef..b6e91d625 100644 --- a/iguana/exchanges/LP_swap.c +++ b/iguana/exchanges/LP_swap.c @@ -119,33 +119,6 @@ */ -int32_t bitcoin_coinptrs(bits256 pubkey,struct iguana_info **bobcoinp,struct iguana_info **alicecoinp,char *src,char *dest,bits256 srchash,bits256 desthash) -{ - struct iguana_info *coin = LP_coinfind(src); - if ( coin == 0 || LP_coinfind(dest) == 0 ) - return(0); - *bobcoinp = *alicecoinp = 0; - *bobcoinp = LP_coinfind(dest); - *alicecoinp = LP_coinfind(src); - if ( bits256_cmp(pubkey,srchash) == 0 ) - { - if ( strcmp(src,(*bobcoinp)->symbol) == 0 ) - return(1); - else if ( strcmp(dest,(*alicecoinp)->symbol) == 0 ) - return(-1); - else return(0); - } - else if ( bits256_cmp(pubkey,desthash) == 0 ) - { - if ( strcmp(src,(*bobcoinp)->symbol) == 0 ) - return(-1); - else if ( strcmp(dest,(*alicecoinp)->symbol) == 0 ) - return(1); - else return(0); - } - return(0); -} - void basilisk_rawtx_purge(struct basilisk_rawtx *rawtx) { if ( rawtx->vins != 0 ) @@ -177,6 +150,14 @@ void basilisk_swap_finished(struct basilisk_swap *swap) swap->nummessages = 0; } +uint32_t basilisk_quoteid(struct basilisk_request *rp) +{ + struct basilisk_request R; + R = *rp; + R.unused = R.requestid = R.quoteid = R.DEXselector = 0; + return(calc_crc32(0,(void *)&R,sizeof(R))); +} + uint32_t basilisk_requestid(struct basilisk_request *rp) { struct basilisk_request R; @@ -190,19 +171,11 @@ uint32_t basilisk_requestid(struct basilisk_request *rp) for (i=0; i %s %.8f %s crc.%u\n",R.timestamp,R.requestid,R.quoteid,R.src,dstr(R.srcamount),bits256_str(str,R.srchash),R.dest,dstr(R.destamount),bits256_str(str2,R.desthash),calc_crc32(0,(void *)&R,sizeof(R))); + char str[65],str2[65]; printf("B REQUESTID: t.%u r.%u q.%u %s %.8f %s -> %s %.8f %s crc.%u q%u\n",R.timestamp,R.requestid,R.quoteid,R.src,dstr(R.srcamount),bits256_str(str,R.srchash),R.dest,dstr(R.destamount),bits256_str(str2,R.desthash),calc_crc32(0,(void *)&R,sizeof(R)),basilisk_quoteid(&R)); } return(calc_crc32(0,(void *)&R,sizeof(R))); } -uint32_t basilisk_quoteid(struct basilisk_request *rp) -{ - struct basilisk_request R; - R = *rp; - R.requestid = R.quoteid = R.unused = R.DEXselector = 0; - return(calc_crc32(0,(void *)&R,sizeof(R))); -} - int32_t LP_pubkeys_data(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) { int32_t i,datalen = 0; @@ -219,7 +192,9 @@ int32_t LP_pubkeys_verify(struct basilisk_swap *swap,uint8_t *data,int32_t datal for (i=0; iotherdeck)/sizeof(swap->otherdeck[0][0]); i++) len += iguana_rwnum(0,&data[len],sizeof(swap->otherdeck[i>>1][i&1]),&swap->otherdeck[i>>1][i&1]); return(0); - } else return(-1); + } + printf("pubkeys verify size mismatch %d != %d\n",datalen,(int32_t)sizeof(swap->otherdeck)); + return(-1); } int32_t LP_choosei_data(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) @@ -267,7 +242,7 @@ int32_t LP_choosei_verify(struct basilisk_swap *swap,uint8_t *data,int32_t datal vcalc_sha256(0,swap->I.secretBn256,swap->I.privBn.bytes,sizeof(swap->I.privBn)); swap->I.pubBn = bitcoin_pubkey33(swap->ctx,pubkey33,swap->I.privBn); printf("set privBn.%s %s\n",bits256_str(str,swap->I.privBn),bits256_str(str2,*(bits256 *)swap->I.secretBn256)); - basilisk_bobscripts_set(swap,1,1); + //basilisk_bobscripts_set(swap,1,1); } else { @@ -371,8 +346,8 @@ int32_t basilisk_verify_privi(void *ptr,uint8_t *data,int32_t datalen) basilisk_dontforget_update(swap,0); char str[65]; printf("privi verified.(%s)\n",bits256_str(str,privkey)); return(0); - } - } + } else printf("pubpair doesnt verify privi\n"); + } else printf("verify privi size mismatch %d != %d\n",datalen,(int32_t)sizeof(bits256)); return(-1); } @@ -406,7 +381,7 @@ int32_t LP_mostprivs_verify(struct basilisk_swap *swap,uint8_t *data,int32_t dat swap->I.secretAm[i] = data[len++]; for (i=0; i<32; i++) swap->I.secretAm256[i] = data[len++]; - basilisk_bobscripts_set(swap,1,1); + //basilisk_bobscripts_set(swap,1,1); } else { @@ -431,10 +406,13 @@ int32_t LP_waitfor(int32_t pairsock,struct basilisk_swap *swap,int32_t timeout,i { if ( (datalen= nn_recv(pairsock,&data,NN_MSG,0)) >= 0 ) { + printf("wait for got.%d\n",datalen); retval = (*verify)(swap,data,datalen); nn_freemsg(data); - } + return(retval); + } else printf("error nn_recv\n"); } + printf("waitfor timedout\n"); return(retval); } @@ -446,11 +424,10 @@ int32_t LP_waitsend(char *statename,int32_t timeout,int32_t pairsock,struct basi if ( (datalen= (*datagen)(swap,data,maxlen)) > 0 ) { if ( (sendlen= nn_send(pairsock,data,datalen,0)) == datalen ) - { retval = 0; - } else printf("send %s error\n",statename); + else printf("send %s error\n",statename); } - } else printf("didnt get pubkeys\n"); + } else printf("didnt get valid data\n"); return(retval); } @@ -489,9 +466,63 @@ void LP_swapsfp_update(struct basilisk_request *rp) } } +struct basilisk_rawtx *LP_swapdata_rawtx(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx) +{ + if ( rawtx->I.datalen != 0 && rawtx->I.datalen <= maxlen ) + { + memcpy(data,rawtx->txbytes,rawtx->I.datalen); + return(rawtx); + } + printf("swapdata rawtx has null txbytes\n"); + return(0); +} + +uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx,uint32_t nextbits,int32_t suppress_swapsend) +{ + uint8_t sendbuf[32768]; int32_t sendlen; + if ( LP_swapdata_rawtx(swap,data,maxlen,rawtx) != 0 ) + { + if ( bits256_nonz(rawtx->I.signedtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 ) + { + rawtx->I.actualtxid = LP_broadcast_tx(rawtx->name,rawtx->coin->symbol,rawtx->txbytes,rawtx->I.datalen); + if ( bits256_cmp(rawtx->I.actualtxid,rawtx->I.signedtxid) != 0 ) + { + //printf("%s rawtxsend.[%d] %s vs %s\n",rawtx->name,rawtx->I.datalen,bits256_str(str,rawtx->I.signedtxid),bits256_str(str2,rawtx->I.actualtxid)); + rawtx->I.actualtxid = rawtx->I.signedtxid; + } + if ( bits256_nonz(rawtx->I.actualtxid) != 0 && msgbits != 0 ) + { + sendlen = 0; + sendbuf[sendlen++] = rawtx->I.datalen & 0xff; + sendbuf[sendlen++] = (rawtx->I.datalen >> 8) & 0xff; + sendbuf[sendlen++] = rawtx->I.redeemlen; + //printf("datalen.%d redeemlen.%d\n",rawtx->I.datalen,rawtx->I.redeemlen); + memcpy(&sendbuf[sendlen],rawtx->txbytes,rawtx->I.datalen), sendlen += rawtx->I.datalen; + if ( rawtx->I.redeemlen > 0 && rawtx->I.redeemlen < 0x100 ) + { + memcpy(&sendbuf[sendlen],rawtx->redeemscript,rawtx->I.redeemlen); + sendlen += rawtx->I.redeemlen; + } + basilisk_dontforget_update(swap,rawtx); + //printf("sendlen.%d datalen.%d redeemlen.%d\n",sendlen,rawtx->datalen,rawtx->redeemlen); + if ( suppress_swapsend == 0 ) + return(LP_swapsend(pairsock,swap,msgbits,sendbuf,sendlen,nextbits,rawtx->I.crcs)); + else + { + printf("suppress swapsend %x\n",msgbits); + return(0); + } + } + } + return(nextbits); + } //else if ( swap->I.iambob == 0 ) + printf("error from basilisk_swapdata_rawtx.%s %p len.%d\n",rawtx->name,rawtx->txbytes,rawtx->I.datalen); + return(0); +} + void LP_bobloop(void *_utxo) { - uint8_t *data; int32_t maxlen; uint32_t expiration; struct basilisk_swap *swap; struct LP_utxoinfo *utxo = _utxo; + uint8_t *data; char *retstr; int32_t maxlen; uint32_t expiration; struct basilisk_swap *swap; struct LP_utxoinfo *utxo = _utxo; fprintf(stderr,"start swap iambob\n"); maxlen = 1024*1024 + sizeof(*swap); data = malloc(maxlen); @@ -507,254 +538,91 @@ void LP_bobloop(void *_utxo) else if ( LP_waitsend("mostprivs",10,utxo->pair,swap,data,maxlen,LP_mostprivs_verify,LP_mostprivs_data) < 0 ) printf("error waitsend mostprivs\n"); else if ( basilisk_bobscripts_set(swap,1,1) < 0 ) - printf("error bobscripts\n"); + printf("error bobscripts deposit\n"); else { LP_swapsfp_update(&swap->I.req); - // wait alicefee - // send bobdeposit - // wait alicepayment - // send bobpayment - // bobspend - // bobrefund - // done + if ( LP_waitfor(utxo->pair,swap,10,LP_verify_otherfee) < 0 ) + printf("error waiting for alicefee\n"); + else if ( LP_swapdata_rawtxsend(utxo->pair,swap,0x200,data,maxlen,&swap->bobdeposit,0x100,0) == 0 ) + printf("error sending bobdeposit\n"); + else if ( LP_waitfor(utxo->pair,swap,10,LP_verify_alicepayment) < 0 ) + printf("error waiting for alicepayment\n"); + else if ( basilisk_bobscripts_set(swap,0,1) < 0 ) + printf("error bobscripts payment\n"); + else if ( LP_swapdata_rawtxsend(utxo->pair,swap,0x8000,data,maxlen,&swap->bobpayment,0x4000,0) == 0 ) + printf("error sending bobpayment\n"); + else + { + printf("looping on swaplist\n"); + while ( 1 ) + { + if ( (retstr= basilisk_swaplist()) != 0 ) + { + printf("%s\n",retstr); + free(retstr); + } + sleep(100); + } + } } + basilisk_swap_finished(swap); + free(utxo->swap); } else printf("swap timed out\n"); - basilisk_swap_finished(swap); - free(utxo->swap); utxo->swap = 0; nn_close(utxo->pair); utxo->pair = -1; } -void LP_aliceloop(void *_utxo) +void LP_aliceloop(void *_qp) { - uint8_t *data; int32_t maxlen; uint32_t expiration; struct basilisk_swap *swap; struct LP_utxoinfo *utxo = _utxo; - fprintf(stderr,"start swap iambob\n"); + uint8_t *data; char *retstr; int32_t maxlen; uint32_t expiration; struct basilisk_swap *swap = 0; struct LP_quoteinfo *qp = _qp; + fprintf(stderr,"start swap iamalice pair.%d\n",qp->pair); maxlen = 1024*1024 + sizeof(*swap); data = malloc(maxlen); expiration = (uint32_t)time(NULL) + 10; - while ( (swap= utxo->swap) == 0 && time(NULL) < expiration ) - sleep(1); - if ( (utxo->swap= swap) != 0 ) + swap = LP_swapinit(0,0,qp->privkey,&qp->R,qp); + if ( swap != 0 ) { - if ( LP_sendwait("pubkeys",10,utxo->pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 ) + if ( LP_sendwait("pubkeys",10,qp->pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 ) printf("error LP_sendwait pubkeys\n"); - else if ( LP_sendwait("choosei",10,utxo->pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 ) + else if ( LP_sendwait("choosei",10,qp->pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 ) printf("error LP_sendwait choosei\n"); - else if ( LP_sendwait("mostprivs",10,utxo->pair,swap,data,maxlen,LP_mostprivs_verify,LP_mostprivs_data) < 0 ) + else if ( LP_sendwait("mostprivs",10,qp->pair,swap,data,maxlen,LP_mostprivs_verify,LP_mostprivs_data) < 0 ) printf("error LP_sendwait mostprivs\n"); - else if ( basilisk_alicetxs(swap,data,maxlen) != 0 ) + else if ( basilisk_alicetxs(qp->pair,swap,data,maxlen) != 0 ) printf("basilisk_alicetxs error\n"); else { LP_swapsfp_update(&swap->I.req); - // send alicefee - // wait bobdeposit - // send alicepayment - // wait bobpayment - // alicespend - // done - } - } else printf("swap timed out\n"); - basilisk_swap_finished(swap); - free(utxo->swap); - utxo->swap = 0; - nn_close(utxo->pair); - utxo->pair = -1; -} - -#ifdef old -void basilisk_swaploop(void *_utxo) -{ - uint8_t *data; uint32_t expiration,savestatebits=0,saveotherbits=0; uint32_t channel; int32_t iters,retval=0,j,datalen,maxlen; struct basilisk_swap *swap; struct LP_utxoinfo *utxo = _utxo; - swap = utxo->swap; - fprintf(stderr,"start swap iambob.%d\n",swap->I.iambob); - maxlen = 1024*1024 + sizeof(*swap); - data = malloc(maxlen); - expiration = (uint32_t)time(NULL) + 300; - //myinfo->DEXactive = expiration; - channel = 'D' + ((uint32_t)'E' << 8) + ((uint32_t)'X' << 16); - while ( swap->aborted == 0 && (swap->I.statebits & (0x08|0x02)) != (0x08|0x02) && time(NULL) < expiration ) - { - LP_channelsend(swap->I.req.srchash,swap->I.req.desthash,channel,0x4000000,(void *)&swap->I.req.requestid,sizeof(swap->I.req.requestid)); //,60); - if ( swap->connected == 0 ) - basilisk_psockinit(swap,swap->I.iambob != 0); - if ( swap->connected > 0 ) - { - printf("A r%u/q%u swapstate.%x\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits); - basilisk_sendstate(swap,data,maxlen); - basilisk_sendpubkeys(swap,data,maxlen); // send pubkeys - if ( basilisk_checkdeck(swap,data,maxlen) == 0) // check for other deck 0x02 - basilisk_sendchoosei(swap,data,maxlen); - basilisk_waitchoosei(swap,data,maxlen); // wait for choosei 0x08 - if ( (swap->I.statebits & (0x08|0x02)) == (0x08|0x02) ) - break; - } - if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits ) - sleep(DEX_SLEEP + (swap->I.iambob == 0)*1); - savestatebits = swap->I.statebits; - saveotherbits = swap->I.otherstatebits; - } - if ( swap->connected == 0 ) - { - printf("couldnt establish connection\n"); - retval = -1; - } - while ( swap->aborted == 0 && retval == 0 && (swap->I.statebits & 0x20) == 0 ) - { - if ( swap->connected == 0 ) - basilisk_psockinit(swap,swap->I.iambob != 0); - printf("B r%u/q%u swapstate.%x\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits); - basilisk_sendstate(swap,data,maxlen); - basilisk_sendchoosei(swap,data,maxlen); - basilisk_sendmostprivs(swap,data,maxlen); - if ( basilisk_swapget(swap,0x20,data,maxlen,basilisk_verify_privkeys) == 0 ) - { - swap->I.statebits |= 0x20; - break; - } - if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits ) - sleep(DEX_SLEEP + (swap->I.iambob == 0)*1); - savestatebits = swap->I.statebits; - saveotherbits = swap->I.otherstatebits; - if ( time(NULL) > expiration ) - break; - } - //myinfo->DEXactive = swap->I.expiration; - if ( time(NULL) >= expiration ) - { - retval = -1; - //myinfo->DEXactive = 0; - } - if ( swap->aborted != 0 ) - { - printf("swap aborted before tx sent\n"); - retval = -1; - } - printf("C r%u/q%u swapstate.%x retval.%d\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits,retval); - iters = 0; - while ( swap->aborted == 0 && retval == 0 && (swap->I.statebits & 0x40) == 0 && iters++ < 10 ) // send fee - { - if ( swap->connected == 0 ) - basilisk_psockinit(swap,swap->I.iambob != 0); - //printf("sendstate.%x\n",swap->I.statebits); - basilisk_sendstate(swap,data,maxlen); - //printf("swapget\n"); - basilisk_swapget(swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits); - //printf("after swapget\n"); - if ( swap->I.iambob != 0 && swap->bobdeposit.I.datalen == 0 ) - { - printf("bobscripts set\n"); - if ( basilisk_bobscripts_set(swap,1,1) < 0 ) - { - sleep(DEX_SLEEP); - printf("bobscripts set error\n"); - continue; - } - } - if ( swap->I.iambob == 0 ) - { - /*for (i=0; i<20; i++) - printf("%02x",swap->secretAm[i]); - printf(" <- secretAm\n"); - for (i=0; i<32; i++) - printf("%02x",swap->secretAm256[i]); - printf(" <- secretAm256\n"); - for (i=0; i<32; i++) - printf("%02x",swap->pubAm.bytes[i]); - printf(" <- pubAm\n"); - for (i=0; i<20; i++) - printf("%02x",swap->secretBn[i]); - printf(" <- secretBn\n"); - for (i=0; i<32; i++) - printf("%02x",swap->secretBn256[i]); - printf(" <- secretBn256\n"); - for (i=0; i<32; i++) - printf("%02x",swap->pubBn.bytes[i]); - printf(" <- pubBn\n"); - for (i=0; i<32; i++) - printf("%02x",swap->pubA0.bytes[i]); - printf(" <- pubA0\n"); - for (i=0; i<32; i++) - printf("%02x",swap->pubA1.bytes[i]); - printf(" <- pubA1\n"); - for (i=0; i<32; i++) - printf("%02x",swap->pubB0.bytes[i]); - printf(" <- pubB0\n"); - for (i=0; i<32; i++) - printf("%02x",swap->pubB1.bytes[i]); - printf(" <- pubB1\n");*/ - if ( (retval= basilisk_alicetxs(swap,data,maxlen)) != 0 ) + if ( LP_swapdata_rawtxsend(qp->pair,swap,0x80,data,maxlen,&swap->myfee,0x40,0) == 0 ) + printf("error sending alicefee\n"); + else if ( LP_waitfor(qp->pair,swap,10,LP_verify_bobdeposit) < 0 ) + printf("error waiting for bobdeposit\n"); + else if ( LP_swapdata_rawtxsend(qp->pair,swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0) == 0 ) + printf("error sending alicepayment\n"); + else if ( LP_waitfor(qp->pair,swap,10,LP_verify_bobpayment) < 0 ) + printf("error waiting for bobpayment\n"); + else { - printf("basilisk_alicetxs error\n"); - break; + printf("looping on swaplist\n"); + while ( 1 ) + { + if ( (retstr= basilisk_swaplist()) != 0 ) + { + printf("%s\n",retstr); + free(retstr); + } + sleep(100); + } } } + basilisk_swap_finished(swap); + free(swap); } - if ( swap->I.iambob == 0 && (swap->I.statebits & 0x40) == 0 ) - { - printf("couldnt send fee\n"); - retval = -8; - } - if ( retval == 0 ) - { - if ( swap->I.iambob == 0 && (swap->myfee.I.datalen == 0 || swap->alicepayment.I.datalen == 0 || swap->alicepayment.I.datalen == 0) ) - { - printf("ALICE's error %d %d %d\n",swap->myfee.I.datalen,swap->alicepayment.I.datalen,swap->alicepayment.I.datalen); - retval = -7; - } - else if ( swap->I.iambob != 0 && swap->bobdeposit.I.datalen == 0 ) //swap->bobpayment.I.datalen == 0 - { - printf("BOB's error %d %d %d\n",swap->myfee.I.datalen,swap->bobpayment.I.datalen,swap->bobdeposit.I.datalen); - retval = -7; - } - } - while ( swap->aborted == 0 && retval == 0 && basilisk_swapiteration(swap,data,maxlen) == 0 ) - { - if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits ) - sleep(DEX_SLEEP + (swap->I.iambob == 0)*1); - savestatebits = swap->I.statebits; - saveotherbits = swap->I.otherstatebits; - basilisk_sendstate(swap,data,maxlen); - basilisk_swapget(swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits); - basilisk_swap_saveupdate(swap); - if ( time(NULL) > swap->I.expiration ) - break; - } - if ( swap->I.iambob != 0 && swap->bobdeposit.I.datalen != 0 && bits256_nonz(swap->bobdeposit.I.actualtxid) != 0 ) - { - printf("BOB waiting for confirm state.%x\n",swap->I.statebits); - sleep(60); // wait for confirm/propagation of msig - printf("BOB reclaims refund\n"); - basilisk_bobdeposit_refund(swap,0); - if ( LP_swapdata_rawtxsend(swap,0,data,maxlen,&swap->bobrefund,0x40000000,0) == 0 ) // use secretBn - { - printf("Bob submit error getting refund of deposit\n"); - } - else - { - // maybe wait for bobrefund to be confirmed - for (j=datalen=0; j<32; j++) - data[datalen++] = swap->I.privBn.bytes[j]; - LP_swapsend(swap,0x40000000,data,datalen,0x40000000,swap->I.crcs_mypriv); - } - basilisk_swap_saveupdate(swap); - } - if ( retval != 0 ) - basilisk_swap_sendabort(swap); - printf("end of atomic swap\n"); - if ( swapcompleted(swap) > 0 ) // only if swap completed - { - if ( swap->I.iambob != 0 ) - tradebot_pendingadd(swapjson(swap),swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount)); - else tradebot_pendingadd(swapjson(swap),swap->I.req.dest,dstr(swap->I.req.destamount),swap->I.req.src,dstr(swap->I.req.srcamount)); - } - printf("%s swap finished statebits %x\n",swap->I.iambob!=0?"BOB":"ALICE",swap->I.statebits); - //basilisk_swap_purge(swap); - free(data); + nn_close(qp->pair); + free(qp); } -#endif bits256 instantdex_derivekeypair(void *ctx,bits256 *newprivp,uint8_t pubkey[33],bits256 privkey,bits256 orderhash) { @@ -840,8 +708,8 @@ void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx * rawtx->coin = coin; strcpy(rawtx->I.coinstr,coin->symbol); rawtx->I.numconfirms = numconfirms; - if ( (rawtx->I.amount= satoshis) < 50000 ) - rawtx->I.amount = 50000; + if ( (rawtx->I.amount= satoshis) < 10000 ) + rawtx->I.amount = 10000; rawtx->I.vintype = vintype; // 0 -> std, 2 -> 2of2, 3 -> spend bobpayment, 4 -> spend bobdeposit rawtx->I.vouttype = vouttype; // 0 -> fee, 1 -> std, 2 -> 2of2, 3 -> bobpayment, 4 -> bobdeposit if ( rawtx->I.vouttype == 0 ) @@ -873,14 +741,14 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 swap->I.putduration -= optionduration; else if ( optionduration > 0 ) swap->I.callduration += optionduration; - swap->I.bobsatoshis = swap->I.req.destamount; - swap->I.alicesatoshis = swap->I.req.srcamount; - if ( (swap->I.bobinsurance= (swap->I.bobsatoshis / INSTANTDEX_INSURANCEDIV)) < 50000 ) - swap->I.bobinsurance = 50000; - if ( (swap->I.aliceinsurance= (swap->I.alicesatoshis / INSTANTDEX_INSURANCEDIV)) < 50000 ) - swap->I.aliceinsurance = 50000; - strcpy(swap->I.bobstr,swap->I.req.dest); - strcpy(swap->I.alicestr,swap->I.req.src); + swap->I.bobsatoshis = swap->I.req.srcamount; + swap->I.alicesatoshis = swap->I.req.destamount; + if ( (swap->I.bobinsurance= (swap->I.bobsatoshis / INSTANTDEX_INSURANCEDIV)) < 10000 ) + swap->I.bobinsurance = 10000; + if ( (swap->I.aliceinsurance= (swap->I.alicesatoshis / INSTANTDEX_INSURANCEDIV)) < 10000 ) + swap->I.aliceinsurance = 10000; + strcpy(swap->I.bobstr,swap->I.req.src); + strcpy(swap->I.alicestr,swap->I.req.dest); swap->I.started = (uint32_t)time(NULL); swap->I.expiration = swap->I.req.timestamp + swap->I.putduration + swap->I.callduration; OS_randombytes((uint8_t *)&swap->I.choosei,sizeof(swap->I.choosei)); @@ -904,16 +772,16 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 char str[65]; printf("couldnt generate privkeys %d %s\n",x,bits256_str(str,privkey)); return(0); } - if ( (coin= LP_coinfind(swap->I.req.dest)) != 0 ) - swap->bobcoin = *coin; + if ( (coin= LP_coinfind(swap->I.alicestr)) != 0 ) + swap->alicecoin = *coin; else { printf("missing bobcoin.%p or missing alicecoin.%p src.%p dest.%p\n",&swap->bobcoin,&swap->alicecoin,LP_coinfind(swap->I.req.src),LP_coinfind(swap->I.req.dest)); free(swap); return(0); } - if ( (coin= LP_coinfind(swap->I.req.src)) != 0 ) - swap->alicecoin = *coin; + if ( (coin= LP_coinfind(swap->I.bobstr)) != 0 ) + swap->bobcoin = *coin; else { printf("missing bobcoin.%p or missing alicecoin.%p src.%p dest.%p\n",&swap->bobcoin,&swap->alicecoin,LP_coinfind(swap->I.req.src),LP_coinfind(swap->I.req.dest)); @@ -975,7 +843,7 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 return(swap); } -struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp) +struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp) { struct basilisk_swap *swap; bits256 pubkey25519; uint8_t pubkey33[33]; swap = calloc(1,sizeof(*swap)); @@ -988,161 +856,19 @@ struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 swap->persistent_pubkey = pubkey25519; swap->persistent_privkey = privkey; memcpy(swap->persistent_pubkey33,pubkey33,33); + calc_rmd160_sha256(swap->changermd160,pubkey33,33); if ( bitcoin_swapinit(privkey,pubkey33,pubkey25519,swap,optionduration,!iambob) == 0 ) { printf("error doing swapinit\n"); free(swap); swap = 0; } + swap->bobpayment.utxotxid = qp->txid, swap->bobpayment.utxovout = qp->vout; + swap->bobdeposit.utxotxid = qp->txid2, swap->bobdeposit.utxovout = qp->vout2; + swap->alicepayment.utxotxid = qp->desttxid, swap->alicepayment.utxovout = qp->destvout; + if ( iambob != 0 ) + swap->otherfee.utxotxid = qp->feetxid, swap->otherfee.utxovout = qp->feevout; + else swap->myfee.utxotxid = qp->feetxid, swap->myfee.utxovout = qp->feevout; return(swap); } -#ifdef notanymore -struct basilisk_swap *basilisk_thread_start(bits256 privkey,struct basilisk_request *rp,uint32_t statebits,int32_t optionduration,int32_t reinit) -{ - int32_t i,m,n,iter; uint8_t pubkey33[33]; bits256 pubkey25519; uint32_t channel,starttime; cJSON *retarray,*item,*msgobj; struct iguana_info *coin; double pending=0.; struct basilisk_swap *swap = 0; - // statebits 1 -> client, 0 -> LP - /*if ( myinfo->numswaps > 0 ) - { - if ( (coin= LP_coinfind(rp->src)) == 0 || coin->FULLNODE >= 0 ) - { - printf("dont have SRC coin.%s or not native and already swap pending\n",rp->src); - return(0); - } - if ( (coin= LP_coinfind(rp->dest)) == 0 || coin->FULLNODE >= 0 ) - { - printf("dont have DEST coin.%s or not native and already swap pending\n",rp->dest); - return(0); - } - } - portable_mutex_lock(&myinfo->DEX_swapmutex); - for (i=0; inumswaps; i++) - if ( myinfo->swaps[i]->I.req.requestid == rp->requestid ) - { - printf("basilisk_thread_start error trying to start requestid.%u which is already started\n",rp->requestid); - break; - } - if ( i == myinfo->numswaps && i < sizeof(myinfo->swaps)/sizeof(*myinfo->swaps) )*/ - { - swap = calloc(1,sizeof(*swap)); - swap->ctx = bitcoin_ctx(); - swap->subsock = swap->pushsock = -1; - vcalc_sha256(0,swap->I.orderhash.bytes,(uint8_t *)rp,sizeof(*rp)); - swap->I.req = *rp; - //swap->myinfoptr = myinfo; - printf("basilisk_thread_start request.%u statebits.%d (%s/%s) reinit.%d\n",rp->requestid,statebits,rp->src,rp->dest,reinit); - bitcoin_pubkey33(swap->ctx,pubkey33,privkey); - pubkey25519 = curve25519(privkey,curve25519_basepoint9()); - swap->persistent_pubkey = pubkey25519; - swap->persistent_privkey = privkey; - memcpy(swap->persistent_pubkey33,pubkey33,33); - m = n = 0; - if ( bitcoin_swapinit(privkey,pubkey33,pubkey25519,swap,optionduration,statebits,reinit) != 0 ) - { - for (iter=0; iter<16; iter++) - { - basilisk_psockinit(swap,statebits == 0); - sleep(3); - if ( swap->connected > 0 ) - break; - sleep(10); - /*basilisk_sendstate(swap,data,sizeof(data)); - basilisk_swapget(swap,0x80000000,data,sizeof(data),basilisk_verify_statebits); - if ( swap->connected > 0 ) - break; - printf("loopback didntwork with %d %d\n",swap->pushsock,swap->subsock);*/ - } - if ( reinit != 0 ) - { - if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)basilisk_swaploop,(void *)swap) != 0 ) - { - - } - //myinfo->swaps[myinfo->numswaps++] = swap; - } - else - { - starttime = (uint32_t)time(NULL); - printf("statebits.%x m.%d n.%d\n",statebits,m,n); - while ( statebits == 0 && m <= n/2 && time(NULL) < starttime+7*BASILISK_MSGDURATION ) - { - uint32_t msgid; uint8_t data[1024]; int32_t datalen; - m = n = 0; - sleep(DEX_SLEEP); - printf("waiting for offer to be accepted\n"); - channel = 'D' + ((uint32_t)'E' << 8) + ((uint32_t)'X' << 16); - datalen = basilisk_rwDEXquote(1,data,rp); - msgid = (uint32_t)time(NULL); - printf("other req.%d >>>>>>>>>>> send response (%llx -> %llx) r.%u quoteid.%u\n",i,(long long)rp->desthash.txid,(long long)rp->srchash.txid,rp->requestid,rp->quoteid); - LP_channelsend(rp->desthash,rp->srchash,channel,msgid,data,datalen); - if ( (retarray= basilisk_channelget(rp->srchash,rp->desthash,channel,0x4000000,30)) != 0 ) - { - if ( is_cJSON_Array(retarray) != 0 && (n= cJSON_GetArraySize(retarray)) > 0 ) - { - for (i=0; i 0 ) - { - item = jitem(msgobj,0); - if ( jobj(item,"data") != 0 && jobj(item,"key") != 0 ) - m++; - else printf("(%s)\n",jprint(item,0)); - } //else printf("msgobj.%p m.%d n.%d\n",msgobj,m,n); - } - } - } else printf("no retarray\n"); - } - printf("LAUNCH check.%d m.%d\n",statebits,m); - if ( statebits != 0 || m > 0 )//n/2 ) - { - //for (i=0; iI.req); i++) - // fprintf(stderr,"%02x",((uint8_t *)&swap->I.req)[i]); - if ( (swap->fp= basilisk_swap_save(swap,privkey,rp,statebits,optionduration,reinit)) != 0 ) - { - } - if ( reinit == 0 ) - { - static FILE *swapsfp; - if ( swapsfp == 0 ) - { - char fname[512]; - sprintf(fname,"%s/SWAPS/list",GLOBAL_DBDIR), OS_compatible_path(fname); - if ( (swapsfp= fopen(fname,"rb+")) == 0 ) - swapsfp = fopen(fname,"wb+"); - else fseek(swapsfp,0,SEEK_END); - printf("LIST fp.%p\n",swapsfp); - } - if ( swapsfp != 0 ) - { - fwrite(&rp->requestid,1,sizeof(rp->requestid),swapsfp); - fwrite(&rp->quoteid,1,sizeof(rp->quoteid),swapsfp); - fflush(swapsfp); - } - } - if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)basilisk_swaploop,(void *)swap) != 0 ) - { - - } - //myinfo->swaps[myinfo->numswaps++] = swap; - } - else - { - if ( statebits != 0 ) - { - if ( (coin= LP_coinfind(rp->src)) != 0 ) - { - - } - } - printf("%u/%u offer wasnt accepted statebits.%d m.%d n.%d pending %.8f\n",rp->requestid,rp->quoteid,statebits,m,n,pending); - } - } - } - } - //portable_mutex_unlock(&myinfo->DEX_swapmutex); - return(swap); -} -#endif - - diff --git a/iguana/exchanges/LP_transaction.c b/iguana/exchanges/LP_transaction.c index 2512c83f9..193c20475 100644 --- a/iguana/exchanges/LP_transaction.c +++ b/iguana/exchanges/LP_transaction.c @@ -19,8 +19,94 @@ // +bits256 LP_broadcast(char *txname,char *symbol,char *txbytes) +{ + char *retstr; bits256 txid; int32_t i,sentflag = 0; + memset(&txid,0,sizeof(txid)); + for (i=0; i<3; i++) + { + if ( (retstr= LP_sendrawtransaction(symbol,txbytes)) != 0 ) + { + if ( is_hexstr(retstr,0) == 64 ) + { + decode_hex(txid.bytes,32,retstr); + sentflag = 1; + } + char str[65]; printf("[%s] %s RETSTR.(%s) %s.%s\n",txname,txbytes,retstr,symbol,bits256_str(str,txid)); + free(retstr); + } + if ( sentflag != 0 ) + break; + } + return(txid); +} + +bits256 LP_broadcast_tx(char *name,char *symbol,uint8_t *data,int32_t datalen) +{ + bits256 txid; char *signedtx; + memset(txid.bytes,0,sizeof(txid)); + if ( data != 0 && datalen != 0 ) + { + char str[65]; +#ifdef BASILISK_DISABLESENDTX + txid = bits256_doublesha256(0,data,datalen); + printf("%s <- dont sendrawtransaction (%s)\n",name,bits256_str(str,txid)); + return(txid); +#endif + signedtx = malloc(datalen*2 + 1); + init_hexbytes_noT(signedtx,data,datalen); + txid = LP_broadcast(name,symbol,signedtx); + // sent to nn_socket! + free(signedtx); + } + return(txid); +} + +uint64_t LP_txvalue(char *symbol,bits256 txid,int32_t vout) +{ + uint64_t value = 0; double interest; cJSON *txobj,*vouts,*utxoobj; int32_t numvouts; + if ( (txobj= LP_gettx(symbol,txid)) != 0 ) + { + //char str[65]; printf("%s.(%s) txobj.(%s)\n",symbol,bits256_str(str,txid),jprint(txobj,0)); + if ( (vouts= jarray(&numvouts,txobj,"vout")) != 0 && vout < numvouts ) + { + utxoobj = jitem(vouts,vout); + if ( (value= jdouble(utxoobj,"amount")*SATOSHIDEN) == 0 && (value= jdouble(utxoobj,"value")*SATOSHIDEN) == 0 ) + { + char str[65]; printf("%s LP_txvalue.%s strange utxo.(%s) vout.%d/%d\n",symbol,bits256_str(str,txid),jprint(utxoobj,0),vout,numvouts); + } + else if ( strcmp(symbol,"KMD") == 0 ) + { + if ( (utxoobj= LP_gettxout(symbol,txid,vout)) != 0 ) + { + if ( (interest= jdouble(utxoobj,"interest")) != 0. ) + { + printf("add interest of %.8f to %.8f\n",interest,dstr(value)); + value += SATOSHIDEN * interest; + } + free_json(utxoobj); + } + } + } + free_json(txobj); + } + return(value); +} + +int32_t LP_numconfirms(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx) +{ + int32_t numconfirms = 100; +#ifndef BASILISK_DISABLEWAITTX + cJSON *txobj; + if ( (txobj= LP_gettx(symbol,txid)) != 0 ) + { + numconfirms = jint(txobj,"confirmations"); + free_json(txobj); + } +#endif + return(numconfirms); +} -#ifdef later int32_t iguana_msgtx_Vset(uint8_t *serialized,int32_t maxlen,struct iguana_msgtx *msgtx,struct vin_info *V) { int32_t vini,j,scriptlen,p2shlen,userdatalen,siglen,plen,need_op0=0,len = 0; uint8_t *script,*redeemscript=0,*userdata=0; struct vin_info *vp; @@ -116,168 +202,6 @@ int32_t iguana_msgtx_Vset(uint8_t *serialized,int32_t maxlen,struct iguana_msgtx return(len); } -int32_t bitcoin_verifyvins(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *signedtxidp,char **signedtx,struct iguana_msgtx *msgtx,uint8_t *serialized,int32_t maxlen,struct vin_info *V,uint32_t sighash,int32_t signtx,int32_t suppress_pubkeys) -{ - bits256 sigtxid; uint8_t *sig,*script; struct vin_info *vp; char vpnstr[64]; int32_t scriptlen,complete=0,j,vini=0,flag=0,siglen,numvouts,numsigs; - numvouts = msgtx->tx_out; - vpnstr[0] = 0; - *signedtx = 0; - memset(signedtxidp,0,sizeof(*signedtxidp)); - for (vini=0; vinitx_in; vini++) - { - if ( V->p2shscript[0] != 0 && V->p2shlen != 0 ) - { - script = V->p2shscript; - scriptlen = V->p2shlen; - //printf("V->p2shlen.%d\n",V->p2shlen); - } - else - { - script = msgtx->vins[vini].spendscript; - scriptlen = msgtx->vins[vini].spendlen; - } - sigtxid = bitcoin_sigtxid(pubtype,p2shtype,isPoS,height,serialized,maxlen,msgtx,vini,script,scriptlen,sighash,vpnstr,suppress_pubkeys); - if ( bits256_nonz(sigtxid) != 0 ) - { - vp = &V[vini]; - vp->sigtxid = sigtxid; - for (j=numsigs=0; jN; j++) - { - sig = vp->signers[j].sig; - siglen = vp->signers[j].siglen; - if ( signtx != 0 && bits256_nonz(vp->signers[j].privkey) != 0 ) - { - siglen = bitcoin_sign(swap->ctx,sig,sigtxid,vp->signers[j].privkey,0); - //if ( (plen= bitcoin_pubkeylen(vp->signers[j].pubkey)) <= 0 ) - bitcoin_pubkey33(swap->ctx,vp->signers[j].pubkey,vp->signers[j].privkey); - sig[siglen++] = sighash; - vp->signers[j].siglen = siglen; - /*char str[65]; printf("SIGTXID.(%s) ",bits256_str(str,sigtxid)); - int32_t i; for (i=0; isigners[j].pubkey[i]); - // s2 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1; - printf(" SIGNEDTX.[%02x] siglen.%d priv.%s\n",sig[siglen-1],siglen,bits256_str(str,vp->signers[j].privkey));*/ - } - if ( sig == 0 || siglen == 0 ) - { - memset(vp->signers[j].pubkey,0,sizeof(vp->signers[j].pubkey)); - continue; - } - if ( bitcoin_verify(sig,siglen-1,sigtxid,vp->signers[j].pubkey,bitcoin_pubkeylen(vp->signers[j].pubkey)) < 0 ) - { - int32_t k; for (k=0; ksigners[j].pubkey); k++) - printf("%02x",vp->signers[j].pubkey[k]); - printf(" SIG.%d.%d ERROR siglen.%d\n",vini,j,siglen); - } - else - { - flag++; - numsigs++; - /*int32_t z; - for (z=0; zsigners[j].pubkey[z]); - printf(" <- pub, SIG.%d.%d VERIFIED numsigs.%d vs M.%d\n",vini,j,numsigs,vp->M);*/ - } - } - if ( numsigs >= vp->M ) - complete = 1; - } - } - iguana_msgtx_Vset(serialized,maxlen,msgtx,V); - cJSON *txobj = cJSON_CreateObject(); - *signedtx = iguana_rawtxbytes(pubtype,p2shtype,isPoS,height,txobj,msgtx,suppress_pubkeys); - //printf("SIGNEDTX.(%s)\n",jprint(txobj,1)); - *signedtxidp = msgtx->txid; - return(complete); -} - -int32_t iguana_vininfo_create(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msgtx,cJSON *vins,int32_t numinputs,struct vin_info *V) -{ - int32_t i,plen,finalized = 1,len = 0; struct vin_info *vp; //struct iguana_waccount *wacct; struct iguana_waddress *waddr; uint32_t sigsize,pubkeysize,p2shsize,userdatalen; - msgtx->tx_in = numinputs; - maxsize -= (sizeof(struct iguana_msgvin) * msgtx->tx_in); - msgtx->vins = (struct iguana_msgvin *)&serialized[maxsize]; - memset(msgtx->vins,0,sizeof(struct iguana_msgvin) * msgtx->tx_in); - if ( msgtx->tx_in > 0 && msgtx->tx_in*sizeof(struct iguana_msgvin) < maxsize ) - { - for (i=0; itx_in; i++) - { - vp = &V[i]; - //printf("VINS.(%s)\n",jprint(jitem(vins,i),0)); - len += iguana_parsevinobj(&serialized[len],maxsize,&msgtx->vins[i],jitem(vins,i),vp); - if ( msgtx->vins[i].sequence < IGUANA_SEQUENCEID_FINAL ) - finalized = 0; - if ( msgtx->vins[i].spendscript == 0 ) - { - /*if ( iguana_RTunspentindfind(coin,&outpt,vp->coinaddr,vp->spendscript,&vp->spendlen,&vp->amount,&vp->height,msgtx->vins[i].prev_hash,msgtx->vins[i].prev_vout,coin->bundlescount-1,0) == 0 ) - { - vp->unspentind = outpt.unspentind; - msgtx->vins[i].spendscript = vp->spendscript; - msgtx->vins[i].spendlen = vp->spendlen; - vp->hashtype = iguana_vinscriptparse(coin,vp,&sigsize,&pubkeysize,&p2shsize,&userdatalen,vp->spendscript,vp->spendlen); - vp->userdatalen = userdatalen; - printf("V %.8f (%s) spendscript.[%d] userdatalen.%d\n",dstr(vp->amount),vp->coinaddr,vp->spendlen,userdatalen); - }*/ - } - else - { - memcpy(vp->spendscript,msgtx->vins[i].spendscript,msgtx->vins[i].spendlen); - vp->spendlen = msgtx->vins[i].spendlen; - _iguana_calcrmd160(pubtype,p2shtype,vp); - if ( (plen= bitcoin_pubkeylen(vp->signers[0].pubkey)) > 0 ) - bitcoin_address(vp->coinaddr,pubtype,vp->signers[0].pubkey,plen); - } - if ( vp->M == 0 && vp->N == 0 ) - vp->M = vp->N = 1; - /*if ( vp->coinaddr[i] != 0 && (waddr= iguana_waddresssearch(&wacct,vp->coinaddr)) != 0 ) - { - vp->signers[0].privkey = waddr->privkey; - if ( (plen= bitcoin_pubkeylen(waddr->pubkey)) != vp->spendscript[1] || vp->spendscript[vp->spendlen-1] != 0xac ) - { - if ( plen > 0 && plen < sizeof(vp->signers[0].pubkey) ) - memcpy(vp->signers[0].pubkey,waddr->pubkey,plen); - } - }*/ - } - } - return(finalized); -} - -void iguana_ensure_privkey(struct iguana_info *coin,bits256 privkey) -{ - uint8_t pubkey33[33]; struct iguana_waccount *wacct; struct iguana_waddress *waddr,addr; char coinaddr[128]; - bitcoin_pubkey33(swap->ctx,pubkey33,privkey); - bitcoin_address(coinaddr,coin->pubtype,pubkey33,33); - //printf("privkey for (%s)\n",coinaddr); - if ( myinfo->expiration != 0 && ((waddr= iguana_waddresssearch(&wacct,coinaddr)) == 0 || bits256_nonz(waddr->privkey) == 0) ) - { - if ( waddr == 0 ) - { - memset(&addr,0,sizeof(addr)); - iguana_waddresscalc(coin->pubtype,coin->wiftype,&addr,privkey); - if ( (wacct= iguana_waccountfind("default")) != 0 ) - waddr = iguana_waddressadd(coin,wacct,&addr,0); - } - if ( waddr != 0 ) - { - waddr->privkey = privkey; - if ( bitcoin_priv2wif(waddr->wifstr,waddr->privkey,coin->wiftype) > 0 ) - { - if ( (0) && waddr->wiftype != coin->wiftype ) - printf("ensurepriv warning: mismatched wiftype %02x != %02x\n",waddr->wiftype,coin->wiftype); - if ( (0) && waddr->addrtype != coin->pubtype ) - printf("ensurepriv warning: mismatched addrtype %02x != %02x\n",waddr->addrtype,coin->pubtype); - } - } - } -} - int32_t iguana_interpreter(struct iguana_info *coin,cJSON *logarray,int64_t nLockTime,struct vin_info *V,int32_t numvins) { uint8_t script[IGUANA_MAXSCRIPTSIZE],*activescript,savescript[IGUANA_MAXSCRIPTSIZE]; char str[IGUANA_MAXSCRIPTSIZE*2+1]; int32_t vini,scriptlen,activescriptlen,savelen,errs = 0; cJSON *spendscript,*item=0; @@ -297,7 +221,7 @@ int32_t iguana_interpreter(struct iguana_info *coin,cJSON *logarray,int64_t nLoc } memcpy(V[vini].spendscript,activescript,activescriptlen); V[vini].spendlen = activescriptlen; - spendscript = iguana_spendasm(coin,activescript,activescriptlen); + spendscript = iguana_spendasm(activescript,activescriptlen); if ( activescriptlen < 16 ) continue; //printf("interpreter.(%s)\n",jprint(spendscript,0)); @@ -359,82 +283,226 @@ bits256 iguana_str2priv(char *str) return(privkey); } -int32_t iguana_signrawtransaction(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,struct iguana_msgtx *msgtx,char **signedtxp,bits256 *signedtxidp,struct vin_info *V,int32_t numinputs,char *rawtx,cJSON *vins,cJSON *privkeysjson) +int32_t iguana_vininfo_create(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msgtx,cJSON *vins,int32_t numinputs,struct vin_info *V) { - uint8_t *serialized,*serialized2,*serialized3,*serialized4,*extraspace,pubkeys[64][33]; int32_t finalized,i,len,n,z,plen,maxsize,complete = 0,extralen = 65536; char *privkeystr,*signedtx = 0; bits256 privkeys[64],privkey,txid; cJSON *item; cJSON *txobj = 0; - maxsize = 1000000; - memset(privkey.bytes,0,sizeof(privkey)); - if ( rawtx != 0 && rawtx[0] != 0 && (len= (int32_t)strlen(rawtx)>>1) < maxsize ) + int32_t i,plen,finalized = 1,len = 0; struct vin_info *vp; //struct iguana_waccount *wacct; struct iguana_waddress *waddr; uint32_t sigsize,pubkeysize,p2shsize,userdatalen; + msgtx->tx_in = numinputs; + maxsize -= (sizeof(struct iguana_msgvin) * msgtx->tx_in); + msgtx->vins = (struct iguana_msgvin *)&serialized[maxsize]; + memset(msgtx->vins,0,sizeof(struct iguana_msgvin) * msgtx->tx_in); + if ( msgtx->tx_in > 0 && msgtx->tx_in*sizeof(struct iguana_msgvin) < maxsize ) { - serialized = malloc(maxsize); - serialized2 = malloc(maxsize); - serialized3 = malloc(maxsize); - serialized4 = malloc(maxsize); - extraspace = malloc(extralen); - memset(msgtx,0,sizeof(*msgtx)); - decode_hex(serialized,len,rawtx); - // printf("call hex2json.(%s) vins.(%s)\n",rawtx,jprint(vins,0)); - if ( (txobj= bitcoin_hex2json(pubtype,p2shtype,isPoS,height,&txid,msgtx,rawtx,extraspace,extralen,serialized4,vins,V->suppress_pubkeys)) != 0 ) - { - //printf("back from bitcoin_hex2json (%s)\n",jprint(vins,0)); - } else fprintf(stderr,"no txobj from bitcoin_hex2json\n"); - if ( (numinputs= cJSON_GetArraySize(vins)) > 0 ) + for (i=0; itx_in; i++) { - //printf("numinputs.%d msgtx.%d\n",numinputs,msgtx->tx_in); - memset(msgtx,0,sizeof(*msgtx)); - if ( iguana_rwmsgtx(pubtype,p2shtype,isPoS,height,0,0,serialized,maxsize,msgtx,&txid,"",extraspace,65536,vins,V->suppress_pubkeys) > 0 && numinputs == msgtx->tx_in ) + vp = &V[i]; + //printf("VINS.(%s)\n",jprint(jitem(vins,i),0)); + len += iguana_parsevinobj(&serialized[len],maxsize,&msgtx->vins[i],jitem(vins,i),vp); + if ( msgtx->vins[i].sequence < IGUANA_SEQUENCEID_FINAL ) + finalized = 0; + if ( msgtx->vins[i].spendscript == 0 ) { - memset(pubkeys,0,sizeof(pubkeys)); - memset(privkeys,0,sizeof(privkeys)); - if ( (n= cJSON_GetArraySize(privkeysjson)) > 0 ) - { - for (i=0; ictx,pubkeys[i],privkey); - //if ( bits256_nonz(privkey) != 0 ) - // iguana_ensure_privkey(coin,privkey); - } - } - //printf("after privkeys tx_in.%d\n",msgtx->tx_in); - for (i=0; itx_in; i++) - { - if ( msgtx->vins[i].p2shlen != 0 ) - { - char coinaddr[64]; uint32_t userdatalen,sigsize,pubkeysize; uint8_t *userdata; int32_t j,k,hashtype,type,flag; struct vin_info mvin,mainvin; bits256 zero; - memset(zero.bytes,0,sizeof(zero)); - coinaddr[0] = 0; - sigsize = 0; - flag = (msgtx->vins[i].vinscript[0] == 0); - type = bitcoin_scriptget(pubtype,p2shtype,&hashtype,&sigsize,&pubkeysize,&userdata,&userdatalen,&mainvin,msgtx->vins[i].vinscript+flag,msgtx->vins[i].scriptlen-flag,0); - //printf("i.%d flag.%d type.%d scriptlen.%d\n",i,flag,type,msgtx->vins[i].scriptlen); - if ( msgtx->vins[i].redeemscript != 0 ) - { - //for (j=0; jvins[i].p2shlen; j++) - // printf("%02x",msgtx->vins[i].redeemscript[j]); - bitcoin_address(coinaddr,p2shtype,msgtx->vins[i].redeemscript,msgtx->vins[i].p2shlen); - type = iguana_calcrmd160(pubtype,p2shtype,0,&mvin,msgtx->vins[i].redeemscript,msgtx->vins[i].p2shlen,zero,0,0); - for (j=0; jsuppress_pubkeys == 0 ) - { - for (z=0; z<33; z++) - V[i].signers[j].pubkey[z] = mvin.signers[j].pubkey[z]; - } - if ( flag != 0 && pubkeysize == 33 && mainvin.signers[0].siglen != 0 ) // jl777: need to generalize - { - if ( memcmp(mvin.signers[j].pubkey,mainvin.signers[0].pubkey,33) == 0 ) - { - for (z=0; zcoinaddr,vp->spendscript,&vp->spendlen,&vp->amount,&vp->height,msgtx->vins[i].prev_hash,msgtx->vins[i].prev_vout,coin->bundlescount-1,0) == 0 ) + { + vp->unspentind = outpt.unspentind; + msgtx->vins[i].spendscript = vp->spendscript; + msgtx->vins[i].spendlen = vp->spendlen; + vp->hashtype = iguana_vinscriptparse(coin,vp,&sigsize,&pubkeysize,&p2shsize,&userdatalen,vp->spendscript,vp->spendlen); + vp->userdatalen = userdatalen; + printf("V %.8f (%s) spendscript.[%d] userdatalen.%d\n",dstr(vp->amount),vp->coinaddr,vp->spendlen,userdatalen); + }*/ + } + else + { + memcpy(vp->spendscript,msgtx->vins[i].spendscript,msgtx->vins[i].spendlen); + vp->spendlen = msgtx->vins[i].spendlen; + _iguana_calcrmd160(pubtype,p2shtype,vp); + if ( (plen= bitcoin_pubkeylen(vp->signers[0].pubkey)) > 0 ) + bitcoin_address(vp->coinaddr,pubtype,vp->signers[0].pubkey,plen); + } + if ( vp->M == 0 && vp->N == 0 ) + vp->M = vp->N = 1; + /*if ( vp->coinaddr[i] != 0 && (waddr= iguana_waddresssearch(&wacct,vp->coinaddr)) != 0 ) + { + vp->signers[0].privkey = waddr->privkey; + if ( (plen= bitcoin_pubkeylen(waddr->pubkey)) != vp->spendscript[1] || vp->spendscript[vp->spendlen-1] != 0xac ) + { + if ( plen > 0 && plen < sizeof(vp->signers[0].pubkey) ) + memcpy(vp->signers[0].pubkey,waddr->pubkey,plen); + } + }*/ + } + } + return(finalized); +} + +int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *signedtxidp,char **signedtx,struct iguana_msgtx *msgtx,uint8_t *serialized,int32_t maxlen,struct vin_info *V,uint32_t sighash,int32_t signtx,int32_t suppress_pubkeys) +{ + bits256 sigtxid; uint8_t *sig,*script; struct vin_info *vp; char vpnstr[64]; int32_t scriptlen,complete=0,j,vini=0,flag=0,siglen,numvouts,numsigs; + numvouts = msgtx->tx_out; + vpnstr[0] = 0; + *signedtx = 0; + memset(signedtxidp,0,sizeof(*signedtxidp)); + for (vini=0; vinitx_in; vini++) + { + if ( V->p2shscript[0] != 0 && V->p2shlen != 0 ) + { + script = V->p2shscript; + scriptlen = V->p2shlen; + //for (j=0; jp2shlen.%d\n",V->p2shlen); + } + else + { + script = msgtx->vins[vini].spendscript; + scriptlen = msgtx->vins[vini].spendlen; + } + sigtxid = bitcoin_sigtxid(pubtype,p2shtype,isPoS,height,serialized,maxlen,msgtx,vini,script,scriptlen,sighash,vpnstr,suppress_pubkeys); + if ( bits256_nonz(sigtxid) != 0 ) + { + vp = &V[vini]; + vp->sigtxid = sigtxid; + for (j=numsigs=0; jN; j++) + { + sig = vp->signers[j].sig; + siglen = vp->signers[j].siglen; + if ( signtx != 0 && bits256_nonz(vp->signers[j].privkey) != 0 ) + { + siglen = bitcoin_sign(ctx,symbol,sig,sigtxid,vp->signers[j].privkey,0); + //if ( (plen= bitcoin_pubkeylen(vp->signers[j].pubkey)) <= 0 ) + bitcoin_pubkey33(ctx,vp->signers[j].pubkey,vp->signers[j].privkey); + sig[siglen++] = sighash; + vp->signers[j].siglen = siglen; + /*char str[65]; printf("SIGTXID.(%s) ",bits256_str(str,sigtxid)); + int32_t i; for (i=0; isigners[j].pubkey[i]); + // s2 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1; + printf(" SIGNEDTX.[%02x] siglen.%d priv.%s\n",sig[siglen-1],siglen,bits256_str(str,vp->signers[j].privkey));*/ + } + if ( sig == 0 || siglen == 0 ) + { + memset(vp->signers[j].pubkey,0,sizeof(vp->signers[j].pubkey)); + continue; + } + if ( bitcoin_verify(ctx,sig,siglen-1,sigtxid,vp->signers[j].pubkey,bitcoin_pubkeylen(vp->signers[j].pubkey)) < 0 ) + { + int32_t k; for (k=0; ksigners[j].pubkey); k++) + printf("%02x",vp->signers[j].pubkey[k]); + printf(" SIG.%d.%d ERROR siglen.%d\n",vini,j,siglen); + } + else + { + flag++; + numsigs++; + int32_t z; char tmpaddr[64]; + for (z=0; zsigners[j].pubkey[z]); + bitcoin_address(tmpaddr,60,vp->signers[j].pubkey,33); + printf(" <- pub, SIG.%d.%d VERIFIED numsigs.%d vs M.%d %s\n",vini,j,numsigs,vp->M,tmpaddr); + } + } + if ( numsigs >= vp->M ) + complete = 1; + } + } + iguana_msgtx_Vset(serialized,maxlen,msgtx,V); + cJSON *txobj = cJSON_CreateObject(); + *signedtx = iguana_rawtxbytes(pubtype,p2shtype,isPoS,height,txobj,msgtx,suppress_pubkeys); + //printf("SIGNEDTX.(%s)\n",jprint(txobj,1)); + *signedtxidp = msgtx->txid; + return(complete); +} + +int64_t iguana_lockval(int32_t finalized,int64_t locktime) +{ + int64_t lockval = -1; + if ( finalized == 0 ) + return(locktime); + return(lockval); +} + +int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,struct iguana_msgtx *msgtx,char **signedtxp,bits256 *signedtxidp,struct vin_info *V,int32_t numinputs,char *rawtx,cJSON *vins,cJSON *privkeysjson) +{ + uint8_t *serialized,*serialized2,*serialized3,*serialized4,*extraspace,pubkeys[64][33]; int32_t finalized,i,len,n,z,plen,maxsize,complete = 0,extralen = 65536; char *privkeystr,*signedtx = 0; bits256 privkeys[64],privkey,txid; cJSON *item; cJSON *txobj = 0; + maxsize = 1000000; + memset(privkey.bytes,0,sizeof(privkey)); + if ( rawtx != 0 && rawtx[0] != 0 && (len= (int32_t)strlen(rawtx)>>1) < maxsize ) + { + serialized = malloc(maxsize); + serialized2 = malloc(maxsize); + serialized3 = malloc(maxsize); + serialized4 = malloc(maxsize); + extraspace = malloc(extralen); + memset(msgtx,0,sizeof(*msgtx)); + decode_hex(serialized,len,rawtx); + // printf("call hex2json.(%s) vins.(%s)\n",rawtx,jprint(vins,0)); + if ( (txobj= bitcoin_hex2json(pubtype,p2shtype,isPoS,height,&txid,msgtx,rawtx,extraspace,extralen,serialized4,vins,V->suppress_pubkeys)) != 0 ) + { + //printf("back from bitcoin_hex2json (%s)\n",jprint(vins,0)); + } else fprintf(stderr,"no txobj from bitcoin_hex2json\n"); + if ( (numinputs= cJSON_GetArraySize(vins)) > 0 ) + { + //printf("numinputs.%d msgtx.%d\n",numinputs,msgtx->tx_in); + memset(msgtx,0,sizeof(*msgtx)); + if ( iguana_rwmsgtx(pubtype,p2shtype,isPoS,height,0,0,serialized,maxsize,msgtx,&txid,"",extraspace,65536,vins,V->suppress_pubkeys) > 0 && numinputs == msgtx->tx_in ) + { + memset(pubkeys,0,sizeof(pubkeys)); + memset(privkeys,0,sizeof(privkeys)); + if ( (n= cJSON_GetArraySize(privkeysjson)) > 0 ) + { + for (i=0; itx_in); + for (i=0; itx_in; i++) + { + if ( msgtx->vins[i].p2shlen != 0 ) + { + char coinaddr[64]; uint32_t userdatalen,sigsize,pubkeysize; uint8_t *userdata; int32_t j,k,hashtype,type,flag; struct vin_info mvin,mainvin; bits256 zero; + memset(zero.bytes,0,sizeof(zero)); + coinaddr[0] = 0; + sigsize = 0; + flag = (msgtx->vins[i].vinscript[0] == 0); + type = bitcoin_scriptget(pubtype,p2shtype,&hashtype,&sigsize,&pubkeysize,&userdata,&userdatalen,&mainvin,msgtx->vins[i].vinscript+flag,msgtx->vins[i].scriptlen-flag,0); + //printf("i.%d flag.%d type.%d scriptlen.%d\n",i,flag,type,msgtx->vins[i].scriptlen); + if ( msgtx->vins[i].redeemscript != 0 ) + { + //for (j=0; jvins[i].p2shlen; j++) + // printf("%02x",msgtx->vins[i].redeemscript[j]); + bitcoin_address(coinaddr,p2shtype,msgtx->vins[i].redeemscript,msgtx->vins[i].p2shlen); + type = iguana_calcrmd160(pubtype,p2shtype,0,&mvin,msgtx->vins[i].redeemscript,msgtx->vins[i].p2shlen,zero,0,0); + for (j=0; jsuppress_pubkeys == 0 ) + { + for (z=0; z<33; z++) + V[i].signers[j].pubkey[z] = mvin.signers[j].pubkey[z]; + } + if ( flag != 0 && pubkeysize == 33 && mainvin.signers[0].siglen != 0 ) // jl777: need to generalize + { + if ( memcmp(mvin.signers[j].pubkey,mainvin.signers[0].pubkey,33) == 0 ) + { + for (z=0; zsuppress_pubkeys)) > 0 && signedtx != 0 ) + printf("finalized.%d\n",finalized); + if ( (complete= bitcoin_verifyvins(ctx,symbol,pubtype,p2shtype,isPoS,height,signedtxidp,&signedtx,msgtx,serialized3,maxsize,V,SIGHASH_ALL,1,V->suppress_pubkeys)) > 0 && signedtx != 0 ) { - /*int32_t tmp; //char str[65]; - if ( (tmp= iguana_interpreter(coin,0,iguana_lockval(finalized,jint(txobj,"locktime")),V,numinputs)) < 0 ) - { - printf("iguana_interpreter %d error.(%s)\n",tmp,signedtx); - complete = 0; - } */ + int32_t tmp; //char str[65]; + if ( (tmp= iguana_interpreter(ctx,cJSON_CreateArray(),iguana_lockval(finalized,jint(txobj,"locktime")),V,numinputs)) < 0 ) + { + printf("iguana_interpreter %d error.(%s)\n",tmp,signedtx); + complete = 0; + } else printf("interpreter passed\n"); } else printf("complete.%d\n",complete); } else printf("rwmsgtx error\n"); } else fprintf(stderr,"no inputs in vins.(%s)\n",vins!=0?jprint(vins,0):"null"); @@ -488,199 +556,10 @@ int32_t iguana_signrawtransaction(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS *signedtxp = signedtx; return(complete); } -#endif -/*int32_t basilisk_rawtx_return(struct basilisk_rawtx *rawtx,cJSON *item,int32_t lockinputs,struct vin_info *V) +char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privkey,bits256 *privkey2p,uint8_t *redeemscript,int32_t redeemlen,uint8_t *userdata,int32_t userdatalen,bits256 utxotxid,int32_t vout,char *destaddr,uint8_t *pubkey33,int32_t finalseqid,uint32_t expiration,int64_t *destamountp,uint64_t satoshis,char *changeaddr,char *vinaddr,int32_t suppress_pubkeys) { - char *signedtx,*txbytes; cJSON *vins,*privkeyarray; int32_t i,n,retval = -1; - if ( (txbytes= jstr(item,"rawtx")) != 0 && (vins= jobj(item,"vins")) != 0 ) - { - privkeyarray = cJSON_CreateArray(); - jaddistr(privkeyarray,wifstr); - if ( (signedtx= LP_signrawtx(rawtx->coin->symbol,&rawtx->I.signedtxid,&rawtx->I.completed,vins,txbytes,privkeyarray,V)) != 0 ) - { - if ( lockinputs != 0 ) - { - //printf("lockinputs\n"); - LP_unspentslock(rawtx->coin->symbol,vins); - if ( (n= cJSON_GetArraySize(vins)) != 0 ) - { - bits256 txid; int32_t vout; - for (i=0; iI.datalen = (int32_t)strlen(signedtx) >> 1; - //rawtx->txbytes = calloc(1,rawtx->I.datalen); - decode_hex(rawtx->txbytes,rawtx->I.datalen,signedtx); - //printf("%s SIGNEDTX.(%s)\n",rawtx->name,signedtx); - free(signedtx); - retval = 0; - } else printf("error signrawtx\n"); //do a very short timeout so it finishes via local poll - free_json(privkeyarray); - } - return(retval); -} - -cJSON *LP_createvins(struct basilisk_rawtx *dest,struct vin_info *V,struct basilisk_rawtx *rawtx,uint8_t *userdata,int32_t userdatalen,uint32_t sequenceid) -{ - cJSON *vins,*item,*sobj; char hexstr[8192]; - vins = cJSON_CreateArray(); - item = cJSON_CreateObject(); - if ( userdata != 0 && userdatalen > 0 ) - { - memcpy(V[0].userdata,userdata,userdatalen); - V[0].userdatalen = userdatalen; - init_hexbytes_noT(hexstr,userdata,userdatalen); - jaddstr(item,"userdata",hexstr); -#ifdef DISABLE_CHECKSIG - needsig = 0; -#endif - } - //printf("rawtx B\n"); - if ( bits256_nonz(rawtx->I.actualtxid) != 0 ) - jaddbits256(item,"txid",rawtx->I.actualtxid); - else jaddbits256(item,"txid",rawtx->I.signedtxid); - jaddnum(item,"vout",0); - sobj = cJSON_CreateObject(); - init_hexbytes_noT(hexstr,rawtx->spendscript,rawtx->I.spendlen); - jaddstr(sobj,"hex",hexstr); - jadd(item,"scriptPubKey",sobj); - jaddnum(item,"suppress",dest->I.suppress_pubkeys); - jaddnum(item,"sequence",sequenceid); - if ( (dest->I.redeemlen= rawtx->I.redeemlen) != 0 ) - { - init_hexbytes_noT(hexstr,rawtx->redeemscript,rawtx->I.redeemlen); - memcpy(dest->redeemscript,rawtx->redeemscript,rawtx->I.redeemlen); - jaddstr(item,"redeemScript",hexstr); - } - jaddi(vins,item); - return(vins); -} - -int32_t _basilisk_rawtx_gen(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) -{ - char scriptstr[1024],wifstr[256],coinaddr[64],*signedtx,*rawtxbytes; uint32_t basilisktag; int32_t retval = -1; cJSON *vins,*privkeys,*addresses,*valsobj; struct vin_info *V; - //bitcoin_address(coinaddr,rawtx->coin->chain->pubtype,myinfo->persistent_pubkey33,33); - if ( rawtx->coin->changeaddr[0] == 0 ) - { - bitcoin_address(rawtx->coin->changeaddr,rawtx->coin->pubtype,pubkey33,33); - printf("set change address.(%s)\n",rawtx->coin->changeaddr); - } - init_hexbytes_noT(scriptstr,script,scriptlen); - basilisktag = (uint32_t)rand(); - valsobj = cJSON_CreateObject(); - jaddstr(valsobj,"coin",rawtx->coin->symbol); - jaddstr(valsobj,"spendscript",scriptstr); - jaddstr(valsobj,"changeaddr",rawtx->coin->changeaddr); - jadd64bits(valsobj,"satoshis",rawtx->I.amount); - if ( strcmp(rawtx->coin->symbol,"BTC") == 0 && txfee > 0 && txfee < 50000 ) - txfee = 50000; - jadd64bits(valsobj,"txfee",txfee); - jaddnum(valsobj,"minconf",minconf); - if ( locktime == 0 ) - locktime = (uint32_t)time(NULL) - 777; - jaddnum(valsobj,"locktime",locktime); - jaddnum(valsobj,"timeout",30000); - jaddnum(valsobj,"timestamp",swapstarted+delay); - addresses = cJSON_CreateArray(); - bitcoin_address(coinaddr,rawtx->coin->pubtype,pubkey33,33); - jaddistr(addresses,coinaddr); - jadd(valsobj,"addresses",addresses); - rawtx->I.locktime = locktime; - printf("%s locktime.%u\n",rawtx->name,locktime); - V = calloc(256,sizeof(*V)); - privkeys = cJSON_CreateArray(); - bitcoin_priv2wif(wifstr,privkey,rawtx->coin->wiftype); - jaddistr(privkeys,wifstr); - vins = LP_createvins(rawtx,V,rawtx,0,0,0xffffffff); - rawtx->vins = jduplicate(vins); - jdelete(valsobj,"vin"); - jadd(valsobj,"vin",vins); - if ( (rawtxbytes= bitcoin_json2hex(rawtx->coin->isPoS,&rawtx->I.txid,valsobj,V)) != 0 ) - { - //printf("rawtx.(%s) vins.%p\n",rawtxbytes,vins); - if ( (signedtx= LP_signrawtx(rawtx->coin->symbol,&rawtx->I.signedtxid,&rawtx->I.completed,vins,rawtxbytes,privkeys,V)) != 0 ) - { - rawtx->I.datalen = (int32_t)strlen(signedtx) >> 1; - if ( rawtx->I.datalen <= sizeof(rawtx->txbytes) ) - decode_hex(rawtx->txbytes,rawtx->I.datalen,signedtx); - else printf("DEX tx is too big %d vs %d\n",rawtx->I.datalen,(int32_t)sizeof(rawtx->txbytes)); - if ( signedtx != rawtxbytes ) - free(signedtx); - if ( rawtx->I.completed != 0 ) - retval = 0; - else printf("couldnt complete sign transaction %s\n",rawtx->name); - } else printf("error signing\n"); - free(rawtxbytes); - } else printf("error making rawtx\n"); - free_json(privkeys); - free_json(valsobj); - free(V); - return(retval); -} - - -int32_t _basilisk_rawtx_sign(char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,struct basilisk_swap *swap,uint32_t timestamp,uint32_t locktime,uint32_t sequenceid,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen,int32_t ignore_cltverr) -{ - char *rawtxbytes=0,*signedtx=0,wifstr[128]; cJSON *txobj,*vins,*privkeys; int32_t needsig=1,retval = -1; struct vin_info *V; - V = calloc(256,sizeof(*V)); - V[0].signers[0].privkey = privkey; - bitcoin_pubkey33(swap->ctx,V[0].signers[0].pubkey,privkey); - privkeys = cJSON_CreateArray(); - bitcoin_priv2wif(wifstr,privkey,wiftype); - jaddistr(privkeys,wifstr); - if ( privkey2 != 0 ) - { - V[0].signers[1].privkey = *privkey2; - bitcoin_pubkey33(swap->ctx,V[0].signers[1].pubkey,*privkey2); - bitcoin_priv2wif(wifstr,*privkey2,wiftype); - jaddistr(privkeys,wifstr); - V[0].N = V[0].M = 2; - //char str[65]; printf("add second privkey.(%s) %s\n",jprint(privkeys,0),bits256_str(str,*privkey2)); - } else V[0].N = V[0].M = 1; - V[0].suppress_pubkeys = dest->I.suppress_pubkeys; - V[0].ignore_cltverr = ignore_cltverr; - if ( dest->I.redeemlen != 0 ) - memcpy(V[0].p2shscript,dest->redeemscript,dest->I.redeemlen), V[0].p2shlen = dest->I.redeemlen; - txobj = bitcoin_txcreate(symbol,isPoS,locktime,userdata == 0 ? 1 : 1,timestamp);//rawtx->coin->locktime_txversion); - vins = LP_createvins(dest,V,rawtx,userdata,userdatalen,sequenceid); - jdelete(txobj,"vin"); - jadd(txobj,"vin",vins); - //printf("basilisk_rawtx_sign locktime.%u/%u for %s spendscript.%s -> %s, suppress.%d\n",rawtx->I.locktime,dest->I.locktime,rawtx->name,hexstr,dest->name,dest->I.suppress_pubkeys); - txobj = bitcoin_txoutput(txobj,dest->spendscript,dest->I.spendlen,dest->I.amount); - if ( (rawtxbytes= bitcoin_json2hex(isPoS,&dest->I.txid,txobj,V)) != 0 ) - { - //printf("rawtx.(%s) vins.%p\n",rawtxbytes,vins); - if ( needsig == 0 ) - signedtx = rawtxbytes; - if ( signedtx != 0 || (signedtx= LP_signrawtx(symbol,&dest->I.signedtxid,&dest->I.completed,vins,rawtxbytes,privkeys,V)) != 0 ) - { - dest->I.datalen = (int32_t)strlen(signedtx) >> 1; - if ( dest->I.datalen <= sizeof(dest->txbytes) ) - decode_hex(dest->txbytes,dest->I.datalen,signedtx); - else printf("DEX tx is too big %d vs %d\n",dest->I.datalen,(int32_t)sizeof(dest->txbytes)); - if ( signedtx != rawtxbytes ) - free(signedtx); - if ( dest->I.completed != 0 ) - retval = 0; - else printf("couldnt complete sign transaction %s\n",rawtx->name); - } else printf("error signing\n"); - free(rawtxbytes); - } else printf("error making rawtx\n"); - free_json(privkeys); - free_json(txobj); - free(V); - return(retval); -}*/ - -char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privkey,bits256 *privkey2p,uint8_t *redeemscript,int32_t redeemlen,uint8_t *userdata,int32_t userdatalen,bits256 utxotxid,int32_t vout,uint8_t *pubkey33,int32_t finalseqid,uint32_t expiration,int64_t *destamountp) -{ - char *rawtxbytes=0,*signedtx=0,str[65],hexstr[999],wifstr[128],destaddr[64]; uint8_t spendscript[512],addrtype,rmd160[20]; cJSON *utxoobj,*txobj,*vins,*item,*sobj,*privkeys; int32_t completed,spendlen,ignore_cltverr=1,suppress_pubkeys=1; struct vin_info *V; uint32_t timestamp,locktime = 0,sequenceid = 0xffffffff * finalseqid; bits256 txid; uint64_t destamount; + char *rawtxbytes=0,*signedtx=0,str[65],tmpaddr[64],hexstr[999],wifstr[128],_destaddr[64]; uint8_t spendscript[512],addrtype,rmd160[20]; cJSON *txobj,*vins,*item,*privkeys; int32_t completed,spendlen,ignore_cltverr=1; struct vin_info V[16]; uint32_t timestamp,locktime = 0,sequenceid = 0xffffffff * finalseqid; bits256 txid; uint64_t value,change = 0; struct iguana_msgtx msgtx; *destamountp = 0; memset(signedtxidp,0,sizeof(*signedtxidp)); if ( finalseqid == 0 ) @@ -688,22 +567,22 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch //printf("bobtxspend.%s redeem.[%d]\n",symbol,redeemlen); if ( redeemlen < 0 ) return(0); - if ( (utxoobj= LP_swapgettxout(symbol,utxotxid,vout)) == 0 ) + if ( (value= LP_txvalue(symbol,utxotxid,vout)) == 0 ) { - printf("basilisk_swap_bobtxspend.%s utxo already spent or doesnt exist\n",name); + printf("basilisk_swap_bobtxspend.%s %s utxo.(%s) already spent or doesnt exist\n",name,symbol,bits256_str(str,utxotxid)); return(0); } - if ( (destamount= jdouble(utxoobj,"amount")*SATOSHIDEN) == 0 && (destamount= jdouble(utxoobj,"value")*SATOSHIDEN) == 0 ) + if ( satoshis != 0 ) { - printf("%s %s basilisk_swap_bobtxspend.%s strange utxo.(%s)\n",symbol,bits256_str(str,utxotxid),name,jprint(utxoobj,0)); - free_json(utxoobj); - return(0); - } else free_json(utxoobj); - *destamountp = destamount; - if ( destamount > txfee ) - destamount -= txfee; + if ( value > satoshis+txfee ) + change = value - (satoshis + txfee); + printf("utxo %.8f, destamount %.8f change %.8f txfee %.8f\n",dstr(value),dstr(satoshis),dstr(change),dstr(txfee)); + } else if ( value > txfee ) + satoshis = value - txfee; + else printf("unexpected small value %.8f vs txfee %.8f\n",dstr(value),dstr(txfee)); + *destamountp = satoshis; timestamp = (uint32_t)time(NULL); - V = calloc(256,sizeof(*V)); + memset(V,0,sizeof(V)); privkeys = cJSON_CreateArray(); if ( privkey2p != 0 ) { @@ -733,63 +612,78 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch } jaddbits256(item,"txid",utxotxid); jaddnum(item,"vout",vout); - sobj = cJSON_CreateObject(); - bitcoin_address(destaddr,pubtype,pubkey33,33); - bitcoin_addr2rmd160(&addrtype,rmd160,destaddr); - /*int32_t i; - for (i=0; i<33; i++) - printf("%02x",pubkey33[i]); - printf(" pubkey33 ->\n"); - for (i=0; i<20; i++) - printf("%02x",rmd160[i]); - printf(" destaddr.(%s)\n",destaddr); - calc_rmd160_sha256(rmd160,pubkey33,33); - for (i=0; i<20; i++) - printf("%02x",rmd160[i]); - printf(" <- vs direct calc\n");*/ - spendlen = bitcoin_standardspend(spendscript,0,rmd160); - init_hexbytes_noT(hexstr,spendscript,spendlen); - jaddstr(sobj,"hex",hexstr); - jadd(item,"scriptPubKey",sobj); - jaddnum(item,"suppress",suppress_pubkeys); - jaddnum(item,"sequence",sequenceid); + bitcoin_address(tmpaddr,pubtype,pubkey33,33); + bitcoin_addr2rmd160(&addrtype,rmd160,tmpaddr); if ( redeemlen != 0 ) { init_hexbytes_noT(hexstr,redeemscript,redeemlen); jaddstr(item,"redeemScript",hexstr); - } + if ( vinaddr != 0 ) + bitcoin_addr2rmd160(&addrtype,rmd160,vinaddr); + spendlen = bitcoin_p2shspend(spendscript,0,rmd160); + printf("P2SH path.%s\n",vinaddr!=0?vinaddr:0); + } else spendlen = bitcoin_standardspend(spendscript,0,rmd160); + init_hexbytes_noT(hexstr,spendscript,spendlen); + jaddstr(item,"scriptPubKey",hexstr); + jaddnum(item,"suppress",suppress_pubkeys); + jaddnum(item,"sequence",sequenceid); jaddi(vins,item); jdelete(txobj,"vin"); jadd(txobj,"vin",vins); - txobj = bitcoin_txoutput(txobj,spendscript,spendlen,destamount); + if ( destaddr == 0 ) + { + destaddr = _destaddr; + bitcoin_address(destaddr,pubtype,pubkey33,33); + } + bitcoin_addr2rmd160(&addrtype,rmd160,destaddr); + if ( addrtype == p2shtype ) + spendlen = bitcoin_p2shspend(spendscript,0,rmd160); + else spendlen = bitcoin_standardspend(spendscript,0,rmd160); + txobj = bitcoin_txoutput(txobj,spendscript,spendlen,satoshis); + if ( change != 0 ) + { + int32_t changelen; uint8_t changescript[1024],changetype,changermd160[20]; + bitcoin_addr2rmd160(&changetype,changermd160,changeaddr); + changelen = bitcoin_standardspend(changescript,0,changermd160); + txobj = bitcoin_txoutput(txobj,changescript,changelen,change); + } if ( (rawtxbytes= bitcoin_json2hex(isPoS,&txid,txobj,V)) != 0 ) { + char str[65]; + completed = 0; + memset(signedtxidp,0,sizeof(*signedtxidp)); //printf("locktime.%u sequenceid.%x rawtx.(%s) vins.(%s)\n",locktime,sequenceid,rawtxbytes,jprint(vins,0)); - if ( (signedtx= LP_signrawtx(symbol,signedtxidp,&completed,vins,rawtxbytes,privkeys,V)) == 0 ) - printf("couldnt sign transaction\n"); + if ( (completed= iguana_signrawtransaction(ctx,symbol,pubtype,p2shtype,isPoS,1000000,&msgtx,&signedtx,signedtxidp,V,1,rawtxbytes,vins,privkeys)) < 0 ) + //if ( (signedtx= LP_signrawtx(symbol,signedtxidp,&completed,vins,rawtxbytes,privkeys,V)) == 0 ) + printf("couldnt sign transaction.%s %s\n",name,bits256_str(str,*signedtxidp)); else if ( completed == 0 ) { - printf("incomplete signing\n"); + printf("incomplete signing suppress.%d %s (%s)\n",suppress_pubkeys,name,jprint(vins,0)); if ( signedtx != 0 ) free(signedtx), signedtx = 0; } else printf("%s -> %s\n",name,bits256_str(str,*signedtxidp)); free(rawtxbytes); - } else printf("error making rawtx\n"); + } else printf("error making rawtx suppress.%d\n",suppress_pubkeys); free_json(privkeys); free_json(txobj); - free(V); return(signedtx); } -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) +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) { - int32_t retval=-1,len,iter; char *signedtx; struct iguana_info *coin; int64_t newtxfee=0,destamount; + int32_t retval=-1,len,iter; char *signedtx,*changeaddr = 0,_changeaddr[64]; struct iguana_info *coin; int64_t newtxfee=0,destamount; if ( (coin= rawtx->coin) == 0 ) return(-1); //return(_basilisk_rawtx_gen(str,swapstarted,pubkey33,iambob,lockinputs,rawtx,locktime,script,scriptlen,txfee,minconf,delay,privkey)); + if ( changermd160 != 0 ) + { + changeaddr = _changeaddr; + bitcoin_address(changeaddr,coin->pubtype,changermd160,20); + printf("changeaddr.(%s) vs destaddr.(%s)\n",changeaddr,rawtx->I.destaddr); + } for (iter=0; iter<2; iter++) { - if ( (signedtx= basilisk_swap_bobtxspend(&rawtx->I.signedtxid,iter == 0 ? txfee : newtxfee,str,coin->symbol,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,ctx,privkey,0,0,0,0,0,rawtx->utxotxid,rawtx->utxovout,pubkey33,1,0,&destamount)) != 0 ) + if ( (signedtx= basilisk_swap_bobtxspend(&rawtx->I.signedtxid,iter == 0 ? txfee : newtxfee,str,coin->symbol,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,ctx,privkey,0,0,0,0,0,rawtx->utxotxid,rawtx->utxovout,rawtx->I.destaddr,pubkey33,1,0,&destamount,rawtx->I.amount,changeaddr,vinaddr,rawtx->I.suppress_pubkeys)) != 0 ) { rawtx->I.datalen = (int32_t)strlen(signedtx) >> 1; if ( rawtx->I.datalen <= sizeof(rawtx->txbytes) ) @@ -802,27 +696,36 @@ int32_t basilisk_rawtx_gen(void *ctx,char *str,uint32_t swapstarted,uint8_t *pub if ( strcmp(coin->symbol,"BTC") != 0 ) return(retval); len = rawtx->I.datalen; - if ( coin->estimatedfee == 0 ) - coin->estimatedfee = LP_getestimatedfee(coin->symbol); - newtxfee = coin->estimatedfee * len; + if ( coin->estimatedrate == 0. ) + coin->estimatedrate = LP_getestimatedrate(coin->symbol); + newtxfee = coin->estimatedrate * len; printf("txfee %.8f -> newtxfee %.8f\n",dstr(txfee),dstr(newtxfee)); } else break; } return(retval); } -int32_t basilisk_rawtx_sign(char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,struct basilisk_swap *swap,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen,int32_t ignore_cltverr) +int32_t basilisk_rawtx_sign(char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,struct basilisk_swap *swap,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen,int32_t ignore_cltverr,uint8_t *changermd160,char *vinaddr) { - char *signedtx; int64_t txfee,newtxfee=0,estimatedfee,destamount; uint32_t timestamp,locktime=0,sequenceid = 0xffffffff; int32_t iter,len,retval = -1; + char *signedtx,*changeaddr = 0,_changeaddr[64]; int64_t txfee,newtxfee=0,destamount; uint32_t timestamp,locktime=0,sequenceid = 0xffffffff; int32_t iter,len,retval = -1; double estimatedrate; timestamp = swap->I.started; if ( dest == &swap->aliceclaim ) locktime = swap->bobdeposit.I.locktime + 1, sequenceid = 0; else if ( dest == &swap->bobreclaim ) locktime = swap->bobpayment.I.locktime + 1, sequenceid = 0; txfee = strcmp("BTC",symbol) == 0 ? 0 : 10000; + if ( changermd160 != 0 ) + { + changeaddr = _changeaddr; + bitcoin_address(changeaddr,pubtype,changermd160,20); + printf("changeaddr.(%s)\n",changeaddr); + } + for (iter=0; iter<33; iter++) + printf("%02x",rawtx->I.pubkey33[iter]); + printf(" pubkey33.%s, suppress.%d\n",rawtx->name,rawtx->I.suppress_pubkeys); for (iter=0; iter<2; iter++) { - if ( (signedtx= basilisk_swap_bobtxspend(&rawtx->I.signedtxid,iter == 0 ? txfee : newtxfee,rawtx->name,symbol,pubtype,p2shtype,isPoS,wiftype,swap->ctx,privkey,privkey2,0,0,userdata,userdatalen,rawtx->utxotxid,rawtx->utxovout,rawtx->pubkey33,1,0,&destamount)) != 0 ) + if ( (signedtx= basilisk_swap_bobtxspend(&rawtx->I.signedtxid,iter == 0 ? txfee : newtxfee,rawtx->name,symbol,pubtype,p2shtype,isPoS,wiftype,swap->ctx,privkey,privkey2,0,0,userdata,userdatalen,rawtx->utxotxid,rawtx->utxovout,dest->p2shaddr,rawtx->I.pubkey33,1,0,&destamount,rawtx->I.amount,changeaddr,vinaddr,rawtx->I.suppress_pubkeys)) != 0 ) { rawtx->I.datalen = (int32_t)strlen(signedtx) >> 1; if ( rawtx->I.datalen <= sizeof(rawtx->txbytes) ) @@ -835,8 +738,8 @@ int32_t basilisk_rawtx_sign(char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_ if ( strcmp(symbol,"BTC") != 0 ) return(retval); len = rawtx->I.datalen; - estimatedfee = LP_getestimatedfee(symbol); - newtxfee = estimatedfee * len; + estimatedrate = LP_getestimatedrate(symbol); + newtxfee = estimatedrate * len; } else break; } return(retval); @@ -859,7 +762,7 @@ int32_t basilisk_alicescript(uint8_t *redeemscript,int32_t *redeemlenp,uint8_t * return(n); } -char *basilisk_swap_Aspend(char *name,char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privAm,bits256 privBn,bits256 utxotxid,int32_t vout,uint8_t pubkey33[33],uint32_t expiration,int64_t *destamountp) +char *basilisk_swap_Aspend(char *name,char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privAm,bits256 privBn,bits256 utxotxid,int32_t vout,uint8_t pubkey33[33],uint32_t expiration,int64_t *destamountp,char *vinaddr) { char msigaddr[64],*signedtx = 0; int32_t spendlen,redeemlen; uint8_t tmp33[33],redeemscript[512],spendscript[128]; bits256 pubAm,pubBn,signedtxid; uint64_t txfee; if ( bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 ) @@ -878,7 +781,7 @@ char *basilisk_swap_Aspend(char *name,char *symbol,uint8_t pubtype,uint8_t p2sht for (i=0; i<32; i++) privBn.bytes[i] = rev.bytes[31 - i];*/ txfee = LP_txfee(symbol); - signedtx = basilisk_swap_bobtxspend(&signedtxid,txfee,name,symbol,pubtype,p2shtype,isPoS,wiftype,ctx,privAm,&privBn,redeemscript,redeemlen,0,0,utxotxid,vout,pubkey33,1,expiration,destamountp); + signedtx = basilisk_swap_bobtxspend(&signedtxid,txfee,name,symbol,pubtype,p2shtype,isPoS,wiftype,ctx,privAm,&privBn,redeemscript,redeemlen,0,0,utxotxid,vout,0,pubkey33,1,expiration,destamountp,0,0,vinaddr,0); } return(signedtx); } @@ -907,7 +810,7 @@ int32_t LP_swap_getcoinaddr(char *symbol,char *coinaddr,bits256 txid,int32_t vou { cJSON *retjson; coinaddr[0] = 0; - if ( (retjson= LP_swapgettx(symbol,txid)) != 0 ) + if ( (retjson= LP_gettx(symbol,txid)) != 0 ) { LP_swap_txdestaddr(coinaddr,txid,vout,retjson); free_json(retjson); @@ -918,7 +821,7 @@ int32_t LP_swap_getcoinaddr(char *symbol,char *coinaddr,bits256 txid,int32_t vou int32_t basilisk_swap_getsigscript(char *symbol,uint8_t *script,int32_t maxlen,bits256 txid,int32_t vini) { cJSON *retjson,*vins,*item,*skey; int32_t n,scriptlen = 0; char *hexstr; - if ( (retjson= LP_swapgettx(symbol,txid)) != 0 ) + if ( (retjson= LP_gettx(symbol,txid)) != 0 ) { if ( (vins= jarray(&n,retjson,"vin")) != 0 && vini < n ) { @@ -939,7 +842,7 @@ int64_t basilisk_txvalue(char *symbol,bits256 txid,int32_t vout) { cJSON *txobj,*vouts,*item; int32_t n; int64_t value = 0; //char str[65]; printf("%s txvalue.(%s)\n",symbol,bits256_str(str,txid)); - if ( (txobj= LP_swapgettx(symbol,txid)) != 0 ) + if ( (txobj= LP_gettx(symbol,txid)) != 0 ) { //printf("txobj.(%s)\n",jprint(txobj,0)); if ( (vouts= jarray(&n,txobj,"vout")) != 0 ) @@ -957,7 +860,7 @@ bits256 _LP_swap_spendtxid(char *symbol,char *destaddr,char *coinaddr,bits256 ut { char *retstr,*addr; cJSON *array,*item,*array2; int32_t i,n,m; bits256 spendtxid,txid; memset(&spendtxid,0,sizeof(spendtxid)); - if ( (retstr= dex_listtransactions(symbol,coinaddr,100,0)) != 0 ) + if ( (retstr= blocktrail_listtransactions(symbol,coinaddr,100,0)) != 0 ) { if ( (array= cJSON_Parse(retstr)) != 0 ) { @@ -1014,7 +917,7 @@ bits256 LP_swap_spendtxid(char *symbol,char *destaddr,bits256 utxotxid,int32_t v coinaddr[0] = 0; memset(&spendtxid,0,sizeof(spendtxid)); //char str[65]; printf("swap %s spendtxid.(%s)\n",symbol,bits256_str(str,utxotxid)); - if ( strcmp("BTC",symbol) == 0 ) + if ( 0 && strcmp("BTC",symbol) == 0 ) { //[{"type":"sent","confirmations":379,"height":275311,"timestamp":1492084664,"txid":"8703c5517bc57db38134058370a14e99b8e662b99ccefa2061dea311bbd02b8b","vout":0,"amount":117.50945263,"spendtxid":"cf2509e076fbb9b22514923df916b7aacb1391dce9c7e1460b74947077b12510","vin":0,"paid":{"type":"paid","txid":"cf2509e076fbb9b22514923df916b7aacb1391dce9c7e1460b74947077b12510","height":275663,"timestamp":1492106024,"vouts":[{"RUDpN6PEBsE7ZFbGjUxk1W3QVsxnjBLYw6":117.50935263}]}}] LP_swap_getcoinaddr(symbol,coinaddr,utxotxid,vout); @@ -1069,7 +972,7 @@ bits256 LP_swap_spendtxid(char *symbol,char *destaddr,bits256 utxotxid,int32_t v if ( (catstr= jstr(item,"category")) != 0 && strcmp(catstr,"send") == 0 ) { txid = jbits256(item,"txid"); - if ( (txobj= LP_swapgettx(symbol,txid)) != 0 ) + if ( (txobj= LP_gettx(symbol,txid)) != 0 ) { if ( (vins= jarray(&m,txobj,"vin")) != 0 && m > jint(item,"vout") ) { @@ -1228,109 +1131,18 @@ int32_t basilisk_swapuserdata(uint8_t *userdata,bits256 privkey,int32_t ifpath,b int32_t basilisk_bobpayment_reclaim(struct basilisk_swap *swap,int32_t delay) { - uint8_t userdata[512]; int32_t i,retval,len = 0; static bits256 zero; - printf("basilisk_bobpayment_reclaim\n"); - len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[1],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); - memcpy(swap->I.userdata_bobreclaim,userdata,len); - swap->I.userdata_bobreclaimlen = len; - if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->bobreclaim,&swap->bobpayment,swap->I.myprivs[1],0,userdata,len,1)) == 0 ) - { - for (i=0; ibobreclaim.I.datalen; i++) - printf("%02x",swap->bobreclaim.txbytes[i]); - printf(" <- bobreclaim\n"); - //basilisk_txlog(swap,&swap->bobreclaim,delay); - return(retval); - } - return(-1); -} - -int32_t basilisk_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys) -{ - int32_t datalen=0,retval=-1,hexlen,n; uint8_t *data; cJSON *txobj,*skey,*vouts,*vout; char *hexstr; bits256 txid; - datalen = recvbuf[0]; - datalen += (int32_t)recvbuf[1] << 8; - if ( datalen > 65536 ) - return(-1); - rawtx->I.redeemlen = recvbuf[2]; - data = &recvbuf[3]; - if ( rawtx->I.redeemlen > 0 && rawtx->I.redeemlen < 0x100 ) - memcpy(rawtx->redeemscript,&data[datalen],rawtx->I.redeemlen); - //printf("recvlen.%d datalen.%d redeemlen.%d\n",recvlen,datalen,rawtx->redeemlen); - if ( rawtx->I.datalen == 0 ) - { - //rawtx->txbytes = calloc(1,datalen); - memcpy(rawtx->txbytes,data,datalen); - rawtx->I.datalen = datalen; - } - else if ( datalen != rawtx->I.datalen || memcmp(rawtx->txbytes,data,datalen) != 0 ) - { - int32_t i; for (i=0; iI.datalen; i++) - printf("%02x",rawtx->txbytes[i]); - printf(" <- rawtx\n"); - printf("%s rawtx data compare error, len %d vs %d <<<<<<<<<< warning\n",rawtx->name,rawtx->I.datalen,datalen); - return(-1); - } - txid = bits256_doublesha256(0,data,datalen); - char str[65]; printf("rawtx.%s txid %s\n",rawtx->name,bits256_str(str,txid)); - if ( bits256_cmp(txid,rawtx->I.actualtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 ) - rawtx->I.actualtxid = txid; - if ( (txobj= bitcoin_data2json(rawtx->coin->pubtype,rawtx->coin->p2shtype,rawtx->coin->isPoS,height,&rawtx->I.signedtxid,&rawtx->msgtx,rawtx->extraspace,sizeof(rawtx->extraspace),data,datalen,0,suppress_pubkeys)) != 0 ) - { - rawtx->I.actualtxid = rawtx->I.signedtxid; - //char str[65]; printf("got txid.%s (%s)\n",bits256_str(str,rawtx->signedtxid),jprint(txobj,0)); - rawtx->I.locktime = rawtx->msgtx.lock_time; - if ( (vouts= jarray(&n,txobj,"vout")) != 0 && v < n ) - { - vout = jitem(vouts,v); - if ( j64bits(vout,"satoshis") == rawtx->I.amount && (skey= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(skey,"hex")) != 0 ) - { - if ( (hexlen= (int32_t)strlen(hexstr) >> 1) < sizeof(rawtx->spendscript) ) - { - decode_hex(rawtx->spendscript,hexlen,hexstr); - rawtx->I.spendlen = hexlen; - bitcoin_address(rawtx->p2shaddr,rawtx->coin->p2shtype,rawtx->spendscript,hexlen); - //if ( swap != 0 ) - // basilisk_txlog(swap->myinfoptr,swap,rawtx,-1); // bobdeposit, bobpayment or alicepayment - retval = 0; - } - } else printf("%s ERROR.(%s)\n",rawtx->name,jprint(txobj,0)); - } - free_json(txobj); - } - return(retval); -} - -int32_t basilisk_verify_bobpaid(void *ptr,uint8_t *data,int32_t datalen) -{ - uint8_t userdata[512]; int32_t i,retval,len = 0; bits256 revAm; struct basilisk_swap *swap = ptr; - memset(revAm.bytes,0,sizeof(revAm)); - if ( basilisk_rawtx_spendscript(swap,swap->bobcoin.longestchain,&swap->bobpayment,0,data,datalen,0) == 0 ) + uint8_t userdata[512]; int32_t i,retval,len = 0; static bits256 zero; + printf("basilisk_bobpayment_reclaim\n"); + len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[1],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); + memcpy(swap->I.userdata_bobreclaim,userdata,len); + swap->I.userdata_bobreclaimlen = len; + if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->bobreclaim,&swap->bobpayment,swap->I.myprivs[1],0,userdata,len,1,swap->changermd160,swap->bobpayment.I.destaddr)) == 0 ) { - swap->bobpayment.I.signedtxid = LP_broadcast(swap->bobpayment.name,swap->bobpayment.coin->symbol,swap->bobpayment.txbytes,swap->bobpayment.I.datalen); - if ( bits256_nonz(swap->bobpayment.I.signedtxid) != 0 ) - swap->paymentunconf = 1; - basilisk_dontforget_update(swap,&swap->bobpayment); - for (i=0; i<32; i++) - revAm.bytes[i] = swap->I.privAm.bytes[31-i]; - len = basilisk_swapuserdata(userdata,revAm,0,swap->I.myprivs[0],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); - memcpy(swap->I.userdata_alicespend,userdata,len); - swap->I.userdata_alicespendlen = len; - 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])); - if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->alicespend,&swap->bobpayment,swap->I.myprivs[0],0,userdata,len,1)) == 0 ) - { - for (i=0; ibobpayment.I.datalen; i++) - printf("%02x",swap->bobpayment.txbytes[i]); - printf(" <- bobpayment\n"); - for (i=0; ialicespend.I.datalen; i++) - printf("%02x",swap->alicespend.txbytes[i]); - printf(" <- alicespend\n\n"); - swap->I.alicespent = 1; - //basilisk_txlog(swap,&swap->alicespend,-1); - return(retval); - } + for (i=0; ibobreclaim.I.datalen; i++) + printf("%02x",swap->bobreclaim.txbytes[i]); + printf(" <- bobreclaim\n"); + //basilisk_txlog(swap,&swap->bobreclaim,delay); + return(retval); } return(-1); } @@ -1341,7 +1153,7 @@ int32_t basilisk_bobdeposit_refund(struct basilisk_swap *swap,int32_t delay) len = basilisk_swapuserdata(userdata,swap->I.privBn,0,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); memcpy(swap->I.userdata_bobrefund,userdata,len); swap->I.userdata_bobrefundlen = len; - if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->bobrefund,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,0)) == 0 ) + if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->bobrefund,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,0,swap->changermd160,swap->bobdeposit.I.destaddr)) == 0 ) { for (i=0; ibobrefund.I.datalen; i++) printf("%02x",swap->bobrefund.txbytes[i]); @@ -1354,42 +1166,40 @@ int32_t basilisk_bobdeposit_refund(struct basilisk_swap *swap,int32_t delay) int32_t basilisk_bobscripts_set(struct basilisk_swap *swap,int32_t depositflag,int32_t genflag) { - int32_t i,j; //char str[65]; + int32_t j; char coinaddr[64]; + bitcoin_address(coinaddr,swap->bobcoin.pubtype,swap->changermd160,20); if ( genflag != 0 && swap->I.iambob == 0 ) printf("basilisk_bobscripts_set WARNING: alice generating BOB tx\n"); if ( depositflag == 0 ) { swap->bobpayment.I.spendlen = basilisk_bobscript(swap->bobpayment.I.rmd160,swap->bobpayment.redeemscript,&swap->bobpayment.I.redeemlen,swap->bobpayment.spendscript,0,&swap->bobpayment.I.locktime,&swap->bobpayment.I.secretstart,&swap->I,0); bitcoin_address(swap->bobpayment.p2shaddr,swap->bobcoin.p2shtype,swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); - //for (i=0; ibobpayment.redeemlen; i++) - // printf("%02x",swap->bobpayment.redeemscript[i]); - //printf(" <- bobpayment.%d\n",i); + strcpy(swap->bobpayment.I.destaddr,swap->bobpayment.p2shaddr); + int32_t i; for (i=0; ibobpayment.I.redeemlen; i++) + printf("%02x",swap->bobpayment.redeemscript[i]); + printf(" <- bobpayment redeem %d %s\n",i,swap->bobpayment.I.destaddr); if ( genflag != 0 && bits256_nonz(*(bits256 *)swap->I.secretBn256) != 0 && swap->bobpayment.I.datalen == 0 ) { - for (i=0; i<3; i++) + basilisk_rawtx_gen(swap->ctx,"payment",swap->I.started,swap->persistent_pubkey33,1,1,&swap->bobpayment,swap->bobpayment.I.locktime,swap->bobpayment.spendscript,swap->bobpayment.I.spendlen,swap->bobpayment.coin->txfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr); + if ( swap->bobpayment.I.spendlen == 0 || swap->bobpayment.I.datalen == 0 ) { - //if ( swap->bobpayment.txbytes != 0 && swap->bobpayment.I.spendlen != 0 ) - // break; - basilisk_rawtx_gen(swap->ctx,"payment",swap->I.started,swap->persistent_pubkey33,1,1,&swap->bobpayment,swap->bobpayment.I.locktime,swap->bobpayment.spendscript,swap->bobpayment.I.spendlen,swap->bobpayment.coin->txfee,1,0,swap->persistent_privkey); - if ( swap->bobpayment.I.spendlen == 0 || swap->bobpayment.I.datalen == 0 ) - { - printf("error bob generating %p payment.%d\n",swap->bobpayment.txbytes,swap->bobpayment.I.spendlen); - sleep(DEX_SLEEP); - } - else - { - for (j=0; jbobpayment.I.datalen; j++) - printf("%02x",swap->bobpayment.txbytes[j]); - //printf(" <- bobpayment.%d\n",swap->bobpayment.datalen); - //for (j=0; jbobpayment.redeemlen; j++) - // printf("%02x",swap->bobpayment.redeemscript[j]); - //printf(" <- redeem.%d\n",swap->bobpayment.redeemlen); - printf(" <- GENERATED BOB PAYMENT.%d\n",swap->bobpayment.I.datalen); - LP_unspents_mark(swap->bobcoin.symbol,swap->bobpayment.vins); + printf("error bob generating %p payment.%d\n",swap->bobpayment.txbytes,swap->bobpayment.I.spendlen); + sleep(DEX_SLEEP); + } + else + { + for (j=0; jbobpayment.I.datalen; j++) + printf("%02x",swap->bobpayment.txbytes[j]); + printf(" <- bobpayment.%d\n",swap->bobpayment.I.datalen); + for (j=0; jbobpayment.I.redeemlen; j++) + printf("%02x",swap->bobpayment.redeemscript[j]); + printf(" <- redeem.%d\n",swap->bobpayment.I.redeemlen); + printf(" <- GENERATED BOB PAYMENT.%d destaddr.(%s)\n",swap->bobpayment.I.datalen,swap->bobpayment.I.destaddr); + LP_unspents_mark(swap->bobcoin.symbol,swap->bobpayment.vins); + if ( swap->I.iambob != 0 ) basilisk_bobpayment_reclaim(swap,swap->I.callduration); - printf("bobscripts set completed\n"); - return(0); - } + //printf("bobscripts set completed\n"); + return(0); } } } @@ -1397,97 +1207,37 @@ int32_t basilisk_bobscripts_set(struct basilisk_swap *swap,int32_t depositflag,i { swap->bobdeposit.I.spendlen = basilisk_bobscript(swap->bobdeposit.I.rmd160,swap->bobdeposit.redeemscript,&swap->bobdeposit.I.redeemlen,swap->bobdeposit.spendscript,0,&swap->bobdeposit.I.locktime,&swap->bobdeposit.I.secretstart,&swap->I,1); bitcoin_address(swap->bobdeposit.p2shaddr,swap->bobcoin.p2shtype,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); + strcpy(swap->bobdeposit.I.destaddr,swap->bobdeposit.p2shaddr); + int32_t i; for (i=0; ibobdeposit.I.redeemlen; i++) + printf("%02x",swap->bobdeposit.redeemscript[i]); + printf(" <- bobdeposit redeem %d %s\n",i,swap->bobdeposit.I.destaddr); if ( genflag != 0 && (swap->bobdeposit.I.datalen == 0 || swap->bobrefund.I.datalen == 0) ) { - for (i=0; i<3; i++) + basilisk_rawtx_gen(swap->ctx,"deposit",swap->I.started,swap->persistent_pubkey33,1,1,&swap->bobdeposit,swap->bobdeposit.I.locktime,swap->bobdeposit.spendscript,swap->bobdeposit.I.spendlen,swap->bobdeposit.coin->txfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr); + if ( swap->bobdeposit.I.datalen == 0 || swap->bobdeposit.I.spendlen == 0 ) { - //if ( swap->bobdeposit.txbytes != 0 && swap->bobdeposit.I.spendlen != 0 ) - // break; - basilisk_rawtx_gen(swap->ctx,"deposit",swap->I.started,swap->persistent_pubkey33,1,1,&swap->bobdeposit,swap->bobdeposit.I.locktime,swap->bobdeposit.spendscript,swap->bobdeposit.I.spendlen,swap->bobdeposit.coin->txfee,1,0,swap->persistent_privkey); - if ( swap->bobdeposit.I.datalen == 0 || swap->bobdeposit.I.spendlen == 0 ) - { - printf("error bob generating %p deposit.%d\n",swap->bobdeposit.txbytes,swap->bobdeposit.I.spendlen); - sleep(DEX_SLEEP); - } - else - { - for (j=0; jbobdeposit.I.datalen; j++) - printf("%02x",swap->bobdeposit.txbytes[j]); - printf(" <- GENERATED BOB DEPOSIT.%d\n",swap->bobdeposit.I.datalen); - //for (j=0; jbobdeposit.redeemlen; j++) - // printf("%02x",swap->bobdeposit.redeemscript[j]); - //printf(" <- redeem.%d\n",swap->bobdeposit.redeemlen); - //printf("GENERATED BOB DEPOSIT\n"); - LP_unspents_mark(swap->bobcoin.symbol,swap->bobdeposit.vins); + printf("error bob generating %p deposit.%d\n",swap->bobdeposit.txbytes,swap->bobdeposit.I.spendlen); + sleep(DEX_SLEEP); + } + else + { + for (j=0; jbobdeposit.I.datalen; j++) + printf("%02x",swap->bobdeposit.txbytes[j]); + printf(" <- GENERATED BOB DEPOSIT.%d\n",swap->bobdeposit.I.datalen); + LP_unspents_mark(swap->bobcoin.symbol,swap->bobdeposit.vins); + if ( swap->I.iambob != 0 ) basilisk_bobdeposit_refund(swap,swap->I.putduration); - printf("bobscripts set completed\n"); - return(0); - } + printf("bobscripts set completed\n"); + return(0); } } - //for (i=0; ibobdeposit.redeemlen; i++) - // printf("%02x",swap->bobdeposit.redeemscript[i]); - //printf(" <- bobdeposit.%d\n",i); } return(0); } /**/ -struct basilisk_rawtx *LP_swapdata_rawtx(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx) -{ - if ( rawtx->I.datalen != 0 && rawtx->I.datalen <= maxlen ) - { - memcpy(data,rawtx->txbytes,rawtx->I.datalen); - return(rawtx); - } - return(0); -} - -uint32_t LP_swapdata_rawtxsend(struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx,uint32_t nextbits,int32_t suppress_swapsend) -{ - uint8_t sendbuf[32768]; int32_t sendlen; - if ( LP_swapdata_rawtx(swap,data,maxlen,rawtx) != 0 ) - { - if ( bits256_nonz(rawtx->I.signedtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 ) - { - char str[65],str2[65]; - rawtx->I.actualtxid = LP_broadcast(rawtx->name,rawtx->coin->symbol,rawtx->txbytes,rawtx->I.datalen); - if ( bits256_cmp(rawtx->I.actualtxid,rawtx->I.signedtxid) != 0 ) - { - printf("%s rawtxsend %s vs %s\n",rawtx->name,bits256_str(str,rawtx->I.signedtxid),bits256_str(str2,rawtx->I.actualtxid)); - rawtx->I.actualtxid = rawtx->I.signedtxid; - } - if ( bits256_nonz(rawtx->I.actualtxid) != 0 && msgbits != 0 ) - { - sendlen = 0; - sendbuf[sendlen++] = rawtx->I.datalen & 0xff; - sendbuf[sendlen++] = (rawtx->I.datalen >> 8) & 0xff; - sendbuf[sendlen++] = rawtx->I.redeemlen; - memcpy(&sendbuf[sendlen],rawtx->txbytes,rawtx->I.datalen), sendlen += rawtx->I.datalen; - if ( rawtx->I.redeemlen > 0 && rawtx->I.redeemlen < 0x100 ) - { - memcpy(&sendbuf[sendlen],rawtx->redeemscript,rawtx->I.redeemlen); - sendlen += rawtx->I.redeemlen; - } - basilisk_dontforget_update(swap,rawtx); - //printf("sendlen.%d datalen.%d redeemlen.%d\n",sendlen,rawtx->datalen,rawtx->redeemlen); - if ( suppress_swapsend == 0 ) - return(LP_swapsend(swap,msgbits,sendbuf,sendlen,nextbits,rawtx->I.crcs)); - else - { - printf("suppress swapsend %x\n",msgbits); - return(0); - } - } - } - return(nextbits); - } else if ( swap->I.iambob == 0 ) - printf("error from basilisk_swapdata_rawtx.%s %p len.%d\n",rawtx->name,rawtx->txbytes,rawtx->I.datalen); - return(0); -} - -void basilisk_swap_coinaddr(struct basilisk_swap *swap,struct iguana_info *coin,char *coinaddr,uint8_t *data,int32_t datalen) +void LP_swap_coinaddr(struct basilisk_swap *swap,struct iguana_info *coin,char *coinaddr,uint8_t *data,int32_t datalen) { cJSON *txobj,*vouts,*vout,*addresses,*item,*skey; uint8_t extraspace[8192]; bits256 signedtxid; struct iguana_msgtx msgtx; char *addr; int32_t n,m,suppress_pubkeys = 0; if ( (txobj= bitcoin_data2json(coin->pubtype,coin->p2shtype,coin->isPoS,coin->longestchain,&signedtxid,&msgtx,extraspace,sizeof(extraspace),data,datalen,0,suppress_pubkeys)) != 0 ) @@ -1512,59 +1262,7 @@ void basilisk_swap_coinaddr(struct basilisk_swap *swap,struct iguana_info *coin, } } -int32_t basilisk_verify_otherfee(void *ptr,uint8_t *data,int32_t datalen) -{ - struct basilisk_swap *swap = ptr; - // add verification and broadcast - //swap->otherfee.txbytes = calloc(1,datalen); - memcpy(swap->otherfee.txbytes,data,datalen); - swap->otherfee.I.datalen = datalen; - swap->otherfee.I.actualtxid = swap->otherfee.I.signedtxid = bits256_doublesha256(0,data,datalen); - //basilisk_txlog(swap,&swap->otherfee,-1); - return(0); -} - -/* Bob deposit: - OP_IF - OP_CLTV OP_DROP OP_CHECKSIG - OP_ELSE - OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG - OP_ENDIF*/ - -int32_t basilisk_verify_bobdeposit(void *ptr,uint8_t *data,int32_t datalen) -{ - uint8_t userdata[512]; int32_t i,retval,len = 0; static bits256 zero; struct basilisk_swap *swap = ptr; - if ( basilisk_rawtx_spendscript(swap,swap->bobcoin.longestchain,&swap->bobdeposit,0,data,datalen,0) == 0 ) - { - swap->bobdeposit.I.signedtxid = LP_broadcast(swap->bobdeposit.name,swap->bobcoin.symbol,swap->bobdeposit.txbytes,swap->bobdeposit.I.datalen); - if ( bits256_nonz(swap->bobdeposit.I.signedtxid) != 0 ) - swap->depositunconf = 1; - basilisk_dontforget_update(swap,&swap->bobdeposit); - len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); - memcpy(swap->I.userdata_aliceclaim,userdata,len); - swap->I.userdata_aliceclaimlen = len; - if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->aliceclaim,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,1)) == 0 ) - { - for (i=0; ibobdeposit.I.datalen; i++) - printf("%02x",swap->bobdeposit.txbytes[i]); - printf(" <- bobdeposit\n"); - for (i=0; ialiceclaim.I.datalen; i++) - printf("%02x",swap->aliceclaim.txbytes[i]); - printf(" <- aliceclaim\n"); - //basilisk_txlog(swap,&swap->aliceclaim,swap->I.putduration+swap->I.callduration); - return(retval); - } - } - printf("error with bobdeposit\n"); - return(-1); -} - -void basilisk_alicepayment(struct basilisk_swap *swap,struct iguana_info *coin,struct basilisk_rawtx *alicepayment,bits256 pubAm,bits256 pubBn) -{ - alicepayment->I.spendlen = basilisk_alicescript(alicepayment->redeemscript,&alicepayment->I.redeemlen,alicepayment->spendscript,0,alicepayment->I.destaddr,coin->p2shtype,pubAm,pubBn); - basilisk_rawtx_gen(swap->ctx,"alicepayment",swap->I.started,swap->persistent_pubkey33,0,1,alicepayment,alicepayment->I.locktime,alicepayment->spendscript,alicepayment->I.spendlen,coin->txfee,1,0,swap->persistent_privkey); -} - +#ifdef old int32_t basilisk_alicepayment_spend(struct basilisk_swap *swap,struct basilisk_rawtx *dest) { int32_t i,retval; @@ -1581,7 +1279,7 @@ int32_t basilisk_alicepayment_spend(struct basilisk_swap *swap,struct basilisk_r memcpy(swap->I.userdata_bobspend,swap->alicepayment.redeemscript,swap->alicepayment.I.spendlen); swap->I.userdata_bobspendlen = swap->alicepayment.I.spendlen; } - if ( (retval= basilisk_rawtx_sign(swap->alicecoin.symbol,swap->alicecoin.pubtype,swap->alicecoin.p2shtype,swap->alicecoin.isPoS,swap->alicecoin.wiftype,swap,dest,&swap->alicepayment,swap->I.privAm,&swap->I.privBn,0,0,1)) == 0 ) + if ( (retval= basilisk_rawtx_sign(swap->alicecoin.symbol,swap->alicecoin.pubtype,swap->alicecoin.p2shtype,swap->alicecoin.isPoS,swap->alicecoin.wiftype,swap,dest,&swap->alicepayment,swap->I.privAm,&swap->I.privBn,0,0,1,swap->changermd160)) == 0 ) { for (i=0; iI.datalen; i++) printf("%02x",dest->txbytes[i]); @@ -1593,56 +1291,51 @@ int32_t basilisk_alicepayment_spend(struct basilisk_swap *swap,struct basilisk_r } return(-1); } +#endif -int32_t basilisk_verify_alicepaid(void *ptr,uint8_t *data,int32_t datalen) +void basilisk_alicepayment(struct basilisk_swap *swap,struct iguana_info *coin,struct basilisk_rawtx *alicepayment,bits256 pubAm,bits256 pubBn) { - struct basilisk_swap *swap = ptr; - if ( basilisk_rawtx_spendscript(swap,swap->alicecoin.longestchain,&swap->alicepayment,0,data,datalen,0) == 0 ) - { - swap->alicepayment.I.signedtxid = LP_broadcast(swap->alicepayment.name,swap->alicecoin.symbol,swap->alicepayment.txbytes,swap->alicepayment.I.datalen); - if ( bits256_nonz(swap->alicepayment.I.signedtxid) != 0 ) - swap->aliceunconf = 1; - basilisk_dontforget_update(swap,&swap->alicepayment); - return(0); - } - else return(-1); + int32_t i; char coinaddr[64]; + alicepayment->I.spendlen = basilisk_alicescript(alicepayment->redeemscript,&alicepayment->I.redeemlen,alicepayment->spendscript,0,alicepayment->I.destaddr,coin->p2shtype,pubAm,pubBn); + for (i=0; i<33; i++) + printf("%02x",swap->persistent_pubkey33[i]); + printf(" pubkey33, "); + for (i=0; i<20; i++) + printf("%02x",swap->changermd160[i]); + printf(" rmd160, "); + bitcoin_address(coinaddr,coin->pubtype,swap->changermd160,20); + printf("%s suppress.%d fee.%d\n",coinaddr,alicepayment->I.suppress_pubkeys,swap->myfee.I.suppress_pubkeys); + basilisk_rawtx_gen(swap->ctx,"alicepayment",swap->I.started,swap->persistent_pubkey33,0,1,alicepayment,alicepayment->I.locktime,alicepayment->spendscript,alicepayment->I.spendlen,coin->txfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr); } -int32_t basilisk_alicetxs(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) +int32_t basilisk_alicetxs(int32_t pairsock,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) { - int32_t i,retval = -1; - printf("alicetxs\n"); - for (i=0; i<3; i++) + char coinaddr[64]; int32_t i,retval = -1; + if ( swap->alicepayment.I.datalen == 0 ) + basilisk_alicepayment(swap,swap->alicepayment.coin,&swap->alicepayment,swap->I.pubAm,swap->I.pubBn); + if ( swap->alicepayment.I.datalen == 0 || swap->alicepayment.I.spendlen == 0 ) + printf("error alice generating payment.%d\n",swap->alicepayment.I.spendlen); + else { - if ( swap->alicepayment.I.datalen == 0 ) - basilisk_alicepayment(swap,swap->alicepayment.coin,&swap->alicepayment,swap->I.pubAm,swap->I.pubBn); - if ( swap->alicepayment.I.datalen == 0 || swap->alicepayment.I.spendlen == 0 ) - { - printf("error alice generating payment.%d\n",swap->alicepayment.I.spendlen); - sleep(20); - } - else - { - retval = 0; - for (i=0; ialicepayment.I.datalen; i++) - printf("%02x",swap->alicepayment.txbytes[i]); - printf(" ALICE PAYMENT created\n"); - LP_unspents_mark(swap->alicecoin.symbol,swap->alicepayment.vins); - //basilisk_txlog(swap,&swap->alicepayment,-1); - break; - } + retval = 0; + for (i=0; ialicepayment.I.datalen; i++) + printf("%02x",swap->alicepayment.txbytes[i]); + printf(" ALICE PAYMENT created\n"); + LP_unspents_mark(swap->alicecoin.symbol,swap->alicepayment.vins); + //basilisk_txlog(swap,&swap->alicepayment,-1); } if ( swap->myfee.I.datalen == 0 ) { - printf("generate fee\n"); - if ( basilisk_rawtx_gen(swap->ctx,"myfee",swap->I.started,swap->persistent_pubkey33,swap->I.iambob,1,&swap->myfee,0,swap->myfee.spendscript,swap->myfee.I.spendlen,swap->myfee.coin->txfee,1,0,swap->persistent_privkey) == 0 ) + //printf("generate fee\n"); + bitcoin_address(coinaddr,swap->alicecoin.pubtype,swap->changermd160,20); + if ( basilisk_rawtx_gen(swap->ctx,"myfee",swap->I.started,swap->persistent_pubkey33,swap->I.iambob,1,&swap->myfee,0,swap->myfee.spendscript,swap->myfee.I.spendlen,swap->myfee.coin->txfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr) == 0 ) { - swap->I.statebits |= LP_swapdata_rawtxsend(swap,0x80,data,maxlen,&swap->myfee,0x40,0); + swap->I.statebits |= LP_swapdata_rawtxsend(pairsock,swap,0x80,data,maxlen,&swap->myfee,0x40,0); LP_unspents_mark(swap->I.iambob!=0?swap->bobcoin.symbol:swap->alicecoin.symbol,swap->myfee.vins); //basilisk_txlog(swap,&swap->myfee,-1); - for (i=0; imyfee.I.spendlen; i++) + for (i=0; imyfee.I.datalen; i++) printf("%02x",swap->myfee.txbytes[i]); - printf(" fee %p %x\n",swap->myfee.txbytes,swap->I.statebits); + printf(" <- fee state.%x\n",swap->I.statebits); swap->I.statebits |= 0x40; } else @@ -1655,3 +1348,164 @@ int32_t basilisk_alicetxs(struct basilisk_swap *swap,uint8_t *data,int32_t maxle return(0); return(-1); } + +int32_t LP_verify_otherfee(struct basilisk_swap *swap,uint8_t *data,int32_t datalen) +{ + // add verification and broadcast + memcpy(swap->otherfee.txbytes,data,datalen); + swap->otherfee.I.datalen = datalen; + swap->otherfee.I.actualtxid = swap->otherfee.I.signedtxid = bits256_doublesha256(0,data,datalen); + return(0); +} + +int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys) +{ + bits256 otherhash,myhash,txid; int32_t i,offset=0,datalen=0,retval=-1,hexlen,n; uint8_t *data; cJSON *txobj,*skey,*vouts,*vout; char *hexstr; uint32_t quoteid,msgbits; + for (i=0; i<32; i++) + otherhash.bytes[i] = recvbuf[offset++]; + for (i=0; i<32; i++) + myhash.bytes[i] = recvbuf[offset++]; + offset += iguana_rwnum(0,&recvbuf[offset],sizeof(quoteid),"eid); + offset += iguana_rwnum(0,&recvbuf[offset],sizeof(msgbits),&msgbits); + datalen = recvbuf[offset++]; + datalen += (int32_t)recvbuf[offset++] << 8; + if ( datalen > 1024 ) + { + printf("LP_rawtx_spendscript %s datalen.%d too big\n",rawtx->name,datalen); + return(-1); + } + rawtx->I.redeemlen = recvbuf[offset++]; + data = &recvbuf[offset++]; + if ( rawtx->I.redeemlen > 0 && rawtx->I.redeemlen < 0x100 ) + memcpy(rawtx->redeemscript,&data[datalen],rawtx->I.redeemlen); + //printf("recvlen.%d datalen.%d redeemlen.%d\n",recvlen,datalen,rawtx->redeemlen); + if ( rawtx->I.datalen == 0 ) + { + //rawtx->txbytes = calloc(1,datalen); + memcpy(rawtx->txbytes,data,datalen); + rawtx->I.datalen = datalen; + } + else if ( datalen != rawtx->I.datalen || memcmp(rawtx->txbytes,data,datalen) != 0 ) + { + int32_t i; for (i=0; iI.datalen; i++) + printf("%02x",rawtx->txbytes[i]); + printf(" <- rawtx\n"); + printf("%s rawtx data compare error, len %d vs %d <<<<<<<<<< warning\n",rawtx->name,rawtx->I.datalen,datalen); + return(-1); + } + txid = bits256_doublesha256(0,data,datalen); + char str[65]; printf("rawtx.%s txid %s\n",rawtx->name,bits256_str(str,txid)); + if ( bits256_cmp(txid,rawtx->I.actualtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 ) + rawtx->I.actualtxid = txid; + if ( (txobj= bitcoin_data2json(rawtx->coin->pubtype,rawtx->coin->p2shtype,rawtx->coin->isPoS,height,&rawtx->I.signedtxid,&rawtx->msgtx,rawtx->extraspace,sizeof(rawtx->extraspace),data,datalen,0,suppress_pubkeys)) != 0 ) + { + rawtx->I.actualtxid = rawtx->I.signedtxid; + char str[65]; printf("got %s txid.%s (%s)\n",rawtx->name,bits256_str(str,rawtx->I.signedtxid),jprint(txobj,0)); + rawtx->I.locktime = rawtx->msgtx.lock_time; + if ( (vouts= jarray(&n,txobj,"vout")) != 0 && v < n ) + { + vout = jitem(vouts,v); + if ( j64bits(vout,"satoshis") == rawtx->I.amount && (skey= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(skey,"hex")) != 0 ) + { + if ( (hexlen= (int32_t)strlen(hexstr) >> 1) < sizeof(rawtx->spendscript) ) + { + decode_hex(rawtx->spendscript,hexlen,hexstr); + rawtx->I.spendlen = hexlen; + bitcoin_address(rawtx->p2shaddr,rawtx->coin->p2shtype,rawtx->spendscript,hexlen); + //if ( swap != 0 ) + // basilisk_txlog(swap->myinfoptr,swap,rawtx,-1); // bobdeposit, bobpayment or alicepayment + retval = 0; + } + } else printf("%s ERROR.(%s)\n",rawtx->name,jprint(txobj,0)); + } + free_json(txobj); + } + return(retval); +} + +/* Bob deposit: + OP_IF + OP_CLTV OP_DROP OP_CHECKSIG + OP_ELSE + OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG + OP_ENDIF*/ + +int32_t LP_verify_bobdeposit(struct basilisk_swap *swap,uint8_t *data,int32_t datalen) +{ + uint8_t userdata[512]; int32_t i,retval=-1,len = 0; static bits256 zero; + if ( LP_rawtx_spendscript(swap,swap->bobcoin.longestchain,&swap->bobdeposit,0,data,datalen,0) == 0 ) + { + swap->bobdeposit.I.signedtxid = LP_broadcast_tx(swap->bobdeposit.name,swap->bobcoin.symbol,swap->bobdeposit.txbytes,swap->bobdeposit.I.datalen); + if ( bits256_nonz(swap->bobdeposit.I.signedtxid) != 0 ) + swap->depositunconf = 1; + basilisk_dontforget_update(swap,&swap->bobdeposit); + len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); + memcpy(swap->I.userdata_aliceclaim,userdata,len); + swap->I.userdata_aliceclaimlen = len; + retval = 0; + if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->aliceclaim,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,1,swap->changermd160,swap->bobdeposit.I.destaddr)) == 0 ) + { + for (i=0; ibobdeposit.I.datalen; i++) + printf("%02x",swap->bobdeposit.txbytes[i]); + printf(" <- bobdeposit\n"); + for (i=0; ialiceclaim.I.datalen; i++) + printf("%02x",swap->aliceclaim.txbytes[i]); + printf(" <- aliceclaim\n"); + //basilisk_txlog(swap,&swap->aliceclaim,swap->I.putduration+swap->I.callduration); + return(retval); + } else printf("error signing aliceclaim suppress.%d vin.(%s)\n",swap->aliceclaim.I.suppress_pubkeys,swap->bobdeposit.I.destaddr); + } + printf("error with bobdeposit\n"); + return(retval); +} + +int32_t LP_verify_alicepayment(struct basilisk_swap *swap,uint8_t *data,int32_t datalen) +{ + if ( LP_rawtx_spendscript(swap,swap->alicecoin.longestchain,&swap->alicepayment,0,data,datalen,0) == 0 ) + { + swap->alicepayment.I.signedtxid = LP_broadcast_tx(swap->alicepayment.name,swap->alicecoin.symbol,swap->alicepayment.txbytes,swap->alicepayment.I.datalen); + if ( bits256_nonz(swap->alicepayment.I.signedtxid) != 0 ) + swap->aliceunconf = 1; + basilisk_dontforget_update(swap,&swap->alicepayment); + return(0); + } + printf("error validating alicepayment\n"); + return(-1); +} + +int32_t LP_verify_bobpayment(struct basilisk_swap *swap,uint8_t *data,int32_t datalen) +{ + uint8_t userdata[512]; int32_t i,retval=-1,len = 0; bits256 revAm; + memset(revAm.bytes,0,sizeof(revAm)); + if ( LP_rawtx_spendscript(swap,swap->bobcoin.longestchain,&swap->bobpayment,0,data,datalen,0) == 0 ) + { + swap->bobpayment.I.signedtxid = LP_broadcast_tx(swap->bobpayment.name,swap->bobpayment.coin->symbol,swap->bobpayment.txbytes,swap->bobpayment.I.datalen); + if ( bits256_nonz(swap->bobpayment.I.signedtxid) != 0 ) + swap->paymentunconf = 1; + basilisk_dontforget_update(swap,&swap->bobpayment); + for (i=0; i<32; i++) + revAm.bytes[i] = swap->I.privAm.bytes[31-i]; + len = basilisk_swapuserdata(userdata,revAm,0,swap->I.myprivs[0],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); + memcpy(swap->I.userdata_alicespend,userdata,len); + swap->I.userdata_alicespendlen = len; + retval = 0; + 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])); + if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->alicespend,&swap->bobpayment,swap->I.myprivs[0],0,userdata,len,1,swap->changermd160,swap->alicepayment.I.destaddr)) == 0 ) + { + for (i=0; ibobpayment.I.datalen; i++) + printf("%02x",swap->bobpayment.txbytes[i]); + printf(" <- bobpayment\n"); + for (i=0; ialicespend.I.datalen; i++) + printf("%02x",swap->alicespend.txbytes[i]); + printf(" <- alicespend\n\n"); + swap->I.alicespent = 1; + //basilisk_txlog(swap,&swap->alicespend,-1); + return(retval); + } + } + printf("error validating bobpayment\n"); + return(-1); +} diff --git a/iguana/exchanges/LP_utxos.c b/iguana/exchanges/LP_utxos.c new file mode 100644 index 000000000..b10a7d93f --- /dev/null +++ b/iguana/exchanges/LP_utxos.c @@ -0,0 +1,366 @@ + +/****************************************************************************** + * Copyright © 2014-2017 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ +// +// LP_utxos.c +// marketmaker +// + +struct LP_utxoinfo *LP_utxofind(bits256 txid,int32_t vout) +{ + struct LP_utxoinfo *utxo=0; uint8_t key[sizeof(txid) + sizeof(vout)]; + memcpy(key,txid.bytes,sizeof(txid)); + memcpy(&key[sizeof(txid)],&vout,sizeof(vout)); + portable_mutex_lock(&LP_utxomutex); + HASH_FIND(hh,LP_utxoinfos,key,sizeof(key),utxo); + portable_mutex_unlock(&LP_utxomutex); + return(utxo); +} + +cJSON *LP_inventoryjson(cJSON *item,struct LP_utxoinfo *utxo) +{ + jaddstr(item,"coin",utxo->coin); + jaddstr(item,"address",utxo->coinaddr); + jaddbits256(item,"txid",utxo->txid); + jaddnum(item,"vout",utxo->vout); + jaddnum(item,"value",dstr(utxo->satoshis)); + jaddbits256(item,"txid2",utxo->txid2); + jaddnum(item,"vout2",utxo->vout2); + jaddnum(item,"value2",dstr(utxo->satoshis2)); + if ( utxo->swappending != 0 ) + jaddnum(item,"pending",utxo->swappending); + if ( bits256_nonz(utxo->otherpubkey) != 0 ) + jaddbits256(item,"desthash",utxo->otherpubkey); + if ( utxo->pair >= 0 ) + jaddnum(item,"socket",utxo->pair); + if ( utxo->swap != 0 ) + jaddstr(item,"swap","in progress"); + return(item); +} + +cJSON *LP_utxojson(struct LP_utxoinfo *utxo) +{ + cJSON *item = cJSON_CreateObject(); + item = LP_inventoryjson(item,utxo); + jaddstr(item,"ipaddr",utxo->ipaddr); + jaddnum(item,"port",utxo->port); + jaddnum(item,"profit",utxo->profitmargin); + jaddstr(item,"base",utxo->coin); + jaddstr(item,"script",utxo->spendscript); + return(item); +} + +char *LP_utxos(struct LP_peerinfo *mypeer,char *coin,int32_t lastn) +{ + int32_t i,firsti; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray(); + i = 0; + if ( lastn >= mypeer->numutxos ) + firsti = -1; + else firsti = (mypeer->numutxos - lastn); + HASH_ITER(hh,LP_utxoinfos,utxo,tmp) + { + if ( i++ < firsti ) + continue; + if ( coin == 0 || coin[0] == 0 || strcmp(coin,utxo->coin) == 0 ) + { + jaddi(utxosjson,LP_utxojson(utxo)); + } + } + return(jprint(utxosjson,1)); +} + +struct LP_utxoinfo *LP_addutxo(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *coin,bits256 txid,int32_t vout,int64_t satoshis,bits256 deposittxid,int32_t depositvout,int64_t depositsatoshis,char *spendscript,char *coinaddr,char *ipaddr,uint16_t port,double profitmargin) +{ + struct LP_utxoinfo *utxo = 0; + if ( coin == 0 || coin[0] == 0 || spendscript == 0 || spendscript[0] == 0 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(deposittxid) == 0 || vout < 0 || depositvout < 0 || satoshis <= 0 || depositsatoshis <= 0 ) + { + printf("malformed addutxo %d %d %d %d %d %d %d %d %d\n", coin == 0,spendscript == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(deposittxid) == 0,vout < 0,depositvout < 0,satoshis <= 0,depositsatoshis <= 0); + return(0); + } + if ( IAMCLIENT == 0 && strcmp(ipaddr,"127.0.0.1") == 0 ) + { + printf("LP node got localhost utxo\n"); + return(0); + } + if ( (utxo= LP_utxofind(txid,vout)) != 0 ) + { + if ( bits256_cmp(txid,utxo->txid) != 0 || bits256_cmp(deposittxid,utxo->txid2) != 0 || vout != utxo->vout || satoshis != utxo->satoshis || depositvout != utxo->vout2 || depositsatoshis != utxo->satoshis2 || strcmp(coin,utxo->coin) != 0 || strcmp(spendscript,utxo->spendscript) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || strcmp(ipaddr,utxo->ipaddr) != 0 || port != utxo->port ) + { + utxo->errors++; + char str[65],str2[65]; printf("error on subsequent utxo add.(%s v %s) %d %d %d %d %d %d %d %d %d %d %d\n",bits256_str(str,txid),bits256_str(str2,utxo->txid),bits256_cmp(txid,utxo->txid) != 0,bits256_cmp(deposittxid,utxo->txid2) != 0,vout != utxo->vout,satoshis != utxo->satoshis,depositvout != utxo->vout2,depositsatoshis != utxo->satoshis2,strcmp(coin,utxo->coin) != 0,strcmp(spendscript,utxo->spendscript) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,strcmp(ipaddr,utxo->ipaddr) != 0,port != utxo->port); + } + else if ( profitmargin != 0. ) + utxo->profitmargin = profitmargin; + } + else + { + utxo = calloc(1,sizeof(*utxo)); + utxo->pair = -1; + utxo->profitmargin = profitmargin; + strcpy(utxo->ipaddr,ipaddr); + utxo->port = port; + safecopy(utxo->coin,coin,sizeof(utxo->coin)); + safecopy(utxo->coinaddr,coinaddr,sizeof(utxo->coinaddr)); + safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript)); + utxo->txid = txid; + utxo->vout = vout; + utxo->satoshis = satoshis; + utxo->txid2 = deposittxid; + utxo->vout2 = depositvout; + utxo->satoshis2 = depositsatoshis; + memcpy(utxo->key,txid.bytes,sizeof(txid)); + memcpy(&utxo->key[sizeof(txid)],&vout,sizeof(vout)); + portable_mutex_lock(&LP_utxomutex); + HASH_ADD_KEYPTR(hh,LP_utxoinfos,utxo->key,sizeof(utxo->key),utxo); + if ( mypeer != 0 ) + mypeer->numutxos++; + portable_mutex_unlock(&LP_utxomutex); + if ( mypubsock >= 0 ) + LP_send(mypubsock,jprint(LP_utxojson(utxo),1),1); + char str[65],str2[65]; printf("amclient.%d %s:%u %s LP_addutxo.(%.8f %.8f) numutxos.%d %s %s\n",IAMCLIENT,ipaddr,port,utxo->coin,dstr(satoshis),dstr(depositsatoshis),mypeer!=0?mypeer->numutxos:0,bits256_str(str,utxo->txid),bits256_str(str2,txid)); + } + return(utxo); +} + +int32_t LP_utxosparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now) +{ + struct LP_peerinfo *peer,*destpeer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; bits256 txid; struct LP_utxoinfo *utxo; + if ( amclient != 0 ) + { + printf("LP_utxosparse not for clientside\n"); + return(-1); + } + if ( (array= cJSON_Parse(retstr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; ilasttime = now; + } + } + } + if ( (destpeer= LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport)) != 0 ) + { + destpeer->numutxos = n; + if ( destpeer->numutxos < n ) + { + //destpeer->numutxos = n; + //printf("got.(%s) from %s numutxos.%d\n",retstr,destpeer->ipaddr,destpeer->numutxos); + } + } + } + free_json(array); + } + return(n); +} + +void LP_utxosquery(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *coin,int32_t lastn,char *myipaddr,uint16_t myport,double myprofit) +{ + char *retstr; struct LP_peerinfo *peer; int32_t i,firsti; uint32_t now; + if ( amclient != 0 ) + { + printf("LP_utxosquery not for clientside\n"); + return; + } + peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); + if ( mypeer == 0 ) //(peer != 0 && peer->errors > 0) || + return; + if ( coin == 0 ) + coin = ""; + if ( (retstr= issue_LP_getutxos(destipaddr,destport,coin,lastn,myipaddr,myport,myprofit,mypeer->numpeers,mypeer->numutxos)) != 0 ) + { + now = (uint32_t)time(NULL); + LP_utxosparse(amclient,mypeer,mypubsock,destipaddr,destport,retstr,now); + free(retstr); + i = 0; + if ( lastn >= mypeer->numutxos ) + firsti = -1; + else firsti = (mypeer->numutxos - lastn); + /*HASH_ITER(hh,LP_utxoinfos,utxo,tmp) + { + if ( i++ < firsti ) + continue; + if ( utxo->lasttime != now && strcmp(utxo->ipaddr,"127.0.0.1") != 0 ) + { + char str[65]; printf("{%s:%u %s} ",utxo->ipaddr,utxo->port,bits256_str(str,utxo->txid)); + flag++; + if ( (retstr= issue_LP_notifyutxo(destipaddr,destport,utxo)) != 0 ) + free(retstr); + } + } + if ( flag != 0 ) + printf(" <- missing utxos\n");*/ + } else if ( peer != 0 ) + peer->errors++; +} + +char *LP_inventory(char *symbol) +{ + struct LP_utxoinfo *utxo,*tmp; char *myipaddr; cJSON *array = cJSON_CreateArray(); + if ( LP_mypeer != 0 ) + myipaddr = LP_mypeer->ipaddr; + else myipaddr = "127.0.0.1"; + HASH_ITER(hh,LP_utxoinfos,utxo,tmp) + { + if ( strcmp(symbol,utxo->coin) == 0 && (IAMCLIENT != 0 || strcmp(utxo->ipaddr,myipaddr) == 0) ) + jaddi(array,LP_inventoryjson(cJSON_CreateObject(),utxo)); + } + return(jprint(array,1)); +} + +int32_t LP_maxvalue(uint64_t *values,int32_t n) +{ + int32_t i,maxi = -1; uint64_t maxval = 0; + for (i=0; i maxval ) + { + maxi = i; + maxval = values[i]; + } + return(maxi); +} + +int32_t LP_nearestvalue(uint64_t *values,int32_t n,uint64_t targetval) +{ + int32_t i,mini = -1; int64_t dist; uint64_t mindist = (1 << 31); + for (i=0; i= 0 && dist < mindist ) + { + mini = i; + mindist = dist; + } + } + return(mini); +} + +uint64_t LP_privkey_init(struct LP_peerinfo *mypeer,int32_t mypubsock,char *symbol,char *passphrase,char *wifstr,int32_t amclient) +{ + static uint32_t counter; + char coinaddr[64],*script; struct LP_utxoinfo *utxo; cJSON *array,*item,*retjson; bits256 userpass,userpub,txid,deposittxid; int32_t used,i,n,vout,depositvout; uint64_t *values,satoshis,depositval,targetval,value,total = 0; bits256 privkey,pubkey; uint8_t pubkey33[33],tmptype,rmd160[20]; struct iguana_info *coin = LP_coinfind(symbol); + if ( coin == 0 ) + { + printf("cant add privkey for %s, coin not active\n",symbol); + return(0); + } + if ( passphrase != 0 ) + conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); + else privkey = iguana_wif2privkey(wifstr); + iguana_priv2pub(pubkey33,coinaddr,privkey,coin->pubtype); + if ( strcmp("BTC",symbol) == 0 ) + strcpy(BTCADDR,coinaddr); + else if ( strcmp("KMD",symbol) == 0 ) + strcpy(KMDADDR,coinaddr); + if ( counter == 0 ) + { + char tmpstr[128]; + counter++; + bitcoin_priv2wif(USERPASS_WIFSTR,privkey,188); + bitcoin_priv2wif(tmpstr,privkey,coin->wiftype); + conv_NXTpassword(userpass.bytes,pubkey.bytes,(uint8_t *)tmpstr,(int32_t)strlen(tmpstr)); + userpub = curve25519(userpass,curve25519_basepoint9()); + printf("userpass.(%s)\n",bits256_str(USERPASS,userpub)); + printf("%s (%s) %d wif.(%s) (%s)\n",symbol,coinaddr,coin->pubtype,tmpstr,passphrase); + if ( (retjson= LP_importprivkey(coin->symbol,tmpstr,coinaddr,-1)) != 0 ) + printf("importprivkey -> (%s)\n",jprint(retjson,1)); + } + bitcoin_addr2rmd160(&tmptype,rmd160,coinaddr); + LP_privkeyadd(privkey,rmd160); + if ( (array= LP_listunspent(symbol,coinaddr)) != 0 ) + { + if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) + { + values = calloc(n,sizeof(*values)); + for (i=0; i= 0 ) + { + item = jitem(array,i); + deposittxid = jbits256(item,"txid"); + depositvout = juint(item,"vout"); + script = jstr(item,"scriptPubKey"); + depositval = values[i]; + values[i] = 0, used++; + if ( amclient != 0 ) + targetval = (depositval / 776) + 50000; + else targetval = (depositval / 9) * 8; + //printf("i.%d %.8f target %.8f\n",i,dstr(depositval),dstr(targetval)); + if ( (i= LP_nearestvalue(values,n,targetval)) >= 0 ) + { + item = jitem(array,i); + txid = jbits256(item,"txid"); + vout = juint(item,"vout"); + if ( jstr(item,"scriptPubKey") != 0 && strcmp(script,jstr(item,"scriptPubKey")) == 0 ) + { + value = values[i]; + values[i] = 0, used++; + if ( amclient == 0 ) + { + if ( (utxo= LP_addutxo(amclient,mypeer,mypubsock,symbol,txid,vout,value,deposittxid,depositvout,depositval,script,coinaddr,LP_peerinfos[0].ipaddr,LP_peerinfos[0].port,LP_peerinfos[0].profitmargin)) != 0 ) + utxo->mypub = curve25519(privkey,curve25519_basepoint9()); + } + else + { + if ( (utxo= LP_addutxo(amclient,mypeer,mypubsock,symbol,deposittxid,depositvout,depositval,txid,vout,value,script,coinaddr,"127.0.0.1",0,0)) != 0 ) + utxo->mypub = curve25519(privkey,curve25519_basepoint9()); + } + total += value; + } + } + } else break; + } + free(values); + } + free_json(array); + } + return(total); +} + +void LP_privkey_updates(struct LP_peerinfo *mypeer,int32_t pubsock,char *passphrase,int32_t amclient) +{ + int32_t i; + for (i=0; i (b) ? (a) : (b)) char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port); #include "stats.c" -#include "LP_prices.c" +void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32]); #if defined(__APPLE__) || defined(WIN32) || defined(USE_STATIC_NANOMSG) #include "../../crypto777/nanosrc/nn.h" @@ -35,6 +35,7 @@ char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port); #include "../../crypto777/nanosrc/pipeline.h" #include "../../crypto777/nanosrc/reqrep.h" #include "../../crypto777/nanosrc/tcp.h" +#include "../../crypto777/nanosrc/pair.h" #else #include "/usr/local/include/nanomsg/nn.h" #include "/usr/local/include/nanomsg/bus.h" @@ -42,6 +43,7 @@ char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port); #include "/usr/local/include/nanomsg/pipeline.h" #include "/usr/local/include/nanomsg/reqrep.h" #include "/usr/local/include/nanomsg/tcp.h" +#include "/usr/local/include/nanomsg/pair.h" #endif char DEX_baseaddr[64],DEX_reladdr[64]; @@ -168,13 +170,13 @@ char *iguana_walletpassphrase(char *passphrase,int32_t timeout) return(bitcoind_RPC(0,"",url,0,"walletpassphrase",postdata)); } -char *iguana_listunspent(char *coin,char *coinaddr) +/*char *iguana_listunspent(char *coin,char *coinaddr) { char url[512],postdata[1024]; sprintf(url,"%s/coin=%s&agent=bitcoinrpc&method=listunspent?",IGUANA_URL,coin); sprintf(postdata,"[\"%s\"]",coinaddr); return(bitcoind_RPC(0,"",url,0,"listunspent",postdata)); -} +}*/ /*char *issue_LP_intro(char *destip,uint16_t destport,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers) { @@ -678,10 +680,43 @@ int32_t marketmaker_spread(char *exchange,char *base,char *rel,double bid,double return(n); } -void marketmaker(double minask,double maxbid,char *baseaddr,char *reladdr,double start_BASE,double start_REL,double profitmargin,double maxexposure,double ratioincr,char *exchange,char *name,char *base,char *rel) +double marketmaker_updateprice(char *name,char *base,char *rel,double theoretical,double *incrp) { static uint32_t counter; - cJSON *fiatjson; char *retstr; double bid,ask,start_DEXbase,start_DEXrel,USD_average=0.,DEX_base = 0.,DEX_rel = 0.,balance_base=0.,balance_rel=0.,mmbid,mmask,usdprice=0.,CMC_average=0.,aveprice,incr,pendingbids,pendingasks,buyvol,sellvol,bidincr,askincr,filledprice,avebid=0.,aveask=0.,val,changes[3],highbid=0.,lowask=0.,theoretical = 0.; uint32_t lasttime = 0; + cJSON *fiatjson; double USD_average=0.,usdprice=0.,CMC_average=0.,avebid=0.,aveask=0.,val,changes[3],highbid=0.,lowask=0.; + if ( (val= get_theoretical(&avebid,&aveask,&highbid,&lowask,&CMC_average,changes,name,base,rel,&USD_average)) != 0. ) + { + if ( theoretical == 0. ) + { + theoretical = val; + if ( *incrp > 2 ) + { + *incrp = (int32_t)*incrp; + *incrp += 0.777; + } + } else theoretical = (theoretical + val) * 0.5; + if ( (counter++ % 12) == 0 ) + { + if ( USD_average > SMALLVAL && CMC_average > SMALLVAL && theoretical > SMALLVAL ) + { + usdprice = USD_average * (theoretical / CMC_average); + printf("USD %.4f <- (%.6f * (%.8f / %.8f))\n",usdprice,USD_average,theoretical,CMC_average); + PAXPRICES[0] = usdprice; + if ( (fiatjson= yahoo_allcurrencies()) != 0 ) + { + marketmaker_fiatupdate(fiatjson); + free_json(fiatjson); + } + } + } + LP_priceupdate(base,rel,theoretical,avebid,aveask,highbid,lowask,PAXPRICES); + } + return(theoretical); +} + +void marketmaker(double minask,double maxbid,char *baseaddr,char *reladdr,double start_BASE,double start_REL,double profitmargin,double maxexposure,double ratioincr,char *exchange,char *name,char *base,char *rel) +{ + char *retstr; double bid,ask,start_DEXbase,start_DEXrel,DEX_base = 0.,DEX_rel = 0.,balance_base=0.,balance_rel=0.,mmbid,mmask,aveprice,incr,pendingbids,pendingasks,buyvol,sellvol,bidincr,askincr,filledprice,avebid=0.,aveask=0.,highbid=0.,lowask=0.,theoretical = 0.; uint32_t lasttime = 0; incr = maxexposure * ratioincr; buyvol = sellvol = 0.; start_DEXbase = dex_balance(base,baseaddr); @@ -690,34 +725,10 @@ void marketmaker(double minask,double maxbid,char *baseaddr,char *reladdr,double { if ( time(NULL) > lasttime+60 ) { - if ( (val= get_theoretical(&avebid,&aveask,&highbid,&lowask,&CMC_average,changes,name,base,rel,&USD_average)) != 0. ) + if ( (theoretical= marketmaker_updateprice(name,base,rel,theoretical,&incr)) != 0. ) { - if ( theoretical == 0. ) - { - theoretical = val; - incr /= theoretical; + if ( lasttime == 0 ) maxexposure /= theoretical; - if ( incr > 2 ) - { - incr = (int32_t)incr; - incr += 0.777; - } - } else theoretical = (theoretical + val) * 0.5; - if ( (counter++ % 12) == 0 ) - { - if ( USD_average > SMALLVAL && CMC_average > SMALLVAL && theoretical > SMALLVAL ) - { - usdprice = USD_average * (theoretical / CMC_average); - printf("USD %.4f <- (%.6f * (%.8f / %.8f))\n",usdprice,USD_average,theoretical,CMC_average); - PAXPRICES[0] = usdprice; - if ( (fiatjson= yahoo_allcurrencies()) != 0 ) - { - marketmaker_fiatupdate(fiatjson); - free_json(fiatjson); - } - } - } - LP_priceupdate(base,rel,theoretical,avebid,aveask,highbid,lowask,PAXPRICES); } if ( strcmp(exchange,"bittrex") == 0 ) { @@ -796,30 +807,60 @@ void marketmaker(double minask,double maxbid,char *baseaddr,char *reladdr,double void LP_main(void *ptr) { - double profitmargin = *(double *)ptr; - LPinit(7779,7780,7781,profitmargin); + char *passphrase; double profitmargin; cJSON *argjson = ptr; + if ( (passphrase= jstr(argjson,"passphrase")) != 0 ) + { + profitmargin = jdouble(argjson,"profitmargin"); + LPinit(7779,7780,7781,profitmargin,passphrase,jint(argjson,"client"),jstr(argjson,"userhome")); + } } int main(int argc, const char * argv[]) { char *base,*rel,*name,*exchange,*apikey,*apisecret,*blocktrail,*retstr,*baseaddr,*reladdr,*passphrase; - double profitmargin,maxexposure,incrratio,start_rel,start_base,minask,maxbid; - cJSON *retjson,*loginjson; int32_t i; + double profitmargin,maxexposure,incrratio,start_rel,start_base,minask,maxbid,incr,theoretical = 0.; + cJSON *retjson,*loginjson,*matchjson; int32_t i; if ( argc > 1 && (retjson= cJSON_Parse(argv[1])) != 0 ) { - minask = jdouble(retjson,"minask"); - maxbid = jdouble(retjson,"maxbid"); - profitmargin = jdouble(retjson,"profitmargin"); - if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_main,(void *)&profitmargin) != 0 ) + if ( (passphrase= jstr(retjson,"passphrase")) == 0 ) + jaddstr(retjson,"passphrase","test"); + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_main,(void *)retjson) != 0 ) { - printf("error launching LP_main %f\n",profitmargin); + printf("error launching LP_main (%s)\n",jprint(retjson,0)); exit(-1); - } getchar(); + } else printf("(%s) launched.(%s)\n",argv[1],passphrase); + if ( (0) && (retstr= basilisk_swaplist()) != 0 ) + { + printf("%s\ngetchar to continue\n",retstr); + getchar(); + free(retstr); + } + incr = 100.; + while ( (0) && IAMCLIENT != 0 ) + { + theoretical = marketmaker_updateprice("komodo","REVS","KMD",theoretical,&incr); + sleep(3); + LP_privkey_updates(0,-1,passphrase,1); + if ( jint(retjson,"client") != 0 ) + { + struct LP_utxoinfo *utxo,*utmp; + HASH_ITER(hh,LP_utxoinfos,utxo,utmp) + { + if ( strcmp(utxo->coin,"REVS") == 0 && (matchjson= LP_autotrade(utxo,"KMD",0.)) != 0 ) + printf("bestprice (%s)\n",jprint(matchjson,1)); + } + } + sleep(1000); + } + while ( 1 ) + sleep(1); + profitmargin = jdouble(retjson,"profitmargin"); + minask = jdouble(retjson,"minask"); + maxbid = jdouble(retjson,"maxbid"); maxexposure = jdouble(retjson,"maxexposure"); incrratio = jdouble(retjson,"lotratio"); start_base = jdouble(retjson,"start_base"); start_rel = jdouble(retjson,"start_rel"); - passphrase = jstr(retjson,"passphrase"); apikey = jstr(retjson,"apikey"); apisecret = jstr(retjson,"apisecret"); base = jstr(retjson,"base"); diff --git a/iguana/exchanges/myprice b/iguana/exchanges/myprice new file mode 100755 index 000000000..cdb93dabc --- /dev/null +++ b/iguana/exchanges/myprice @@ -0,0 +1,2 @@ +source userpass +curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"myprice\",\"base\":\"REVS\",\"rel\":\"KMD\"}" diff --git a/iguana/exchanges/orderbook b/iguana/exchanges/orderbook new file mode 100755 index 000000000..4d2367a42 --- /dev/null +++ b/iguana/exchanges/orderbook @@ -0,0 +1,2 @@ +source userpass +curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"orderbook\",\"base\":\"REVS\",\"rel\":\"KMD\"}" diff --git a/iguana/exchanges/randval b/iguana/exchanges/randval new file mode 100644 index 000000000..ca5c33f4d --- /dev/null +++ b/iguana/exchanges/randval @@ -0,0 +1 @@ +export randval="" diff --git a/iguana/exchanges/run b/iguana/exchanges/run new file mode 100755 index 000000000..ccc62231a --- /dev/null +++ b/iguana/exchanges/run @@ -0,0 +1,2 @@ +source randval +pkill -15 marketmaker; git pull; cd ..; ./m_mm; ./marketmaker "{\"profitmargin\":0.01,\"passphrase\":\"$randval\"}" & diff --git a/iguana/exchanges/setprice b/iguana/exchanges/setprice new file mode 100755 index 000000000..e5a9c3c9c --- /dev/null +++ b/iguana/exchanges/setprice @@ -0,0 +1,2 @@ +source userpass +curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"setprice\",\"base\":\"REVS\",\"rel\":\"KMD\",\"price\":1.234}" diff --git a/iguana/exchanges/userpass b/iguana/exchanges/userpass new file mode 100644 index 000000000..1a8a9ad5a --- /dev/null +++ b/iguana/exchanges/userpass @@ -0,0 +1 @@ +export userpass="" diff --git a/iguana/m_mm b/iguana/m_mm index 2e310704b..2a2f6c130 100755 --- a/iguana/m_mm +++ b/iguana/m_mm @@ -1,2 +1,2 @@ cd secp256k1; ./m_unix; cd .. -gcc -o marketmaker -I../crypto777 exchanges/mm.c mini-gmp.c secp256k1.o ../agents/libcrypto777.a -lnanomsg -lcurl -lpthread -lm +gcc -g -o marketmaker -I../crypto777 exchanges/mm.c mini-gmp.c secp256k1.o ../agents/libcrypto777.a -lnanomsg -lcurl -lpthread -lm diff --git a/iguana/main.c b/iguana/main.c index 9a224d3d2..335d68baa 100755 --- a/iguana/main.c +++ b/iguana/main.c @@ -2056,10 +2056,12 @@ FOUR_STRINGS(SuperNET,login,handle,password,permanentfile,passphrase) void komodo_ICO_batch(cJSON *array,int32_t batchid) { int32_t i,n,iter; cJSON *item; uint64_t kmdamount,revsamount; char *coinaddr,cmd[512]; double totalKMD,totalREVS; struct supernet_info *myinfo = SuperNET_MYINFO(0); + if ( myinfo->rpcport == 0 ) + myinfo->rpcport = 7778; if ( (n= cJSON_GetArraySize(array)) > 0 ) { totalKMD = totalREVS = 0; - for (iter=3; iter<4; iter++) + for (iter=0; iter<1; iter++) for (i=0; i