diff --git a/depends/packages/googletest.mk b/depends/packages/googletest.mk index 1275593f5..409c83a1b 100644 --- a/depends/packages/googletest.mk +++ b/depends/packages/googletest.mk @@ -1,6 +1,6 @@ package=googletest $(package)_version=1.8.0 -$(package)_download_path=https://github.com/google/$(package)/archive/ +$(package)_download_path=https://github.com/google/$(package)/archive $(package)_file_name=$(package)-$($(package)_version).tar.gz $(package)_download_file=release-$($(package)_version).tar.gz $(package)_sha256_hash=58a6f4277ca2bc8565222b3bbd58a177609e9c488e8a72649359ba51450db7d8 diff --git a/depends/packages/libevent.mk b/depends/packages/libevent.mk index 2a1125fda..ffe6f7e79 100644 --- a/depends/packages/libevent.mk +++ b/depends/packages/libevent.mk @@ -1,6 +1,6 @@ package=libevent $(package)_version=2.1.8 -$(package)_download_path=https://github.com/libevent/libevent/archive/ +$(package)_download_path=https://github.com/libevent/libevent/archive $(package)_file_name=$(package)-$($(package)_version).tar.gz $(package)_download_file=release-$($(package)_version)-stable.tar.gz $(package)_sha256_hash=316ddb401745ac5d222d7c529ef1eada12f58f6376a66c1118eee803cb70f83d diff --git a/depends/packages/libgmp.mk b/depends/packages/libgmp.mk index d8e41573a..c62fa18ed 100644 --- a/depends/packages/libgmp.mk +++ b/depends/packages/libgmp.mk @@ -1,7 +1,7 @@ package=libgmp ifeq ($(host_os),mingw32) -$(package)_download_path=https://github.com/joshuayabut/$(package)/archive/ +$(package)_download_path=https://github.com/joshuayabut/$(package)/archive $(package)_file_name=$(package)-$($(package)_git_commit).tar.gz $(package)_download_file=$($(package)_git_commit).tar.gz $(package)_sha256_hash=193836c1acc9dc00fe2521205d7bbe1ba13263f6cbef6f02584bf6f8b34b108f @@ -9,7 +9,7 @@ $(package)_git_commit=053c03b1cab347671d936f43ef66b48ab5e380ee $(package)_dependencies= $(package)_config_opts=--enable-cxx --disable-shared else ifeq ($(build_os),darwin) -$(package)_download_path=https://github.com/ca333/$(package)/archive/ +$(package)_download_path=https://github.com/ca333/$(package)/archive $(package)_file_name=$(package)-$($(package)_git_commit).tar.gz $(package)_download_file=$($(package)_git_commit).tar.gz $(package)_sha256_hash=59b2c2b5d58fdf5943bfde1fa709e9eb53e7e072c9699d28dc1c2cbb3c8cc32c diff --git a/depends/packages/librustzcash.mk b/depends/packages/librustzcash.mk index 20126776a..689082f8f 100644 --- a/depends/packages/librustzcash.mk +++ b/depends/packages/librustzcash.mk @@ -1,6 +1,6 @@ package=librustzcash $(package)_version=0.1 -$(package)_download_path=https://github.com/zcash/$(package)/archive/ +$(package)_download_path=https://github.com/zcash/$(package)/archive $(package)_file_name=$(package)-$($(package)_git_commit).tar.gz $(package)_download_file=$($(package)_git_commit).tar.gz $(package)_sha256_hash=a5760a90d4a1045c8944204f29fa2a3cf2f800afee400f88bf89bbfe2cce1279 diff --git a/depends/packages/libsodium.mk b/depends/packages/libsodium.mk index efa5d90de..67e096fae 100644 --- a/depends/packages/libsodium.mk +++ b/depends/packages/libsodium.mk @@ -9,7 +9,7 @@ $(package)_config_opts= else package=libsodium $(package)_version=1.0.15 -$(package)_download_path=https://download.libsodium.org/libsodium/releases/ +$(package)_download_path=https://download.libsodium.org/libsodium/releases $(package)_file_name=$(package)-$($(package)_version).tar.gz $(package)_sha256_hash=fb6a9e879a2f674592e4328c5d9f79f082405ee4bb05cb6e679b90afe9e178f4 $(package)_dependencies= diff --git a/depends/packages/zeromq.mk b/depends/packages/zeromq.mk index 850cce778..66e491ffb 100644 --- a/depends/packages/zeromq.mk +++ b/depends/packages/zeromq.mk @@ -1,6 +1,6 @@ ifeq ($(host_os),mingw32) $(package)_version=4.2.2-1 -$(package)_download_path=https://github.com/ca333/libzmq/archive/ +$(package)_download_path=https://github.com/ca333/libzmq/archive $(package)_download_file=v$($(package)_version).tar.gz $(package)_file_name=libzmq-$($(package)_version).tar.gz $(package)_sha256_hash=0e225b85ce11be23bf7eb7d3f25c6686728bf30d5c31f61c12d37bb646c69962 diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index 50de39f64..fb4ff99a7 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -11,6 +11,7 @@ export BITCOIND=${REAL_BITCOIND} #Run the tests testScripts=( + 'cryptoconditions.py' 'paymentdisclosure.py' 'prioritisetransaction.py' 'wallet_treestate.py' diff --git a/qa/pull-tester/tests-config.sh.in b/qa/pull-tester/tests-config.sh.in index cc76e8ad8..8d9467f3f 100755 --- a/qa/pull-tester/tests-config.sh.in +++ b/qa/pull-tester/tests-config.sh.in @@ -13,6 +13,6 @@ EXEEXT="@EXEEXT@" @ENABLE_ZMQ_TRUE@ENABLE_ZMQ=1 @ENABLE_PROTON_TRUE@ENABLE_PROTON=1 -REAL_BITCOIND="$BUILDDIR/src/zcashd${EXEEXT}" -REAL_BITCOINCLI="$BUILDDIR/src/zcash-cli${EXEEXT}" +REAL_BITCOIND="$BUILDDIR/src/komodod${EXEEXT}" +REAL_BITCOINCLI="$BUILDDIR/src/komodo-cli${EXEEXT}" diff --git a/qa/rpc-tests/README.md b/qa/rpc-tests/README.md index a0229b56d..17aee1967 100644 --- a/qa/rpc-tests/README.md +++ b/qa/rpc-tests/README.md @@ -18,9 +18,9 @@ Possible options: ``` -h, --help show this help message and exit - --nocleanup Leave bitcoinds and test.* datadir on exit or error - --noshutdown Don't stop bitcoinds after the test execution - --srcdir=SRCDIR Source directory containing bitcoind/bitcoin-cli (default: + --nocleanup Leave komodods and test.* datadir on exit or error + --noshutdown Don't stop komodods after the test execution + --srcdir=SRCDIR Source directory containing komodod/komodo-cli (default: ../../src) --tmpdir=TMPDIR Root directory for datadirs --tracerpc Print out all RPC calls as they are made @@ -31,7 +31,7 @@ If you set the environment variable `PYTHON_DEBUG=1` you will get some debug out A 200-block -regtest blockchain and wallets for four nodes is created the first time a regression test is run and is stored in the cache/ directory. Each node has the miner -subsidy from 25 mature blocks (25*10=250 ZEC) in its wallet. +subsidy from 25 mature blocks (25*10=250 KMD) in its wallet. After the first run, the cache/ blockchain and wallets are copied into a temporary directory and used as the initial @@ -42,5 +42,5 @@ to recover with: ```bash rm -rf cache -killall zcashd +killall komodod ``` diff --git a/qa/rpc-tests/cryptoconditions.py b/qa/rpc-tests/cryptoconditions.py new file mode 100755 index 000000000..68b381272 --- /dev/null +++ b/qa/rpc-tests/cryptoconditions.py @@ -0,0 +1,337 @@ +#!/usr/bin/env python2 +# Copyright (c) 2018 SuperNET developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.authproxy import JSONRPCException +from test_framework.util import assert_equal, assert_greater_than, \ + initialize_chain_clean, start_nodes, start_node, connect_nodes_bi, \ + stop_nodes, sync_blocks, sync_mempools, wait_bitcoinds, rpc_port + +import time +from decimal import Decimal + +def assert_success(result): + assert_equal(result['result'], 'success') + +def assert_error(result): + assert_equal(result['result'], 'error') + +class CryptoConditionsTest (BitcoinTestFramework): + + def setup_chain(self): + print("Initializing CC test directory "+self.options.tmpdir) + self.num_nodes = 1 + initialize_chain_clean(self.options.tmpdir, self.num_nodes) + + def setup_network(self, split = False): + print("Setting up network...") + self.addr = "RWPg8B91kfK5UtUN7z6s6TeV9cHSGtVY8D" + self.pubkey = "02676d00110c2cd14ae24f95969e8598f7ccfaa675498b82654a5b5bd57fc1d8cf" + self.privkey = "UqMgxk7ySPNQ4r9nKAFPjkXy6r5t898yhuNCjSZJLg3RAM4WW1m9" + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, + extra_args=[[ + # always give -ac_name as first extra_arg + '-ac_name=REGTEST', + '-conf='+self.options.tmpdir+'/node0/REGTEST.conf', + '-port=64367', + '-rpcport=64368', + '-regtest', + '-addressindex=1', + '-spentindex=1', + '-ac_supply=5555555', + '-ac_reward=10000000', + '-pubkey=' + self.pubkey, + '-ac_cc=1', + '-whitelist=127.0.0.1', + '-debug', + '-daemon', + '-rpcuser=rt', + '-rpcpassword=rt' + ]] + ) + self.is_network_split = split + self.rpc = self.nodes[0] + self.sync_all() + print("Done setting up network") + + def send_and_mine(self, xtn): + txid = self.rpc.sendrawtransaction(xtn) + assert txid, 'got txid' + # we need the tx above to be confirmed in the next block + self.rpc.generate(1) + return txid + + def run_faucet_tests(self): + rpc = self.rpc + + # basic sanity tests + result = rpc.getwalletinfo() + assert_equal(result['txcount'], 101) + assert_greater_than(result['balance'], 0.0) + balance = result['balance'] + + faucet = rpc.faucetaddress() + assert_equal(faucet['result'], 'success') + # verify all keys look like valid AC addrs, could be better + for x in ['myCCaddress', 'FaucetCCaddress', 'Faucetmarker', 'myaddress']: + assert_equal(faucet[x][0], 'R') + + # no funds in the faucet yet + result = rpc.faucetget() + assert_equal(result['result'], 'error') + + result = rpc.faucetinfo() + assert_equal(result['result'], 'success') + + result = rpc.faucetfund("0") + assert_equal(result['result'], 'error') + + result = rpc.faucetfund("-1") + assert_equal(result['result'], 'error') + + # we need at least 1 + txfee to get + result = rpc.faucetfund("2") + assert_equal(result['result'], 'success') + assert result['hex'], "hex key found" + + # broadcast the xtn + result = rpc.sendrawtransaction(result['hex']) + txid = result[0] + assert txid, "found txid" + + # we need the tx above to be confirmed in the next block + rpc.generate(1) + + result = rpc.getwalletinfo() + balance2 = result['balance'] + # make sure our balance is less now + assert_greater_than(balance, balance2) + + result = rpc.faucetinfo() + assert_equal(result['result'], 'success') + assert_greater_than( result['funding'], 0 ) + + result = rpc.faucetget() + assert_equal(result['result'], 'success') + assert result['hex'], "hex key found" + + # broadcast the xtn + result = rpc.sendrawtransaction(result['hex']) + txid = result[0] + assert txid, "found txid" + + # confirm above tx + rpc.generate(1) + result = rpc.getwalletinfo() + + # we should have slightly more funds from the faucet now + assert_greater_than(result['balance'], balance2) + + def run_dice_tests(self): + rpc = self.nodes[0] + + dice = rpc.diceaddress() + assert_equal(dice['result'], 'success') + for x in ['myCCaddress', 'DiceCCaddress', 'Dicemarker', 'myaddress']: + assert_equal(dice[x][0], 'R') + + # no dice created yet + result = rpc.dicelist() + assert_equal(result, []) + + #result = rpc.dicefund("LUCKY",10000,1,10000,10,5) + #assert_equal(result, []) + + def run_token_tests(self): + rpc = self.nodes[0] + result = rpc.tokenaddress() + assert_equal(result['result'], 'success') + for x in ['AssetsCCaddress', 'myCCaddress', 'Assetsmarker', 'myaddress']: + assert_equal(result[x][0], 'R') + + result = rpc.tokenaddress(self.pubkey) + assert_equal(result['result'], 'success') + for x in ['AssetsCCaddress', 'myCCaddress', 'Assetsmarker', 'myaddress', 'CCaddress']: + assert_equal(result[x][0], 'R') + # there are no tokens created yet + result = rpc.tokenlist() + assert_equal(result, []) + + result = rpc.tokencreate("DUKE", "1987.420", "duke") + assert_equal(result['result'], 'success') + self.send_and_mine(result['hex']) + + result = rpc.tokenlist() + tokenid = result[0] + assert(tokenid, "got tokenid") + + # there are no token orders yet + result = rpc.tokenorders() + assert_equal(result, []) + + result = rpc.tokenbalance(self.pubkey) + assert_equal(result['balance'], 0) + assert_equal(result['result'], 'success') + assert_equal(result['CCaddress'], 'RCRsm3VBXz8kKTsYaXKpy7pSEzrtNNQGJC') + assert_equal(result['tokenid'], self.pubkey) + + # this is not a valid assetid + result = rpc.tokeninfo(self.pubkey) + assert_error(result) + + # invalid numtokens + result = rpc.tokenask("-1", tokenid, "1") + assert_error(result) + + # invalid numtokens + result = rpc.tokenask("0", tokenid, "1") + assert_error(result) + + # invalid price + result = rpc.tokenask("1", tokenid, "-1") + assert_error(result) + + # invalid price + result = rpc.tokenask("1", tokenid, "0") + assert_error(result) + + # invalid tokenid + result = rpc.tokenask("100", "deadbeef", "1") + assert_error(result) + + # valid + result = rpc.tokenask("100", tokenid, "7.77") + assert_success(result) + tokenaskhex = result['hex'] + assert tokenaskhex, "got tokenask hexk" + tokenaskid = self.send_and_mine(result['hex']) + + + # invalid fillunits + result = rpc.tokenfillask(tokenid, tokenaskid, "0") + assert_error(result) + + # invalid fillunits + result = rpc.tokenfillask(tokenid, tokenaskid, "-777") + assert_error(result) + + # should this pass or fail? + result = rpc.tokenfillask(tokenid, tokenaskid, "10") + #assert_success(result) + + def run_rewards_tests(self): + rpc = self.nodes[0] + result = rpc.rewardsaddress() + for x in ['RewardsCCaddress', 'myCCaddress', 'Rewardsmarker', 'myaddress']: + assert_equal(result[x][0], 'R') + + result = rpc.rewardsaddress(self.pubkey) + for x in ['RewardsCCaddress', 'myCCaddress', 'Rewardsmarker', 'myaddress', 'CCaddress']: + assert_equal(result[x][0], 'R') + + # no rewards yet + result = rpc.rewardslist() + assert_equal(result, []) + + # looking up non-existent reward should return error + result = rpc.rewardsinfo("none") + assert_equal(result['result'], 'error') + + result = rpc.rewardscreatefunding("STUFF", "7777", "25", "0", "10", "10") + assert result['hex'], 'got raw xtn' + txid = rpc.sendrawtransaction(result['hex']) + assert txid, 'got txid' + + # confirm the above xtn + rpc.generate(1) + result = rpc.rewardsinfo(txid) + assert_equal(result['result'], 'success') + assert_equal(result['name'], 'STUFF') + assert_equal(result['APR'], "25.00000000") + assert_equal(result['minseconds'], 0) + assert_equal(result['maxseconds'], 864000) + assert_equal(result['funding'], "7777.00000000") + assert_equal(result['mindeposit'], "10.00000000") + assert_equal(result['fundingtxid'], txid) + + # funding amount must be positive + result = rpc.rewardsaddfunding("STUFF", txid, "0") + assert_equal(result['result'], 'error') + + result = rpc.rewardsaddfunding("STUFF", txid, "555") + assert_equal(result['result'], 'success') + fundingtxid = result['hex'] + assert fundingtxid, "got funding txid" + + result = rpc.rewardslock("STUFF", fundingtxid, "7") + assert_equal(result['result'], 'error') + + # the previous xtn has not been broadcasted yet + result = rpc.rewardsunlock("STUFF", fundingtxid) + assert_equal(result['result'], 'error') + + # wrong plan name + result = rpc.rewardsunlock("SHTUFF", fundingtxid) + assert_equal(result['result'], 'error') + + txid = rpc.sendrawtransaction(fundingtxid) + assert txid, 'got txid from sendrawtransaction' + + # confirm the xtn above + rpc.generate(1) + + # amount must be positive + result = rpc.rewardslock("STUFF", fundingtxid, "-5") + assert_equal(result['result'], 'error') + + # amount must be positive + result = rpc.rewardslock("STUFF", fundingtxid, "0") + assert_equal(result['result'], 'error') + + # trying to lock less than the min amount is an error + result = rpc.rewardslock("STUFF", fundingtxid, "7") + assert_equal(result['result'], 'error') + + # not working + #result = rpc.rewardslock("STUFF", fundingtxid, "10") + #assert_equal(result['result'], 'success') + #locktxid = result['hex'] + #assert locktxid, "got lock txid" + + # locktxid has not been broadcast yet + #result = rpc.rewardsunlock("STUFF", locktxid) + #assert_equal(result['result'], 'error') + + # broadcast xtn + #txid = rpc.sendrawtransaction(locktxid) + #assert txid, 'got txid from sendrawtransaction' + + # confirm the xtn above + #rpc.generate(1) + + #result = rpc.rewardsunlock("STUFF", locktxid) + #assert_equal(result['result'], 'error') + + + def run_test (self): + print("Mining blocks...") + rpc = self.nodes[0] + + # utxos from block 1 become mature in block 101 + rpc.generate(101) + self.sync_all() + + # this corresponds to -pubkey above + print("Importing privkey") + rpc.importprivkey(self.privkey) + + self.run_faucet_tests() + self.run_rewards_tests() + self.run_dice_tests() + self.run_token_tests() + + +if __name__ == '__main__': + CryptoConditionsTest ().main () diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py index 56151bb3e..f545b4246 100755 --- a/qa/rpc-tests/test_framework/test_framework.py +++ b/qa/rpc-tests/test_framework/test_framework.py @@ -90,11 +90,11 @@ class BitcoinTestFramework(object): parser = optparse.OptionParser(usage="%prog [options]") parser.add_option("--nocleanup", dest="nocleanup", default=False, action="store_true", - help="Leave bitcoinds and test.* datadir on exit or error") + help="Leave komodods and test.* datadir on exit or error") parser.add_option("--noshutdown", dest="noshutdown", default=False, action="store_true", - help="Don't stop bitcoinds after the test execution") + help="Don't stop komodods after the test execution") parser.add_option("--srcdir", dest="srcdir", default="../../src", - help="Source directory containing bitcoind/bitcoin-cli (default: %default)") + help="Source directory containing komodod/komodo-cli (default: %default)") parser.add_option("--tmpdir", dest="tmpdir", default=tempfile.mkdtemp(prefix="test"), help="Root directory for datadirs") parser.add_option("--tracerpc", dest="trace_rpc", default=False, action="store_true", @@ -137,7 +137,7 @@ class BitcoinTestFramework(object): stop_nodes(self.nodes) wait_bitcoinds() else: - print("Note: bitcoinds were not stopped and may still be running") + print("Note: komodods were not stopped and may still be running") if not self.options.nocleanup and not self.options.noshutdown: print("Cleaning up") @@ -151,7 +151,7 @@ class BitcoinTestFramework(object): sys.exit(1) -# Test framework for doing p2p comparison testing, which sets up some bitcoind +# Test framework for doing p2p comparison testing, which sets up some komodod # binaries: # 1 binary: test binary # 2 binaries: 1 test binary, 1 ref binary @@ -165,10 +165,10 @@ class ComparisonTestFramework(BitcoinTestFramework): def add_options(self, parser): parser.add_option("--testbinary", dest="testbinary", - default=os.getenv("BITCOIND", "bitcoind"), + default=os.getenv("BITCOIND", "komodod"), help="bitcoind binary to test") parser.add_option("--refbinary", dest="refbinary", - default=os.getenv("BITCOIND", "bitcoind"), + default=os.getenv("BITCOIND", "komodod"), help="bitcoind binary to use for reference nodes (if any)") def setup_chain(self): diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index f3ea481ee..5cb0d1b10 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 The Bitcoin Core developers +# Copyright (c) 2018 The SuperNET developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -75,38 +76,55 @@ def initialize_datadir(dirname, n): datadir = os.path.join(dirname, "node"+str(n)) if not os.path.isdir(datadir): os.makedirs(datadir) - with open(os.path.join(datadir, "zcash.conf"), 'w') as f: + # kmd AC's don't use this, they use the conf auto-created when the AC is created + # plus CLI arguments. This is for komodod tests + print("Writing to " + os.path.join(datadir,"komodo.conf")) + with open(os.path.join(datadir, "komodo.conf"), 'w') as f: f.write("regtest=1\n"); + f.write("txindex=1\n"); + f.write("server=1\n"); f.write("showmetrics=0\n"); f.write("rpcuser=rt\n"); f.write("rpcpassword=rt\n"); - f.write("port="+str(p2p_port(n))+"\n"); - f.write("rpcport="+str(rpc_port(n))+"\n"); + #f.write("port="+str(p2p_port(n))+"\n"); + #rpcport = str(rpc_port(n)) + #f.write("rpcport="+rpcport+"\n"); + #print "RPC port=" + rpcport f.write("listenonion=0\n"); + # TODO: maybe make these optional, defaulted to on for now + f.write("addressindex=1\n"); + f.write("spentindex=1\n"); + f.write("timestampindex=1\n"); return datadir def initialize_chain(test_dir): """ Create (or copy from cache) a 200-block-long chain and 4 wallets. - bitcoind and bitcoin-cli must be in search path. + komodod and komodo-cli must be in search path. """ + print("initialize_chain") if not os.path.isdir(os.path.join("cache", "node0")): devnull = open("/dev/null", "w+") - # Create cache directories, run bitcoinds: + # Create cache directories, run komodods: for i in range(4): datadir=initialize_datadir("cache", i) - args = [ os.getenv("BITCOIND", "bitcoind"), "-keypool=1", "-datadir="+datadir, "-discover=0" ] + args = [ os.getenv("BITCOIND", "komodod"), "-keypool=1", "-datadir="+datadir, "-discover=0" ] if i > 0: args.append("-connect=127.0.0.1:"+str(p2p_port(0))) bitcoind_processes[i] = subprocess.Popen(args) + cmd = os.getenv("BITCOINCLI", "komodo-cli") + cmd_args = cmd + " -datadir="+datadir + " -rpcwait getblockcount" if os.getenv("PYTHON_DEBUG", ""): - print "initialize_chain: bitcoind started, calling bitcoin-cli -rpcwait getblockcount" - subprocess.check_call([ os.getenv("BITCOINCLI", "bitcoin-cli"), "-datadir="+datadir, - "-rpcwait", "getblockcount"], stdout=devnull) + print "initialize_chain: komodod started, calling: " + cmd_args + strcmd = cmd + " " + "-datadir="+datadir + " -rpcwait getblockcount" + + print("Running " + strcmd) + subprocess.check_call(strcmd, shell=True); + #subprocess.check_call([ cmd, "-rpcwait", "getblockcount"], stdout=devnull) if os.getenv("PYTHON_DEBUG", ""): - print "initialize_chain: bitcoin-cli -rpcwait getblockcount completed" + print "initialize_chain: komodo-cli -rpcwait getblockcount completed" devnull.close() rpcs = [] for i in range(4): @@ -144,7 +162,7 @@ def initialize_chain(test_dir): from_dir = os.path.join("cache", "node"+str(i)) to_dir = os.path.join(test_dir, "node"+str(i)) shutil.copytree(from_dir, to_dir) - initialize_datadir(test_dir, i) # Overwrite port/rpcport in zcash.conf + initialize_datadir(test_dir, i) # Overwrite port/rpcport in komodo.conf def initialize_chain_clean(test_dir, num_nodes): """ @@ -177,34 +195,50 @@ def _rpchost_to_args(rpchost): def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None): """ - Start a bitcoind and return RPC connection to it + Start a komodod and return RPC connection to it """ datadir = os.path.join(dirname, "node"+str(i)) if binary is None: - binary = os.getenv("BITCOIND", "bitcoind") + binary = os.getenv("BITCOIND", "komodod") args = [ binary, "-datadir="+datadir, "-keypool=1", "-discover=0", "-rest" ] if extra_args is not None: args.extend(extra_args) + #print("args=" + ' '.join(args)) bitcoind_processes[i] = subprocess.Popen(args) devnull = open("/dev/null", "w+") + + cmd = os.getenv("BITCOINCLI", "komodo-cli") + print("cmd=" + cmd) + cmd_args = ' '.join(extra_args) + " -rpcwait getblockcount " if os.getenv("PYTHON_DEBUG", ""): - print "start_node: bitcoind started, calling bitcoin-cli -rpcwait getblockcount" - subprocess.check_call([ os.getenv("BITCOINCLI", "bitcoin-cli"), "-datadir="+datadir] + - _rpchost_to_args(rpchost) + - ["-rpcwait", "getblockcount"], stdout=devnull) + print "start_node: komodod started, calling : " + cmd + " " + cmd_args + strcmd = cmd + " " + cmd_args + + print("Running " + strcmd) + import time + time.sleep(2) + subprocess.check_call(strcmd, shell=True); + #subprocess.check_call([ os.getenv("BITCOINCLI", "komodo-cli"), "-datadir="+datadir] + + # _rpchost_to_args(rpchost) + + # ["-rpcwait", "-rpcport=6438", "getblockcount"], stdout=devnull) if os.getenv("PYTHON_DEBUG", ""): - print "start_node: calling bitcoin-cli -rpcwait getblockcount returned" + print "start_node: calling komodo-cli -rpcwait getblockcount returned" devnull.close() - url = "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', rpc_port(i)) + if extra_args[0] == '-ac_name=REGTEST': + url = "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', 64368) + else: + url = "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', rpc_port(i)) + print("connecting to " + url) if timewait is not None: proxy = AuthServiceProxy(url, timeout=timewait) else: proxy = AuthServiceProxy(url) + print("created proxy") proxy.url = url # store URL on proxy for info return proxy def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, binary=None): """ - Start multiple bitcoinds, return RPC connections to them + Start multiple komodods, return RPC connections to them """ if extra_args is None: extra_args = [ None for i in range(num_nodes) ] if binary is None: binary = [ None for i in range(num_nodes) ] diff --git a/src/cc/CCassetsCore.cpp b/src/cc/CCassetsCore.cpp index da505db9c..9ef08348e 100644 --- a/src/cc/CCassetsCore.cpp +++ b/src/cc/CCassetsCore.cpp @@ -58,16 +58,20 @@ bool ValidateBidRemainder(int64_t remaining_units,int64_t remaining_nValue,int64 } else { - unitprice = (orig_nValue * COIN) / totalunits; - recvunitprice = (received_nValue * COIN) / paidunits; + //unitprice = (orig_nValue * COIN) / totalunits; + //recvunitprice = (received_nValue * COIN) / paidunits; + //if ( remaining_units != 0 ) + // newunitprice = (remaining_nValue * COIN) / remaining_units; + unitprice = (orig_nValue / totalunits); + recvunitprice = (received_nValue / paidunits); if ( remaining_units != 0 ) - newunitprice = (remaining_nValue * COIN) / remaining_units; + newunitprice = (remaining_nValue / remaining_units); if ( recvunitprice < unitprice ) { - fprintf(stderr,"error recvunitprice %.16f < %.16f unitprice, new unitprice %.16f\n",(double)recvunitprice/(COIN*COIN),(double)unitprice/(COIN*COIN),(double)newunitprice/(COIN*COIN)); + fprintf(stderr,"error recvunitprice %.16f < %.16f unitprice, new unitprice %.16f\n",(double)recvunitprice/(COIN),(double)unitprice/(COIN),(double)newunitprice/(COIN)); return(false); } - fprintf(stderr,"orig %llu total %llu, recv %llu paid %llu,recvunitprice %.16f >= %.16f unitprice, new unitprice %.16f\n",(long long)orig_nValue,(long long)totalunits,(long long)received_nValue,(long long)paidunits,(double)recvunitprice/(COIN*COIN),(double)unitprice/(COIN*COIN),(double)newunitprice/(COIN*COIN)); + fprintf(stderr,"orig %llu total %llu, recv %llu paid %llu,recvunitprice %.16f >= %.16f unitprice, new unitprice %.16f\n",(long long)orig_nValue,(long long)totalunits,(long long)received_nValue,(long long)paidunits,(double)recvunitprice/(COIN),(double)unitprice/(COIN),(double)newunitprice/(COIN)); } return(true); } @@ -89,8 +93,10 @@ bool SetBidFillamounts(int64_t &received_nValue,int64_t &remaining_units,int64_t return(true); } remaining_units = (totalunits - paidunits); - unitprice = (orig_nValue * COIN) / totalunits; - received_nValue = (paidunits * unitprice) / COIN; + //unitprice = (orig_nValue * COIN) / totalunits; + //received_nValue = (paidunits * unitprice) / COIN; + unitprice = (orig_nValue / totalunits); + received_nValue = (paidunits * unitprice); if ( unitprice > 0 && received_nValue > 0 && received_nValue <= orig_nValue ) { remaining_nValue = (orig_nValue - received_nValue); diff --git a/src/cc/CCassetstx.cpp b/src/cc/CCassetstx.cpp index 7d55b85ff..74ef9fb58 100644 --- a/src/cc/CCassetstx.cpp +++ b/src/cc/CCassetstx.cpp @@ -14,6 +14,7 @@ ******************************************************************************/ #include "CCassets.h" +extern std::string CCerror; int64_t AddAssetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 assetid,int64_t total,int32_t maxinputs) { @@ -60,20 +61,21 @@ UniValue AssetInfo(uint256 assetid) if ( GetTransaction(assetid,vintx,hashBlock,false) == 0 ) { fprintf(stderr,"cant find assetid\n"); + result.push_back(Pair("result","error")); result.push_back(Pair("error","cant find assetid")); - return(0); + return(result); } if ( vintx.vout.size() > 0 && DecodeAssetCreateOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,origpubkey,name,description) == 0 ) { fprintf(stderr,"assetid isnt assetcreation txid\n"); + result.push_back(Pair("result","error")); result.push_back(Pair("error","assetid isnt assetcreation txid")); } result.push_back(Pair("result","success")); result.push_back(Pair("tokenid",uint256_str(str,assetid))); result.push_back(Pair("owner",pubkey33_str(str,origpubkey.data()))); result.push_back(Pair("name",name)); - sprintf(numstr,"%.8f",(double)vintx.vout[0].nValue/COIN); - result.push_back(Pair("supply",numstr)); + result.push_back(Pair("supply",vintx.vout[0].nValue)); result.push_back(Pair("description",description)); return(result); } @@ -182,13 +184,13 @@ std::string CreateAsset(int64_t txfee,int64_t assetsupply,std::string name,std:: if ( assetsupply < 0 ) { fprintf(stderr,"negative assetsupply %lld\n",(long long)assetsupply); - return(0); + return(""); } cp = CCinit(&C,EVAL_ASSETS); if ( name.size() > 32 || description.size() > 4096 ) { fprintf(stderr,"name.%d or description.%d is too big\n",(int32_t)name.size(),(int32_t)description.size()); - return(0); + return(""); } if ( txfee == 0 ) txfee = 10000; @@ -199,7 +201,7 @@ std::string CreateAsset(int64_t txfee,int64_t assetsupply,std::string name,std:: mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(cp->CChexstr) << OP_CHECKSIG)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeAssetCreateOpRet('c',Mypubkey(),name,description))); } - return(0); + return(""); } std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector destpubkey,int64_t total) @@ -208,7 +210,7 @@ std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector des if ( total < 0 ) { fprintf(stderr,"negative total %lld\n",(long long)total); - return(0); + return(""); } cp = CCinit(&C,EVAL_ASSETS); if ( txfee == 0 ) @@ -234,7 +236,7 @@ std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector des } else fprintf(stderr,"not enough CC asset inputs for %.8f\n",(double)total/COIN); //} else fprintf(stderr,"numoutputs.%d != numamounts.%d\n",n,(int32_t)amounts.size()); } - return(0); + return(""); } std::string CreateBuyOffer(int64_t txfee,int64_t bidamount,uint256 assetid,int64_t pricetotal) @@ -243,17 +245,17 @@ std::string CreateBuyOffer(int64_t txfee,int64_t bidamount,uint256 assetid,int64 if ( bidamount < 0 || pricetotal < 0 ) { fprintf(stderr,"negative bidamount %lld, pricetotal %lld\n",(long long)bidamount,(long long)pricetotal); - return(0); + return(""); } if ( GetTransaction(assetid,vintx,hashBlock,false) == 0 ) { fprintf(stderr,"cant find assetid\n"); - return(0); + return(""); } if ( vintx.vout.size() > 0 && DecodeAssetCreateOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,origpubkey,name,description) == 0 ) { fprintf(stderr,"assetid isnt assetcreation txid\n"); - return(0); + return(""); } cp = CCinit(&C,EVAL_ASSETS); if ( txfee == 0 ) @@ -264,7 +266,7 @@ std::string CreateBuyOffer(int64_t txfee,int64_t bidamount,uint256 assetid,int64 mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,bidamount,GetUnspendable(cp,0))); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeAssetOpRet('b',assetid,zeroid,pricetotal,Mypubkey()))); } - return(0); + return(""); } std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t pricetotal) @@ -273,7 +275,7 @@ std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t p if ( askamount < 0 || pricetotal < 0 ) { fprintf(stderr,"negative askamount %lld, askamount %lld\n",(long long)pricetotal,(long long)askamount); - return(0); + return(""); } cp = CCinit(&C,EVAL_ASSETS); if ( txfee == 0 ) @@ -296,18 +298,18 @@ std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t p } else fprintf(stderr,"need some assets to place ask\n"); } fprintf(stderr,"need some native coins to place ask\n"); - return(0); + return(""); } std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 assetid2,int64_t pricetotal) { CMutableTransaction mtx; CPubKey mypk; uint64_t mask; int64_t inputs,CCchange; CScript opret; struct CCcontract_info *cp,C; fprintf(stderr,"asset swaps disabled\n"); - return(0); + return(""); if ( askamount < 0 || pricetotal < 0 ) { fprintf(stderr,"negative askamount %lld, askamount %lld\n",(long long)pricetotal,(long long)askamount); - return(0); + return(""); } cp = CCinit(&C,EVAL_ASSETS); if ( txfee == 0 ) @@ -335,7 +337,7 @@ std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 a } else fprintf(stderr,"need some assets to place ask\n"); } fprintf(stderr,"need some native coins to place ask\n"); - return(0); + return(""); } std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid) @@ -356,7 +358,7 @@ std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid) return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,EncodeAssetOpRet('o',assetid,zeroid,0,Mypubkey()))); } } - return(0); + return(""); } std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid) @@ -377,7 +379,7 @@ std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid) return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,EncodeAssetOpRet('x',assetid,zeroid,0,Mypubkey()))); } } - return(0); + return(""); } std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t fillamount) @@ -386,7 +388,7 @@ std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t f if ( fillamount < 0 ) { fprintf(stderr,"negative fillamount %lld\n",(long long)fillamount); - return(0); + return(""); } cp = CCinit(&C,EVAL_ASSETS); if ( txfee == 0 ) @@ -425,13 +427,15 @@ std::string FillSell(int64_t txfee,uint256 assetid,uint256 assetid2,uint256 askt CTransaction vintx,filltx; uint256 hashBlock; CMutableTransaction mtx; CPubKey mypk; std::vector origpubkey; double dprice; uint64_t mask; int32_t askvout=0; int64_t received_assetoshis,total_nValue,orig_assetoshis,paid_nValue,remaining_nValue,inputs,CCchange=0; struct CCcontract_info *cp,C; if ( fillunits < 0 ) { - fprintf(stderr,"negative fillunits %lld\n",(long long)fillunits); - return(0); + CCerror = strprintf("negative fillunits %lld\n",(long long)fillunits); + fprintf(stderr,"%s\n",CCerror.c_str()); + return(""); } if ( assetid2 != zeroid ) { - fprintf(stderr,"asset swaps disabled\n"); - return(0); + CCerror = "asset swaps disabled"; + fprintf(stderr,"%s\n",CCerror.c_str()); + return(""); } cp = CCinit(&C,EVAL_ASSETS); @@ -472,8 +476,11 @@ std::string FillSell(int64_t txfee,uint256 assetid,uint256 assetid2,uint256 askt if ( CCchange != 0 ) mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk)); return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,EncodeAssetOpRet(assetid2!=zeroid?'E':'S',assetid,assetid2,remaining_nValue,origpubkey))); - } else fprintf(stderr,"filltx not enough utxos\n"); + } else { + CCerror = strprintf("filltx not enough utxos"); + fprintf(stderr,"%s\n", CCerror.c_str()); + } } } - return(0); + return(""); } diff --git a/src/cc/CCauction.h b/src/cc/CCauction.h index 52cd03d14..855cdf72e 100644 --- a/src/cc/CCauction.h +++ b/src/cc/CCauction.h @@ -23,8 +23,8 @@ bool AuctionValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx); -std::string AuctionPost(uint64_t txfee,uint256 itemhash,uint64_t minbid,char *title,char *description); -std::string AuctionBid(uint64_t txfee,uint256 itemhash,uint64_t amount); +std::string AuctionPost(uint64_t txfee,uint256 itemhash,int64_t minbid,char *title,char *description); +std::string AuctionBid(uint64_t txfee,uint256 itemhash,int64_t amount); std::string AuctionDeliver(uint64_t txfee,uint256 itemhash,uint256 bidtxid); #endif diff --git a/src/cc/CCfaucet.h b/src/cc/CCfaucet.h index b875bd133..39930cb20 100644 --- a/src/cc/CCfaucet.h +++ b/src/cc/CCfaucet.h @@ -20,11 +20,12 @@ #include "CCinclude.h" #define EVAL_FAUCET 0xe4 +#define FAUCETSIZE (COIN / 10) bool FaucetValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx); // CCcustom -std::string FaucetFund(uint64_t txfee,uint64_t funds); +std::string FaucetFund(uint64_t txfee,int64_t funds); std::string FaucetGet(uint64_t txfee); UniValue FaucetInfo(); diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index a59a2325c..761e64bcd 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -28,6 +28,7 @@ #include #include +extern int32_t KOMODO_CONNECTING; #define SMALLVAL 0.000000000000001 union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; @@ -64,6 +65,7 @@ bool myAddtomempool(CTransaction &tx); bool myIsutxo_spentinmempool(uint256 txid,int32_t vout); int32_t myIsutxo_spent(uint256 &spenttxid,uint256 txid,int32_t vout); bool mySendrawtransaction(std::string res); +int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); // CCcustom CPubKey GetUnspendable(struct CCcontract_info *cp,uint8_t *unspendablepriv); @@ -81,7 +83,7 @@ char *pubkey33_str(char *dest,uint8_t *pubkey33); uint256 Parseuint256(char *hexstr); CPubKey pubkey2pk(std::vector pubkey); bool GetCCaddress(struct CCcontract_info *cp,char *destaddr,CPubKey pk); -bool ConstrainVout(CTxOut vout,int32_t CCflag,char *cmpaddr,uint64_t nValue); +bool ConstrainVout(CTxOut vout,int32_t CCflag,char *cmpaddr,int64_t nValue); bool PreventCC(Eval* eval,const CTransaction &tx,int32_t preventCCvins,int32_t numvins,int32_t preventCCvouts,int32_t numvouts); bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); std::vector Mypubkey(); @@ -92,13 +94,14 @@ int64_t CCduration(int32_t &numblocks,uint256 txid); std::string FinalizeCCTx(uint64_t skipmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret); void SetCCunspents(std::vector > &unspentOutputs,char *coinaddr); void SetCCtxids(std::vector > &addressIndex,char *coinaddr); -uint64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,uint64_t total,int32_t maxinputs); -uint64_t CCutxovalue(char *coinaddr,uint256 utxotxid,int32_t utxovout); +int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs); +int64_t CCutxovalue(char *coinaddr,uint256 utxotxid,int32_t utxovout); // curve25519 and sha256 bits256 curve25519_shared(bits256 privkey,bits256 otherpub); bits256 curve25519_basepoint9(); bits256 curve25519(bits256 mysecret,bits256 basepoint); void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len); +bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen); #endif diff --git a/src/cc/CClotto.h b/src/cc/CClotto.h index a0354252e..41e3cb5b1 100644 --- a/src/cc/CClotto.h +++ b/src/cc/CClotto.h @@ -23,7 +23,7 @@ bool LottoValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx); -std::string LottoTicket(uint64_t txfee,uint64_t numtickets); +std::string LottoTicket(uint64_t txfee,int64_t numtickets); std::string LottoWinner(uint64_t txfee); #endif diff --git a/src/cc/CCrewards.h b/src/cc/CCrewards.h index e7db9d4a9..ef675797c 100644 --- a/src/cc/CCrewards.h +++ b/src/cc/CCrewards.h @@ -20,6 +20,7 @@ #include "CCinclude.h" #define EVAL_REWARDS 0xe5 +#define REWARDSCC_MAXAPR (COIN * 25) bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx); UniValue RewardsInfo(uint256 rewardid); diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index 666132590..2c3001c10 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -23,7 +23,7 @@ By using -addressindex=1, it allows tracking of all the CC addresses */ -bool SignTx(CMutableTransaction &mtx,int32_t vini,uint64_t utxovalue,const CScript scriptPubKey) +bool SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScript scriptPubKey) { #ifdef ENABLE_WALLET CTransaction txNewConst(mtx); SignatureData sigdata; const CKeyStore& keystore = *pwalletMain; @@ -41,7 +41,7 @@ bool SignTx(CMutableTransaction &mtx,int32_t vini,uint64_t utxovalue,const CScri std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret) { auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); - CTransaction vintx; std::string hex; uint256 hashBlock; uint64_t mask=0,nmask=0,vinimask=0,utxovalues[64],change,normalinputs=0,totaloutputs=0,normaloutputs=0,totalinputs=0; int32_t i,utxovout,n,err = 0; char myaddr[64],destaddr[64],unspendable[64]; uint8_t *privkey,myprivkey[32],unspendablepriv[32],*msg32 = 0; CC *mycond=0,*othercond=0,*cond; CPubKey unspendablepk; + CTransaction vintx; std::string hex; uint256 hashBlock; uint64_t mask=0,nmask=0,vinimask=0; int64_t utxovalues[64],change,normalinputs=0,totaloutputs=0,normaloutputs=0,totalinputs=0; int32_t i,utxovout,n,err = 0; char myaddr[64],destaddr[64],unspendable[64]; uint8_t *privkey,myprivkey[32],unspendablepriv[32],*msg32 = 0; CC *mycond=0,*othercond=0,*cond; CPubKey unspendablepk; n = mtx.vout.size(); for (i=0; i > &addressIndex } } -uint64_t CCutxovalue(char *coinaddr,uint256 utxotxid,int32_t utxovout) +int64_t CCutxovalue(char *coinaddr,uint256 utxotxid,int32_t utxovout) { uint256 txid; std::vector > unspentOutputs; SetCCunspents(unspentOutputs,coinaddr); @@ -201,7 +201,7 @@ uint64_t CCutxovalue(char *coinaddr,uint256 utxotxid,int32_t utxovout) return(0); } -int32_t CC_vinselect(int32_t *aboveip,int64_t *abovep,int32_t *belowip,int64_t *belowp,struct CC_utxo utxos[],int32_t numunspents,uint64_t value) +int32_t CC_vinselect(int32_t *aboveip,int64_t *abovep,int32_t *belowip,int64_t *belowp,struct CC_utxo utxos[],int32_t numunspents,int64_t value) { int32_t i,abovei,belowi; int64_t above,below,gap,atx_value; abovei = belowi = -1; @@ -249,12 +249,11 @@ int32_t CC_vinselect(int32_t *aboveip,int64_t *abovep,int32_t *belowip,int64_t * else if ( abovei >= 0 ) return(abovei); else return(belowi); - //return(abovei >= 0 && above < (below>>1) ? abovei : belowi); } -uint64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,uint64_t total,int32_t maxinputs) +int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs) { - int32_t abovei,belowi,ind,vout,i,n = 0,maxutxos=1024; int64_t above,below; uint64_t remains,nValue,totalinputs = 0; uint256 txid,hashBlock; std::vector vecOutputs; CTransaction tx; struct CC_utxo *utxos,*up; + int32_t abovei,belowi,ind,vout,i,n = 0,maxutxos=1024; int64_t above,below; int64_t remains,nValue,totalinputs = 0; uint256 txid,hashBlock; std::vector vecOutputs; CTransaction tx; struct CC_utxo *utxos,*up; #ifdef ENABLE_WALLET const CKeyStore& keystore = *pwalletMain; assert(pwalletMain != NULL); @@ -267,30 +266,38 @@ uint64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,uint64_t total,in { txid = out.tx->GetHash(); vout = out.i; - for (i=0; i 0 && vout < tx.vout.size() && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() == 0 ) { - up = &utxos[n++]; - up->txid = txid; - up->nValue = out.tx->vout[out.i].nValue; - up->vout = vout; - /*mtx.vin.push_back(CTxIn(txid,vout,CScript())); - nValue = out.tx->vout[out.i].nValue; - totalinputs += nValue; - n++; - if ( totalinputs >= total || n >= maxinputs ) - break;*/ - if ( n >= maxutxos ) - break; + if ( mtx.vin.size() > 0 ) + { + for (i=0; i 0 ) + { + for (i=0; itxid = txid; + up->nValue = out.tx->vout[out.i].nValue; + up->vout = vout; + if ( n >= maxutxos ) + break; + } } } } remains = total; - for (i=0; i0; i++) { below = above = 0; abovei = belowi = -1; @@ -310,11 +317,11 @@ uint64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,uint64_t total,in return(0); } up = &utxos[ind]; - utxos[ind] = utxos[--n]; - memset(&utxos[n],0,sizeof(utxos[n])); mtx.vin.push_back(CTxIn(up->txid,up->vout,CScript())); totalinputs += up->nValue; remains -= up->nValue; + utxos[ind] = utxos[--n]; + memset(&utxos[n],0,sizeof(utxos[n])); if ( totalinputs >= total || (i+1) >= maxinputs ) break; } diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 240e5b7e0..54a9a0225 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -156,7 +156,7 @@ bool GetCCaddress(struct CCcontract_info *cp,char *destaddr,CPubKey pk) return(destaddr[0] != 0); } -bool ConstrainVout(CTxOut vout,int32_t CCflag,char *cmpaddr,uint64_t nValue) +bool ConstrainVout(CTxOut vout,int32_t CCflag,char *cmpaddr,int64_t nValue) { char destaddr[64]; if ( vout.scriptPubKey.IsPayToCryptoCondition() != CCflag ) @@ -255,7 +255,16 @@ CPubKey GetUnspendable(struct CCcontract_info *cp,uint8_t *unspendablepriv) bool ProcessCC(struct CCcontract_info *cp,Eval* eval, std::vector paramsNull,const CTransaction &ctx, unsigned int nIn) { - CTransaction createTx; uint256 assetid,assetid2,hashBlock; uint8_t funcid; int32_t i,n; uint64_t amount; std::vector origpubkey; + CTransaction createTx; uint256 assetid,assetid2,hashBlock; uint8_t funcid; int32_t height,i,n,from_mempool = 0; int64_t amount; std::vector origpubkey; + if ( KOMODO_CONNECTING < 0 ) // always comes back with > 0 for final confirmation + return(true); + height = KOMODO_CONNECTING; + if ( (KOMODO_CONNECTING & (1<<30)) != 0 ) + { + from_mempool = 1; + height &= ((1<<30) - 1); + } + fprintf(stderr,"KOMODO_CONNECTING.%d mempool.%d\n",height,from_mempool); // there is a chance CC tx is valid in mempool, but invalid when in block, so we cant filter duplicate requests. if any of the vins are spent, for example //txid = ctx.GetHash(); //if ( txid == cp->prevtxid ) diff --git a/src/cc/auction.cpp b/src/cc/auction.cpp index 7d8512ede..7b5f106d0 100644 --- a/src/cc/auction.cpp +++ b/src/cc/auction.cpp @@ -21,7 +21,7 @@ // start of consensus code -uint64_t IsAuctionvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) +int64_t IsAuctionvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) { char destaddr[64]; if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) @@ -35,7 +35,7 @@ uint64_t IsAuctionvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t bool AuctionExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee) { static uint256 zerohash; - CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; uint64_t inputs=0,outputs=0,assetoshis; + CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis; numvins = tx.vin.size(); numvouts = tx.vout.size(); for (i=0; i origpubkey; CTransaction vintx; int32_t n = 0; + char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t n = 0; std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); SetCCunspents(unspentOutputs,coinaddr); @@ -147,9 +147,9 @@ uint64_t AddAuctionInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CP return(totalinputs); } -std::string AuctionBid(uint64_t txfee,uint256 itemhash,uint64_t amount) +std::string AuctionBid(uint64_t txfee,uint256 itemhash,int64_t amount) { - CMutableTransaction mtx; CPubKey mypk,Auctionpk; CScript opret; uint64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C; + CMutableTransaction mtx; CPubKey mypk,Auctionpk; CScript opret; int64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C; cp = CCinit(&C,EVAL_AUCTION); if ( txfee == 0 ) txfee = 10000; @@ -164,12 +164,12 @@ std::string AuctionBid(uint64_t txfee,uint256 itemhash,uint64_t amount) mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,opret)); } else fprintf(stderr,"cant find Auction inputs\n"); - return(0); + return(""); } std::string AuctionDeliver(uint64_t txfee,uint256 itemhash,uint256 bidtxid) { - CMutableTransaction mtx; CPubKey mypk,Auctionpk; CScript opret; uint64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C; + CMutableTransaction mtx; CPubKey mypk,Auctionpk; CScript opret; int64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C; cp = CCinit(&C,EVAL_AUCTION); if ( txfee == 0 ) txfee = 10000; @@ -184,12 +184,12 @@ std::string AuctionDeliver(uint64_t txfee,uint256 itemhash,uint256 bidtxid) mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,opret)); } else fprintf(stderr,"cant find Auction inputs\n"); - return(0); + return(""); } -std::string AuctionPost(uint64_t txfee,uint256 itemhash,uint64_t minbid,char *title,char *description) +std::string AuctionPost(uint64_t txfee,uint256 itemhash,int64_t minbid,char *title,char *description) { - CMutableTransaction mtx; CPubKey mypk,Auctionpk; uint64_t funds = 0; CScript opret; struct CCcontract_info *cp,C; + CMutableTransaction mtx; CPubKey mypk,Auctionpk; int64_t funds = 0; CScript opret; struct CCcontract_info *cp,C; cp = CCinit(&C,EVAL_AUCTION); if ( txfee == 0 ) txfee = 10000; @@ -200,7 +200,7 @@ std::string AuctionPost(uint64_t txfee,uint256 itemhash,uint64_t minbid,char *ti mtx.vout.push_back(MakeCC1vout(EVAL_AUCTION,funds,Auctionpk)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret)); } - return(0); + return(""); } diff --git a/src/cc/dice.cpp b/src/cc/dice.cpp index 8d8600fb6..8da052c86 100644 --- a/src/cc/dice.cpp +++ b/src/cc/dice.cpp @@ -79,6 +79,12 @@ winner: timeout: same as winner, just without hentropy or proof +WARNING: there is an attack vector that precludes betting any large amounts, it goes as follows: + 1. do dicebet to get the house entropy revealed + 2. calculate bettor entropy that would win against the house entropy + 3. reorg the chain and make a big bet using the winning entropy calculated in 2. + + In order to mitigate this, the disclosure of the house entropy needs to be delayed beyond a reasonable reorg depth (notarization). It is recommended for production dice game with significant amounts of money to use such a delayed disclosure method. */ #include "../compat/endian.h" @@ -219,9 +225,14 @@ uint256 DiceHashEntropy(uint256 &entropy,uint256 _txidpriv) // max 1 vout per tx return(hentropy); } +int32_t dice_5nibbles(uint8_t *fivevals) +{ + return(((int32_t)fivevals[0]<<16) + ((int32_t)fivevals[1]<<12) + ((int32_t)fivevals[2]<<8) + ((int32_t)fivevals[3]<<4) + ((int32_t)fivevals[4])); +} + uint64_t DiceCalc(int64_t bet,int64_t odds,int64_t minbet,int64_t maxbet,int64_t maxodds,int64_t timeoutblocks,uint256 houseentropy,uint256 bettorentropy) { - uint8_t buf[64],_house[32],_bettor[32]; uint64_t winnings; arith_uint256 house,bettor; char str[65],str2[65]; + uint8_t buf[64],_house[32],_bettor[32],_hash[32],hash[32],hash16[64]; uint64_t winnings; arith_uint256 house,bettor; char str[65],str2[65]; int32_t i,modval; if ( odds < 10000 ) return(0); else odds -= 10000; @@ -241,11 +252,43 @@ uint64_t DiceCalc(int64_t bet,int64_t odds,int64_t minbet,int64_t maxbet,int64_t endiancpy(&buf[32],(uint8_t *)&houseentropy,32); vcalc_sha256(0,(uint8_t *)&_bettor,buf,64); endiancpy((uint8_t *)&bettor,_bettor,32); + winnings = 0; if ( odds > 1 ) - bettor = (bettor / arith_uint256(odds)); - if ( bettor >= house ) + { + if ( 0 ) + { // old way + bettor = (bettor / arith_uint256(odds)); + if ( bettor >= house ) + winnings = bet * (odds+1); + return(winnings); + } + if ( odds > 9999 ) // shouldnt happen + return(0); + endiancpy(buf,(uint8_t *)&house,32); + endiancpy(&buf[32],(uint8_t *)&bettor,32); + vcalc_sha256(0,(uint8_t *)&_hash,buf,64); + endiancpy(hash,_hash,32); + for (i=0; i<32; i++) + { + hash16[i<<1] = ((hash[i] >> 4) & 0x0f); + hash16[(i<<1) + 1] = (hash[i] & 0x0f); + } + modval = 0; + for (i=0; i<12; i++) + { + modval = dice_5nibbles(&hash16[i*5]); + if ( modval < 1000000 ) + { + modval %= 10000; + break; + } + } + fprintf(stderr,"modval %d vs %d\n",modval,(int32_t)(10000/(odds+1))); + if ( modval < 10000/(odds+1) ) + winnings = bet * (odds+1); + } + else if ( bettor >= house ) winnings = bet * (odds+1); - else winnings = 0; return(winnings); } @@ -313,18 +356,21 @@ uint256 DiceGetEntropy(CTransaction tx,uint8_t reffuncid) else return(zeroid); } -uint64_t IsDicevout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) +uint64_t IsDicevout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v,uint64_t refsbits,uint256 reffundingtxid) { - char destaddr[64]; + char destaddr[64]; uint8_t funcid; int32_t numvouts; uint64_t sbits; uint256 fundingtxid,hash,proof; if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) { - if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 ) - return(tx.vout[v].nValue); + if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 && (numvouts= tx.vout.size()) > 0 ) + { + if ( (funcid= DecodeDiceOpRet(tx.GetHash(),tx.vout[numvouts-1].scriptPubKey,sbits,fundingtxid,hash,proof)) != 0 && sbits == refsbits && ((funcid == 'F' && tx.GetHash() == reffundingtxid) || fundingtxid == reffundingtxid) ) + return(tx.vout[v].nValue); + } } return(0); } -int64_t DiceAmounts(uint64_t &inputs,uint64_t &outputs,struct CCcontract_info *cp,Eval *eval,const CTransaction &tx) +int64_t DiceAmounts(uint64_t &inputs,uint64_t &outputs,struct CCcontract_info *cp,Eval *eval,const CTransaction &tx,uint64_t refsbits,uint256 reffundingtxid) { CTransaction vinTx; uint256 hashBlock; int32_t i,numvins,numvouts; uint64_t assetoshis; numvins = tx.vin.size(); @@ -338,7 +384,7 @@ int64_t DiceAmounts(uint64_t &inputs,uint64_t &outputs,struct CCcontract_info *c return eval->Invalid("always should find vin, but didnt"); else { - if ( (assetoshis= IsDicevout(cp,vinTx,tx.vin[i].prevout.n)) != 0 ) + if ( (assetoshis= IsDicevout(cp,vinTx,tx.vin[i].prevout.n,refsbits,reffundingtxid)) != 0 ) inputs += assetoshis; } } @@ -346,7 +392,7 @@ int64_t DiceAmounts(uint64_t &inputs,uint64_t &outputs,struct CCcontract_info *c for (i=0; iInvalid("cant find fundingtxid"); else if ( fundingTx.vout.size() > 0 && DecodeDiceFundingOpRet(fundingTx.vout[fundingTx.vout.size()-1].scriptPubKey,sbits,minbet,maxbet,maxodds,timeoutblocks) != 'F' ) return eval->Invalid("fundingTx not valid"); + if ( maxodds > 9999 ) + return eval->Invalid("maxodds too big"); fundingPubKey = fundingTx.vout[1].scriptPubKey; switch ( funcid ) { @@ -487,6 +535,7 @@ bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx) DiceQueue(iswin,sbits,fundingtxid,txid); } break; + // make sure all funding txid are from matching sbits and fundingtxid!! case 'L': case 'W': case 'T': @@ -496,7 +545,7 @@ bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx) //vin.3+: funding CC vout.0 from 'F', 'E', 'W', 'L' or 'T' //vout.1: tag to owner address for entropy funds preventCCvouts = 1; - DiceAmounts(inputs,outputs,cp,eval,tx); + DiceAmounts(inputs,outputs,cp,eval,tx,sbits,fundingtxid); if ( IsCCInput(tx.vin[1].scriptSig) == 0 || IsCCInput(tx.vin[2].scriptSig) == 0 ) return eval->Invalid("vin0 or vin1 normal vin for bet"); else if ( tx.vin[1].prevout.hash != tx.vin[2].prevout.hash ) @@ -567,7 +616,7 @@ bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx) return(true); } -uint64_t AddDiceInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint64_t total,int32_t maxinputs) +uint64_t AddDiceInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint64_t total,int32_t maxinputs,uint64_t refsbits,uint256 reffundingtxid) { char coinaddr[64],str[65]; uint64_t sbits,nValue,totalinputs = 0; uint256 txid,hash,proof,hashBlock,fundingtxid; CTransaction tx; int32_t j,vout,n = 0; uint8_t funcid; std::vector > unspentOutputs; @@ -589,14 +638,20 @@ uint64_t AddDiceInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubK { if ( (funcid= DecodeDiceOpRet(txid,tx.vout[tx.vout.size()-1].scriptPubKey,sbits,fundingtxid,hash,proof)) != 0 ) { - if ( funcid == 'F' || funcid == 'E' || funcid == 'W' || funcid == 'L' || funcid == 'T' ) + char str[65],sstr[16]; + unstringbits(sstr,sbits); + fprintf(stderr,"(%c) %.8f %s %s\n",funcid,(double)tx.vout[0].nValue/COIN,sstr,uint256_str(str,txid)); + if ( sbits == refsbits && (funcid == 'F' && reffundingtxid == txid) || reffundingtxid == fundingtxid ) { - if ( total != 0 && maxinputs != 0 ) - mtx.vin.push_back(CTxIn(txid,vout,CScript())); - totalinputs += it->second.satoshis; - n++; - if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) - break; + if ( funcid == 'F' || funcid == 'E' || funcid == 'W' || funcid == 'L' || funcid == 'T' ) + { + if ( total != 0 && maxinputs != 0 ) + mtx.vin.push_back(CTxIn(txid,vout,CScript())); + totalinputs += it->second.satoshis; + n++; + if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) + break; + } } } else fprintf(stderr,"null funcid\n"); } @@ -604,9 +659,9 @@ uint64_t AddDiceInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubK return(totalinputs); } -uint64_t DicePlanFunds(uint64_t &entropyval,uint256 &entropytxid,uint64_t refsbits,struct CCcontract_info *cp,CPubKey dicepk,uint256 reffundingtxid) +int64_t DicePlanFunds(uint64_t &entropyval,uint256 &entropytxid,uint64_t refsbits,struct CCcontract_info *cp,CPubKey dicepk,uint256 reffundingtxid) { - char coinaddr[64],str[65]; uint64_t sbits,nValue,totalinputs = 0; uint256 hash,txid,proof,hashBlock,fundingtxid; CScript fundingPubKey; CTransaction tx,vinTx; int32_t vout,first=0,n=0; uint8_t funcid; + char coinaddr[64],str[65]; uint64_t sbits; int64_t nValue,totalinputs = 0; uint256 hash,txid,proof,hashBlock,fundingtxid; CScript fundingPubKey; CTransaction tx,vinTx; int32_t vout,first=0,n=0; uint8_t funcid; std::vector > unspentOutputs; if ( GetTransaction(reffundingtxid,tx,hashBlock,false) != 0 && tx.vout.size() > 1 && ConstrainVout(tx.vout[0],1,cp->unspendableCCaddr,0) != 0 ) { @@ -626,13 +681,11 @@ uint64_t DicePlanFunds(uint64_t &entropyval,uint256 &entropytxid,uint64_t refsbi { if ( (funcid == 'F' && reffundingtxid == txid) || reffundingtxid == fundingtxid ) { - if ( refsbits == sbits && (nValue= IsDicevout(cp,tx,vout)) > 10000 && (funcid == 'F' || funcid == 'E' || funcid == 'W' || funcid == 'L' || funcid == 'T') ) + if ( refsbits == sbits && (nValue= IsDicevout(cp,tx,vout,refsbits,reffundingtxid)) > 10000 && (funcid == 'F' || funcid == 'E' || funcid == 'W' || funcid == 'L' || funcid == 'T') ) { + fprintf(stderr,"%s.(%c %.8f) ",uint256_str(str,txid),funcid,(double)nValue/COIN); if ( funcid != 'F' && funcid != 'T' ) - { n++; - fprintf(stderr,"%s.(%c %.8f) ",uint256_str(str,txid),funcid,(double)nValue/COIN); - } totalinputs += nValue; if ( first == 0 && (funcid == 'E' || funcid == 'W' || funcid == 'L') ) { @@ -802,14 +855,14 @@ UniValue DiceList() std::string DiceCreateFunding(uint64_t txfee,char *planstr,int64_t funds,int64_t minbet,int64_t maxbet,int64_t maxodds,int64_t timeoutblocks) { CMutableTransaction mtx; uint256 zero; CScript fundingPubKey; CPubKey mypk,dicepk; int64_t a,b,c,d; uint64_t sbits; struct CCcontract_info *cp,C; - if ( funds < 0 || minbet < 0 || maxbet < 0 || maxodds < 1 || timeoutblocks < 0 || timeoutblocks > 1440 ) + if ( funds < 0 || minbet < 0 || maxbet < 0 || maxodds < 1 || maxodds > 9999 || timeoutblocks < 0 || timeoutblocks > 1440 ) { fprintf(stderr,"negative parameter error\n"); - return(0); + return(""); } memset(&zero,0,sizeof(zero)); if ( (cp= Diceinit(fundingPubKey,zero,&C,planstr,txfee,mypk,dicepk,sbits,a,b,c,d)) == 0 ) - return(0); + return(""); if ( AddNormalinputs(mtx,mypk,funds+3*txfee,60) > 0 ) { mtx.vout.push_back(MakeCC1vout(cp->evalcode,funds,dicepk)); @@ -818,7 +871,7 @@ std::string DiceCreateFunding(uint64_t txfee,char *planstr,int64_t funds,int64_t return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeDiceFundingOpRet('F',sbits,minbet,maxbet,maxodds,timeoutblocks))); } fprintf(stderr,"cant find enough inputs\n"); - return(0); + return(""); } std::string DiceAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t amount) @@ -826,11 +879,11 @@ std::string DiceAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,int6 CMutableTransaction mtx; CScript fundingPubKey,scriptPubKey; uint256 entropy,hentropy; CPubKey mypk,dicepk; uint64_t sbits; struct CCcontract_info *cp,C; int64_t minbet,maxbet,maxodds,timeoutblocks; if ( amount < 0 ) { - fprintf(stderr,"negative parameter error\n"); - return(0); + fprintf(stderr,"negative parameter\n"); + return(""); } if ( (cp= Diceinit(fundingPubKey,fundingtxid,&C,planstr,txfee,mypk,dicepk,sbits,minbet,maxbet,maxodds,timeoutblocks)) == 0 ) - return(0); + return(""); scriptPubKey = CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG; if ( 0 ) { @@ -854,30 +907,30 @@ std::string DiceAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,int6 return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeDiceOpRet('E',sbits,fundingtxid,hentropy,zeroid))); } else fprintf(stderr,"cant find enough inputs\n"); } else fprintf(stderr,"only fund creator can add more funds (entropy)\n"); - return(0); + return(""); } std::string DiceBet(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t bet,int32_t odds) { CMutableTransaction mtx; CScript fundingPubKey; CPubKey mypk,dicepk; uint64_t sbits,entropyval; int64_t funding,minbet,maxbet,maxodds,timeoutblocks; uint256 entropytxid,entropy,hentropy; struct CCcontract_info *cp,C; - if ( bet < 0 || odds < 1 ) + if ( bet < 0 || odds < 1 || odds > 9999 ) { - fprintf(stderr,"negative parameter error\n"); - return(0); + fprintf(stderr,"negative parameter or odds too big error\n"); + return(""); } if ( (cp= Diceinit(fundingPubKey,fundingtxid,&C,planstr,txfee,mypk,dicepk,sbits,minbet,maxbet,maxodds,timeoutblocks)) == 0 ) - return(0); + return(""); if ( bet < minbet || bet > maxbet || odds > maxodds ) { fprintf(stderr,"Dice plan %s illegal bet %.8f: minbet %.8f maxbet %.8f or odds %d vs max.%d\n",planstr,(double)bet/COIN,(double)minbet/COIN,(double)maxbet/COIN,(int32_t)odds,(int32_t)maxodds); - return(0); + return(""); } if ( (funding= DicePlanFunds(entropyval,entropytxid,sbits,cp,dicepk,fundingtxid)) >= 2*bet*odds+txfee && entropyval != 0 ) { if ( myIsutxo_spentinmempool(entropytxid,0) != 0 ) { fprintf(stderr,"entropy txid is spent\n"); - return(0); + return(""); } mtx.vin.push_back(CTxIn(entropytxid,0,CScript())); if ( AddNormalinputs(mtx,mypk,bet+2*txfee+odds,60) > 0 ) @@ -892,18 +945,18 @@ std::string DiceBet(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t bet if ( entropyval == 0 && funding != 0 ) fprintf(stderr,"cant find dice entropy inputs\n"); else fprintf(stderr,"cant find dice inputs\n"); - return(0); + return(""); } std::string DiceBetFinish(int32_t *resultp,uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettxid,int32_t winlosetimeout) { - CMutableTransaction mtx; CScript scriptPubKey,fundingPubKey; CTransaction betTx,entropyTx; uint256 hentropyproof,entropytxid,hashBlock,bettorentropy,entropy,hentropy; CPubKey mypk,dicepk,fundingpk; struct CCcontract_info *cp,C; int64_t inputs,CCchange=0,odds,fundsneeded,minbet,maxbet,maxodds,timeoutblocks; uint8_t funcid=0; int32_t iswin=0; uint64_t entropyval,sbits; + CMutableTransaction mtx; CScript scriptPubKey,fundingPubKey; CTransaction betTx,entropyTx; uint256 hentropyproof,entropytxid,hashBlock,bettorentropy,entropy,hentropy; CPubKey mypk,dicepk,fundingpk; struct CCcontract_info *cp,C; int64_t inputs=0,CCchange=0,odds,fundsneeded,minbet,maxbet,maxodds,timeoutblocks; uint8_t funcid=0; int32_t iswin=0; uint64_t entropyval,sbits; *resultp = 0; //char str[65]; fprintf(stderr,"DiceBetFinish.%s %s\n",planstr,uint256_str(str,bettxid)); if ( (cp= Diceinit(fundingPubKey,fundingtxid,&C,planstr,txfee,mypk,dicepk,sbits,minbet,maxbet,maxodds,timeoutblocks)) == 0 ) { fprintf(stderr,"Diceinit error\n"); - return("0"); + return(""); } fundingpk = DiceFundingPk(fundingPubKey); if ( winlosetimeout != 0 ) @@ -918,7 +971,7 @@ std::string DiceBetFinish(int32_t *resultp,uint64_t txfee,char *planstr,uint256 if ( AddNormalinputs(mtx,mypk,txfee,1) == 0 ) { fprintf(stderr,"no txfee inputs for win/lose\n"); - return("0"); + return(""); } if ( GetTransaction(bettxid,betTx,hashBlock,false) != 0 && GetTransaction(betTx.vin[0].prevout.hash,entropyTx,hashBlock,false) != 0 ) { @@ -932,7 +985,7 @@ std::string DiceBetFinish(int32_t *resultp,uint64_t txfee,char *planstr,uint256 if ( myIsutxo_spentinmempool(bettxid,0) != 0 || myIsutxo_spentinmempool(bettxid,1) != 0 ) { fprintf(stderr,"bettxid already spent\n"); - return("0"); + return(""); } //fprintf(stderr,"iswin.%d matches\n",iswin); mtx.vin.push_back(CTxIn(bettxid,0,CScript())); @@ -942,7 +995,7 @@ std::string DiceBetFinish(int32_t *resultp,uint64_t txfee,char *planstr,uint256 funcid = 'T'; if ( DiceVerifyTimeout(betTx,timeoutblocks) == 0 ) // hasnt timed out yet { - return("0"); + return(""); } else { @@ -958,23 +1011,25 @@ std::string DiceBetFinish(int32_t *resultp,uint64_t txfee,char *planstr,uint256 if ( odds < 1 || odds > maxodds ) { fprintf(stderr,"illegal odds.%d vs maxodds.%d\n",(int32_t)odds,(int32_t)maxodds); - return("0"); + return(""); } - CCchange = betTx.vout[0].nValue; - fundsneeded = txfee + odds*betTx.vout[1].nValue; - if ( (inputs= AddDiceInputs(cp,mtx,dicepk,fundsneeded,60)) > 0 ) + CCchange = betTx.vout[0].nValue + betTx.vout[1].nValue; + fundsneeded = txfee + (odds+1)*betTx.vout[1].nValue; + if ( CCchange >= fundsneeded ) + CCchange -= fundsneeded; + else if ( (inputs= AddDiceInputs(cp,mtx,dicepk,fundsneeded,60,sbits,fundingtxid)) > 0 ) { if ( inputs > fundsneeded ) CCchange += (inputs - fundsneeded); - mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange,dicepk)); - mtx.vout.push_back(CTxOut(txfee,fundingPubKey)); - mtx.vout.push_back(CTxOut((odds+1) * betTx.vout[1].nValue,betTx.vout[2].scriptPubKey)); } else { fprintf(stderr,"not enough inputs for %.8f\n",(double)fundsneeded/COIN); - return("0"); + return(""); } + mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange,dicepk)); + mtx.vout.push_back(CTxOut(txfee,fundingPubKey)); + mtx.vout.push_back(CTxOut((odds+1) * betTx.vout[1].nValue,betTx.vout[2].scriptPubKey)); } else { @@ -994,12 +1049,12 @@ std::string DiceBetFinish(int32_t *resultp,uint64_t txfee,char *planstr,uint256 { *resultp = -1; fprintf(stderr,"iswin.%d winlosetimeout.%d\n",iswin,winlosetimeout); - return("0"); + return(""); } } *resultp = -1; fprintf(stderr,"couldnt find bettx or entropytx\n"); - return("0"); + return(""); } double DiceStatus(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettxid) @@ -1047,14 +1102,19 @@ double DiceStatus(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettx } else { + char str[65]; if ( (vout= myIsutxo_spent(spenttxid,bettxid,1)) >= 0 ) { - if ( GetTransaction(spenttxid,spenttx,hashBlock,false) != 0 && spenttx.vout.size() > 2 ) + //fprintf(stderr,"bettx is spent\n"); + if ( GetTransaction(bettxid,betTx,hashBlock,false) != 0 && GetTransaction(spenttxid,spenttx,hashBlock,false) != 0 && spenttx.vout.size() > 2 ) { - if ( spenttx.vout[2].scriptPubKey == fundingPubKey ) + //fprintf(stderr,"found spenttxid %s\n",uint256_str(str,spenttxid)); + if ( betTx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 || betTx.vout[2].scriptPubKey.IsPayToCryptoCondition() != 0 || spenttx.vout[2].scriptPubKey != betTx.vout[2].scriptPubKey ) return(0.); else return((double)spenttx.vout[2].nValue/COIN); - } else return(0.); + } + fprintf(stderr,"couldnt find bettx or spenttx %s\n",uint256_str(str,spenttxid)); + return(0.); } else if ( scriptPubKey == fundingPubKey ) res = DiceBetFinish(&result,txfee,planstr,fundingtxid,bettxid,1); @@ -1065,15 +1125,17 @@ double DiceStatus(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettx sleep(1); if ( (vout= myIsutxo_spent(spenttxid,bettxid,1)) >= 0 ) { - if ( GetTransaction(spenttxid,spenttx,hashBlock,false) != 0 && spenttx.vout.size() >= 2 ) + if ( GetTransaction(txid,betTx,hashBlock,false) != 0 && GetTransaction(spenttxid,spenttx,hashBlock,false) != 0 && spenttx.vout.size() >= 2 ) { - if ( spenttx.vout[2].scriptPubKey == fundingPubKey || ((uint8_t *)spenttx.vout[2].scriptPubKey.data())[0] == 0x6a ) + if ( betTx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 || betTx.vout[2].scriptPubKey.IsPayToCryptoCondition() != 0 || spenttx.vout[2].scriptPubKey != betTx.vout[2].scriptPubKey ) + //if ( spenttx.vout[2].scriptPubKey == fundingPubKey || ((uint8_t *)spenttx.vout[2].scriptPubKey.data())[0] == 0x6a ) return(0.); else return((double)spenttx.vout[2].nValue/COIN); } else return(0.); } fprintf(stderr,"didnt find dicefinish tx\n"); - } else return(-1.); + } + return(-1.); } return(0.); } diff --git a/src/cc/eval.cpp b/src/cc/eval.cpp index 95f5c33de..b6fcf57dd 100644 --- a/src/cc/eval.cpp +++ b/src/cc/eval.cpp @@ -38,7 +38,7 @@ bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn) pthread_mutex_lock(&KOMODO_CC_mutex); bool out = eval->Dispatch(cond, tx, nIn); pthread_mutex_unlock(&KOMODO_CC_mutex); - //fprintf(stderr,"out %d vs %d isValid\n",(int32_t)out,(int32_t)eval->state.IsValid()); + //fprintf(stderr,"out %d vs %d isValid\n",(int32_t)out,(int32_t)eval->state.IsValid()); assert(eval->state.IsValid() == out); if (eval->state.IsValid()) return true; diff --git a/src/cc/faucet.cpp b/src/cc/faucet.cpp index b8b3b62cb..1ac601e64 100644 --- a/src/cc/faucet.cpp +++ b/src/cc/faucet.cpp @@ -28,7 +28,7 @@ // start of consensus code -uint64_t IsFaucetvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) +int64_t IsFaucetvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) { char destaddr[64]; if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) @@ -42,7 +42,7 @@ uint64_t IsFaucetvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t bool FaucetExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee) { static uint256 zerohash; - CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; uint64_t inputs=0,outputs=0,assetoshis; + CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis; numvins = tx.vin.size(); numvouts = tx.vout.size(); for (i=0; iInvalid("mismatched inputs != outputs + COIN + txfee"); + return eval->Invalid("mismatched inputs != outputs + FAUCETSIZE + txfee"); } else return(true); } bool FaucetValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx) { - int32_t numvins,numvouts,preventCCvins,preventCCvouts,i; bool retval; + int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64]; + std::vector > txids; numvins = tx.vin.size(); numvouts = tx.vout.size(); preventCCvins = preventCCvouts = -1; @@ -87,7 +88,6 @@ bool FaucetValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx return eval->Invalid("no vouts"); else { - //fprintf(stderr,"check vins\n"); for (i=0; iInvalid("invalid faucet output"); + else if ( (hash[0] & 0xff) != 0 || (hash[31] & 0xff) != 0 ) + return eval->Invalid("invalid faucetget txid"); + Getscriptaddress(destaddr,tx.vout[i].scriptPubKey); + SetCCtxids(txids,destaddr); + for (std::vector >::const_iterator it=txids.begin(); it!=txids.end(); it++) + { + //int height = it->first.blockHeight; + if ( CCduration(numblocks,it->first.txhash) > 0 && numblocks > 3 ) + { + //fprintf(stderr,"would return error %s numblocks.%d ago\n",uint256_str(str,it->first.txhash),numblocks); + return eval->Invalid("faucet is only for brand new addresses"); + } + } retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts); if ( retval != 0 ) fprintf(stderr,"faucetget validated\n"); @@ -124,9 +140,9 @@ bool FaucetValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx // helper functions for rpc calls in rpcwallet.cpp -uint64_t AddFaucetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint64_t total,int32_t maxinputs) +int64_t AddFaucetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs) { - char coinaddr[64]; uint64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t vout,n = 0; + char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t vout,n = 0; std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); SetCCunspents(unspentOutputs,coinaddr); @@ -154,7 +170,7 @@ uint64_t AddFaucetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPu std::string FaucetGet(uint64_t txfee) { - CMutableTransaction mtx; CPubKey mypk,faucetpk; CScript opret; uint64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C; + CMutableTransaction mtx,tmpmtx; CPubKey mypk,faucetpk; int64_t inputs,CCchange=0,nValue=FAUCETSIZE; struct CCcontract_info *cp,C; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash; cp = CCinit(&C,EVAL_FAUCET); if ( txfee == 0 ) txfee = 10000; @@ -167,12 +183,32 @@ std::string FaucetGet(uint64_t txfee) if ( CCchange != 0 ) mtx.vout.push_back(MakeCC1vout(EVAL_FAUCET,CCchange,faucetpk)); mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,opret)); + fprintf(stderr,"start at %u\n",(uint32_t)time(NULL)); + j = rand() & 0xfffffff; + for (i=0; i<1000000; i++,j++) + { + tmpmtx = mtx; + rawhex = FinalizeCCTx(-1LL,cp,tmpmtx,mypk,txfee,CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_FAUCET << (uint8_t)'G' << j)); + if ( (len= (int32_t)rawhex.size()) > 0 && len < 65536 ) + { + len >>= 1; + decode_hex(buf,len,(char *)rawhex.c_str()); + hash = bits256_doublesha256(0,buf,len); + if ( (hash.bytes[0] & 0xff) == 0 && (hash.bytes[31] & 0xff) == 0 ) + { + fprintf(stderr,"found valid txid after %d iterations %u\n",i,(uint32_t)time(NULL)); + return(rawhex); + } + //fprintf(stderr,"%02x%02x ",hash.bytes[0],hash.bytes[31]); + } + } + fprintf(stderr,"couldnt generate valid txid %u\n",(uint32_t)time(NULL)); + return(""); } else fprintf(stderr,"cant find faucet inputs\n"); - return(0); + return(""); } -std::string FaucetFund(uint64_t txfee,uint64_t funds) +std::string FaucetFund(uint64_t txfee,int64_t funds) { CMutableTransaction mtx; CPubKey mypk,faucetpk; CScript opret; struct CCcontract_info *cp,C; cp = CCinit(&C,EVAL_FAUCET); @@ -185,13 +221,13 @@ std::string FaucetFund(uint64_t txfee,uint64_t funds) mtx.vout.push_back(MakeCC1vout(EVAL_FAUCET,funds,faucetpk)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret)); } - return(0); + return(""); } UniValue FaucetInfo() { UniValue result(UniValue::VOBJ); char numstr[64]; - CMutableTransaction mtx; CPubKey faucetpk; struct CCcontract_info *cp,C; uint64_t funding; + CMutableTransaction mtx; CPubKey faucetpk; struct CCcontract_info *cp,C; int64_t funding; result.push_back(Pair("result","success")); result.push_back(Pair("name","Faucet")); cp = CCinit(&C,EVAL_FAUCET); diff --git a/src/cc/fsm.cpp b/src/cc/fsm.cpp index e3e112bf6..04c620e99 100644 --- a/src/cc/fsm.cpp +++ b/src/cc/fsm.cpp @@ -21,7 +21,7 @@ // start of consensus code -uint64_t IsFSMvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) +int64_t IsFSMvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) { char destaddr[64]; if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) @@ -35,7 +35,7 @@ uint64_t IsFSMvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) bool FSMExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee) { static uint256 zerohash; - CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; uint64_t inputs=0,outputs=0,assetoshis; + CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis; numvins = tx.vin.size(); numvouts = tx.vout.size(); for (i=0; i origpubkey; CTransaction vintx; int32_t n = 0; + char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t n = 0; std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); SetCCunspents(unspentOutputs,coinaddr); @@ -149,12 +149,12 @@ uint64_t AddFSMInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKe std::string FSMList() { - return(0); + return(""); } std::string FSMCreate(uint64_t txfee,std::string name,std::string states) { - CMutableTransaction mtx; CPubKey mypk,fsmpk; CScript opret; uint64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C; + CMutableTransaction mtx; CPubKey mypk,fsmpk; CScript opret; int64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C; cp = CCinit(&C,EVAL_FSM); if ( txfee == 0 ) txfee = 10000; @@ -169,16 +169,16 @@ std::string FSMCreate(uint64_t txfee,std::string name,std::string states) mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,opret)); } else fprintf(stderr,"cant find fsm inputs\n"); - return(0); + return(""); } std::string FSMInfo(uint256 fsmtxid) { - CMutableTransaction mtx; CPubKey mypk,fsmpk; uint64_t funds = 0; CScript opret; struct CCcontract_info *cp,C; + CMutableTransaction mtx; CPubKey mypk,fsmpk; int64_t funds = 0; CScript opret; struct CCcontract_info *cp,C; cp = CCinit(&C,EVAL_FSM); mypk = pubkey2pk(Mypubkey()); fsmpk = GetUnspendable(cp,0); - return(0); + return(""); } diff --git a/src/cc/lotto.cpp b/src/cc/lotto.cpp index 0ed223c25..e20cb3505 100644 --- a/src/cc/lotto.cpp +++ b/src/cc/lotto.cpp @@ -21,7 +21,7 @@ // start of consensus code -uint64_t IsLottovout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) +int64_t IsLottovout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) { char destaddr[64]; if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) @@ -35,7 +35,7 @@ uint64_t IsLottovout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v bool LottoExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee) { static uint256 zerohash; - CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; uint64_t inputs=0,outputs=0,assetoshis; + CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis; numvins = tx.vin.size(); numvouts = tx.vout.size(); for (i=0; i origpubkey; CTransaction vintx; int32_t n = 0; + char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t n = 0; std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); SetCCunspents(unspentOutputs,coinaddr); @@ -147,9 +147,9 @@ uint64_t AddLottoInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPub return(totalinputs); } -std::string LottoTicket(uint64_t txfee,uint64_t numtickets) +std::string LottoTicket(uint64_t txfee,int64_t numtickets) { - CMutableTransaction mtx; CPubKey mypk,Lottopk; CScript opret; uint64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C; + CMutableTransaction mtx; CPubKey mypk,Lottopk; CScript opret; int64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C; cp = CCinit(&C,EVAL_LOTTO); if ( txfee == 0 ) txfee = 10000; @@ -164,12 +164,12 @@ std::string LottoTicket(uint64_t txfee,uint64_t numtickets) mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,opret)); } else fprintf(stderr,"cant find Lotto inputs\n"); - return(0); + return(""); } std::string LottoWinner(uint64_t txfee) { - CMutableTransaction mtx; CPubKey mypk,Lottopk; uint64_t winnings = 0; CScript opret; struct CCcontract_info *cp,C; + CMutableTransaction mtx; CPubKey mypk,Lottopk; int64_t winnings = 0; CScript opret; struct CCcontract_info *cp,C; cp = CCinit(&C,EVAL_LOTTO); if ( txfee == 0 ) txfee = 10000; @@ -180,7 +180,7 @@ std::string LottoWinner(uint64_t txfee) mtx.vout.push_back(MakeCC1vout(EVAL_LOTTO,winnings,Lottopk)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret)); } - return(0); + return(""); } diff --git a/src/cc/rewards.cpp b/src/cc/rewards.cpp index afa025851..61bcf5ca3 100644 --- a/src/cc/rewards.cpp +++ b/src/cc/rewards.cpp @@ -13,7 +13,7 @@ * * ******************************************************************************/ -#include "CCinclude.h" +#include "CCrewards.h" /* The rewards CC contract is initially for OOT, which needs this functionality. However, many of the attributes can be parameterized to allow different rewards programs to run. Multiple rewards plans could even run on the same blockchain, though the user would need to choose which one to lock funds into. @@ -66,10 +66,12 @@ */ -uint64_t RewardsCalc(uint64_t amount,uint256 txid,uint64_t APR,uint64_t minseconds,uint64_t maxseconds,uint64_t mindeposit) +extern std::string CCerror; + +int64_t RewardsCalc(int64_t amount,uint256 txid,uint64_t APR,uint64_t minseconds,uint64_t maxseconds,uint64_t mindeposit) { int32_t numblocks; uint64_t duration,reward = 0; - fprintf(stderr,"minseconds %llu maxseconds %llu\n",(long long)minseconds,(long long)maxseconds); + //fprintf(stderr,"minseconds %llu maxseconds %llu\n",(long long)minseconds,(long long)maxseconds); if ( (duration= CCduration(numblocks,txid)) < minseconds ) { fprintf(stderr,"duration %llu < minseconds %llu\n",(long long)duration,(long long)minseconds); @@ -77,8 +79,12 @@ uint64_t RewardsCalc(uint64_t amount,uint256 txid,uint64_t APR,uint64_t minsecon //duration = (uint32_t)time(NULL) - (1532713903 - 3600 * 24); } else if ( duration > maxseconds ) duration = maxseconds; - reward = (((amount * APR) / COIN) * duration) / (365*24*3600LL * 100); - fprintf(stderr,"amount %.8f %.8f %llu -> duration.%llu reward %.8f\n",(double)amount/COIN,((double)amount * APR)/COIN,(long long)((amount * APR) / (COIN * 365*24*3600)),(long long)duration,(double)reward/COIN); + if ( 0 ) // amount * APR * duration / COIN * 100 * 365*24*3600 + reward = (((amount * APR) / COIN) * duration) / (365*24*3600LL * 100); + else reward = (((amount * duration) / (365 * 24 * 3600LL)) * (APR / 1000000)) / 10000; + if ( reward > amount ) + reward = amount; + fprintf(stderr,"amount %.8f %.8f %llu -> duration.%llu reward %.8f vals %.8f %.8f\n",(double)amount/COIN,((double)amount * APR)/COIN,(long long)((amount * APR) / (COIN * 365*24*3600)),(long long)duration,(double)reward/COIN,(double)((amount * duration) / (365 * 24 * 3600LL))/COIN,(double)(((amount * duration) / (365 * 24 * 3600LL)) * (APR / 1000000))/COIN); return(reward); } @@ -137,21 +143,26 @@ uint8_t DecodeRewardsOpRet(uint256 txid,const CScript &scriptPubKey,uint64_t &sb return(0); } -uint64_t IsRewardsvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) +int64_t IsRewardsvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v,uint64_t refsbits,uint256 reffundingtxid) { - char destaddr[64]; - if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) + char destaddr[64]; uint64_t sbits; uint256 fundingtxid,txid; uint8_t funcid; int32_t numvouts; + if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 && (numvouts= (int32_t)tx.vout.size()) > 0 ) { - if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 ) - return(tx.vout[v].nValue); + txid = tx.GetHash(); + if ( (funcid= DecodeRewardsOpRet(txid,tx.vout[numvouts-1].scriptPubKey,sbits,fundingtxid)) != 0 && sbits == refsbits && (fundingtxid == reffundingtxid || txid == reffundingtxid) ) + { + + if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 ) + return(tx.vout[v].nValue); + } } return(0); } -bool RewardsExactAmounts(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx,uint64_t txfee) +bool RewardsExactAmounts(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx,uint64_t txfee,uint64_t refsbits,uint256 reffundingtxid) { static uint256 zerohash; - CTransaction vinTx; uint256 hashBlock; int32_t i,numvins,numvouts; uint64_t inputs=0,outputs=0,assetoshis; + CTransaction vinTx; uint256 hashBlock; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis; numvins = tx.vin.size(); numvouts = tx.vout.size(); for (i=0; iInvalid("cant rewards from mempool"); - if ( (assetoshis= IsRewardsvout(cp,vinTx,tx.vin[i].prevout.n)) != 0 ) + if ( (assetoshis= IsRewardsvout(cp,vinTx,tx.vin[i].prevout.n,refsbits,reffundingtxid)) != 0 ) inputs += assetoshis; } } @@ -172,12 +183,12 @@ bool RewardsExactAmounts(struct CCcontract_info *cp,Eval *eval,const CTransactio for (i=0; iInvalid("mismatched inputs != outputs + txfee"); } else return(true); @@ -200,6 +211,8 @@ bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t return eval->Invalid("cant find fundingtxid"); else if ( fundingTx.vout.size() > 0 && DecodeRewardsFundingOpRet(fundingTx.vout[fundingTx.vout.size()-1].scriptPubKey,sbits,APR,minseconds,maxseconds,mindeposit) != 'F' ) return eval->Invalid("fundingTx not valid"); + if ( APR > REWARDSCC_MAXAPR ) + return eval->Invalid("excessive APR"); switch ( funcid ) { case 'F': @@ -228,22 +241,32 @@ bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t case 'U': //vin.0: locked funds CC vout.0 from lock //vin.1+: funding CC vout.0 from 'F' and 'A' and 'U' - //vout.0: funding CC change + //vout.0: funding CC change or recover normal payout //vout.1: normal output to unlock address //vout.n-1: opreturn 'U' sbits fundingtxid + if ( eval->GetTxUnconfirmed(tx.vin[0].prevout.hash,vinTx,hashBlock) == 0 ) + return eval->Invalid("always should find vin.0, but didnt"); for (i=0; iismyvin)(tx.vin[i].scriptSig) == 0 ) return eval->Invalid("unexpected normal vin for unlock"); } - if ( RewardsExactAmounts(cp,eval,tx,txfee+tx.vout[1].nValue) == 0 ) - return false; - else if ( eval->GetTxUnconfirmed(tx.vin[0].prevout.hash,vinTx,hashBlock) == 0 ) - return eval->Invalid("always should find vin.0, but didnt"); - else if ( vinTx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) - return eval->Invalid("lock tx vout.0 is normal output"); - else if ( tx.vout.size() < 3 ) - return eval->Invalid("unlock tx not enough vouts"); + if ( numvouts == 2 && numvins == 1 ) + { + if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() != 0 ) + return eval->Invalid("unlock recover tx vout.0 is not normal output"); + else if ( tx.vout[0].scriptPubKey != vinTx.vout[1].scriptPubKey ) + return eval->Invalid("unlock recover tx vout.0 mismatched scriptPubKey"); + else if ( tx.vout[0].nValue > vinTx.vout[0].nValue ) + return eval->Invalid("unlock recover tx vout.0 mismatched amounts"); + else if ( tx.vout[1].nValue > 0 ) + return eval->Invalid("unlock recover tx vout.1 nonz amount"); + else return(true); + } + if ( vinTx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("unlock tx vout.0 is normal output"); + else if ( numvouts != 3 ) + return eval->Invalid("unlock tx wrong number of vouts"); else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) return eval->Invalid("unlock tx vout.0 is normal output"); else if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() != 0 ) @@ -252,8 +275,12 @@ bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t return eval->Invalid("unlock tx vout.1 mismatched scriptPubKey"); amount = vinTx.vout[0].nValue; reward = RewardsCalc(amount,tx.vin[0].prevout.hash,APR,minseconds,maxseconds,mindeposit); - if ( tx.vout[1].nValue > amount+reward ) + if ( RewardsExactAmounts(cp,eval,tx,txfee+tx.vout[1].nValue,sbits,fundingtxid) == 0 ) + return false; + else if ( tx.vout[1].nValue > amount+reward ) return eval->Invalid("unlock tx vout.1 isnt amount+reward"); + else if ( tx.vout[2].nValue > 0 ) + return eval->Invalid("unlock tx vout.2 isnt 0"); preventCCvouts = 1; break; } @@ -263,10 +290,38 @@ bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t return(true); } -// 'L' vs 'F' and 'A' -uint64_t AddRewardsInputs(CScript &scriptPubKey,int32_t fundsflag,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint64_t total,int32_t maxinputs) +uint64_t myIs_unlockedtx_inmempool(uint256 &txid,int32_t &vout,uint64_t refsbits,uint256 reffundingtxid,uint64_t needed) { - char coinaddr[64],str[65]; uint64_t sbits,nValue,totalinputs = 0; uint256 txid,hashBlock,fundingtxid; CTransaction tx; int32_t j,vout,n = 0; uint8_t funcid; + uint8_t funcid; uint64_t sbits,nValue; uint256 fundingtxid; char str[65]; + memset(&txid,0,sizeof(txid)); + vout = -1; + nValue = 0; + BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) + { + const CTransaction &tx = e.GetTx(); + if ( tx.vout.size() > 0 && tx.vout[0].nValue >= needed ) + { + const uint256 &hash = tx.GetHash(); + if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() != 0 && myIsutxo_spentinmempool(hash,0) == 0 ) + { + if ( (funcid= DecodeRewardsOpRet(hash,tx.vout[tx.vout.size()-1].scriptPubKey,sbits,fundingtxid)) == 'U' && sbits == refsbits && fundingtxid == reffundingtxid ) + { + txid = hash; + vout = 0; + nValue = tx.vout[0].nValue; + fprintf(stderr,"found 'U' %s %.8f in unspent in mempool\n",uint256_str(str,txid),(double)nValue/COIN); + return(nValue); + } + } + } + } + return(nValue); +} + +// 'L' vs 'F' and 'A' +int64_t AddRewardsInputs(CScript &scriptPubKey,uint64_t maxseconds,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs,uint64_t refsbits,uint256 reffundingtxid) +{ + char coinaddr[64],str[65]; uint64_t sbits,nValue,totalinputs = 0; uint256 txid,hashBlock,fundingtxid; CTransaction tx; int32_t numblocks,j,vout,n = 0; uint8_t funcid; std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); SetCCunspents(unspentOutputs,coinaddr); @@ -276,7 +331,7 @@ uint64_t AddRewardsInputs(CScript &scriptPubKey,int32_t fundsflag,struct CCcontr vout = (int32_t)it->first.index; if ( it->second.satoshis < 1000000 ) continue; - fprintf(stderr,"(%s) %s/v%d %.8f\n",coinaddr,uint256_str(str,txid),vout,(double)it->second.satoshis/COIN); + //fprintf(stderr,"(%s) %s/v%d %.8f\n",coinaddr,uint256_str(str,txid),vout,(double)it->second.satoshis/COIN); for (j=0; jsecond.satoshis/COIN); - if ( fundsflag != 0 && funcid != 'F' && funcid != 'A' && funcid != 'U' ) + if ( sbits != refsbits || fundingtxid != reffundingtxid ) continue; - else if ( fundsflag == 0 && (funcid != 'L' || tx.vout.size() < 4) ) + if ( maxseconds == 0 && funcid != 'F' && funcid != 'A' && funcid != 'U' ) continue; + else if ( maxseconds != 0 && funcid != 'L' ) + { + if ( CCduration(numblocks,txid) < maxseconds ) + continue; + } + fprintf(stderr,"maxseconds.%d (%c) %.8f %.8f\n",(int32_t)maxseconds,funcid,(double)tx.vout[vout].nValue/COIN,(double)it->second.satoshis/COIN); if ( total != 0 && maxinputs != 0 ) { - if ( fundsflag == 0 ) + if ( maxseconds != 0 ) scriptPubKey = tx.vout[1].scriptPubKey; mtx.vin.push_back(CTxIn(txid,vout,CScript())); } @@ -304,13 +364,25 @@ uint64_t AddRewardsInputs(CScript &scriptPubKey,int32_t fundsflag,struct CCcontr } else fprintf(stderr,"null funcid\n"); } } + if ( maxseconds == 0 && totalinputs < total && (maxinputs == 0 || n < maxinputs-1) ) + { + fprintf(stderr,"search mempool for unlocked and unspent CC rewards output for %.8f\n",(double)(total-totalinputs)/COIN); + if ( (nValue= myIs_unlockedtx_inmempool(txid,vout,refsbits,reffundingtxid,total-totalinputs)) > 0 ) + { + mtx.vin.push_back(CTxIn(txid,vout,CScript())); + fprintf(stderr,"added mempool vout for %.8f\n",(double)nValue/COIN); + totalinputs += nValue; + n++; + } + } return(totalinputs); } -uint64_t RewardsPlanFunds(uint64_t refsbits,struct CCcontract_info *cp,CPubKey pk,uint256 reffundingtxid) +int64_t RewardsPlanFunds(uint64_t &lockedfunds,uint64_t refsbits,struct CCcontract_info *cp,CPubKey pk,uint256 reffundingtxid) { - char coinaddr[64]; uint64_t sbits,nValue,totalinputs = 0; uint256 txid,hashBlock,fundingtxid; CTransaction tx; int32_t vout; uint8_t funcid; + char coinaddr[64]; uint64_t sbits; int64_t nValue,totalinputs = 0; uint256 txid,hashBlock,fundingtxid; CTransaction tx; int32_t vout; uint8_t funcid; std::vector > unspentOutputs; + lockedfunds = 0; GetCCaddress(cp,coinaddr,pk); SetCCunspents(unspentOutputs,coinaddr); for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) @@ -319,12 +391,16 @@ uint64_t RewardsPlanFunds(uint64_t refsbits,struct CCcontract_info *cp,CPubKey p vout = (int32_t)it->first.index; if ( GetTransaction(txid,tx,hashBlock,false) != 0 && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 ) { - if ( (funcid= DecodeRewardsOpRet(txid,tx.vout[tx.vout.size()-1].scriptPubKey,sbits,fundingtxid)) != 0 ) + if ( (funcid= DecodeRewardsOpRet(txid,tx.vout[tx.vout.size()-1].scriptPubKey,sbits,fundingtxid)) == 'F' || funcid == 'A' || funcid == 'U' || funcid == 'L' ) { - if ( (funcid == 'F' && reffundingtxid == txid) || reffundingtxid == fundingtxid ) + if ( refsbits == sbits && (funcid == 'F' && reffundingtxid == txid) || reffundingtxid == fundingtxid ) { - if ( refsbits == sbits && (nValue= IsRewardsvout(cp,tx,vout)) > 0 ) - totalinputs += nValue; + if ( (nValue= IsRewardsvout(cp,tx,vout,sbits,fundingtxid)) > 0 ) + { + if ( funcid == 'L' ) + lockedfunds += nValue; + else totalinputs += nValue; + } else fprintf(stderr,"refsbits.%llx sbits.%llx nValue %.8f\n",(long long)refsbits,(long long)sbits,(double)nValue/COIN); } //else fprintf(stderr,"else case\n"); } else fprintf(stderr,"funcid.%d %c skipped %.8f\n",funcid,funcid,(double)tx.vout[vout].nValue/COIN); @@ -358,16 +434,18 @@ bool RewardsPlanExists(struct CCcontract_info *cp,uint64_t refsbits,CPubKey rewa UniValue RewardsInfo(uint256 rewardsid) { - UniValue result(UniValue::VOBJ); uint256 hashBlock; CTransaction vintx; uint64_t APR,minseconds,maxseconds,mindeposit,sbits,funding; CPubKey rewardspk; struct CCcontract_info *cp,C; char str[67],numstr[65]; + UniValue result(UniValue::VOBJ); uint256 hashBlock; CTransaction vintx; uint64_t lockedfunds,APR,minseconds,maxseconds,mindeposit,sbits,funding; CPubKey rewardspk; struct CCcontract_info *cp,C; char str[67],numstr[65]; if ( GetTransaction(rewardsid,vintx,hashBlock,false) == 0 ) { fprintf(stderr,"cant find fundingtxid\n"); + result.push_back(Pair("result","error")); result.push_back(Pair("error","cant find fundingtxid")); return(result); } if ( vintx.vout.size() > 0 && DecodeRewardsFundingOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,sbits,APR,minseconds,maxseconds,mindeposit) == 0 ) { fprintf(stderr,"fundingtxid isnt rewards creation txid\n"); + result.push_back(Pair("result","error")); result.push_back(Pair("error","fundingtxid isnt rewards creation txid")); return(result); } @@ -384,9 +462,11 @@ UniValue RewardsInfo(uint256 rewardsid) result.push_back(Pair("mindeposit",numstr)); cp = CCinit(&C,EVAL_REWARDS); rewardspk = GetUnspendable(cp,0); - funding = RewardsPlanFunds(sbits,cp,rewardspk,rewardsid); + funding = RewardsPlanFunds(lockedfunds,sbits,cp,rewardspk,rewardsid); sprintf(numstr,"%.8f",(double)funding/COIN); result.push_back(Pair("funding",numstr)); + sprintf(numstr,"%.8f",(double)lockedfunds/COIN); + result.push_back(Pair("locked",numstr)); return(result); } @@ -412,10 +492,15 @@ UniValue RewardsList() std::string RewardsCreateFunding(uint64_t txfee,char *planstr,int64_t funds,int64_t APR,int64_t minseconds,int64_t maxseconds,int64_t mindeposit) { CMutableTransaction mtx; CPubKey mypk,rewardspk; CScript opret; uint64_t sbits,a,b,c,d; struct CCcontract_info *cp,C; - if ( funds < 0 || mindeposit < 0 || minseconds < 0 || maxseconds < 0 ) + if ( funds < COIN || mindeposit < 0 || minseconds < 0 || maxseconds < 0 ) { fprintf(stderr,"negative parameter error\n"); - return(0); + return(""); + } + if ( APR > REWARDSCC_MAXAPR ) + { + fprintf(stderr,"25%% APR is maximum\n"); + return(""); } cp = CCinit(&C,EVAL_REWARDS); if ( txfee == 0 ) @@ -426,7 +511,7 @@ std::string RewardsCreateFunding(uint64_t txfee,char *planstr,int64_t funds,int6 if ( RewardsPlanExists(cp,sbits,rewardspk,a,b,c,d) != 0 ) { fprintf(stderr,"Rewards plan (%s) already exists\n",planstr); - return(0); + return(""); } if ( AddNormalinputs(mtx,mypk,funds+2*txfee,64) > 0 ) { @@ -435,7 +520,7 @@ std::string RewardsCreateFunding(uint64_t txfee,char *planstr,int64_t funds,int6 return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeRewardsFundingOpRet('F',sbits,APR,minseconds,maxseconds,mindeposit))); } fprintf(stderr,"cant find enough inputs\n"); - return(0); + return(""); } std::string RewardsAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t amount) @@ -444,7 +529,7 @@ std::string RewardsAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,i if ( amount < 0 ) { fprintf(stderr,"negative parameter error\n"); - return(0); + return(""); } cp = CCinit(&C,EVAL_REWARDS); if ( txfee == 0 ) @@ -455,7 +540,7 @@ std::string RewardsAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,i if ( RewardsPlanExists(cp,sbits,rewardspk,a,b,c,d) == 0 ) { fprintf(stderr,"Rewards plan %s doesnt exist\n",planstr); - return(0); + return(""); } sbits = stringbits(planstr); if ( AddNormalinputs(mtx,mypk,amount+txfee,64) > 0 ) @@ -464,16 +549,16 @@ std::string RewardsAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,i return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeRewardsOpRet('A',sbits,fundingtxid))); } else fprintf(stderr,"cant find enough inputs\n"); fprintf(stderr,"cant find fundingtxid\n"); - return(0); + return(""); } std::string RewardsLock(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t deposit) { - CMutableTransaction mtx; CPubKey mypk,rewardspk; CScript opret; uint64_t sbits,funding,APR,minseconds,maxseconds,mindeposit; struct CCcontract_info *cp,C; - if ( deposit < 0 ) + CMutableTransaction mtx; CPubKey mypk,rewardspk; CScript opret; uint64_t lockedfunds,sbits,funding,APR,minseconds,maxseconds,mindeposit; struct CCcontract_info *cp,C; + if ( deposit < txfee ) { - fprintf(stderr,"negative parameter error\n"); - return(0); + fprintf(stderr,"deposit amount less than txfee\n"); + return(""); } cp = CCinit(&C,EVAL_REWARDS); if ( txfee == 0 ) @@ -484,29 +569,29 @@ std::string RewardsLock(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t if ( RewardsPlanExists(cp,sbits,rewardspk,APR,minseconds,maxseconds,mindeposit) == 0 ) { fprintf(stderr,"Rewards plan %s doesnt exist\n",planstr); - return(0); + return(""); } if ( deposit < mindeposit ) { fprintf(stderr,"Rewards plan %s deposit %.8f < mindeposit %.8f\n",planstr,(double)deposit/COIN,(double)mindeposit/COIN); - return(0); + return(""); } - if ( (funding= RewardsPlanFunds(sbits,cp,rewardspk,fundingtxid)) >= deposit ) // arbitrary cmpval + if ( (funding= RewardsPlanFunds(lockedfunds,sbits,cp,rewardspk,fundingtxid)) >= deposit ) // arbitrary cmpval { if ( AddNormalinputs(mtx,mypk,deposit+2*txfee,64) > 0 ) { mtx.vout.push_back(MakeCC1vout(cp->evalcode,deposit,rewardspk)); mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeRewardsOpRet('L',sbits,fundingtxid))); - } else fprintf(stderr,"cant find enough inputs %.8f note enough for %.8f\n",(double)funding/COIN,(double)deposit/COIN); + } else fprintf(stderr,"cant find enough inputs %.8f not enough for %.8f, make sure you imported privkey for the -pubkey address\n",(double)funding/COIN,(double)deposit/COIN); } - fprintf(stderr,"cant find rewards inputs\n"); - return(0); + fprintf(stderr,"cant find rewards inputs funding %.8f locked %.8f vs deposit %.8f\n",(double)funding/COIN,(double)lockedfunds/COIN,(double)deposit/COIN); + return(""); } std::string RewardsUnlock(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 locktxid) { - CMutableTransaction mtx; CTransaction tx; char coinaddr[64]; CPubKey mypk,rewardspk; CScript opret,scriptPubKey,ignore; uint256 hashBlock; uint64_t funding,sbits,reward=0,amount=0,inputs,CCchange=0,APR,minseconds,maxseconds,mindeposit; struct CCcontract_info *cp,C; + CMutableTransaction mtx,firstmtx; CTransaction tx; char coinaddr[64]; CPubKey mypk,rewardspk; CScript scriptPubKey,ignore; uint256 hashBlock; uint64_t sbits,APR,minseconds,maxseconds,mindeposit; int64_t funding,reward=0,amount=0,inputs,CCchange=0; struct CCcontract_info *cp,C; cp = CCinit(&C,EVAL_REWARDS); if ( txfee == 0 ) txfee = 10000; @@ -516,18 +601,20 @@ std::string RewardsUnlock(uint64_t txfee,char *planstr,uint256 fundingtxid,uint2 if ( RewardsPlanExists(cp,sbits,rewardspk,APR,minseconds,maxseconds,mindeposit) == 0 ) { fprintf(stderr,"Rewards plan %s doesnt exist\n",planstr); - return(0); + CCerror = "Rewards plan does not exist"; + return(""); } fprintf(stderr,"APR %.8f minseconds.%llu maxseconds.%llu mindeposit %.8f\n",(double)APR/COIN,(long long)minseconds,(long long)maxseconds,(double)mindeposit/COIN); if ( locktxid == zeroid ) - amount = AddRewardsInputs(scriptPubKey,0,cp,mtx,rewardspk,(1LL << 30),1); + amount = AddRewardsInputs(scriptPubKey,maxseconds,cp,mtx,rewardspk,(1LL << 30),1,sbits,fundingtxid); else { GetCCaddress(cp,coinaddr,rewardspk); if ( (amount= CCutxovalue(coinaddr,locktxid,0)) == 0 ) { fprintf(stderr,"%s locktxid/v0 is spent\n",coinaddr); - return(0); + CCerror = "locktxid/v0 is spent"; + return(""); } if ( GetTransaction(locktxid,tx,hashBlock,false) != 0 && tx.vout.size() > 0 && tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) { @@ -537,23 +624,53 @@ std::string RewardsUnlock(uint64_t txfee,char *planstr,uint256 fundingtxid,uint2 else { fprintf(stderr,"%s no normal vout.1 in locktxid\n",coinaddr); - return(0); + CCerror = "no normal vout.1 in locktxid"; + return(""); } } - if ( amount > 0 && (reward= RewardsCalc(amount,mtx.vin[0].prevout.hash,APR,minseconds,maxseconds,mindeposit)) > txfee && scriptPubKey.size() > 0 ) + if ( amount > txfee ) { - if ( (inputs= AddRewardsInputs(ignore,1,cp,mtx,rewardspk,reward+txfee,30)) > 0 ) + reward = RewardsCalc(amount,mtx.vin[0].prevout.hash,APR,minseconds,maxseconds,mindeposit); + if ( scriptPubKey.size() > 0 ) { - if ( inputs >= (reward + 2*txfee) ) - CCchange = (inputs - (reward + txfee)); - fprintf(stderr,"inputs %.8f CCchange %.8f amount %.8f reward %.8f\n",(double)inputs/COIN,(double)CCchange/COIN,(double)amount/COIN,(double)reward/COIN); - mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange,rewardspk)); - mtx.vout.push_back(CTxOut(amount+reward,scriptPubKey)); - return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,EncodeRewardsOpRet('U',sbits,fundingtxid))); + if ( reward > txfee ) + { + firstmtx = mtx; + if ( (inputs= AddRewardsInputs(ignore,0,cp,mtx,rewardspk,reward+txfee,30,sbits,fundingtxid)) >= reward+txfee ) + { + if ( inputs >= (reward + 2*txfee) ) + CCchange = (inputs - (reward + txfee)); + fprintf(stderr,"inputs %.8f CCchange %.8f amount %.8f reward %.8f\n",(double)inputs/COIN,(double)CCchange/COIN,(double)amount/COIN,(double)reward/COIN); + mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange,rewardspk)); + mtx.vout.push_back(CTxOut(amount+reward,scriptPubKey)); + return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,EncodeRewardsOpRet('U',sbits,fundingtxid))); + } + else + { + firstmtx.vout.push_back(CTxOut(amount-txfee,scriptPubKey)); + //CCerror = "cant find enough rewards inputs"; + fprintf(stderr,"not enough rewards funds to payout %.8f, recover mode tx\n",(double)(reward+txfee)/COIN); + return(FinalizeCCTx(-1LL,cp,firstmtx,mypk,txfee,EncodeRewardsOpRet('U',sbits,fundingtxid))); + } + } + else + { + CCerror = strprintf("reward %.8f is <= the transaction fee", reward); + fprintf(stderr,"%s\n", CCerror.c_str()); + } } - fprintf(stderr,"cant find enough rewards inputs\n"); + else + { + CCerror = "invalid scriptPubKey"; + fprintf(stderr,"%s\n", CCerror.c_str()); + } + } + else + { + CCerror = "amount must be more than txfee"; + fprintf(stderr,"%s\n", CCerror.c_str()); } fprintf(stderr,"amount %.8f -> reward %.8f\n",(double)amount/COIN,(double)reward/COIN); - return(0); + return(""); } diff --git a/src/chain.h b/src/chain.h index d882083e6..394b4a6bd 100644 --- a/src/chain.h +++ b/src/chain.h @@ -121,7 +121,7 @@ public: //! height of the entry in the chain. The genesis block has height 0 int nHeight; - int64_t newcoins,zfunds; + int64_t newcoins,zfunds; int8_t segid; // jl777 fields //! Which # file this block is stored in (blk?????.dat) int nFile; @@ -182,6 +182,7 @@ public: { phashBlock = NULL; newcoins = zfunds = 0; + segid = -2; pprev = NULL; pskip = NULL; nHeight = 0; diff --git a/src/cryptoconditions/src/anon.c b/src/cryptoconditions/src/anon.c index 43e96ae44..8c2b9cea6 100644 --- a/src/cryptoconditions/src/anon.c +++ b/src/cryptoconditions/src/anon.c @@ -55,6 +55,7 @@ static void anonToJSON(const CC *cond, cJSON *params) { static unsigned char *anonFingerprint(const CC *cond) { unsigned char *out = calloc(1, 32); + fprintf(stderr,"anon fingerprint %p %p\n",out,cond->fingerprint); memcpy(out, cond->fingerprint, 32); return out; } diff --git a/src/cryptoconditions/src/cryptoconditions.c b/src/cryptoconditions/src/cryptoconditions.c index 3c0e9ea2c..b9b08af20 100644 --- a/src/cryptoconditions/src/cryptoconditions.c +++ b/src/cryptoconditions/src/cryptoconditions.c @@ -29,11 +29,7 @@ #include "src/json_rpc.c" #include -#ifdef __LP64__ #include -#else -#include // Index into CTransaction.vjoinsplit -#endif struct CCType *CCTypeRegistry[] = { @@ -75,8 +71,7 @@ char *cc_conditionUri(const CC *cond) { unsigned char *encoded = base64_encode(fp, 32); unsigned char *out = calloc(1, 1000); - sprintf(out, "ni:///sha-256;%s?fpt=%s&cost=%lu", - encoded, cc_typeName(cond), cc_getCost(cond)); + sprintf(out, "ni:///sha-256;%s?fpt=%s&cost=%lu",encoded, cc_typeName(cond), cc_getCost(cond)); if (cond->type->getSubtypes) { appendUriSubtypes(cond->type->getSubtypes(cond), out); @@ -151,7 +146,6 @@ void asnCondition(const CC *cond, Condition_t *asn) { // This may look a little weird - we dont have a reference here to the correct // union choice for the condition type, so we just assign everything to the threshold // type. This works out nicely since the union choices have the same binary interface. - CompoundSha256Condition_t *choice = &asn->choice.thresholdSha256; choice->cost = cc_getCost(cond); choice->fingerprint.buf = cond->type->fingerprint(cond); @@ -199,7 +193,7 @@ CC *fulfillmentToCC(Fulfillment_t *ffill) { CC *cc_readFulfillmentBinary(const unsigned char *ffill_bin, size_t ffill_bin_len) { CC *cond = 0; - unsigned char *buf = malloc(ffill_bin_len); + unsigned char *buf = calloc(1,ffill_bin_len); Fulfillment_t *ffill = 0; asn_dec_rval_t rval = ber_decode(0, &asn_DEF_Fulfillment, (void **)&ffill, ffill_bin, ffill_bin_len); if (rval.code != RC_OK) { @@ -236,12 +230,14 @@ int cc_verify(const struct CC *cond, const unsigned char *msg, size_t msgLength, const unsigned char *condBin, size_t condBinLength, VerifyEval verifyEval, void *evalContext) { unsigned char targetBinary[1000]; + //fprintf(stderr,"in cc_verify cond.%p msg.%p[%d] dohash.%d condbin.%p[%d]\n",cond,msg,(int32_t)msgLength,doHashMsg,condBin,(int32_t)condBinLength); const size_t binLength = cc_conditionBinary(cond, targetBinary); if (0 != memcmp(condBin, targetBinary, binLength)) { + fprintf(stderr,"cc_verify error A\n"); return 0; } - if (!cc_ed25519VerifyTree(cond, msg, msgLength)) { + fprintf(stderr,"cc_verify error B\n"); return 0; } @@ -250,10 +246,12 @@ int cc_verify(const struct CC *cond, const unsigned char *msg, size_t msgLength, else memcpy(msgHash, msg, 32); if (!cc_secp256k1VerifyTreeMsg32(cond, msgHash)) { + fprintf(stderr,"cc_verify error C\n"); return 0; } if (!cc_verifyEval(cond, verifyEval, evalContext)) { + //fprintf(stderr,"cc_verify error D\n"); return 0; } return 1; diff --git a/src/cryptoconditions/src/ed25519.c b/src/cryptoconditions/src/ed25519.c index 6cdd80d1d..4fb3bbb8d 100644 --- a/src/cryptoconditions/src/ed25519.c +++ b/src/cryptoconditions/src/ed25519.c @@ -27,6 +27,7 @@ struct CCType CC_Ed25519Type; static unsigned char *ed25519Fingerprint(const CC *cond) { Ed25519FingerprintContents_t *fp = calloc(1, sizeof(Ed25519FingerprintContents_t)); + //fprintf(stderr,"ed25519 fingerprint %p %p\n",fp,cond->publicKey); OCTET_STRING_fromBuf(&fp->publicKey, cond->publicKey, 32); return hashFingerprintContents(&asn_DEF_Ed25519FingerprintContents, fp); } @@ -62,7 +63,7 @@ static int ed25519Sign(CC *cond, CCVisitor visitor) { if (cond->type->typeId != CC_Ed25519Type.typeId) return 1; CCEd25519SigningData *signing = (CCEd25519SigningData*) visitor.context; if (0 != memcmp(cond->publicKey, signing->pk, 32)) return 1; - if (!cond->signature) cond->signature = malloc(64); + if (!cond->signature) cond->signature = calloc(1,64); ed25519_sign(cond->signature, visitor.msg, visitor.msgLength, signing->pk, signing->skpk); signing->nSigned++; @@ -141,9 +142,9 @@ static void ed25519ToJSON(const CC *cond, cJSON *params) { static CC *ed25519FromFulfillment(const Fulfillment_t *ffill) { CC *cond = cc_new(CC_Ed25519); - cond->publicKey = malloc(32); + cond->publicKey = calloc(1,32); memcpy(cond->publicKey, ffill->choice.ed25519Sha256.publicKey.buf, 32); - cond->signature = malloc(64); + cond->signature = calloc(1,64); memcpy(cond->signature, ffill->choice.ed25519Sha256.signature.buf, 64); return cond; } diff --git a/src/cryptoconditions/src/eval.c b/src/cryptoconditions/src/eval.c index a2bac4c51..544f6dd54 100644 --- a/src/cryptoconditions/src/eval.c +++ b/src/cryptoconditions/src/eval.c @@ -27,6 +27,7 @@ struct CCType CC_EvalType; static unsigned char *evalFingerprint(const CC *cond) { unsigned char *hash = calloc(1, 32); + //fprintf(stderr,"evalfingerprint %p %p\n",hash,cond->code); sha256(cond->code, cond->codeLength, hash); return hash; } @@ -68,7 +69,7 @@ static CC *evalFromFulfillment(const Fulfillment_t *ffill) { OCTET_STRING_t octets = eval->code; cond->codeLength = octets.size; - cond->code = malloc(octets.size); + cond->code = calloc(1,octets.size); memcpy(cond->code, octets.buf, octets.size); return cond; diff --git a/src/cryptoconditions/src/internal.h b/src/cryptoconditions/src/internal.h index e027176ee..41080186e 100644 --- a/src/cryptoconditions/src/internal.h +++ b/src/cryptoconditions/src/internal.h @@ -28,7 +28,7 @@ extern "C" { #endif -#define BUF_SIZE 1024 * 1024 +#define BUF_SIZE 4096 typedef char bool; @@ -56,8 +56,8 @@ typedef struct CCType { /* * Globals */ -struct CCType *CCTypeRegistry[32]; -int CCTypeRegistryLength; +extern struct CCType *CCTypeRegistry[]; +extern int CCTypeRegistryLength; /* diff --git a/src/cryptoconditions/src/json_rpc.c b/src/cryptoconditions/src/json_rpc.c index 63b5909da..73377af50 100644 --- a/src/cryptoconditions/src/json_rpc.c +++ b/src/cryptoconditions/src/json_rpc.c @@ -17,11 +17,8 @@ #include "internal.h" #include -#ifdef __LP64__ #include -#else -#include // Index into CTransaction.vjoinsplit -#endif + static cJSON *jsonCondition(CC *cond) { cJSON *root = cJSON_CreateObject(); diff --git a/src/cryptoconditions/src/prefix.c b/src/cryptoconditions/src/prefix.c index 97a9d1074..626fc5992 100644 --- a/src/cryptoconditions/src/prefix.c +++ b/src/cryptoconditions/src/prefix.c @@ -26,7 +26,7 @@ struct CCType CC_PrefixType; static int prefixVisitChildren(CC *cond, CCVisitor visitor) { size_t prefixedLength = cond->prefixLength + visitor.msgLength; - unsigned char *prefixed = malloc(prefixedLength); + unsigned char *prefixed = calloc(1,prefixedLength); memcpy(prefixed, cond->prefix, cond->prefixLength); memcpy(prefixed + cond->prefixLength, visitor.msg, visitor.msgLength); visitor.msg = prefixed; @@ -39,6 +39,7 @@ static int prefixVisitChildren(CC *cond, CCVisitor visitor) { static unsigned char *prefixFingerprint(const CC *cond) { PrefixFingerprintContents_t *fp = calloc(1, sizeof(PrefixFingerprintContents_t)); + //fprintf(stderr,"prefixfinger %p %p\n",fp,cond->prefix); asnCondition(cond->subcondition, &fp->subcondition); // TODO: check asnCondition for safety fp->maxMessageLength = cond->maxMessageLength; OCTET_STRING_fromBuf(&fp->prefix, cond->prefix, cond->prefixLength); diff --git a/src/cryptoconditions/src/preimage.c b/src/cryptoconditions/src/preimage.c index 8902817dd..7c8e56996 100644 --- a/src/cryptoconditions/src/preimage.c +++ b/src/cryptoconditions/src/preimage.c @@ -46,6 +46,7 @@ static unsigned long preimageCost(const CC *cond) { static unsigned char *preimageFingerprint(const CC *cond) { unsigned char *hash = calloc(1, 32); + //fprintf(stderr,"preimage %p %p\n",hash,cond->preimage); sha256(cond->preimage, cond->preimageLength, hash); return hash; } diff --git a/src/cryptoconditions/src/secp256k1.c b/src/cryptoconditions/src/secp256k1.c index 78b9c4e9e..a95895fa4 100644 --- a/src/cryptoconditions/src/secp256k1.c +++ b/src/cryptoconditions/src/secp256k1.c @@ -45,9 +45,11 @@ void lockSign() { int read = (int) fread(&ent, 1, 32, fp); fclose(fp); #endif - if (read != 32) { - fprintf(stderr, "Could not read 32 bytes entropy from system\n"); - exit(1); + if (read != 32) + { + int32_t i; + for (i=0; i<32; i++) + ((uint8_t *)ent)[i] = rand(); } if (!secp256k1_context_randomize(ec_ctx_sign, ent)) { fprintf(stderr, "Could not randomize secp256k1 context\n"); @@ -73,6 +75,7 @@ void initVerify() { static unsigned char *secp256k1Fingerprint(const CC *cond) { Secp256k1FingerprintContents_t *fp = calloc(1, sizeof(Secp256k1FingerprintContents_t)); + //fprintf(stderr,"secpfinger %p %p size %d vs %d\n",fp,cond->publicKey,(int32_t)sizeof(Secp256k1FingerprintContents_t),(int32_t)SECP256K1_PK_SIZE); OCTET_STRING_fromBuf(&fp->publicKey, cond->publicKey, SECP256K1_PK_SIZE); return hashFingerprintContents(&asn_DEF_Secp256k1FingerprintContents, fp); } diff --git a/src/cryptoconditions/src/threshold.c b/src/cryptoconditions/src/threshold.c index 88d4e7f50..13c3fdab3 100644 --- a/src/cryptoconditions/src/threshold.c +++ b/src/cryptoconditions/src/threshold.c @@ -86,6 +86,7 @@ static int cmpConditionBin(const void *a, const void *b) { static unsigned char *thresholdFingerprint(const CC *cond) { /* Create fingerprint */ ThresholdFingerprintContents_t *fp = calloc(1, sizeof(ThresholdFingerprintContents_t)); + //fprintf(stderr,"thresholdfinger %p\n",fp); fp->threshold = cond->threshold; for (int i=0; isize; i++) { Condition_t *asnCond = asnConditionNew(cond->subconditions[i]); diff --git a/src/cryptoconditions/src/utils.c b/src/cryptoconditions/src/utils.c index 623331ff7..25783ddfc 100644 --- a/src/cryptoconditions/src/utils.c +++ b/src/cryptoconditions/src/utils.c @@ -39,7 +39,7 @@ static int mod_table[] = {0, 2, 1}; void build_decoding_table() { - decoding_table = malloc(256); + decoding_table = calloc(1,256); for (int i = 0; i < 64; i++) decoding_table[(unsigned char) encoding_table[i]] = i; } @@ -49,7 +49,7 @@ unsigned char *base64_encode(const unsigned char *data, size_t input_length) { size_t output_length = 4 * ((input_length + 2) / 3); - unsigned char *encoded_data = malloc(output_length + 1); + unsigned char *encoded_data = calloc(1,output_length + 1); if (encoded_data == NULL) return NULL; for (int i = 0, j = 0; i < input_length;) { @@ -90,7 +90,7 @@ unsigned char *base64_decode(const unsigned char *data_, size_t input_length = strlen(data_); int rem = input_length % 4; - unsigned char *data = malloc(input_length + (4-rem)); + unsigned char *data = calloc(1,input_length + (4-rem)); strcpy(data, data_); // for unpadded b64 @@ -111,7 +111,7 @@ unsigned char *base64_decode(const unsigned char *data_, if (data[input_length - 1] == '=') (*output_length)--; if (data[input_length - 2] == '=') (*output_length)--; - unsigned char *decoded_data = malloc(*output_length); + unsigned char *decoded_data = calloc(1,*output_length); if (decoded_data == NULL) return NULL; for (int i = 0, j = 0; i < input_length;) { @@ -137,6 +137,7 @@ unsigned char *base64_decode(const unsigned char *data_, void base64_cleanup() { free(decoding_table); + decoding_table = 0; } @@ -217,7 +218,7 @@ unsigned char *hashFingerprintContents(asn_TYPE_descriptor_t *asnType, void *fp) fprintf(stderr, "Encoding fingerprint failed\n"); return 0; } - unsigned char *hash = malloc(32); + unsigned char *hash = calloc(1,32); sha256(buf, rc.encoded, hash); return hash; } @@ -225,7 +226,7 @@ unsigned char *hashFingerprintContents(asn_TYPE_descriptor_t *asnType, void *fp) char* cc_hex_encode(const uint8_t *bin, size_t len) { - char* hex = malloc(len*2+1); + char* hex = calloc(1,len*2+1); if (bin == NULL) return hex; char map[16] = "0123456789ABCDEF"; for (int i=0; i= 10000 sats PoS stake must be without txfee and in the last tx in the block at vout[0] */ -//#define KOMODO_POWMINMULT 16 uint64_t komodo_commission(const CBlock *pblock) { @@ -1135,11 +1134,13 @@ uint32_t komodo_segid32(char *coinaddr) return(addrhash.uints[0]); } -int8_t komodo_segid(int32_t height) +int8_t komodo_segid(int32_t nocache,int32_t height) { CTxDestination voutaddress; CBlock block; CBlockIndex *pindex; uint64_t value; uint32_t txtime; char voutaddr[64],destaddr[64]; int32_t txn_count,vout; uint256 txid; int8_t segid = -1; if ( height > 0 && (pindex= komodo_chainactive(height)) != 0 ) { + if ( nocache == 0 && pindex->segid >= -1 ) + return(pindex->segid); if ( komodo_blockload(block,pindex) == 0 ) { txn_count = block.vtx.size(); @@ -1154,6 +1155,7 @@ int8_t komodo_segid(int32_t height) if ( strcmp(destaddr,voutaddr) == 0 && block.vtx[txn_count-1].vout[0].nValue == value ) { segid = komodo_segid32(voutaddr) & 0x3f; + //fprintf(stderr,"komodo_segid.(%d) -> %02x\n",height,segid); } } else fprintf(stderr,"komodo_segid ht.%d couldnt extract voutaddress\n",height); } @@ -1173,7 +1175,7 @@ int32_t komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n) memset(hashbuf,0xff,n); for (i=0; i prevtime+480 ) coinage *= ((blocktime+iter+segid*2) - (prevtime+400)); - //if ( nHeight >= 2500 && blocktime+iter+segid*2 > prevtime+180 ) - // coinage *= ((blocktime+iter+segid*2) - (prevtime+60)); coinage256 = arith_uint256(coinage+1); hashval = ratio * (UintToArith256(hash) / coinage256); - //if ( nHeight >= 900 && nHeight < 916 ) - // hashval = (hashval / coinage256); if ( hashval <= bnTarget ) { winner = 1; @@ -1308,7 +1299,7 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he continue; if ( (pindex= komodo_chainactive(ht)) != 0 ) { - if ( komodo_segid(ht) >= 0 ) + if ( komodo_segid(0,ht) >= 0 ) { n++; percPoS++; @@ -1323,26 +1314,6 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he m++; } } - /*if ( (pindex= komodo_chainactive(ht)) != 0 ) - { - bnTarget.SetCompact(pindex->nBits,&fNegative,&fOverflow); - bnTarget = (bnTarget / arith_uint256(KOMODO_POWMINMULT)); - hashval = UintToArith256(pindex->GetBlockHash()); - if ( hashval <= bnTarget ) // PoW is never as easy as PoS/16, some PoS will be counted as PoW - { - if ( ASSETCHAINS_STAKED < 100 ) - fprintf(stderr,"1"); - sum += hashval; - n++; - } - else - { - n++; - percPoS++; - if ( ASSETCHAINS_STAKED < 100 ) - fprintf(stderr,"0"); - } - }*/ if ( ASSETCHAINS_STAKED < 100 && (i % 10) == 9 ) fprintf(stderr," %d, ",percPoS); } @@ -1351,20 +1322,21 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he if ( ASSETCHAINS_STAKED < 100 ) fprintf(stderr," -> %d%% percPoS vs goalperc.%d ht.%d\n",percPoS,goalperc,height); *percPoSp = percPoS; - //target = (target / arith_uint256(KOMODO_POWMINMULT)); if ( m > 0 ) { ave = (sum / arith_uint256(m)); if ( ave > target ) ave = target; - } else ave = easydiff; //else return(target); + } else ave = target; //easydiff; //else return(target); if ( percPoS == 0 ) percPoS = 1; if ( percPoS < goalperc ) // increase PoW diff -> lower bnTarget { + //if ( oldflag != 0 ) + // bnTarget = (ave * arith_uint256(percPoS * percPoS)) / arith_uint256(goalperc * goalperc * goalperc); if ( oldflag != 0 ) - bnTarget = (ave * arith_uint256(percPoS * percPoS)) / arith_uint256(goalperc * goalperc * goalperc); - else bnTarget = (ave / arith_uint256(goalperc * goalperc * goalperc)) * arith_uint256(percPoS * percPoS); + bnTarget = (ave / arith_uint256(goalperc * goalperc * goalperc)) * arith_uint256(percPoS * percPoS); + else bnTarget = (ave / arith_uint256(goalperc * goalperc * goalperc * goalperc)) * arith_uint256(percPoS * percPoS); if ( ASSETCHAINS_STAKED < 100 ) { for (i=31; i>=24; i--) @@ -1385,7 +1357,8 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he bnTarget = ((ave * arith_uint256(goalperc)) + (easydiff * arith_uint256(percPoS))) / arith_uint256(percPoS + goalperc); //bnTarget = (bnTarget * arith_uint256(percPoS * percPoS * percPoS)) / arith_uint256(goalperc * goalperc); bnTarget = (bnTarget / arith_uint256(goalperc * goalperc)) * arith_uint256(percPoS * percPoS * percPoS); - } else bnTarget = (ave / arith_uint256(goalperc * goalperc)) * arith_uint256(percPoS * percPoS * percPoS); + } + else bnTarget = (ave / arith_uint256(goalperc * goalperc)) * arith_uint256(percPoS * percPoS * percPoS); if ( bnTarget > easydiff ) bnTarget = easydiff; else if ( bnTarget < ave ) // overflow @@ -1411,11 +1384,18 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he return(bnTarget); } -int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_uint256 bnTarget) +int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_uint256 bnTarget,arith_uint256 bhash) { - CBlockIndex *previndex; char voutaddr[64],destaddr[64]; uint256 txid; uint32_t txtime,prevtime=0; int32_t vout,txn_count,eligible=0,isPoS = 0; uint64_t value; CTxDestination voutaddress; + CBlockIndex *previndex,*pindex; char voutaddr[64],destaddr[64]; uint256 txid; uint32_t txtime,prevtime=0; int32_t vout,PoSperc,txn_count,eligible=0,isPoS = 0,segid; uint64_t value; CTxDestination voutaddress; if ( ASSETCHAINS_STAKED == 100 && height <= 10 ) return(1); + pindex = mapBlockIndex[pblock->GetHash()]; + if ( pindex != 0 && pindex->segid >= -1 ) + { + if ( pindex->segid == -1 ) + return(0); + else return(1); + } txn_count = pblock->vtx.size(); if ( txn_count > 1 && pblock->vtx[txn_count-1].vin.size() == 1 && pblock->vtx[txn_count-1].vout.size() == 1 ) { @@ -1429,29 +1409,59 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_ if ( prevtime != 0 ) { if ( komodo_isPoS(pblock) != 0 ) + { eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime+27,(char *)""); + } if ( eligible == 0 || eligible > pblock->nTime ) { - if ( ASSETCHAINS_STAKED < 100 ) + if ( 0 && ASSETCHAINS_STAKED < 100 ) fprintf(stderr,"komodo_is_PoSblock PoS failure ht.%d eligible.%u vs blocktime.%u, lag.%d -> check to see if it is PoW block\n",height,eligible,(uint32_t)pblock->nTime,(int32_t)(eligible - pblock->nTime)); - } else isPoS = 1; + if ( slowflag != 0 && pindex != 0 ) + { + pindex->segid = -1; + fprintf(stderr,"PoW block detected set segid.%d <- %d\n",height,pindex->segid); + } + } + else + { + isPoS = 2; // 2 means staking utxo validated + if ( slowflag != 0 && height > 100 ) + { + segid = -3; + if ( pindex != 0 && pindex->segid == -2 && (segid= komodo_segid(1,height)) >= 0 ) + { + pindex->segid = segid; + fprintf(stderr,"B set segid.%d <- %d\n",height,pindex->segid); + } //else fprintf(stderr,"unexpected null pindex for slowflag set ht.%d segid.%d:%d\n",height,pindex!=0?pindex->segid:-3,segid); + } + } } - if ( slowflag == 0 ) // maybe previous block is not seen yet, do the best approx + if ( slowflag == 0 && isPoS == 0 ) // maybe previous block is not seen yet, do the best approx { if ( komodo_isPoS(pblock) != 0 ) isPoS = 1; - /*txtime = komodo_txtime(&value,txid,vout,destaddr); - if ( ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) ) + } + if ( slowflag != 0 && isPoS != 0 ) + { + if ( isPoS != 2 ) { - strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); - if ( strcmp(destaddr,voutaddr) == 0 && pblock->vtx[txn_count-1].vout[0].nValue == value ) - isPoS = 1; // close enough for a pre-filter - //else fprintf(stderr,"komodo_is_PoSblock ht.%d (%s) != (%s) or %.8f != %.8f\n",height,destaddr,voutaddr,dstr(value),dstr(pblock->vtx[txn_count-1].vout[0].nValue)); - } else fprintf(stderr,"komodo_is_PoSblock ht.%d couldnt extract voutaddress\n",height);*/ - } //else return(-1); + fprintf(stderr,"ht.%d isPoS.%d utxo not validated -> must be PoW fake\n",height,isPoS); + isPoS = 0; + } + else + { + bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED); + if ( bhash < bnTarget ) + { + fprintf(stderr,"ht.%d isPoS but meets PoW diff!\n",height); + isPoS = 0; + } + } + } + //else return(-1); } //fprintf(stderr,"slow.%d ht.%d isPoS.%d\n",slowflag,height,isPoS); - return(isPoS); + return(isPoS != 0); } int64_t komodo_checkcommission(CBlock *pblock,int32_t height) @@ -1482,6 +1492,8 @@ bool KOMODO_TEST_ASSETCHAIN_SKIP_POW = 0; int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height) { uint256 hash; arith_uint256 bnTarget,bhash; bool fNegative,fOverflow; uint8_t *script,pubkey33[33],pubkeys[64][33]; int32_t i,possible,PoSperc,is_PoSblock=0,n,failed = 0,notaryid = -1; int64_t checktoshis,value; CBlockIndex *pprev; + if ( KOMODO_TEST_ASSETCHAIN_SKIP_POW == 0 && Params().NetworkIDString() == "regtest" ) + KOMODO_TEST_ASSETCHAIN_SKIP_POW = 1; if ( !CheckEquihashSolution(pblock, Params()) ) { fprintf(stderr,"komodo_checkPOW slowflag.%d ht.%d CheckEquihashSolution failed\n",slowflag,height); @@ -1522,13 +1534,13 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height) { if ( KOMODO_TEST_ASSETCHAIN_SKIP_POW ) return(0); - if ( ASSETCHAINS_STAKED == 0 ) // komodo_is_PoSblock will check bnTarget + if ( ASSETCHAINS_STAKED == 0 ) // komodo_is_PoSblock will check bnTarget for staked chains return(-1); } } if ( ASSETCHAINS_STAKED != 0 && height >= 2 ) // must PoS or have at least 16x better PoW { - if ( (is_PoSblock= komodo_is_PoSblock(slowflag,height,pblock,bnTarget)) == 0 ) + if ( (is_PoSblock= komodo_is_PoSblock(slowflag,height,pblock,bnTarget,bhash)) == 0 ) { if ( ASSETCHAINS_STAKED == 100 && height > 100 ) // only PoS allowed! POSTEST64 return(-1); diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 6a8ef310b..20ece62d2 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -755,6 +755,7 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim if ( height > 1 && checktoshis == 0 ) { checktoshis = ((uint64_t)GetBlockSubsidy(height, Params().GetConsensus()) - block.vtx[0].vout[0].nValue); + //checktoshis += txn_count * 0.001; // rely on higher level validations to prevent emitting more coins than actual txfees } if ( height >= 2 && (overflow != 0 || total > checktoshis || strangeout != 0) ) { diff --git a/src/komodo_globals.h b/src/komodo_globals.h index c4ba26eb6..2d64bc8fc 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -45,7 +45,7 @@ struct komodo_state KOMODO_STATES[34]; #define _COINBASE_MATURITY 100 int COINBASE_MATURITY = _COINBASE_MATURITY;//100; -int32_t IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE,KOMODO_PAX,KOMODO_EXCHANGEWALLET,KOMODO_REWIND; +int32_t KOMODO_MININGTHREADS = -1,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE,KOMODO_PAX,KOMODO_EXCHANGEWALLET,KOMODO_REWIND,KOMODO_CONNECTING = -1; int32_t KOMODO_INSYNC,KOMODO_LASTMINED,prevKOMODO_LASTMINED,JUMBLR_PAUSE = 1; std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY; uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE; diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 747a43b72..616f7ecaa 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -1505,6 +1505,9 @@ void komodo_args(char *argv0) extern const char *Notaries_elected1[][2]; std::string name,addn; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[256],*extraptr=0; FILE *fp; uint64_t val; uint16_t port; int32_t i,baseid,len,n,extralen = 0; IS_KOMODO_NOTARY = GetBoolArg("-notary", false); + if ( GetBoolArg("-gen", false) != 0 ) + KOMODO_MININGTHREADS = GetArg("-genproclimit",1); + else KOMODO_MININGTHREADS = -1; if ( (KOMODO_EXCHANGEWALLET= GetBoolArg("-exchange", false)) != 0 ) fprintf(stderr,"KOMODO_EXCHANGEWALLET mode active\n"); DONATION_PUBKEY = GetArg("-donation", ""); diff --git a/src/main.cpp b/src/main.cpp index b42f85ce7..548ce2011 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -56,7 +56,7 @@ using namespace std; CCriticalSection cs_main; extern uint8_t NOTARY_PUBKEY33[33]; -extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN,KOMODO_INSYNC; +extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN,KOMODO_INSYNC,KOMODO_CONNECTING; int32_t KOMODO_NEWBLOCKS; int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); void komodo_broadcast(CBlock *pblock,int32_t limit); @@ -1263,7 +1263,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (pfMissingInputs) *pfMissingInputs = false; - int nextBlockHeight = chainActive.Height() + 1; + int flag=0,nextBlockHeight = chainActive.Height() + 1; auto consensusBranchId = CurrentEpochBranchId(nextBlockHeight, Params().GetConsensus()); // Node operator can choose to reject tx by number of transparent inputs @@ -1285,7 +1285,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } if (!CheckTransaction(tx, state, verifier)) { - return error("AcceptToMemoryPool: CheckTransaction failed"); } // DoS level set to 10 to be more forgiving. @@ -1294,7 +1293,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa { return error("AcceptToMemoryPool: ContextualCheckTransaction failed"); } - + // Coinbase is only valid in a block, not as a loose transaction if (tx.IsCoinBase()) { @@ -1527,12 +1526,20 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // invalid blocks, however allowing such transactions into the mempool // can be exploited as a DoS attack. // XXX: is this neccesary for CryptoConditions? + if ( KOMODO_CONNECTING <= 0 && chainActive.LastTip() != 0 ) + { + flag = 1; + KOMODO_CONNECTING = (1<<30) + (int32_t)chainActive.LastTip()->nHeight + 1; + } if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId)) { - fprintf(stderr,"accept failure.10\n"); + if ( flag != 0 ) + KOMODO_CONNECTING = -1; return error("AcceptToMemoryPool: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s", hash.ToString()); } - + if ( flag != 0 ) + KOMODO_CONNECTING = -1; + // Store transaction in memory if ( komodo_is_notarytx(tx) == 0 ) KOMODO_ON_DEMAND++; @@ -3368,6 +3375,10 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { assert(view.Flush()); DisconnectNotarisations(block); } + pindexDelete->segid = -2; + pindexDelete->newcoins = 0; + pindexDelete->zfunds = 0; + LogPrint("bench", "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001); uint256 anchorAfterDisconnect = pcoinsTip->GetBestAnchor(); // Write the chain state to disk, if necessary. @@ -3444,6 +3455,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * return AbortNode(state, "Failed to read block"); pblock = █ } + KOMODO_CONNECTING = (int32_t)pindexNew->nHeight; // Get the current commitment tree ZCIncrementalMerkleTree oldTree; assert(pcoinsTip->GetAnchorAt(pcoinsTip->GetBestAnchor(), oldTree)); @@ -3454,6 +3466,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * { CCoinsViewCache view(pcoinsTip); bool rv = ConnectBlock(*pblock, state, pindexNew, view, false, true); + KOMODO_CONNECTING = -1; GetMainSignals().BlockChecked(*pblock, state); if (!rv) { if (state.IsInvalid()) @@ -4154,17 +4167,32 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C // Check transactions if ( ASSETCHAINS_CC != 0 ) // CC contracts might refer to transactions in the current block, from a CC spend within the same block and out of order { - CValidationState stateDummy; + CValidationState stateDummy; int32_t i,j,rejects=0,lastrejects=0; //fprintf(stderr,"put block's tx into mempool\n"); - for (int i = 0; i < block.vtx.size(); i++) + while ( 1 ) { - const CTransaction &tx = block.vtx[i]; - if (tx.IsCoinBase() != 0 ) - continue; - else if ( ASSETCHAINS_STAKED != 0 && (i == (block.vtx.size() - 1)) && komodo_isPoS((CBlock *)&block) != 0 ) - continue; - AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL); - } + for (i=0; i all tx in mempool\n",lastrejects); + break; + } + fprintf(stderr,"addtomempool ht.%d for CC checking: n.%d rejects.%d last.%d\n",height,(int32_t)block.vtx.size(),rejects,lastrejects); + lastrejects = rejects; + rejects = 0; + } //fprintf(stderr,"done putting block's tx into mempool\n"); } BOOST_FOREACH(const CTransaction& tx, block.vtx) diff --git a/src/miner.cpp b/src/miner.cpp index fb2eb2d05..874c1b4f8 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -106,7 +106,7 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, #include "komodo_defs.h" -extern int32_t KOMODO_LONGESTCHAIN,ASSETCHAINS_SEED,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAIN_INIT,KOMODO_INITDONE,KOMODO_ON_DEMAND,KOMODO_INITDONE,KOMODO_PASSPORT_INITDONE; +extern int32_t KOMODO_MININGTHREADS,KOMODO_LONGESTCHAIN,ASSETCHAINS_SEED,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAIN_INIT,KOMODO_INITDONE,KOMODO_ON_DEMAND,KOMODO_INITDONE,KOMODO_PASSPORT_INITDONE; extern uint64_t ASSETCHAINS_REWARD,ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED; extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY; @@ -393,7 +393,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) //pblock->nTime = blocktime + 1; pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus()); //LogPrintf("CreateNewBlock(): total size %u blocktime.%u nBits.%08x\n", nBlockSize,blocktime,pblock->nBits); - if ( ASSETCHAINS_SYMBOL[0] != 0 && ASSETCHAINS_STAKED != 0 && GetArg("-genproclimit", 0) == 0 ) + if ( ASSETCHAINS_SYMBOL[0] != 0 && ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0 ) { uint64_t txfees,utxovalue; uint32_t txtime; uint256 utxotxid,revtxid; int32_t i,siglen,numsigs,utxovout; uint8_t utxosig[128],*ptr; CMutableTransaction txStaked = CreateNewContextualCMutableTransaction(Params().GetConsensus(), chainActive.Height() + 1); @@ -453,7 +453,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) // Fill in header pblock->hashPrevBlock = pindexPrev->GetBlockHash(); pblock->hashReserved = uint256(); - if ( ASSETCHAINS_SYMBOL[0] == 0 || ASSETCHAINS_STAKED == 0 || GetArg("-genproclimit", 0) > 0 ) + if ( ASSETCHAINS_SYMBOL[0] == 0 || ASSETCHAINS_STAKED == 0 || KOMODO_MININGTHREADS > 0 ) { UpdateTime(pblock, Params().GetConsensus(), pindexPrev); pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus()); @@ -788,7 +788,7 @@ void static BitcoinMiner() } if (!fvNodesEmpty )//&& !IsInitialBlockDownload()) break; - MilliSleep(5000); + MilliSleep(15000); //fprintf(stderr,"fvNodesEmpty %d IsInitialBlockDownload(%s) %d\n",(int32_t)fvNodesEmpty,ASSETCHAINS_SYMBOL,(int32_t)IsInitialBlockDownload()); } while (true); @@ -950,7 +950,7 @@ void static BitcoinMiner() // (x_1, x_2, ...) = A(I, V, n, k) LogPrint("pow", "Running Equihash solver \"%s\" with nNonce = %s\n",solver, pblock->nNonce.ToString()); arith_uint256 hashTarget; - if ( GetArg("-genproclimit", 0) > 0 && ASSETCHAINS_STAKED > 0 && ASSETCHAINS_STAKED < 100 && Mining_height > 10 ) + if ( KOMODO_MININGTHREADS > 0 && ASSETCHAINS_STAKED > 0 && ASSETCHAINS_STAKED < 100 && Mining_height > 10 ) hashTarget = HASHTarget_POW; else hashTarget = HASHTarget; std::function)> validBlock = @@ -978,7 +978,7 @@ void static BitcoinMiner() fprintf(stderr," POW\n");*/ if ( h > hashTarget ) { - //if ( ASSETCHAINS_STAKED != 0 && GetArg("-genproclimit", 0) == 0 ) + //if ( ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0 ) // sleep(1); return false; } diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index b76698917..7f01c862f 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -121,6 +121,7 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex) result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits))); result.push_back(Pair("difficulty", GetDifficulty(blockindex))); result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); + result.push_back(Pair("segid", (int64_t)blockindex->segid)); if (blockindex->pprev) result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); @@ -146,6 +147,7 @@ UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex) result.push_back(Pair("height", blockindex->nHeight)); result.push_back(Pair("version", block.nVersion)); result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); + result.push_back(Pair("segid", (int64_t)blockindex->segid)); UniValue deltas(UniValue::VARR); @@ -262,6 +264,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx result.push_back(Pair("height", blockindex->nHeight)); result.push_back(Pair("version", block.nVersion)); result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); + result.push_back(Pair("segid", (int64_t)blockindex->segid)); UniValue txs(UniValue::VARR); BOOST_FOREACH(const CTransaction&tx, block.vtx) { @@ -349,7 +352,7 @@ UniValue getdifficulty(const UniValue& params, bool fHelp) bool myIsutxo_spentinmempool(uint256 txid,int32_t vout) { //char *uint256_str(char *str,uint256); char str[65]; - LOCK(mempool.cs); + //LOCK(mempool.cs); BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) { const CTransaction &tx = e.GetTx(); diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 4c4d2eed5..df58a5573 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -33,6 +33,7 @@ using namespace std; extern uint64_t ASSETCHAINS_STAKED; +extern int32_t KOMODO_MININGTHREADS; arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc); /** @@ -327,6 +328,9 @@ UniValue setgenerate(const UniValue& params, bool fHelp) mapArgs["-gen"] = (fGenerate ? "1" : "0"); mapArgs ["-genproclimit"] = itostr(nGenProcLimit); + if ( fGenerate == 0 ) + KOMODO_MININGTHREADS = -1; + else KOMODO_MININGTHREADS = (int32_t)nGenProcLimit; #ifdef ENABLE_WALLET GenerateBitcoins(fGenerate, pwalletMain, nGenProcLimit); #else @@ -382,6 +386,7 @@ UniValue getmininginfo(const UniValue& params, bool fHelp) obj.push_back(Pair("chain", Params().NetworkIDString())); #ifdef ENABLE_MINING obj.push_back(Pair("generate", getgenerate(params, false))); + obj.push_back(Pair("numthreads", (int64_t)KOMODO_MININGTHREADS)); #endif return obj; } @@ -647,7 +652,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) pblocktemplate = CreateNewBlockWithKey(); #endif if (!pblocktemplate) - throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); + throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory or no available utxo for staking"); // Need to update only after we know CreateNewBlockWithKey succeeded pindexPrev = pindexPrevNew; diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 4295d4ddc..c2e02ad25 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -952,7 +952,7 @@ bool EvalScript( if (stack.size() < 2) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); - +//fprintf(stderr,"check cryptocondition\n"); int fResult = checker.CheckCryptoCondition(stacktop(-1), stacktop(-2), script, consensusBranchId); if (fResult == -1) { return set_error(serror, SCRIPT_ERR_CRYPTOCONDITION_INVALID_FULFILLMENT); @@ -1313,19 +1313,20 @@ int TransactionSignatureChecker::CheckCryptoCondition( } catch (logic_error ex) { return 0; } - //int32_t z; uint8_t *ptr; - //ptr = (uint8_t *)scriptCode.data(); - //for (z=0; zCheckEvalCondition(cond); }; - + //fprintf(stderr,"non-checker path\n"); int out = cc_verify(cond, (const unsigned char*)&sighash, 32, 0, condBin.data(), condBin.size(), eval, (void*)this); //fprintf(stderr,"out.%d from cc_verify\n",(int32_t)out); diff --git a/src/script/serverchecker.cpp b/src/script/serverchecker.cpp index 4de69001a..e82fd3a81 100644 --- a/src/script/serverchecker.cpp +++ b/src/script/serverchecker.cpp @@ -102,5 +102,6 @@ bool ServerTransactionSignatureChecker::VerifySignature(const std::vectorSeekToLast(); iter->Valid(); iter->Prev()) { boost::this_thread::interruption_point(); @@ -487,7 +487,7 @@ extern UniValue CBlockTreeDB::Snapshot(int top) } UniValue addresses(UniValue::VARR); - fprintf(stderr, "total=%f, totalAddresses=%li, utxos=%li, ignored=%li\n", (double) total / COIN, totalAddresses, utxos, ignoredAddresses); + //fprintf(stderr, "total=%f, totalAddresses=%li, utxos=%li, ignored=%li\n", (double) total / COIN, totalAddresses, utxos, ignoredAddresses); for (std::pair element : addressAmounts) { vaddr.push_back( make_pair(element.second, element.first) ); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index c2e486a05..05faaeeb1 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -38,6 +38,8 @@ #include +#define ERR_RESULT(x) result.push_back(Pair("result", "error")) , result.push_back(Pair("error", x)); + using namespace std; using namespace libzcash; @@ -49,6 +51,7 @@ uint32_t komodo_segid32(char *coinaddr); int64_t nWalletUnlockTime; static CCriticalSection cs_nWalletUnlockTime; +std::string CCerror; // Private method: UniValue z_getoperationstatus_IMPL(const UniValue&, bool); @@ -4925,11 +4928,13 @@ UniValue diceaddress(const UniValue& params, bool fHelp) UniValue faucetaddress(const UniValue& params, bool fHelp) { struct CCcontract_info *cp,C; std::vector pubkey; + int errno; cp = CCinit(&C,EVAL_FAUCET); if ( fHelp || params.size() > 1 ) throw runtime_error("faucetaddress [pubkey]\n"); - if ( ensure_CCrequirements() < 0 ) - throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + errno = ensure_CCrequirements(); + if ( errno < 0 ) + throw runtime_error(strprintf("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet. ERR=%d\n", errno)); if ( params.size() == 1 ) pubkey = ParseHex(params[0].get_str().c_str()); return(CCaddress(cp,(char *)"Faucet",pubkey)); @@ -4995,13 +5000,13 @@ UniValue rewardscreatefunding(const UniValue& params, bool fHelp) { result.push_back(Pair("result", "success")); result.push_back(Pair("hex", hex)); - } else result.push_back(Pair("error", "couldnt create rewards funding transaction")); + } else ERR_RESULT("couldnt create rewards funding transaction"); return(result); } UniValue rewardslock(const UniValue& params, bool fHelp) { - UniValue result(UniValue::VOBJ); char *name; uint256 fundingtxid; uint64_t amount; std::string hex; + UniValue result(UniValue::VOBJ); char *name; uint256 fundingtxid; int64_t amount; std::string hex; if ( fHelp || params.size() != 3 ) throw runtime_error("rewardslock name fundingtxid amount\n"); if ( ensure_CCrequirements() < 0 ) @@ -5012,17 +5017,19 @@ UniValue rewardslock(const UniValue& params, bool fHelp) fundingtxid = Parseuint256((char *)params[1].get_str().c_str()); amount = atof(params[2].get_str().c_str()) * COIN; hex = RewardsLock(0,name,fundingtxid,amount); - if ( hex.size() > 0 ) - { - result.push_back(Pair("result", "success")); - result.push_back(Pair("hex", hex)); - } else result.push_back(Pair("error", "couldnt create rewards lock transaction")); + if ( amount > 0 ) { + if ( hex.size() > 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } else ERR_RESULT( "couldnt create rewards lock transaction"); + } else ERR_RESULT("amount must be positive"); return(result); } UniValue rewardsaddfunding(const UniValue& params, bool fHelp) { - UniValue result(UniValue::VOBJ); char *name; uint256 fundingtxid; uint64_t amount; std::string hex; + UniValue result(UniValue::VOBJ); char *name; uint256 fundingtxid; int64_t amount; std::string hex; if ( fHelp || params.size() != 3 ) throw runtime_error("rewardsaddfunding name fundingtxid amount\n"); if ( ensure_CCrequirements() < 0 ) @@ -5033,18 +5040,26 @@ UniValue rewardsaddfunding(const UniValue& params, bool fHelp) fundingtxid = Parseuint256((char *)params[1].get_str().c_str()); amount = atof(params[2].get_str().c_str()) * COIN; hex = RewardsAddfunding(0,name,fundingtxid,amount); - if ( hex.size() > 0 ) - { - result.push_back(Pair("result", "success")); - result.push_back(Pair("hex", hex)); - } else result.push_back(Pair("error", "couldnt create rewards addfunding transaction")); + if (amount > 0) { + if ( hex.size() > 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } else { + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "couldnt create rewards addfunding transaction")); + } + } else { + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "funding amount must be positive")); + } return(result); } UniValue rewardsunlock(const UniValue& params, bool fHelp) { UniValue result(UniValue::VOBJ); std::string hex; char *name; uint256 fundingtxid,txid; - if ( fHelp || params.size() > 3 ) + if ( fHelp || params.size() > 3 || params.size() < 2 ) throw runtime_error("rewardsunlock name fundingtxid [txid]\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); @@ -5056,11 +5071,12 @@ UniValue rewardsunlock(const UniValue& params, bool fHelp) txid = Parseuint256((char *)params[2].get_str().c_str()); else memset(&txid,0,sizeof(txid)); hex = RewardsUnlock(0,name,fundingtxid,txid); - if ( hex.size() > 0 ) - { + if (CCerror != "") { + ERR_RESULT(CCerror); + } else if ( hex.size() > 0 ) { result.push_back(Pair("result", "success")); result.push_back(Pair("hex", hex)); - } else result.push_back(Pair("error", "couldnt create rewards unlock transaction")); + } else ERR_RESULT("couldnt create rewards unlock transaction"); return(result); } @@ -5138,7 +5154,7 @@ UniValue faucetinfo(const UniValue& params, bool fHelp) UniValue faucetfund(const UniValue& params, bool fHelp) { - UniValue result(UniValue::VOBJ); uint64_t funds; std::string hex; + UniValue result(UniValue::VOBJ); int64_t funds; std::string hex; if ( fHelp || params.size() > 1 ) throw runtime_error("faucetfund amount\n"); if ( ensure_CCrequirements() < 0 ) @@ -5146,12 +5162,14 @@ UniValue faucetfund(const UniValue& params, bool fHelp) const CKeyStore& keystore = *pwalletMain; LOCK2(cs_main, pwalletMain->cs_wallet); funds = atof(params[0].get_str().c_str()) * COIN; - hex = FaucetFund(0,funds); - if ( hex.size() > 0 ) - { - result.push_back(Pair("result", "success")); - result.push_back(Pair("hex", hex)); - } else result.push_back(Pair("error", "couldnt create faucet funding transaction")); + if (funds > 0) { + hex = FaucetFund(0,(uint64_t) funds); + if ( hex.size() > 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } else ERR_RESULT("couldnt create faucet funding transaction"); + } else ERR_RESULT( "funding amount must be positive"); return(result); } @@ -5165,11 +5183,10 @@ UniValue faucetget(const UniValue& params, bool fHelp) const CKeyStore& keystore = *pwalletMain; LOCK2(cs_main, pwalletMain->cs_wallet); hex = FaucetGet(0); - if ( hex.size() > 0 ) - { + if ( hex.size() > 0 ) { result.push_back(Pair("result", "success")); result.push_back(Pair("hex", hex)); - } else result.push_back(Pair("error", "couldnt create faucet get transaction")); + } else ERR_RESULT("couldnt create faucet get transaction"); return(result); } @@ -5189,17 +5206,20 @@ UniValue dicefund(const UniValue& params, bool fHelp) maxodds = atol(params[4].get_str().c_str()); timeoutblocks = atol(params[5].get_str().c_str()); hex = DiceCreateFunding(0,name,funds,minbet,maxbet,maxodds,timeoutblocks); - if ( hex.size() > 0 ) - { + if (CCerror != "") { + ERR_RESULT(CCerror); + } else if ( hex.size() > 0 ) { result.push_back(Pair("result", "success")); result.push_back(Pair("hex", hex)); - } else result.push_back(Pair("error", "couldnt create dice funding transaction")); + } else { + ERR_RESULT( "couldnt create dice funding transaction"); + } return(result); } UniValue diceaddfunds(const UniValue& params, bool fHelp) { - UniValue result(UniValue::VOBJ); char *name; uint256 fundingtxid; uint64_t amount; std::string hex; + UniValue result(UniValue::VOBJ); char *name; uint256 fundingtxid; int64_t amount; std::string hex; if ( fHelp || params.size() != 3 ) throw runtime_error("diceaddfunds name fundingtxid amount\n"); if ( ensure_CCrequirements() < 0 ) @@ -5209,18 +5229,21 @@ UniValue diceaddfunds(const UniValue& params, bool fHelp) name = (char *)params[0].get_str().c_str(); fundingtxid = Parseuint256((char *)params[1].get_str().c_str()); amount = atof(params[2].get_str().c_str()) * COIN; - hex = DiceAddfunding(0,name,fundingtxid,amount); - if ( hex.size() > 0 ) - { - result.push_back(Pair("result", "success")); - result.push_back(Pair("hex", hex)); - } else result.push_back(Pair("error", "couldnt create dice addfunding transaction")); + if ( amount > 0 ) { + hex = DiceAddfunding(0,name,fundingtxid,amount); + if (CCerror != "") { + ERR_RESULT(CCerror); + } else if ( hex.size() > 0 ) { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } else ERR_RESULT("couldnt create dice addfunding transaction"); + } else ERR_RESULT("amount must be positive"); return(result); } UniValue dicebet(const UniValue& params, bool fHelp) { - UniValue result(UniValue::VOBJ); std::string hex; uint256 fundingtxid; uint64_t amount,odds; char *name; + UniValue result(UniValue::VOBJ); std::string hex; uint256 fundingtxid; int64_t amount,odds; char *name; if ( fHelp || params.size() != 4 ) throw runtime_error("dicebet name fundingtxid amount odds\n"); if ( ensure_CCrequirements() < 0 ) @@ -5231,18 +5254,22 @@ UniValue dicebet(const UniValue& params, bool fHelp) fundingtxid = Parseuint256((char *)params[1].get_str().c_str()); amount = atof(params[2].get_str().c_str()) * COIN; odds = atol(params[3].get_str().c_str()); - hex = DiceBet(0,name,fundingtxid,amount,odds); - if ( hex.size() > 0 ) - { - result.push_back(Pair("result", "success")); - result.push_back(Pair("hex", hex)); - } else result.push_back(Pair("error", "couldnt create faucet get transaction")); + if (amount > 0 && odds > 0) { + hex = DiceBet(0,name,fundingtxid,amount,odds); + if ( hex.size() > 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } else ERR_RESULT("couldnt create faucet get transaction"); + } else { + ERR_RESULT("amount and odds must be positive"); + } return(result); } UniValue dicefinish(const UniValue& params, bool fHelp) { - UniValue result(UniValue::VOBJ); char *name; uint256 fundingtxid,bettxid; uint64_t amount; std::string hex; int32_t r; + UniValue result(UniValue::VOBJ); char *name; uint256 fundingtxid,bettxid; std::string hex; int32_t r; if ( fHelp || params.size() != 3 ) throw runtime_error("dicefinish name fundingtxid bettxid\n"); if ( ensure_CCrequirements() < 0 ) @@ -5257,13 +5284,13 @@ UniValue dicefinish(const UniValue& params, bool fHelp) { result.push_back(Pair("result", "success")); result.push_back(Pair("hex", hex)); - } else result.push_back(Pair("error", "couldnt create dicefinish transaction")); + } else ERR_RESULT( "couldnt create dicefinish transaction"); return(result); } UniValue dicestatus(const UniValue& params, bool fHelp) { - UniValue result(UniValue::VOBJ); char *name; uint256 fundingtxid,bettxid; uint64_t amount; std::string status; double winnings; + UniValue result(UniValue::VOBJ); char *name; uint256 fundingtxid,bettxid; std::string status; double winnings; if ( fHelp || (params.size() != 2 && params.size() != 3) ) throw runtime_error("dicestatus name fundingtxid bettxid\n"); if ( ensure_CCrequirements() < 0 ) @@ -5298,7 +5325,7 @@ UniValue dicestatus(const UniValue& params, bool fHelp) result.push_back(Pair("status", "loss")); else result.push_back(Pair("status", "no pending bets")); } - } else result.push_back(Pair("status", "invalid bet txid")); + } else result.push_back(Pair("status", "bet still pending")); return(result); } @@ -5390,20 +5417,32 @@ UniValue tokencreate(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); name = params[0].get_str(); supply = atof(params[1].get_str().c_str()) * COIN; + if ( name.size() == 0 || supply <= 0 ) + { + result.push_back(Pair("error", "invalid parameter")); + return(result); + } if ( params.size() == 3 ) + { description = params[2].get_str(); + if ( description.size() > 4096 ) + { + result.push_back(Pair("error", "token description longer than 4096")); + return(result); + } + } hex = CreateAsset(0,supply,name,description); if ( hex.size() > 0 ) { result.push_back(Pair("result", "success")); result.push_back(Pair("hex", hex)); - } else result.push_back(Pair("error", "couldnt create transaction")); + } else ERR_RESULT("couldnt create transaction"); return(result); } UniValue tokentransfer(const UniValue& params, bool fHelp) { - UniValue result(UniValue::VOBJ); std::string hex; uint64_t amount; uint256 tokenid; + UniValue result(UniValue::VOBJ); std::string hex; int64_t amount; uint256 tokenid; if ( fHelp || params.size() != 3 ) throw runtime_error("tokentransfer tokenid destpubkey amount\n"); if ( ensure_CCrequirements() < 0 ) @@ -5413,18 +5452,27 @@ UniValue tokentransfer(const UniValue& params, bool fHelp) tokenid = Parseuint256((char *)params[0].get_str().c_str()); std::vector pubkey(ParseHex(params[1].get_str().c_str())); amount = atol(params[2].get_str().c_str()); - hex = AssetTransfer(0,tokenid,pubkey,amount); - if ( hex.size() > 0 ) + if ( tokenid == zeroid || amount <= 0 ) { - result.push_back(Pair("result", "success")); - result.push_back(Pair("hex", hex)); - } else result.push_back(Pair("error", "couldnt transfer assets")); + result.push_back(Pair("error", "invalid parameter")); + return(result); + } + hex = AssetTransfer(0,tokenid,pubkey,amount); + if (amount > 0) { + if ( hex.size() > 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } else ERR_RESULT("couldnt transfer assets"); + } else { + ERR_RESULT("amount must be positive"); + } return(result); } UniValue tokenbid(const UniValue& params, bool fHelp) { - UniValue result(UniValue::VOBJ); uint64_t bidamount,numtokens; std::string hex; double price; uint256 tokenid; + UniValue result(UniValue::VOBJ); int64_t bidamount,numtokens; std::string hex; double price; uint256 tokenid; if ( fHelp || params.size() != 3 ) throw runtime_error("tokenbid numtokens tokenid price\n"); if ( ensure_CCrequirements() < 0 ) @@ -5435,12 +5483,21 @@ UniValue tokenbid(const UniValue& params, bool fHelp) tokenid = Parseuint256((char *)params[1].get_str().c_str()); price = atof(params[2].get_str().c_str()); bidamount = (price * numtokens) * COIN + 0.0000000049999; - hex = CreateBuyOffer(0,bidamount,tokenid,numtokens); - if ( hex.size() > 0 ) + if ( tokenid == zeroid || tokenid == zeroid || price <= 0 || bidamount <= 0 ) { - result.push_back(Pair("result", "success")); - result.push_back(Pair("hex", hex)); - } else result.push_back(Pair("error", "couldnt create bid")); + result.push_back(Pair("error", "invalid parameter")); + return(result); + } + hex = CreateBuyOffer(0,bidamount,tokenid,numtokens); + if (price > 0 && numtokens > 0) { + if ( hex.size() > 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } else result.push_back(Pair("error", "couldnt create bid")); + } else { + ERR_RESULT("price and numtokens must be positive"); + } return(result); } @@ -5455,12 +5512,17 @@ UniValue tokencancelbid(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); tokenid = Parseuint256((char *)params[0].get_str().c_str()); bidtxid = Parseuint256((char *)params[1].get_str().c_str()); + if ( tokenid == zeroid || bidtxid == zeroid ) + { + result.push_back(Pair("error", "invalid parameter")); + return(result); + } hex = CancelBuyOffer(0,tokenid,bidtxid); if ( hex.size() > 0 ) { result.push_back(Pair("result", "success")); result.push_back(Pair("hex", hex)); - } else result.push_back(Pair("error", "couldnt cancel bid")); + } else ERR_RESULT("couldnt cancel bid"); return(result); } @@ -5476,18 +5538,23 @@ UniValue tokenfillbid(const UniValue& params, bool fHelp) tokenid = Parseuint256((char *)params[0].get_str().c_str()); bidtxid = Parseuint256((char *)params[1].get_str().c_str()); fillamount = atol(params[2].get_str().c_str()); + if ( tokenid == zeroid || bidtxid == zeroid || fillamount <= 0 ) + { + result.push_back(Pair("error", "invalid parameter")); + return(result); + } hex = FillBuyOffer(0,tokenid,bidtxid,fillamount); if ( hex.size() > 0 ) { result.push_back(Pair("result", "success")); result.push_back(Pair("hex", hex)); - } else result.push_back(Pair("error", "couldnt fill bid")); + } else ERR_RESULT("couldnt fill bid"); return(result); } UniValue tokenask(const UniValue& params, bool fHelp) { - UniValue result(UniValue::VOBJ); uint64_t askamount,numtokens; std::string hex; double price; uint256 tokenid; + UniValue result(UniValue::VOBJ); int64_t askamount,numtokens; std::string hex; double price; uint256 tokenid; if ( fHelp || params.size() != 3 ) throw runtime_error("tokenask numtokens tokenid price\n"); if ( ensure_CCrequirements() < 0 ) @@ -5498,19 +5565,28 @@ UniValue tokenask(const UniValue& params, bool fHelp) tokenid = Parseuint256((char *)params[1].get_str().c_str()); price = atof(params[2].get_str().c_str()); askamount = (price * numtokens) * COIN + 0.0000000049999; - hex = CreateSell(0,numtokens,tokenid,askamount); - if ( hex.size() > 0 ) + if ( tokenid == zeroid || numtokens <= 0 || price <= 0 || askamount <= 0 ) { - result.push_back(Pair("result", "success")); - result.push_back(Pair("hex", hex)); - } else result.push_back(Pair("error", "couldnt create ask")); + result.push_back(Pair("error", "invalid parameter")); + return(result); + } + hex = CreateSell(0,numtokens,tokenid,askamount); + if (price > 0 && numtokens > 0) { + if ( hex.size() > 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } else ERR_RESULT("couldnt create ask"); + } else { + ERR_RESULT("price and numtokens must be positive"); + } return(result); } UniValue tokenswapask(const UniValue& params, bool fHelp) { static uint256 zeroid; - UniValue result(UniValue::VOBJ); uint64_t askamount,numtokens; std::string hex; double price; uint256 tokenid,otherid; + UniValue result(UniValue::VOBJ); int64_t askamount,numtokens; std::string hex; double price; uint256 tokenid,otherid; if ( fHelp || params.size() != 4 ) throw runtime_error("tokenswapask numtokens tokenid otherid price\n"); if ( ensure_CCrequirements() < 0 ) @@ -5523,11 +5599,15 @@ UniValue tokenswapask(const UniValue& params, bool fHelp) price = atof(params[3].get_str().c_str()); askamount = (price * numtokens); hex = CreateSwap(0,numtokens,tokenid,otherid,askamount); - if ( hex.size() > 0 ) - { - result.push_back(Pair("result", "success")); - result.push_back(Pair("hex", hex)); - } else result.push_back(Pair("error", "couldnt create swap")); + if (price > 0 && numtokens > 0) { + if ( hex.size() > 0 ) + { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } else ERR_RESULT("couldnt create swap"); + } else { + ERR_RESULT("price and numtokens must be positive"); + } return(result); } @@ -5542,18 +5622,22 @@ UniValue tokencancelask(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); tokenid = Parseuint256((char *)params[0].get_str().c_str()); asktxid = Parseuint256((char *)params[1].get_str().c_str()); + if ( tokenid == zeroid || asktxid == zeroid ) + { + result.push_back(Pair("error", "invalid parameter")); + return(result); + } hex = CancelSell(0,tokenid,asktxid); if ( hex.size() > 0 ) { result.push_back(Pair("result", "success")); result.push_back(Pair("hex", hex)); - } else result.push_back(Pair("error", "couldnt cancel bid")); + } else ERR_RESULT("couldnt cancel ask"); return(result); } UniValue tokenfillask(const UniValue& params, bool fHelp) { - static uint256 zeroid; UniValue result(UniValue::VOBJ); uint64_t fillunits; std::string hex; uint256 tokenid,asktxid; if ( fHelp || params.size() != 3 ) throw runtime_error("tokenfillask tokenid asktxid fillunits\n"); @@ -5564,19 +5648,31 @@ UniValue tokenfillask(const UniValue& params, bool fHelp) tokenid = Parseuint256((char *)params[0].get_str().c_str()); asktxid = Parseuint256((char *)params[1].get_str().c_str()); fillunits = atol(params[2].get_str().c_str()); - hex = FillSell(0,tokenid,zeroid,asktxid,fillunits); - if ( hex.size() > 0 ) + if ( tokenid == zeroid || asktxid == zeroid || fillunits <= 0 ) { - result.push_back(Pair("result", "success")); - result.push_back(Pair("hex", hex)); - } else result.push_back(Pair("error", "couldnt fill bid")); + result.push_back(Pair("error", "invalid parameter")); + return(result); + } + hex = FillSell(0,tokenid,zeroid,asktxid,fillunits); + if (fillunits > 0) { + if (CCerror != "") { + ERR_RESULT(CCerror); + } else if ( hex.size() > 0) { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } else { + ERR_RESULT("couldnt fill bid"); + } + } else { + ERR_RESULT("fillunits must be positive"); + } return(result); } UniValue tokenfillswap(const UniValue& params, bool fHelp) { static uint256 zeroid; - UniValue result(UniValue::VOBJ); uint64_t fillunits; std::string hex; uint256 tokenid,otherid,asktxid; + UniValue result(UniValue::VOBJ); int64_t fillunits; std::string hex; uint256 tokenid,otherid,asktxid; if ( fHelp || params.size() != 4 ) throw runtime_error("tokenfillswap tokenid otherid asktxid fillunits\n"); if ( ensure_CCrequirements() < 0 ) @@ -5588,11 +5684,14 @@ UniValue tokenfillswap(const UniValue& params, bool fHelp) asktxid = Parseuint256((char *)params[2].get_str().c_str()); fillunits = atol(params[3].get_str().c_str()); hex = FillSell(0,tokenid,otherid,asktxid,fillunits); - if ( hex.size() > 0 ) - { - result.push_back(Pair("result", "success")); - result.push_back(Pair("hex", hex)); - } else result.push_back(Pair("error", "couldnt fill bid")); + if (fillunits > 0) { + if ( hex.size() > 0 ) { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hex", hex)); + } else ERR_RESULT("couldnt fill bid"); + } else { + ERR_RESULT("fillunits must be positive"); + } return(result); }