Merge branch 'jl777' into FSM

This commit is contained in:
jl777
2018-08-15 22:11:18 -11:00
31 changed files with 798 additions and 337 deletions

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

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

@@ -0,0 +1,231 @@
#!/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
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.sync_all()
print("Done setting up network")
def run_faucet_tests(self):
rpc = self.nodes[0]
# 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)
# clear the rawmempool
result = rpc.getrawmempool()
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')
result = rpc.tokencreate("DUKE", "1987.420", "duke")
assert_equal(result['result'], 'success')
# there are no tokens created yet
result = rpc.tokenlist()
assert_equal(result, [])
# 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_equal(result['result'], 'error')
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", "1000", "5", "1", "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'], "5.00000000")
assert_equal(result['minseconds'], 86400)
assert_equal(result['maxseconds'], 864000)
assert_equal(result['funding'], "1000.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, "100")
assert_equal(result['result'], 'success')
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

@@ -60,20 +60,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 +183,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 +200,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 +209,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 +235,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 +244,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 +265,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 +274,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 +297,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 +336,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 +357,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 +378,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 +387,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 )
@@ -426,12 +427,12 @@ std::string FillSell(int64_t txfee,uint256 assetid,uint256 assetid2,uint256 askt
if ( fillunits < 0 )
{
fprintf(stderr,"negative fillunits %lld\n",(long long)fillunits);
return(0);
return("");
}
if ( assetid2 != zeroid )
{
fprintf(stderr,"asset swaps disabled\n");
return(0);
return("");
}
cp = CCinit(&C,EVAL_ASSETS);
@@ -475,5 +476,5 @@ std::string FillSell(int64_t txfee,uint256 assetid,uint256 assetid2,uint256 askt
} else fprintf(stderr,"filltx not enough utxos\n");
}
}
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

@@ -64,6 +64,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 +82,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 +93,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,7 @@ 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 i,n; int64_t amount; std::vector<uint8_t> origpubkey;
// 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"
@@ -313,18 +319,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 +347,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 +355,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);
@@ -487,6 +496,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 +506,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 +577,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 +599,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 +620,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 +642,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') )
{
@@ -805,11 +819,11 @@ std::string DiceCreateFunding(uint64_t txfee,char *planstr,int64_t funds,int64_t
if ( funds < 0 || minbet < 0 || maxbet < 0 || maxodds < 1 || 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 +832,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)
@@ -827,10 +841,10 @@ std::string DiceAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,int6
if ( amount < 0 )
{
fprintf(stderr,"negative parameter error\n");
return(0);
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,7 +868,7 @@ 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)
@@ -863,21 +877,21 @@ std::string DiceBet(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t bet
if ( bet < 0 || odds < 1 )
{
fprintf(stderr,"negative parameter error\n");
return(0);
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 +906,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 +932,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 +946,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 +956,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 +972,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 +1010,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 +1063,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 +1086,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

@@ -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; int32_t i,j,len; uint8_t buf[32768]; bits256 hash;
cp = CCinit(&C,EVAL_FAUCET);
if ( txfee == 0 )
txfee = 10000;
@@ -167,12 +183,31 @@ 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));
for (i=0; i<1000000; i++)
{
tmpmtx = mtx;
rawhex = FinalizeCCTx(-1LL,cp,tmpmtx,mypk,txfee,CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_FAUCET << (uint8_t)'G' << mypk << i));
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 +220,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,10 @@
*/
uint64_t RewardsCalc(uint64_t amount,uint256 txid,uint64_t APR,uint64_t minseconds,uint64_t maxseconds,uint64_t mindeposit)
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 +77,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 +141,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 +173,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 +181,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 +209,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':
@@ -236,9 +247,7 @@ bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t
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 )
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");
@@ -252,7 +261,9 @@ 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");
preventCCvouts = 1;
break;
@@ -263,10 +274,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 +315,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 +325,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 +348,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 +375,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 +418,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 +446,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 +476,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 +495,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 +504,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 +513,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 +524,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 +533,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;
CMutableTransaction mtx; CPubKey mypk,rewardspk; CScript opret; uint64_t lockedfunds,sbits,funding,APR,minseconds,maxseconds,mindeposit; struct CCcontract_info *cp,C;
if ( deposit < 0 )
{
fprintf(stderr,"negative parameter error\n");
return(0);
return("");
}
cp = CCinit(&C,EVAL_REWARDS);
if ( txfee == 0 )
@@ -484,29 +553,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; CTransaction tx; char coinaddr[64]; CPubKey mypk,rewardspk; CScript opret,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 +585,18 @@ 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);
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);
return("");
}
if ( GetTransaction(locktxid,tx,hashBlock,false) != 0 && tx.vout.size() > 0 && tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 )
{
@@ -537,12 +606,12 @@ 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);
return("");
}
}
if ( amount > 0 && (reward= RewardsCalc(amount,mtx.vin[0].prevout.hash,APR,minseconds,maxseconds,mindeposit)) > txfee && scriptPubKey.size() > 0 )
{
if ( (inputs= AddRewardsInputs(ignore,1,cp,mtx,rewardspk,reward+txfee,30)) > 0 )
if ( (inputs= AddRewardsInputs(ignore,0,cp,mtx,rewardspk,reward+txfee,30,sbits,fundingtxid)) > 0 )
{
if ( inputs >= (reward + 2*txfee) )
CCchange = (inputs - (reward + txfee));
@@ -554,6 +623,6 @@ std::string RewardsUnlock(uint64_t txfee,char *planstr,uint256 fundingtxid,uint2
fprintf(stderr,"cant find enough rewards inputs\n");
}
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

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

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

@@ -3368,6 +3368,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.

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

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

@@ -4925,11 +4925,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));
@@ -5022,7 +5024,7 @@ UniValue rewardslock(const UniValue& params, bool fHelp)
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 +5035,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");
@@ -5138,7 +5148,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 +5156,20 @@ 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 {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "couldnt create faucet funding transaction"));
}
} else {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "funding amount must be positive"));
}
return(result);
}
@@ -5169,7 +5187,10 @@ UniValue faucetget(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 faucet get transaction"));
} else {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "couldnt create faucet get transaction"));
}
return(result);
}
@@ -5298,7 +5319,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);
}
@@ -5391,7 +5412,14 @@ UniValue tokencreate(const UniValue& params, bool fHelp)
name = params[0].get_str();
supply = atof(params[1].get_str().c_str()) * COIN;
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 )
{