ca333
8 years ago
committed by
GitHub
184 changed files with 28844 additions and 987 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
@ -0,0 +1,2 @@ |
|||
curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"COQUI.conf\",\"path\":\"${HOME#"/"}/.komodo/COQUI\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":0,\"VALIDATE\":1,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"COQUI\",\"name\":\"COQUI\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"dd5ce076\",\"p2p\":14275,\"rpc\":14276,\"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\"}" |
|||
|
@ -1 +1 @@ |
|||
curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"MESH.conf\",\"path\":\"${HOME#"/"}/.komodo/MESH\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":0,\"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\":\"c28227c2\",\"p2p\":11940,\"rpc\":11941,\"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:7778" --data "{\"conf\":\"MESH.conf\",\"path\":\"${HOME#"/"}/.komodo/MESH\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":0,\"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\"}" |
|||
|
@ -1 +0,0 @@ |
|||
curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"WIRELESS.conf\",\"path\":\"${HOME#"/"}/.komodo/WIRELESS\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":0,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"WIRELESS\",\"name\":\"WIRELESS\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"62071ed3\",\"p2p\":11666,\"rpc\":11667,\"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\"}" |
@ -0,0 +1 @@ |
|||
curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"WLC.conf\",\"path\":\"${HOME#"/"}/.komodo/WLC\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":0,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"WLC\",\"name\":\"WLC\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"7ec1c253\",\"p2p\":12166,\"rpc\":12167,\"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\"}" |
@ -0,0 +1,2 @@ |
|||
curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"bitcoin.conf\",\"path\":\"/${HOME#"/"}/Library/Application\ Support/Bitcoin\",\"prefetchlag\":-1,\"poll\":1,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"newcoin\":\"BTC\",\"startpend\":64,\"endpend\":64,\"services\":0,\"maxpeers\":512,\"RELAY\":-1,\"VALIDATE\":0,\"portp2p\":8333,\"minconfirms\":1}" |
|||
|
@ -0,0 +1 @@ |
|||
curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"COQUI.conf\",\"path\":\"${HOME#"/"}/.komodo/COQUI\",\"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\":\"COQUI\",\"name\":\"COQUI\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"fa05f107\",\"p2p\":14275,\"rpc\":14276,\"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\"}" |
@ -1,4 +1,4 @@ |
|||
#!/bin/bash |
|||
|
|||
curl --url "http://127.0.0.1:7778" --data "{\"RELAY\":1,\"VALIDATE\":1,\"prefetchlag\":-1,\"poll\":10,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":68,\"endpend\":68,\"services\":129,\"maxpeers\":256,\"newcoin\":\"LTC\",\"name\":\"Litecoin\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"fbc0b6db\",\"p2p\":9333,\"rpc\":9332,\"pubval\":48,\"p2shval\":5,\"wifval\":176,\"txfee_satoshis\":\"100000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2\",\"genesis\":{\"version\":1,\"timestamp\":1317972665,\"nBits\":\"1e0ffff0\",\"nonce\":2084524493,\"merkle_root\":\"97ddfbbae6be97fd6cdf3e7ca13232a3afff2353e29badfab7f73011edd4ced9\"},\"alertpubkey\":\"040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9\",\"protover\":70002}" |
|||
curl --url "http://127.0.0.1:7778" --data "{\"RELAY\":1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":10,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":68,\"endpend\":68,\"services\":129,\"maxpeers\":256,\"newcoin\":\"LTC\",\"name\":\"Litecoin\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"fbc0b6db\",\"p2p\":9333,\"rpc\":9332,\"pubval\":48,\"p2shval\":5,\"wifval\":176,\"txfee_satoshis\":\"100000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2\",\"genesis\":{\"version\":1,\"timestamp\":1317972665,\"nBits\":\"1e0ffff0\",\"nonce\":2084524493,\"merkle_root\":\"97ddfbbae6be97fd6cdf3e7ca13232a3afff2353e29badfab7f73011edd4ced9\"},\"alertpubkey\":\"040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9\",\"protover\":70002}" |
|||
|
|||
|
@ -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\"}" |
|||
|
@ -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\"}" |
|||
|
@ -0,0 +1,2 @@ |
|||
curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"komodo.conf\",\"path\":\"/${HOME#"/"}/Library/Application\ Support/Komodo\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":10,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":8,\"endpend\":8,\"services\":0,\"maxpeers\":32,\"newcoin\":\"KMD\",\"name\":\"Komodo\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"f9eee48d\",\"p2p\":7770,\"rpc\":7771,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0}" |
|||
|
@ -0,0 +1,4 @@ |
|||
#!/bin/bash |
|||
|
|||
curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"litecoin.conf\",\"path\":\"${HOME#"/"}/.litecoin\",\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":10,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":68,\"endpend\":68,\"services\":129,\"maxpeers\":256,\"newcoin\":\"LTC\",\"name\":\"Litecoin\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"fbc0b6db\",\"p2p\":9333,\"rpc\":9332,\"pubval\":48,\"p2shval\":5,\"wifval\":176,\"txfee_satoshis\":\"100000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2\",\"genesis\":{\"version\":1,\"timestamp\":1317972665,\"nBits\":\"1e0ffff0\",\"nonce\":2084524493,\"merkle_root\":\"97ddfbbae6be97fd6cdf3e7ca13232a3afff2353e29badfab7f73011edd4ced9\"},\"alertpubkey\":\"040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9\",\"protover\":70002}" |
|||
|
@ -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\":\"c28227c2\",\"p2p\":11940,\"rpc\":11941,\"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\"}" |
|||
|
@ -0,0 +1,3 @@ |
|||
~/komodo/src/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\"}" |
|||
|
@ -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\"}" |
|||
|
@ -1 +0,0 @@ |
|||
curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"WIRELESS.conf\",\"path\":\"${HOME#"/"}/.komodo/WIRELESS\",\"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\":\"WIRELESS\",\"name\":\"WIRELESS\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"62071ed3\",\"p2p\":11666,\"rpc\":11667,\"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\"}" |
@ -0,0 +1 @@ |
|||
curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"WLC.conf\",\"path\":\"${HOME#"/"}/.komodo/WLC\",\"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\":\"WLC\",\"name\":\"WLC\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"7ec1c253\",\"p2p\":12166,\"rpc\":12167,\"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\"}" |
@ -0,0 +1,957 @@ |
|||
/******************************************************************************
|
|||
* 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. * |
|||
* * |
|||
******************************************************************************/ |
|||
//
|
|||
// DEXstats.h
|
|||
// marketmaker
|
|||
//
|
|||
|
|||
#ifndef DEXstats_h |
|||
#define DEXstats_h |
|||
|
|||
#define LEFTMARGIN 40 |
|||
#define MAX_SPLINES 1024 |
|||
#define MAX_LOOKAHEAD 7 |
|||
|
|||
struct stats_spline { char name[64]; int32_t splineid,lasti,basenum,num,firstx,dispincr,spline32[MAX_SPLINES][4]; uint32_t utc32[MAX_SPLINES]; int64_t spline64[MAX_SPLINES][4]; double dSplines[MAX_SPLINES][4],pricevals[MAX_SPLINES+MAX_LOOKAHEAD],lastutc,lastval,aveslopeabs; }; |
|||
|
|||
#define _extrapolate_Spline(Splines,gap) ((double)(Splines)[0] + ((gap) * ((double)(Splines)[1] + ((gap) * ((double)(Splines)[2] + ((gap) * (double)(Splines)[3])))))) |
|||
#define _extrapolate_Slope(Splines,gap) ((double)(Splines)[1] + ((gap) * ((double)(Splines)[2] + ((gap) * (double)(Splines)[3])))) |
|||
|
|||
#define dto64(x) ((int64_t)((x) * (double)SATOSHIDEN * SATOSHIDEN)) |
|||
#define dto32(x) ((int32_t)((x) * (double)SATOSHIDEN)) |
|||
#define i64tod(x) ((double)(x) / ((double)SATOSHIDEN * SATOSHIDEN)) |
|||
#define i32tod(x) ((double)(x) / (double)SATOSHIDEN) |
|||
#define _extrapolate_spline64(spline64,gap) ((double)i64tod((spline64)[0]) + ((gap) * ((double)i64tod(.001*.001*(spline64)[1]) + ((gap) * ((double)i64tod(.001*.001*.001*.001*(spline64)[2]) + ((gap) * (double)i64tod(.001*.001*.001*.001*.001*.001*(spline64)[3]))))))) |
|||
#define _extrapolate_spline32(spline32,gap) ((double)i32tod((spline32)[0]) + ((gap) * ((double)i32tod(.001*.001*(spline32)[1]) + ((gap) * ((double)i32tod(.001*.001*.001*.001*(spline32)[2]) + ((gap) * (double)i32tod(.001*.001*.001*.001*.001*.001*(spline32)[3]))))))) |
|||
|
|||
uint32_t forex_colors[16]; |
|||
double Display_scale = 0.25; |
|||
|
|||
struct DEXstats_disp { double pricesum,volumesum; }; |
|||
|
|||
struct DEXstats_pricepoint |
|||
{ |
|||
double price,volume; |
|||
uint32_t height; |
|||
uint16_t seconds; |
|||
int8_t hour,dir; |
|||
}; |
|||
|
|||
struct DEXstats_pairinfo |
|||
{ |
|||
char dest[16]; |
|||
int32_t numprices; |
|||
struct DEXstats_pricepoint *prices; |
|||
}; |
|||
|
|||
struct DEXstats_datenuminfo |
|||
{ |
|||
int32_t numpairs,datenum; |
|||
struct DEXstats_pairinfo *pairs; |
|||
}; |
|||
|
|||
struct DEXstats_priceinfo |
|||
{ |
|||
char symbol[16]; |
|||
int32_t firstdatenum,numdates; |
|||
struct DEXstats_datenuminfo *dates; |
|||
} Prices[1024]; |
|||
int32_t Num_priceinfos; |
|||
|
|||
void stats_pricepoint(int32_t dir,struct DEXstats_pricepoint *ptr,uint8_t hour,uint16_t seconds,int32_t height,double volume,double price) |
|||
{ |
|||
ptr->price = price; |
|||
ptr->volume = volume; |
|||
ptr->height = height; |
|||
ptr->hour = hour; |
|||
ptr->dir = dir; |
|||
ptr->seconds = seconds; |
|||
} |
|||
|
|||
void stats_pairupdate(int32_t dir,struct DEXstats_datenuminfo *date,char *symbol,char *dest,int32_t datenum,int32_t hour,int32_t seconds,int32_t height,double volume,double price) |
|||
{ |
|||
int32_t i; struct DEXstats_pairinfo *pair = 0; |
|||
if ( date->datenum != datenum || seconds < 0 || seconds >= 3600 || hour < 0 || hour >= 24 ) |
|||
{ |
|||
printf("date->datenum %d != %d? hour.%d seconds.%d\n",date->datenum,datenum,hour,seconds); |
|||
return; |
|||
} |
|||
//printf("%d numpairs.%d %p %p\n",date->datenum,date->numpairs,date,date->pairs);
|
|||
for (i=0; i<date->numpairs; i++) |
|||
if ( strcmp(dest,date->pairs[i].dest) == 0 ) |
|||
{ |
|||
pair = &date->pairs[i]; |
|||
break; |
|||
} |
|||
if ( date->pairs == 0 || i == date->numpairs ) |
|||
{ |
|||
date->pairs = realloc(date->pairs,sizeof(*date->pairs) * (date->numpairs + 1)); |
|||
pair = &date->pairs[date->numpairs++]; |
|||
memset(pair,0,sizeof(*pair)); |
|||
strcpy(pair->dest,dest); |
|||
printf("%d new pair.%d (%s) -> dest.(%s)\n",date->datenum,date->numpairs,symbol,dest); |
|||
} |
|||
pair->prices = realloc(pair->prices,sizeof(*pair->prices) * (pair->numprices+1)); |
|||
stats_pricepoint(dir,&pair->prices[pair->numprices++],hour,seconds,height,volume,price); |
|||
//printf("(%s/%s).%d numprices.%d h.%d s.%-4d %.8f %.6f\n",symbol,dest,date->datenum,pair->numprices,hour,seconds,price,volume);
|
|||
} |
|||
|
|||
void stats_datenumupdate(int32_t dir,struct DEXstats_priceinfo *pp,int32_t datenum,int32_t hour,int32_t seconds,int32_t height,double volume,char *dest,double price) |
|||
{ |
|||
int32_t offset,i,n; struct DEXstats_datenuminfo *date; |
|||
if ( (offset= datenum - pp->firstdatenum) < 0 ) |
|||
{ |
|||
printf("illegal datenum.%d for %s when 1st.%d\n",datenum,pp->symbol,pp->firstdatenum); |
|||
return; |
|||
} |
|||
if ( offset == 0 || offset > pp->numdates ) |
|||
{ |
|||
pp->dates = realloc(pp->dates,sizeof(*pp->dates) * (offset+1)); |
|||
n = (offset - pp->numdates); |
|||
printf("allocate %s.[%d to %d]\n",pp->symbol,pp->numdates,pp->numdates+n); |
|||
for (i=0; i<=n; i++) |
|||
{ |
|||
date = &pp->dates[pp->numdates + i]; |
|||
if ( date->datenum != pp->firstdatenum + pp->numdates + i ) |
|||
{ |
|||
memset(date,0,sizeof(*date)); |
|||
date->datenum = pp->firstdatenum + pp->numdates + i; |
|||
} |
|||
} |
|||
pp->numdates = offset; |
|||
} |
|||
stats_pairupdate(dir,&pp->dates[offset],pp->symbol,dest,datenum,hour,seconds,height,volume,price); |
|||
} |
|||
|
|||
struct DEXstats_priceinfo *stats_priceinfo(char *symbol,int32_t datenum) |
|||
{ |
|||
int32_t i; struct DEXstats_priceinfo *pp = 0; |
|||
if ( Num_priceinfos >= sizeof(Prices)/sizeof(*Prices) ) |
|||
return(0); |
|||
for (i=0; i<Num_priceinfos; i++) |
|||
if ( strcmp(Prices[i].symbol,symbol) == 0 ) |
|||
{ |
|||
pp = &Prices[i]; |
|||
break; |
|||
} |
|||
if ( i == Num_priceinfos ) |
|||
{ |
|||
pp = &Prices[Num_priceinfos++]; |
|||
strcpy(pp->symbol,symbol); |
|||
pp->firstdatenum = datenum; |
|||
} |
|||
return(pp); |
|||
} |
|||
|
|||
void stats_LPpubkeyupdate(char *LPpubkey,uint32_t timestamp) |
|||
{ |
|||
printf("LP.(%s) t.%u\n",LPpubkey,timestamp); |
|||
} |
|||
|
|||
void stats_priceupdate(int32_t datenum,int32_t hour,int32_t seconds,uint32_t timestamp,int32_t height,char *key,char *LPpubkey,cJSON *tradejson) |
|||
{ |
|||
int32_t dir = 0; uint64_t srcamount,destamount; char *source,*dest; double price; struct DEXstats_priceinfo *pp; |
|||
if ( LPpubkey != 0 ) |
|||
stats_LPpubkeyupdate(LPpubkey,timestamp); |
|||
if ( tradejson != 0 ) |
|||
{ |
|||
source = jstr(jitem(tradejson,0),0); |
|||
srcamount = SATOSHIDEN * jdouble(jitem(tradejson,1),0); |
|||
dest = jstr(jitem(tradejson,2),0); |
|||
destamount = SATOSHIDEN * jdouble(jitem(tradejson,3),0); |
|||
if ( srcamount != 0 && destamount != 0 ) |
|||
{ |
|||
price = (double)destamount / srcamount; |
|||
if ( key != 0 ) |
|||
{ |
|||
dir = 1; |
|||
if ( (pp= stats_priceinfo(source,datenum)) != 0 ) |
|||
stats_datenumupdate(-1,pp,datenum,hour,seconds,height,dstr(srcamount),dest,price); |
|||
if ( (pp= stats_priceinfo(dest,datenum)) != 0 ) |
|||
stats_datenumupdate(1,pp,datenum,hour,seconds,height,dstr(destamount),source,1. / price); |
|||
} |
|||
else if ( (pp= stats_priceinfo(source,datenum)) != 0 ) |
|||
stats_datenumupdate(0,pp,datenum,hour,seconds,height,dstr(srcamount),dest,price); |
|||
} else price = 0.; |
|||
if ( dir != 0 ) |
|||
printf("dir.%-2d %d.%02d.%04d ht.%-4d %s (%s %12.8f) -> (%s %12.8f) %16.8f %16.8f\n",dir,datenum,hour,seconds,height,key!=0?key:"",source,dstr(srcamount),dest,dstr(destamount),price,1./price); |
|||
} |
|||
} |
|||
|
|||
double _pairaved(double valA,double valB) |
|||
{ |
|||
if ( valA != 0. && valB != 0. ) |
|||
return((valA + valB) / 2.); |
|||
else if ( valA != 0. ) return(valA); |
|||
else return(valB); |
|||
} |
|||
|
|||
double calc_loganswer(double pastlogprice,double futurelogprice) |
|||
{ |
|||
if ( fabs(pastlogprice) < .0000001 || fabs(futurelogprice) < .0000001 ) |
|||
return(0); |
|||
return(10000. * (exp(futurelogprice - pastlogprice)-1.)); |
|||
} |
|||
|
|||
double _pairdiff(register double valA,register double valB) |
|||
{ |
|||
if ( valA != 0. && valB != 0. ) |
|||
return((valA - valB)); |
|||
else return(0.); |
|||
} |
|||
|
|||
double balanced_ave(double buf[],int32_t i,int32_t width) |
|||
{ |
|||
register int32_t nonz,j; register double sum,price; |
|||
nonz = 0; |
|||
sum = 0.0; |
|||
for (j=-width; j<=width; j++) |
|||
{ |
|||
price = buf[i + j]; |
|||
if ( price != 0.0 ) |
|||
{ |
|||
sum += price; |
|||
nonz++; |
|||
} |
|||
} |
|||
if ( nonz != 0 ) |
|||
sum /= nonz; |
|||
return(sum); |
|||
} |
|||
|
|||
void buf_trioave(double dest[],double src[],int32_t n) |
|||
{ |
|||
register int32_t i,j,width = 3; |
|||
for (i=0; i<128; i++) |
|||
src[i] = 0; |
|||
//for (i=n-width-1; i>width; i--)
|
|||
// dest[i] = balanced_ave(src,i,width);
|
|||
//for (i=width; i>0; i--)
|
|||
// dest[i] = balanced_ave(src,i,i);
|
|||
for (i=1; i<width; i++) |
|||
dest[i] = balanced_ave(src,i,i); |
|||
for (i=width; i<1024-width; i++) |
|||
dest[i] = balanced_ave(src,i,width); |
|||
dest[0] = _pairaved(dest[0],dest[1] - _pairdiff(dest[2],dest[1])); |
|||
j = width-1; |
|||
for (i=1024-width; i<1023; i++,j--) |
|||
dest[i] = balanced_ave(src,i,j); |
|||
if ( dest[1021] != 0. && dest[1021] != 0. ) |
|||
dest[1023] = ((2.0 * dest[1022]) - dest[1021]); |
|||
else dest[1023] = 0.; |
|||
} |
|||
|
|||
void smooth1024(double dest[],double src[],int32_t smoothiters) |
|||
{ |
|||
double smoothbufA[1024],smoothbufB[1024]; int32_t i; |
|||
buf_trioave(smoothbufA,src,1024); |
|||
for (i=0; i<smoothiters; i++) |
|||
{ |
|||
buf_trioave(smoothbufB,smoothbufA,1024); |
|||
buf_trioave(smoothbufA,smoothbufB,1024); |
|||
} |
|||
buf_trioave(dest,smoothbufA,1024); |
|||
} |
|||
|
|||
float _calc_pricey(register double price,register double weekave) |
|||
{ |
|||
if ( price != 0. && weekave != 0. ) |
|||
return(0.1 * calc_loganswer(weekave,price)); |
|||
else return(0.f); |
|||
} |
|||
|
|||
float pixelwt(register int32_t color) |
|||
{ |
|||
return(((float)((color>>16)&0x0ff) + (float)((color>>8)&0x0ff) + (float)((color>>0)&0x0ff))/0x300); |
|||
} |
|||
|
|||
int32_t pixel_ratios(uint32_t red,uint32_t green,uint32_t blue) |
|||
{ |
|||
float max; |
|||
/*if ( red > green )
|
|||
max = red; |
|||
else |
|||
max = green; |
|||
if ( blue > max ) |
|||
max = blue;*/ |
|||
max = (red + green + blue); |
|||
if ( max == 0. ) |
|||
return(0); |
|||
if ( max > 0xff ) |
|||
{ |
|||
red = (uint32_t)(((float)red / max) * 0xff); |
|||
green = (uint32_t)(((float)green / max) * 0xff); |
|||
blue = (uint32_t)(((float)blue / max) * 0xff); |
|||
} |
|||
|
|||
if ( red > 0xff ) |
|||
red = 0xff; |
|||
if ( green > 0xff ) |
|||
green = 0xff; |
|||
if ( blue > 0xff ) |
|||
blue = 0xff; |
|||
return((red << 16) | (green << 8) | blue); |
|||
} |
|||
|
|||
int32_t conv_yval_to_y(register float yval,register int32_t height) |
|||
{ |
|||
register int32_t y; |
|||
height = (height>>1) - 2; |
|||
y = (int32_t)-yval; |
|||
if ( y > height ) |
|||
y = height; |
|||
else if ( y < -height ) |
|||
y = -height; |
|||
|
|||
y += height; |
|||
if ( y < 0 ) |
|||
y = 0; |
|||
height <<= 1; |
|||
if ( y >= height-1 ) |
|||
y = height-1; |
|||
return(y); |
|||
} |
|||
|
|||
uint32_t scale_color(uint32_t color,float strength) |
|||
{ |
|||
int32_t red,green,blue; |
|||
if ( strength < 0. ) |
|||
strength = -strength; |
|||
red = (color>>16) & 0xff; |
|||
green = (color>>8) & 0xff; |
|||
blue = color & 0xff; |
|||
|
|||
red = (int32_t)((float)red * (strength/100.f)); |
|||
green = (int32_t)((float)green * (strength/100.f)); |
|||
blue = (int32_t)((float)blue * (strength/100.f)); |
|||
if ( red > 0xff ) |
|||
red = 0xff; |
|||
if ( green > 0xff ) |
|||
green = 0xff; |
|||
if ( blue > 0xff ) |
|||
blue = 0xff; |
|||
return((red<<16) | (green<<8) | blue); |
|||
} |
|||
|
|||
uint32_t pixel_blend(uint32_t pixel,uint32_t color)//,int32_t groupsize)
|
|||
{ |
|||
int32_t red,green,blue,sum,n,n2,groupsize = 1; |
|||
float red2,green2,blue2,sum2; |
|||
if ( color == 0 ) |
|||
return(pixel); |
|||
if ( pixel == 0 ) |
|||
{ |
|||
return((1<<24) | scale_color(color,100.f/(float)groupsize)); |
|||
} |
|||
n = (pixel>>24) & 0xff; |
|||
if ( n == 0 ) |
|||
n = 1; |
|||
pixel &= 0xffffff; |
|||
red = (pixel>>16) & 0xff; |
|||
green = (pixel>>8) & 0xff; |
|||
blue = pixel & 0xff; |
|||
sum = red + green + blue; |
|||
|
|||
n2 = (color>>24) & 0xff; |
|||
if ( n2 == 0 ) |
|||
n2 = 1; |
|||
red2 = ((float)((color>>16) & 0xff)) / groupsize; |
|||
green2 = ((float)((color>>8) & 0xff)) / groupsize; |
|||
blue2 = ((float)(color & 0xff)) / groupsize; |
|||
sum2 = (red2 + green2 + blue2); |
|||
|
|||
//printf("gs %d (%d x %d,%d,%d: %d) + (%d x %.1f,%.1f,%.1f: %.1f) = ",groupsize,n,red,green,blue,sum,n2,red2,green2,blue2,sum2);
|
|||
red = (uint32_t)(((((((float)red / (float) sum) * n) + (((float)red2 / (float) sum2) * n2)) / (n+n2)) * ((sum+sum2)/2))); |
|||
green = (uint32_t)(((((((float)green / (float) sum) * n) + (((float)green2 / (float) sum2) * n2)) / (n+n2)) * ((sum+sum2)/2))); |
|||
blue = (uint32_t)(((((((float)blue / (float) sum) * n) + (((float)blue2 / (float) sum2) * n2)) / (n+n2)) * ((sum+sum2)/2))); |
|||
|
|||
n += n2; |
|||
if ( n > 0xff ) |
|||
n = 0xff; |
|||
///printf("%x (%d,%d,%d) ",color,red,green,blue);
|
|||
color = (n<<24) | pixel_ratios(red,green,blue);//pixel_overflow(&red,&green,&blue);
|
|||
|
|||
//printf("%x (%d,%d,%d)\n",color,(color>>16)&0xff,(color>>8)&0xff,color&0xff);
|
|||
return(color); |
|||
} |
|||
|
|||
void init_forex_colors(uint32_t *forex_colors) |
|||
{ |
|||
int32_t i; |
|||
forex_colors[0] = 0x00ff00; |
|||
forex_colors[1] = 0x0033ff; |
|||
forex_colors[2] = 0xff0000; |
|||
forex_colors[3] = 0x00ffff; |
|||
forex_colors[4] = 0xffff00; |
|||
forex_colors[5] = 0xff00ff; |
|||
forex_colors[6] = 0xffffff; |
|||
forex_colors[7] = 0xff8800; |
|||
forex_colors[8] = 0xff88ff; |
|||
for (i=9; i<16; i++) |
|||
forex_colors[i] = pixel_blend(forex_colors[i-8],0xffffff); |
|||
} |
|||
|
|||
int32_t is_primary_color(register uint32_t color) |
|||
{ |
|||
static uint32_t forex_colors[16]; |
|||
register int32_t i; |
|||
if ( forex_colors[0] == 0 ) |
|||
init_forex_colors(forex_colors); |
|||
for (i=0; i<8; i++) |
|||
if ( color == forex_colors[i] ) |
|||
return(1); |
|||
return(0); |
|||
} |
|||
|
|||
void disp_yval(register int32_t color,register float yval,register uint32_t *bitmap,register int32_t x,register int32_t rowwidth,register int32_t height) |
|||
{ |
|||
register int32_t y; |
|||
if ( forex_colors[0] == 0 ) |
|||
init_forex_colors(forex_colors); |
|||
x += LEFTMARGIN; |
|||
if ( x < 0 || x >= rowwidth ) |
|||
return; |
|||
//y = conv_yval_to_y(yval,height/Display_scale) * Display_scale;
|
|||
y = conv_yval_to_y(yval * Display_scale,height); |
|||
if ( 1 && is_primary_color(color) != 0 ) |
|||
{ |
|||
bitmap[y*rowwidth + x] = color; |
|||
//printf("(%d, %d) <- %x, ",x,y,color);
|
|||
return; |
|||
} |
|||
//if ( pixelwt(color) > pixelwt(bitmap[y*rowwidth + x]) )
|
|||
bitmap[y*rowwidth + x] = pixel_blend(bitmap[y*rowwidth + x],color); |
|||
return; |
|||
//if ( is_primary_color(color) != 0 || (is_primary_color(bitmap[y*rowwidth+x]) == 0 && pixelwt(color) > pixelwt(bitmap[y*rowwidth + x])) )
|
|||
// bitmap[y*rowwidth + x] = color;
|
|||
} |
|||
|
|||
void disp_yvalsum(register int32_t color,register float yval,register uint32_t *bitmap,register int32_t x,register int32_t rowwidth,register int32_t height) |
|||
{ |
|||
int32_t y,red,green,blue,dispcolor; |
|||
x += LEFTMARGIN; |
|||
if ( x < 0 || x >= rowwidth ) |
|||
return; |
|||
y = conv_yval_to_y(yval * Display_scale,height); |
|||
red = (color>>16) & 0xff; |
|||
green = (color>>8) & 0xff; |
|||
blue = color & 0xff; |
|||
dispcolor = bitmap[y*rowwidth + x]; |
|||
red += (dispcolor>>16) & 0xff; |
|||
green += (dispcolor>>8) & 0xff; |
|||
blue += dispcolor & 0xff; |
|||
bitmap[y*rowwidth + x] = pixel_ratios(red,green,blue); |
|||
} |
|||
|
|||
void disp_dot(register float radius,register int32_t color,register float yval,register uint32_t *bitmap,register int32_t x,register int32_t rowwidth,register int32_t height) |
|||
{ |
|||
register float i,j,sq,val; |
|||
if ( radius > 1 ) |
|||
{ |
|||
sq = radius * radius; |
|||
for (i=-radius; i<=radius; i++) |
|||
{ |
|||
for (j=-radius; j<=radius; j++) |
|||
{ |
|||
val = ((j*j + i*i) / sq); |
|||
if ( val <= 1. ) |
|||
{ |
|||
val = 1. - val; |
|||
disp_yval(scale_color(color,(100 * val * val * val * val)),yval+j,bitmap,x+i,rowwidth,height); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
else disp_yval(color,yval,bitmap,x,rowwidth,height); |
|||
} |
|||
|
|||
void horizline(int32_t calclogflag,int32_t rowwidth,int32_t height,uint32_t *bitmap,double rawprice,double ave) |
|||
{ |
|||
int32_t x; |
|||
double yval; |
|||
if ( calclogflag != 0 ) |
|||
yval = _calc_pricey(log(rawprice),log(ave)); |
|||
else yval = _calc_pricey(rawprice,ave); |
|||
for (x=0; x<rowwidth; x++) |
|||
disp_yval(0x888888,yval,bitmap,x,rowwidth,height); |
|||
} |
|||
|
|||
void rescale_floats(float *line,int32_t width,double scale) |
|||
{ |
|||
int32_t i; |
|||
for (i=0; i<width; i++) |
|||
line[i] *= scale; |
|||
} |
|||
|
|||
void rescale_doubles(double *line,int32_t width,double scale) |
|||
{ |
|||
int32_t i; |
|||
for (i=0; i<width; i++) |
|||
line[i] *= scale; |
|||
} |
|||
|
|||
double _output_line(int32_t calclogflag,double ave,double *output,double *buf,int32_t n,int32_t color,uint32_t *bitmap,int32_t rowwidth,int32_t height) |
|||
{ |
|||
int32_t x,nonz = 0; |
|||
double yval,val,aveabs = 0.; |
|||
if ( ave == 0. ) |
|||
return(0.); |
|||
if ( calclogflag != 0 ) |
|||
ave = log(ave); |
|||
for (x=0; x<n; x++) |
|||
{ |
|||
if ( (val= buf[x]) != 0. ) |
|||
{ |
|||
//if ( calclogflag != 0 )
|
|||
{ |
|||
val = log(buf[x]); |
|||
if ( ave != 1. ) |
|||
yval = _calc_pricey(val,ave); |
|||
else yval = val; |
|||
} //else yval = (val / ave) * height / 3;
|
|||
//printf("(%f -> %f) ",val,yval);
|
|||
if ( fabs(yval) > .0000000001 ) |
|||
{ |
|||
aveabs += fabs(yval); |
|||
nonz++; |
|||
if ( color != 0 ) |
|||
disp_yval(color,yval,bitmap,x,rowwidth,height); |
|||
} |
|||
} else yval = 0.; |
|||
output[x] = yval; |
|||
} |
|||
if ( nonz != 0 ) |
|||
aveabs /= nonz; |
|||
return(aveabs); |
|||
//
|
|||
//printf("ave %f rowwidth.%d\n",ave,rowwidth);
|
|||
} |
|||
|
|||
double stats_splineval(struct stats_spline *spline,uint32_t timestamp,int32_t lookahead) |
|||
{ |
|||
int32_t i,gap,ind = (spline->num - 1); |
|||
if ( timestamp >= spline->utc32[ind] ) |
|||
{ |
|||
gap = (timestamp - spline->utc32[ind]); |
|||
if ( gap < lookahead ) |
|||
return(_extrapolate_spline64(spline->spline64[ind],gap)); |
|||
else return(0.); |
|||
} |
|||
else if ( timestamp <= spline->utc32[0] ) |
|||
{ |
|||
gap = (spline->utc32[0] - timestamp); |
|||
if ( gap < lookahead ) |
|||
return(_extrapolate_spline64(spline->spline64[0],gap)); |
|||
else return(0.); |
|||
} |
|||
for (i=0; i<spline->num-1; i++) |
|||
{ |
|||
ind = (i + spline->lasti) % (spline->num - 1); |
|||
if ( timestamp >= spline->utc32[ind] && timestamp < spline->utc32[ind+1] ) |
|||
{ |
|||
spline->lasti = ind; |
|||
return(_extrapolate_spline64(spline->spline64[ind],timestamp - spline->utc32[ind])); |
|||
} |
|||
} |
|||
return(0.); |
|||
} |
|||
|
|||
double stats_calcspline(struct stats_spline *spline,double *outputs,double *slopes,int32_t dispwidth,uint32_t *utc32,double *splinevals,int32_t num) |
|||
{ |
|||
static double errsums[3]; static int errcount; |
|||
double c[MAX_SPLINES],f[MAX_SPLINES],dd[MAX_SPLINES],dl[MAX_SPLINES],du[MAX_SPLINES],gaps[MAX_SPLINES]; |
|||
int32_t n,i,lasti,x,numsplines,nonz; double vx,vy,vw,vz,gap,sum,xval,yval,abssum,lastval,lastxval,yval64,yval32,yval3; uint32_t gap32; |
|||
sum = lastxval = n = lasti = nonz = 0; |
|||
for (i=0; i<MAX_SPLINES&&i<num; i++) |
|||
{ |
|||
if ( (f[n]= splinevals[i]) != 0. && utc32[i] != 0 ) |
|||
{ |
|||
//printf("i%d.(%u %f) ",i,utc32[i],splinevals[i]);
|
|||
//printf("%f ",splinevals[i]);
|
|||
if ( n > 0 ) |
|||
{ |
|||
if ( (gaps[n-1]= utc32[i] - lastxval) < 0 ) |
|||
{ |
|||
printf("illegal gap %f to t%d\n",lastxval,utc32[i]); |
|||
return(0); |
|||
} |
|||
} |
|||
spline->utc32[n] = lastxval = utc32[i]; |
|||
n++; |
|||
} |
|||
} |
|||
if ( (numsplines= n) < 4 ) |
|||
return(0); |
|||
for (i=0; i<n-3; i++) |
|||
dl[i] = du[i] = gaps[i+1]; |
|||
for (i=0; i<n-2; i++) |
|||
{ |
|||
dd[i] = 2.0 * (gaps[i] + gaps[i+1]); |
|||
c[i] = (3.0 / (double)gaps[i+1]) * (f[i+2] - f[i+1]) - (3.0 / (double)gaps[i]) * (f[i+1] - f[i]); |
|||
} |
|||
//for (i=0; i<n; i++)
|
|||
// printf("%f ",f[i]);
|
|||
//printf("F2[%d]\n",n);
|
|||
dd[0] += (gaps[0] + (double)gaps[0]*gaps[0] / gaps[1]); |
|||
du[0] -= ((double)gaps[0]*gaps[0] / gaps[1]); |
|||
dd[n-3] += (gaps[n-2] + (double)gaps[n-2]*gaps[n-2] / gaps[n-3]); |
|||
dl[n-4] -= ((double)gaps[n-2]*gaps[n-2] / gaps[n-3]); |
|||
|
|||
//tridiagonal(n-2, dl, dd, du, c);
|
|||
for (i=0; i<n-1-2; i++) |
|||
{ |
|||
du[i] /= dd[i]; |
|||
dd[i+1] -= dl[i]*du[i]; |
|||
} |
|||
c[0] /= dd[0]; |
|||
for (i=1; i<n-2; i++) |
|||
c[i] = (c[i] - dl[i-1] * c[i-1]) / dd[i]; |
|||
for (i=n-2-4; i>=0; i--) |
|||
c[i] -= c[i+1] * du[i]; |
|||
//tridiagonal(n-2, dl, dd, du, c);
|
|||
|
|||
for (i=n-3; i>=0; i--) |
|||
c[i+1] = c[i]; |
|||
c[0] = (1.0 + (double)gaps[0] / gaps[1]) * c[1] - ((double)gaps[0] / gaps[1] * c[2]); |
|||
c[n-1] = (1.0 + (double)gaps[n-2] / gaps[n-3] ) * c[n-2] - ((double)gaps[n-2] / gaps[n-3] * c[n-3]); |
|||
//printf("c[n-1] %f, n-2 %f, n-3 %f\n",c[n-1],c[n-2],c[n-3]);
|
|||
abssum = nonz = lastval = 0; |
|||
outputs[spline->firstx] = f[0]; |
|||
spline->num = numsplines; |
|||
for (i=0; i<n; i++) |
|||
{ |
|||
vx = f[i]; |
|||
vz = c[i]; |
|||
if ( i < n-1 ) |
|||
{ |
|||
gap = gaps[i]; |
|||
vy = ((f[i+1] - f[i]) / gap) - (gap * (c[i+1] + 2.*c[i]) / 3.); |
|||
vw = (c[i+1] - c[i]) / (3. * gap); |
|||
} |
|||
else |
|||
{ |
|||
vy = 0; |
|||
vw = 0; |
|||
} |
|||
//printf("%3d: t%u [%14.11f %14.11f %14.11f %14.11f] gap %f | %d\n",i,spline->utc32[i],(vx),vy*1000*1000,vz*1000*1000*1000*1000,vw*1000*1000*1000*1000*1000*1000,gap,conv_unixtime(&tmp,spline->utc32[i]));
|
|||
spline->dSplines[i][0] = vx, spline->dSplines[i][1] = vy, spline->dSplines[i][2] = vz, spline->dSplines[i][3] = vw; |
|||
spline->spline64[i][0] = dto64(vx), spline->spline64[i][1] = dto64(vy*1000*1000), spline->spline64[i][2] = dto64(vz*1000*1000*1000*1000), spline->spline64[i][3] = dto64(vw*1000*1000*1000*1000*1000*1000); |
|||
spline->spline32[i][0] = dto32(vx), spline->spline32[i][1] = dto32(vy*1000*1000), spline->spline32[i][2] = dto32(vz*1000*1000*1000*1000), spline->spline32[i][3] = dto32(vw*1000*1000*1000*1000*1000*1000); |
|||
gap32 = gap = spline->dispincr; |
|||
xval = spline->utc32[i] + gap; |
|||
lastval = vx; |
|||
while ( i < n-1 ) |
|||
{ |
|||
x = spline->firstx + ((xval - spline->utc32[0]) / spline->dispincr); |
|||
if ( x > dispwidth-1 ) x = dispwidth-1; |
|||
if ( x < 0 ) x = 0; |
|||
if ( (i < n-2 && gap > gaps[i] + spline->dispincr) ) |
|||
break; |
|||
if ( i == n-2 && xval > spline->utc32[n-1] + MAX_LOOKAHEAD*spline->dispincr ) |
|||
{ |
|||
//printf("x.%d dispwidth.%d xval %f > utc[n-1] %f + %f\n",x,dispwidth,xval,utc[n-1],MAX_LOOKAHEAD*incr);
|
|||
break; |
|||
} |
|||
if ( x >= 0 ) |
|||
{ |
|||
yval = _extrapolate_Spline(spline->dSplines[i],gap); |
|||
yval64 = _extrapolate_spline64(spline->spline64[i],gap32); |
|||
if ( (yval3 = stats_splineval(spline,gap32 + spline->utc32[i],MAX_LOOKAHEAD*spline->dispincr)) != 0 ) |
|||
{ |
|||
yval32 = _extrapolate_spline32(spline->spline32[i],gap32); |
|||
errsums[0] += fabs(yval - yval64), errsums[1] += fabs(yval - yval32), errsums[2] += fabs(yval - yval3), errcount++; |
|||
if ( fabs(yval - yval3) > SMALLVAL ) |
|||
printf("(%.10f vs %.10f %.10f %.10f [%.16f %.16f %.16f]) ",yval,yval64,yval32,yval3, errsums[0]/errcount,errsums[1]/errcount,errsums[2]/errcount); |
|||
} |
|||
if ( yval > 5000. ) yval = 5000.; |
|||
else if ( yval < -5000. ) yval = -5000.; |
|||
if ( isnan(yval) == 0 ) |
|||
{ |
|||
outputs[x] = yval; |
|||
spline->lastval = outputs[x], spline->lastutc = xval; |
|||
if ( 1 && fabs(lastval) > SMALLVAL ) |
|||
{ |
|||
if ( lastval != 0 && outputs[x] != 0 ) |
|||
{ |
|||
if ( slopes != 0 ) |
|||
slopes[x] = (outputs[x] - lastval), abssum += fabs(slopes[x]); |
|||
nonz++; |
|||
} |
|||
} |
|||
} |
|||
//else outputs[x] = 0.;
|
|||
//printf("x.%-4d %d %f %f %f i%-4d: gap %9.6f %9.6f last %9.6f slope %9.6f | %9.1f [%9.1f %9.6f %9.6f %9.6f %9.6f]\n",x,firstx,xval,utc[0],incr,i,gap,yval,lastval,slopes[x],xval,utc[i+1],dSplines[i][0],dSplines[i][1]*1000*1000,dSplines[i][2]*1000*1000*1000*1000,dSplines[i][3]*1000*1000*1000*1000*1000*1000);
|
|||
} |
|||
gap32 += spline->dispincr, gap += spline->dispincr, xval += spline->dispincr; |
|||
} |
|||
//double pred = (i>0) ? _extrapolate_Spline(dSplines[i-1],gaps[i-1]) : 0.;
|
|||
//printf("%2d: w%8.1f [gap %f -> %9.6f | %9.6f %9.6f %9.6f %9.6f %9.6f]\n",i,weekinds[i],gap,pred,f[i],dSplines[i].x,1000000*dSplines[i].y,1000000*1000000*dSplines[i].z,1000000*1000000*1000*dSplines[i].w);
|
|||
} |
|||
if ( nonz != 0 ) |
|||
abssum /= nonz; |
|||
spline->aveslopeabs = abssum; |
|||
return(lastval); |
|||
} |
|||
|
|||
int32_t stats_genspline(double output[2048],double slopes[2048],struct stats_spline *spline,int32_t splineid,char *name,uint32_t *utc32,double *splinevals,int32_t numsplines,double *refvals) |
|||
{ |
|||
int32_t i; double origvals[MAX_SPLINES]; |
|||
if ( numsplines > MAX_SPLINES ) |
|||
{ |
|||
printf("numsplines.%d > MAX_SPLINES.%d\n",numsplines,MAX_SPLINES); |
|||
return(-1); |
|||
} |
|||
memset(spline,0,sizeof(*spline)), memset(output,0,sizeof(*output)*2048), memset(slopes,0,sizeof(*slopes)*2048); |
|||
spline->dispincr = 3600, spline->basenum = splineid, strcpy(spline->name,name); |
|||
memcpy(origvals,splinevals,sizeof(*splinevals) * MAX_SPLINES); |
|||
spline->lastval = stats_calcspline(spline,output,slopes,2048,utc32,splinevals,numsplines); |
|||
if ( refvals != 0 ) |
|||
{ |
|||
for (i=0; i<spline->num; i++) |
|||
{ |
|||
if ( i < spline->num ) |
|||
{ |
|||
if ( 0 && refvals[i] != 0 && output[i * 24] != refvals[i] ) |
|||
printf("{%.8f != %.8f}.%d ",output[i * 24],refvals[i],i); |
|||
spline->pricevals[i] = output[i * 24]; |
|||
} |
|||
} |
|||
} |
|||
//printf("spline.%s num.%d\n",name,spline->num);
|
|||
return(spline->num); |
|||
} |
|||
|
|||
void output_line(int32_t calclogflag,double ave,double *buf,int32_t n,int32_t color,uint32_t *bitmap,int32_t rowwidth,int32_t height) |
|||
{ |
|||
double src[1024],dest[1024]; int32_t i; |
|||
memset(src,0,sizeof(src)); |
|||
memset(dest,0,sizeof(dest)); |
|||
if ( (1) ) |
|||
{ |
|||
for (i=0; i<1024; i++) |
|||
src[1023-i] = dest[1023-i] = buf[i]; |
|||
smooth1024(dest,src,3); |
|||
for (i=0; i<1024; i++) |
|||
src[1023-i] = dest[i]; |
|||
} |
|||
else |
|||
{ |
|||
for (i=0; i<1024; i++) |
|||
src[i] = buf[i]; |
|||
} |
|||
_output_line(calclogflag,ave,buf,src,1024,color,bitmap,rowwidth,height); |
|||
} |
|||
|
|||
void stats_updatedisp(struct DEXstats_disp *disp,double price,double volume) |
|||
{ |
|||
if ( price > SMALLVAL && volume > SMALLVAL ) |
|||
{ |
|||
disp->pricesum += (price * volume); |
|||
disp->volumesum += volume; |
|||
} |
|||
} |
|||
|
|||
void stats_dispprices(struct DEXstats_disp *prices,int32_t leftdatenum,int32_t numdates,struct DEXstats_datenuminfo *date,char *dest,int32_t current_daysecond) |
|||
{ |
|||
int32_t i,j,offset,datenum = date->datenum; struct DEXstats_pairinfo *pair; struct DEXstats_pricepoint *ptr; uint32_t timestamp,lefttimestamp,righttimestamp; |
|||
offset = datenum - leftdatenum; |
|||
lefttimestamp = OS_conv_datenum(leftdatenum,0,0,0); |
|||
righttimestamp = OS_conv_datenum(leftdatenum+numdates,0,0,0); |
|||
//printf("search dest.%s datenum.%d vs leftdatenum.%d numdates.%d offset.%d numpairs.%d\n",dest,datenum,leftdatenum,numdates,offset,date->numpairs);
|
|||
for (i=0; i<date->numpairs; i++) |
|||
{ |
|||
if ( strcmp(dest,date->pairs[i].dest) == 0 ) |
|||
{ |
|||
pair = &date->pairs[i]; |
|||
//printf("found dest.(%s) numprices.%d\n",dest,pair->numprices);
|
|||
for (j=0; j<pair->numprices; j++) |
|||
{ |
|||
ptr = &pair->prices[j]; |
|||
timestamp = OS_conv_datenum(date->datenum,ptr->hour,ptr->seconds/60,ptr->seconds%60); |
|||
timestamp += (24*3600 - current_daysecond); |
|||
offset = (timestamp - lefttimestamp) / (24*3600); |
|||
if ( offset >= 0 && offset < numdates ) |
|||
{ |
|||
//printf("found dest.(%s) numprices.%d offset.%d (%.8f %.6f)\n",dest,pair->numprices,offset,ptr->price,ptr->volume);
|
|||
stats_updatedisp(&prices[offset],ptr->price,ptr->volume); |
|||
} |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
#include "../../crypto777/jpeg/jinclude.h" |
|||
#include "../../crypto777/jpeg/jpeglib.h" |
|||
#include "../../crypto777/jpeg/jerror.h" |
|||
|
|||
void gen_jpegfile(char *fname,int32_t quality,uint8_t *bitmap,int32_t width,int32_t height) |
|||
{ |
|||
struct jpeg_compress_struct cinfo; |
|||
struct jpeg_error_mgr jerr; |
|||
FILE * outfile; /* target file */ |
|||
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ |
|||
int row_stride; /* physical row width in image buffer */ |
|||
cinfo.err = jpeg_std_error(&jerr); |
|||
jpeg_create_compress(&cinfo); |
|||
if ( (outfile= fopen(fname,"wb")) == NULL) |
|||
{ |
|||
fprintf(stderr, "can't open %s\n", fname); |
|||
return; |
|||
} |
|||
jpeg_stdio_dest(&cinfo, outfile); |
|||
cinfo.image_width = width; /* image width and height, in pixels */ |
|||
cinfo.image_height = height; |
|||
cinfo.input_components = 3; /* # of color components per pixel */ |
|||
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ |
|||
jpeg_set_defaults(&cinfo); |
|||
jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); |
|||
jpeg_start_compress(&cinfo, TRUE); |
|||
row_stride = width * 3; /* JSAMPLEs per row in image_buffer */ |
|||
while (cinfo.next_scanline < cinfo.image_height) |
|||
{ |
|||
row_pointer[0] = &bitmap[cinfo.next_scanline * row_stride]; |
|||
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1); |
|||
} |
|||
jpeg_finish_compress(&cinfo); |
|||
fclose(outfile); |
|||
jpeg_destroy_compress(&cinfo); |
|||
} |
|||
|
|||
char *stats_prices(char *symbol,char *dest,struct DEXstats_disp *prices,int32_t leftdatenum,int32_t numdates) |
|||
{ |
|||
int32_t i,j,n; struct DEXstats_priceinfo *pp; uint32_t *utc32,tmp,timestamp,lefttimestamp,righttimestamp; double *splinevals,total; char fname[1024]; cJSON *retjson,*array,*item; |
|||
timestamp = (uint32_t)time(NULL); |
|||
if ( Num_priceinfos >= sizeof(Prices)/sizeof(*Prices) ) |
|||
return(0); |
|||
lefttimestamp = OS_conv_datenum(leftdatenum-1,0,0,0); |
|||
righttimestamp = OS_conv_datenum(leftdatenum+numdates,0,0,0); |
|||
for (i=0; i<Num_priceinfos; i++) |
|||
if ( strcmp(Prices[i].symbol,symbol) == 0 ) |
|||
{ |
|||
pp = &Prices[i]; |
|||
for (j=0; j<=pp->numdates; j++) |
|||
{ |
|||
timestamp = OS_conv_datenum(pp->firstdatenum+j,0,0,0); |
|||
if ( timestamp < lefttimestamp ) // can speed up by calculating offset 0
|
|||
{ |
|||
//printf("skip (%s) datenums %d %d %d\n",symbol,datenum,pp->firstdatenum,pp->firstdatenum+pp->numdates);
|
|||
continue; |
|||
} |
|||
stats_dispprices(prices,leftdatenum,numdates,&pp->dates[j],dest,timestamp % (3600*24)); |
|||
} |
|||
break; |
|||
} |
|||
tmp = OS_conv_datenum(leftdatenum,0,0,0); |
|||
utc32 = calloc(sizeof(*utc32),numdates); |
|||
splinevals = calloc(sizeof(*splinevals),numdates); |
|||
for (total=i=n=0; i<numdates; i++,tmp+=24*3600) |
|||
{ |
|||
if ( prices[i].volumesum != 0. ) |
|||
{ |
|||
total += prices[i].volumesum; |
|||
splinevals[n] = (prices[i].pricesum / prices[i].volumesum); |
|||
utc32[n] = tmp; |
|||
//printf("offset.%d splineval %.8f t%u n.%d\n",i,splinevals[n],tmp,n);
|
|||
n++; |
|||
} |
|||
} |
|||
retjson = cJSON_CreateObject(); |
|||
jaddstr(retjson,"source",symbol); |
|||
jaddstr(retjson,"dest",dest); |
|||
jaddnum(retjson,"totalvolume",total); |
|||
jaddnum(retjson,"start",leftdatenum); |
|||
jaddnum(retjson,"numdates",numdates); |
|||
if ( n > 3 ) |
|||
{ |
|||
double output[2048],slopes[2048],sum = 0.; struct stats_spline spline; int32_t splineid = 0; |
|||
memset(&spline,0,sizeof(spline)); |
|||
stats_genspline(output,slopes,&spline,splineid,"spline",utc32,splinevals,n,0); |
|||
array = cJSON_CreateArray(); |
|||
for (i=0; i<n; i++) |
|||
{ |
|||
item = cJSON_CreateArray(); |
|||
jaddinum(item,utc32[i]); |
|||
jaddinum(item,splinevals[i]); |
|||
jaddi(array,item); |
|||
} |
|||
jadd(retjson,"splinevals",array); |
|||
array = cJSON_CreateArray(); |
|||
for (i=0; i<2048; i++) |
|||
{ |
|||
if ( output[i] == 0. ) |
|||
break; |
|||
jaddinum(array,output[i]); |
|||
sum += output[i]; |
|||
} |
|||
if ( i != 2048 ) |
|||
i++; |
|||
sum /= i; |
|||
uint32_t val,height = 400,*bitmap = calloc(sizeof(*bitmap),height * numdates*24); |
|||
uint8_t red,green,blue,*tmpptr,*bytemap = calloc(sizeof(*bytemap),3 * height * numdates*24); |
|||
horizline(1,numdates*24,height,bitmap,sum,sum); |
|||
output_line(1,sum,output,i,0x00ff00,bitmap,numdates*24,height); |
|||
tmpptr = bytemap; |
|||
for (j=0; j<height*numdates*24; j++) |
|||
{ |
|||
val = bitmap[j]; |
|||
red = val & 0xff; |
|||
green = (val >> 8) & 0xff; |
|||
blue = (val >> 16) & 0xff; |
|||
*tmpptr++ = red; |
|||
*tmpptr++ = green; |
|||
*tmpptr++ = blue; |
|||
} |
|||
sprintf(fname,"%s/bitmaps/%s_%s.jpg",STATS_DESTDIR,symbol,dest), OS_portable_path(fname); |
|||
gen_jpegfile(fname,100,bytemap,numdates*24,height); |
|||
free(bitmap), free(bytemap); |
|||
jaddstr(retjson,"bitmap",fname); |
|||
jadd(retjson,"hourly",array); |
|||
jaddnum(retjson,"average",sum); |
|||
} |
|||
free(utc32); |
|||
free(splinevals); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
#ifndef FROM_MARKETMAKER |
|||
char *stats_JSON(char *myipaddr,int32_t mypubsock,double profitmargin,cJSON *argjson,char *remoteaddr,uint16_t port) |
|||
{ |
|||
char *method,*agent,*retstr,*source,*dest; struct tai T; uint32_t endtimestamp; struct DEXstats_disp prices[365]; int32_t leftdatenum,seconds,numdates; |
|||
if ( (method= jstr(argjson,"method")) == 0 ) |
|||
return(clonestr("{\"error\":\"need method in request\"}")); |
|||
if ( (agent= jstr(argjson,"agent")) == 0 ) |
|||
agent = "stats"; |
|||
if ( strcmp(method,"bitmap") == 0 ) |
|||
{ |
|||
if ( (endtimestamp= juint(argjson,"endtimestamp")) == 0 ) |
|||
endtimestamp = (uint32_t)time(NULL); |
|||
if ( (source= jstr(argjson,"source")) == 0 ) |
|||
source = "KMD"; |
|||
if ( (dest= jstr(argjson,"dest")) == 0 ) |
|||
dest = "USD"; |
|||
if ( (numdates= jint(argjson,"numdates")) <= 0 || numdates > 1024/24 ) |
|||
numdates = 1024/24; |
|||
leftdatenum = OS_conv_unixtime(&T,&seconds,endtimestamp - numdates*24*3600); |
|||
printf("(%s/%s) endtimestamp.%u: leftdatenum.%d\n",source,dest,endtimestamp,leftdatenum); |
|||
memset(prices,0,sizeof(prices)); |
|||
if ( (retstr= stats_prices(source,dest,prices,leftdatenum,numdates+1)) != 0 ) |
|||
return(retstr); |
|||
} |
|||
return(clonestr(jprint(argjson,0))); |
|||
} |
|||
#endif |
|||
|
|||
#endif /* DEXstats_h */ |
File diff suppressed because it is too large
@ -0,0 +1,325 @@ |
|||
|
|||
/******************************************************************************
|
|||
* 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_coins.c
|
|||
// marketmaker
|
|||
//
|
|||
|
|||
char *portstrs[][2] = { { "BTC", "8332" }, { "KMD", "7771" } }; |
|||
|
|||
uint16_t LP_rpcport(char *symbol) |
|||
{ |
|||
int32_t i; |
|||
for (i=0; i<sizeof(portstrs)/sizeof(*portstrs); i++) |
|||
if ( strcmp(portstrs[i][0],symbol) == 0 ) |
|||
return(atoi(portstrs[i][1])); |
|||
return(0); |
|||
} |
|||
|
|||
char *parse_conf_line(char *line,char *field) |
|||
{ |
|||
line += strlen(field); |
|||
for (; *line!='='&&*line!=0; line++) |
|||
break; |
|||
if ( *line == 0 ) |
|||
return(0); |
|||
if ( *line == '=' ) |
|||
line++; |
|||
while ( line[strlen(line)-1] == '\r' || line[strlen(line)-1] == '\n' || line[strlen(line)-1] == ' ' ) |
|||
line[strlen(line)-1] = 0; |
|||
//printf("LINE.(%s)\n",line);
|
|||
_stripwhite(line,0); |
|||
return(clonestr(line)); |
|||
} |
|||
|
|||
void LP_userpassfp(char *symbol,char *username,char *password,FILE *fp) |
|||
{ |
|||
char *rpcuser,*rpcpassword,*str,line[8192]; |
|||
rpcuser = rpcpassword = 0; |
|||
username[0] = password[0] = 0; |
|||
while ( fgets(line,sizeof(line),fp) != 0 ) |
|||
{ |
|||
if ( line[0] == '#' ) |
|||
continue; |
|||
//printf("line.(%s) %p %p\n",line,strstr(line,(char *)"rpcuser"),strstr(line,(char *)"rpcpassword"));
|
|||
if ( (str= strstr(line,(char *)"rpcuser")) != 0 ) |
|||
rpcuser = parse_conf_line(str,(char *)"rpcuser"); |
|||
else if ( (str= strstr(line,(char *)"rpcpassword")) != 0 ) |
|||
rpcpassword = parse_conf_line(str,(char *)"rpcpassword"); |
|||
} |
|||
if ( rpcuser != 0 && rpcpassword != 0 ) |
|||
{ |
|||
strcpy(username,rpcuser); |
|||
strcpy(password,rpcpassword); |
|||
} |
|||
//printf("%s rpcuser.(%s) rpcpassword.(%s)\n",symbol,rpcuser,rpcpassword);
|
|||
if ( rpcuser != 0 ) |
|||
free(rpcuser); |
|||
if ( rpcpassword != 0 ) |
|||
free(rpcpassword); |
|||
} |
|||
|
|||
void LP_statefname(char *fname,char *symbol,char *assetname,char *str,char *name) |
|||
{ |
|||
sprintf(fname,"%s",LP_getdatadir()); |
|||
#ifdef WIN32 |
|||
strcat(fname,"\\"); |
|||
#else |
|||
strcat(fname,"/"); |
|||
#endif |
|||
if ( strcmp(symbol,"BTC") == 0 ) |
|||
{ |
|||
#ifdef __APPLE__ |
|||
strcat(fname,"Bitcoin"); |
|||
#else |
|||
strcat(fname,".bitcoin"); |
|||
#endif |
|||
} |
|||
else if ( name != 0 ) |
|||
{ |
|||
char name2[64]; |
|||
#ifdef __APPLE__ |
|||
int32_t len; |
|||
strcpy(name2,name); |
|||
name2[0] = toupper(name2[0]); |
|||
len = (int32_t)strlen(name2); |
|||
if ( strcmp(&name2[len-4],"coin") == 0 ) |
|||
name2[len - 4] = 'C'; |
|||
#else |
|||
name2[0] = '.'; |
|||
strcpy(name2+1,name); |
|||
#endif |
|||
strcat(fname,name2); |
|||
} |
|||
else |
|||
{ |
|||
#ifdef __APPLE__ |
|||
strcat(fname,"Komodo"); |
|||
#else |
|||
strcat(fname,".komodo"); |
|||
#endif |
|||
if ( strcmp(symbol,"KMD") != 0 ) |
|||
{ |
|||
#ifdef WIN32 |
|||
strcat(fname,"\\"); |
|||
#else |
|||
strcat(fname,"/"); |
|||
#endif |
|||
strcat(fname,assetname); |
|||
} |
|||
} |
|||
#ifdef WIN32 |
|||
strcat(fname,"\\"); |
|||
#else |
|||
strcat(fname,"/"); |
|||
#endif |
|||
strcat(fname,str); |
|||
} |
|||
|
|||
int32_t LP_userpass(char *userpass,char *symbol,char *assetname,char *confroot,char *name) |
|||
{ |
|||
FILE *fp; char fname[512],username[512],password[512],confname[16]; |
|||
userpass[0] = 0; |
|||
sprintf(confname,"%s.conf",confroot); |
|||
#ifdef __APPLE__ |
|||
int32_t len; |
|||
confname[0] = toupper(confname[0]); |
|||
len = (int32_t)strlen(confname); |
|||
if ( strcmp(&confname[len-4],"coin") == 0 ) |
|||
confname[len - 4] = 'C'; |
|||
#endif |
|||
LP_statefname(fname,symbol,assetname,confname,name); |
|||
if ( (fp= fopen(fname,"rb")) != 0 ) |
|||
{ |
|||
LP_userpassfp(symbol,username,password,fp); |
|||
sprintf(userpass,"%s:%s",username,password); |
|||
fclose(fp); |
|||
if ( 0 && strcmp(symbol,"HUSH") == 0 ) |
|||
printf("LP_statefname.(%s) <- %s %s %s (%s)\n",fname,name,symbol,assetname,userpass); |
|||
return((int32_t)strlen(userpass)); |
|||
} else printf("cant open.(%s)\n",fname); |
|||
return(-1); |
|||
} |
|||
|
|||
cJSON *LP_coinjson(struct iguana_info *coin) |
|||
{ |
|||
cJSON *item = cJSON_CreateObject(); |
|||
jaddstr(item,"coin",coin->symbol); |
|||
if ( coin->inactive != 0 ) |
|||
jaddstr(item,"status","inactive"); |
|||
else jaddstr(item,"status","active"); |
|||
if ( coin->isPoS != 0 ) |
|||
jaddstr(item,"type","PoS"); |
|||
jaddstr(item,"smartaddress",coin->smartaddr); |
|||
jaddstr(item,"rpc",coin->serverport); |
|||
jaddnum(item,"pubtype",coin->pubtype); |
|||
jaddnum(item,"p2shtype",coin->p2shtype); |
|||
jaddnum(item,"wiftype",coin->wiftype); |
|||
jaddnum(item,"estimatedrate",coin->estimatedrate); |
|||
jaddnum(item,"txfee",coin->txfee); |
|||
return(item); |
|||
} |
|||
|
|||
static struct iguana_info *LP_coins; static int32_t LP_numcoins; |
|||
cJSON *LP_coinsjson() |
|||
{ |
|||
int32_t i; cJSON *array = cJSON_CreateArray(); |
|||
for (i=0; i<LP_numcoins; i++) |
|||
jaddi(array,LP_coinjson(&LP_coins[i])); |
|||
return(array); |
|||
} |
|||
|
|||
int32_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *assetname,int32_t isPoS,uint16_t port,uint8_t pubtype,uint8_t p2shtype,uint8_t wiftype,uint64_t txfee,double estimatedrate,int32_t longestchain,uint8_t taddr) |
|||
{ |
|||
char *name2; |
|||
memset(coin,0,sizeof(*coin)); |
|||
safecopy(coin->symbol,symbol,sizeof(coin->symbol)); |
|||
sprintf(coin->serverport,"127.0.0.1:%u",port); |
|||
coin->isPoS = isPoS; |
|||
coin->taddr = taddr; |
|||
coin->longestchain = longestchain; |
|||
coin->txfee = txfee; |
|||
coin->estimatedrate = estimatedrate; |
|||
coin->pubtype = pubtype; |
|||
coin->p2shtype = p2shtype; |
|||
coin->wiftype = wiftype; |
|||
coin->inactive = (uint32_t)time(NULL); |
|||
if ( strcmp(symbol,"KMD") == 0 || (assetname != 0 && assetname[0] != 0) ) |
|||
name2 = 0; |
|||
else name2 = name; |
|||
return(LP_userpass(coin->userpass,symbol,assetname,name,name2)); |
|||
} |
|||
|
|||
struct iguana_info *LP_coinadd(struct iguana_info *cdata) |
|||
{ |
|||
struct iguana_info *coin; |
|||
//printf("%s: (%s) (%s)\n",symbol,cdata.serverport,cdata.userpass);
|
|||
LP_coins = realloc(LP_coins,sizeof(*LP_coins) * (LP_numcoins+1)); |
|||
coin = &LP_coins[LP_numcoins]; |
|||
*coin = *cdata; |
|||
LP_numcoins++; |
|||
return(coin); |
|||
} |
|||
|
|||
struct iguana_info *LP_coinsearch(char *symbol) |
|||
{ |
|||
int32_t i; |
|||
for (i=0; i<LP_numcoins; i++) |
|||
if ( strcmp(LP_coins[i].symbol,symbol) == 0 ) |
|||
return(&LP_coins[i]); |
|||
return(0); |
|||
} |
|||
|
|||
int32_t LP_isdisabled(char *base,char *rel) |
|||
{ |
|||
struct iguana_info *coin; |
|||
if ( base != 0 && (coin= LP_coinsearch(base)) != 0 && coin->inactive != 0 ) |
|||
return(1); |
|||
else if ( rel != 0 && (coin= LP_coinsearch(rel)) != 0 && coin->inactive != 0 ) |
|||
return(1); |
|||
else return(0); |
|||
} |
|||
|
|||
struct iguana_info *LP_coinfind(char *symbol) |
|||
{ |
|||
struct iguana_info *coin,cdata; int32_t isPoS,longestchain = 1000000; uint16_t port; uint64_t txfee; double estimatedrate; uint8_t pubtype,p2shtype,wiftype; char *name,*assetname; |
|||
if ( (coin= LP_coinsearch(symbol)) != 0 ) |
|||
return(coin); |
|||
if ( (port= LP_rpcport(symbol)) == 0 ) |
|||
return(0); |
|||
isPoS = 0; |
|||
txfee = 10000; |
|||
estimatedrate = 20; |
|||
pubtype = 60; |
|||
p2shtype = 85; |
|||
wiftype = 188; |
|||
assetname = ""; |
|||
if ( strcmp(symbol,"BTC") == 0 ) |
|||
{ |
|||
txfee = 50000; |
|||
estimatedrate = 300; |
|||
pubtype = 0; |
|||
p2shtype = 5; |
|||
wiftype = 128; |
|||
name = "bitcoin"; |
|||
} |
|||
else if ( strcmp(symbol,"KMD") == 0 ) |
|||
name = "komodo"; |
|||
else return(0); |
|||
if ( LP_coininit(&cdata,symbol,name,assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain,0) > 0 ) |
|||
{ |
|||
if ( (coin= LP_coinadd(&cdata)) != 0 ) |
|||
{ |
|||
if ( strcmp(symbol,"KMD") == 0 ) |
|||
coin->inactive = 0; |
|||
else if ( strcmp(symbol,"BTC") == 0 ) |
|||
{ |
|||
coin->inactive = !IAMLP * (uint32_t)time(NULL); |
|||
printf("BTC inactive.%u\n",coin->inactive); |
|||
} |
|||
} |
|||
} |
|||
return(coin); |
|||
} |
|||
|
|||
// "coins":[{"coin":"<assetchain>", "rpcport":pppp}, {"coin":"LTC", "name":"litecoin", "rpcport":9332, "pubtype":48, "p2shtype":5, "wiftype":176, "txfee":100000 }]
|
|||
// {"coin":"HUSH", "name":"hush", "rpcport":8822, "taddr":28, "pubtype":184, "p2shtype":189, "wiftype":128, "txfee":10000 }
|
|||
|
|||
struct iguana_info *LP_coincreate(cJSON *item) |
|||
{ |
|||
struct iguana_info cdata,*coin=0; int32_t isPoS,longestchain = 1000000; uint16_t port; uint64_t txfee; double estimatedrate; uint8_t pubtype,p2shtype,wiftype; char *name=0,*symbol,*assetname=0; |
|||
if ( (symbol= jstr(item,"coin")) != 0 && symbol[0] != 0 && strlen(symbol) < 16 && LP_coinfind(symbol) == 0 && (port= juint(item,"rpcport")) != 0 ) |
|||
{ |
|||
isPoS = jint(item,"isPoS"); |
|||
if ( (txfee= j64bits(item,"txfee")) == 0 ) |
|||
txfee = 10000; |
|||
if ( (estimatedrate= jdouble(item,"estimatedrate")) == 0. ) |
|||
estimatedrate = 20; |
|||
if ( (pubtype= juint(item,"pubtype")) == 0 ) |
|||
pubtype = 60; |
|||
if ( (p2shtype= juint(item,"p2shtype")) == 0 ) |
|||
p2shtype = 85; |
|||
if ( (wiftype= juint(item,"wiftype")) == 0 ) |
|||
wiftype = 188; |
|||
if ( (assetname= jstr(item,"asset")) != 0 ) |
|||
name = assetname; |
|||
else if ( (name= jstr(item,"name")) == 0 ) |
|||
name = symbol; |
|||
if ( LP_coininit(&cdata,symbol,name,assetname==0?"":assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain,jint(item,"taddr")) < 0 ) |
|||
{ |
|||
coin = LP_coinadd(&cdata); |
|||
coin->inactive = (uint32_t)time(NULL); |
|||
} else coin = LP_coinadd(&cdata); |
|||
} |
|||
if ( coin != 0 && item != 0 ) |
|||
{ |
|||
if ( strcmp("KMD",coin->symbol) != 0 ) |
|||
{ |
|||
if ( jobj(item,"active") != 0 ) |
|||
coin->inactive = !jint(item,"active"); |
|||
else |
|||
{ |
|||
if ( IAMLP == 0 || assetname != name ) |
|||
coin->inactive = (uint32_t)time(NULL); |
|||
else coin->inactive = 0; |
|||
} |
|||
} else coin->inactive = 0; |
|||
} |
|||
if ( coin != 0 && coin->inactive != 0 ) |
|||
printf("LPnode.%d %s inactive.%u %p vs %p\n",IAMLP,coin->symbol,coin->inactive,assetname,name); |
|||
return(0); |
|||
} |
|||
|
@ -0,0 +1,268 @@ |
|||
|
|||
/******************************************************************************
|
|||
* 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_commands.c
|
|||
// marketmaker
|
|||
//
|
|||
|
|||
|
|||
char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port
|
|||
{ |
|||
char *method,*ipaddr,*userpass,*base,*rel,*coin,*retstr = 0; uint16_t argport=0,pushport,subport; int32_t otherpeers,othernumutxos,flag = 0; struct LP_peerinfo *peer; cJSON *retjson; struct iguana_info *ptr; |
|||
//printf("stats_JSON(%s)\n",jprint(argjson,0));
|
|||
if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 ) |
|||
{ |
|||
if ( strcmp(ipaddr,"127.0.0.1") != 0 && argport >= 1000 ) |
|||
{ |
|||
flag = 1; |
|||
if ( (pushport= juint(argjson,"push")) == 0 ) |
|||
pushport = argport + 1; |
|||
if ( (subport= juint(argjson,"sub")) == 0 ) |
|||
subport = argport + 2; |
|||
if ( (peer= LP_peerfind((uint32_t)calc_ipbits(ipaddr),argport)) != 0 ) |
|||
{ |
|||
if ( 0 && (otherpeers= jint(argjson,"numpeers")) > peer->numpeers ) |
|||
peer->numpeers = otherpeers; |
|||
if ( 0 && (othernumutxos= jint(argjson,"numutxos")) > peer->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 ( (method= jstr(argjson,"method")) == 0 ) |
|||
{ |
|||
if ( flag == 0 || jobj(argjson,"result") != 0 ) |
|||
printf("stats_JSON no method: (%s) (%s:%u)\n",jprint(argjson,0),ipaddr,argport); |
|||
return(0); |
|||
} |
|||
if ( strcmp(method,"hello") == 0 ) |
|||
{ |
|||
//printf("got hello from %s:%u\n",ipaddr!=0?ipaddr:"",argport);
|
|||
return(0); |
|||
} |
|||
else if ( strcmp(method,"nn_tests") == 0 ) |
|||
return(clonestr("{\"result\":\"success\"}")); |
|||
else if ( strcmp(method,"help") == 0 ) |
|||
return(clonestr("{\"result\":\" \
|
|||
available localhost RPC commands:\n \ |
|||
setprice(base, rel, price)\n\ |
|||
myprice(base, rel)\n\ |
|||
enable(coin)\n\ |
|||
disable(coin)\n\ |
|||
inventory(coin)\n\ |
|||
autotrade(base, rel, price, volume, timeout)\n\ |
|||
swapstatus()\n\ |
|||
swapstatus(requestid, quoteid)\n\ |
|||
public API:\n \ |
|||
getcoins()\n\ |
|||
getpeers()\n\ |
|||
getutxos()\n\ |
|||
getutxos(coin, lastn)\n\ |
|||
orderbook(base, rel)\n\ |
|||
getprices(base, rel)\n\ |
|||
trust(pubkey, trust)\n\ |
|||
register(pubkey,pushaddr)\n\ |
|||
registerall(numnodes)\n\ |
|||
lookup(pubkey)\n\ |
|||
forward(pubkey,method2,<argjson>)\n\ |
|||
forward(pubkey,method2=publish,<argjson>)\n\ |
|||
forwardhex(pubkey,hex)\n\ |
|||
\"}")); |
|||
base = jstr(argjson,"base"); |
|||
rel = jstr(argjson,"rel"); |
|||
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); |
|||
jaddbits256(retjson,"mypubkey",LP_mypubkey); |
|||
jadd(retjson,"coins",LP_coinsjson()); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
if ( (userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,USERPASS) != 0 ) |
|||
return(clonestr("{\"error\":\"authentication error\"}")); |
|||
if ( base != 0 && rel != 0 ) |
|||
{ |
|||
double price; |
|||
if ( LP_isdisabled(base,rel) != 0 ) |
|||
return(clonestr("{\"error\":\"at least one of coins disabled\"}")); |
|||
price = jdouble(argjson,"price"); |
|||
if ( strcmp(method,"setprice") == 0 ) |
|||
{ |
|||
if ( price > SMALLVAL ) |
|||
{ |
|||
if ( LP_mypriceset(base,rel,price) < 0 ) |
|||
return(clonestr("{\"error\":\"couldnt set price\"}")); |
|||
else return(LP_pricepings(ctx,myipaddr,LP_mypubsock,profitmargin,base,rel,price * LP_profitratio)); |
|||
} else return(clonestr("{\"error\":\"no price\"}")); |
|||
} |
|||
else if ( strcmp(method,"myprice") == 0 ) |
|||
{ |
|||
double bid,ask; |
|||
if ( LP_myprice(&bid,&ask,base,rel) > SMALLVAL ) |
|||
{ |
|||
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 ( strcmp(method,"autotrade") == 0 ) |
|||
{ |
|||
if ( price > SMALLVAL ) |
|||
{ |
|||
printf("price set (%s/%s) <- %.8f\n",rel,base,1./price); |
|||
LP_mypriceset(rel,base,1./price); |
|||
return(LP_autotrade(ctx,myipaddr,pubsock,profitmargin,base,rel,price,jdouble(argjson,"volume"),jint(argjson,"timeout"))); |
|||
} else return(clonestr("{\"error\":\"no price set\"}")); |
|||
} |
|||
} |
|||
else if ( (coin= jstr(argjson,"coin")) != 0 ) |
|||
{ |
|||
if ( strcmp(method,"enable") == 0 ) |
|||
{ |
|||
if ( (ptr= LP_coinsearch(coin)) != 0 ) |
|||
ptr->inactive = 0; |
|||
return(jprint(LP_coinsjson(),1)); |
|||
} |
|||
else if ( strcmp(method,"disable") == 0 ) |
|||
{ |
|||
if ( (ptr= LP_coinsearch(coin)) != 0 ) |
|||
ptr->inactive = (uint32_t)time(NULL); |
|||
return(jprint(LP_coinsjson(),1)); |
|||
} |
|||
if ( LP_isdisabled(coin,0) != 0 ) |
|||
return(clonestr("{\"error\":\"coin is disabled\"}")); |
|||
if ( strcmp(method,"inventory") == 0 ) |
|||
{ |
|||
struct iguana_info *ptr; bits256 privkey,pubkey; uint8_t pubkey33[33]; |
|||
if ( (ptr= LP_coinfind(coin)) != 0 ) |
|||
{ |
|||
privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,ptr,"",USERPASS_WIFSTR); |
|||
//LP_utxopurge(0);
|
|||
LP_privkey_init(-1,ptr,privkey,pubkey,pubkey33); |
|||
retjson = cJSON_CreateObject(); |
|||
jaddstr(retjson,"result","success"); |
|||
jaddstr(retjson,"coin",coin); |
|||
jaddnum(retjson,"timestamp",time(NULL)); |
|||
jadd(retjson,"alice",LP_inventory(coin,0)); |
|||
jadd(retjson,"bob",LP_inventory(coin,1)); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
} |
|||
} |
|||
else if ( strcmp(method,"swapstatus") == 0 ) |
|||
{ |
|||
uint32_t requestid,quoteid; |
|||
if ( (requestid= juint(argjson,"requestid")) != 0 && (quoteid= juint(argjson,"quoteid")) != 0 ) |
|||
return(basilisk_swapentry(requestid,quoteid)); |
|||
else return(basilisk_swaplist()); |
|||
} |
|||
else if ( strcmp(method,"myprices") == 0 ) |
|||
return(LP_myprices()); |
|||
else if ( strcmp(method,"trust") == 0 ) |
|||
return(LP_pubkey_trustset(jbits256(argjson,"pubkey"),jint(argjson,"trust"))); |
|||
} |
|||
if ( LP_isdisabled(base,rel) != 0 ) |
|||
retstr = clonestr("{\"error\":\"at least one of coins disabled\"}"); |
|||
else if ( LP_isdisabled(jstr(argjson,"coin"),0) != 0 ) |
|||
retstr = clonestr("{\"error\":\"coin is disabled\"}"); |
|||
else if ( strcmp(method,"reserved") == 0 ) |
|||
retstr = LP_quotereceived(argjson); |
|||
else if ( strcmp(method,"connected") == 0 ) |
|||
retstr = LP_connectedalice(argjson); |
|||
else if ( strcmp(method,"checktxid") == 0 ) |
|||
retstr = LP_spentcheck(argjson); |
|||
else if ( strcmp(method,"getcoins") == 0 ) |
|||
return(jprint(LP_coinsjson(),1)); |
|||
else if ( strcmp(method,"postprice") == 0 ) |
|||
retstr = LP_postedprice(argjson); |
|||
else if ( strcmp(method,"broadcast") == 0 ) |
|||
retstr = LP_broadcasted(argjson); |
|||
else if ( strcmp(method,"getprices") == 0 ) |
|||
return(LP_prices()); |
|||
else if ( strcmp(method,"orderbook") == 0 ) |
|||
return(LP_orderbook(base,rel)); |
|||
else if ( strcmp(method,"registerall") == 0 ) |
|||
return(LP_registerall(jint(argjson,"numnodes"))); |
|||
else if ( strcmp(method,"forward") == 0 ) |
|||
{ |
|||
cJSON *reqjson; |
|||
if ( (reqjson= LP_dereference(argjson,"forward")) != 0 ) |
|||
{ |
|||
//printf("FORWARDED.(%s)\n",jprint(argjson,0));
|
|||
if ( LP_forward(ctx,myipaddr,pubsock,profitmargin,jbits256(argjson,"pubkey"),jprint(reqjson,1),1) > 0 ) |
|||
retstr = clonestr("{\"result\":\"success\"}"); |
|||
else retstr = clonestr("{\"error\":\"error forwarding\"}"); |
|||
} else retstr = clonestr("{\"error\":\"cant recurse forwards\"}"); |
|||
|
|||
} |
|||
else if ( strcmp(method,"keepalive") == 0 ) |
|||
{ |
|||
printf("got keepalive lag.%d switch.%u\n",(int32_t)time(NULL) - LP_deadman_switch,LP_deadman_switch); |
|||
LP_deadman_switch = (uint32_t)time(NULL); |
|||
return(clonestr("{\"result\":\"success\"}")); |
|||
} |
|||
else if ( strcmp(method,"getpeers") == 0 ) |
|||
return(LP_peers()); |
|||
else if ( strcmp(method,"getutxos") == 0 ) |
|||
return(LP_utxos(1,LP_mypeer,jstr(argjson,"coin"),jint(argjson,"lastn"))); |
|||
else if ( strcmp(method,"notified") == 0 ) |
|||
{ |
|||
if ( LP_utxoaddjson(1,LP_mypubsock,argjson) != 0 ) |
|||
return(clonestr("{\"result\":\"success\",\"notifyutxo\":\"received\"}")); |
|||
else return(clonestr("{\"error\":\"couldnt add utxo\"}")); |
|||
} |
|||
else if ( IAMLP != 0 ) |
|||
{ |
|||
if ( strcmp(method,"register") == 0 ) |
|||
{ |
|||
retstr = LP_register(jbits256(argjson,"client"),jstr(argjson,"pushaddr"),juint(argjson,"pushport")); |
|||
//printf("got (%s) from register\n",retstr!=0?retstr:"");
|
|||
return(retstr); |
|||
} |
|||
else if ( strcmp(method,"lookup") == 0 ) |
|||
return(LP_lookup(jbits256(argjson,"client"))); |
|||
else if ( strcmp(method,"forwardhex") == 0 ) |
|||
retstr = LP_forwardhex(ctx,pubsock,jbits256(argjson,"pubkey"),jstr(argjson,"hex")); |
|||
else if ( strcmp(method,"psock") == 0 ) |
|||
{ |
|||
if ( myipaddr == 0 || myipaddr[0] == 0 || strcmp(myipaddr,"127.0.0.1") == 0 ) |
|||
{ |
|||
if ( LP_mypeer != 0 ) |
|||
myipaddr = LP_mypeer->ipaddr; |
|||
else printf("LP_psock dont have actual ipaddr?\n"); |
|||
} |
|||
return(LP_psock(myipaddr,jint(argjson,"ispaired"))); |
|||
} |
|||
else if ( strcmp(method,"notify") == 0 ) |
|||
retstr = clonestr("{\"result\":\"success\",\"notify\":\"received\"}"); |
|||
} |
|||
if ( retstr != 0 ) |
|||
{ |
|||
free(retstr); |
|||
return(0); |
|||
} |
|||
printf("ERROR.(%s)\n",jprint(argjson,0)); |
|||
return(0); |
|||
} |
@ -0,0 +1,349 @@ |
|||
|
|||
/******************************************************************************
|
|||
* 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_forwarding.c
|
|||
// marketmaker
|
|||
//
|
|||
|
|||
struct LP_forwardinfo |
|||
{ |
|||
UT_hash_handle hh; |
|||
bits256 pubkey; |
|||
char pushaddr[64]; |
|||
int32_t pushsock; |
|||
uint32_t lasttime,hello; |
|||
} *LP_forwardinfos; |
|||
#define LP_KEEPALIVE (3600 * 24) |
|||
|
|||
struct LP_forwardinfo *LP_forwardfind(bits256 pubkey) |
|||
{ |
|||
struct LP_forwardinfo *ptr=0; |
|||
portable_mutex_lock(&LP_forwardmutex); |
|||
HASH_FIND(hh,LP_forwardinfos,&pubkey,sizeof(pubkey),ptr); |
|||
portable_mutex_unlock(&LP_forwardmutex); |
|||
if ( ptr != 0 && ptr->lasttime > time(NULL)-LP_KEEPALIVE ) |
|||
return(ptr); |
|||
else return(0); |
|||
} |
|||
|
|||
char *LP_lookup(bits256 pubkey) |
|||
{ |
|||
if ( bits256_nonz(pubkey) == 0 ) |
|||
return(clonestr("{\"error\":\"illegal pubkey\"}")); |
|||
if ( LP_forwardfind(pubkey) != 0 ) |
|||
return(clonestr("{\"result\":\"success\",\"forwarding\":1}")); |
|||
else return(clonestr("{\"error\":\"notfound\"}")); |
|||
} |
|||
|
|||
int32_t LP_hello(struct LP_forwardinfo *ptr) |
|||
{ |
|||
int32_t i,n=10; char msg[512]; struct nn_pollfd pfd; |
|||
if ( bits256_cmp(ptr->pubkey,LP_mypubkey) != 0 ) |
|||
{ |
|||
pfd.fd = ptr->pushsock; |
|||
pfd.events = NN_POLLOUT; |
|||
for (i=0; i<n; i++) |
|||
{ |
|||
if ( nn_poll(&pfd,1,1) > 0 ) |
|||
{ |
|||
sprintf(msg,"{\"method\":\"hello\",\"from\":\"%s\"}",LP_mypeer != 0 ? LP_mypeer->ipaddr : ""); |
|||
//printf("HELLO sent.%d bytes to %s on i.%d\n",LP_send(ptr->pushsock,msg,0),ptr->pushaddr,i);
|
|||
ptr->hello = (uint32_t)time(NULL); |
|||
return(i); |
|||
} |
|||
} |
|||
//printf("%d iterations on nn_poll and %s pushsock still not ready\n",i,ptr->pushaddr);
|
|||
return(-1); |
|||
} |
|||
return(0); |
|||
} |
|||
|
|||
int32_t LP_hellos() |
|||
{ |
|||
struct LP_forwardinfo *ptr,*tmp; int32_t nonz = 0; |
|||
HASH_ITER(hh,LP_forwardinfos,ptr,tmp) |
|||
{ |
|||
if ( ptr->hello == 0 && LP_hello(ptr) >= 0 ) |
|||
nonz++; |
|||
} |
|||
return(nonz); |
|||
} |
|||
|
|||
int32_t LP_pushsock_create(struct LP_forwardinfo *ptr,char *pushaddr) |
|||
{ |
|||
int32_t pushsock,timeout; |
|||
if ( (pushsock= nn_socket(AF_SP,LP_COMMAND_SENDSOCK)) < 0 ) |
|||
{ |
|||
printf("LP_pushsock_create couldnt allocate socket for %s\n",pushaddr); |
|||
return(-1); |
|||
} |
|||
else if ( nn_connect(pushsock,pushaddr) < 0 ) |
|||
{ |
|||
nn_close(pushsock); |
|||
printf("LP_pushsock_create couldnt connect to %s\n",pushaddr); |
|||
return(-1); |
|||
} |
|||
timeout = 1; |
|||
nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); |
|||
nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); |
|||
if ( ptr != 0 ) |
|||
LP_hello(ptr); |
|||
return(pushsock); |
|||
} |
|||
|
|||
char *LP_register(bits256 pubkey,char *ipaddr,uint16_t port) |
|||
{ |
|||
struct LP_forwardinfo *ptr=0; int32_t pushsock; char pushaddr[64]; |
|||
if ( ipaddr == 0 || ipaddr[0] == 0 || is_ipaddr(ipaddr) == 0 || bits256_nonz(pubkey) == 0 ) |
|||
return(clonestr("{\"error\":\"illegal ipaddr or null pubkey\"}")); |
|||
nanomsg_transportname(0,pushaddr,ipaddr,port); |
|||
char str[65]; printf("register.(%s) %s\n",pushaddr,bits256_str(str,pubkey)); |
|||
if ( (ptr= LP_forwardfind(pubkey)) != 0 ) |
|||
{ |
|||
ptr->lasttime = (uint32_t)time(NULL); |
|||
if ( ptr->pushsock >= 0 ) |
|||
{ |
|||
if ( strcmp(pushaddr,ptr->pushaddr) != 0 ) |
|||
{ |
|||
nn_close(ptr->pushsock); |
|||
if ( LP_psockmark(ptr->pushaddr) < 0 ) |
|||
{ |
|||
//printf("cant mark (%s)\n",ptr->pushaddr);
|
|||
} |
|||
char str[65]; printf("%u recreate pushsock for %s <- %s\n",(uint32_t)time(NULL),pushaddr,bits256_str(str,pubkey)); |
|||
strcpy(ptr->pushaddr,pushaddr); |
|||
if ( (ptr->pushsock= LP_pushsock_create(ptr,pushaddr)) < 0 ) |
|||
return(clonestr("{\"error\":\"couldnt recreate pushsock\",\"registered\":0}")); |
|||
} //else printf("no need to create identical endpoint\n");
|
|||
} |
|||
return(clonestr("{\"error\":\"already registered\",\"registered\":1}")); |
|||
} |
|||
else if ( (pushsock= LP_pushsock_create(0,pushaddr)) < 0 ) |
|||
return(clonestr("{\"error\":\"couldnt create pushsock\"}")); |
|||
else |
|||
{ |
|||
ptr = calloc(1,sizeof(*ptr)); |
|||
ptr->pubkey = pubkey; |
|||
strcpy(ptr->pushaddr,pushaddr); |
|||
ptr->pushsock = pushsock; |
|||
ptr->lasttime = (uint32_t)time(NULL); |
|||
portable_mutex_lock(&LP_forwardmutex); |
|||
HASH_ADD_KEYPTR(hh,LP_forwardinfos,&ptr->pubkey,sizeof(ptr->pubkey),ptr); |
|||
portable_mutex_unlock(&LP_forwardmutex); |
|||
char str[65]; printf("registered (%s) -> (%s) pushsock.%d\n",bits256_str(str,pubkey),pushaddr,ptr->pushsock); |
|||
LP_hello(ptr); |
|||
return(LP_lookup(pubkey)); |
|||
} |
|||
} |
|||
|
|||
int32_t LP_forwarding_register(bits256 pubkey,char *publicaddr,uint16_t publicport,int32_t max) |
|||
{ |
|||
char *retstr,ipaddr[64]; cJSON *retjson; struct LP_peerinfo *peer,*tmp; int32_t j,n=0,retval = -1; |
|||
if ( publicaddr == 0 || publicaddr[0] == 0 || bits256_nonz(pubkey) == 0 ) |
|||
{ |
|||
char str[65]; printf("LP_forwarding_register illegal publicaddr.(%s):%u or null pubkey (%s)\n",publicaddr,publicport,bits256_str(str,pubkey)); |
|||
return(0); |
|||
} |
|||
for (j=0; publicaddr[j]!=0; j++) |
|||
if ( publicaddr[j] >= '0' && publicaddr[j] <= '9' ) |
|||
break; |
|||
parse_ipaddr(ipaddr,publicaddr+j); |
|||
HASH_ITER(hh,LP_peerinfos,peer,tmp) |
|||
{ |
|||
//printf("register.(%s) %s %u with (%s)\n",publicaddr,ipaddr,publicport,peer->ipaddr);
|
|||
if ( (retstr= issue_LP_register(peer->ipaddr,peer->port,pubkey,ipaddr,publicport)) != 0 ) |
|||
{ |
|||
//printf("[%s] LP_register.(%s) returned.(%s)\n",publicaddr,peer->ipaddr,retstr);
|
|||
if ( (retjson= cJSON_Parse(retstr)) != 0 ) |
|||
{ |
|||
if ( jint(retjson,"registered") != 0 && ++n >= max ) |
|||
retval = 0; |
|||
free_json(retjson); |
|||
} |
|||
free(retstr); |
|||
} else printf("timeout registering with %s errs.%d good.%d\n",peer->ipaddr,peer->errors,peer->good); |
|||
if ( retval == 0 ) |
|||
break; |
|||
} |
|||
return(n); |
|||
} |
|||
|
|||
char *LP_registerall(int32_t numnodes) |
|||
{ |
|||
int32_t i,maxnodes,n=0; cJSON *retjson; |
|||
if ( numnodes < sizeof(default_LPnodes)/sizeof(*default_LPnodes) ) |
|||
numnodes = (int32_t)(sizeof(default_LPnodes)/sizeof(*default_LPnodes)); |
|||
if ( (maxnodes= LP_numpeers()) < numnodes ) |
|||
numnodes = maxnodes; |
|||
for (i=0; i<numnodes; i++) |
|||
if ( (n= LP_forwarding_register(LP_mypubkey,LP_publicaddr,LP_publicport,numnodes)) >= numnodes ) |
|||
break; |
|||
retjson = cJSON_CreateObject(); |
|||
if ( i == numnodes ) |
|||
jaddstr(retjson,"error","not enough nodes"); |
|||
jaddnum(retjson,"numnodes",numnodes); |
|||
jaddnum(retjson,"registered",n); |
|||
jaddnum(retjson,"iters",i); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
cJSON *LP_dereference(cJSON *argjson,char *excludemethod) |
|||
{ |
|||
cJSON *reqjson = 0; |
|||
if ( jstr(argjson,"method2") != 0 && strncmp(excludemethod,jstr(argjson,"method2"),strlen(excludemethod)) != 0 ) |
|||
{ |
|||
reqjson = jduplicate(argjson); |
|||
jdelete(reqjson,"method"); |
|||
jaddstr(reqjson,"method",jstr(argjson,"method2")); |
|||
} |
|||
return(reqjson); |
|||
} |
|||
|
|||
char *LP_forwardhex(void *ctx,int32_t pubsock,bits256 pubkey,char *hexstr) |
|||
{ |
|||
struct LP_forwardinfo *ptr=0; uint8_t *data; int32_t datalen=0,sentbytes=0; char *msg,*retstr=0; cJSON *retjson=0,*argjson=0,*reqjson=0; |
|||
if ( hexstr == 0 || hexstr[0] == 0 ) |
|||
return(clonestr("{\"error\":\"nohex\"}")); |
|||
datalen = (int32_t)strlen(hexstr) >> 1; |
|||
data = malloc(datalen); |
|||
decode_hex(data,datalen,hexstr); |
|||
if ( (argjson= cJSON_Parse((char *)data)) != 0 ) |
|||
reqjson = LP_dereference(argjson,"forward"); |
|||
if ( bits256_nonz(pubkey) == 0 || bits256_cmp(pubkey,LP_mypubkey) == 0 ) |
|||
{ |
|||
if ( reqjson != 0 ) |
|||
{ |
|||
retstr = LP_command_process(ctx,LP_mypeer != 0 ? LP_mypeer->ipaddr : "127.0.0.1",LP_mypubsock,reqjson,0,0,LP_profitratio - 1.); |
|||
printf("LP_forwardhex.(%s) -> (%s)\n",jprint(reqjson,0),retstr!=0?retstr:""); |
|||
if ( pubsock >= 0 ) |
|||
{ |
|||
msg = jprint(reqjson,0); |
|||
LP_send(pubsock,msg,(int32_t)strlen(msg)+1,0); |
|||
} |
|||
} else printf("LP_forwardhex couldnt parse (%s)\n",(char *)data); |
|||
} |
|||
else if ( (ptr= LP_forwardfind(pubkey)) != 0 ) |
|||
{ |
|||
if ( ptr->pushsock >= 0 )//&& ptr->hello != 0 )
|
|||
{ |
|||
printf("%s forwardhex.(%s)\n",ptr->pushaddr,(char *)data); |
|||
sentbytes = LP_send(ptr->pushsock,(char *)data,datalen,0); |
|||
} |
|||
retjson = cJSON_CreateObject(); |
|||
if ( sentbytes == datalen ) |
|||
{ |
|||
jaddstr(retjson,"result","success"); |
|||
jaddnum(retjson,"forwarded",sentbytes); |
|||
retstr = jprint(retjson,1); |
|||
} |
|||
else |
|||
{ |
|||
jaddstr(retjson,"error","send error"); |
|||
jaddnum(retjson,"sentbytes",sentbytes); |
|||
jaddnum(retjson,"datalen",datalen); |
|||
jaddnum(retjson,"hello",ptr->hello); |
|||
retstr = jprint(retjson,1); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
char str[65]; printf("couldnt find %s to forward to\n",bits256_str(str,pubkey)); |
|||
if ( pubsock >= 0 ) |
|||
{ |
|||
msg = jprint(reqjson,0); |
|||
LP_send(pubsock,msg,(int32_t)strlen(msg)+1,1); |
|||
} |
|||
retstr = clonestr("{\"error\":\"notfound\"}"); |
|||
} |
|||
free(data); |
|||
if ( reqjson != 0 ) |
|||
free_json(reqjson); |
|||
if ( argjson != 0 ) |
|||
free_json(argjson); |
|||
return(retstr); |
|||
} |
|||
|
|||
int32_t LP_forward(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,bits256 pubkey,char *jsonstr,int32_t freeflag) |
|||
{ |
|||
struct LP_forwardinfo *ptr; struct LP_peerinfo *peer,*tmp; char *msg,*hexstr,*retstr; int32_t len,retval = -1; cJSON *retjson,*reqjson,*argjson; |
|||
if ( jsonstr == 0 || jsonstr[0] == 0 ) |
|||
return(-1); |
|||
if ( bits256_nonz(pubkey) != 0 ) |
|||
{ |
|||
if ( bits256_cmp(pubkey,LP_mypubkey) == 0 ) |
|||
{ |
|||
printf("GOT FORWARDED.(%s)\n",myipaddr); |
|||
if ( (argjson= cJSON_Parse(jsonstr)) != 0 ) |
|||
{ |
|||
if ( (retstr= LP_command_process(ctx,myipaddr,pubsock,argjson,0,0,profitmargin)) != 0 ) |
|||
free(retstr); |
|||
free_json(argjson); |
|||
} |
|||
return(1); |
|||
} |
|||
else if ( IAMLP != 0 && (ptr= LP_forwardfind(pubkey)) != 0 && ptr->pushsock >= 0 && ptr->lasttime > time(NULL)-LP_KEEPALIVE ) |
|||
{ |
|||
printf("GOT FORWARDED.(%s) -> pushsock.%d\n",jsonstr,ptr->pushsock); |
|||
len = (int32_t)strlen(jsonstr); |
|||
if ( LP_send(ptr->pushsock,jsonstr,(int32_t)strlen(jsonstr)+1,0) == len+1 ) |
|||
return(1); |
|||
} |
|||
} |
|||
HASH_ITER(hh,LP_peerinfos,peer,tmp) |
|||
{ |
|||
if ( bits256_nonz(pubkey) != 0 ) |
|||
{ |
|||
if ( (retstr= issue_LP_lookup(peer->ipaddr,peer->port,pubkey)) != 0 ) |
|||
{ |
|||
if ( (retjson= cJSON_Parse(retstr)) != 0 ) |
|||
{ |
|||
if ( jint(retjson,"forwarding") != 0 && peer->pushsock >= 0 ) |
|||
retval = 0; |
|||
free_json(retjson); |
|||
} |
|||
free(retstr); |
|||
} |
|||
} else retval = 0; |
|||
if ( retval >= 0 && peer->pushsock >= 0 ) |
|||
{ |
|||
printf("found LPnode.(%s) forward.(%s)\n",peer->ipaddr,jsonstr); |
|||
len = (int32_t)strlen(jsonstr) + 1; |
|||
hexstr = malloc(len*2 + 1); |
|||
init_hexbytes_noT(hexstr,(uint8_t *)jsonstr,len); |
|||
if ( freeflag != 0 ) |
|||
free(jsonstr); |
|||
reqjson = cJSON_CreateObject(); |
|||
jaddstr(reqjson,"method","forwardhex"); |
|||
jaddstr(reqjson,"hex",hexstr); |
|||
jaddbits256(reqjson,"pubkey",pubkey); |
|||
free(hexstr); |
|||
msg = jprint(reqjson,1); |
|||
return(LP_send(peer->pushsock,msg,(int32_t)strlen(msg)+1,1)); |
|||
} else retval = -1; |
|||
} |
|||
if ( freeflag != 0 ) |
|||
free(jsonstr); |
|||
return(-1); |
|||
} |
|||
|
|||
|
|||
char *LP_broadcasted(cJSON *argjson) |
|||
{ |
|||
printf("RECV BROADCAST.(%s)\n",jprint(argjson,0)); |
|||
return(clonestr("{\"result\":\"need to update broadcast messages\"}")); |
|||
} |
|||
|
|||
|
@ -0,0 +1,252 @@ |
|||
|
|||
/******************************************************************************
|
|||
* 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_include.h
|
|||
// marketmaker
|
|||
//
|
|||
|
|||
#ifndef LP_INCLUDE_H |
|||
#define LP_INCLUDE_H |
|||
|
|||
#define LP_COMMAND_SENDSOCK NN_PUSH |
|||
#define LP_COMMAND_RECVSOCK NN_PULL |
|||
|
|||
#define LP_MAXPUBKEY_ERRORS 3 |
|||
#define PSOCK_KEEPALIVE 3600 |
|||
#define MAINLOOP_PERSEC 10 |
|||
#define MAX_PSOCK_PORT 60000 |
|||
#define MIN_PSOCK_PORT 10000 |
|||
|
|||
#define LP_HTTP_TIMEOUT 2 // 1 is too small due to edge cases of time(NULL)
|
|||
#define LP_MAXPEER_ERRORS 3 |
|||
#define LP_MINPEER_GOOD 20 |
|||
#define LP_PEERGOOD_ERRORDECAY 0.9 |
|||
|
|||
#define LP_SWAPSTEP_TIMEOUT 3 |
|||
#define LP_AUTOTRADE_TIMEOUT 3 |
|||
#define LP_MIN_TXFEE 10000 |
|||
#define LP_MINVOL 3 |
|||
#define LP_MINCLIENTVOL 6 |
|||
|
|||
#define LP_DEXFEE(destsatoshis) ((destsatoshis) / INSTANTDEX_INSURANCEDIV) |
|||
#define LP_DEPOSITSATOSHIS(satoshis) ((satoshis) + (satoshis >> 3)) |
|||
|
|||
#define INSTANTDEX_DECKSIZE 1000 |
|||
#define INSTANTDEX_LOCKTIME (3600*2 + 300*2) |
|||
#define INSTANTDEX_INSURANCEDIV 777 |
|||
#define INSTANTDEX_PUBKEY "03bc2c7ba671bae4a6fc835244c9762b41647b9827d4780a89a949b984a8ddcc06" |
|||
#define INSTANTDEX_RMD160 "ca1e04745e8ca0c60d8c5881531d51bec470743f" |
|||
#define JUMBLR_RMD160 "5177f8b427e5f47342a4b8ab5dac770815d4389e" |
|||
#define TIERNOLAN_RMD160 "daedddd8dbe7a2439841ced40ba9c3d375f98146" |
|||
#define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu" |
|||
#define INSTANTDEX_BTCD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf" |
|||
|
|||
//#define BASILISK_DISABLEWAITTX
|
|||
//#define BASILISK_DISABLESENDTX
|
|||
|
|||
#define LP_PROPAGATION_SLACK 100 // 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 1 |
|||
#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 IAMLP,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; }; |
|||
|
|||
struct iguana_msgtx |
|||
{ |
|||
uint32_t version,tx_in,tx_out,lock_time; |
|||
struct iguana_msgvin *vins; |
|||
struct iguana_msgvout *vouts; |
|||
bits256 txid; |
|||
int32_t allocsize,timestamp,numinputs,numoutputs; |
|||
int64_t inputsum,outputsum,txfee; |
|||
uint8_t *serialized; |
|||
}; |
|||
|
|||
struct vin_signer { bits256 privkey; char coinaddr[64]; uint8_t siglen,sig[80],rmd160[20],pubkey[66]; }; |
|||
|
|||
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[10000],p2shscript[10000],userdata[10000]; |
|||
}; |
|||
|
|||
struct basilisk_swapmessage |
|||
{ |
|||
bits256 srchash,desthash; |
|||
uint32_t crc32,msgbits,quoteid,datalen; |
|||
uint8_t *data; |
|||
}; |
|||
|
|||
struct basilisk_swap; |
|||
|
|||
struct basilisk_rawtxinfo |
|||
{ |
|||
char destaddr[64],coinstr[16]; |
|||
bits256 txid,signedtxid,actualtxid; |
|||
uint64_t amount,change,inputsum; |
|||
int32_t redeemlen,datalen,completed,vintype,vouttype,numconfirms,spendlen,secretstart,suppress_pubkeys; |
|||
uint32_t locktime,crcs[2]; |
|||
uint8_t addrtype,pubkey33[33],rmd160[20]; |
|||
}; |
|||
|
|||
struct basilisk_request |
|||
{ |
|||
uint32_t requestid,timestamp,quoteid,quotetime; // 0 to 15
|
|||
uint64_t srcamount,unused; // 16 to 31
|
|||
bits256 srchash; // 32 to 63
|
|||
bits256 desthash; |
|||
char src[8],dest[8]; |
|||
uint64_t destamount; |
|||
int32_t optionhours,DEXselector; |
|||
}; |
|||
|
|||
struct basilisk_rawtx |
|||
{ |
|||
char name[32]; |
|||
struct iguana_msgtx msgtx; |
|||
struct basilisk_rawtxinfo I; |
|||
struct iguana_info *coin; |
|||
char vinstr[8192],p2shaddr[64]; |
|||
cJSON *vins; |
|||
bits256 utxotxid; int32_t utxovout; |
|||
uint8_t txbytes[16384],spendscript[512],redeemscript[1024],extraspace[4096],pubkey33[33]; |
|||
}; |
|||
|
|||
struct basilisk_swapinfo |
|||
{ |
|||
struct basilisk_request req; |
|||
char bobstr[64],alicestr[64]; |
|||
bits256 myhash,otherhash,orderhash; |
|||
uint32_t statebits,otherstatebits,started,expiration,finished,dead,reftime,putduration,callduration; |
|||
int32_t bobconfirms,aliceconfirms,iambob,reclaimed,bobspent,alicespent,pad; |
|||
uint64_t alicesatoshis,bobsatoshis,bobinsurance,aliceinsurance; |
|||
|
|||
bits256 myprivs[2],mypubs[2],otherpubs[2],pubA0,pubA1,pubB0,pubB1,privAm,pubAm,privBn,pubBn; |
|||
uint32_t crcs_mypub[2],crcs_mychoosei[2],crcs_myprivs[2],crcs_mypriv[2]; |
|||
int32_t choosei,otherchoosei,cutverified,otherverifiedcut,numpubs,havestate,otherhavestate,pad2; |
|||
uint8_t secretAm[20],secretBn[20]; |
|||
uint8_t secretAm256[32],secretBn256[32]; |
|||
uint8_t userdata_aliceclaim[256],userdata_aliceclaimlen; |
|||
uint8_t userdata_alicereclaim[256],userdata_alicereclaimlen; |
|||
uint8_t userdata_alicespend[256],userdata_alicespendlen; |
|||
uint8_t userdata_bobspend[256],userdata_bobspendlen; |
|||
uint8_t userdata_bobreclaim[256],userdata_bobreclaimlen; |
|||
uint8_t userdata_bobrefund[256],userdata_bobrefundlen; |
|||
}; |
|||
|
|||
struct iguana_info |
|||
{ |
|||
uint64_t txfee; double estimatedrate,profitmargin; |
|||
int32_t longestchain; uint32_t counter,inactive; |
|||
uint8_t pubtype,p2shtype,isPoS,wiftype,taddr; |
|||
char symbol[16],smartaddr[64],userpass[1024],serverport[128]; |
|||
}; |
|||
|
|||
struct _LP_utxoinfo { bits256 txid; uint64_t value; int32_t vout; }; |
|||
|
|||
struct LP_utxostats { uint32_t lasttime,errors,swappending,spentflag,lastspentcheck,bestflag; }; |
|||
|
|||
struct LP_utxobob { struct _LP_utxoinfo utxo,deposit; }; |
|||
|
|||
struct LP_utxoalice { struct _LP_utxoinfo utxo,fee; }; |
|||
|
|||
struct LP_utxoswap { bits256 otherpubkey; void *swap; uint64_t satoshis; double profitmargin; }; |
|||
|
|||
struct LP_utxoinfo |
|||
{ |
|||
UT_hash_handle hh,hh2; |
|||
bits256 pubkey; |
|||
struct _LP_utxoinfo payment,deposit,fee; |
|||
struct LP_utxostats T; |
|||
struct LP_utxoswap S; |
|||
//struct LP_utxonetwork N;
|
|||
int32_t iambob,iamlp; |
|||
uint8_t key[sizeof(bits256) + sizeof(int32_t)]; |
|||
uint8_t key2[sizeof(bits256) + sizeof(int32_t)]; |
|||
char coin[16],coinaddr[64],spendscript[256],gui[16]; |
|||
}; |
|||
|
|||
struct LP_peerinfo |
|||
{ |
|||
UT_hash_handle hh; |
|||
uint64_t ip_port; |
|||
double profitmargin; |
|||
uint32_t ipbits,errortime,errors,numpeers,numutxos,lasttime,connected,lastutxos,lastpeers,diduquery,good; |
|||
int32_t pushsock,subsock; |
|||
uint16_t port; |
|||
char ipaddr[64]; |
|||
}; |
|||
|
|||
struct LP_quoteinfo |
|||
{ |
|||
struct basilisk_request R; |
|||
bits256 srchash,desthash,txid,txid2,desttxid,feetxid,privkey; |
|||
uint64_t satoshis,txfee,destsatoshis,desttxfee; |
|||
uint32_t timestamp,quotetime; int32_t vout,vout2,destvout,feevout,pair; |
|||
char srccoin[16],coinaddr[64],destcoin[16],destaddr[64]; |
|||
}; |
|||
|
|||
struct LP_endpoint { int32_t pair; char ipaddr[64]; uint16_t port; }; |
|||
|
|||
struct basilisk_swap |
|||
{ |
|||
void *ctx; struct iguana_info bobcoin,alicecoin; struct LP_utxoinfo *utxo; |
|||
struct LP_endpoint N; |
|||
void (*balancingtrade)(struct basilisk_swap *swap,int32_t iambob); |
|||
int32_t subsock,pushsock,connected,aliceunconf,depositunconf,paymentunconf; uint32_t lasttime,aborted; |
|||
FILE *fp; |
|||
bits256 persistent_privkey,persistent_pubkey; |
|||
struct basilisk_swapinfo I; |
|||
struct basilisk_rawtx bobdeposit,bobpayment,alicepayment,myfee,otherfee,aliceclaim,alicespend,bobreclaim,bobspend,bobrefund,alicereclaim; |
|||
bits256 privkeys[INSTANTDEX_DECKSIZE]; |
|||
struct basilisk_swapmessage *messages; int32_t nummessages,sentflag; |
|||
char Bdeposit[64],Bpayment[64]; |
|||
uint64_t otherdeck[INSTANTDEX_DECKSIZE][2],deck[INSTANTDEX_DECKSIZE][2]; |
|||
uint8_t persistent_pubkey33[33],changermd160[20],pad[15],verifybuf[65536]; |
|||
|
|||
}; |
|||
|
|||
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); |
|||
//double LP_query(char *method,struct LP_quoteinfo *qp,char *base,char *rel,bits256 mypub);
|
|||
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); |
|||
void LP_quotesinit(char *base,char *rel); |
|||
int32_t LP_forward(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,bits256 pubkey,char *jsonstr,int32_t freeflag); |
|||
int32_t LP_ismine(struct LP_utxoinfo *utxo); |
|||
int32_t LP_isavailable(struct LP_utxoinfo *utxo); |
|||
struct LP_peerinfo *LP_peerfind(uint32_t ipbits,uint16_t port); |
|||
char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin); |
|||
void LP_availableset(struct LP_utxoinfo *utxo); |
|||
int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2,bits256 pubkey); |
|||
int32_t LP_pullsock_check(void *ctx,char **retstrp,char *myipaddr,int32_t pubsock,int32_t pullsock,double profitmargin); |
|||
uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired); |
|||
|
|||
|
|||
#endif |
@ -0,0 +1,525 @@ |
|||
|
|||
/******************************************************************************
|
|||
* 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_nativeDEX.c
|
|||
// marketmaker
|
|||
//
|
|||
|
|||
#include <stdio.h> |
|||
#include "LP_include.h" |
|||
portable_mutex_t LP_peermutex,LP_UTXOmutex,LP_utxomutex,LP_commandmutex,LP_cachemutex,LP_swaplistmutex,LP_forwardmutex,LP_pubkeymutex,LP_networkmutex,LP_psockmutex; |
|||
int32_t LP_canbind; |
|||
#include "LP_network.c" |
|||
|
|||
struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2]; |
|||
struct LP_peerinfo *LP_peerinfos,*LP_mypeer; |
|||
struct LP_forwardinfo *LP_forwardinfos; |
|||
|
|||
char *activecoins[] = { "BTC", "KMD" }; |
|||
char GLOBAL_DBDIR[] = { "DB" }; |
|||
char USERPASS[65],USERPASS_WIFSTR[64],LP_myipaddr[64],LP_publicaddr[64],USERHOME[512] = { "/root" }; |
|||
char LP_gui[16] = { "cli" }; |
|||
|
|||
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" }; //
|
|||
|
|||
uint32_t LP_deadman_switch; |
|||
uint16_t LP_fixed_pairport,LP_publicport; |
|||
int32_t LP_mypubsock = -1; |
|||
int32_t USERPASS_COUNTER,IAMLP = 0; |
|||
double LP_profitratio = 1.; |
|||
bits256 LP_mypubkey; |
|||
|
|||
// stubs
|
|||
|
|||
void tradebot_swap_balancingtrade(struct basilisk_swap *swap,int32_t iambob) |
|||
{ |
|||
|
|||
} |
|||
|
|||
void tradebot_pendingadd(cJSON *tradejson,char *base,double basevolume,char *rel,double relvolume) |
|||
{ |
|||
// add to trades
|
|||
} |
|||
|
|||
char *LP_getdatadir() |
|||
{ |
|||
return(USERHOME); |
|||
} |
|||
|
|||
char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_t skip) |
|||
{ |
|||
return(0); |
|||
} |
|||
|
|||
#include "LP_secp.c" |
|||
#include "LP_bitcoin.c" |
|||
#include "LP_coins.c" |
|||
#include "LP_rpc.c" |
|||
#include "LP_prices.c" |
|||
#include "LP_scan.c" |
|||
#include "LP_transaction.c" |
|||
#include "LP_remember.c" |
|||
#include "LP_swap.c" |
|||
#include "LP_peers.c" |
|||
#include "LP_utxos.c" |
|||
#include "LP_forwarding.c" |
|||
#include "LP_ordermatch.c" |
|||
#include "LP_commands.c" |
|||
|
|||
char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin) |
|||
{ |
|||
char *retstr=0; |
|||
if ( jobj(argjson,"result") != 0 || jobj(argjson,"error") != 0 ) |
|||
return(0); |
|||
if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,data,datalen,profitmargin) <= 0 ) |
|||
{ |
|||
if ( (retstr= stats_JSON(ctx,myipaddr,pubsock,profitmargin,argjson,"127.0.0.1",0)) != 0 ) |
|||
{ |
|||
//printf("%s PULL.[%d]-> (%s)\n",myipaddr != 0 ? myipaddr : "127.0.0.1",datalen,retstr);
|
|||
if ( pubsock >= 0 ) //strncmp("{\"error\":",retstr,strlen("{\"error\":")) != 0 &&
|
|||
LP_send(pubsock,retstr,(int32_t)strlen(retstr)+1,0); |
|||
} |
|||
} |
|||
return(retstr); |
|||
} |
|||
|
|||
char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock,double profitmargin,void *ptr,int32_t recvlen,int32_t recvsock) |
|||
{ |
|||
int32_t len,datalen=0; char *msg,*retstr=0,*jsonstr=0; cJSON *argjson,*reqjson; |
|||
if ( (datalen= is_hexstr((char *)ptr,0)) > 0 ) |
|||
{ |
|||
datalen >>= 1; |
|||
jsonstr = malloc(datalen + 1); |
|||
decode_hex((void *)jsonstr,datalen,(char *)ptr); |
|||
jsonstr[datalen] = 0; |
|||
} else jsonstr = (char *)ptr; |
|||
if ( 0 && IAMLP == 0 ) |
|||
printf("%s %d, datalen.%d (%s)\n",typestr,recvlen,datalen,jsonstr); |
|||
if ( (argjson= cJSON_Parse(jsonstr)) != 0 ) |
|||
{ |
|||
len = (int32_t)strlen(jsonstr) + 1; |
|||
portable_mutex_lock(&LP_commandmutex); |
|||
if ( jstr(argjson,"method") != 0 && strcmp(jstr(argjson,"method"),"forwardhex") == 0 ) |
|||
{ |
|||
//printf("got forwardhex\n");
|
|||
if ( (retstr= LP_forwardhex(ctx,pubsock,jbits256(argjson,"pubkey"),jstr(argjson,"hex"))) != 0 ) |
|||
{ |
|||
} |
|||
} |
|||
else if ( jstr(argjson,"method") != 0 && strcmp(jstr(argjson,"method"),"publish") == 0 ) |
|||
{ |
|||
printf("got publish\n"); |
|||
if ( jobj(argjson,"method2") != 0 ) |
|||
jdelete(argjson,"method2"); |
|||
jaddstr(argjson,"method2","broadcast"); |
|||
if ( pubsock >= 0 && (reqjson= LP_dereference(argjson,"publish")) != 0 ) |
|||
{ |
|||
msg = jprint(reqjson,1); |
|||
LP_send(pubsock,msg,(int32_t)strlen(msg)+1,1); |
|||
} |
|||
} |
|||
else if ( (retstr= LP_command_process(ctx,myipaddr,pubsock,argjson,&((uint8_t *)ptr)[len],recvlen - len,profitmargin)) != 0 ) |
|||
{ |
|||
} |
|||
portable_mutex_unlock(&LP_commandmutex); |
|||
if ( LP_COMMAND_RECVSOCK == NN_REP ) |
|||
{ |
|||
if ( retstr != 0 ) |
|||
{ |
|||
if ( strcmp("PULL",typestr) == 0 ) |
|||
{ |
|||
printf("%d got REQ.(%s) -> (%s)\n",recvsock,jprint(argjson,0),retstr); |
|||
LP_send(recvsock,retstr,(int32_t)strlen(retstr)+1,0); |
|||
} |
|||
} |
|||
else if ( strcmp("PULL",typestr) == 0 ) |
|||
{ |
|||
printf("%d got REQ.(%s) -> null\n",recvsock,jprint(argjson,0)); |
|||
LP_send(recvsock,"{\"result\":null}",(int32_t)strlen("{\"result\":null}")+1,0); |
|||
} |
|||
} |
|||
free_json(argjson); |
|||
} else printf("error parsing(%s)\n",jsonstr); |
|||
if ( (void *)jsonstr != ptr ) |
|||
free(jsonstr); |
|||
if ( ptr != 0 ) |
|||
nn_freemsg(ptr), ptr = 0; |
|||
return(retstr); |
|||
} |
|||
|
|||
int32_t LP_pullsock_check(void *ctx,char **retstrp,char *myipaddr,int32_t pubsock,int32_t pullsock,double profitmargin) |
|||
{ |
|||
void *ptr; int32_t recvlen=-1,nonz = 0; |
|||
*retstrp = 0; |
|||
if ( pullsock >= 0 ) |
|||
{ |
|||
while ( (recvlen= nn_recv(pullsock,&ptr,NN_MSG,0)) > 0 ) |
|||
{ |
|||
nonz++; |
|||
*retstrp = LP_process_message(ctx,"PULL",myipaddr,pubsock,profitmargin,ptr,recvlen,pullsock); |
|||
} |
|||
} |
|||
return(nonz); |
|||
} |
|||
|
|||
int32_t LP_subsock_check(void *ctx,char *myipaddr,int32_t pubsock,int32_t sock,double profitmargin) |
|||
{ |
|||
int32_t recvlen,nonz = 0; void *ptr; char *retstr; |
|||
if ( sock >= 0 ) |
|||
{ |
|||
while ( (recvlen= nn_recv(sock,&ptr,NN_MSG,0)) > 0 ) |
|||
{ |
|||
nonz++; |
|||
if ( (retstr= LP_process_message(ctx,"SUB",myipaddr,pubsock,profitmargin,ptr,recvlen,sock)) != 0 ) |
|||
free(retstr); |
|||
} |
|||
} |
|||
return(nonz); |
|||
} |
|||
|
|||
void LP_utxo_spentcheck(int32_t pubsock,struct LP_utxoinfo *utxo,double profitmargin) |
|||
{ |
|||
struct _LP_utxoinfo u; char str[65],destaddr[64]; uint32_t now = (uint32_t)time(NULL); |
|||
//printf("%s lag.%d\n",bits256_str(str,utxo->txid),now-utxo->lastspentcheck);
|
|||
if ( utxo->T.spentflag == 0 && now > utxo->T.lastspentcheck+60 ) |
|||
{ |
|||
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; |
|||
utxo->T.lastspentcheck = now; |
|||
if ( LP_txvalue(destaddr,utxo->coin,utxo->payment.txid,utxo->payment.vout) == 0 ) |
|||
{ |
|||
printf("txid.%s %s/v%d %.8f has been spent\n",utxo->coin,bits256_str(str,utxo->payment.txid),utxo->payment.vout,dstr(utxo->payment.value)); |
|||
LP_spentnotify(utxo,0); |
|||
} |
|||
else if ( LP_txvalue(destaddr,utxo->coin,u.txid,u.vout) == 0 ) |
|||
{ |
|||
printf("txid2.%s %s/v%d %.8f has been spent\n",utxo->coin,bits256_str(str,u.txid),u.vout,dstr(u.value)); |
|||
LP_spentnotify(utxo,1); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void LP_myutxo_updates(void *ctx,int32_t pubsock,char *passphrase,double profitmargin) |
|||
{ |
|||
//LP_utxopurge(0); not good to disrupt existing pointers
|
|||
LP_privkey_updates(ctx,pubsock,passphrase,0); |
|||
} |
|||
|
|||
int32_t LP_peer_utxosquery(struct LP_peerinfo *mypeer,uint16_t myport,int32_t pubsock,struct LP_peerinfo *peer,uint32_t now,double profitmargin,int32_t interval) |
|||
{ |
|||
int32_t lastn,n = -1; |
|||
if ( peer->lastutxos < now-interval ) |
|||
{ |
|||
//lastn = peer->numutxos - mypeer->numutxos + LP_PROPAGATION_SLACK;
|
|||
//if ( lastn < LP_PROPAGATION_SLACK * 2 )
|
|||
lastn = LP_PROPAGATION_SLACK * 2; |
|||
if ( mypeer == 0 || strcmp(peer->ipaddr,mypeer->ipaddr) != 0 ) |
|||
{ |
|||
peer->lastutxos = now; |
|||
//printf("query utxos from %s\n",peer->ipaddr);
|
|||
n = LP_utxosquery(mypeer,pubsock,peer->ipaddr,peer->port,"",lastn,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1",myport,profitmargin); |
|||
} |
|||
} //else printf("LP_peer_utxosquery skip.(%s) %u\n",peer->ipaddr,peer->lastutxos);
|
|||
return(n); |
|||
} |
|||
|
|||
int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int32_t pubsock,char *pushaddr,uint16_t pushport,int32_t pullsock,uint16_t myport,char *passphrase,double profitmargin) |
|||
{ |
|||
static uint32_t counter,lastforward,numpeers; |
|||
struct LP_utxoinfo *utxo,*utmp; char *retstr,*origipaddr; struct LP_peerinfo *peer,*tmp; uint32_t now; int32_t nonz = 0,n=0,lastn=-1; |
|||
now = (uint32_t)time(NULL); |
|||
if ( (origipaddr= myipaddr) == 0 ) |
|||
origipaddr = "127.0.0.1"; |
|||
if ( mypeer == 0 ) |
|||
myipaddr = "127.0.0.1"; |
|||
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d peers\n",counter,LP_canbind);
|
|||
numpeers = LP_numpeers(); |
|||
HASH_ITER(hh,LP_peerinfos,peer,tmp) |
|||
{ |
|||
if ( peer->errors >= LP_MAXPEER_ERRORS ) |
|||
{ |
|||
if ( (rand() % 10000) == 0 ) |
|||
peer->errors--; |
|||
else continue; |
|||
} |
|||
if ( now > peer->lastpeers+60 && peer->numpeers > 0 && (peer->numpeers != numpeers || (rand() % 10000) == 0) ) |
|||
{ |
|||
if ( IAMLP != 0 ) |
|||
printf("numpeers.%d updatepeer.%s lag.%d\n",numpeers,peer->ipaddr,now-peer->lastpeers); |
|||
peer->lastpeers = now; |
|||
if ( IAMLP != 0 && peer->numpeers != numpeers ) |
|||
printf("%s num.%d vs %d\n",peer->ipaddr,peer->numpeers,numpeers); |
|||
if ( strcmp(peer->ipaddr,myipaddr) != 0 ) |
|||
LP_peersquery(mypeer,pubsock,peer->ipaddr,peer->port,myipaddr,myport,profitmargin); |
|||
} |
|||
if ( peer->diduquery == 0 ) |
|||
{ |
|||
if ( lastn != n || n < 20 ) |
|||
{ |
|||
lastn = n; |
|||
n = LP_peer_utxosquery(mypeer,myport,pubsock,peer,now,profitmargin,60); |
|||
} |
|||
LP_peer_pricesquery(peer->ipaddr,peer->port); |
|||
peer->diduquery = now; |
|||
} |
|||
nonz += LP_subsock_check(ctx,origipaddr,pubsock,peer->subsock,profitmargin); |
|||
} |
|||
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d forwarding\n",counter,LP_canbind);
|
|||
if ( (counter % 600) == 20 ) |
|||
{ |
|||
LP_myutxo_updates(ctx,pubsock,passphrase,profitmargin); |
|||
if ( lastforward < now-3600 ) |
|||
{ |
|||
if ( (retstr= LP_registerall(0)) != 0 ) |
|||
free(retstr); |
|||
//LP_forwarding_register(LP_mypubkey,pushaddr,pushport,10);
|
|||
lastforward = now; |
|||
} |
|||
} |
|||
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d utxos\n",counter,LP_canbind);
|
|||
if ( (counter % 600) == 60 ) |
|||
{ |
|||
HASH_ITER(hh,LP_utxoinfos[0],utxo,utmp) |
|||
{ |
|||
LP_utxo_spentcheck(pubsock,utxo,profitmargin); |
|||
} |
|||
HASH_ITER(hh,LP_utxoinfos[1],utxo,utmp) |
|||
{ |
|||
//char str[65];
|
|||
LP_utxo_spentcheck(pubsock,utxo,profitmargin); |
|||
if ( utxo->T.lasttime == 0 ) |
|||
LP_utxo_clientpublish(utxo); |
|||
//else if ( strcmp(utxo->coin,"HUSH") == 0 )
|
|||
// printf("lasttime set %s\n",bits256_str(str,utxo->payment.txid));
|
|||
} |
|||
} |
|||
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d swapentry\n",counter,LP_canbind);
|
|||
if ( (counter % 6000) == 5999 ) |
|||
{ |
|||
if ( (retstr= basilisk_swapentry(0,0)) != 0 ) |
|||
{ |
|||
//printf("SWAPS.(%s)\n",retstr);
|
|||
free(retstr); |
|||
} |
|||
} |
|||
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d pullsock check\n",counter,LP_canbind);
|
|||
nonz += LP_pullsock_check(ctx,&retstr,myipaddr,pubsock,pullsock,profitmargin); |
|||
if ( retstr != 0 ) |
|||
free(retstr); |
|||
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d hellos\n",counter,LP_canbind);
|
|||
if ( IAMLP != 0 && (counter % 600) == 42 ) |
|||
LP_hellos(); |
|||
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d\n",counter,LP_canbind);
|
|||
if ( LP_canbind == 0 && (counter % (PSOCK_KEEPALIVE*MAINLOOP_PERSEC/2)) == 13 ) |
|||
{ |
|||
char keepalive[128]; |
|||
sprintf(keepalive,"{\"method\":\"keepalive\"}"); |
|||
//printf("send keepalive to %s pullsock.%d\n",pushaddr,pullsock);
|
|||
if ( LP_send(pullsock,keepalive,(int32_t)strlen(keepalive)+1,0) < 0 ) |
|||
{ |
|||
//LP_deadman_switch = 0;
|
|||
} |
|||
} |
|||
counter++; |
|||
return(nonz); |
|||
} |
|||
|
|||
void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins,char *passphrase) |
|||
{ |
|||
int32_t i,n; cJSON *item; |
|||
for (i=0; i<sizeof(activecoins)/sizeof(*activecoins); i++) |
|||
{ |
|||
fprintf(stderr,"%s ",activecoins[i]); |
|||
LP_coinfind(activecoins[i]); |
|||
LP_priceinfoadd(activecoins[i]); |
|||
} |
|||
if ( (n= cJSON_GetArraySize(coins)) > 0 ) |
|||
{ |
|||
for (i=0; i<n; i++) |
|||
{ |
|||
item = jitem(coins,i); |
|||
fprintf(stderr,"%s ",jstr(item,"coin")); |
|||
LP_coincreate(item); |
|||
LP_priceinfoadd(jstr(item,"coin")); |
|||
} |
|||
} |
|||
fprintf(stderr,"privkey updates\n"); |
|||
LP_privkey_updates(ctx,pubsock,passphrase,1); |
|||
} |
|||
|
|||
void LP_initpeers(int32_t pubsock,struct LP_peerinfo *mypeer,char *myipaddr,uint16_t myport,char *seednode,double profitmargin) |
|||
{ |
|||
int32_t i,j; uint32_t r; |
|||
if ( IAMLP != 0 ) |
|||
{ |
|||
LP_mypeer = mypeer = LP_addpeer(mypeer,pubsock,myipaddr,myport,0,0,profitmargin,0,0); |
|||
if ( myipaddr == 0 || mypeer == 0 ) |
|||
{ |
|||
printf("couldnt get myipaddr or null mypeer.%p\n",mypeer); |
|||
exit(-1); |
|||
} |
|||
if ( seednode == 0 || seednode[0] == 0 ) |
|||
{ |
|||
for (i=0; i<sizeof(default_LPnodes)/sizeof(*default_LPnodes); i++) |
|||
{ |
|||
if ( (rand() % 100) > 25 ) |
|||
continue; |
|||
LP_peersquery(mypeer,pubsock,default_LPnodes[i],myport,mypeer->ipaddr,myport,profitmargin); |
|||
} |
|||
} else LP_peersquery(mypeer,pubsock,seednode,myport,mypeer->ipaddr,myport,profitmargin); |
|||
} |
|||
else |
|||
{ |
|||
if ( myipaddr == 0 ) |
|||
{ |
|||
printf("couldnt get myipaddr\n"); |
|||
exit(-1); |
|||
} |
|||
if ( seednode == 0 || seednode[0] == 0 ) |
|||
{ |
|||
OS_randombytes((void *)&r,sizeof(r)); |
|||
for (j=0; j<sizeof(default_LPnodes)/sizeof(*default_LPnodes); j++) |
|||
{ |
|||
i = (r + j) % (sizeof(default_LPnodes)/sizeof(*default_LPnodes)); |
|||
LP_peersquery(mypeer,pubsock,default_LPnodes[i],myport,"127.0.0.1",myport,profitmargin); |
|||
} |
|||
} else LP_peersquery(mypeer,pubsock,seednode,myport,"127.0.0.1",myport,profitmargin); |
|||
} |
|||
} |
|||
|
|||
void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profitmargin,char *passphrase,int32_t amclient,char *userhome,cJSON *argjson) |
|||
{ |
|||
char *myipaddr=0; long filesize,n; int32_t timeout,pullsock=-1,pubsock=-1; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128],bindaddr[128]; void *ctx = bitcoin_ctx(); |
|||
IAMLP = !amclient; |
|||
#ifndef __linux__ |
|||
if ( IAMLP != 0 ) |
|||
{ |
|||
printf("must run a unix node for LP node\n"); |
|||
exit(-1); |
|||
} |
|||
#endif |
|||
LP_profitratio += profitmargin; |
|||
OS_randombytes((void *)&n,sizeof(n)); |
|||
if ( jobj(argjson,"gui") != 0 ) |
|||
safecopy(LP_gui,jstr(argjson,"gui"),sizeof(LP_gui)); |
|||
if ( jobj(argjson,"canbind") == 0 ) |
|||
{ |
|||
#ifndef __linux__ |
|||
LP_canbind = 1; |
|||
#else |
|||
LP_canbind = IAMLP; |
|||
#endif |
|||
} else LP_canbind = jint(argjson,"canbind"); |
|||
if ( LP_canbind > 1000 && LP_canbind < 65536 ) |
|||
LP_fixed_pairport = LP_canbind; |
|||
if ( LP_canbind != 0 ) |
|||
LP_canbind = 1; |
|||
srand((int32_t)n); |
|||
if ( userhome != 0 && userhome[0] != 0 ) |
|||
{ |
|||
safecopy(USERHOME,userhome,sizeof(USERHOME)); |
|||
#ifdef __APPLE__ |
|||
strcat(USERHOME,"/Library/Application Support"); |
|||
#endif |
|||
} |
|||
portable_mutex_init(&LP_peermutex); |
|||
portable_mutex_init(&LP_utxomutex); |
|||
portable_mutex_init(&LP_UTXOmutex); |
|||
portable_mutex_init(&LP_commandmutex); |
|||
portable_mutex_init(&LP_swaplistmutex); |
|||
portable_mutex_init(&LP_cachemutex); |
|||
portable_mutex_init(&LP_networkmutex); |
|||
portable_mutex_init(&LP_forwardmutex); |
|||
portable_mutex_init(&LP_psockmutex); |
|||
portable_mutex_init(&LP_pubkeymutex); |
|||
if ( profitmargin == 0. || profitmargin == 0.01 ) |
|||
{ |
|||
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 ( (myipaddr= OS_filestr(&filesize,"/tmp/myipaddr")) != 0 && myipaddr[0] != 0 ) |
|||
{ |
|||
n = strlen(myipaddr); |
|||
if ( myipaddr[n-1] == '\n' ) |
|||
myipaddr[--n] = 0; |
|||
strcpy(LP_myipaddr,myipaddr); |
|||
} else printf("error getting myipaddr\n"); |
|||
} else printf("error issuing curl\n"); |
|||
if ( IAMLP != 0 ) |
|||
{ |
|||
pubsock = -1; |
|||
nanomsg_transportname(0,subaddr,myipaddr,mypubport); |
|||
nanomsg_transportname(1,bindaddr,myipaddr,mypubport); |
|||
if ( (pubsock= nn_socket(AF_SP,NN_PUB)) >= 0 ) |
|||
{ |
|||
if ( nn_bind(pubsock,bindaddr) >= 0 ) |
|||
{ |
|||
timeout = 10; |
|||
nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); |
|||
} |
|||
else |
|||
{ |
|||
printf("error binding to (%s).%d\n",subaddr,pubsock); |
|||
if ( pubsock >= 0 ) |
|||
nn_close(pubsock), pubsock = -1; |
|||
} |
|||
} else printf("error getting pubsock %d\n",pubsock); |
|||
printf(">>>>>>>>> myipaddr.%s (%s) pullsock.%d\n",myipaddr,subaddr,pubsock); |
|||
LP_mypubsock = pubsock; |
|||
} |
|||
LP_initpeers(pubsock,mypeer,myipaddr,myport,jstr(argjson,"seednode"),profitmargin); |
|||
pullsock = LP_initpublicaddr(ctx,&mypullport,pushaddr,myipaddr,mypullport,0); |
|||
strcpy(LP_publicaddr,pushaddr); |
|||
LP_publicport = mypullport; |
|||
LP_deadman_switch = (uint32_t)time(NULL); |
|||
printf("my command address is (%s) pullsock.%d pullport.%u\n",pushaddr,pullsock,mypullport); |
|||
LP_initcoins(ctx,pubsock,jobj(argjson,"coins"),passphrase); |
|||
if ( IAMLP != 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_psockloop,(void *)&myipaddr) != 0 ) |
|||
{ |
|||
printf("error launching LP_psockloop for (%s)\n",myipaddr); |
|||
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); |
|||
} |
|||
while ( 1 ) |
|||
{ |
|||
//fprintf(stderr,".");
|
|||
if ( LP_mainloop_iter(ctx,myipaddr,mypeer,pubsock,pushaddr,mypullport,pullsock,myport,passphrase,profitmargin) == 0 ) |
|||
usleep(1000000 / MAINLOOP_PERSEC); |
|||
if ( LP_canbind == 0 ) |
|||
{ |
|||
//printf("check deadman %u vs %u\n",LP_deadman_switch,(uint32_t)time(NULL));
|
|||
if ( LP_deadman_switch < time(NULL)-PSOCK_KEEPALIVE ) |
|||
{ |
|||
printf("DEAD man's switch %u activated at %u lag.%d, register forwarding again\n",LP_deadman_switch,(uint32_t)time(NULL),(uint32_t)(time(NULL) - LP_deadman_switch)); |
|||
if ( pullsock >= 0 ) |
|||
nn_close(pullsock); |
|||
pullsock = LP_initpublicaddr(ctx,&mypullport,pushaddr,myipaddr,mypullport,0); |
|||
LP_deadman_switch = (uint32_t)time(NULL); |
|||
strcpy(LP_publicaddr,pushaddr); |
|||
LP_publicport = mypullport; |
|||
LP_forwarding_register(LP_mypubkey,pushaddr,mypullport,MAX_PSOCK_PORT); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
|
@ -0,0 +1,452 @@ |
|||
|
|||
/******************************************************************************
|
|||
* 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_network.c
|
|||
// marketmaker
|
|||
//
|
|||
|
|||
struct psock |
|||
{ |
|||
uint32_t lasttime,lastping,errors; |
|||
int32_t publicsock,sendsock,ispaired; |
|||
uint16_t publicport,sendport; |
|||
char sendaddr[128],publicaddr[128]; |
|||
} *PSOCKS; |
|||
|
|||
uint16_t Numpsocks,Psockport = MIN_PSOCK_PORT; |
|||
|
|||
char *nanomsg_transportname(int32_t bindflag,char *str,char *ipaddr,uint16_t port) |
|||
{ |
|||
sprintf(str,"tcp://%s:%u",bindflag == 0 ? ipaddr : "*",port); |
|||
return(str); |
|||
} |
|||
|
|||
int32_t LP_send(int32_t sock,void *msg,int32_t sendlen,int32_t freeflag) |
|||
{ |
|||
int32_t sentbytes,i; struct nn_pollfd pfd; |
|||
if ( sock < 0 ) |
|||
{ |
|||
printf("LP_send.(%s) to illegal socket\n",(char *)msg); |
|||
if ( freeflag != 0 ) |
|||
free(msg); |
|||
return(-1); |
|||
} |
|||
//len = (int32_t)strlen(msg) + 1;
|
|||
for (i=0; i<1000; i++) // 1000 * (1 ms + 1000 us) = 2 seconds
|
|||
{ |
|||
pfd.fd = sock; |
|||
pfd.events = NN_POLLOUT; |
|||
//portable_mutex_lock(&LP_networkmutex);
|
|||
if ( nn_poll(&pfd,1,1) > 0 ) |
|||
{ |
|||
if ( (sentbytes= nn_send(sock,msg,sendlen,0)) != sendlen ) |
|||
printf("LP_send sent %d instead of %d\n",sentbytes,sendlen); |
|||
//else printf("SENT.(%s)\n",msg);
|
|||
if ( freeflag != 0 ) |
|||
free(msg); |
|||
//portable_mutex_unlock(&LP_networkmutex);
|
|||
return(sentbytes); |
|||
} |
|||
//portable_mutex_unlock(&LP_networkmutex);
|
|||
usleep(1000); |
|||
} |
|||
printf("error LP_send sock.%d, i.%d timeout.(%s) %s\n",sock,i,(char *)msg,nn_strerror(nn_errno())); |
|||
if ( freeflag != 0 ) |
|||
free(msg); |
|||
return(-1); |
|||
} |
|||
|
|||
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); |
|||
for (i=0; i<32; i++) |
|||
buf[offset++] = swap->I.myhash.bytes[i]; |
|||
for (i=0; i<32; i++) |
|||
buf[offset++] = swap->I.otherhash.bytes[i]; |
|||
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 ( datalen > 0 ) |
|||
memcpy(&buf[offset],data,datalen), offset += datalen; |
|||
if ( (sentbytes= nn_send(pairsock,buf,offset,0)) != offset ) |
|||
{ |
|||
printf("sentbytes.%d vs offset.%d\n",sentbytes,offset); |
|||
if ( sentbytes < 0 ) |
|||
{ |
|||
} |
|||
} |
|||
//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 LP_psockloop(void *_ptr) |
|||
{ |
|||
static struct nn_pollfd *pfds; |
|||
int32_t i,n,nonz,iter,retval,size=0,sentbytes,sendsock = -1; uint32_t now; struct psock *ptr=0; void *buf=0; char keepalive[512];//,*myipaddr = _ptr;
|
|||
while ( 1 ) |
|||
{ |
|||
now = (uint32_t)time(NULL); |
|||
if ( buf != 0 && ptr != 0 && sendsock >= 0 ) |
|||
{ |
|||
if ( size > 0 ) |
|||
{ |
|||
if ( (sentbytes= LP_send(sendsock,buf,size,0)) > 0 ) |
|||
{ |
|||
//printf("PSOCKS (%d %d %d) (%s) -> %d/%d bytes %s\n",ptr->publicsock,ptr->sendsock,sendsock,(char *)buf,size,sentbytes,ptr->sendaddr);
|
|||
} |
|||
else |
|||
{ |
|||
ptr->errors++; |
|||
printf("send error.%d to %s\n",ptr->errors,ptr->sendaddr); |
|||
} |
|||
if ( buf != 0 ) |
|||
{ |
|||
if ( buf != keepalive ) |
|||
nn_freemsg(buf); |
|||
buf = 0; |
|||
size = 0; |
|||
ptr = 0; |
|||
sendsock = -1; |
|||
} |
|||
} |
|||
} |
|||
else if ( Numpsocks > 0 ) |
|||
{ |
|||
if ( pfds == 0 ) |
|||
pfds = calloc(MAX_PSOCK_PORT,sizeof(*pfds)); |
|||
portable_mutex_lock(&LP_psockmutex); |
|||
memset(pfds,0,sizeof(*pfds) * ((Numpsocks*2 <= MAX_PSOCK_PORT) ? Numpsocks*2 : MAX_PSOCK_PORT)); |
|||
for (iter=0; iter<2; iter++) |
|||
{ |
|||
for (i=n=0; i<Numpsocks; i++) |
|||
{ |
|||
ptr = &PSOCKS[i]; |
|||
if ( iter == 0 ) |
|||
{ |
|||
pfds[n].fd = ptr->publicsock; |
|||
pfds[n].events = POLLIN; |
|||
} |
|||
else |
|||
{ |
|||
if ( pfds[n].fd != ptr->publicsock ) |
|||
{ |
|||
printf("unexpected fd.%d mismatched publicsock.%d\n",pfds[n].fd,ptr->publicsock); |
|||
break; |
|||
} |
|||
else if ( (pfds[n].revents & POLLIN) != 0 ) |
|||
{ |
|||
//printf("publicsock.%d %s has pollin\n",ptr->publicsock,ptr->publicaddr);
|
|||
if ( (size= nn_recv(ptr->publicsock,&buf,NN_MSG,0)) > 0 ) |
|||
{ |
|||
ptr->lasttime = now; |
|||
sendsock = ptr->sendsock; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
n++; |
|||
if ( iter == 0 ) |
|||
{ |
|||
pfds[n].fd = ptr->sendsock; |
|||
pfds[n].events = POLLIN; |
|||
} |
|||
else |
|||
{ |
|||
if ( pfds[n].fd != ptr->sendsock ) |
|||
{ |
|||
printf("unexpected fd.%d mismatched sendsock.%d\n",pfds[n].fd,ptr->sendsock); |
|||
break; |
|||
} |
|||
else if ( (pfds[n].revents & POLLIN) != 0 ) |
|||
{ |
|||
if ( (size= nn_recv(ptr->sendsock,&buf,NN_MSG,0)) > 0 ) |
|||
{ |
|||
//printf("%s paired has pollin (%s)\n",ptr->sendaddr,(char *)buf);
|
|||
ptr->lasttime = now; |
|||
if ( ptr->ispaired != 0 ) |
|||
{ |
|||
sendsock = ptr->publicsock; |
|||
break; |
|||
} |
|||
else |
|||
{ |
|||
nn_freemsg(buf); |
|||
buf = 0; |
|||
size = 0; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
n++; |
|||
} |
|||
if ( iter == 0 ) |
|||
{ |
|||
if ( (retval= nn_poll(pfds,n,1)) <= 0 ) |
|||
{ |
|||
if ( retval != 0 ) |
|||
printf("nn_poll retval.%d\n",retval); |
|||
break; |
|||
} // else printf("num pfds.%d retval.%d\n",n,retval);
|
|||
} |
|||
} |
|||
//free(pfds);
|
|||
//printf("sendsock.%d Numpsocks.%d\n",sendsock,Numpsocks);
|
|||
if ( sendsock < 0 ) |
|||
{ |
|||
for (i=nonz=0; i<Numpsocks; i++) |
|||
{ |
|||
if ( i < Numpsocks ) |
|||
{ |
|||
ptr = &PSOCKS[i]; |
|||
if ( now > ptr->lasttime+PSOCK_KEEPALIVE ) |
|||
{ |
|||
printf("PSOCKS[%d] of %d (%u %u) lag.%d IDLETIMEOUT\n",i,Numpsocks,ptr->publicport,ptr->sendport,now - ptr->lasttime); |
|||
if ( ptr->publicsock >= 0 ) |
|||
nn_close(ptr->publicsock); |
|||
if ( ptr->sendsock >= 0 ) |
|||
nn_close(ptr->sendsock); |
|||
//portable_mutex_lock(&LP_psockmutex);
|
|||
if ( Numpsocks > 1 ) |
|||
{ |
|||
PSOCKS[i] = PSOCKS[--Numpsocks]; |
|||
memset(&PSOCKS[Numpsocks],0,sizeof(*ptr)); |
|||
} else Numpsocks = 0; |
|||
//portable_mutex_unlock(&LP_psockmutex);
|
|||
break; |
|||
} |
|||
else if ( now > ptr->lastping+PSOCK_KEEPALIVE/2 && ptr->errors < 3 ) |
|||
{ |
|||
ptr->lastping = now; |
|||
sendsock = ptr->sendsock; |
|||
sprintf(keepalive,"{\"method\":\"keepalive\",\"endpoint\":\"%s\"}",ptr->sendaddr); |
|||
size = (int32_t)strlen(keepalive) + 1; |
|||
buf = keepalive; |
|||
printf("send keepalive.(%s)\n",keepalive); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
if ( nonz == 0 && i == Numpsocks ) |
|||
usleep(100000); |
|||
} |
|||
portable_mutex_unlock(&LP_psockmutex); |
|||
} else usleep(100000); |
|||
} |
|||
} |
|||
|
|||
void LP_psockadd(int32_t ispaired,int32_t publicsock,uint16_t recvport,int32_t sendsock,uint16_t sendport,char *subaddr,char *publicaddr) |
|||
{ |
|||
struct psock *ptr; |
|||
portable_mutex_lock(&LP_psockmutex); |
|||
PSOCKS = realloc(PSOCKS,sizeof(*PSOCKS) * (Numpsocks + 1)); |
|||
ptr = &PSOCKS[Numpsocks++]; |
|||
ptr->ispaired = ispaired; |
|||
ptr->publicsock = publicsock; |
|||
ptr->publicport = recvport; |
|||
ptr->sendsock = sendsock; |
|||
ptr->sendport = sendport; |
|||
safecopy(ptr->sendaddr,subaddr,sizeof(ptr->sendaddr)); |
|||
safecopy(ptr->publicaddr,publicaddr,sizeof(ptr->publicaddr)); |
|||
ptr->lasttime = (uint32_t)time(NULL); |
|||
portable_mutex_unlock(&LP_psockmutex); |
|||
} |
|||
|
|||
int32_t LP_psockmark(char *publicaddr) |
|||
{ |
|||
int32_t i,retval = -1; struct psock *ptr; |
|||
portable_mutex_lock(&LP_psockmutex); |
|||
for (i=0; i<Numpsocks; i++) |
|||
{ |
|||
ptr = &PSOCKS[i]; |
|||
if ( strcmp(publicaddr,ptr->publicaddr) == 0 ) |
|||
{ |
|||
printf("mark PSOCKS[%d] %s for deletion\n",i,publicaddr); |
|||
ptr->lasttime = 0; |
|||
retval = i; |
|||
break; |
|||
} |
|||
} |
|||
portable_mutex_unlock(&LP_psockmutex); |
|||
return(retval); |
|||
} |
|||
|
|||
char *LP_psock(char *myipaddr,int32_t ispaired) |
|||
{ |
|||
char pushaddr[128],subaddr[128]; uint16_t i,publicport,subport,maxiters=100; int32_t timeout,maxsize,pullsock=-1,pubsock=-1; cJSON *retjson=0; |
|||
retjson = cJSON_CreateObject(); |
|||
publicport = Psockport++; |
|||
subport = Psockport++; |
|||
for (i=0; i<maxiters; i++,publicport+=2,subport+=2) |
|||
{ |
|||
if ( publicport < MIN_PSOCK_PORT ) |
|||
publicport = MIN_PSOCK_PORT+1; |
|||
if ( subport <= publicport ) |
|||
subport = publicport + 1; |
|||
pullsock = pubsock = -1; |
|||
nanomsg_transportname(1,pushaddr,myipaddr,publicport); |
|||
nanomsg_transportname(1,subaddr,myipaddr,subport); |
|||
if ( (pullsock= nn_socket(AF_SP,ispaired!=0?NN_PAIR:NN_PULL)) >= 0 && (pubsock= nn_socket(AF_SP,ispaired!=0?NN_PAIR:NN_PAIR)) >= 0 ) |
|||
{ |
|||
if ( nn_bind(pullsock,pushaddr) >= 0 && nn_bind(pubsock,subaddr) >= 0 ) |
|||
{ |
|||
timeout = 1; |
|||
nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); |
|||
timeout = 1; |
|||
nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); |
|||
if ( ispaired != 0 ) |
|||
{ |
|||
maxsize = 1024 * 1024; |
|||
nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVBUF,&maxsize,sizeof(maxsize)); |
|||
} |
|||
//if ( ispaired != 0 )
|
|||
{ |
|||
nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); |
|||
nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); |
|||
} |
|||
nanomsg_transportname(0,pushaddr,myipaddr,publicport); |
|||
nanomsg_transportname(0,subaddr,myipaddr,subport); |
|||
LP_psockadd(ispaired,pullsock,publicport,pubsock,subport,subaddr,pushaddr); |
|||
jaddstr(retjson,"result","success"); |
|||
jaddstr(retjson,"LPipaddr",myipaddr); |
|||
jaddstr(retjson,"connectaddr",subaddr); |
|||
jaddnum(retjson,"connectport",subport); |
|||
jaddnum(retjson,"ispaired",ispaired); |
|||
jaddstr(retjson,"publicaddr",pushaddr); |
|||
jaddnum(retjson,"publicport",publicport); |
|||
printf("i.%d publicaddr.(%s) for subaddr.(%s), pullsock.%d pubsock.%d\n",i,pushaddr,subaddr,pullsock,pubsock); |
|||
break; |
|||
} else printf("bind error on %s or %s\n",pushaddr,subaddr); |
|||
if ( pullsock >= 0 ) |
|||
nn_close(pullsock); |
|||
if ( pubsock >= 0 ) |
|||
nn_close(pubsock); |
|||
} |
|||
} |
|||
if ( Psockport > MAX_PSOCK_PORT ) |
|||
Psockport = MIN_PSOCK_PORT; |
|||
if ( i == maxiters ) |
|||
jaddstr(retjson,"error","cant find psock ports"); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
/*
|
|||
LP_pushaddr_get makes transparent the fact that most nodes cannot bind()! |
|||
|
|||
The idea is to create an LP node NN_PAIR sock that the LP node binds to and client node connects to. Additionally, the LP node creates an NN_PULL that other nodes can NN_PUSH to and returns this address in pushaddr/retval for the client node to register with. The desired result is that other than the initial LP node, all the other nodes do a normal NN_PUSH, requiring no change to the NN_PUSH/NN_PULL logic. Of course, the initial LP node needs to autoforward all packets from the public NN_PULL to the NN_PUB |
|||
|
|||
similar to LP_pushaddr_get, create an NN_PAIR for DEX atomic data, can be assumed to have a max lifetime of 2*INSTANTDEX_LOCKTIME |
|||
|
|||
both are combined in LP_psock_get |
|||
|
|||
*/ |
|||
|
|||
int32_t nn_tests(void *ctx,int32_t pullsock,char *pushaddr,int32_t nnother) |
|||
{ |
|||
int32_t sock,n,m,timeout,retval = -1; char msg[512],*retstr; |
|||
printf("nn_tests.(%s)\n",pushaddr); |
|||
if ( (sock= nn_socket(AF_SP,nnother)) >= 0 ) |
|||
{ |
|||
if ( nn_connect(sock,pushaddr) < 0 ) |
|||
printf("connect error %s\n",nn_strerror(nn_errno())); |
|||
else |
|||
{ |
|||
sleep(3); |
|||
timeout = 1; |
|||
nn_setsockopt(sock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); |
|||
sprintf(msg,"{\"method\":\"nn_tests\",\"ipaddr\":\"%s\"}",pushaddr); |
|||
n = LP_send(sock,msg,(int32_t)strlen(msg)+1,0); |
|||
sleep(3); |
|||
LP_pullsock_check(ctx,&retstr,"127.0.0.1",-1,pullsock,0.); |
|||
sprintf(msg,"{\"method\":\"nn_tests2\",\"ipaddr\":\"%s\"}",pushaddr); |
|||
m = LP_send(pullsock,msg,(int32_t)strlen(msg)+1,0); |
|||
printf(">>>>>>>>>>>>>>>>>>>>>> sent %d+%d bytes -> pullsock.%d retstr.(%s)\n",n,m,pullsock,retstr!=0?retstr:""); |
|||
if ( retstr != 0 ) |
|||
{ |
|||
free(retstr); |
|||
retval = 0; |
|||
} |
|||
} |
|||
nn_close(sock); |
|||
} |
|||
return(retval); |
|||
} |
|||
|
|||
int32_t LP_initpublicaddr(void *ctx,uint16_t *mypullportp,char *publicaddr,char *myipaddr,uint16_t mypullport,int32_t ispaired) |
|||
{ |
|||
int32_t nntype,pullsock,timeout; char bindaddr[128],connectaddr[128]; |
|||
*mypullportp = mypullport; |
|||
if ( ispaired == 0 ) |
|||
{ |
|||
if ( LP_canbind != 0 ) |
|||
nntype = LP_COMMAND_RECVSOCK; |
|||
else nntype = NN_PAIR;//NN_SUB;
|
|||
} else nntype = NN_PAIR; |
|||
if ( LP_canbind != 0 ) |
|||
{ |
|||
nanomsg_transportname(0,publicaddr,myipaddr,mypullport); |
|||
nanomsg_transportname(1,bindaddr,myipaddr,mypullport); |
|||
} |
|||
else |
|||
{ |
|||
*mypullportp = 0; |
|||
while ( *mypullportp == 0 ) |
|||
{ |
|||
if ( (*mypullportp= LP_psock_get(connectaddr,publicaddr,ispaired)) != 0 ) |
|||
break; |
|||
sleep(10); |
|||
printf("try to get publicaddr again\n"); |
|||
} |
|||
} |
|||
while ( 1 ) |
|||
{ |
|||
if ( (pullsock= nn_socket(AF_SP,nntype)) >= 0 ) |
|||
{ |
|||
if ( LP_canbind == 0 ) |
|||
{ |
|||
if ( nn_connect(pullsock,connectaddr) < 0 ) |
|||
{ |
|||
printf("bind to %s error for %s: %s\n",connectaddr,publicaddr,nn_strerror(nn_errno())); |
|||
exit(-1); |
|||
} else printf("nntype.%d NN_PAIR.%d connect to %s connectsock.%d\n",nntype,NN_PAIR,connectaddr,pullsock); |
|||
} |
|||
else |
|||
{ |
|||
if ( nn_bind(pullsock,bindaddr) < 0 ) |
|||
{ |
|||
printf("bind to %s error for %s: %s\n",bindaddr,publicaddr,nn_strerror(nn_errno())); |
|||
exit(-1); |
|||
} |
|||
} |
|||
timeout = 1; |
|||
nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); |
|||
timeout = 1; |
|||
nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); |
|||
//maxsize = 2 * 1024 * 1024;
|
|||
//nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVBUF,&maxsize,sizeof(maxsize));
|
|||
if ( nntype == NN_SUB ) |
|||
nn_setsockopt(pullsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); |
|||
} |
|||
if ( LP_canbind != 0 || ispaired != 0 || nn_tests(ctx,pullsock,publicaddr,NN_PUSH) >= 0 ) |
|||
break; |
|||
printf("nn_tests failed, try again\n"); |
|||
sleep(3); |
|||
if ( pullsock >= 0 ) |
|||
nn_close(pullsock); |
|||
} |
|||
return(pullsock); |
|||
} |
@ -0,0 +1,690 @@ |
|||
|
|||
/******************************************************************************
|
|||
* 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_ordermatch.c
|
|||
// marketmaker
|
|||
//
|
|||
|
|||
|
|||
struct basilisk_request *LP_requestinit(struct basilisk_request *rp,bits256 srchash,bits256 desthash,char *src,uint64_t srcsatoshis,char *dest,uint64_t destsatoshis,uint32_t timestamp,uint32_t quotetime,int32_t DEXselector) |
|||
{ |
|||
struct basilisk_request R; |
|||
memset(rp,0,sizeof(*rp)); |
|||
rp->srchash = srchash; |
|||
rp->srcamount = srcsatoshis; |
|||
rp->timestamp = timestamp; |
|||
rp->DEXselector = DEXselector; |
|||
safecopy(rp->src,src,sizeof(rp->src)); |
|||
safecopy(rp->dest,dest,sizeof(rp->dest)); |
|||
R = *rp; |
|||
rp->requestid = basilisk_requestid(rp); |
|||
rp->quotetime = quotetime; |
|||
rp->desthash = desthash; |
|||
rp->destamount = destsatoshis; |
|||
rp->quoteid = basilisk_quoteid(rp); |
|||
printf("r.%u %u, q.%u %u: %s %.8f -> %s %.8f\n",rp->timestamp,rp->requestid,rp->quotetime,rp->quoteid,rp->src,dstr(rp->srcamount),rp->dest,dstr(rp->destamount)); |
|||
return(rp); |
|||
} |
|||
|
|||
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); |
|||
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 ( 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->desttxfee != 0 ) |
|||
jadd64bits(retjson,"desttxfee",qp->desttxfee); |
|||
if ( qp->destsatoshis != 0 ) |
|||
{ |
|||
jadd64bits(retjson,"destsatoshis",qp->destsatoshis); |
|||
if ( qp->satoshis != 0 ) |
|||
{ |
|||
price = (double)qp->destsatoshis / qp->satoshis; |
|||
jaddnum(retjson,"price",price); |
|||
} |
|||
} |
|||
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"); |
|||
qp->satoshis = j64bits(argjson,"satoshis"); |
|||
qp->destsatoshis = j64bits(argjson,"destsatoshis"); |
|||
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,uint64_t destsatoshis) |
|||
{ |
|||
memset(qp,0,sizeof(*qp)); |
|||
if ( qp->timestamp == 0 ) |
|||
qp->timestamp = (uint32_t)time(NULL); |
|||
safecopy(qp->destcoin,destcoin,sizeof(qp->destcoin)); |
|||
if ( (qp->txfee= LP_getestimatedrate(utxo->coin)*LP_AVETXSIZE) < LP_MIN_TXFEE ) |
|||
qp->txfee = LP_MIN_TXFEE; |
|||
qp->satoshis = destsatoshis / price + 0.49; |
|||
if ( utxo->iambob == 0 || qp->txfee >= qp->satoshis || qp->txfee >= utxo->deposit.value || utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis) ) |
|||
{ |
|||
printf("quoteinit error.(%d %d %d %d) %.8f vs %.8f\n",utxo->iambob == 0,qp->txfee >= qp->satoshis,qp->txfee >= utxo->deposit.value,utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis),dstr(utxo->deposit.value),dstr(LP_DEPOSITSATOSHIS(qp->satoshis))); |
|||
return(-1); |
|||
} |
|||
qp->txid = utxo->payment.txid; |
|||
qp->vout = utxo->payment.vout; |
|||
qp->txid2 = utxo->deposit.txid; |
|||
qp->vout2 = utxo->deposit.vout; |
|||
qp->destsatoshis = destsatoshis; |
|||
if ( (qp->desttxfee= LP_getestimatedrate(qp->destcoin) * LP_AVETXSIZE) < LP_MIN_TXFEE ) |
|||
qp->desttxfee = LP_MIN_TXFEE; |
|||
if ( qp->desttxfee >= qp->destsatoshis ) |
|||
{ |
|||
printf("quoteinit desttxfee %.8f < %.8f destsatoshis\n",dstr(qp->desttxfee),dstr(qp->destsatoshis)); |
|||
return(-2); |
|||
} |
|||
safecopy(qp->srccoin,utxo->coin,sizeof(qp->srccoin)); |
|||
safecopy(qp->coinaddr,utxo->coinaddr,sizeof(qp->coinaddr)); |
|||
qp->srchash = utxo->pubkey; |
|||
return(0); |
|||
} |
|||
|
|||
int32_t LP_quotedestinfo(struct LP_quoteinfo *qp,bits256 desttxid,int32_t destvout,bits256 feetxid,int32_t feevout,bits256 desthash,char *destaddr) |
|||
{ |
|||
qp->desttxid = desttxid; |
|||
qp->destvout = destvout; |
|||
qp->desthash = desthash; |
|||
qp->feetxid = feetxid; |
|||
qp->feevout = feevout; |
|||
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; |
|||
printf(">>>>>>>>>> received quote %s/%s %.8f\n",Q.srccoin,Q.destcoin,price); |
|||
return(clonestr("{\"result\":\"updated\"}")); |
|||
} else return(clonestr("{\"error\":\"nullptr\"}")); |
|||
} |
|||
|
|||
char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,char *base,char *rel,double price) |
|||
{ |
|||
bits256 zero; char *msg; cJSON *reqjson = cJSON_CreateObject(); |
|||
jaddbits256(reqjson,"pubkey",LP_mypubkey); |
|||
jaddstr(reqjson,"base",base); |
|||
jaddstr(reqjson,"rel",rel); |
|||
jaddnum(reqjson,"price",price); |
|||
if ( pubsock >= 0 ) |
|||
{ |
|||
jaddstr(reqjson,"method","postprice"); |
|||
//printf("%d pricepings.(%s)\n",pubsock,jprint(reqjson,0));
|
|||
msg = jprint(reqjson,1); |
|||
LP_send(pubsock,msg,(int32_t)strlen(msg)+1,1); |
|||
} |
|||
else |
|||
{ |
|||
jaddstr(reqjson,"method","forward"); |
|||
jaddstr(reqjson,"method2","postprice"); |
|||
memset(zero.bytes,0,sizeof(zero)); |
|||
LP_forward(ctx,myipaddr,pubsock,profitmargin,zero,jprint(reqjson,1),1); |
|||
} |
|||
return(clonestr("{\"result\":\"success\"}")); |
|||
} |
|||
|
|||
char *LP_postedprice(cJSON *argjson) |
|||
{ |
|||
bits256 pubkey; double price; char *base,*rel; |
|||
//printf("PRICE POSTED.(%s)\n",jprint(argjson,0));
|
|||
if ( (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 && (price= jdouble(argjson,"price")) > SMALLVAL ) |
|||
{ |
|||
pubkey = jbits256(argjson,"pubkey"); |
|||
if ( bits256_nonz(pubkey) != 0 ) |
|||
{ |
|||
LP_pricefeedupdate(pubkey,base,rel,price); |
|||
return(clonestr("{\"result\":\"success\"}")); |
|||
} |
|||
} |
|||
return(clonestr("{\"error\":\"missing fields in posted price\"}")); |
|||
} |
|||
|
|||
int32_t LP_quote_checkmempool(struct LP_quoteinfo *qp) |
|||
{ |
|||
int32_t selector,spendvini; bits256 spendtxid; |
|||
if ( (selector= LP_mempool_vinscan(&spendtxid,&spendvini,qp->srccoin,qp->txid,qp->vout,qp->txid2,qp->vout2)) >= 0 ) |
|||
{ |
|||
char str[65]; printf("LP_tradecommand selector.%d in mempool %s vini.%d",selector,bits256_str(str,spendtxid),spendvini); |
|||
return(-1); |
|||
} |
|||
if ( (selector= LP_mempool_vinscan(&spendtxid,&spendvini,qp->destcoin,qp->desttxid,qp->destvout,qp->feetxid,qp->feevout)) >= 0 ) |
|||
{ |
|||
char str[65]; printf("LP_tradecommand dest selector.%d in mempool %s vini.%d",selector,bits256_str(str,spendtxid),spendvini); |
|||
return(-1); |
|||
} |
|||
return(0); |
|||
} |
|||
|
|||
double LP_quote_validate(struct LP_utxoinfo **autxop,struct LP_utxoinfo **butxop,struct LP_quoteinfo *qp,int32_t iambob) |
|||
{ |
|||
double qprice; uint64_t srcvalue,srcvalue2,destvalue,destvalue2; |
|||
*autxop = *butxop = 0; |
|||
if ( LP_iseligible(&srcvalue,&srcvalue2,1,qp->srccoin,qp->txid,qp->vout,qp->satoshis,qp->txid2,qp->vout2,qp->srchash) == 0 ) |
|||
{ |
|||
printf("bob not eligible\n"); |
|||
return(-2); |
|||
} |
|||
if ( LP_iseligible(&destvalue,&destvalue2,0,qp->destcoin,qp->desttxid,qp->destvout,qp->destsatoshis,qp->feetxid,qp->feevout,qp->desthash) == 0 ) |
|||
{ |
|||
char str[65]; printf("alice not eligible (%.8f %.8f) %s/v%d\n",dstr(destvalue),dstr(destvalue2),bits256_str(str,qp->feetxid),qp->feevout); |
|||
return(-3); |
|||
} |
|||
if ( LP_quote_checkmempool(qp) < 0 ) |
|||
return(-4); |
|||
if ( (*butxop= LP_utxofind(1,qp->txid,qp->vout)) == 0 ) |
|||
return(-5); |
|||
if ( bits256_cmp((*butxop)->deposit.txid,qp->txid2) != 0 || (*butxop)->deposit.vout != qp->vout2 ) |
|||
return(-6); |
|||
if ( strcmp((*butxop)->coinaddr,qp->coinaddr) != 0 ) |
|||
return(-7); |
|||
if ( iambob == 0 ) |
|||
{ |
|||
if ( (*autxop= LP_utxofind(0,qp->desttxid,qp->destvout)) == 0 ) |
|||
return(-8); |
|||
if ( bits256_cmp((*autxop)->fee.txid,qp->feetxid) != 0 || (*autxop)->fee.vout != qp->feevout ) |
|||
return(-9); |
|||
if ( strcmp((*autxop)->coinaddr,qp->destaddr) != 0 ) |
|||
return(-10); |
|||
} |
|||
if ( destvalue < qp->desttxfee+qp->destsatoshis || srcvalue < qp->txfee+qp->satoshis ) |
|||
{ |
|||
printf("destvalue %.8f srcvalue %.8f, destsatoshis %.8f or satoshis %.8f is too small txfees %.8f %.8f?\n",dstr(destvalue),dstr(srcvalue),dstr(qp->destsatoshis),dstr(qp->satoshis),dstr(qp->desttxfee),dstr(qp->txfee)); |
|||
return(-11); |
|||
} |
|||
qprice = ((double)qp->destsatoshis / qp->satoshis); |
|||
if ( qp->satoshis < (srcvalue >> LP_MINVOL) ) |
|||
{ |
|||
printf("utxo payment %.8f is less than half covered by Q %.8f\n",dstr(srcvalue),dstr(qp->satoshis)); |
|||
return(-12); |
|||
} |
|||
if ( qp->destsatoshis < (destvalue >> LP_MINCLIENTVOL) ) |
|||
{ |
|||
printf("destsatoshis %.8f is less than half of value %.8f\n",dstr(qp->destsatoshis),dstr(destvalue)); |
|||
return(-13); |
|||
} |
|||
printf("qprice %.8f <- %.8f/%.8f txfees.(%.8f %.8f)\n",qprice,dstr(qp->destsatoshis),dstr(qp->satoshis),dstr(qp->txfee),dstr(qp->desttxfee)); |
|||
return(qprice); |
|||
} |
|||
|
|||
int32_t LP_arrayfind(cJSON *array,bits256 txid,int32_t vout) |
|||
{ |
|||
int32_t i,n = cJSON_GetArraySize(array); cJSON *item; |
|||
for (i=0; i<n; i++) |
|||
{ |
|||
item = jitem(array,i); |
|||
if ( vout == jint(item,"vout") && bits256_cmp(txid,jbits256(item,"txid")) == 0 ) |
|||
return(i); |
|||
} |
|||
return(-1); |
|||
} |
|||
|
|||
double LP_query(void *ctx,char *myipaddr,int32_t mypubsock,double profitmargin,char *method,struct LP_quoteinfo *qp) |
|||
{ |
|||
cJSON *reqjson; char *msg; int32_t i,flag = 0; double price = 0.; struct LP_utxoinfo *utxo; |
|||
if ( strcmp(method,"request") == 0 ) |
|||
{ |
|||
if ( (utxo= LP_utxofind(0,qp->desttxid,qp->destvout)) != 0 && LP_ismine(utxo) > 0 && LP_isavailable(utxo) > 0 ) |
|||
LP_unavailableset(utxo,qp->srchash); |
|||
else |
|||
{ |
|||
printf("couldnt find my txid to make request\n"); |
|||
return(0.); |
|||
} |
|||
} |
|||
reqjson = LP_quotejson(qp); |
|||
if ( bits256_nonz(qp->desthash) != 0 ) |
|||
flag = 1; |
|||
//printf("QUERY.(%s)\n",jprint(reqjson,0));
|
|||
if ( IAMLP != 0 ) |
|||
{ |
|||
jaddstr(reqjson,"method",method); |
|||
msg = jprint(reqjson,1); |
|||
LP_send(LP_mypubsock,msg,(int32_t)strlen(msg)+1,1); |
|||
} |
|||
else |
|||
{ |
|||
jaddstr(reqjson,"method2",method); |
|||
jaddstr(reqjson,"method","forward"); |
|||
jaddbits256(reqjson,"pubkey",qp->srchash); |
|||
LP_forward(ctx,myipaddr,mypubsock,profitmargin,qp->srchash,jprint(reqjson,1),1); |
|||
} |
|||
for (i=0; i<30; i++) |
|||
{ |
|||
if ( (price= LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout)) > SMALLVAL ) |
|||
{ |
|||
if ( flag == 0 || bits256_nonz(qp->desthash) != 0 ) |
|||
{ |
|||
//printf("break out of loop.%d price %.8f\n",i,price);
|
|||
break; |
|||
} |
|||
} |
|||
usleep(100000); |
|||
} |
|||
return(price); |
|||
} |
|||
|
|||
int32_t LP_nanobind(void *ctx,char *pairstr) |
|||
{ |
|||
int32_t i,timeout,r,pairsock = -1; uint16_t mypullport; char bindaddr[128]; |
|||
if ( LP_canbind != 0 ) |
|||
{ |
|||
if ( (pairsock= nn_socket(AF_SP,NN_PAIR)) < 0 ) |
|||
printf("error creating utxo->pair\n"); |
|||
else |
|||
{ |
|||
for (i=0; i<10; i++) |
|||
{ |
|||
r = (10000 + (rand() % 50000)) & 0xffff; |
|||
if ( LP_fixed_pairport != 0 ) |
|||
r = LP_fixed_pairport; |
|||
nanomsg_transportname(0,pairstr,LP_myipaddr,r); |
|||
nanomsg_transportname(1,bindaddr,LP_myipaddr,r); |
|||
if ( nn_bind(pairsock,bindaddr) >= 0 ) |
|||
{ |
|||
timeout = 100; |
|||
nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); |
|||
nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); |
|||
printf("nanobind %s to %d\n",pairstr,pairsock); |
|||
return(pairsock); |
|||
} else printf("error binding to %s for %s\n",bindaddr,pairstr); |
|||
if ( LP_fixed_pairport != 0 ) |
|||
break; |
|||
} |
|||
} |
|||
} else pairsock = LP_initpublicaddr(ctx,&mypullport,pairstr,"127.0.0.1",0,1); |
|||
return(pairsock); |
|||
} |
|||
|
|||
int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJSON *argjson,char *myipaddr,char *base,char *rel,double profitmargin,double price,struct LP_quoteinfo *qp) |
|||
{ |
|||
char pairstr[512],*msg; cJSON *retjson; bits256 privkey; int32_t pair=-1,retval = -1,DEXselector = 0; struct basilisk_swap *swap; struct iguana_info *coin; |
|||
printf("LP_connectstartbob.(%s) with.(%s) %s\n",myipaddr,jprint(argjson,0),LP_myipaddr); |
|||
qp->quotetime = (uint32_t)time(NULL); |
|||
if ( (coin= LP_coinfind(utxo->coin)) == 0 ) |
|||
{ |
|||
printf("cant find coin.%s\n",utxo->coin); |
|||
return(-1); |
|||
} |
|||
privkey = LP_privkey(utxo->coinaddr,coin->taddr); |
|||
if ( bits256_nonz(privkey) != 0 && qp->quotetime >= qp->timestamp-3 && qp->quotetime <= utxo->T.swappending && bits256_cmp(LP_mypubkey,qp->srchash) == 0 ) |
|||
{ |
|||
if ( (pair= LP_nanobind(ctx,pairstr)) >= 0 ) |
|||
{ |
|||
LP_requestinit(&qp->R,qp->srchash,qp->desthash,base,qp->satoshis,rel,qp->destsatoshis,qp->timestamp,qp->quotetime,DEXselector); |
|||
swap = LP_swapinit(1,0,privkey,&qp->R,qp); |
|||
swap->N.pair = pair; |
|||
utxo->S.swap = swap; |
|||
swap->utxo = utxo; |
|||
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_bobloop,(void *)swap) == 0 ) |
|||
{ |
|||
retjson = LP_quotejson(qp); |
|||
jaddstr(retjson,"method","connected"); |
|||
jaddstr(retjson,"pair",pairstr); |
|||
jaddnum(retjson,"requestid",qp->R.requestid); |
|||
jaddnum(retjson,"quoteid",qp->R.quoteid); |
|||
char str[65]; printf("BOB pubsock.%d sends to (%s)\n",pubsock,bits256_str(str,utxo->S.otherpubkey)); |
|||
if ( pubsock >= 0 ) |
|||
{ |
|||
msg = jprint(retjson,0); |
|||
LP_send(pubsock,msg,(int32_t)strlen(msg)+1,1); |
|||
} |
|||
jdelete(retjson,"method"); |
|||
jaddstr(retjson,"method2","connected"); |
|||
jaddstr(retjson,"method","forward"); |
|||
LP_forward(ctx,myipaddr,pubsock,profitmargin,utxo->S.otherpubkey,jprint(retjson,1),1); |
|||
retval = 0; |
|||
} else printf("error launching swaploop\n"); |
|||
} else printf("couldnt bind to any port %s\n",pairstr); |
|||
} |
|||
else |
|||
{ |
|||
printf("dest %.8f vs required %.8f (%d %d %d %d %d)\n",dstr(qp->destsatoshis),dstr(price*(utxo->S.satoshis-qp->txfee)),bits256_nonz(privkey) != 0 ,qp->timestamp == utxo->T.swappending-LP_RESERVETIME,qp->quotetime >= qp->timestamp-3,qp->quotetime < utxo->T.swappending,bits256_cmp(LP_mypubkey,qp->srchash) == 0); |
|||
} |
|||
if ( retval < 0 ) |
|||
{ |
|||
if ( pair >= 0 ) |
|||
nn_close(pair); |
|||
LP_availableset(utxo); |
|||
} else LP_unavailableset(utxo,utxo->S.otherpubkey); |
|||
return(retval); |
|||
} |
|||
|
|||
char *LP_connectedalice(cJSON *argjson) // alice
|
|||
{ |
|||
cJSON *retjson; double bid,ask,price,qprice; int32_t timeout,pairsock = -1; char *pairstr; int32_t DEXselector = 0; struct LP_utxoinfo *autxo,*butxo; struct LP_quoteinfo Q; struct basilisk_swap *swap; struct iguana_info *coin; |
|||
if ( LP_quoteparse(&Q,argjson) < 0 ) |
|||
clonestr("{\"error\":\"cant parse quote\"}"); |
|||
if ( bits256_cmp(Q.desthash,LP_mypubkey) != 0 ) |
|||
return(clonestr("{\"result\",\"update stats\"}")); |
|||
printf("CONNECTED.(%s)\n",jprint(argjson,0)); |
|||
if ( (qprice= LP_quote_validate(&autxo,&butxo,&Q,0)) <= SMALLVAL ) |
|||
{ |
|||
LP_availableset(autxo); |
|||
printf("quote validate error %.0f\n",qprice); |
|||
return(clonestr("{\"error\":\"quote validation error\"}")); |
|||
} |
|||
if ( (price= LP_myprice(&bid,&ask,Q.destcoin,Q.srccoin)) <= SMALLVAL || ask <= SMALLVAL ) |
|||
{ |
|||
printf("this node has no price for %s/%s (%.8f %.8f)\n",Q.destcoin,Q.srccoin,bid,ask); |
|||
LP_availableset(autxo); |
|||
return(clonestr("{\"error\":\"no price set\"}")); |
|||
} |
|||
price = 1. / ask; |
|||
if ( qprice > price+0.00000001 ) |
|||
{ |
|||
printf("qprice %.8f too big vs %.8f\n",qprice,price); |
|||
LP_availableset(autxo); |
|||
return(clonestr("{\"error\":\"quote price too expensive\"}")); |
|||
} |
|||
if ( (coin= LP_coinfind(Q.destcoin)) == 0 ) |
|||
{ |
|||
return(clonestr("{\"error\":\"cant get alicecoin\"}")); |
|||
} |
|||
Q.privkey = LP_privkey(Q.destaddr,coin->taddr); |
|||
if ( bits256_nonz(Q.privkey) != 0 && Q.quotetime >= Q.timestamp-3 ) |
|||
{ |
|||
retjson = cJSON_CreateObject(); |
|||
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 ) |
|||
{ |
|||
timeout = 100; |
|||
nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); |
|||
nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); |
|||
LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis,Q.destcoin,Q.destsatoshis,Q.timestamp,Q.quotetime,DEXselector); |
|||
swap = LP_swapinit(0,0,Q.privkey,&Q.R,&Q); |
|||
swap->N.pair = pairsock; |
|||
autxo->S.swap = swap; |
|||
swap->utxo = autxo; |
|||
printf("alice pairstr.(%s) pairsock.%d\n",pairstr,pairsock); |
|||
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_aliceloop,(void *)swap) == 0 ) |
|||
{ |
|||
jaddstr(retjson,"result","success"); |
|||
jadd(retjson,"trade",LP_quotejson(&Q)); |
|||
jaddnum(retjson,"requestid",Q.R.requestid); |
|||
jaddnum(retjson,"quoteid",Q.R.quoteid); |
|||
} else jaddstr(retjson,"error","couldnt aliceloop"); |
|||
} else printf("connect error %s\n",nn_strerror(nn_errno())); |
|||
printf("connected result.(%s)\n",jprint(retjson,0)); |
|||
if ( jobj(retjson,"error") != 0 ) |
|||
LP_availableset(autxo); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
else |
|||
{ |
|||
LP_availableset(autxo); |
|||
printf("no privkey found\n"); |
|||
return(clonestr("{\"error\",\"no privkey\"}")); |
|||
} |
|||
} |
|||
|
|||
int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin) |
|||
{ |
|||
char *method,*msg; cJSON *retjson; double qprice,price,bid,ask; struct LP_utxoinfo *autxo,*butxo; int32_t retval = -1; struct LP_quoteinfo Q; |
|||
if ( (method= jstr(argjson,"method")) != 0 && (strcmp(method,"request") == 0 ||strcmp(method,"connect") == 0) ) |
|||
{ |
|||
//printf("TRADECOMMAND.(%s)\n",jprint(argjson,0));
|
|||
retval = 1; |
|||
if ( LP_quoteparse(&Q,argjson) == 0 && bits256_cmp(LP_mypubkey,Q.srchash) == 0 ) |
|||
{ |
|||
if ( (price= LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin)) <= SMALLVAL || ask <= SMALLVAL ) |
|||
{ |
|||
printf("this node has no price for %s/%s\n",Q.srccoin,Q.destcoin); |
|||
return(-3); |
|||
} |
|||
price = ask; |
|||
if ( (qprice= LP_quote_validate(&autxo,&butxo,&Q,1)) <= SMALLVAL ) |
|||
{ |
|||
printf("quote validate error %.0f\n",qprice); |
|||
return(-4); |
|||
} |
|||
if ( qprice < price-0.00000001 ) |
|||
{ |
|||
printf("(%.8f %.8f) quote price %.8f too low vs %.8f for %s/%s\n",bid,ask,qprice,price,Q.srccoin,Q.destcoin); |
|||
return(-5); |
|||
} |
|||
if ( butxo->S.swap == 0 && time(NULL) > butxo->T.swappending ) |
|||
butxo->T.swappending = 0; |
|||
if ( strcmp(method,"request") == 0 ) // bob needs apayment + fee tx's
|
|||
{ |
|||
if ( LP_isavailable(butxo) > 0 ) |
|||
{ |
|||
butxo->T.swappending = Q.timestamp + LP_RESERVETIME; |
|||
retjson = LP_quotejson(&Q); |
|||
butxo->S.otherpubkey = jbits256(argjson,"desthash"); |
|||
LP_unavailableset(butxo,butxo->S.otherpubkey); |
|||
jaddnum(retjson,"quotetime",juint(argjson,"quotetime")); |
|||
jaddnum(retjson,"pending",butxo->T.swappending); |
|||
jaddbits256(retjson,"desthash",butxo->S.otherpubkey); |
|||
jaddbits256(retjson,"pubkey",butxo->S.otherpubkey); |
|||
jaddstr(retjson,"method","reserved"); |
|||
if ( pubsock >= 0 ) |
|||
{ |
|||
msg = jprint(retjson,0); |
|||
LP_send(pubsock,msg,(int32_t)strlen(msg)+1,1); |
|||
} |
|||
jdelete(retjson,"method"); |
|||
jaddstr(retjson,"method2","reserved"); |
|||
jaddstr(retjson,"method","forward"); |
|||
LP_forward(ctx,myipaddr,pubsock,profitmargin,butxo->S.otherpubkey,jprint(retjson,1),1); |
|||
butxo->T.lasttime = (uint32_t)time(NULL); |
|||
printf("set swappending.%u accept qprice %.8f, min %.8f\n",butxo->T.swappending,qprice,price); |
|||
} else printf("warning swappending.%u swap.%p\n",butxo->T.swappending,butxo->S.swap); |
|||
} |
|||
else if ( strcmp(method,"connect") == 0 ) // bob
|
|||
{ |
|||
retval = 4; |
|||
if ( butxo->T.swappending != 0 && butxo->S.swap == 0 ) |
|||
LP_connectstartbob(ctx,pubsock,butxo,argjson,myipaddr,Q.srccoin,Q.destcoin,profitmargin,qprice,&Q); |
|||
else printf("pend.%u swap %p when connect came in (%s)\n",butxo->T.swappending,butxo->S.swap,jprint(argjson,0)); |
|||
} |
|||
} |
|||
} |
|||
return(retval); |
|||
} |
|||
|
|||
char *LP_autotrade(void *ctx,char *myipaddr,int32_t mypubsock,double profitmargin,char *base,char *rel,double maxprice,double volume,int32_t timeout) |
|||
{ |
|||
int64_t satoshis,destsatoshis,desttxfee,txfee,bestdestsatoshis=0; bits256 txid,pubkey; char *obookstr,*retstr; cJSON *orderbook,*asks,*item,*bestitem=0; struct LP_utxoinfo *autxo,*butxo,*bestutxo = 0; int32_t i,vout,numasks,DEXselector=0; uint32_t expiration; double ordermatchprice,bestmetric,metric,bestprice=0.,vol,price; struct LP_quoteinfo Q; struct LP_pubkeyinfo *pubp; |
|||
if ( maxprice <= 0. || volume <= 0. || LP_priceinfofind(base) == 0 || LP_priceinfofind(rel) == 0 ) |
|||
return(clonestr("{\"error\":\"invalid parameter\"}")); |
|||
if ( (autxo= LP_utxo_bestfit(rel,SATOSHIDEN * volume)) == 0 ) |
|||
return(clonestr("{\"error\":\"cant find utxo that is big enough\"}")); |
|||
bestmetric = ordermatchprice = 0.; |
|||
if ( (desttxfee= LP_getestimatedrate(rel) * LP_AVETXSIZE) < LP_MIN_TXFEE ) |
|||
desttxfee = LP_MIN_TXFEE; |
|||
if ( (txfee= LP_getestimatedrate(base) * LP_AVETXSIZE) < LP_MIN_TXFEE ) |
|||
txfee = LP_MIN_TXFEE; |
|||
if ( timeout == 0 ) |
|||
timeout = LP_AUTOTRADE_TIMEOUT; |
|||
if ( (obookstr= LP_orderbook(base,rel)) != 0 ) |
|||
{ |
|||
if ( (orderbook= cJSON_Parse(obookstr)) != 0 ) |
|||
{ |
|||
if ( (asks= jarray(&numasks,orderbook,"asks")) != 0 ) |
|||
{ |
|||
for (i=0; i<numasks; i++) |
|||
{ |
|||
item = jitem(asks,i); |
|||
if ( (price= jdouble(item,"price")) > SMALLVAL && price <= maxprice ) |
|||
{ |
|||
price *= 1.0001; |
|||
if ( price > maxprice ) |
|||
price = maxprice; |
|||
pubkey = jbits256(item,"pubkey"); |
|||
if ( bits256_cmp(pubkey,LP_mypubkey) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 && pubp->numerrors < LP_MAXPUBKEY_ERRORS ) |
|||
{ |
|||
if ( bestprice == 0. ) // assumes price ordered asks
|
|||
bestprice = price; |
|||
//printf("item.[%d] %s\n",i,jprint(item,0));
|
|||
txid = jbits256(item,"txid"); |
|||
vout = jint(item,"vout"); |
|||
vol = jdouble(item,"volume"); |
|||
metric = price / bestprice; |
|||
if ( (butxo= LP_utxofind(1,txid,vout)) != 0 && (long long)(vol*SATOSHIDEN) == butxo->S.satoshis && LP_isavailable(butxo) > 0 && LP_ismine(butxo) == 0 && butxo->T.bestflag == 0 ) |
|||
{ |
|||
destsatoshis = ((butxo->S.satoshis - txfee) * price); |
|||
if ( destsatoshis > autxo->payment.value-desttxfee-1 ) |
|||
destsatoshis = autxo->payment.value-desttxfee-1; |
|||
satoshis = (destsatoshis / price + 0.0000000049) - txfee; |
|||
if ( metric < 1.2 && destsatoshis > desttxfee && destsatoshis-desttxfee > (autxo->payment.value >> LP_MINCLIENTVOL) && satoshis-txfee > (butxo->S.satoshis >> LP_MINVOL) && satoshis <= butxo->payment.value-txfee ) |
|||
{ |
|||
printf("value %.8f price %.8f/%.8f best %.8f destsatoshis %.8f * metric %.8f -> (%f)\n",dstr(autxo->payment.value),price,bestprice,bestmetric,dstr(destsatoshis),metric,dstr(destsatoshis) * metric * metric * metric); |
|||
metric = dstr(destsatoshis) * metric * metric * metric; |
|||
if ( bestmetric == 0. || metric < bestmetric ) |
|||
{ |
|||
bestutxo = butxo; |
|||
ordermatchprice = price; |
|||
bestdestsatoshis = destsatoshis; |
|||
bestmetric = metric; |
|||
printf("set best!\n"); |
|||
} |
|||
} else printf("skip.(%d %d %d %d %d) metric %f destsatoshis %.8f value %.8f destvalue %.8f txfees %.8f %.8f sats %.8f\n",metric < 1.2,destsatoshis > desttxfee,destsatoshis-desttxfee > (autxo->payment.value >> LP_MINCLIENTVOL),satoshis-txfee > (butxo->S.satoshis >> LP_MINVOL),satoshis < butxo->payment.value-txfee,metric,dstr(destsatoshis),dstr(butxo->S.satoshis),dstr(autxo->payment.value),dstr(txfee),dstr(desttxfee),dstr(satoshis)); |
|||
} |
|||
else |
|||
{ |
|||
if ( butxo != 0 ) |
|||
printf("%llu %llu %d %d %d: ",(long long)(vol*SATOSHIDEN),(long long)butxo->S.satoshis,vol*SATOSHIDEN == butxo->S.satoshis,LP_isavailable(butxo) > 0,LP_ismine(butxo) == 0); |
|||
printf("cant find butxo.%p or value mismatch %.8f != %.8f\n",butxo,vol,butxo!=0?dstr(butxo->S.satoshis):0); |
|||
} |
|||
} |
|||
} else break; |
|||
} |
|||
} |
|||
free_json(orderbook); |
|||
} |
|||
free(obookstr); |
|||
} |
|||
if ( bestutxo == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 ) |
|||
return(clonestr("{\"error\":\"cant find ordermatch utxo\"}")); |
|||
if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestdestsatoshis) < 0 ) |
|||
return(clonestr("{\"error\":\"cant set ordermatch quote\"}")); |
|||
if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,LP_mypubkey,autxo->coinaddr) < 0 ) |
|||
return(clonestr("{\"error\":\"cant set ordermatch quote info\"}")); |
|||
bestutxo->T.bestflag = (uint32_t)time(NULL); |
|||
if ( (retstr= LP_registerall(0)) != 0 ) |
|||
free(retstr); |
|||
price = LP_query(ctx,myipaddr,mypubsock,profitmargin,"request",&Q); |
|||
bestitem = LP_quotejson(&Q); |
|||
if ( price > SMALLVAL ) |
|||
{ |
|||
if ( price <= maxprice ) |
|||
{ |
|||
price = LP_query(ctx,myipaddr,mypubsock,profitmargin,"connect",&Q); |
|||
LP_requestinit(&Q.R,Q.srchash,Q.desthash,base,Q.satoshis,Q.destcoin,Q.destsatoshis,Q.timestamp,Q.quotetime,DEXselector); |
|||
expiration = (uint32_t)time(NULL) + timeout; |
|||
while ( time(NULL) < expiration ) |
|||
{ |
|||
if ( autxo->S.swap != 0 ) |
|||
break; |
|||
sleep(1); |
|||
} |
|||
if ( autxo->S.swap == 0 ) |
|||
{ |
|||
if ( (pubp= LP_pubkeyadd(bestutxo->pubkey)) != 0 ) |
|||
pubp->numerrors++; |
|||
jaddstr(bestitem,"status","couldnt establish connection"); |
|||
} else jaddstr(bestitem,"status","connected"); |
|||
jaddnum(bestitem,"quotedprice",price); |
|||
jaddnum(bestitem,"maxprice",maxprice); |
|||
jaddnum(bestitem,"requestid",Q.R.requestid); |
|||
jaddnum(bestitem,"quoteid",Q.R.quoteid); |
|||
printf("Alice r.%u q.%u\n",Q.R.requestid,Q.R.quoteid); |
|||
} |
|||
else |
|||
{ |
|||
jaddnum(bestitem,"quotedprice",price); |
|||
jaddnum(bestitem,"maxprice",maxprice); |
|||
jaddstr(bestitem,"status","too expensive"); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
jaddnum(bestitem,"maxprice",maxprice); |
|||
jaddstr(bestitem,"status","no response to request"); |
|||
} |
|||
if ( autxo->S.swap == 0 ) |
|||
LP_availableset(autxo); |
|||
return(jprint(bestitem,0)); |
|||
} |
|||
|
|||
|
|||
|
|||
|
@ -0,0 +1,197 @@ |
|||
|
|||
/******************************************************************************
|
|||
* 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) |
|||
{ |
|||
//if ( peer->errors < LP_MAXPEER_ERRORS )
|
|||
jaddi(peersjson,LP_peerjson(peer)); |
|||
} |
|||
return(jprint(peersjson,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 maxsize,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 ) |
|||
{ |
|||
if ( (peer= LP_peerfind(ipbits,port)) != 0 ) |
|||
{ |
|||
if ( 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 ( pushport != 0 && subport != 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 ) |
|||
{ |
|||
nanomsg_transportname(0,pushaddr,peer->ipaddr,pushport); |
|||
if ( nn_connect(pushsock,pushaddr) >= 0 ) |
|||
{ |
|||
timeout = 100; |
|||
nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); |
|||
maxsize = 2 * 1024 * 1024; |
|||
nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDBUF,&maxsize,sizeof(maxsize)); |
|||
printf("connected to push.(%s) %d\n",pushaddr,pushsock); |
|||
peer->connected = (uint32_t)time(NULL); |
|||
peer->pushsock = pushsock; |
|||
if ( (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_transportname(0,subaddr,peer->ipaddr,subport); |
|||
if ( nn_connect(subsock,subaddr) >= 0 ) |
|||
{ |
|||
peer->subsock = subsock; |
|||
printf("connected to sub.(%s) %d\n",subaddr,peer->subsock); |
|||
} 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 ) |
|||
{ |
|||
char *msg = jprint(LP_peerjson(peer),1); |
|||
LP_send(mypubsock,msg,(int32_t)strlen(msg)+1,1); |
|||
} |
|||
} |
|||
} else printf("LP_addpeer: checkip.(%s) vs (%s)\n",checkip,ipaddr); |
|||
return(peer); |
|||
} |
|||
|
|||
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 ( (n= cJSON_GetArraySize(array)) > 0 ) |
|||
{ |
|||
for (i=0; i<n; i++) |
|||
{ |
|||
item = jitem(array,i); |
|||
if ( (argipaddr= jstr(item,"ipaddr")) != 0 && (argport= juint(item,"port")) != 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 ) |
|||
{ |
|||
peer->lasttime = now; |
|||
if ( strcmp(argipaddr,destipaddr) == 0 && destport == argport && peer->numpeers != n ) |
|||
peer->numpeers = n; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
free_json(array); |
|||
} |
|||
return(n); |
|||
} |
|||
|
|||
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 ( (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(mypeer,mypubsock,destipaddr,destport,retstr,now); |
|||
free(retstr); |
|||
if ( IAMLP != 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"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
int32_t LP_numpeers() |
|||
{ |
|||
struct LP_peerinfo *peer,*tmp; int32_t numpeers = 0; |
|||
HASH_ITER(hh,LP_peerinfos,peer,tmp) |
|||
{ |
|||
numpeers++; |
|||
} |
|||
return(numpeers); |
|||
} |
@ -0,0 +1,691 @@ |
|||
|
|||
/******************************************************************************
|
|||
* 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_prices.c
|
|||
// marketmaker
|
|||
//
|
|||
|
|||
struct LP_orderbookentry { bits256 txid,txid2,pubkey; double price; uint64_t basesatoshis; int32_t vout,vout2; }; |
|||
|
|||
#define LP_MAXPRICEINFOS 256 |
|||
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; |
|||
|
|||
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; |
|||
|
|||
struct LP_pubkeyinfo |
|||
{ |
|||
UT_hash_handle hh; |
|||
bits256 pubkey; |
|||
double matrix[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS]; |
|||
uint32_t timestamp,istrusted,numerrors; |
|||
} *LP_pubkeyinfos; |
|||
|
|||
struct LP_priceinfo *LP_priceinfofind(char *symbol) |
|||
{ |
|||
int32_t i; struct LP_priceinfo *pp; uint64_t coinbits; |
|||
if ( symbol == 0 || symbol[0] == 0 ) |
|||
return(0); |
|||
if ( LP_numpriceinfos > 0 ) |
|||
{ |
|||
coinbits = stringbits(symbol); |
|||
pp = LP_priceinfos; |
|||
for (i=0; i<LP_numpriceinfos; i++,pp++) |
|||
if ( pp->coinbits == 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); |
|||
} |
|||
} |
|||
|
|||
int32_t LP_cachekey(uint8_t *key,char *base,char *rel,bits256 txid,int32_t vout) |
|||
{ |
|||
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); |
|||
} |
|||
|
|||
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 ( base == 0 || rel == 0 ) |
|||
return(0); |
|||
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); |
|||
} |
|||
|
|||
struct LP_pubkeyinfo *LP_pubkeyfind(bits256 pubkey) |
|||
{ |
|||
struct LP_pubkeyinfo *pubp=0; |
|||
portable_mutex_lock(&LP_pubkeymutex); |
|||
HASH_FIND(hh,LP_pubkeyinfos,&pubkey,sizeof(pubkey),pubp); |
|||
portable_mutex_unlock(&LP_pubkeymutex); |
|||
return(pubp); |
|||
} |
|||
|
|||
struct LP_pubkeyinfo *LP_pubkeyadd(bits256 pubkey) |
|||
{ |
|||
struct LP_pubkeyinfo *pubp=0; |
|||
if ( (pubp= LP_pubkeyfind(pubkey)) == 0 ) |
|||
{ |
|||
portable_mutex_lock(&LP_pubkeymutex); |
|||
pubp = calloc(1,sizeof(*pubp)); |
|||
pubp->pubkey = pubkey; |
|||
HASH_ADD_KEYPTR(hh,LP_pubkeyinfos,&pubp->pubkey,sizeof(pubp->pubkey),pubp); |
|||
portable_mutex_unlock(&LP_pubkeymutex); |
|||
if ( (pubp= LP_pubkeyfind(pubkey)) == 0 ) |
|||
printf("pubkeyadd find error after add\n"); |
|||
} |
|||
return(pubp); |
|||
} |
|||
|
|||
int32_t LP_pubkey_istrusted(bits256 pubkey) |
|||
{ |
|||
struct LP_pubkeyinfo *pubp; |
|||
if ( (pubp= LP_pubkeyfind(pubkey)) != 0 ) |
|||
return(pubp->istrusted != 0); |
|||
return(0); |
|||
} |
|||
|
|||
char *LP_pubkey_trustset(bits256 pubkey,uint32_t trustval) |
|||
{ |
|||
struct LP_pubkeyinfo *pubp; |
|||
if ( (pubp= LP_pubkeyfind(pubkey)) != 0 ) |
|||
{ |
|||
pubp->istrusted = trustval; |
|||
return(clonestr("{\"result\":\"success\"}")); |
|||
} |
|||
return(clonestr("{\"error\":\"pubkey not found\"}")); |
|||
} |
|||
|
|||
cJSON *LP_pubkeyjson(struct LP_pubkeyinfo *pubp) |
|||
{ |
|||
int32_t baseid,relid; char *base; double price; cJSON *item,*array,*obj; |
|||
obj = cJSON_CreateObject(); |
|||
array = cJSON_CreateArray(); |
|||
for (baseid=0; baseid<LP_numpriceinfos; baseid++) |
|||
{ |
|||
base = LP_priceinfos[baseid].symbol; |
|||
for (relid=0; relid<LP_numpriceinfos; relid++) |
|||
{ |
|||
if ( (price= pubp->matrix[baseid][relid]) > SMALLVAL ) |
|||
{ |
|||
item = cJSON_CreateArray(); |
|||
jaddistr(item,base); |
|||
jaddistr(item,LP_priceinfos[relid].symbol); |
|||
jaddinum(item,price); |
|||
jaddi(array,item); |
|||
} |
|||
} |
|||
} |
|||
jaddbits256(obj,"pubkey",pubp->pubkey); |
|||
jaddnum(obj,"timestamp",pubp->timestamp); |
|||
jadd(obj,"asks",array); |
|||
if ( pubp->istrusted != 0 ) |
|||
jaddnum(obj,"istrusted",pubp->istrusted); |
|||
return(obj); |
|||
} |
|||
|
|||
char *LP_prices() |
|||
{ |
|||
struct LP_pubkeyinfo *pubp,*tmp; cJSON *array = cJSON_CreateArray(); |
|||
HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) |
|||
{ |
|||
jaddi(array,LP_pubkeyjson(pubp)); |
|||
} |
|||
return(jprint(array,1)); |
|||
} |
|||
|
|||
void LP_prices_parse(cJSON *obj) |
|||
{ |
|||
struct LP_pubkeyinfo *pubp; struct LP_priceinfo *basepp; uint32_t timestamp; bits256 pubkey; cJSON *asks,*item; int32_t i,n,relid; char *base,*rel; double askprice; |
|||
pubkey = jbits256(obj,"pubkey"); |
|||
if ( bits256_nonz(pubkey) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 ) |
|||
{ |
|||
if ( (timestamp= juint(obj,"timestamp")) > pubp->timestamp && (asks= jarray(&n,obj,"asks")) != 0 ) |
|||
{ |
|||
pubp->timestamp = timestamp; |
|||
for (i=0; i<n; i++) |
|||
{ |
|||
item = jitem(asks,i); |
|||
base = jstri(item,0); |
|||
rel = jstri(item,1); |
|||
askprice = jdoublei(item,2); |
|||
if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 ) |
|||
{ |
|||
char str[65]; printf("%s %s/%s (%d/%d) %.8f\n",bits256_str(str,pubkey),base,rel,basepp->ind,relid,askprice); |
|||
pubp->matrix[basepp->ind][relid] = askprice; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
void LP_peer_pricesquery(char *destipaddr,uint16_t destport) |
|||
{ |
|||
char *retstr; cJSON *array; int32_t i,n; |
|||
if ( (retstr= issue_LP_getprices(destipaddr,destport)) != 0 ) |
|||
{ |
|||
if ( (array= cJSON_Parse(retstr)) != 0 ) |
|||
{ |
|||
if ( is_cJSON_Array(array) && (n= cJSON_GetArraySize(array)) > 0 ) |
|||
{ |
|||
for (i=0; i<n; i++) |
|||
LP_prices_parse(jitem(array,i)); |
|||
} |
|||
free_json(array); |
|||
} |
|||
free(retstr); |
|||
} |
|||
} |
|||
|
|||
double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,int32_t vout) |
|||
{ |
|||
struct LP_cacheinfo *ptr; |
|||
if ( (ptr= LP_cachefind(base,rel,txid,vout)) != 0 ) |
|||
{ |
|||
if ( qp != 0 ) |
|||
(*qp) = ptr->Q; |
|||
if ( ptr->price == 0. && ptr->Q.satoshis != 0 ) |
|||
{ |
|||
printf("LP_pricecache: 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.); |
|||
} |
|||
|
|||
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);
|
|||
basepp->relvals[relpp->ind] = price; |
|||
relpp->relvals[basepp->ind] = 1. / price; |
|||
} |
|||
} |
|||
|
|||
double LP_myprice(double *bidp,double *askp,char *base,char *rel) |
|||
{ |
|||
struct LP_priceinfo *basepp,*relpp; double val; |
|||
*bidp = *askp = 0.; |
|||
if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) |
|||
{ |
|||
if ( (*askp= basepp->myprices[relpp->ind]) > SMALLVAL ) |
|||
{ |
|||
if ( (val= relpp->myprices[basepp->ind]) > SMALLVAL ) |
|||
{ |
|||
*bidp = 1. / val; |
|||
return((*askp + *bidp) * 0.5); |
|||
} |
|||
else |
|||
{ |
|||
*bidp = 0.; |
|||
return(*askp); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if ( (val= relpp->myprices[basepp->ind]) > SMALLVAL ) |
|||
{ |
|||
*bidp = 1. / val; |
|||
*askp = 0.; |
|||
return(*bidp); |
|||
} |
|||
} |
|||
} |
|||
return(0.); |
|||
} |
|||
|
|||
char *LP_myprices() |
|||
{ |
|||
int32_t baseid,relid; double bid,ask; char *base,*rel; cJSON *item,*array; |
|||
array = cJSON_CreateArray(); |
|||
for (baseid=0; baseid<LP_numpriceinfos; baseid++) |
|||
{ |
|||
base = LP_priceinfos[baseid].symbol; |
|||
for (relid=0; relid<LP_numpriceinfos; relid++) |
|||
{ |
|||
rel = LP_priceinfos[relid].symbol; |
|||
if ( LP_myprice(&bid,&ask,base,rel) > SMALLVAL ) |
|||
{ |
|||
item = cJSON_CreateObject(); |
|||
jaddstr(item,"base",base); |
|||
jaddstr(item,"rel",rel); |
|||
jaddnum(item,"bid",bid); |
|||
jaddnum(item,"ask",ask); |
|||
jaddi(array,item); |
|||
} |
|||
} |
|||
} |
|||
return(jprint(array,1)); |
|||
} |
|||
|
|||
int32_t LP_mypriceset(char *base,char *rel,double price) |
|||
{ |
|||
struct LP_priceinfo *basepp,*relpp; struct LP_pubkeyinfo *pubp; |
|||
if ( base != 0 && rel != 0 && price > SMALLVAL && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) |
|||
{ |
|||
basepp->myprices[relpp->ind] = price; // ask
|
|||
//relpp->myprices[basepp->ind] = (1. / price); // bid
|
|||
if ( (pubp= LP_pubkeyadd(LP_mypubkey)) != 0 ) |
|||
{ |
|||
pubp->matrix[basepp->ind][relpp->ind] = price; |
|||
//pubp->matrix[relpp->ind][basepp->ind] = (1. / price);
|
|||
pubp->timestamp = (uint32_t)time(NULL); |
|||
} |
|||
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-3600*2 || ptr->price == 0. ) |
|||
continue; |
|||
LP_priceinfoupdate(ptr->Q.srccoin,ptr->Q.destcoin,ptr->price); |
|||
} |
|||
pp = LP_priceinfos; |
|||
total = m = 0; |
|||
for (i=0; i<LP_numpriceinfos; i++,pp++) |
|||
{ |
|||
pp->diagval = sum = n = 0; |
|||
for (j=0; j<LP_numpriceinfos; j++) |
|||
{ |
|||
if ( usemyprices == 0 || (val= pp->myprices[j]) == 0. ) |
|||
val = pp->relvals[j]; |
|||
if ( val > SMALLVAL ) |
|||
{ |
|||
sum += val; |
|||
n++; |
|||
} |
|||
} |
|||
if ( n > 0 ) |
|||
{ |
|||
pp->diagval = sum / n; |
|||
total += pp->diagval, m++; |
|||
} |
|||
} |
|||
if ( m > 0 ) |
|||
{ |
|||
pp = LP_priceinfos; |
|||
for (i=0; i<LP_numpriceinfos; i++,pp++) |
|||
{ |
|||
if ( pp->diagval > SMALLVAL ) |
|||
{ |
|||
pp->diagval /= total; |
|||
jaddnum(vectorjson,pp->symbol,pp->diagval); |
|||
} |
|||
} |
|||
} |
|||
return(vectorjson); |
|||
} |
|||
|
|||
struct LP_priceinfo *LP_priceinfoadd(char *symbol) |
|||
{ |
|||
struct LP_priceinfo *pp; cJSON *retjson; |
|||
if ( symbol == 0 ) |
|||
return(0); |
|||
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++; |
|||
LP_numpriceinfos++; |
|||
if ( (retjson= LP_priceinfomatrix(0)) != 0 ) |
|||
free_json(retjson); |
|||
return(pp); |
|||
} |
|||
|
|||
struct LP_cacheinfo *LP_cacheadd(char *base,char *rel,bits256 txid,int32_t vout,double price,struct LP_quoteinfo *qp) |
|||
{ |
|||
char str[65]; struct LP_cacheinfo *ptr=0; |
|||
if ( base == 0 || rel == 0 ) |
|||
return(0); |
|||
if ( (ptr= LP_cachefind(base,rel,txid,vout)) == 0 ) |
|||
{ |
|||
ptr = calloc(1,sizeof(*ptr)); |
|||
if ( LP_cachekey(ptr->key,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) |
|||
{ |
|||
int32_t retval = 0; |
|||
#define ptr_a (*(struct LP_orderbookentry **)a)->price |
|||
#define ptr_b (*(struct LP_orderbookentry **)b)->price |
|||
if ( ptr_b > ptr_a ) |
|||
retval = -1; |
|||
else if ( ptr_b < ptr_a ) |
|||
retval = 1; |
|||
else |
|||
{ |
|||
#undef ptr_a |
|||
#undef ptr_b |
|||
#define ptr_a ((struct LP_orderbookentry *)a)->basesatoshis |
|||
#define ptr_b ((struct LP_orderbookentry *)b)->basesatoshis |
|||
if ( ptr_b > ptr_a ) |
|||
return(-1); |
|||
else if ( ptr_b < ptr_a ) |
|||
return(1); |
|||
} |
|||
// printf("%.8f vs %.8f -> %d\n",ptr_a,ptr_b,retval);
|
|||
return(retval); |
|||
#undef ptr_a |
|||
#undef ptr_b |
|||
} |
|||
|
|||
cJSON *LP_orderbookjson(struct LP_orderbookentry *op) |
|||
{ |
|||
cJSON *item = cJSON_CreateObject(); |
|||
if ( op->price > SMALLVAL ) |
|||
{ |
|||
jaddnum(item,"price",op->price); |
|||
jaddnum(item,"volume",dstr(op->basesatoshis)); |
|||
jaddbits256(item,"txid",op->txid); |
|||
jaddnum(item,"vout",op->vout); |
|||
jaddbits256(item,"pubkey",op->pubkey); |
|||
} |
|||
return(item); |
|||
} |
|||
|
|||
struct LP_orderbookentry *LP_orderbookentry(char *base,char *rel,bits256 txid,int32_t vout,bits256 txid2,int32_t vout2,double price,uint64_t basesatoshis,bits256 pubkey) |
|||
{ |
|||
struct LP_orderbookentry *op; |
|||
if ( (op= calloc(1,sizeof(*op))) != 0 ) |
|||
{ |
|||
op->txid = txid; |
|||
op->vout = vout; |
|||
op->txid2 = txid2; |
|||
op->vout2 = vout2; |
|||
op->price = price; |
|||
op->basesatoshis = basesatoshis; |
|||
op->pubkey = pubkey; |
|||
} |
|||
return(op); |
|||
} |
|||
|
|||
int32_t LP_orderbookfind(struct LP_orderbookentry **array,int32_t num,bits256 txid,int32_t vout) |
|||
{ |
|||
int32_t i; |
|||
for (i=0; i<num; i++) |
|||
if ( (array[i]->vout == vout && bits256_cmp(array[i]->txid,txid) == 0) || (array[i]->vout2 == vout && bits256_cmp(array[i]->txid2,txid) == 0) ) |
|||
return(i); |
|||
return(-1); |
|||
} |
|||
|
|||
int32_t LP_utxo_clientpublish(struct LP_utxoinfo *utxo) |
|||
{ |
|||
struct LP_peerinfo *peer,*tmp; cJSON *retjson; char *retstr; int32_t n = 0; |
|||
HASH_ITER(hh,LP_peerinfos,peer,tmp) |
|||
{ |
|||
if ( (retstr= issue_LP_notifyutxo(peer->ipaddr,peer->port,utxo)) != 0 ) |
|||
{ |
|||
if ( (retjson= cJSON_Parse(retstr)) != 0 ) |
|||
{ |
|||
if ( jobj(retjson,"error") == 0 ) |
|||
{ |
|||
//if ( strcmp("HUSH",utxo->coin) == 0 )
|
|||
// printf("clientpublish %s (%s)\n",peer->ipaddr,retstr);
|
|||
utxo->T.lasttime = (uint32_t)time(NULL); |
|||
n++; |
|||
} |
|||
free_json(retjson); |
|||
} |
|||
free(retstr); |
|||
} |
|||
//if ( utxo->T.lasttime != 0 )
|
|||
// return(0);
|
|||
} |
|||
return(n); |
|||
} |
|||
|
|||
int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char *rel,struct LP_orderbookentry *(**arrayp),int32_t num,int32_t cachednum) |
|||
{ |
|||
struct LP_utxoinfo *utxo,*tmp; struct LP_pubkeyinfo *pubp=0; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; double price; int32_t baseid,relid; uint64_t basesatoshis; |
|||
if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 ) |
|||
baseid = basepp->ind; |
|||
else return(num); |
|||
HASH_ITER(hh,LP_utxoinfos[1],utxo,tmp) |
|||
{ |
|||
if ( pubp == 0 || bits256_cmp(pubp->pubkey,utxo->pubkey) != 0 ) |
|||
pubp = LP_pubkeyfind(utxo->pubkey); |
|||
if ( pubp != 0 && pubp->numerrors >= LP_MAXPUBKEY_ERRORS ) |
|||
continue; |
|||
//char str[65],str2[65]; printf("check utxo.%s/v%d from %s\n",bits256_str(str,utxo->payment.txid),utxo->payment.vout,bits256_str(str2,utxo->pubkey));
|
|||
if ( strcmp(base,utxo->coin) == 0 && LP_isavailable(utxo) > 0 && pubp != 0 && (price= pubp->matrix[baseid][relid]) > SMALLVAL ) |
|||
{ |
|||
if ( LP_orderbookfind(*arrayp,cachednum,utxo->payment.txid,utxo->payment.vout) < 0 ) |
|||
{ |
|||
if ( polarity > 0 ) |
|||
basesatoshis = utxo->S.satoshis; |
|||
else basesatoshis = utxo->S.satoshis * price; |
|||
//char str[65]; printf("found utxo not in orderbook %s/v%d %.8f %.8f\n",bits256_str(str,utxo->payment.txid),utxo->payment.vout,dstr(basesatoshis),polarity > 0 ? price : 1./price);
|
|||
if ( (op= LP_orderbookentry(base,rel,utxo->payment.txid,utxo->payment.vout,utxo->deposit.txid,utxo->deposit.vout,polarity > 0 ? price : 1./price,basesatoshis,utxo->pubkey)) != 0 ) |
|||
{ |
|||
*arrayp = realloc(*arrayp,sizeof(*(*arrayp)) * (num+1)); |
|||
(*arrayp)[num++] = op; |
|||
if ( bits256_cmp(utxo->pubkey,LP_mypubkey) == 0 && utxo->T.lasttime == 0 ) |
|||
LP_utxo_clientpublish(utxo); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
return(num); |
|||
} |
|||
|
|||
char *LP_orderbook(char *base,char *rel) |
|||
{ |
|||
uint32_t now,i; struct LP_priceinfo *basepp=0,*relpp=0; struct LP_orderbookentry **bids = 0,**asks = 0; cJSON *retjson,*array; int32_t numbids=0,numasks=0,cachenumbids,cachenumasks,baseid,relid; |
|||
if ( (basepp= LP_priceinfofind(base)) == 0 || (relpp= LP_priceinfofind(rel)) == 0 ) |
|||
return(clonestr("{\"error\":\"base or rel not added\"}")); |
|||
baseid = basepp->ind; |
|||
relid = relpp->ind; |
|||
now = (uint32_t)time(NULL); |
|||
/*struct LP_cacheinfo *ptr,*tmp;
|
|||
HASH_ITER(hh,LP_cacheinfos,ptr,tmp) |
|||
{ |
|||
if ( ptr->timestamp < now-3600*2 || ptr->price == 0. ) |
|||
continue; |
|||
if ( strcmp(ptr->Q.srccoin,base) == 0 && strcmp(ptr->Q.destcoin,rel) == 0 ) |
|||
{ |
|||
asks = realloc(asks,sizeof(*asks) * (numasks+1)); |
|||
if ( (op= LP_orderbookentry(base,rel,ptr->Q.txid,ptr->Q.vout,ptr->Q.txid2,ptr->Q.vout2,ptr->price,ptr->Q.satoshis,ptr->Q.srchash)) != 0 ) |
|||
asks[numasks++] = op; |
|||
} |
|||
else if ( strcmp(ptr->Q.srccoin,rel) == 0 && strcmp(ptr->Q.destcoin,base) == 0 ) |
|||
{ |
|||
bids = realloc(bids,sizeof(*bids) * (numbids+1)); |
|||
if ( (op= LP_orderbookentry(base,rel,ptr->Q.txid,ptr->Q.vout,ptr->Q.txid2,ptr->Q.vout2,1./ptr->price,ptr->Q.satoshis,ptr->Q.srchash)) != 0 ) |
|||
bids[numbids++] = op; |
|||
} |
|||
}*/ |
|||
cachenumbids = numbids, cachenumasks = numasks; |
|||
//printf("start cache.(%d %d) numbids.%d numasks.%d\n",cachenumbids,cachenumasks,numbids,numasks);
|
|||
numasks = LP_orderbook_utxoentries(now,1,base,rel,&asks,numasks,cachenumasks); |
|||
numbids = LP_orderbook_utxoentries(now,-1,rel,base,&bids,numbids,cachenumbids); |
|||
retjson = cJSON_CreateObject(); |
|||
array = cJSON_CreateArray(); |
|||
if ( numbids > 1 ) |
|||
qsort(bids,numbids,sizeof(*bids),_cmp_orderbook); |
|||
if ( numasks > 1 ) |
|||
{ |
|||
for (i=0; i<numasks; i++) |
|||
printf("%.8f ",asks[i]->price); |
|||
printf(" -> "); |
|||
qsort(asks,numasks,sizeof(*asks),_cmp_orderbook); |
|||
for (i=0; i<numasks; i++) |
|||
printf("%.8f ",asks[i]->price); |
|||
printf("sorted asks.%d\n",numasks); |
|||
} |
|||
for (i=0; i<numbids; i++) |
|||
{ |
|||
jaddi(array,LP_orderbookjson(bids[i])); |
|||
free(bids[i]); |
|||
bids[i] = 0; |
|||
} |
|||
jadd(retjson,"bids",array); |
|||
jaddnum(retjson,"numbids",numbids); |
|||
array = cJSON_CreateArray(); |
|||
for (i=0; i<numasks; i++) |
|||
{ |
|||
jaddi(array,LP_orderbookjson(asks[i])); |
|||
free(asks[i]); |
|||
asks[i] = 0; |
|||
} |
|||
jadd(retjson,"asks",array); |
|||
jaddnum(retjson,"numasks",numasks); |
|||
jaddstr(retjson,"base",base); |
|||
jaddstr(retjson,"rel",rel); |
|||
jaddnum(retjson,"timestamp",now); |
|||
if ( bids != 0 ) |
|||
free(bids); |
|||
if ( asks != 0 ) |
|||
free(asks); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
char *LP_pricestr(char *base,char *rel,double origprice) |
|||
{ |
|||
cJSON *retjson; double price = 0.; |
|||
if ( base != 0 && base[0] != 0 && rel != 0 && rel[0] != 0 ) |
|||
{ |
|||
price = LP_price(base,rel); |
|||
if ( origprice > SMALLVAL && origprice < price ) |
|||
price = origprice; |
|||
} |
|||
if ( price > SMALLVAL ) |
|||
{ |
|||
retjson = cJSON_CreateObject(); |
|||
jaddstr(retjson,"result","success"); |
|||
jaddstr(retjson,"method","postprice"); |
|||
jaddbits256(retjson,"pubkey",LP_mypubkey); |
|||
jaddstr(retjson,"base",base); |
|||
jaddstr(retjson,"rel",rel); |
|||
jaddnum(retjson,"price",price); |
|||
jadd(retjson,"theoretical",LP_priceinfomatrix(0)); |
|||
jadd(retjson,"quotes",LP_priceinfomatrix(1)); |
|||
return(jprint(retjson,1)); |
|||
} else return(clonestr("{\"error\":\"cant find baserel pair\"}")); |
|||
} |
|||
|
|||
void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32]) |
|||
{ |
|||
LP_priceinfoupdate(base,rel,price); |
|||
} |
|||
|
|||
void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price) |
|||
{ |
|||
struct LP_priceinfo *basepp,*relpp; struct LP_pubkeyinfo *pubp; char str[65]; |
|||
if ( price > SMALLVAL && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) |
|||
{ |
|||
printf("PRICEFEED UPDATE.(%s/%s) %.8f %s\n",base,rel,price,bits256_str(str,pubkey)); |
|||
if ( (pubp= LP_pubkeyadd(pubkey)) != 0 ) |
|||
{ |
|||
pubp->matrix[basepp->ind][relpp->ind] = price; |
|||
pubp->timestamp = (uint32_t)time(NULL); |
|||
} else printf("error creating pubkey entry\n"); |
|||
} else printf("error finding %s/%s %.8f\n",base,rel,price); |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
File diff suppressed because it is too large
@ -0,0 +1,427 @@ |
|||
|
|||
/******************************************************************************
|
|||
* 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_rpc.c
|
|||
// marketmaker
|
|||
//
|
|||
|
|||
char *LP_issue_curl(char *debugstr,char *destip,uint16_t port,char *url) |
|||
{ |
|||
char *retstr = 0; int32_t maxerrs; struct LP_peerinfo *peer = 0; |
|||
peer = LP_peerfind((uint32_t)calc_ipbits(destip),port); |
|||
maxerrs = LP_MAXPEER_ERRORS; |
|||
if ( peer == 0 || (peer->errors < maxerrs || peer->good >= LP_MINPEER_GOOD) ) |
|||
{ |
|||
if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) == 0 ) |
|||
{ |
|||
if ( peer != 0 ) |
|||
{ |
|||
peer->errors++; |
|||
peer->good *= LP_PEERGOOD_ERRORDECAY; |
|||
} else printf("%s error on (%s:%u) without peer\n",debugstr,destip,port); |
|||
} |
|||
else if ( peer != 0 ) |
|||
peer->good++; |
|||
} |
|||
return(retstr); |
|||
} |
|||
|
|||
char *LP_isitme(char *destip,uint16_t destport) |
|||
{ |
|||
if ( LP_mypeer != 0 && strcmp(destip,LP_mypeer->ipaddr) == 0 && LP_mypeer->port == destport ) |
|||
{ |
|||
//printf("no need to notify ourselves\n");
|
|||
return(clonestr("{\"result\":\"success\"}")); |
|||
} else return(0); |
|||
} |
|||
|
|||
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); |
|||
return(LP_issue_curl("getpeers",destip,port,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(LP_issue_curl("getutxos",destip,destport,url)); |
|||
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
|
|||
} |
|||
|
|||
char *issue_LP_clientgetutxos(char *destip,uint16_t destport,char *coin,int32_t lastn) |
|||
{ |
|||
char url[512];//,*retstr;
|
|||
sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=127.0.0.1&port=0",destip,destport,coin,lastn); |
|||
return(LP_issue_curl("clientgetutxos",destip,destport,url)); |
|||
//retstr = issue_curlt(url,LP_HTTP_TIMEOUT);
|
|||
//printf("%s clientgetutxos.(%s)\n",url,retstr);
|
|||
//return(retstr);
|
|||
} |
|||
|
|||
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],*retstr; |
|||
if ( (retstr= LP_isitme(destip,destport)) != 0 ) |
|||
{ |
|||
free(retstr); |
|||
return(0); |
|||
} |
|||
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(LP_issue_curl("notify",destip,destport,url)); |
|||
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
|
|||
} |
|||
|
|||
char *issue_LP_notifyutxo(char *destip,uint16_t destport,struct LP_utxoinfo *utxo) |
|||
{ |
|||
char url[4096],str[65],str2[65],str3[65],*retstr; struct _LP_utxoinfo u; uint64_t val,val2; |
|||
if ( (retstr= LP_isitme(destip,destport)) != 0 ) |
|||
{ |
|||
free(retstr); |
|||
return(0); |
|||
} |
|||
if ( utxo->iambob == 0 ) |
|||
{ |
|||
printf("issue_LP_notifyutxo trying to send Alice %s/v%d\n",bits256_str(str,utxo->payment.txid),utxo->payment.vout); |
|||
return(0); |
|||
} |
|||
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; |
|||
if ( LP_iseligible(&val,&val2,utxo->iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,u.txid,u.vout,utxo->pubkey) > 0 ) |
|||
{ |
|||
sprintf(url,"http://%s:%u/api/stats/notified?iambob=%d&pubkey=%s&profit=%.6f&coin=%s&txid=%s&vout=%d&value=%llu&txid2=%s&vout2=%d&value2=%llu&script=%s&address=%s×tamp=%u&gui=%s",destip,destport,utxo->iambob,bits256_str(str3,utxo->pubkey),utxo->S.profitmargin,utxo->coin,bits256_str(str,utxo->payment.txid),utxo->payment.vout,(long long)utxo->payment.value,bits256_str(str2,utxo->deposit.txid),utxo->deposit.vout,(long long)utxo->deposit.value,utxo->spendscript,utxo->coinaddr,(uint32_t)time(NULL),utxo->gui); |
|||
if ( strlen(url) > 1024 ) |
|||
printf("WARNING long url.(%s)\n",url); |
|||
return(LP_issue_curl("notifyutxo",destip,destport,url)); |
|||
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
|
|||
} |
|||
else |
|||
{ |
|||
printf("issue_LP_notifyutxo: ineligible utxo iambob.%d %.8f %.8f\n",utxo->iambob,dstr(val),dstr(val2)); |
|||
return(0); |
|||
} |
|||
} |
|||
|
|||
char *issue_LP_register(char *destip,uint16_t destport,bits256 pubkey,char *ipaddr,uint16_t pushport) |
|||
{ |
|||
char url[512],str[65];//*retstr;
|
|||
sprintf(url,"http://%s:%u/api/stats/register?client=%s&pushaddr=%s&pushport=%u",destip,destport,bits256_str(str,pubkey),ipaddr,pushport); |
|||
return(LP_issue_curl("register",destip,destport,url)); |
|||
//retstr = issue_curlt(url,LP_HTTP_TIMEOUT);
|
|||
//printf("getutxo.(%s) -> (%s)\n",url,retstr!=0?retstr:"");
|
|||
//return(retstr);
|
|||
} |
|||
|
|||
char *issue_LP_psock(char *destip,uint16_t destport,int32_t ispaired) |
|||
{ |
|||
char url[512]; |
|||
sprintf(url,"http://%s:%u/api/stats/psock?ispaired=%d",destip,destport,ispaired); |
|||
return(LP_issue_curl("psock",destip,destport,url)); |
|||
//retstr = issue_curlt(url,LP_HTTP_TIMEOUT);
|
|||
//printf("getutxo.(%s) -> (%s)\n",url,retstr!=0?retstr:"");
|
|||
//return(retstr);
|
|||
} |
|||
|
|||
uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired) |
|||
{ |
|||
uint16_t publicport = 0; char *retstr,*addr; cJSON *retjson; struct LP_peerinfo *peer,*tmp; |
|||
HASH_ITER(hh,LP_peerinfos,peer,tmp) |
|||
{ |
|||
connectaddr[0] = publicaddr[0] = 0; |
|||
if ( peer->errors < LP_MAXPEER_ERRORS && (retstr= issue_LP_psock(peer->ipaddr,peer->port,ispaired)) != 0 ) |
|||
{ |
|||
if ( (retjson= cJSON_Parse(retstr)) != 0 ) |
|||
{ |
|||
if ( (addr= jstr(retjson,"publicaddr")) != 0 ) |
|||
safecopy(publicaddr,addr,128); |
|||
if ( (addr= jstr(retjson,"connectaddr")) != 0 ) |
|||
safecopy(connectaddr,addr,128); |
|||
if ( publicaddr[0] != 0 && connectaddr[0] != 0 ) |
|||
publicport = juint(retjson,"publicport"); |
|||
free_json(retjson); |
|||
} |
|||
printf("got.(%s) connect.%s public.%s\n",retstr,connectaddr,publicaddr); |
|||
free(retstr); |
|||
} |
|||
if ( publicport != 0 ) |
|||
break; |
|||
} |
|||
return(publicport); |
|||
} |
|||
|
|||
char *issue_LP_lookup(char *destip,uint16_t destport,bits256 pubkey) |
|||
{ |
|||
char url[512],str[65]; |
|||
sprintf(url,"http://%s:%u/api/stats/lookup?client=%s",destip,destport,bits256_str(str,pubkey)); |
|||
//printf("getutxo.(%s)\n",url);
|
|||
return(LP_issue_curl("lookup",destip,destport,url)); |
|||
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
|
|||
} |
|||
|
|||
char *issue_LP_getprices(char *destip,uint16_t destport) |
|||
{ |
|||
char url[512]; |
|||
sprintf(url,"http://%s:%u/api/stats/getprices",destip,destport); |
|||
//printf("getutxo.(%s)\n",url);
|
|||
return(LP_issue_curl("getprices",destip,destport,url)); |
|||
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
|
|||
} |
|||
|
|||
cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params) |
|||
{ |
|||
char *retstr; cJSON *retjson = 0; |
|||
if ( coin != 0 ) |
|||
{ |
|||
//printf("issue.(%s, %s, %s, %s, %s)\n",coin->symbol,coin->serverport,coin->userpass,method,params);
|
|||
if ( coin->inactive == 0 || strcmp(method,"importprivkey") == 0 ) |
|||
{ |
|||
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); |
|||
} |
|||
//usleep(1000);
|
|||
//printf("dpow_gettxout.(%s)\n",retstr);
|
|||
} else retjson = cJSON_Parse("{\"error\":\"disabled\"}"); |
|||
} else printf("bitcoin_json cant talk to NULL coin\n"); |
|||
return(retjson); |
|||
} |
|||
|
|||
void LP_unspents_mark(char *symbol,cJSON *vins) |
|||
{ |
|||
printf("LOCK (%s)\n",jprint(vins,0)); |
|||
} |
|||
|
|||
cJSON *LP_getinfo(char *symbol) |
|||
{ |
|||
struct iguana_info *coin = LP_coinfind(symbol); |
|||
return(bitcoin_json(coin,"getinfo","[]")); |
|||
} |
|||
|
|||
cJSON *LP_getmempool(char *symbol) |
|||
{ |
|||
struct iguana_info *coin = LP_coinfind(symbol); |
|||
return(bitcoin_json(coin,"getrawmempool","[]")); |
|||
} |
|||
|
|||
cJSON *LP_gettxout(char *symbol,bits256 txid,int32_t vout) |
|||
{ |
|||
char buf[128],str[65]; struct iguana_info *coin = LP_coinfind(symbol); |
|||
sprintf(buf,"\"%s\", %d, true",bits256_str(str,txid),vout); |
|||
return(bitcoin_json(coin,"gettxout",buf)); |
|||
} |
|||
|
|||
cJSON *LP_gettx(char *symbol,bits256 txid) |
|||
{ |
|||
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 *LP_getblock(char *symbol,bits256 txid) |
|||
{ |
|||
char buf[128],str[65]; struct iguana_info *coin = LP_coinfind(symbol); |
|||
sprintf(buf,"[\"%s\"]",bits256_str(str,txid)); |
|||
return(bitcoin_json(coin,"getblock",buf)); |
|||
} |
|||
|
|||
cJSON *LP_getblockhashstr(char *symbol,char *blockhashstr) |
|||
{ |
|||
char buf[128]; struct iguana_info *coin = LP_coinfind(symbol); |
|||
sprintf(buf,"[\"%s\"]",blockhashstr); |
|||
return(bitcoin_json(coin,"getblock",buf)); |
|||
} |
|||
|
|||
cJSON *LP_listunspent(char *symbol,char *coinaddr) |
|||
{ |
|||
char buf[128]; struct iguana_info *coin = LP_coinfind(symbol); |
|||
sprintf(buf,"0, 99999999, [\"%s\"]",coinaddr); |
|||
return(bitcoin_json(coin,"listunspent",buf)); |
|||
} |
|||
|
|||
cJSON *LP_listtransactions(char *symbol,char *coinaddr,int32_t count,int32_t skip) |
|||
{ |
|||
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)); |
|||
} |
|||
|
|||
cJSON *LP_validateaddress(char *symbol,char *address) |
|||
{ |
|||
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)); |
|||
} |
|||
|
|||
int32_t LP_importaddress(char *symbol,char *address) |
|||
{ |
|||
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 ( (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 ( isvalid == 0 ) |
|||
return(-1); |
|||
if ( doneflag != 0 ) |
|||
return(0); // success
|
|||
sprintf(buf,"[\"%s\", \"%s\", false]",address,address); |
|||
if ( (retstr= bitcoind_passthru(symbol,coin->serverport,coin->userpass,"importaddress",buf)) != 0 ) |
|||
{ |
|||
//printf("importaddress.(%s %s) -> (%s)\n",symbol,address,retstr);
|
|||
free(retstr); |
|||
} //else printf("importaddress.(%s %s)\n",symbol,address);
|
|||
return(1); |
|||
} |
|||
|
|||
double LP_getestimatedrate(char *symbol) |
|||
{ |
|||
char buf[512],*retstr; double rate = 20; struct iguana_info *coin = LP_coinfind(symbol); |
|||
if ( coin != 0 ) |
|||
{ |
|||
sprintf(buf,"[%d]",3); |
|||
if ( (retstr= bitcoind_passthru(symbol,coin->serverport,coin->userpass,"estimatefee",buf)) != 0 ) |
|||
{ |
|||
if ( retstr[0] != '-' ) |
|||
{ |
|||
coin->estimatedrate = rate = atof(retstr) / 1024.; |
|||
printf("estimated rate.(%s) %s -> %.8f\n",symbol,retstr,rate); |
|||
} |
|||
free(retstr); |
|||
} |
|||
} |
|||
return(rate); |
|||
} |
|||
|
|||
uint64_t LP_txfee(char *symbol) |
|||
{ |
|||
uint64_t txfee = 0; |
|||
if ( strcmp(symbol,"BTC") != 0 ) |
|||
txfee = 10000; |
|||
return(txfee); |
|||
} |
|||
|
|||
char *LP_blockhashstr(char *symbol,int32_t height) |
|||
{ |
|||
cJSON *array; char *paramstr,*retstr; struct iguana_info *coin = LP_coinfind(symbol); |
|||
if ( coin == 0 ) |
|||
return(0); |
|||
array = cJSON_CreateArray(); |
|||
jaddinum(array,height); |
|||
paramstr = jprint(array,1); |
|||
retstr = bitcoind_passthru(symbol,coin->serverport,coin->userpass,"getblockhash",paramstr); |
|||
free(paramstr); |
|||
return(retstr); |
|||
} |
|||
|
|||
char *LP_sendrawtransaction(char *symbol,char *signedtx) |
|||
{ |
|||
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); |
|||
} |
|||
|
|||
char *LP_signrawtx(char *symbol,bits256 *signedtxidp,int32_t *completedp,cJSON *vins,char *rawtx,cJSON *privkeys,struct vin_info *V) |
|||
{ |
|||
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 ) |
|||
{ |
|||
if ( (json= cJSON_Parse(retstr)) != 0 ) |
|||
{ |
|||
if ( (hexstr= jstr(json,"hex")) != 0 ) |
|||
{ |
|||
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(paramstr); |
|||
return(signedtx); |
|||
} |
|||
|
|||
cJSON *LP_blockjson(int32_t *heightp,char *symbol,char *blockhashstr,int32_t height) |
|||
{ |
|||
cJSON *json = 0; int32_t flag = 0; |
|||
if ( blockhashstr == 0 ) |
|||
blockhashstr = LP_blockhashstr(symbol,height), flag = 1; |
|||
if ( blockhashstr != 0 ) |
|||
{ |
|||
if ( (json= LP_getblockhashstr(symbol,blockhashstr)) != 0 ) |
|||
{ |
|||
if ( *heightp != 0 ) |
|||
{ |
|||
*heightp = juint(json,"height"); |
|||
if ( height >= 0 && *heightp != height ) |
|||
{ |
|||
printf("unexpected height %d vs %d\n",*heightp,height); |
|||
*heightp = -1; |
|||
free_json(json); |
|||
json = 0; |
|||
} |
|||
} |
|||
} |
|||
if ( flag != 0 && blockhashstr != 0 ) |
|||
free(blockhashstr); |
|||
} |
|||
return(json); |
|||
} |
|||
|
@ -0,0 +1,241 @@ |
|||
|
|||
/******************************************************************************
|
|||
* 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_scan.c
|
|||
// marketmaker
|
|||
//
|
|||
|
|||
/*uint64_t oldLP_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); |
|||
}*/ |
|||
|
|||
uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout) |
|||
{ |
|||
uint64_t value = 0; double interest; cJSON *txobj,*sobj,*array; int32_t n; struct iguana_info *coin; |
|||
if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) |
|||
return(0); |
|||
coinaddr[0] = 0; |
|||
if ( (txobj= LP_gettxout(symbol,txid,vout)) != 0 ) |
|||
{ |
|||
if ( (value= jdouble(txobj,"amount")*SATOSHIDEN) == 0 && (value= jdouble(txobj,"value")*SATOSHIDEN) == 0 ) |
|||
{ |
|||
char str[65]; printf("%s LP_txvalue.%s strange utxo.(%s) vout.%d\n",symbol,bits256_str(str,txid),jprint(txobj,0),vout); |
|||
} |
|||
else if ( strcmp(symbol,"KMD") == 0 ) |
|||
{ |
|||
if ( (interest= jdouble(txobj,"interest")) != 0. ) |
|||
{ |
|||
//printf("add interest of %.8f to %.8f\n",interest,dstr(value));
|
|||
value += SATOSHIDEN * interest; |
|||
} |
|||
} |
|||
if ( (sobj= jobj(txobj,"scriptPubKey")) != 0 && (array= jarray(&n,sobj,"addresses")) != 0 ) |
|||
strcpy(coinaddr,jstri(array,0)); |
|||
//char str[65]; printf("%.8f <- %s.(%s) txobj.(%s)\n",dstr(value),symbol,bits256_str(str,txid),jprint(txobj,0));
|
|||
free_json(txobj); |
|||
} |
|||
return(value); |
|||
} |
|||
|
|||
int32_t LP_vinscan(bits256 *spendtxidp,int32_t *spendvinip,char *symbol,bits256 txid,bits256 searchtxid,int32_t searchvout,bits256 searchtxid2,int32_t searchvout2) |
|||
{ |
|||
cJSON *txobj,*vins,*vin; bits256 spenttxid; struct iguana_info *coin; int32_t j,numvins,spentvout,retval = -1; |
|||
memset(spendtxidp,0,sizeof(*spendtxidp)); |
|||
*spendvinip = -1; |
|||
if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) |
|||
return(retval); |
|||
if ( (txobj= LP_gettx(symbol,txid)) != 0 ) |
|||
{ |
|||
if ( bits256_cmp(txid,jbits256(txobj,"txid")) != 0 ) |
|||
{ |
|||
char str[65]; printf("txid mismatch error %s vs %s\n",bits256_str(str,txid),jprint(txobj,0)); |
|||
free_json(txobj); |
|||
return(-2); |
|||
} |
|||
vins = jarray(&numvins,txobj,"vin"); |
|||
for (j=0; j<numvins; j++) |
|||
{ |
|||
vin = jitem(vins,j); |
|||
spenttxid = jbits256(vin,"txid"); |
|||
spentvout = jint(vin,"vout"); |
|||
if ( spentvout == searchvout && bits256_cmp(spenttxid,searchtxid) == 0 ) |
|||
{ |
|||
*spendtxidp = txid; |
|||
*spendvinip = j; |
|||
retval = 0; |
|||
break; |
|||
} |
|||
else if ( spentvout == searchvout2 && bits256_cmp(spenttxid,searchtxid2) == 0 ) |
|||
{ |
|||
*spendtxidp = txid; |
|||
*spendvinip = j; |
|||
retval = 1; |
|||
break; |
|||
} |
|||
} |
|||
free_json(txobj); |
|||
} else printf("unexpected missing txid\n"), retval = -3; |
|||
return(retval); |
|||
} |
|||
|
|||
int32_t LP_spendsearch(bits256 *spendtxidp,int32_t *indp,char *symbol,bits256 searchtxid,int32_t searchvout) |
|||
{ |
|||
char destaddr[64]; struct iguana_info *coin; cJSON *blockjson,*txids,*txobj; bits256 hash,txid; int32_t h,i,j,numtxids,loadheight,errs = 0; |
|||
*indp = -1; |
|||
if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) |
|||
return(0); |
|||
memset(spendtxidp,0,sizeof(*spendtxidp)); |
|||
if ( LP_txvalue(destaddr,symbol,searchtxid,searchvout) > 0 ) |
|||
return(0); |
|||
if ( (txobj= LP_gettx(symbol,searchtxid)) == 0 ) |
|||
return(0); |
|||
hash = jbits256(txobj,"blockhash"); |
|||
free_json(txobj); |
|||
if ( bits256_nonz(hash) == 0 ) |
|||
return(0); |
|||
if ( (blockjson= LP_getblock(symbol,hash)) == 0 ) |
|||
return(0); |
|||
loadheight = jint(blockjson,"height"); |
|||
free_json(blockjson); |
|||
if ( loadheight <= 0 ) |
|||
return(0); |
|||
while ( errs == 0 && *indp < 0 ) |
|||
{ |
|||
//printf("search %s ht.%d\n",symbol,loadheight);
|
|||
if ( (blockjson= LP_blockjson(&h,symbol,0,loadheight)) != 0 && h == loadheight ) |
|||
{ |
|||
if ( (txids= jarray(&numtxids,blockjson,"tx")) != 0 ) |
|||
{ |
|||
for (i=0; i<numtxids; i++) |
|||
{ |
|||
txid = jbits256(jitem(txids,i),0); |
|||
if ( (j= LP_vinscan(spendtxidp,indp,symbol,txid,searchtxid,searchvout,searchtxid,searchvout)) >= 0 ) |
|||
break; |
|||
} |
|||
} |
|||
free_json(blockjson); |
|||
} else errs++; |
|||
loadheight++; |
|||
} |
|||
char str[65]; printf("reached %s ht.%d %s/v%d\n",symbol,loadheight,bits256_str(str,*spendtxidp),*indp); |
|||
if ( bits256_nonz(*spendtxidp) != 0 && *indp >= 0 ) |
|||
return(loadheight); |
|||
else return(0); |
|||
} |
|||
|
|||
int32_t LP_mempoolscan(char *symbol,bits256 txid) |
|||
{ |
|||
int32_t i,n; cJSON *array; struct iguana_info *coin; |
|||
if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) |
|||
return(-1); |
|||
if ( (array= LP_getmempool(symbol)) != 0 ) |
|||
{ |
|||
if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) |
|||
{ |
|||
for (i=0; i<n; i++) |
|||
if ( bits256_cmp(txid,jbits256i(array,i)) == 0 ) |
|||
{ |
|||
char str[65]; printf("found %s tx.(%s) in mempool slot.%d\n",symbol,bits256_str(str,txid),i); |
|||
return(i); |
|||
} |
|||
} |
|||
free_json(array); |
|||
} |
|||
return(-1); |
|||
} |
|||
|
|||
int32_t LP_numconfirms(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx) |
|||
{ |
|||
struct iguana_info *coin; int32_t numconfirms = 100; |
|||
//#ifndef BASILISK_DISABLEWAITTX
|
|||
cJSON *txobj; |
|||
if ( (coin= LP_coinfind(rawtx->coin->symbol)) == 0 || coin->inactive != 0 ) |
|||
return(-1); |
|||
numconfirms = -1; |
|||
if ( (txobj= LP_gettx(rawtx->coin->symbol,rawtx->I.signedtxid)) != 0 ) |
|||
{ |
|||
numconfirms = jint(txobj,"confirmations"); |
|||
free_json(txobj); |
|||
} |
|||
else if ( LP_mempoolscan(rawtx->coin->symbol,rawtx->I.signedtxid) >= 0 ) |
|||
numconfirms = 0; |
|||
//#endif
|
|||
return(numconfirms); |
|||
} |
|||
|
|||
int32_t LP_waitmempool(char *symbol,bits256 txid,int32_t duration) |
|||
{ |
|||
uint32_t expiration = (uint32_t)time(NULL) + duration; |
|||
while ( time(NULL) < expiration ) |
|||
{ |
|||
if ( LP_mempoolscan(symbol,txid) >= 0 ) |
|||
return(0); |
|||
usleep(250000); |
|||
} |
|||
return(-1); |
|||
} |
|||
|
|||
int32_t LP_mempool_vinscan(bits256 *spendtxidp,int32_t *spendvinp,char *symbol,bits256 searchtxid,int32_t searchvout,bits256 searchtxid2,int32_t searchvout2) |
|||
{ |
|||
int32_t i,n; cJSON *array; bits256 mempooltxid; struct iguana_info *coin; |
|||
if ( symbol == 0 || symbol[0] == 0 || bits256_nonz(searchtxid) == 0 || bits256_nonz(searchtxid2) == 0 ) |
|||
return(-1); |
|||
if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) |
|||
return(-1); |
|||
if ( (array= LP_getmempool(symbol)) != 0 ) |
|||
{ |
|||
if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) |
|||
{ |
|||
for (i=0; i<n; i++) |
|||
{ |
|||
mempooltxid = jbits256i(array,i); |
|||
if ( (*spendvinp= LP_vinscan(spendtxidp,spendvinp,symbol,mempooltxid,searchtxid,searchvout,searchtxid2,searchvout2)) >= 0 ) |
|||
return(i); |
|||
} |
|||
free_json(array); |
|||
} |
|||
} |
|||
return(-1); |
|||
} |
|||
|
|||
|
@ -0,0 +1,186 @@ |
|||
|
|||
/******************************************************************************
|
|||
* 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_secp.c
|
|||
// marketmaker
|
|||
//
|
|||
|
|||
|
|||
#include <ctype.h> |
|||
#include <string.h> |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include "../../includes/curve25519.h" |
|||
#include "../secp256k1/include/secp256k1.h" |
|||
#include "../secp256k1/include/secp256k1_ecdh.h" |
|||
#include "../secp256k1/include/secp256k1_schnorr.h" |
|||
#include "../secp256k1/include/secp256k1_rangeproof.h" |
|||
#include "../secp256k1/include/secp256k1_recovery.h" |
|||
|
|||
SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_rfc6979; |
|||
|
|||
#define bits256_nonz(a) (((a).ulongs[0] | (a).ulongs[1] | (a).ulongs[2] | (a).ulongs[3]) != 0) |
|||
|
|||
#define SECP_ENSURE_CTX int32_t flag = 0; if ( ctx == 0 ) { ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); secp256k1_pedersen_context_initialize(ctx); secp256k1_rangeproof_context_initialize(ctx); flag++; } else flag = 0; if ( ctx != 0 ) |
|||
#define ENDSECP_ENSURE_CTX if ( flag != 0 ) secp256k1_context_destroy(ctx); |
|||
|
|||
void *bitcoin_ctx() |
|||
{ |
|||
void *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); |
|||
secp256k1_pedersen_context_initialize(ctx); |
|||
secp256k1_rangeproof_context_initialize(ctx); |
|||
return(ctx); |
|||
} |
|||
|
|||
bits256 bitcoin_pubkey33(void *ctx,uint8_t *data,bits256 privkey) |
|||
{ |
|||
size_t plen; bits256 pubkey; secp256k1_pubkey secppub; |
|||
memset(pubkey.bytes,0,sizeof(pubkey)); |
|||
SECP_ENSURE_CTX |
|||
{ |
|||
if ( secp256k1_ec_seckey_verify(ctx,privkey.bytes) == 0 ) |
|||
{ |
|||
//printf("bitcoin_sign illegal privkey\n");
|
|||
return(pubkey); |
|||
} |
|||
if ( secp256k1_ec_pubkey_create(ctx,&secppub,privkey.bytes) != 0 ) |
|||
{ |
|||
plen = 33; |
|||
secp256k1_ec_pubkey_serialize(ctx,data,&plen,&secppub,SECP256K1_EC_COMPRESSED); |
|||
if ( plen == 33 ) |
|||
memcpy(pubkey.bytes,data+1,sizeof(pubkey)); |
|||
} |
|||
ENDSECP_ENSURE_CTX |
|||
} |
|||
return(pubkey); |
|||
} |
|||
|
|||
bits256 bitcoin_pub256(void *ctx,bits256 *privkeyp,uint8_t odd_even) |
|||
{ |
|||
bits256 pub256; uint8_t pubkey[33]; int32_t i; |
|||
for (i=0; i<100; i++) |
|||
{ |
|||
*privkeyp = rand256(0); |
|||
pub256 = bitcoin_pubkey33(ctx,pubkey,*privkeyp); |
|||
if ( pubkey[0] == odd_even+2 ) |
|||
return(pub256); |
|||
} |
|||
printf("bitcoin_pub256 couldnt generate pubkey.%d\n",odd_even+2); |
|||
memset(pub256.bytes,0,sizeof(pub256)); |
|||
return(pub256); |
|||
} |
|||
|
|||
int32_t bitcoin_sign(void *ctx,char *symbol,uint8_t *sig,bits256 txhash2,bits256 privkey,int32_t recoverflag) |
|||
{ |
|||
int32_t fCompressed = 1; |
|||
secp256k1_ecdsa_signature SIG; secp256k1_ecdsa_recoverable_signature rSIG; bits256 extra_entropy,seed; int32_t recid,retval = -1; size_t siglen = 72; secp256k1_pubkey SECPUB,CHECKPUB; |
|||
seed = rand256(0); |
|||
extra_entropy = rand256(0); |
|||
SECP_ENSURE_CTX |
|||
{ |
|||
if ( secp256k1_ec_seckey_verify(ctx,privkey.bytes) == 0 ) |
|||
{ |
|||
//printf("bitcoin_sign illegal privkey\n");
|
|||
return(-1); |
|||
} |
|||
if ( secp256k1_context_randomize(ctx,seed.bytes) != 0 ) |
|||
{ |
|||
if ( recoverflag != 0 ) |
|||
{ |
|||
if ( secp256k1_ecdsa_sign_recoverable(ctx,&rSIG,txhash2.bytes,privkey.bytes,secp256k1_nonce_function_rfc6979,extra_entropy.bytes) != 0 ) |
|||
{ |
|||
recid = -1; |
|||
secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx,sig+1,&recid,&rSIG); |
|||
if ( secp256k1_ecdsa_recover(ctx,&SECPUB,&rSIG,txhash2.bytes) != 0 ) |
|||
{ |
|||
if ( secp256k1_ec_pubkey_create(ctx,&CHECKPUB,privkey.bytes) != 0 ) |
|||
{ |
|||
if ( memcmp(&SECPUB,&CHECKPUB,sizeof(SECPUB)) == 0 ) |
|||
{ |
|||
sig[0] = 27 + recid + (fCompressed != 0 ? 4 : 0); |
|||
retval = 64 + 1; |
|||
//size_t i,plen = 33; uint8_t pubkey[33];
|
|||
//secp256k1_ec_pubkey_serialize(ctx,pubkey,&plen,&CHECKPUB,SECP256K1_EC_COMPRESSED);
|
|||
//for (i=0; i<33; i++)
|
|||
// printf("%02x",pubkey[i]);
|
|||
//printf(" bitcoin_sign's pubkey\n");
|
|||
|
|||
} //else printf("secpub mismatch\n");
|
|||
} else printf("pubkey create error\n"); |
|||
} //else printf("recover error\n");
|
|||
} else printf("secp256k1_ecdsa_sign_recoverable error\n"); |
|||
} |
|||
else |
|||
{ |
|||
if ( secp256k1_ecdsa_sign(ctx,&SIG,txhash2.bytes,privkey.bytes,secp256k1_nonce_function_rfc6979,extra_entropy.bytes) != 0 ) |
|||
{ |
|||
if ( secp256k1_ecdsa_signature_serialize_der(ctx,sig,&siglen,&SIG) != 0 ) |
|||
retval = (int32_t)siglen; |
|||
} |
|||
} |
|||
} |
|||
ENDSECP_ENSURE_CTX |
|||
} |
|||
return(retval); |
|||
} |
|||
|
|||
int32_t bitcoin_recoververify(void *ctx,char *symbol,uint8_t *sig,bits256 messagehash2,uint8_t *pubkey,size_t plen) |
|||
{ |
|||
int32_t retval = -1; secp256k1_pubkey PUB; secp256k1_ecdsa_signature SIG; secp256k1_ecdsa_recoverable_signature rSIG; |
|||
pubkey[0] = 0; |
|||
SECP_ENSURE_CTX |
|||
{ |
|||
if ( plen == 0 ) |
|||
{ |
|||
plen = (sig[0] <= 31) ? 65 : 33; |
|||
sig++; |
|||
} |
|||
secp256k1_ecdsa_recoverable_signature_parse_compact(ctx,&rSIG,sig,0); |
|||
secp256k1_ecdsa_recoverable_signature_convert(ctx,&SIG,&rSIG); |
|||
if ( secp256k1_ecdsa_recover(ctx,&PUB,&rSIG,messagehash2.bytes) != 0 ) |
|||
{ |
|||
plen = 33; |
|||
memset(pubkey,0,33); |
|||
secp256k1_ec_pubkey_serialize(ctx,pubkey,&plen,&PUB,SECP256K1_EC_COMPRESSED);//plen == 65 ? SECP256K1_EC_UNCOMPRESSED : SECP256K1_EC_COMPRESSED);
|
|||
if ( secp256k1_ecdsa_verify(ctx,&SIG,messagehash2.bytes,&PUB) != 0 ) |
|||
{ |
|||
retval = 0; |
|||
/*if ( pubkey[0] == 4 ) // experimentally looks like 04 is set
|
|||
pubkey[0] = 2; |
|||
else if ( pubkey[0] != 2 ) |
|||
pubkey[0] = 3;*/ |
|||
} else printf("secp256k1_ecdsa_verify error\n"); |
|||
} else printf("secp256k1_ecdsa_recover error\n"); |
|||
ENDSECP_ENSURE_CTX |
|||
} |
|||
return(retval); |
|||
} |
|||
|
|||
int32_t bitcoin_verify(void *ctx,uint8_t *sig,int32_t siglen,bits256 txhash2,uint8_t *pubkey,int32_t plen) |
|||
{ |
|||
int32_t retval = -1; secp256k1_pubkey PUB; secp256k1_ecdsa_signature SIG; |
|||
SECP_ENSURE_CTX |
|||
{ |
|||
if ( secp256k1_ec_pubkey_parse(ctx,&PUB,pubkey,plen) != 0 ) |
|||
{ |
|||
secp256k1_ecdsa_signature_parse_der(ctx,&SIG,sig,siglen); |
|||
if ( secp256k1_ecdsa_verify(ctx,&SIG,txhash2.bytes,&PUB) != 0 ) |
|||
retval = 0; |
|||
} |
|||
ENDSECP_ENSURE_CTX |
|||
} |
|||
return(retval); |
|||
} |
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -0,0 +1,796 @@ |
|||
|
|||
/******************************************************************************
|
|||
* 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
|
|||
//
|
|||
|
|||
int32_t LP_ismine(struct LP_utxoinfo *utxo) |
|||
{ |
|||
if ( utxo != 0 && bits256_cmp(utxo->pubkey,LP_mypubkey) == 0 ) |
|||
return(1); |
|||
else return(0); |
|||
} |
|||
|
|||
int32_t LP_isavailable(struct LP_utxoinfo *utxo) |
|||
{ |
|||
if ( time(NULL) > utxo->T.swappending ) |
|||
utxo->T.swappending = 0; |
|||
if ( utxo != 0 && utxo->T.swappending == 0 && utxo->S.swap == 0 ) |
|||
return(1); |
|||
else return(0); |
|||
} |
|||
|
|||
int32_t LP_isunspent(struct LP_utxoinfo *utxo) |
|||
{ |
|||
if ( utxo != 0 && utxo->T.spentflag == 0 && LP_isavailable(utxo) > 0 ) |
|||
return(1); |
|||
else return(0); |
|||
} |
|||
|
|||
void LP_utxosetkey(uint8_t *key,bits256 txid,int32_t vout) |
|||
{ |
|||
memcpy(key,txid.bytes,sizeof(txid)); |
|||
memcpy(&key[sizeof(txid)],&vout,sizeof(vout)); |
|||
} |
|||
|
|||
struct LP_utxoinfo *_LP_utxofind(int32_t iambob,bits256 txid,int32_t vout) |
|||
{ |
|||
struct LP_utxoinfo *utxo=0; uint8_t key[sizeof(txid) + sizeof(vout)]; |
|||
LP_utxosetkey(key,txid,vout); |
|||
HASH_FIND(hh,LP_utxoinfos[iambob],key,sizeof(key),utxo); |
|||
return(utxo); |
|||
} |
|||
|
|||
struct LP_utxoinfo *_LP_utxo2find(int32_t iambob,bits256 txid2,int32_t vout2) |
|||
{ |
|||
struct LP_utxoinfo *utxo=0; uint8_t key2[sizeof(txid2) + sizeof(vout2)]; |
|||
LP_utxosetkey(key2,txid2,vout2); |
|||
HASH_FIND(hh2,LP_utxoinfos2[iambob],key2,sizeof(key2),utxo); |
|||
return(utxo); |
|||
} |
|||
|
|||
struct LP_utxoinfo *LP_utxofind(int32_t iambob,bits256 txid,int32_t vout) |
|||
{ |
|||
struct LP_utxoinfo *utxo=0; |
|||
portable_mutex_lock(&LP_utxomutex); |
|||
utxo = _LP_utxofind(iambob,txid,vout); |
|||
portable_mutex_unlock(&LP_utxomutex); |
|||
return(utxo); |
|||
} |
|||
|
|||
struct LP_utxoinfo *LP_utxo2find(int32_t iambob,bits256 txid2,int32_t vout2) |
|||
{ |
|||
struct LP_utxoinfo *utxo=0; |
|||
portable_mutex_lock(&LP_utxomutex); |
|||
utxo = _LP_utxo2find(iambob,txid2,vout2); |
|||
portable_mutex_unlock(&LP_utxomutex); |
|||
return(utxo); |
|||
} |
|||
|
|||
struct LP_utxoinfo *LP_utxofinds(int32_t iambob,bits256 txid,int32_t vout,bits256 txid2,int32_t vout2) |
|||
{ |
|||
struct LP_utxoinfo *utxo; |
|||
if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 || (utxo= LP_utxofind(iambob,txid2,vout2)) != 0 || (utxo= LP_utxo2find(iambob,txid,vout)) != 0 || (utxo= LP_utxo2find(iambob,txid2,vout2)) != 0 ) |
|||
return(utxo); |
|||
else return(0); |
|||
} |
|||
|
|||
int32_t LP_utxoaddptrs(struct LP_utxoinfo *ptrs[],int32_t n,struct LP_utxoinfo *utxo) |
|||
{ |
|||
int32_t i; |
|||
for (i=0; i<n; i++) |
|||
if ( ptrs[i] == utxo ) |
|||
return(n); |
|||
ptrs[n++] = utxo; |
|||
return(n); |
|||
} |
|||
|
|||
int32_t LP_utxocollisions(struct LP_utxoinfo *ptrs[],struct LP_utxoinfo *refutxo) |
|||
{ |
|||
int32_t iambob,n = 0; struct LP_utxoinfo *utxo; struct _LP_utxoinfo u; |
|||
portable_mutex_lock(&LP_utxomutex); |
|||
for (iambob=0; iambob<=1; iambob++) |
|||
{ |
|||
if ( (utxo= _LP_utxofind(iambob,refutxo->payment.txid,refutxo->payment.vout)) != 0 && utxo != refutxo ) |
|||
n = LP_utxoaddptrs(ptrs,n,utxo); |
|||
if ( (utxo= _LP_utxo2find(iambob,refutxo->payment.txid,refutxo->payment.vout)) != 0 && utxo != refutxo ) |
|||
n = LP_utxoaddptrs(ptrs,n,utxo); |
|||
u = (refutxo->iambob != 0) ? refutxo->deposit : refutxo->fee; |
|||
if ( (utxo= _LP_utxofind(iambob,u.txid,u.vout)) != 0 && utxo != refutxo ) |
|||
n = LP_utxoaddptrs(ptrs,n,utxo); |
|||
if ( (utxo= _LP_utxo2find(iambob,u.txid,u.vout)) != 0 && utxo != refutxo ) |
|||
n = LP_utxoaddptrs(ptrs,n,utxo); |
|||
} |
|||
portable_mutex_unlock(&LP_utxomutex); |
|||
if ( 0 && n > 0 ) |
|||
printf("LP_utxocollisions n.%d\n",n); |
|||
return(n); |
|||
} |
|||
|
|||
int32_t _LP_availableset(struct LP_utxoinfo *utxo) |
|||
{ |
|||
int32_t flag = 0; |
|||
if ( utxo != 0 ) |
|||
{ |
|||
if ( bits256_nonz(utxo->S.otherpubkey) != 0 ) |
|||
flag = 1, memset(&utxo->S.otherpubkey,0,sizeof(utxo->S.otherpubkey)); |
|||
if ( utxo->S.swap != 0 ) |
|||
flag = 1, utxo->S.swap = 0; |
|||
if ( utxo->T.swappending != 0 ) |
|||
flag = 1, utxo->T.swappending = 0; |
|||
return(flag); |
|||
} |
|||
return(0); |
|||
} |
|||
|
|||
void _LP_unavailableset(struct LP_utxoinfo *utxo,bits256 otherpubkey) |
|||
{ |
|||
if ( utxo != 0 ) |
|||
{ |
|||
utxo->T.swappending = (uint32_t)(time(NULL) + LP_RESERVETIME); |
|||
utxo->S.otherpubkey = otherpubkey; |
|||
} |
|||
} |
|||
|
|||
void LP_unavailableset(struct LP_utxoinfo *utxo,bits256 otherpubkey) |
|||
{ |
|||
struct LP_utxoinfo *ptrs[8]; int32_t i,n; struct _LP_utxoinfo u; |
|||
memset(ptrs,0,sizeof(ptrs)); |
|||
if ( (n= LP_utxocollisions(ptrs,utxo)) > 0 ) |
|||
{ |
|||
for (i=0; i<n; i++) |
|||
_LP_unavailableset(ptrs[i],otherpubkey); |
|||
} |
|||
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; |
|||
char str[65],str2[65]; printf("UTXO.[%d] RESERVED %s/v%d %s/v%d collisions.%d\n",utxo->iambob,bits256_str(str,utxo->payment.txid),utxo->payment.vout,bits256_str(str2,u.txid),u.vout,n); |
|||
_LP_unavailableset(utxo,otherpubkey); |
|||
} |
|||
|
|||
void LP_availableset(struct LP_utxoinfo *utxo) |
|||
{ |
|||
struct LP_utxoinfo *ptrs[8]; int32_t i,n,count = 0; struct _LP_utxoinfo u; |
|||
memset(ptrs,0,sizeof(ptrs)); |
|||
if ( (n= LP_utxocollisions(ptrs,utxo)) > 0 ) |
|||
{ |
|||
for (i=0; i<n; i++) |
|||
count += _LP_availableset(ptrs[i]); |
|||
} |
|||
count += _LP_availableset(utxo); |
|||
if ( count > 0 ) |
|||
{ |
|||
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; |
|||
char str[65],str2[65]; printf("UTXO.[%d] AVAIL %s/v%d %s/v%d collisions.%d\n",utxo->iambob,bits256_str(str,utxo->payment.txid),utxo->payment.vout,bits256_str(str2,u.txid),u.vout,n); |
|||
} |
|||
} |
|||
|
|||
int32_t LP_utxopurge(int32_t allutxos) |
|||
{ |
|||
char str[65]; struct LP_utxoinfo *utxo,*tmp; int32_t iambob,n = 0; |
|||
printf("LP_utxopurge mypub.(%s)\n",bits256_str(str,LP_mypubkey)); |
|||
portable_mutex_lock(&LP_utxomutex); |
|||
for (iambob=0; iambob<=1; iambob++) |
|||
{ |
|||
HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) |
|||
{ |
|||
if ( LP_isavailable(utxo) > 0 ) |
|||
{ |
|||
if ( allutxos != 0 || LP_ismine(utxo) > 0 ) |
|||
{ |
|||
printf("iambob.%d delete.(%s)\n",iambob,bits256_str(str,utxo->payment.txid)); |
|||
HASH_DELETE(hh,LP_utxoinfos[iambob],utxo); |
|||
//free(utxo); let the LP_utxoinfos2 free the utxo, should be 1:1
|
|||
} else n++; |
|||
} else n++; |
|||
} |
|||
HASH_ITER(hh,LP_utxoinfos2[iambob],utxo,tmp) |
|||
{ |
|||
if ( LP_isavailable(utxo) > 0 ) |
|||
{ |
|||
if ( allutxos != 0 || LP_ismine(utxo) > 0 ) |
|||
{ |
|||
printf("iambob.%d delete2.(%s)\n",iambob,bits256_str(str,utxo->payment.txid)); |
|||
HASH_DELETE(hh2,LP_utxoinfos2[iambob],utxo); |
|||
free(utxo); |
|||
} else n++; |
|||
} else n++; |
|||
} |
|||
} |
|||
portable_mutex_unlock(&LP_utxomutex); |
|||
return(n); |
|||
} |
|||
|
|||
cJSON *LP_inventoryjson(cJSON *item,struct LP_utxoinfo *utxo) |
|||
{ |
|||
struct _LP_utxoinfo u; |
|||
jaddstr(item,"method","notified"); |
|||
if ( utxo->gui[0] != 0 ) |
|||
jaddstr(item,"gui",utxo->gui); |
|||
jaddstr(item,"coin",utxo->coin); |
|||
jaddnum(item,"now",time(NULL)); |
|||
jaddnum(item,"iambob",utxo->iambob); |
|||
jaddstr(item,"address",utxo->coinaddr); |
|||
jaddbits256(item,"txid",utxo->payment.txid); |
|||
jaddnum(item,"vout",utxo->payment.vout); |
|||
jadd64bits(item,"value",utxo->payment.value); |
|||
jadd64bits(item,"satoshis",utxo->S.satoshis); |
|||
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; |
|||
if ( bits256_nonz(u.txid) != 0 ) |
|||
{ |
|||
jaddbits256(item,"txid2",u.txid); |
|||
jaddnum(item,"vout2",u.vout); |
|||
jadd64bits(item,"value2",u.value); |
|||
} |
|||
if ( utxo->T.swappending != 0 ) |
|||
jaddnum(item,"pending",utxo->T.swappending); |
|||
if ( utxo->iambob != 0 ) |
|||
{ |
|||
jaddbits256(item,"srchash",LP_mypubkey); |
|||
if ( bits256_nonz(utxo->S.otherpubkey) != 0 ) |
|||
jaddbits256(item,"desthash",utxo->S.otherpubkey); |
|||
} |
|||
else |
|||
{ |
|||
jaddbits256(item,"desthash",LP_mypubkey); |
|||
if ( bits256_nonz(utxo->S.otherpubkey) != 0 ) |
|||
jaddbits256(item,"srchash",utxo->S.otherpubkey); |
|||
} |
|||
if ( utxo->S.swap != 0 ) |
|||
jaddstr(item,"swap","in progress"); |
|||
if ( utxo->T.spentflag != 0 ) |
|||
jaddnum(item,"spent",utxo->T.spentflag); |
|||
return(item); |
|||
} |
|||
|
|||
cJSON *LP_utxojson(struct LP_utxoinfo *utxo) |
|||
{ |
|||
cJSON *item = cJSON_CreateObject(); |
|||
item = LP_inventoryjson(item,utxo); |
|||
jaddbits256(item,"pubkey",utxo->pubkey); |
|||
jaddnum(item,"profit",utxo->S.profitmargin); |
|||
jaddstr(item,"base",utxo->coin); |
|||
jaddstr(item,"script",utxo->spendscript); |
|||
return(item); |
|||
} |
|||
|
|||
int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2,bits256 pubkey) |
|||
{ |
|||
uint64_t val,val2=0,threshold; char destaddr[64],destaddr2[64]; |
|||
destaddr[0] = destaddr2[0] = 0; |
|||
if ( (val= LP_txvalue(destaddr,symbol,txid,vout)) >= satoshis ) |
|||
{ |
|||
threshold = (iambob != 0) ? LP_DEPOSITSATOSHIS(satoshis) : LP_DEXFEE(satoshis); |
|||
if ( (val2= LP_txvalue(destaddr2,symbol,txid2,vout2)) >= threshold ) |
|||
{ |
|||
if ( strcmp(destaddr,destaddr2) != 0 ) |
|||
printf("mismatched %s destaddr %s vs %s\n",symbol,destaddr,destaddr2); |
|||
else if ( (iambob == 0 && val2 > val) || (iambob != 0 && val2 <= satoshis) ) |
|||
printf("iambob.%d ineligible due to offsides: val %.8f and val2 %.8f vs %.8f diff %lld\n",iambob,dstr(val),dstr(val2),dstr(satoshis),(long long)(val2 - val)); |
|||
else |
|||
{ |
|||
*valp = val; |
|||
*val2p = val2; |
|||
return(1); |
|||
} |
|||
} else printf("no val2\n"); |
|||
} else printf("mismatched %s txid value %.8f < %.8f\n",symbol,dstr(val),dstr(satoshis)); |
|||
*valp = val; |
|||
*val2p = val2; |
|||
return(0); |
|||
} |
|||
|
|||
char *LP_utxos(int32_t iambob,struct LP_peerinfo *mypeer,char *symbol,int32_t lastn) |
|||
{ |
|||
int32_t i,firsti,n; uint64_t val,val2; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray(); |
|||
i = 0; |
|||
n = mypeer != 0 ? mypeer->numutxos : 0; |
|||
if ( lastn <= 0 ) |
|||
lastn = LP_PROPAGATION_SLACK * 2; |
|||
if ( lastn >= n ) |
|||
firsti = -1; |
|||
else firsti = (lastn - n); |
|||
//printf("LP_utxos iambob.%d symbol.%s firsti.%d lastn.%d\n",iambob,symbol==0?"":symbol,firsti,lastn);
|
|||
HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) |
|||
{ |
|||
//char str[65]; printf("check %s.%s\n",utxo->coin,bits256_str(str,utxo->payment.txid));
|
|||
if ( i++ < firsti ) |
|||
continue; |
|||
if ( (symbol == 0 || symbol[0] == 0 || strcmp(symbol,utxo->coin) == 0) && utxo->T.spentflag == 0 ) |
|||
{ |
|||
u = (iambob != 0) ? utxo->deposit : utxo->fee; |
|||
if ( LP_iseligible(&val,&val2,iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,u.txid,u.vout,utxo->pubkey) == 0 ) |
|||
{ |
|||
char str[65]; printf("iambob.%d not eligible (%.8f %.8f) %s %s/v%d\n",iambob,dstr(val),dstr(val2),utxo->coin,bits256_str(str,utxo->payment.txid),utxo->payment.vout); |
|||
continue; |
|||
} else jaddi(utxosjson,LP_utxojson(utxo)); |
|||
} |
|||
} |
|||
return(jprint(utxosjson,1)); |
|||
} |
|||
|
|||
int32_t LP_inventory_prevent(int32_t iambob,bits256 txid,int32_t vout) |
|||
{ |
|||
struct LP_utxoinfo *utxo; |
|||
if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 || (utxo= LP_utxo2find(iambob,txid,vout)) != 0 ) |
|||
{ |
|||
//if ( utxo->T.spentflag != 0 )
|
|||
{ |
|||
//char str[65]; printf("prevent adding %s/v%d to inventory\n",bits256_str(str,txid),vout);
|
|||
return(1); |
|||
} |
|||
} |
|||
return(0); |
|||
} |
|||
|
|||
struct LP_utxoinfo *LP_utxo_bestfit(char *symbol,uint64_t destsatoshis) |
|||
{ |
|||
struct LP_utxoinfo *utxo,*tmp,*bestutxo = 0; |
|||
if ( symbol == 0 || destsatoshis == 0 ) |
|||
return(0); |
|||
HASH_ITER(hh,LP_utxoinfos[0],utxo,tmp) |
|||
{ |
|||
//char str[65]; printf("check %s.%s\n",utxo->coin,bits256_str(str,utxo->payment.txid));
|
|||
if ( strcmp(symbol,utxo->coin) == 0 && LP_isavailable(utxo) > 0 && LP_ismine(utxo) > 0 ) |
|||
{ |
|||
if ( utxo->S.satoshis >= destsatoshis && (bestutxo == 0 || utxo->S.satoshis < bestutxo->S.satoshis) ) |
|||
bestutxo = utxo; |
|||
} |
|||
} |
|||
return(bestutxo); |
|||
} |
|||
|
|||
void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector) |
|||
{ |
|||
cJSON *argjson; struct _LP_utxoinfo u; char *msg; |
|||
utxo->T.spentflag = (uint32_t)time(NULL); |
|||
if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 ) |
|||
LP_mypeer->numutxos--; |
|||
if ( LP_mypubsock >= 0 ) |
|||
{ |
|||
argjson = cJSON_CreateObject(); |
|||
jaddstr(argjson,"method","checktxid"); |
|||
jaddbits256(argjson,"txid",utxo->payment.txid); |
|||
jaddnum(argjson,"vout",utxo->payment.vout); |
|||
if ( selector != 0 ) |
|||
{ |
|||
if ( bits256_nonz(utxo->deposit.txid) != 0 ) |
|||
u = utxo->deposit; |
|||
else u = utxo->fee; |
|||
jaddbits256(argjson,"checktxid",u.txid); |
|||
jaddnum(argjson,"checkvout",u.vout); |
|||
} |
|||
msg = jprint(argjson,1); |
|||
LP_send(LP_mypubsock,msg,(int32_t)strlen(msg)+1,1); |
|||
} |
|||
} |
|||
|
|||
char *LP_spentcheck(cJSON *argjson) |
|||
{ |
|||
char destaddr[64]; bits256 txid,checktxid; int32_t vout,checkvout; struct LP_utxoinfo *utxo; int32_t iambob,retval = 0; |
|||
txid = jbits256(argjson,"txid"); |
|||
vout = jint(argjson,"vout"); |
|||
for (iambob=0; iambob<=1; iambob++) |
|||
{ |
|||
if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 && utxo->T.spentflag == 0 ) |
|||
{ |
|||
if ( jobj(argjson,"check") == 0 ) |
|||
checktxid = txid, checkvout = vout; |
|||
else |
|||
{ |
|||
checktxid = jbits256(argjson,"checktxid"); |
|||
checkvout = jint(argjson,"checkvout"); |
|||
} |
|||
if ( LP_txvalue(destaddr,utxo->coin,checktxid,checkvout) == 0 ) |
|||
{ |
|||
if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 ) |
|||
LP_mypeer->numutxos--; |
|||
utxo->T.spentflag = (uint32_t)time(NULL); |
|||
retval++; |
|||
//printf("indeed txid was spent\n");
|
|||
} |
|||
} |
|||
} |
|||
if ( retval > 0 ) |
|||
return(clonestr("{\"result\":\"marked as spent\"}")); |
|||
return(clonestr("{\"error\":\"cant find txid to check spent status\"}")); |
|||
} |
|||
|
|||
struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bits256 txid,int32_t vout,int64_t value,bits256 txid2,int32_t vout2,int64_t value2,char *spendscript,char *coinaddr,bits256 pubkey,double profitmargin,char *gui) |
|||
{ |
|||
uint64_t val,val2=0,tmpsatoshis,bigtxfee = 100000; int32_t spendvini,selector; bits256 spendtxid; char *msg; struct iguana_info *coin; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo = 0; |
|||
if ( symbol == 0 || symbol[0] == 0 || spendscript == 0 || spendscript[0] == 0 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 || vout < 0 || vout2 < 0 || value <= 0 || value2 <= 0 ) |
|||
{ |
|||
printf("malformed addutxo %d %d %d %d %d %d %d %d %d\n", symbol == 0,spendscript == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(txid2) == 0,vout < 0,vout2 < 0,value <= 0,value2 <= 0); |
|||
return(0); |
|||
} |
|||
if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) |
|||
return(0); |
|||
if ( iambob != 0 && value2 < 9 * (value >> 3) + bigtxfee ) // big txfee padding
|
|||
{ |
|||
if ( value2 > bigtxfee+20000 ) |
|||
tmpsatoshis = (((value2 - bigtxfee) / 9) << 3); |
|||
else return(0); |
|||
} else tmpsatoshis = value; |
|||
char str[65],str2[65],dispflag = (iambob == 0); |
|||
if ( iambob == 0 && bits256_cmp(pubkey,LP_mypubkey) != 0 ) |
|||
{ |
|||
printf("trying to add Alice utxo when not mine? %s/v%d\n",bits256_str(str,txid),vout); |
|||
return(0); |
|||
} |
|||
if ( LP_iseligible(&val,&val2,iambob,symbol,txid,vout,tmpsatoshis,txid2,vout2,pubkey) <= 0 ) |
|||
{ |
|||
printf("iambob.%d utxoadd %s inactive.%u got ineligible txid value %.8f, value2 %.8f, tmpsatoshis %.8f\n",iambob,symbol,coin->inactive,dstr(value),dstr(value2),dstr(tmpsatoshis)); |
|||
return(0); |
|||
} |
|||
if ( dispflag != 0 ) |
|||
printf("%.8f %.8f %s iambob.%d %s utxoadd.(%.8f %.8f) %s %s\n",dstr(val),dstr(val2),coinaddr,iambob,symbol,dstr(value),dstr(value2),bits256_str(str,txid),bits256_str(str2,txid2)); |
|||
dispflag = 1; |
|||
if ( 0 && (selector= LP_mempool_vinscan(&spendtxid,&spendvini,symbol,txid,vout,txid2,vout2)) >= 0 ) |
|||
{ |
|||
printf("utxoadd selector.%d in mempool %s vini.%d",selector,bits256_str(str,spendtxid),spendvini); |
|||
return(0); |
|||
} |
|||
if ( (utxo= LP_utxofinds(iambob,txid,vout,txid2,vout2)) != 0 ) |
|||
{ |
|||
if ( 0 && LP_ismine(utxo) == 0 ) |
|||
{ |
|||
char str2[65],str3[65]; printf("iambob.%d %s %s utxoadd.(%.8f %.8f) %s %s\n",iambob,bits256_str(str3,pubkey),symbol,dstr(value),dstr(value2),bits256_str(str,txid),bits256_str(str2,txid2)); |
|||
printf("duplicate %.8f %.8f %.8f vs utxo.(%.8f %.8f %.8f)\n",dstr(value),dstr(value2),dstr(tmpsatoshis),dstr(utxo->payment.value),dstr(utxo->deposit.value),dstr(utxo->S.satoshis)); |
|||
} |
|||
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; |
|||
if ( bits256_cmp(txid,utxo->payment.txid) != 0 || bits256_cmp(txid2,u.txid) != 0 || vout != utxo->payment.vout || value != utxo->payment.value || tmpsatoshis != utxo->S.satoshis || vout2 != u.vout || value2 != u.value || strcmp(symbol,utxo->coin) != 0 || strcmp(spendscript,utxo->spendscript) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || bits256_cmp(pubkey,utxo->pubkey) != 0 ) |
|||
{ |
|||
utxo->T.errors++; |
|||
char str[65],str2[65],str3[65],str4[65],str5[65],str6[65]; |
|||
if ( dispflag != 0 ) |
|||
printf("error on subsequent utxo iambob.%d %.8f %.8f add.(%s %s) when.(%s %s) %d %d %d %d %d %d %d %d %d %d %d pubkeys.(%s vs %s)\n",iambob,dstr(val),dstr(val2),bits256_str(str,txid),bits256_str(str2,txid2),bits256_str(str3,utxo->payment.txid),bits256_str(str4,utxo->deposit.txid),bits256_cmp(txid,utxo->payment.txid) != 0,bits256_cmp(txid2,u.txid) != 0,vout != utxo->payment.vout,tmpsatoshis != utxo->S.satoshis,vout2 != u.vout,value2 != u.value,strcmp(symbol,utxo->coin) != 0,strcmp(spendscript,utxo->spendscript) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,bits256_cmp(pubkey,utxo->pubkey) != 0,value != utxo->payment.value,bits256_str(str5,pubkey),bits256_str(str6,utxo->pubkey)); |
|||
if ( utxo->T.spentflag != 0 || LP_txvalue(utxo->coinaddr,utxo->coin,utxo->payment.txid,utxo->payment.vout) < utxo->payment.value || LP_txvalue(utxo->coinaddr,utxo->coin,u.txid,u.vout) < u.value ) |
|||
{ |
|||
if ( utxo->T.spentflag == 0 ) |
|||
utxo->T.spentflag = (uint32_t)time(NULL); |
|||
printf("original utxo pair not valid\n"); |
|||
utxo = 0; |
|||
} |
|||
} |
|||
else if ( profitmargin > SMALLVAL ) |
|||
utxo->S.profitmargin = profitmargin; |
|||
if ( utxo != 0 ) |
|||
return(utxo); |
|||
} |
|||
utxo = calloc(1,sizeof(*utxo)); |
|||
utxo->S.profitmargin = profitmargin; |
|||
utxo->pubkey = pubkey; |
|||
safecopy(utxo->gui,gui,sizeof(utxo->gui)); |
|||
safecopy(utxo->coin,symbol,sizeof(utxo->coin)); |
|||
safecopy(utxo->coinaddr,coinaddr,sizeof(utxo->coinaddr)); |
|||
safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript)); |
|||
utxo->payment.txid = txid; |
|||
utxo->payment.vout = vout; |
|||
utxo->payment.value = value; |
|||
utxo->S.satoshis = tmpsatoshis; |
|||
if ( (utxo->iambob= iambob) != 0 ) |
|||
{ |
|||
utxo->deposit.txid = txid2; |
|||
utxo->deposit.vout = vout2; |
|||
utxo->deposit.value = value2; |
|||
} |
|||
else |
|||
{ |
|||
utxo->fee.txid = txid2; |
|||
utxo->fee.vout = vout2; |
|||
utxo->fee.value = value2; |
|||
} |
|||
LP_utxosetkey(utxo->key,txid,vout); |
|||
LP_utxosetkey(utxo->key2,txid2,vout2); |
|||
portable_mutex_lock(&LP_utxomutex); |
|||
HASH_ADD_KEYPTR(hh,LP_utxoinfos[iambob],utxo->key,sizeof(utxo->key),utxo); |
|||
if ( _LP_utxo2find(iambob,txid2,vout2) == 0 ) |
|||
HASH_ADD_KEYPTR(hh2,LP_utxoinfos2[iambob],utxo->key2,sizeof(utxo->key2),utxo); |
|||
portable_mutex_unlock(&LP_utxomutex); |
|||
if ( iambob != 0 ) |
|||
{ |
|||
if ( mypubsock >= 0 ) |
|||
{ |
|||
msg = jprint(LP_utxojson(utxo),1); |
|||
LP_send(mypubsock,msg,(int32_t)strlen(msg)+1,1); |
|||
} else LP_utxo_clientpublish(utxo); |
|||
if ( LP_mypeer != 0 && LP_ismine(utxo) > 0 ) |
|||
LP_mypeer->numutxos++; |
|||
} |
|||
return(utxo); |
|||
} |
|||
|
|||
struct LP_utxoinfo *LP_utxoaddjson(int32_t iambob,int32_t pubsock,cJSON *argjson) |
|||
{ |
|||
struct LP_utxoinfo *utxo; |
|||
if ( jobj(argjson,"iambob") == 0 || iambob != jint(argjson,"iambob") ) |
|||
{ |
|||
printf("LP_utxoaddjson: iambob.%d != arg.%d obj.%p (%s)\n",iambob,jint(argjson,"iambob"),jobj(argjson,"iambob"),jprint(argjson,0)); |
|||
return(0); |
|||
} |
|||
portable_mutex_lock(&LP_UTXOmutex); |
|||
utxo = LP_utxoadd(iambob,pubsock,jstr(argjson,"coin"),jbits256(argjson,"txid"),jint(argjson,"vout"),j64bits(argjson,"value"),jbits256(argjson,"txid2"),jint(argjson,"vout2"),j64bits(argjson,"value2"),jstr(argjson,"script"),jstr(argjson,"address"),jbits256(argjson,"pubkey"),jdouble(argjson,"profit"),jstr(argjson,"gui")); |
|||
portable_mutex_unlock(&LP_UTXOmutex); |
|||
return(utxo); |
|||
} |
|||
|
|||
int32_t LP_utxosparse(char *destipaddr,uint16_t destport,char *retstr,uint32_t now) |
|||
{ |
|||
struct LP_peerinfo *destpeer,*peer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; bits256 txid; struct LP_utxoinfo *utxo; |
|||
//printf("parse.(%s)\n",retstr);
|
|||
if ( (array= cJSON_Parse(retstr)) != 0 ) |
|||
{ |
|||
if ( (n= cJSON_GetArraySize(array)) > 0 ) |
|||
{ |
|||
for (i=0; i<n; i++) |
|||
{ |
|||
item = jitem(array,i); |
|||
if ( (argipaddr= jstr(item,"ipaddr")) != 0 && (argport= juint(item,"port")) != 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(0,-1,argipaddr,argport,pushport,subport,jdouble(item,"profit"),jint(item,"numpeers"),jint(item,"numutxos")); |
|||
} |
|||
if ( jobj(item,"txid") != 0 ) |
|||
{ |
|||
txid = jbits256(item,"txid"); |
|||
//printf("parse.(%s)\n",jprint(item,0));
|
|||
if ( (utxo= LP_utxoaddjson(1,-1,item)) != 0 ) |
|||
{ |
|||
//if ( strcmp(utxo->coin,"HUSH") == 0 )
|
|||
// printf("%s set lasttime (%s)\n",destipaddr,jprint(item,0));
|
|||
utxo->T.lasttime = now; |
|||
} |
|||
} |
|||
} |
|||
if ( (destpeer= LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport)) != 0 ) |
|||
{ |
|||
destpeer->numutxos = n; |
|||
} |
|||
} |
|||
free_json(array); |
|||
} |
|||
return(n); |
|||
} |
|||
|
|||
int32_t 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_peerinfo *peer; uint32_t now; int32_t retval = -1; |
|||
peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); |
|||
if ( coin == 0 ) |
|||
coin = ""; |
|||
//printf("utxo query.(%s)\n",destipaddr);
|
|||
if ( IAMLP != 0 ) |
|||
retstr = issue_LP_getutxos(destipaddr,destport,coin,lastn,myipaddr,myport,myprofit,mypeer != 0 ? mypeer->numpeers : 0,mypeer != 0 ? mypeer->numutxos : 0); |
|||
else retstr = issue_LP_clientgetutxos(destipaddr,destport,coin,100); |
|||
if ( retstr != 0 ) |
|||
{ |
|||
now = (uint32_t)time(NULL); |
|||
retval = LP_utxosparse(destipaddr,destport,retstr,now); |
|||
//printf("got.(%s)\n",retstr);
|
|||
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");*/ |
|||
} |
|||
return(retval); |
|||
} |
|||
|
|||
cJSON *LP_inventory(char *symbol,int32_t iambob) |
|||
{ |
|||
struct LP_utxoinfo *utxo,*tmp; char *myipaddr; cJSON *array; |
|||
array = cJSON_CreateArray(); |
|||
if ( LP_mypeer != 0 ) |
|||
myipaddr = LP_mypeer->ipaddr; |
|||
else myipaddr = "127.0.0.1"; |
|||
HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) |
|||
{ |
|||
//char str[65]; printf("iambob.%d iterate %s\n",iambob,bits256_str(str,LP_mypubkey));
|
|||
if ( LP_isunspent(utxo) != 0 && strcmp(symbol,utxo->coin) == 0 && utxo->iambob == iambob && LP_ismine(utxo) > 0 ) |
|||
jaddi(array,LP_inventoryjson(cJSON_CreateObject(),utxo)); |
|||
//else printf("skip %s %d %d %d %d\n",bits256_str(str,utxo->pubkey),LP_isunspent(utxo) != 0,strcmp(symbol,utxo->coin) == 0,utxo->iambob == iambob,LP_ismine(utxo) > 0);
|
|||
} |
|||
return(array); |
|||
} |
|||
|
|||
int32_t LP_maxvalue(uint64_t *values,int32_t n) |
|||
{ |
|||
int32_t i,maxi = -1; uint64_t maxval = 0; |
|||
for (i=0; i<n; i++) |
|||
if ( values[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<n; i++) |
|||
{ |
|||
dist = (values[i] - targetval); |
|||
if ( dist < 0 && -dist < values[i]/10 ) |
|||
dist = -dist; |
|||
if ( dist >= 0 && dist < mindist ) |
|||
{ |
|||
mini = i; |
|||
mindist = dist; |
|||
} |
|||
} |
|||
return(mini); |
|||
} |
|||
|
|||
uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 myprivkey,bits256 mypub,uint8_t *pubkey33) |
|||
{ |
|||
char *script; struct LP_utxoinfo *utxo; cJSON *array,*item; bits256 txid,deposittxid; int32_t used,i,n,iambob,vout,depositvout; uint64_t *values=0,satoshis,depositval,targetval,value,total = 0; |
|||
if ( coin == 0 ) |
|||
{ |
|||
printf("coin not active\n"); |
|||
return(0); |
|||
} |
|||
//printf("privkey init.(%s) %s\n",coin->symbol,coin->smartaddr);
|
|||
if ( coin->inactive == 0 && (array= LP_listunspent(coin->symbol,coin->smartaddr)) != 0 ) |
|||
{ |
|||
if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) |
|||
{ |
|||
for (iambob=0; iambob<=1; iambob++) |
|||
{ |
|||
if ( iambob == 0 ) |
|||
values = calloc(n,sizeof(*values)); |
|||
else memset(values,0,n * sizeof(*values)); |
|||
//if ( iambob == 0 && IAMLP != 0 )
|
|||
// continue;
|
|||
used = 0; |
|||
for (i=0; i<n; i++) |
|||
{ |
|||
item = jitem(array,i); |
|||
satoshis = SATOSHIDEN * jdouble(item,"amount"); |
|||
if ( LP_inventory_prevent(iambob,jbits256(item,"txid"),juint(item,"vout")) == 0 ) |
|||
values[i] = satoshis; |
|||
else used++; |
|||
//printf("%.8f ",dstr(satoshis));
|
|||
} |
|||
//printf("array.%d\n",n);
|
|||
while ( used < n-1 ) |
|||
{ |
|||
//printf("used.%d of n.%d\n",used,n);
|
|||
if ( (i= LP_maxvalue(values,n)) >= 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 ( iambob == 0 ) |
|||
targetval = (depositval / 776) + 100000; |
|||
else targetval = (depositval / 9) * 8 + 100000; |
|||
//printf("i.%d %.8f target %.8f\n",i,dstr(depositval),dstr(targetval));
|
|||
if ( (i= LP_nearestvalue(values,n,targetval)) < 0 && iambob != 0 ) |
|||
targetval /= 4; |
|||
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++; |
|||
portable_mutex_lock(&LP_UTXOmutex); |
|||
if ( iambob != 0 ) |
|||
{ |
|||
if ( (utxo= LP_utxoadd(1,mypubsock,coin->symbol,txid,vout,value,deposittxid,depositvout,depositval,script,coin->smartaddr,mypub,LP_mypeer != 0 ? LP_mypeer->profitmargin : 0.01,LP_gui)) != 0 ) |
|||
{ |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if ( (utxo= LP_utxoadd(0,mypubsock,coin->symbol,deposittxid,depositvout,depositval,txid,vout,value,script,coin->smartaddr,mypub,0.,LP_gui)) != 0 ) |
|||
{ |
|||
} |
|||
} |
|||
portable_mutex_unlock(&LP_UTXOmutex); |
|||
total += value; |
|||
} |
|||
} |
|||
} else break; |
|||
} |
|||
if ( iambob == 1 ) |
|||
free(values); |
|||
} |
|||
} |
|||
free_json(array); |
|||
} |
|||
//printf("privkey.%s %.8f\n",symbol,dstr(total));
|
|||
return(total); |
|||
} |
|||
|
|||
bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguana_info *coin,char *passphrase,char *wifstr) |
|||
{ |
|||
static uint32_t counter; |
|||
bits256 privkey,userpub,userpass; char tmpstr[128]; cJSON *retjson; uint8_t tmptype,rmd160[20]; |
|||
if ( passphrase != 0 && passphrase[0] != 0 ) |
|||
conv_NXTpassword(privkey.bytes,pubkeyp->bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); |
|||
else |
|||
{ |
|||
privkey = iguana_wif2privkey(wifstr); |
|||
//printf("WIF.(%s) -> %s\n",wifstr,bits256_str(str,privkey));
|
|||
} |
|||
iguana_priv2pub(ctx,pubkey33,coin->smartaddr,privkey,coin->taddr,coin->pubtype); |
|||
if ( coin->counter == 0 ) |
|||
{ |
|||
coin->counter++; |
|||
bitcoin_priv2wif(tmpstr,privkey,coin->wiftype); |
|||
bitcoin_addr2rmd160(coin->taddr,&tmptype,rmd160,coin->smartaddr); |
|||
LP_privkeyadd(privkey,rmd160); |
|||
if ( coin->pubtype != 60 || strcmp(coin->symbol,"KMD") == 0 ) |
|||
printf("%s (%s) %d wif.(%s) (%s)\n",coin->symbol,coin->smartaddr,coin->pubtype,tmpstr,passphrase); |
|||
if ( counter++ == 0 ) |
|||
{ |
|||
bitcoin_priv2wif(USERPASS_WIFSTR,privkey,188); |
|||
conv_NXTpassword(userpass.bytes,pubkeyp->bytes,(uint8_t *)USERPASS_WIFSTR,(int32_t)strlen(USERPASS_WIFSTR)); |
|||
userpub = curve25519(userpass,curve25519_basepoint9()); |
|||
printf("userpass.(%s)\n",bits256_str(USERPASS,userpub)); |
|||
} |
|||
if ( (retjson= LP_importprivkey(coin->symbol,tmpstr,coin->smartaddr,-1)) != 0 ) //coin->inactive == 0 &&
|
|||
printf("importprivkey.%s -> (%s)\n",coin->symbol,jprint(retjson,1)); |
|||
} |
|||
LP_mypubkey = *pubkeyp = curve25519(privkey,curve25519_basepoint9()); |
|||
//printf("privkey.(%s) -> LP_mypubkey.(%s)\n",bits256_str(str,privkey),bits256_str(str2,LP_mypubkey));
|
|||
return(privkey); |
|||
} |
|||
|
|||
void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase,int32_t initonly) |
|||
{ |
|||
int32_t i; struct iguana_info *coin; bits256 pubkey,privkey; uint8_t pubkey33[33]; |
|||
memset(privkey.bytes,0,sizeof(privkey)); |
|||
pubkey = privkey; |
|||
for (i=0; i<LP_numcoins; i++) |
|||
{ |
|||
//printf("i.%d of %d\n",i,LP_numcoins);
|
|||
if ( (coin= LP_coinfind(LP_coins[i].symbol)) != 0 ) |
|||
{ |
|||
if ( bits256_nonz(privkey) == 0 || coin->smartaddr[0] == 0 ) |
|||
privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,coin,passphrase,""); |
|||
if ( coin->inactive == 0 && initonly == 0 ) |
|||
LP_privkey_init(pubsock,coin,privkey,pubkey,pubkey33); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
@ -0,0 +1,23 @@ |
|||
You need to build iguana onetime from ~/SuperNET/iguana: |
|||
|
|||
./m_LP |
|||
|
|||
Then launch it to run in background ../agents/iguana & |
|||
|
|||
Now iguana should be running and providing port 7778 API: 127.0.0.1:7778 page in the browser will show the API testpage, but for marketmaker these functions are not used very much. it is port 7779 that is used and the marketmaker program is what provides those functions. |
|||
|
|||
From ~/SuperNET/iguana/exchanges: |
|||
|
|||
./install |
|||
|
|||
Now in the ~/SuperNET/iguana/dexscripts directory you will have example scripts that you can change without new git updates overwriting them. Of course, if a new update to a script is made and you dont run install again then you wont have the latest versions. All these scripts are expecting a userpass file, which contains the definition of the $userpass variable to authenticate API access. This avoids evil webpages that try to issue port 7779 calls to steal your money. The userpass variable is linked to each passphrase and that is defined in the randval file. Put your passphrase in that file. You can find templates for these two files in the iguana/exchanges dir. |
|||
|
|||
Next step is to actually start the marketmaker from ~/SuperNET/iguana/dexscripts. Use ./run for LP node and ./client for client mode |
|||
|
|||
At first you wont know the value of userpass. To find out, just run any API script. The first one will return all the required data, the "userpass" field is first and you can copy that value and put it into ~/SuperNET/iguana/dexscripts/userpass file. If you dont, all subsequent API calls will get authorization errors. |
|||
|
|||
Assuming you created the userpass file properly, you can now issue barterDEX api calls using all the scripts in the dexscripts dir. Please look at these scripts, they are simple curl invocations of a couple lines. Nothing scary and should be self explanatory. |
|||
|
|||
The help script displays all the api endpoints you should need. You can customize any of the dexscripts for your desired usage, make sure you edit them with the right coins, as if you issue a script for BTC it will do it for BTC instead of the coin you wanted. These scripts wont read your mind, they just do what is in them |
|||
|
|||
|
@ -0,0 +1,2 @@ |
|||
source userpass |
|||
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autotrade\",\"base\":\"REVS\",\"rel\":\"KMD\",\"volume\":1.01,\"price\":1.234}" |
@ -0,0 +1,8 @@ |
|||
source randval |
|||
source coins |
|||
pkill -15 marketmaker; |
|||
git pull; |
|||
cd ..; |
|||
./m_mm; |
|||
./marketmaker "{\"gui\":\"nogui\",\"client\":1, \"userhome\":\"/${HOME#"/"}\", \"passphrase\":\"$randval\", \"coins\":$coins}" & |
|||
|
@ -0,0 +1,8 @@ |
|||
source randval |
|||
source coins |
|||
pkill -15 marketmaker; |
|||
git pull; |
|||
cd ..; |
|||
./m_mm; |
|||
./marketmaker "{\"gui\":\"nogui\",\"client\":1, \"userhome\":\"/${HOME#"/"}/Library/Application\ Support\", \"passphrase\":\"$randval\", \"coins\":$coins}" & |
|||
|
@ -0,0 +1 @@ |
|||
export coins="[{\"coin\":\"REVS\",\"active\":1, \"asset\":\"REVS\",\"rpcport\":10196}, {\"coin\":\"JUMBLR\",\"active\":1, \"asset\":\"JUMBLR\",\"rpcport\":15106}, {\"coin\":\"DOGE\", \"name\":\"dogecoin\", \"pubtype\":30, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000000}, {\"coin\":\"HUSH\",\"name\":\"hush\",\"rpcport\":8822,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000 }, {\"active\":0,\"coin\":\"ZEC\",\"name\":\"zcash\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000 }, {\"coin\":\"DGB\", \"name\":\"digibyte\", \"pubtype\":30, \"p2shtype\":5, \"wiftype\":128, \"txfee\":10000}, {\"coin\":\"MZC\", \"name\":\"mazacoin\", \"pubtype\":50, \"p2shtype\":9, \"wiftype\":224, \"txfee\":0}, {\"coin\":\"SYS\", \"name\":\"syscoin\", \"pubtype\":0, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000}, {\"coin\":\"UNO\", \"name\":\"unobtanium\", \"pubtype\":130, \"p2shtype\":30, \"wiftype\":224, \"txfee\":1000000}, {\"coin\":\"ZET\", \"name\":\"zetacoin\", \"pubtype\":80, \"p2shtype\":9, \"wiftype\":224, \"txfee\":10000}, {\"coin\":\"ZEC\", \"name\":\"zcash\", \"pubtype\":184, \"p2shtype\":189, \"wiftype\":128, \"txfee\":10000}, {\"coin\":\"BTM\", \"name\":\"bitmark\", \"pubtype\":85, \"p2shtype\":5, \"wiftype\":213, \"txfee\":0}, {\"coin\":\"CARB\", \"name\":\"carboncoin\", \"pubtype\":47, \"p2shtype\":5, \"wiftype\":175, \"txfee\":0}, {\"coin\":\"ANC\", \"name\":\"anoncoin\", \"pubtype\":23, \"p2shtype\":5, \"wiftype\":151, \"txfee\":2000000}, {\"coin\":\"FRK\", \"name\":\"franko\", \"pubtype\":35, \"p2shtype\":5, \"wiftype\":163, \"txfee\":0}, {\"coin\":\"GAME\", \"name\":\"gamecredits\", \"pubtype\":38, \"p2shtype\":5, \"wiftype\":166, \"txfee\":100000}, {\"coin\":\"LTC\", \"name\":\"litecoin\", \"rpcport\":9332, \"pubtype\":48, \"p2shtype\":5, \"wiftype\":176, \"txfee\":100000 }, {\"coin\":\"SUPERNET\",\"asset\":\"SUPERNET\",\"rpcport\":11341}, {\"coin\":\"WLC\",\"asset\":\"WLC\",\"rpcport\":12167}, {\"coin\":\"PANGEA\",\"asset\":\"PANGEA\",\"rpcport\":14068}, {\"coin\":\"DEX\",\"asset\":\"DEX\",\"rpcport\":11890}, {\"coin\":\"BET\",\"asset\":\"BET\",\"rpcport\":14250}, {\"coin\":\"CRYPTO\",\"asset\":\"CRYPTO\",\"rpcport\":8516}, {\"coin\":\"HODL\",\"asset\":\"HODL\",\"rpcport\":14431}, {\"coin\":\"SHARK\",\"asset\":\"SHARK\",\"rpcport\":10114}, {\"coin\":\"BOTS\",\"asset\":\"BOTS\",\"rpcport\":11964}, {\"coin\":\"MGW\",\"asset\":\"MGW\",\"rpcport\":12386}, {\"coin\":\"COQUI\",\"asset\":\"COQUI\",\"rpcport\":14276}, {\"coin\":\"KV\",\"asset\":\"KV\",\"rpcport\":8299}, {\"coin\":\"CEAL\",\"asset\":\"CEAL\",\"rpcport\":11116}, {\"coin\":\"MESH\",\"asset\":\"MESH\",\"rpcport\":9455}]" |
@ -0,0 +1,2 @@ |
|||
source userpass |
|||
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"disable\",\"coin\":\"REVS\"}" |
@ -0,0 +1,2 @@ |
|||
source userpass |
|||
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"BTC\"}" |
@ -0,0 +1,2 @@ |
|||
source userpass |
|||
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"6578099f6474d9b8bd66a7a136b922029a989818ec0309aee962dd6ac1862b74\",\"method\":\"forward\",\"method2\":\"getprice\",\"base\":\"REVS\",\"rel\":\"KMD\"}" |
@ -0,0 +1,2 @@ |
|||
source userpass |
|||
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"getcoins\"}" |
@ -0,0 +1,2 @@ |
|||
source userpass |
|||
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"getpeers\"}" |
@ -0,0 +1,10 @@ |
|||
curl --url "http://5.9.253.195:7779" --data "{\"method\":\"getpeers\"}" |
|||
curl --url "http://5.9.253.196:7779" --data "{\"method\":\"getpeers\"}" |
|||
curl --url "http://5.9.253.197:7779" --data "{\"method\":\"getpeers\"}" |
|||
curl --url "http://5.9.253.198:7779" --data "{\"method\":\"getpeers\"}" |
|||
curl --url "http://5.9.253.199:7779" --data "{\"method\":\"getpeers\"}" |
|||
curl --url "http://5.9.253.200:7779" --data "{\"method\":\"getpeers\"}" |
|||
curl --url "http://5.9.253.201:7779" --data "{\"method\":\"getpeers\"}" |
|||
curl --url "http://5.9.253.202:7779" --data "{\"method\":\"getpeers\"}" |
|||
curl --url "http://5.9.253.203:7779" --data "{\"method\":\"getpeers\"}" |
|||
curl --url "http://5.9.253.204:7779" --data "{\"method\":\"getpeers\"}" |
@ -0,0 +1,2 @@ |
|||
source userpass |
|||
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"getprices\",\"coin\":\"REVS\"}" |
@ -0,0 +1,2 @@ |
|||
source userpass |
|||
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"getutxos\",\"coin\":\"REVS\"}" |
@ -0,0 +1,2 @@ |
|||
source userpass |
|||
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"help\"}" |
@ -0,0 +1 @@ |
|||
cp autotrade client run_osx client_osx run coins disable enable forward myprice myprices getcoins getpeers getpeersIP getprices getutxos help inv lookup pub run_osx setprice status utxos ../dexscripts |
@ -0,0 +1,2 @@ |
|||
source userpass |
|||
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"inventory\",\"coin\":\"BTC\"}" |
@ -0,0 +1,2 @@ |
|||
source userpass |
|||
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"6578099f6474d9b8bd66a7a136b922029a989818ec0309aee962dd6ac1862b74\",\"method\":\"forward\",\"method2\":\"lookup\",\"client\":\"$1\"}" |
@ -0,0 +1,7 @@ |
|||
while true |
|||
do |
|||
source userpass |
|||
#curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"setprice\",\"base\":\"REVS\",\"rel\":\"KMD\",\"price\":1.234}" |
|||
./s |
|||
sleep 3600 |
|||
done |
@ -0,0 +1,2 @@ |
|||
source userpass |
|||
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"myprice\",\"base\":\"REVS\",\"rel\":\"KMD\"}" |
@ -0,0 +1,2 @@ |
|||
source userpass |
|||
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"myprices\"}" |
@ -0,0 +1,2 @@ |
|||
source userpass |
|||
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"orderbook\",\"base\":\"KMD\",\"rel\":\"BTC\"}" |
@ -0,0 +1,2 @@ |
|||
source userpass |
|||
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"6578099f6474d9b8bd66a7a136b922029a989818ec0309aee962dd6ac1862b74\",\"method\":\"forward\",\"method2\":\"publish\",\"data\":\"nonsense\"}" |
@ -0,0 +1 @@ |
|||
export randval="<put a very strong passphrase here>" |
@ -0,0 +1,3 @@ |
|||
|
|||
source userpass |
|||
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"registerall\",\"numnodes\":10}" |
@ -0,0 +1,7 @@ |
|||
source randval |
|||
source coins |
|||
pkill -15 marketmaker; |
|||
git pull; |
|||
cd ..; |
|||
./m_mm; |
|||
$1 ./marketmaker "{\"gui\":\"nogui\", \"profitmargin\":0.01, \"userhome\":\"/${HOME#"/"}\", \"passphrase\":\"$randval\", \"coins\":$coins}" & |
@ -0,0 +1,7 @@ |
|||
source randval |
|||
source coins |
|||
pkill -15 marketmaker; |
|||
git pull; |
|||
cd ..; |
|||
./m_mm; |
|||
$1 ./marketmaker "{\"gui\":\"nogui\", \"profitmargin\":0.01, \"userhome\":\"/${HOME#"/"}/Library/Application\ Support\", \"passphrase\":\"$randval\", \"coins\":$coins}" & |
@ -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}" |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue