Merge pull request #819 from jl777/beta

Height 1 million Release Candidate
This commit is contained in:
jl777
2018-08-20 21:47:39 -11:00
committed by GitHub
53 changed files with 1287 additions and 507 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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=

View File

@@ -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

View File

@@ -11,6 +11,7 @@ export BITCOIND=${REAL_BITCOIND}
#Run the tests
testScripts=(
'cryptoconditions.py'
'paymentdisclosure.py'
'prioritisetransaction.py'
'wallet_treestate.py'

View File

@@ -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}"

View File

@@ -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
```

337
qa/rpc-tests/cryptoconditions.py Executable file
View File

@@ -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 ()

View File

@@ -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):

View File

@@ -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) ]

View File

@@ -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);

View File

@@ -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<uint8_t> destpubkey,int64_t total)
@@ -208,7 +210,7 @@ std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector<uint8_t> 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<uint8_t> 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<uint8_t> 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("");
}

View File

@@ -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

View File

@@ -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();

View File

@@ -28,6 +28,7 @@
#include <univalue.h>
#include <exception>
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<uint8_t> 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<uint8_t> 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<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs,char *coinaddr);
void SetCCtxids(std::vector<std::pair<CAddressIndexKey, CAmount> > &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

View File

@@ -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

View File

@@ -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);

View File

@@ -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<n; i++)
{
@@ -188,7 +188,7 @@ void SetCCtxids(std::vector<std::pair<CAddressIndexKey, CAmount> > &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<std::pair<CAddressUnspentKey, CAddressUnspentValue> > 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<COutput> 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<COutput> 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<mtx.vin.size(); i++)
if ( txid == mtx.vin[i].prevout.hash && vout == mtx.vin[i].prevout.n )
break;
if ( i != mtx.vin.size() )
continue;
if ( myIsutxo_spentinmempool(txid,vout) == 0 )
if ( GetTransaction(txid,tx,hashBlock,false) != 0 && tx.vout.size() > 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<mtx.vin.size(); i++)
if ( txid == mtx.vin[i].prevout.hash && vout == mtx.vin[i].prevout.n )
break;
if ( i != mtx.vin.size() )
continue;
}
if ( n > 0 )
{
for (i=0; i<n; i++)
if ( txid == utxos[i].txid && vout == utxos[i].vout )
break;
if ( i != n )
continue;
}
if ( myIsutxo_spentinmempool(txid,vout) == 0 )
{
up = &utxos[n++];
up->txid = txid;
up->nValue = out.tx->vout[out.i].nValue;
up->vout = vout;
if ( n >= maxutxos )
break;
}
}
}
}
remains = total;
for (i=0; i<maxinputs; i++)
for (i=0; i<maxinputs && n>0; 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;
}

View File

@@ -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<uint8_t> 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<uint8_t> origpubkey;
CTransaction createTx; uint256 assetid,assetid2,hashBlock; uint8_t funcid; int32_t height,i,n,from_mempool = 0; int64_t amount; std::vector<uint8_t> 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 )

View File

@@ -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<numvins; i++)
@@ -118,9 +118,9 @@ bool AuctionValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t
// helper functions for rpc calls in rpcwallet.cpp
uint64_t AddAuctionInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint64_t total,int32_t maxinputs)
int64_t AddAuctionInputs(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<uint8_t> origpubkey; CTransaction vintx; int32_t n = 0;
char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector<uint8_t> origpubkey; CTransaction vintx; int32_t n = 0;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > 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("");
}

View File

@@ -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; i<numvouts; i++)
{
//fprintf(stderr,"i.%d of numvouts.%d\n",i,numvouts);
if ( (assetoshis= IsDicevout(cp,tx,i)) != 0 )
if ( (assetoshis= IsDicevout(cp,tx,i,refsbits,reffundingtxid)) != 0 )
outputs += assetoshis;
}
return(inputs - outputs);
@@ -415,6 +461,8 @@ bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx)
return eval->Invalid("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<std::pair<CAddressUnspentKey, CAddressUnspentValue> > 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<std::pair<CAddressUnspentKey, CAddressUnspentValue> > 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.);
}

View File

@@ -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;

View File

@@ -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; i<numvins; i++)
@@ -69,17 +69,18 @@ bool FaucetExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction
if ( (assetoshis= IsFaucetvout(cp,tx,i)) != 0 )
outputs += assetoshis;
}
if ( inputs != outputs+COIN+txfee )
if ( inputs != outputs+FAUCETSIZE+txfee )
{
fprintf(stderr,"inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs);
return eval->Invalid("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<std::pair<CAddressIndexKey, CAmount> > 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; i<numvins; i++)
{
if ( IsCCInput(tx.vin[0].scriptSig) == 0 )
@@ -110,8 +110,24 @@ bool FaucetValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx
preventCCvouts++;
i = 1;
} else i = 0;
if ( tx.vout[i].nValue != COIN )
txid = tx.GetHash();
memcpy(hash,&txid,sizeof(hash));
fprintf(stderr,"check faucetget txid %s %02x/%02x\n",uint256_str(str,txid),hash[0],hash[31]);
if ( tx.vout[i].nValue != FAUCETSIZE )
return eval->Invalid("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<std::pair<CAddressIndexKey, CAmount> >::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<uint8_t> origpubkey; CTransaction vintx; int32_t vout,n = 0;
char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector<uint8_t> origpubkey; CTransaction vintx; int32_t vout,n = 0;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > 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);

View File

@@ -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<numvins; i++)
@@ -118,9 +118,9 @@ bool FSMValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx)
// helper functions for rpc calls in rpcwallet.cpp
uint64_t AddFSMInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint64_t total,int32_t maxinputs)
int64_t AddFSMInputs(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<uint8_t> origpubkey; CTransaction vintx; int32_t n = 0;
char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector<uint8_t> origpubkey; CTransaction vintx; int32_t n = 0;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > 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("");
}

View File

@@ -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<numvins; i++)
@@ -118,9 +118,9 @@ bool LottoValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx)
// helper functions for rpc calls in rpcwallet.cpp
uint64_t AddLottoInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint64_t total,int32_t maxinputs)
int64_t AddLottoInputs(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<uint8_t> origpubkey; CTransaction vintx; int32_t n = 0;
char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector<uint8_t> origpubkey; CTransaction vintx; int32_t n = 0;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > 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("");
}

View File

@@ -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; i<numvins; i++)
@@ -164,7 +175,7 @@ bool RewardsExactAmounts(struct CCcontract_info *cp,Eval *eval,const CTransactio
{
if ( hashBlock == zerohash )
return eval->Invalid("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; i<numvouts; i++)
{
//fprintf(stderr,"i.%d of numvouts.%d\n",i,numvouts);
if ( (assetoshis= IsRewardsvout(cp,tx,i)) != 0 )
if ( (assetoshis= IsRewardsvout(cp,tx,i,refsbits,reffundingtxid)) != 0 )
outputs += assetoshis;
}
if ( inputs != outputs+txfee )
{
fprintf(stderr,"inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs);
fprintf(stderr,"inputs %llu vs outputs %llu txfee %llu\n",(long long)inputs,(long long)outputs,(long long)txfee);
return eval->Invalid("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; i<numvins; i++)
{
if ( (*cp->ismyvin)(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<std::pair<CAddressUnspentKey, CAddressUnspentValue> > 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; j<mtx.vin.size(); j++)
if ( txid == mtx.vin[j].prevout.hash && vout == mtx.vin[j].prevout.n )
break;
@@ -286,14 +341,19 @@ uint64_t AddRewardsInputs(CScript &scriptPubKey,int32_t fundsflag,struct CCcontr
{
if ( (funcid= DecodeRewardsOpRet(txid,tx.vout[tx.vout.size()-1].scriptPubKey,sbits,fundingtxid)) != 0 )
{
fprintf(stderr,"fundsflag.%d (%c) %.8f %.8f\n",fundsflag,funcid,(double)tx.vout[vout].nValue/COIN,(double)it->second.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<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
lockedfunds = 0;
GetCCaddress(cp,coinaddr,pk);
SetCCunspents(unspentOutputs,coinaddr);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::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("");
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -29,11 +29,7 @@
#include "src/json_rpc.c"
#include <cJSON.h>
#ifdef __LP64__
#include <stdlib.h>
#else
#include <malloc.h> // 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;

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
/*

View File

@@ -17,11 +17,8 @@
#include "internal.h"
#include <cJSON.h>
#ifdef __LP64__
#include <stdlib.h>
#else
#include <malloc.h> // Index into CTransaction.vjoinsplit
#endif
static cJSON *jsonCondition(CC *cond) {
cJSON *root = cJSON_CreateObject();

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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; i<cond->size; i++) {
Condition_t *asnCond = asnConditionNew(cond->subconditions[i]);

View File

@@ -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<len; i++) {

View File

@@ -427,7 +427,7 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar
errs++;
if ( fwrite(opretbuf,1,olen,fp) != olen )
errs++;
printf("create ht.%d R opret[%d] sp.%p\n",height,olen,sp);
//printf("create ht.%d R opret[%d] sp.%p\n",height,olen,sp);
//komodo_opreturn(height,opretvalue,opretbuf,olen,txhash,vout);
komodo_eventadd_opreturn(sp,symbol,height,txhash,opretvalue,vout,opretbuf,olen);
}

View File

@@ -1105,7 +1105,6 @@ int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_
commission must be in coinbase.vout[1] and must be >= 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<n; i++)
{
hashbuf[i] = (uint8_t)komodo_segid(height+i);
hashbuf[i] = (uint8_t)komodo_segid(1,height+i);
//fprintf(stderr,"%02x ",hashbuf[i]);
}
if ( n == 100 )
@@ -1224,13 +1226,6 @@ uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeigh
komodo_segids(hashbuf,nHeight-101,100);
segid32 = komodo_stakehash(&hash,address,hashbuf,txid,vout);
segid = ((nHeight + segid32) & 0x3f);
/*vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)address,(int32_t)strlen(address));
segid = ((nHeight + addrhash.uints[0]) & 0x3f);
komodo_segids(hashbuf,nHeight-101,100);
memcpy(&hashbuf[100],&addrhash,sizeof(addrhash));
memcpy(&hashbuf[100+sizeof(addrhash)],&txid,sizeof(txid));
memcpy(&hashbuf[100+sizeof(addrhash)+sizeof(txid)],&vout,sizeof(vout));
vcalc_sha256(0,(uint8_t *)&hash,hashbuf,100 + (int32_t)sizeof(uint256)*2 + sizeof(vout));*/
for (iter=0; iter<600; iter++)
{
if ( blocktime+iter+segid*2 < txtime+minage )
@@ -1248,12 +1243,8 @@ uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeigh
coinage = (value * diff);
if ( blocktime+iter+segid*2 > 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);

View File

@@ -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) )
{

View File

@@ -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;

View File

@@ -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", "");

View File

@@ -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 = &block;
}
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<block.vtx.size(); i++)
{
CTransaction Tx; const CTransaction &tx = (CTransaction)block.vtx[i];
if (tx.IsCoinBase() != 0 )
continue;
else if ( ASSETCHAINS_STAKED != 0 && (i == (block.vtx.size() - 1)) && komodo_isPoS((CBlock *)&block) != 0 )
continue;
Tx = tx;
if ( myAddtomempool(Tx) == false ) // can happen with out of order tx in block on resync
//if ( AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL) == false )
rejects++;
}
if ( rejects == 0 || rejects == lastrejects )
{
if ( lastrejects != 0 )
fprintf(stderr,"lastrejects.%d -> 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)

View File

@@ -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<bool(std::vector<unsigned char>)> 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;
}

View File

@@ -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();

View File

@@ -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;

View File

@@ -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; z<scriptCode.size(); z++)
// fprintf(stderr,"%02x",ptr[z]);
//fprintf(stderr," <- CScript\n");
//for (z=0; z<32; z++)
// fprintf(stderr,"%02x",((uint8_t *)&sighash)[z]);
//fprintf(stderr," sighash nIn.%d nHashType.%d %.8f id.%d\n",(int32_t)nIn,(int32_t)nHashType,(double)amount/COIN,(int32_t)consensusBranchId);
/*int32_t z; uint8_t *ptr;
ptr = (uint8_t *)scriptCode.data();
for (z=0; z<scriptCode.size(); z++)
fprintf(stderr,"%02x",ptr[z]);
fprintf(stderr," <- CScript\n");
for (z=0; z<32; z++)
fprintf(stderr,"%02x",((uint8_t *)&sighash)[z]);
fprintf(stderr," sighash nIn.%d nHashType.%d %.8f id.%d\n",(int32_t)nIn,(int32_t)nHashType,(double)amount/COIN,(int32_t)consensusBranchId);
*/
VerifyEval eval = [] (CC *cond, void *checker) {
//fprintf(stderr,"checker.%p\n",(TransactionSignatureChecker*)checker);
return ((TransactionSignatureChecker*)checker)->CheckEvalCondition(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);

View File

@@ -102,5 +102,6 @@ bool ServerTransactionSignatureChecker::VerifySignature(const std::vector<unsign
*/
int ServerTransactionSignatureChecker::CheckEvalCondition(const CC *cond) const
{
//fprintf(stderr,"call RunCCeval from ServerTransactionSignatureChecker::CheckEvalCondition\n");
return RunCCEval(cond, *txTo, nIn);
}

View File

@@ -430,7 +430,7 @@ extern UniValue CBlockTreeDB::Snapshot(int top)
};
int64_t startingHeight = chainActive.Height();
fprintf(stderr, "Starting snapshot at height %li\n", startingHeight);
//fprintf(stderr, "Starting snapshot at height %lli\n", startingHeight);
for (iter->SeekToLast(); 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<std::string, CAmount> element : addressAmounts) {
vaddr.push_back( make_pair(element.second, element.first) );

View File

@@ -38,6 +38,8 @@
#include <numeric>
#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<unsigned char> 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<unsigned char> 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);
}