Merge branch 'dev' into jl777

This commit is contained in:
jl777
2018-08-24 14:01:30 -11:00
4 changed files with 193 additions and 81 deletions

View File

@@ -7,7 +7,7 @@ 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, initialize_chain, start_nodes, start_node, connect_nodes_bi, \
stop_nodes, sync_blocks, sync_mempools, wait_bitcoinds, rpc_port
stop_nodes, sync_blocks, sync_mempools, wait_bitcoinds, rpc_port, assert_raises
import time
from decimal import Decimal
@@ -80,20 +80,20 @@ class CryptoConditionsTest (BitcoinTestFramework):
# no funds in the faucet yet
result = rpc.faucetget()
assert_equal(result['result'], 'error')
assert_error(result)
result = rpc.faucetinfo()
assert_equal(result['result'], 'success')
assert_success(result)
result = rpc.faucetfund("0")
assert_equal(result['result'], 'error')
assert_error(result)
result = rpc.faucetfund("-1")
assert_equal(result['result'], 'error')
assert_error(result)
# we need at least 1 + txfee to get
result = rpc.faucetfund("2")
assert_equal(result['result'], 'success')
assert_success(result)
assert result['hex'], "hex key found"
# broadcast the xtn
@@ -110,24 +110,21 @@ class CryptoConditionsTest (BitcoinTestFramework):
assert_greater_than(balance, balance2)
result = rpc.faucetinfo()
assert_equal(result['result'], 'success')
assert_success(result)
assert_greater_than( result['funding'], 0 )
result = rpc.faucetget()
assert_equal(result['result'], 'success')
assert_success(result)
assert result['hex'], "hex key found"
# broadcast the xtn
result = rpc.sendrawtransaction(result['hex'])
txid = result[0]
assert txid, "found txid"
# try to broadcast the xtn, but we will get 'faucet is only for brand new addresses'
assert_raises(JSONRPCException, rpc.sendrawtransaction, [ result['hex'] ])
# 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)
newaddr = rpc.getnewaddress()
assert newaddr, "got a new address"
result = rpc.validateaddress(newaddr)
newpubkey = result['pubkey']
assert newpubkey, "got a pubkey for new address"
def run_dice_tests(self):
rpc = self.nodes[0]
@@ -147,79 +144,184 @@ class CryptoConditionsTest (BitcoinTestFramework):
def run_token_tests(self):
rpc = self.nodes[0]
result = rpc.tokenaddress()
assert_equal(result['result'], 'success')
assert_success(result)
for x in ['AssetsCCaddress', 'myCCaddress', 'Assetsmarker', 'myaddress']:
assert_equal(result[x][0], 'R')
result = rpc.tokenaddress(self.pubkey)
assert_equal(result['result'], 'success')
assert_success(result)
for x in ['AssetsCCaddress', 'myCCaddress', 'Assetsmarker', 'myaddress', 'CCaddress']:
assert_equal(result[x][0], 'R')
assert_equal(result[x][0], 'R')
# there are no tokens created yet
result = rpc.tokenlist()
assert_equal(result, [])
result = rpc.tokencreate("DUKE", "1987.420", "duke")
assert_equal(result['result'], 'success')
self.send_and_mine(result['hex'])
assert_success(result)
tokenid = self.send_and_mine(result['hex'])
result = rpc.tokenlist()
tokenid = result[0]
assert(tokenid, "got tokenid")
assert_equal(result[0], tokenid)
# there are no token orders yet
result = rpc.tokenorders()
assert_equal(result, [])
# getting token balance for pubkey
result = rpc.tokenbalance(self.pubkey)
assert_success(result)
assert_equal(result['balance'], 0)
assert_equal(result['result'], 'success')
assert_equal(result['CCaddress'], 'RCRsm3VBXz8kKTsYaXKpy7pSEzrtNNQGJC')
assert_equal(result['tokenid'], self.pubkey)
# get token balance for token with pubkey
result = rpc.tokenbalance(tokenid, self.pubkey)
assert_success(result)
assert_equal(result['balance'], 198742000000)
assert_equal(result['tokenid'], tokenid)
# get token balance for token without pubkey
result = rpc.tokenbalance(tokenid)
assert_success(result)
assert_equal(result['balance'], 198742000000)
assert_equal(result['tokenid'], tokenid)
# this is not a valid assetid
result = rpc.tokeninfo(self.pubkey)
assert_error(result)
# invalid numtokens
# check tokeninfo for valid token
result = rpc.tokeninfo(tokenid)
assert_success(result)
assert_equal(result['tokenid'], tokenid)
assert_equal(result['owner'], self.pubkey)
assert_equal(result['name'], "DUKE")
assert_equal(result['supply'], 198742000000)
assert_equal(result['description'], "duke")
# invalid numtokens ask
result = rpc.tokenask("-1", tokenid, "1")
assert_error(result)
# invalid numtokens
# invalid numtokens ask
result = rpc.tokenask("0", tokenid, "1")
assert_error(result)
# invalid price
# invalid price ask
result = rpc.tokenask("1", tokenid, "-1")
assert_error(result)
# invalid price
# invalid price ask
result = rpc.tokenask("1", tokenid, "0")
assert_error(result)
# invalid tokenid
# invalid tokenid ask
result = rpc.tokenask("100", "deadbeef", "1")
assert_error(result)
# valid
result = rpc.tokenask("100", tokenid, "7.77")
assert_success(result)
tokenaskhex = result['hex']
assert tokenaskhex, "got tokenask hexk"
tokenaskid = self.send_and_mine(result['hex'])
# valid ask
tokenask = rpc.tokenask("100", tokenid, "7.77")
tokenaskhex = tokenask['hex']
tokenaskid = self.send_and_mine(tokenask['hex'])
result = rpc.tokenorders()
order = result[0]
assert order, "found order"
# invalid fillunits
# invalid ask fillunits
result = rpc.tokenfillask(tokenid, tokenaskid, "0")
assert_error(result)
# invalid fillunits
# invalid ask fillunits
result = rpc.tokenfillask(tokenid, tokenaskid, "-777")
assert_error(result)
# should this pass or fail?
result = rpc.tokenfillask(tokenid, tokenaskid, "10")
#assert_success(result)
# valid ask fillunits
fillask = rpc.tokenfillask(tokenid, tokenaskid, "777")
result = self.send_and_mine(fillask['hex'])
txid = result[0]
assert txid, "found txid"
# should be no token orders
result = rpc.tokenorders()
assert_equal(result, [])
# checking ask cancellation
testorder = rpc.tokenask("100", tokenid, "7.77")
testorderid = self.send_and_mine(testorder['hex'])
cancel = rpc.tokencancelask(tokenid, testorderid)
self.send_and_mine(cancel["hex"])
result = rpc.tokenorders()
assert_equal(result, [])
# invalid numtokens bid (have to add status to CC code!)
result = rpc.tokenbid("-1", tokenid, "1")
assert_equal(result['error'], 'invalid parameter')
# invalid numtokens bid (have to add status to CC code!)
result = rpc.tokenbid("0", tokenid, "1")
assert_equal(result['error'], 'invalid parameter')
# invalid price bid (have to add status to CC code!)
result = rpc.tokenbid("1", tokenid, "-1")
assert_equal(result['error'], 'invalid parameter')
# invalid price bid (have to add status to CC code!)
result = rpc.tokenbid("1", tokenid, "0")
assert_equal(result['error'], 'invalid parameter')
# invalid tokenid bid (have to add status to CC code!)
result = rpc.tokenbid("100", "deadbeef", "1")
assert_equal(result['error'], 'invalid parameter')
# valid bid
tokenbid = rpc.tokenbid("100", tokenid, "10")
tokenbidhex = tokenbid['hex']
tokenbidid = self.send_and_mine(tokenbid['hex'])
result = rpc.tokenorders()
order = result[0]
assert order, "found order"
# invalid bid fillunits
result = rpc.tokenfillbid(tokenid, tokenbidid, "0")
assert_error(result)
# invalid bid fillunits
result = rpc.tokenfillbid(tokenid, tokenbidid, "-777")
assert_error(result)
# valid bid fillunits
fillbid = rpc.tokenfillbid(tokenid, tokenbidid, "1000")
result = self.send_and_mine(fillbid['hex'])
txid = result[0]
assert txid, "found txid"
# should be no token orders
result = rpc.tokenorders()
assert_equal(result, [])
# checking bid cancellation
testorder = rpc.tokenbid("100", tokenid, "7.77")
testorderid = self.send_and_mine(testorder['hex'])
cancel = rpc.tokencancelbid(tokenid, testorderid)
self.send_and_mine(cancel["hex"])
result = rpc.tokenorders()
assert_equal(result, [])
# invalid token transfer amount (have to add status to CC code!)
randompubkey = "021a559101e355c907d9c553671044d619769a6e71d624f68bfec7d0afa6bd6a96"
result = rpc.tokentransfer(tokenid,randompubkey,"0")
assert_equal(result['error'], 'invalid parameter')
# invalid token transfer amount (have to add status to CC code!)
result = rpc.tokentransfer(tokenid,randompubkey,"-1")
assert_equal(result['error'], 'invalid parameter')
# valid token transfer
sendtokens = rpc.tokentransfer(tokenid,randompubkey,"1")
self.send_and_mine(sendtokens["hex"])
result = rpc.tokenbalance(tokenid,randompubkey)
assert_equal(result["balance"], 1)
def run_rewards_tests(self):
rpc = self.nodes[0]
@@ -237,7 +339,7 @@ class CryptoConditionsTest (BitcoinTestFramework):
# looking up non-existent reward should return error
result = rpc.rewardsinfo("none")
assert_equal(result['result'], 'error')
assert_error(result)
result = rpc.rewardscreatefunding("STUFF", "7777", "25", "0", "10", "10")
assert result['hex'], 'got raw xtn'
@@ -247,7 +349,7 @@ class CryptoConditionsTest (BitcoinTestFramework):
# confirm the above xtn
rpc.generate(1)
result = rpc.rewardsinfo(txid)
assert_equal(result['result'], 'success')
assert_success(result)
assert_equal(result['name'], 'STUFF')
assert_equal(result['APR'], "25.00000000")
assert_equal(result['minseconds'], 0)
@@ -258,23 +360,23 @@ class CryptoConditionsTest (BitcoinTestFramework):
# funding amount must be positive
result = rpc.rewardsaddfunding("STUFF", txid, "0")
assert_equal(result['result'], 'error')
assert_error(result)
result = rpc.rewardsaddfunding("STUFF", txid, "555")
assert_equal(result['result'], 'success')
assert_success(result)
fundingtxid = result['hex']
assert fundingtxid, "got funding txid"
result = rpc.rewardslock("STUFF", fundingtxid, "7")
assert_equal(result['result'], 'error')
assert_error(result)
# the previous xtn has not been broadcasted yet
result = rpc.rewardsunlock("STUFF", fundingtxid)
assert_equal(result['result'], 'error')
assert_error(result)
# wrong plan name
result = rpc.rewardsunlock("SHTUFF", fundingtxid)
assert_equal(result['result'], 'error')
assert_error(result)
txid = rpc.sendrawtransaction(fundingtxid)
assert txid, 'got txid from sendrawtransaction'
@@ -284,25 +386,25 @@ class CryptoConditionsTest (BitcoinTestFramework):
# amount must be positive
result = rpc.rewardslock("STUFF", fundingtxid, "-5")
assert_equal(result['result'], 'error')
assert_error(result)
# amount must be positive
result = rpc.rewardslock("STUFF", fundingtxid, "0")
assert_equal(result['result'], 'error')
assert_error(result)
# trying to lock less than the min amount is an error
result = rpc.rewardslock("STUFF", fundingtxid, "7")
assert_equal(result['result'], 'error')
assert_error(result)
# not working
#result = rpc.rewardslock("STUFF", fundingtxid, "10")
#assert_equal(result['result'], 'success')
#assert_success(result)
#locktxid = result['hex']
#assert locktxid, "got lock txid"
# locktxid has not been broadcast yet
#result = rpc.rewardsunlock("STUFF", locktxid)
#assert_equal(result['result'], 'error')
#assert_error(result)
# broadcast xtn
#txid = rpc.sendrawtransaction(locktxid)
@@ -312,7 +414,7 @@ class CryptoConditionsTest (BitcoinTestFramework):
#rpc.generate(1)
#result = rpc.rewardsunlock("STUFF", locktxid)
#assert_equal(result['result'], 'error')
#assert_error(result)
def run_test (self):

View File

@@ -21,24 +21,24 @@ extern std::string CCerror;
/*
in order to implement a dice game, we need a source of entropy, reasonably fast completion time and a way to manage the utxos.
1. CC vout locks "house" funds with hash(entropy)
2. bettor submits bet, with entropy, odds, houseid and sends combined amount into another CC vout.
3. house account sends funds to winner/loser with proof of entropy
4. if timeout, bettor gets refund
2. and 3. can be done in mempool
The house commits to an entropy value by including the hash of the entropy value in the 'E' transaction.
To bet, one of these 'E' transactions is used as the first input and its hashed entropy is combined with the unhashed entropy attached to the bet 'B' transaction.
The house node monitors the 'B' transactions and if it sees one of its own, it creates either a winner 'W' or loser 'L' transaction, with proof of hash of entropy.
In the even the house node doesnt respond before timeoutblocks, then anybody (including bettor) can undo the bet with funds going back to the house and bettor
In order for people to play dice, someone (anyone) needs to create a funded dice plan and addfunding with enough utxo to allow players to find one.
createfunding:
vins.*: normal inputs
vout.0: CC vout for funding
@@ -72,7 +72,7 @@ loser:
vout.1: tag to owner address for entropy funds
vout.2: change to fundingpk
vout.n-1: opreturn 'L' sbits fundingtxid hentropy proof
winner:
same as loser, but vout.2 is winnings
vout.3: change to fundingpk
@@ -80,12 +80,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.
*/
@@ -238,9 +238,16 @@ uint64_t DiceCalc(int64_t bet,int64_t odds,int64_t minbet,int64_t maxbet,int64_t
if ( odds < 10000 )
return(0);
else odds -= 10000;
if ( bet < minbet || bet > maxbet || odds > maxodds )
if ( bet < minbet || bet > maxbet )
{
fprintf(stderr,"bet size violation %.8f\n",(double)bet/COIN);
CCerror = strprintf("bet size violation %.8f",(double)bet/COIN);
fprintf(stderr,"%s\n", CCerror.c_str() );
return(0);
}
if ( odds > maxodds )
{
CCerror = strprintf("invalid odds %d, must be <= %d",odds, maxodds);
fprintf(stderr,"%s\n", CCerror.c_str() );
return(0);
}
//fprintf(stderr,"calc house entropy %s vs bettor %s\n",uint256_str(str,houseentropy),uint256_str(str2,bettorentropy));
@@ -810,13 +817,13 @@ UniValue DiceInfo(uint256 diceid)
if ( GetTransaction(diceid,vintx,hashBlock,false) == 0 )
{
fprintf(stderr,"cant find fundingtxid\n");
result.push_back(Pair("error","cant find fundingtxid"));
ERR_RESULT("cant find fundingtxid");
return(result);
}
if ( vintx.vout.size() > 0 && DecodeDiceFundingOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,sbits,minbet,maxbet,maxodds,timeoutblocks) == 0 )
{
fprintf(stderr,"fundingtxid isnt dice creation txid\n");
result.push_back(Pair("error","fundingtxid isnt dice creation txid"));
ERR_RESULT("fundingtxid isnt dice creation txid");
return(result);
}
result.push_back(Pair("result","success"));
@@ -1155,7 +1162,8 @@ double DiceStatus(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettx
return(0.);
else return((double)spenttx.vout[2].nValue/COIN);
}
fprintf(stderr,"couldnt find bettx or spenttx %s\n",uint256_str(str,spenttxid));
CCerror = "couldnt find bettx or spenttx %s\n",uint256_str(str,spenttxid);
fprintf(stderr,"%s\n", CCerror.c_str());
return(0.);
}
else if ( scriptPubKey == fundingPubKey )
@@ -1175,7 +1183,8 @@ double DiceStatus(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettx
else return((double)spenttx.vout[2].nValue/COIN);
} else return(0.);
}
fprintf(stderr,"didnt find dicefinish tx\n");
CCerror = "didnt find dicefinish tx";
fprintf(stderr,"%s\n", CCerror.c_str());
}
return(-1.);
}

View File

@@ -38,7 +38,6 @@
#include <numeric>
#define ERR_RESULT(x) result.push_back(Pair("result", "error")) , result.push_back(Pair("error", x));
using namespace std;
@@ -119,9 +118,9 @@ string AccountFromValue(const UniValue& value)
return strAccount;
}
char *komodo_chainname()
{
return(ASSETCHAINS_SYMBOL[0] == 0 ? (char *)"KMD" : ASSETCHAINS_SYMBOL);
char *komodo_chainname()
{
return(ASSETCHAINS_SYMBOL[0] == 0 ? (char *)"KMD" : ASSETCHAINS_SYMBOL);
}
UniValue getnewaddress(const UniValue& params, bool fHelp)
@@ -4567,7 +4566,7 @@ int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33)
utxovout = out.i;
best_scriptPubKey = out.tx->vout[out.i].scriptPubKey;
//fprintf(stderr,"check %s/v%d %llu\n",(char *)utxotxid.GetHex().c_str(),utxovout,(long long)utxovalue);
txNew.vin.resize(1);
txNew.vout.resize(1);
txfee = utxovalue / 2;
@@ -5779,5 +5778,3 @@ UniValue getbalance64(const UniValue& params, bool fHelp)
ret.push_back(Pair("notstaking", b));
return ret;
}

View File

@@ -1148,7 +1148,7 @@ public:
int minDepth=1,
bool ignoreSpent=true,
bool ignoreUnspendable=true);
};
/** A key allocated from the key pool. */
@@ -1204,4 +1204,8 @@ public:
READWRITE(vchPubKey);
}
};
/** Error status printout */
#define ERR_RESULT(x) result.push_back(Pair("result", "error")) , result.push_back(Pair("error", x));
#endif // BITCOIN_WALLET_WALLET_H