Merge pull request #12 from jl777/FSM

Fsm
This commit is contained in:
blackjok3rtt
2019-01-23 21:20:26 +08:00
committed by GitHub
46 changed files with 3371 additions and 1858 deletions

View File

@@ -13,12 +13,13 @@ export BITCOIND=${REAL_BITCOIND}
testScripts=( testScripts=(
'cryptoconditions_faucet.py' 'cryptoconditions_faucet.py'
'cryptoconditions_channels.py'
'cryptoconditions_dice.py' 'cryptoconditions_dice.py'
'cryptoconditions_oracles.py' 'cryptoconditions_oracles.py'
'cryptoconditions_rewards.py' 'cryptoconditions_rewards.py'
'cryptoconditions_token.py' 'cryptoconditions_token.py'
#'cryptoconditions_gateways.py' #'cryptoconditions_gateways.py'
# TODO: cant reconnect nodes back in channels test because of crash (seems regtest only specific)
'cryptoconditions_channels.py'
); );
extArg="-extended" extArg="-extended"

View File

@@ -4,6 +4,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.
import time
from test_framework.test_framework import CryptoconditionsTestFramework from test_framework.test_framework import CryptoconditionsTestFramework
from test_framework.authproxy import JSONRPCException from test_framework.authproxy import JSONRPCException
from test_framework.util import assert_equal, assert_greater_than, \ from test_framework.util import assert_equal, assert_greater_than, \
@@ -71,6 +72,58 @@ class CryptoconditionsChannelsTest(CryptoconditionsTestFramework):
result = rpc.channelsinfo(channel_txid) result = rpc.channelsinfo(channel_txid)
assert_equal(result["Transactions"][1]["Payment"], payment_tx_id) assert_equal(result["Transactions"][1]["Payment"], payment_tx_id)
# number of payments should be equal 1 (one denomination used)
result = rpc.channelsinfo(channel_txid)["Transactions"][1]["Number of payments"]
assert_equal(result, 1)
# payments left param should reduce 1 and be equal 9 now ( 10 - 1 = 9 )
result = rpc.channelsinfo(channel_txid)["Transactions"][1]["Payments left"]
assert_equal(result, 9)
# lets try payment with x2 amount to ensure that counters works correct
result = rpc.channelspayment(channel_txid, "200000")
assert_success(result)
payment_tx_id = self.send_and_mine(result["hex"], rpc)
assert payment_tx_id, "got txid"
result = rpc.channelsinfo(channel_txid)
assert_equal(result["Transactions"][2]["Payment"], payment_tx_id)
result = rpc.channelsinfo(channel_txid)["Transactions"][2]["Number of payments"]
assert_equal(result, 2)
result = rpc.channelsinfo(channel_txid)["Transactions"][2]["Payments left"]
assert_equal(result, 7)
# check if payment value really transferred
raw_transaction = rpc.getrawtransaction(payment_tx_id, 1)
result = raw_transaction["vout"][3]["valueSat"]
assert_equal(result, 200000)
result = rpc1.validateaddress(raw_transaction["vout"][3]["scriptPubKey"]["addresses"][0])["ismine"]
assert_equal(result, True)
# have to check that second node have coins to cover txfee at least
rpc.sendtoaddress(rpc1.getnewaddress(), 1)
rpc.sendtoaddress(rpc1.getnewaddress(), 1)
rpc.generate(2)
self.sync_all()
result = rpc1.getbalance()
assert_greater_than(result, 0.1)
# trying to initiate channels payment from node B without any secret
# TODO: have to add RPC validation
payment_hex = rpc1.channelspayment(channel_txid, "100000")
try:
result = rpc1.sendrawtransaction(payment_hex["hex"])
except Exception as e:
pass
# trying to initiate channels payment from node B with secret from previous payment
result = rpc1.channelspayment(channel_txid, "100000", rpc1.channelsinfo(channel_txid)["Transactions"][1]["Secret"])
#result = rpc1.sendrawtransaction(payment_hex["hex"])
assert_error(result)
# executing channel close # executing channel close
result = rpc.channelsclose(channel_txid) result = rpc.channelsclose(channel_txid)
assert_success(result) assert_success(result)
@@ -82,7 +135,7 @@ class CryptoconditionsChannelsTest(CryptoconditionsTestFramework):
# now in channelinfo closed flag should appear # now in channelinfo closed flag should appear
result = rpc.channelsinfo(channel_txid) result = rpc.channelsinfo(channel_txid)
assert_equal(result["Transactions"][2]["Close"], channel_close_txid) assert_equal(result["Transactions"][3]["Close"], channel_close_txid)
# executing channel refund # executing channel refund
result = rpc.channelsrefund(channel_txid, channel_close_txid) result = rpc.channelsrefund(channel_txid, channel_close_txid)
@@ -90,6 +143,92 @@ class CryptoconditionsChannelsTest(CryptoconditionsTestFramework):
refund_txid = self.send_and_mine(result["hex"], rpc) refund_txid = self.send_and_mine(result["hex"], rpc)
assert refund_txid, "got txid" assert refund_txid, "got txid"
# TODO: check if it refunded to opener address
raw_transaction = rpc.getrawtransaction(refund_txid, 1)
result = raw_transaction["vout"][2]["valueSat"]
assert_equal(result, 700000)
result = rpc.validateaddress(raw_transaction["vout"][2]["scriptPubKey"]["addresses"][0])["ismine"]
assert_equal(result, True)
# creating and draining channel (10 payment by 100000 satoshies in total to fit full capacity)
new_channel_hex1 = rpc.channelsopen(self.pubkey1, "10", "100000")
assert_success(new_channel_hex1)
channel1_txid = self.send_and_mine(new_channel_hex1["hex"], rpc)
assert channel1_txid, "got channel txid"
# need to have 2+ confirmations in the test mode
rpc.generate(2)
self.sync_all()
for i in range(10):
result = rpc.channelspayment(channel1_txid, "100000")
assert_success(result)
payment_tx_id = self.send_and_mine(result["hex"], rpc)
assert payment_tx_id, "got txid"
# last payment should indicate that 0 payments left
result = rpc.channelsinfo(channel1_txid)["Transactions"][10]["Payments left"]
assert_equal(result, 0)
# no more payments possible
result = rpc.channelspayment(channel1_txid, "100000")
assert_error(result)
# creating new channel to test the case when node B initiate payment when node A revealed secret in offline
# 10 payments, 100000 sat denomination channel opening with second node pubkey
new_channel_hex2 = rpc.channelsopen(self.pubkey1, "10", "100000")
assert_success(new_channel_hex)
channel2_txid = self.send_and_mine(new_channel_hex2["hex"], rpc)
assert channel2_txid, "got channel txid"
rpc.generate(2)
self.sync_all()
# disconnecting first node from network
rpc.setban("127.0.0.0/24","add")
assert_equal(rpc.getinfo()["connections"], 0)
assert_equal(rpc1.getinfo()["connections"], 0)
rpc1.generate(1)
# sending one payment to mempool to reveal the secret but not mine it
payment_hex = rpc.channelspayment(channel2_txid, "100000")
result = rpc.sendrawtransaction(payment_hex["hex"])
assert result, "got payment txid"
secret = rpc.channelsinfo(channel2_txid)["Transactions"][1]["Secret"]
assert secret, "Secret revealed"
# secret shouldn't be available for node B
secret_not_revealed = None
try:
rpc1.channelsinfo(channel2_txid)["Transactions"][1]["Secret"]
except Exception:
secret_not_revealed = True
assert_equal(secret_not_revealed, True)
# trying to initiate payment from second node with revealed secret
assert_equal(rpc1.getinfo()["connections"], 0)
dc_payment_hex = rpc1.channelspayment(channel2_txid, "100000", secret)
assert_success(dc_payment_hex)
result = rpc1.sendrawtransaction(dc_payment_hex["hex"])
assert result, "got channelspayment transaction id"
# TODO: it crash first node after block generating on mempools merging
# # restoring connection between nodes
# rpc.setban("127.0.0.0/24","remove")
# #rpc.generate(1)
# #rpc1.generate(1)
# sync_blocks(self.nodes)
# rpc.generate(1)
# sync_blocks(self.nodes)
# sync_mempools(self.nodes)
# assert_equal(rpc.getinfo()["connections"], 1)
# assert_equal(rpc1.getinfo()["connections"], 1)
def run_test(self): def run_test(self):
print("Mining blocks...") print("Mining blocks...")
rpc = self.nodes[0] rpc = self.nodes[0]

View File

@@ -15,21 +15,35 @@ from cryptoconditions import assert_success, assert_error, generate_random_strin
class CryptoconditionsTokenTest(CryptoconditionsTestFramework): class CryptoconditionsTokenTest(CryptoconditionsTestFramework):
def run_token_tests(self): def run_token_tests(self):
rpc = self.nodes[0] rpc = self.nodes[0]
rpc1 = self.nodes[1]
result = rpc.tokenaddress() result = rpc.tokenaddress()
assert_success(result) assert_success(result)
for x in ['AssetsCCaddress', 'myCCaddress', 'Assetsmarker', 'myaddress']: for x in ['TokensCCaddress', 'myCCaddress', 'Tokensmarker', 'myaddress']:
assert_equal(result[x][0], 'R') assert_equal(result[x][0], 'R')
result = rpc.tokenaddress(self.pubkey) result = rpc.tokenaddress(self.pubkey)
assert_success(result) assert_success(result)
for x in ['TokensCCaddress', 'myCCaddress', 'Tokensmarker', 'myaddress', 'CCaddress']:
assert_equal(result[x][0], 'R')
result = rpc.assetsaddress()
assert_success(result)
for x in ['AssetsCCaddress', 'myCCaddress', 'Assetsmarker', 'myaddress']:
assert_equal(result[x][0], 'R')
result = rpc.assetsaddress(self.pubkey)
assert_success(result)
for x in ['AssetsCCaddress', 'myCCaddress', 'Assetsmarker', 'myaddress', 'CCaddress']: 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 # there are no tokens created yet
result = rpc.tokenlist() result = rpc.tokenlist()
assert_equal(result, []) assert_equal(result, [])
# trying to create token with negaive supply # trying to create token with negative supply
result = rpc.tokencreate("NUKE", "-1987420", "no bueno supply") result = rpc.tokencreate("NUKE", "-1987420", "no bueno supply")
assert_error(result) assert_error(result)
@@ -50,12 +64,9 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework):
result = rpc.tokenorders() result = rpc.tokenorders()
assert_equal(result, []) assert_equal(result, [])
# getting token balance for pubkey # getting token balance for non existing tokenid
result = rpc.tokenbalance(self.pubkey) result = rpc.tokenbalance(self.pubkey)
assert_success(result) assert_error(result)
assert_equal(result['balance'], 0)
assert_equal(result['CCaddress'], 'RCRsm3VBXz8kKTsYaXKpy7pSEzrtNNQGJC')
assert_equal(result['tokenid'], self.pubkey)
# get token balance for token with pubkey # get token balance for token with pubkey
result = rpc.tokenbalance(tokenid, self.pubkey) result = rpc.tokenbalance(tokenid, self.pubkey)
@@ -131,11 +142,25 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework):
# checking ask cancellation # checking ask cancellation
testorder = rpc.tokenask("100", tokenid, "7.77") testorder = rpc.tokenask("100", tokenid, "7.77")
testorderid = self.send_and_mine(testorder['hex'], rpc) testorderid = self.send_and_mine(testorder['hex'], rpc)
# from other node (ensuring that second node have enough balance to cover txfee
# to get the actual error - not "not enough balance" one
rpc.sendtoaddress(rpc1.getnewaddress(), 1)
rpc.sendtoaddress(rpc1.getnewaddress(), 1)
rpc.generate(2)
self.sync_all()
result = rpc1.getbalance()
assert_greater_than(result, 0.1)
result = rpc1.tokencancelask(tokenid, testorderid)
assert_error(result)
# from valid node
cancel = rpc.tokencancelask(tokenid, testorderid) cancel = rpc.tokencancelask(tokenid, testorderid)
self.send_and_mine(cancel["hex"], rpc) self.send_and_mine(cancel["hex"], rpc)
result = rpc.tokenorders() result = rpc.tokenorders()
assert_equal(result, []) assert_equal(result, [])
# invalid numtokens bid # invalid numtokens bid
result = rpc.tokenbid("-1", tokenid, "1") result = rpc.tokenbid("-1", tokenid, "1")
assert_error(result) assert_error(result)
@@ -184,6 +209,15 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework):
# checking bid cancellation # checking bid cancellation
testorder = rpc.tokenbid("100", tokenid, "7.77") testorder = rpc.tokenbid("100", tokenid, "7.77")
testorderid = self.send_and_mine(testorder['hex'], rpc) testorderid = self.send_and_mine(testorder['hex'], rpc)
# from other node
result = rpc1.getbalance()
assert_greater_than(result, 0.1)
result = rpc1.tokencancelbid(tokenid, testorderid)
assert_error(result)
# from valid node
cancel = rpc.tokencancelbid(tokenid, testorderid) cancel = rpc.tokencancelbid(tokenid, testorderid)
self.send_and_mine(cancel["hex"], rpc) self.send_and_mine(cancel["hex"], rpc)
result = rpc.tokenorders() result = rpc.tokenorders()
@@ -220,5 +254,6 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework):
rpc1.importprivkey(self.privkey1) rpc1.importprivkey(self.privkey1)
self.run_token_tests() self.run_token_tests()
if __name__ == '__main__': if __name__ == '__main__':
CryptoconditionsTokenTest().main() CryptoconditionsTokenTest().main()

View File

@@ -571,7 +571,8 @@ komodod_LDADD += \
$(LIBBITCOIN_CRYPTO) \ $(LIBBITCOIN_CRYPTO) \
$(LIBVERUS_CRYPTO) \ $(LIBVERUS_CRYPTO) \
$(LIBVERUS_PORTABLE_CRYPTO) \ $(LIBVERUS_PORTABLE_CRYPTO) \
$(LIBZCASH_LIBS) $(LIBZCASH_LIBS) \
cclib.so
if ENABLE_PROTON if ENABLE_PROTON
komodod_LDADD += $(LIBBITCOIN_PROTON) $(PROTON_LIBS) komodod_LDADD += $(LIBBITCOIN_PROTON) $(PROTON_LIBS)

View File

@@ -94,7 +94,8 @@ void WaitForShutdown(boost::thread_group* threadGroup)
// //
// Start // Start
// //
extern int32_t IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,ASSETCHAIN_INIT; extern int32_t IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY;
extern uint32_t ASSETCHAIN_INIT;
extern std::string NOTARY_PUBKEY; extern std::string NOTARY_PUBKEY;
int32_t komodo_is_issuer(); int32_t komodo_is_issuer();
void komodo_passport_iteration(); void komodo_passport_iteration();

View File

@@ -212,7 +212,7 @@ bool FaucetExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction
bool FaucetValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx) bool FaucetValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx)
int64_t AddFaucetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs) int64_t AddFaucetInputs(struct CCcontract_infoCC_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs)
std::string FaucetGet(uint64_t txfee) std::string FaucetGet(uint64_t txfee)

View File

@@ -27,10 +27,10 @@ bool HeirValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,
class CoinHelper; class CoinHelper;
class TokenHelper; class TokenHelper;
UniValue HeirFundCoinCaller(uint64_t txfee, int64_t funds, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid); UniValue HeirFundCoinCaller(int64_t txfee, int64_t satoshis, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid);
UniValue HeirFundTokenCaller(uint64_t txfee, int64_t funds, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid); UniValue HeirFundTokenCaller(int64_t txfee, int64_t satoshis, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid);
UniValue HeirClaimCaller(uint256 fundingtxid, uint64_t txfee, int64_t amount); UniValue HeirClaimCaller(uint256 fundingtxid, int64_t txfee, std::string amount);
UniValue HeirAddCaller(uint256 fundingtxid, uint64_t txfee, int64_t amount); UniValue HeirAddCaller(uint256 fundingtxid, int64_t txfee, std::string amount);
UniValue HeirInfo(uint256 fundingtxid); UniValue HeirInfo(uint256 fundingtxid);
UniValue HeirList(); UniValue HeirList();

View File

@@ -23,15 +23,18 @@
#define MARMARA_GROUPSIZE 60 #define MARMARA_GROUPSIZE 60
#define MARMARA_MINLOCK (1440 * 3 * 30) #define MARMARA_MINLOCK (1440 * 3 * 30)
#define MARMARA_MAXLOCK (1440 * 24 * 30) #define MARMARA_MAXLOCK (1440 * 24 * 30)
#define MARMARA_VINS 16
extern uint8_t ASSETCHAINS_MARMARA;
uint64_t komodo_block_prg(uint32_t nHeight); uint64_t komodo_block_prg(uint32_t nHeight);
int32_t MarmaraGetcreatetxid(uint256 &createtxid,uint256 txid); int32_t MarmaraGetcreatetxid(uint256 &createtxid,uint256 txid);
int32_t MarmaraGetbatontxid(std::vector<uint256> &creditloop,uint256 &batontxid,uint256 txid); int32_t MarmaraGetbatontxid(std::vector<uint256> &creditloop,uint256 &batontxid,uint256 txid);
UniValue MarmaraCreditloop(uint256 txid); UniValue MarmaraCreditloop(uint256 txid);
UniValue MarmaraSettlement(uint64_t txfee,uint256 batontxid); UniValue MarmaraSettlement(uint64_t txfee,uint256 batontxid);
UniValue MarmaraLock(uint64_t txfee,int64_t amount,int32_t height);
UniValue MarmaraPoolPayout(uint64_t txfee,int32_t firstheight,double perc,char *jsonstr); // [[pk0, shares0], [pk1, shares1], ...] UniValue MarmaraPoolPayout(uint64_t txfee,int32_t firstheight,double perc,char *jsonstr); // [[pk0, shares0], [pk1, shares1], ...]
UniValue MarmaraReceive(uint64_t txfee,CPubKey senderpk,int64_t amount,std::string currency,int32_t matures,uint256 batontxid); UniValue MarmaraReceive(uint64_t txfee,CPubKey senderpk,int64_t amount,std::string currency,int32_t matures,uint256 batontxid,bool automaticflag);
UniValue MarmaraIssue(uint64_t txfee,uint8_t funcid,CPubKey receiverpk,int64_t amount,std::string currency,int32_t matures,uint256 approvaltxid,uint256 batontxid); UniValue MarmaraIssue(uint64_t txfee,uint8_t funcid,CPubKey receiverpk,int64_t amount,std::string currency,int32_t matures,uint256 approvaltxid,uint256 batontxid);
UniValue MarmaraInfo(CPubKey refpk,int32_t firstheight,int32_t lastheight,int64_t minamount,int64_t maxamount,std::string currency); UniValue MarmaraInfo(CPubKey refpk,int32_t firstheight,int32_t lastheight,int64_t minamount,int64_t maxamount,std::string currency);

View File

@@ -477,14 +477,10 @@ std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 a
std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid) std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid)
{ {
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction vintx; CTransaction vintx; uint64_t mask;
uint64_t mask; uint256 hashBlock; int64_t bidamount;
uint256 hashBlock; CPubKey mypk; struct CCcontract_info *cpAssets, C;
int64_t bidamount; uint8_t funcid,dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; std::vector<uint8_t> dummyOrigpubkey;
CPubKey mypk;
struct CCcontract_info *cpAssets, C;
uint8_t dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; std::vector<uint8_t> dummyOrigpubkey;
cpAssets = CCinit(&C, EVAL_ASSETS); cpAssets = CCinit(&C, EVAL_ASSETS);
@@ -501,9 +497,12 @@ std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid)
bidamount = vintx.vout[0].nValue; bidamount = vintx.vout[0].nValue;
mtx.vin.push_back(CTxIn(bidtxid, 0, CScript())); // coins in Assets mtx.vin.push_back(CTxIn(bidtxid, 0, CScript())); // coins in Assets
if( DecodeAssetTokenOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey) == 'b') if((funcid=DecodeAssetTokenOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey))!=0)
mtx.vin.push_back(CTxIn(bidtxid, 1, CScript())); // spend marker if funcid='b' (not 'B') {
// TODO: spend it also in FillBuyOffer?
if (funcid == 's') mtx.vin.push_back(CTxIn(bidtxid, 1, CScript())); // spend marker if funcid='b'
else if (funcid=='S') mtx.vin.push_back(CTxIn(bidtxid, 3, CScript())); // spend marker if funcid='B'
}
mtx.vout.push_back(CTxOut(bidamount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); mtx.vout.push_back(CTxOut(bidamount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
@@ -523,12 +522,9 @@ std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid)
{ {
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction vintx; uint64_t mask; CTransaction vintx; uint64_t mask;
uint256 hashBlock; uint256 hashBlock; int64_t askamount;
int64_t askamount; CPubKey mypk; struct CCcontract_info *cpTokens, *cpAssets, tokensC, assetsC;
CPubKey mypk; uint8_t funcid,dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; std::vector<uint8_t> dummyOrigpubkey;
struct CCcontract_info *cpTokens, *cpAssets, tokensC, assetsC;
uint8_t dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; std::vector<uint8_t> dummyOrigpubkey;
cpAssets = CCinit(&assetsC, EVAL_ASSETS); cpAssets = CCinit(&assetsC, EVAL_ASSETS);
@@ -545,9 +541,11 @@ std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid)
askamount = vintx.vout[0].nValue; askamount = vintx.vout[0].nValue;
mtx.vin.push_back(CTxIn(asktxid, 0, CScript())); mtx.vin.push_back(CTxIn(asktxid, 0, CScript()));
if (DecodeAssetTokenOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey) == 's') if ((funcid=DecodeAssetTokenOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey))!=0)
mtx.vin.push_back(CTxIn(asktxid, 1, CScript())); // marker if funcid='s' (not 'S') {
// TODO: spend it also in FillSell? if (funcid == 's') mtx.vin.push_back(CTxIn(asktxid, 1, CScript())); // marker if funcid='s'
else if (funcid=='S') mtx.vin.push_back(CTxIn(asktxid, 3, CScript())); // marker if funcid='S'
}
mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, askamount, mypk)); // one-eval token vout mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, askamount, mypk)); // one-eval token vout
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
@@ -607,7 +605,7 @@ std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t f
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
if (AddNormalinputs(mtx, mypk, txfee, 3) > 0) if (AddNormalinputs(mtx, mypk, 2*txfee, 3) > 0)
{ {
mask = ~((1LL << mtx.vin.size()) - 1); mask = ~((1LL << mtx.vin.size()) - 1);
if (GetTransaction(bidtxid, vintx, hashBlock, false) != 0) if (GetTransaction(bidtxid, vintx, hashBlock, false) != 0)
@@ -637,9 +635,10 @@ std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t f
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, bidamount - paid_amount, unspendableAssetsPk)); // vout0 coins remainder mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, bidamount - paid_amount, unspendableAssetsPk)); // vout0 coins remainder
mtx.vout.push_back(CTxOut(paid_amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // vout1 coins to normal mtx.vout.push_back(CTxOut(paid_amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // vout1 coins to normal
mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, fillamount, pubkey2pk(origpubkey))); // vout2 single-eval tokens sent to the buyer mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, fillamount, pubkey2pk(origpubkey))); // vout2 single-eval tokens sent to the buyer
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,txfee,origpubkey)); // vout3 marker to origpubkey
if (CCchange != 0) if (CCchange != 0)
mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, CCchange, mypk)); // vout3 change in single-eval tokens mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, CCchange, mypk)); // vout4 change in single-eval tokens
fprintf(stderr,"FillBuyOffer remaining %llu -> origpubkey\n", (long long)remaining_required); fprintf(stderr,"FillBuyOffer remaining %llu -> origpubkey\n", (long long)remaining_required);
@@ -698,7 +697,7 @@ std::string FillSell(int64_t txfee, uint256 assetid, uint256 assetid2, uint256 a
txfee = 10000; txfee = 10000;
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
if (AddNormalinputs(mtx, mypk, txfee, 3) > 0) if (AddNormalinputs(mtx, mypk, 2*txfee, 3) > 0)
{ {
mask = ~((1LL << mtx.vin.size()) - 1); mask = ~((1LL << mtx.vin.size()) - 1);
if (GetTransaction(asktxid, vintx, hashBlock, false) != 0) if (GetTransaction(asktxid, vintx, hashBlock, false) != 0)
@@ -747,6 +746,7 @@ std::string FillSell(int64_t txfee, uint256 assetid, uint256 assetid2, uint256 a
//std::cerr << "FillSell() paid_value=" << paid_nValue << " origpubkey=" << HexStr(pubkey2pk(origpubkey)) << std::endl; //std::cerr << "FillSell() paid_value=" << paid_nValue << " origpubkey=" << HexStr(pubkey2pk(origpubkey)) << std::endl;
mtx.vout.push_back(CTxOut(paid_nValue, CScript() << origpubkey << OP_CHECKSIG)); //vout.2 coins to tokens seller's normal addr mtx.vout.push_back(CTxOut(paid_nValue, CScript() << origpubkey << OP_CHECKSIG)); //vout.2 coins to tokens seller's normal addr
} }
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,txfee,origpubkey)); //vout.3 marker to origpubkey
// not implemented // not implemented
if (CCchange != 0) { if (CCchange != 0) {

View File

@@ -234,6 +234,34 @@ uint8_t TokensCCpriv[32] = { 0x1d, 0x0d, 0x0d, 0xce, 0x2d, 0xd2, 0xe1, 0x9d, 0xf
#undef FUNCNAME #undef FUNCNAME
#undef EVALCODE #undef EVALCODE
#define FUNCNAME IsCClibInput
#define EVALCODE EVAL_FIRSTUSER
const char *CClibNormaladdr = "RVVeUg43rNcq3mZFnvZ8yqagyzqFgUnq4u";
char CClibCChexstr[67] = { "032447d97655da079729dc024c61088ea415b22f4c15d4810ddaf2069ac6468d2f" };
uint8_t CClibCCpriv[32] = { 0x57, 0xcf, 0x49, 0x71, 0x7d, 0xb4, 0x15, 0x1b, 0x4f, 0x98, 0xc5, 0x45, 0x8d, 0x26, 0x52, 0x4b, 0x7b, 0xe9, 0xbd, 0x55, 0xd8, 0x20, 0xd6, 0xc4, 0x82, 0x0f, 0xf5, 0xec, 0x6c, 0x1c, 0xa0, 0xc0 };
#include "CCcustom.inc"
#undef FUNCNAME
#undef EVALCODE
int32_t CClib_initcp(struct CCcontract_info *cp,uint8_t evalcode)
{
CPubKey pk; uint8_t pub33[33]; char CCaddr[64];
if ( evalcode == EVAL_FIRSTUSER ) // eventually make a hashchain for each evalcode
{
cp->evalcode = evalcode;
cp->ismyvin = IsCClibInput;
strcpy(cp->CChexstr,CClibCChexstr);
memcpy(cp->CCpriv,CClibCCpriv,32);
decode_hex(pub33,33,cp->CChexstr);
pk = buf2pk(pub33);
Getscriptaddress(cp->normaladdr,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG);
if ( strcmp(cp->normaladdr,CClibNormaladdr) != 0 )
fprintf(stderr,"CClib_initcp addr mismatch %s vs %s\n",cp->normaladdr,CClibNormaladdr);
GetCCaddress(cp,cp->unspendableCCaddr,pk);
return(0);
}
return(-1);
}
struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode)
{ {
@@ -369,6 +397,10 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode)
cp->validate = TokensValidate; cp->validate = TokensValidate;
cp->ismyvin = IsTokensInput; cp->ismyvin = IsTokensInput;
break; break;
default:
if ( CClib_initcp(cp,evalcode) < 0 )
return(0);
break;
} }
return(cp); return(cp);
} }

View File

@@ -51,10 +51,6 @@ one other technical note is that komodod has the insight-explorer extensions bui
#include "../utlist.h" #include "../utlist.h"
#include "../uthash.h" #include "../uthash.h"
extern int32_t KOMODO_CONNECTING,KOMODO_CCACTIVATE,KOMODO_DEALERNODE;
extern uint32_t ASSETCHAINS_CC;
extern char ASSETCHAINS_SYMBOL[];
extern std::string CCerror;
#define CC_MAXVINS 1024 #define CC_MAXVINS 1024
@@ -68,6 +64,7 @@ extern std::string CCerror;
typedef union _bits256 bits256; typedef union _bits256 bits256;
#endif #endif
#include "../komodo_cJSON.h"
struct CC_utxo struct CC_utxo
{ {
@@ -133,6 +130,9 @@ CBlockIndex *komodo_getblockindex(uint256 hash);
int32_t komodo_nextheight(); int32_t komodo_nextheight();
int32_t CCgetspenttxid(uint256 &spenttxid,int32_t &vini,int32_t &height,uint256 txid,int32_t vout); int32_t CCgetspenttxid(uint256 &spenttxid,int32_t &vini,int32_t &height,uint256 txid,int32_t vout);
void CCclearvars(struct CCcontract_info *cp);
UniValue CClib(struct CCcontract_info *cp,char *method,cJSON *params);
UniValue CClib_info(struct CCcontract_info *cp);
static const uint256 zeroid; static const uint256 zeroid;
bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock); bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock);
@@ -199,6 +199,7 @@ CC *MakeTokensCCcond1(uint8_t evalcode, CPubKey pk);
bool GetTokensCCaddress(struct CCcontract_info *cp, char *destaddr, CPubKey pk); bool GetTokensCCaddress(struct CCcontract_info *cp, char *destaddr, CPubKey pk);
bool GetTokensCCaddress1of2(struct CCcontract_info *cp, char *destaddr, CPubKey pk, CPubKey pk2); bool GetTokensCCaddress1of2(struct CCcontract_info *cp, char *destaddr, CPubKey pk, CPubKey pk2);
void CCaddrTokens1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, char *coinaddr); void CCaddrTokens1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, char *coinaddr);
int32_t CClib_initcp(struct CCcontract_info *cp,uint8_t evalcode);
bool IsCCInput(CScript const& scriptSig); bool IsCCInput(CScript const& scriptSig);
int32_t unstringbits(char *buf,uint64_t bits); int32_t unstringbits(char *buf,uint64_t bits);
@@ -222,9 +223,11 @@ std::vector<uint8_t> Mypubkey();
bool Myprivkey(uint8_t myprivkey[]); bool Myprivkey(uint8_t myprivkey[]);
int64_t CCduration(int32_t &numblocks,uint256 txid); int64_t CCduration(int32_t &numblocks,uint256 txid);
bool komodo_txnotarizedconfirmed(uint256 txid); bool komodo_txnotarizedconfirmed(uint256 txid);
CPubKey check_signing_pubkey(CScript scriptSig);
// CCtx // CCtx
bool SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScript scriptPubKey); bool SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScript scriptPubKey);
std::string FinalizeCCTx(uint64_t skipmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret); extern std::vector<CPubKey> NULL_pubkeys;
std::string FinalizeCCTx(uint64_t skipmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret,std::vector<CPubKey> pubkeys = NULL_pubkeys);
void SetCCunspents(std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs,char *coinaddr); void SetCCunspents(std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs,char *coinaddr);
void SetCCtxids(std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex,char *coinaddr); void SetCCtxids(std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex,char *coinaddr);
int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs); int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs);

View File

@@ -404,7 +404,6 @@ int64_t IsTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *c
uint8_t evalCodeInOpret; uint8_t evalCodeInOpret;
if (vopretExtra.size() >= 2 /*|| vopretExtra.size() != vopretExtra.begin()[0] <-- shold we check this?*/) { if (vopretExtra.size() >= 2 /*|| vopretExtra.size() != vopretExtra.begin()[0] <-- shold we check this?*/) {
std::cerr << "IsTokensvout() empty or incorrect contract opret" << std::endl;
evalCodeInOpret = vopretExtra.begin()[1]; evalCodeInOpret = vopretExtra.begin()[1];
} }
else { else {

View File

@@ -16,6 +16,8 @@
#include "CCinclude.h" #include "CCinclude.h"
#include "key_io.h" #include "key_io.h"
std::vector<CPubKey> NULL_pubkeys;
/* /*
FinalizeCCTx is a very useful function that will properly sign both CC and normal inputs, adds normal change and the opreturn. FinalizeCCTx is a very useful function that will properly sign both CC and normal inputs, adds normal change and the opreturn.
@@ -38,18 +40,18 @@ bool SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScrip
return(false); return(false);
} }
std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret) std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret,std::vector<CPubKey> pubkeys)
{ {
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
CTransaction vintx; std::string hex; uint256 hashBlock; uint64_t mask=0,nmask=0,vinimask=0; CTransaction vintx; std::string hex; CPubKey globalpk; uint256 hashBlock; uint64_t mask=0,nmask=0,vinimask=0;
int64_t utxovalues[CC_MAXVINS],change,normalinputs=0,totaloutputs=0,normaloutputs=0,totalinputs=0,normalvins=0,ccvins=0; int64_t utxovalues[CC_MAXVINS],change,normalinputs=0,totaloutputs=0,normaloutputs=0,totalinputs=0,normalvins=0,ccvins=0;
int32_t i,utxovout,n,err = 0; int32_t i,flag,utxovout,n,err = 0;
char myaddr[64], destaddr[64], unspendable[64], mytokensaddr[64], mysingletokensaddr[64], tokensunspendable[64]; char myaddr[64], destaddr[64], unspendable[64], mytokensaddr[64], mysingletokensaddr[64], tokensunspendable[64];
uint8_t *privkey, myprivkey[32], unspendablepriv[32], tokensunspendablepriv[32], *msg32 = 0; uint8_t *privkey, myprivkey[32], unspendablepriv[32], tokensunspendablepriv[32], *msg32 = 0;
CC *mycond=0, *othercond=0, *othercond2=0, *othercond3=0, *othercond1of2=NULL, *othercond1of2tokens = NULL, *cond, *mytokenscond = NULL, *mysingletokenscond = NULL, *othertokenscond = NULL; CC *mycond=0, *othercond=0, *othercond2=0,*othercond4=0, *othercond3=0, *othercond1of2=NULL, *othercond1of2tokens = NULL, *cond, *mytokenscond = NULL, *mysingletokenscond = NULL, *othertokenscond = NULL;
CPubKey unspendablepk /*, tokensunspendablepk*/; CPubKey unspendablepk /*, tokensunspendablepk*/;
struct CCcontract_info *cpTokens, tokensC; struct CCcontract_info *cpTokens, tokensC;
globalpk = GetUnspendable(cp,0);
n = mtx.vout.size(); n = mtx.vout.size();
for (i=0; i<n; i++) for (i=0; i<n; i++)
{ {
@@ -220,9 +222,28 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
cond = othercond1of2tokens; cond = othercond1of2tokens;
} }
else else
{
flag = 0;
if ( pubkeys != NULL_pubkeys )
{
char coinaddr[64];
GetCCaddress1of2(cp,coinaddr,globalpk,pubkeys[i]);
//fprintf(stderr,"%s + %s -> %s vs %s\n",HexStr(globalpk).c_str(),HexStr(pubkeys[i]).c_str(),coinaddr,destaddr);
if ( strcmp(destaddr,coinaddr) == 0 )
{
privkey = cp->CCpriv;
if ( othercond4 != 0 )
cc_free(othercond4);
othercond4 = MakeCCcond1of2(cp->evalcode,globalpk,pubkeys[i]);
cond = othercond4;
flag = 1;
}
}
if ( flag == 0 )
{ {
fprintf(stderr,"CC signing error: vini.%d has unknown CC address.(%s)\n",i,destaddr); fprintf(stderr,"CC signing error: vini.%d has unknown CC address.(%s)\n",i,destaddr);
return(""); continue;
}
} }
uint256 sighash = SignatureHash(CCPubKey(cond), mtx, i, SIGHASH_ALL, utxovalues[i],consensusBranchId, &txdata); uint256 sighash = SignatureHash(CCPubKey(cond), mtx, i, SIGHASH_ALL, utxovalues[i],consensusBranchId, &txdata);
if ( cc_signTreeSecp256k1Msg32(cond,privkey,sighash.begin()) != 0 ) if ( cc_signTreeSecp256k1Msg32(cond,privkey,sighash.begin()) != 0 )
@@ -252,6 +273,8 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
cc_free(othercond2); cc_free(othercond2);
if ( othercond3 != 0 ) if ( othercond3 != 0 )
cc_free(othercond3); cc_free(othercond3);
if ( othercond4 != 0 )
cc_free(othercond4);
std::string strHex = EncodeHexTx(mtx); std::string strHex = EncodeHexTx(mtx);
if ( strHex.size() > 0 ) if ( strHex.size() > 0 )
return(strHex); return(strHex);
@@ -450,8 +473,8 @@ int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int3
{ {
int32_t abovei,belowi,ind,vout,i,n = 0,maxutxos=64; int64_t sum,threshold,above,below; int64_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=64; int64_t sum,threshold,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 #ifdef ENABLE_WALLET
const CKeyStore& keystore = *pwalletMain;
assert(pwalletMain != NULL); assert(pwalletMain != NULL);
const CKeyStore& keystore = *pwalletMain;
LOCK2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet);
pwalletMain->AvailableCoins(vecOutputs, false, NULL, true); pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
utxos = (struct CC_utxo *)calloc(maxutxos,sizeof(*utxos)); utxos = (struct CC_utxo *)calloc(maxutxos,sizeof(*utxos));

View File

@@ -493,39 +493,10 @@ CPubKey GetUnspendable(struct CCcontract_info *cp,uint8_t *unspendablepriv)
return(pubkey2pk(ParseHex(cp->CChexstr))); return(pubkey2pk(ParseHex(cp->CChexstr)));
} }
bool ProcessCC(struct CCcontract_info *cp,Eval* eval, std::vector<uint8_t> paramsNull,const CTransaction &ctx, unsigned int nIn) void CCclearvars(struct CCcontract_info *cp)
{ {
CTransaction createTx; uint256 assetid,assetid2,hashBlock; uint8_t funcid; int32_t height,i,n,from_mempool = 0; int64_t amount; std::vector<uint8_t> origpubkey;
height = KOMODO_CONNECTING;
if ( KOMODO_CONNECTING < 0 ) // always comes back with > 0 for final confirmation
return(true);
if ( ASSETCHAINS_CC == 0 || (height & ~(1<<30)) < KOMODO_CCACTIVATE )
return eval->Invalid("CC are disabled or not active yet");
if ( (KOMODO_CONNECTING & (1<<30)) != 0 )
{
from_mempool = 1;
height &= ((1<<30) - 1);
}
//fprintf(stderr,"KOMODO_CONNECTING.%d mempool.%d vs CCactive.%d\n",height,from_mempool,KOMODO_CCACTIVATE);
// 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 )
// return(true);
//fprintf(stderr,"process CC %02x\n",cp->evalcode);
cp->evalcode2 = cp->evalcode3 = 0; cp->evalcode2 = cp->evalcode3 = 0;
cp->unspendableaddr2[0] = cp->unspendableaddr3[0] = 0; cp->unspendableaddr2[0] = cp->unspendableaddr3[0] = 0;
if ( paramsNull.size() != 0 ) // Don't expect params
return eval->Invalid("Cannot have params");
//else if ( ctx.vout.size() == 0 ) // spend can go to z-addresses
// return eval->Invalid("no-vouts");
else if ( (*cp->validate)(cp,eval,ctx,nIn) != 0 )
{
//fprintf(stderr,"done CC %02x\n",cp->evalcode);
//cp->prevtxid = txid;
return(true);
}
//fprintf(stderr,"invalid CC %02x\n",cp->evalcode);
return(false);
} }
int64_t CCduration(int32_t &numblocks,uint256 txid) int64_t CCduration(int32_t &numblocks,uint256 txid)
@@ -599,3 +570,109 @@ bool komodo_txnotarizedconfirmed(uint256 txid)
return (true); return (true);
return (false); return (false);
} }
CPubKey check_signing_pubkey(CScript scriptSig)
{
bool found = false;
CPubKey pubkey;
auto findEval = [](CC *cond, struct CCVisitor _) {
bool r = false;
if (cc_typeId(cond) == CC_Secp256k1) {
*(CPubKey*)_.context=buf2pk(cond->publicKey);
r = true;
}
// false for a match, true for continue
return r ? 0 : 1;
};
CC *cond = GetCryptoCondition(scriptSig);
if (cond) {
CCVisitor visitor = { findEval, (uint8_t*)"", 0, &pubkey };
bool out = !cc_visit(cond, visitor);
cc_free(cond);
if (pubkey.IsValid()) {
return pubkey;
}
}
return CPubKey();
}
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 height,i,n,from_mempool = 0; int64_t amount; std::vector<uint8_t> origpubkey;
height = KOMODO_CONNECTING;
if ( KOMODO_CONNECTING < 0 ) // always comes back with > 0 for final confirmation
return(true);
if ( ASSETCHAINS_CC == 0 || (height & ~(1<<30)) < KOMODO_CCACTIVATE )
return eval->Invalid("CC are disabled or not active yet");
if ( (KOMODO_CONNECTING & (1<<30)) != 0 )
{
from_mempool = 1;
height &= ((1<<30) - 1);
}
//fprintf(stderr,"KOMODO_CONNECTING.%d mempool.%d vs CCactive.%d\n",height,from_mempool,KOMODO_CCACTIVATE);
// 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 )
// return(true);
//fprintf(stderr,"process CC %02x\n",cp->evalcode);
CCclearvars(cp);
if ( paramsNull.size() != 0 ) // Don't expect params
return eval->Invalid("Cannot have params");
//else if ( ctx.vout.size() == 0 ) // spend can go to z-addresses
// return eval->Invalid("no-vouts");
else if ( (*cp->validate)(cp,eval,ctx,nIn) != 0 )
{
//fprintf(stderr,"done CC %02x\n",cp->evalcode);
//cp->prevtxid = txid;
return(true);
}
//fprintf(stderr,"invalid CC %02x\n",cp->evalcode);
return(false);
}
extern struct CCcontract_info CCinfos[0x100];
extern std::string MYCCLIBNAME;
bool CClib_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx,unsigned int nIn);
bool CClib_Dispatch(const CC *cond,Eval *eval,std::vector<uint8_t> paramsNull,const CTransaction &txTo,unsigned int nIn)
{
uint8_t evalcode; int32_t height,from_mempool; struct CCcontract_info *cp;
if ( ASSETCHAINS_CCLIB != MYCCLIBNAME )
{
fprintf(stderr,"-ac_cclib=%s vs myname %s\n",ASSETCHAINS_CCLIB.c_str(),MYCCLIBNAME.c_str());
return eval->Invalid("-ac_cclib name mismatches myname");
}
height = KOMODO_CONNECTING;
if ( KOMODO_CONNECTING < 0 ) // always comes back with > 0 for final confirmation
return(true);
if ( ASSETCHAINS_CC == 0 || (height & ~(1<<30)) < KOMODO_CCACTIVATE )
return eval->Invalid("CC are disabled or not active yet");
if ( (KOMODO_CONNECTING & (1<<30)) != 0 )
{
from_mempool = 1;
height &= ((1<<30) - 1);
}
evalcode = cond->code[0];
if ( evalcode >= EVAL_FIRSTUSER && evalcode <= EVAL_LASTUSER )
{
cp = &CCinfos[(int32_t)evalcode];
if ( cp->didinit == 0 )
{
if ( CClib_initcp(cp,evalcode) == 0 )
cp->didinit = 1;
else return eval->Invalid("unsupported CClib evalcode");
}
CCclearvars(cp);
if ( paramsNull.size() != 0 ) // Don't expect params
return eval->Invalid("Cannot have params");
else if ( CClib_validate(cp,height,eval,txTo,nIn) != 0 )
return(true);
return(false); //eval->Invalid("error in CClib_validate");
}
return eval->Invalid("cclib CC must have evalcode between 16 and 127");
}

33
src/cc/Makefile Normal file
View File

@@ -0,0 +1,33 @@
SHELL = /bin/sh
CC = gcc
CC_DARWIN = g++-6
CC_WIN = x86_64-w64-mingw32-gcc-posix
CFLAGS_DARWIN = -std=c++11 -arch x86_64 -I/usr/local/Cellar/gcc\@6/6.4.0_2/include/c++/6.4.0/ -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -c -Wl,-undefined -Wl,dynamic_lookup
CFLAGS = -std=c++11 -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c
CFLAGS_WIN = -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c
DEBUGFLAGS = -O0 -D _DEBUG
RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program
$(info $(OS))
OS := $(shell uname -s)
$(info $(OS))
TARGET = ../cclib.so
TARGET_WIN = ../cclib.dll
SOURCES = cclib.cpp
#HEADERS = $(shell echo ../cryptoconditions/include/*.h)
all: $(TARGET)
$(TARGET): $(SOURCES)
$(info Building cclib to src/)
ifeq ($(OS),Darwin)
$(CC_DARWIN) $(CFLAGS_DARWIN) $(DEBUGFLAGS) -o $(TARGET) $(SOURCES)
else ifeq ($(OS),Linux)
$(CC) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) $(SOURCES)
#else ifeq ($(WIN_HOST),True) - todo: pass ENV var from build.sh if WIN host
else
$(info WINDOWS)
$(CC_WIN) $(CFLAGS_WIN) $(DEBUGFLAGS) -o $(TARGET_WIN) $(SOURCES)
endif
clean:
rm -rf $(TARGET)

View File

@@ -153,8 +153,9 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti
return eval->Invalid("AssetValidate: invalid opreturn payload"); return eval->Invalid("AssetValidate: invalid opreturn payload");
// find dual-eval tokens unspendable addr: // find dual-eval tokens unspendable addr:
char tokensUnspendableAddr[64]; char tokensUnspendableAddr[64],origpubkeyCCaddr[64];
GetTokensCCaddress(cpAssets, tokensUnspendableAddr, GetUnspendable(cpAssets, NULL)); GetTokensCCaddress(cpAssets, tokensUnspendableAddr, GetUnspendable(cpAssets, NULL));
GetCCaddress(cpAssets, origpubkeyCCaddr, origpubkey);
// we need this for validating single-eval tokens' vins/vous: // we need this for validating single-eval tokens' vins/vous:
struct CCcontract_info *cpTokens, tokensC; struct CCcontract_info *cpTokens, tokensC;
@@ -258,7 +259,7 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti
if( (nValue = AssetValidateBuyvin(cpAssets, eval, totalunits, tmporigpubkey, assetsCCaddr, origaddr, tx, assetid)) == 0 ) if( (nValue = AssetValidateBuyvin(cpAssets, eval, totalunits, tmporigpubkey, assetsCCaddr, origaddr, tx, assetid)) == 0 )
return(false); return(false);
else if( numvouts < 3 ) else if( numvouts < 4 )
return eval->Invalid("not enough vouts for fillbuy"); return eval->Invalid("not enough vouts for fillbuy");
else if( tmporigpubkey != origpubkey ) else if( tmporigpubkey != origpubkey )
return eval->Invalid("mismatched origpubkeys for fillbuy"); return eval->Invalid("mismatched origpubkeys for fillbuy");
@@ -266,17 +267,19 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti
{ {
if( nValue != tx.vout[0].nValue + tx.vout[1].nValue ) if( nValue != tx.vout[0].nValue + tx.vout[1].nValue )
return eval->Invalid("locked value doesnt match vout0+1 fillbuy"); return eval->Invalid("locked value doesnt match vout0+1 fillbuy");
else if( tx.vout[3].scriptPubKey.IsPayToCryptoCondition() != 0 ) else if( tx.vout[4].scriptPubKey.IsPayToCryptoCondition() != 0 )
{ {
if( ConstrainVout(tx.vout[2], 1, assetsCCaddr, 0) == 0 ) // tokens on user cc addr if( ConstrainVout(tx.vout[2], 1, assetsCCaddr, 0) == 0 ) // tokens on user cc addr
return eval->Invalid("vout2 doesnt go to origpubkey fillbuy"); return eval->Invalid("vout2 doesnt go to origpubkey fillbuy");
else if ( inputs != tx.vout[2].nValue + tx.vout[3].nValue ) else if ( inputs != tx.vout[2].nValue + tx.vout[4].nValue )
return eval->Invalid("asset inputs doesnt match vout2+3 fillbuy"); return eval->Invalid("asset inputs doesnt match vout2+3 fillbuy");
} }
else if( ConstrainVout(tx.vout[2], 1, assetsCCaddr, inputs) == 0 ) // tokens on user cc addr else if( ConstrainVout(tx.vout[2], 1, assetsCCaddr, inputs) == 0 ) // tokens on user cc addr
return eval->Invalid("vout2 doesnt match inputs fillbuy"); return eval->Invalid("vout2 doesnt match inputs fillbuy");
else if( ConstrainVout(tx.vout[1],0,0,0) == 0 ) else if( ConstrainVout(tx.vout[1],0,0,0) == 0 )
return eval->Invalid("vout1 is CC for fillbuy"); return eval->Invalid("vout1 is CC for fillbuy");
else if( ConstrainVout(tx.vout[3], 1, origpubkeyCCaddr, 10000) == 0 )
return eval->Invalid("invalid marker for original pubkey");
else if( ValidateBidRemainder(remaining_price, tx.vout[0].nValue, nValue, tx.vout[1].nValue, tx.vout[2].nValue, totalunits) == false ) else if( ValidateBidRemainder(remaining_price, tx.vout[0].nValue, nValue, tx.vout[1].nValue, tx.vout[2].nValue, totalunits) == false )
return eval->Invalid("mismatched remainder for fillbuy"); return eval->Invalid("mismatched remainder for fillbuy");
else if( remaining_price != 0 ) else if( remaining_price != 0 )
@@ -345,7 +348,7 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti
if( (assetoshis = AssetValidateSellvin(cpAssets, eval, totalunits, tmporigpubkey, userTokensCCaddr, origaddr, tx, assetid)) == 0 ) if( (assetoshis = AssetValidateSellvin(cpAssets, eval, totalunits, tmporigpubkey, userTokensCCaddr, origaddr, tx, assetid)) == 0 )
return(false); return(false);
else if( numvouts < 3 ) else if( numvouts < 4 )
return eval->Invalid("not enough vouts for fillask"); return eval->Invalid("not enough vouts for fillask");
else if( tmporigpubkey != origpubkey ) else if( tmporigpubkey != origpubkey )
return eval->Invalid("mismatched origpubkeys for fillask"); return eval->Invalid("mismatched origpubkeys for fillask");
@@ -359,6 +362,8 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti
return eval->Invalid("normal vout1 for fillask"); return eval->Invalid("normal vout1 for fillask");
else if( ConstrainVout(tx.vout[2], 0, origaddr, 0) == 0 ) else if( ConstrainVout(tx.vout[2], 0, origaddr, 0) == 0 )
return eval->Invalid("normal vout1 for fillask"); return eval->Invalid("normal vout1 for fillask");
else if( ConstrainVout(tx.vout[3], 1, origpubkeyCCaddr, 10000) == 0 )
return eval->Invalid("invalid marker for original pubkey");
else if( remaining_price != 0 ) else if( remaining_price != 0 )
{ {
//char tokensUnspendableAddr[64]; //char tokensUnspendableAddr[64];

317
src/cc/cclib.cpp Normal file
View File

@@ -0,0 +1,317 @@
/******************************************************************************
* Copyright © 2014-2019 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#include <assert.h>
#include <cryptoconditions.h>
#include "primitives/block.h"
#include "primitives/transaction.h"
#include "script/cc.h"
#include "cc/eval.h"
#include "cc/utils.h"
#include "cc/CCinclude.h"
#include "main.h"
#include "chain.h"
#include "core_io.h"
#include "crosschain.h"
#define FAUCET2SIZE COIN
struct CClib_rpcinfo
{
char *method,*help;
int32_t numrequiredargs,maxargs; // frontloaded with required
uint8_t funcid;
}
CClib_methods[] =
{
{ (char *)"faucet2_fund", (char *)"amount", 1, 1, 'F' },
{ (char *)"faucet2_get", (char *)"<no args>", 0, 0, 'G' },
};
std::string MYCCLIBNAME = (char *)"faucet2";
char *CClib_name() { return((char *)MYCCLIBNAME.c_str()); }
std::string CClib_rawtxgen(struct CCcontract_info *cp,uint8_t funcid,cJSON *params);
UniValue CClib_info(struct CCcontract_info *cp)
{
UniValue result(UniValue::VOBJ),a(UniValue::VARR); int32_t i; char str[2];
result.push_back(Pair("result","success"));
result.push_back(Pair("CClib",CClib_name()));
for (i=0; i<sizeof(CClib_methods)/sizeof(*CClib_methods); i++)
{
UniValue obj(UniValue::VOBJ);
if ( CClib_methods[i].funcid < ' ' || CClib_methods[i].funcid >= 128 )
obj.push_back(Pair("funcid",CClib_methods[i].funcid));
else
{
str[0] = CClib_methods[i].funcid;
str[1] = 0;
obj.push_back(Pair("funcid",str));
}
obj.push_back(Pair("name",CClib_methods[i].method));
obj.push_back(Pair("help",CClib_methods[i].help));
obj.push_back(Pair("params_required",CClib_methods[i].numrequiredargs));
obj.push_back(Pair("params_max",CClib_methods[i].maxargs));
a.push_back(obj);
}
result.push_back(Pair("methods",a));
return(result);
}
UniValue CClib(struct CCcontract_info *cp,char *method,cJSON *params)
{
UniValue result(UniValue::VOBJ); int32_t i; std::string rawtx;
for (i=0; i<sizeof(CClib_methods)/sizeof(*CClib_methods); i++)
{
if ( strcmp(method,CClib_methods[i].method) == 0 )
{
result.push_back(Pair("result","success"));
result.push_back(Pair("method",CClib_methods[i].method));
rawtx = CClib_rawtxgen(cp,CClib_methods[i].funcid,params);
result.push_back(Pair("rawtx",rawtx));
return(result);
}
}
result.push_back(Pair("result","error"));
result.push_back(Pair("method",CClib_methods[i].method));
result.push_back(Pair("error","method not found"));
return(result);
}
int64_t IsCClibvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v)
{
char destaddr[64];
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);
}
return(0);
}
bool CClibExactAmounts(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; int64_t inputs=0,outputs=0,assetoshis;
numvins = tx.vin.size();
numvouts = tx.vout.size();
for (i=0; i<numvins; i++)
{
//fprintf(stderr,"vini.%d\n",i);
if ( (*cp->ismyvin)(tx.vin[i].scriptSig) != 0 )
{
//fprintf(stderr,"vini.%d check mempool\n",i);
if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 )
return eval->Invalid("cant find vinTx");
else
{
//fprintf(stderr,"vini.%d check hash and vout\n",i);
if ( hashBlock == zerohash )
return eval->Invalid("cant faucet2 from mempool");
if ( (assetoshis= IsCClibvout(cp,vinTx,tx.vin[i].prevout.n)) != 0 )
inputs += assetoshis;
}
}
}
for (i=0; i<numvouts; i++)
{
//fprintf(stderr,"i.%d of numvouts.%d\n",i,numvouts);
if ( (assetoshis= IsCClibvout(cp,tx,i)) != 0 )
outputs += assetoshis;
}
if ( inputs != outputs+FAUCET2SIZE+txfee )
{
fprintf(stderr,"inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs);
return eval->Invalid("mismatched inputs != outputs + FAUCET2SIZE + txfee");
}
else return(true);
}
bool CClib_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx,unsigned int nIn)
{
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;
if ( numvouts < 1 )
return eval->Invalid("no vouts");
else
{
for (i=0; i<numvins; i++)
{
if ( IsCCInput(tx.vin[0].scriptSig) == 0 )
{
fprintf(stderr,"faucetget invalid vini\n");
return eval->Invalid("illegal normal vini");
}
}
//fprintf(stderr,"check amounts\n");
if ( CClibExactAmounts(cp,eval,tx,1,10000) == false )
{
fprintf(stderr,"faucetget invalid amount\n");
return false;
}
else
{
preventCCvouts = 1;
if ( IsCClibvout(cp,tx,0) != 0 )
{
preventCCvouts++;
i = 1;
} else i = 0;
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 != FAUCET2SIZE )
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("faucet2 is only for brand new addresses");
}
}
retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts);
if ( retval != 0 )
fprintf(stderr,"faucet2get validated\n");
else fprintf(stderr,"faucet2get invalid\n");
return(retval);
}
}
}
int64_t AddCClibInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs)
{
char coinaddr[64]; int64_t threshold,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);
threshold = total/(maxinputs+1);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
txid = it->first.txhash;
vout = (int32_t)it->first.index;
if ( it->second.satoshis < threshold )
continue;
//char str[65]; fprintf(stderr,"check %s/v%d %.8f`\n",uint256_str(str,txid),vout,(double)it->second.satoshis/COIN);
// no need to prevent dup
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
{
if ( (nValue= IsCClibvout(cp,vintx,vout)) > 1000000 && myIsutxo_spentinmempool(txid,vout) == 0 )
{
if ( total != 0 && maxinputs != 0 )
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
nValue = it->second.satoshis;
totalinputs += nValue;
n++;
if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) )
break;
} else fprintf(stderr,"nValue too small or already spent in mempool\n");
} else fprintf(stderr,"couldnt get tx\n");
}
return(totalinputs);
}
std::string Faucet2Fund(struct CCcontract_info *cp,uint64_t txfee,int64_t funds)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,cclibpk; CScript opret;
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
cclibpk = GetUnspendable(cp,0);
if ( AddNormalinputs(mtx,mypk,funds+txfee,64) > 0 )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,funds,cclibpk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret));
}
return("");
}
/*UniValue FaucetInfo()
{
UniValue result(UniValue::VOBJ); char numstr[64];
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
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);
faucetpk = GetUnspendable(cp,0);
funding = AddFaucetInputs(cp,mtx,faucetpk,0,0);
sprintf(numstr,"%.8f",(double)funding/COIN);
result.push_back(Pair("funding",numstr));
return(result);
}*/
std::string CClib_rawtxgen(struct CCcontract_info *cp,uint8_t funcid,cJSON *params)
{
CMutableTransaction tmpmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,cclibpk; int64_t funds,txfee=0,inputs,CCchange=0,nValue=FAUCET2SIZE; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash;
if ( txfee == 0 )
txfee = 10000;
if ( funcid == 'F' )
{
if ( cJSON_GetArraySize(params) > 0 )
{
funds = (int64_t)jdouble(jitem(params,0),0)*COIN + 0.0000000049;
return(Faucet2Fund(cp,0,funds));
} else return("");
}
else if ( funcid != 'G' )
return("");
cclibpk = GetUnspendable(cp,0);
mypk = pubkey2pk(Mypubkey());
if ( (inputs= AddCClibInputs(cp,mtx,cclibpk,nValue+txfee,60)) > 0 )
{
if ( inputs > nValue )
CCchange = (inputs - nValue - txfee);
if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(EVAL_FIRSTUSER,CCchange,cclibpk));
mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
fprintf(stderr,"start at %u\n",(uint32_t)time(NULL));
j = rand() & 0xfffffff;
for (i=0; i<1000000; i++,j++)
{
tmpmtx = mtx;
rawhex = FinalizeCCTx(-1LL,cp,tmpmtx,mypk,txfee,CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_FIRSTUSER << (uint8_t)'G' << j));
if ( (len= (int32_t)rawhex.size()) > 0 && len < 65536 )
{
len >>= 1;
decode_hex(buf,len,(char *)rawhex.c_str());
hash = bits256_doublesha256(0,buf,len);
if ( (hash.bytes[0] & 0xff) == 0 && (hash.bytes[31] & 0xff) == 0 )
{
fprintf(stderr,"found valid txid after %d iterations %u\n",i,(uint32_t)time(NULL));
return(rawhex);
}
//fprintf(stderr,"%02x%02x ",hash.bytes[0],hash.bytes[31]);
}
}
fprintf(stderr,"couldnt generate valid txid %u\n",(uint32_t)time(NULL));
return("");
} else fprintf(stderr,"cant find faucet inputs\n");
return("");
}

View File

@@ -422,8 +422,8 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C
if ( (int32_t)it->first.index==0 && GetTransaction(it->first.txhash,tx,hashBlock,false) != 0 && (numvouts=tx.vout.size()) > 0) if ( (int32_t)it->first.index==0 && GetTransaction(it->first.txhash,tx,hashBlock,false) != 0 && (numvouts=tx.vout.size()) > 0)
{ {
if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3)!=0 && if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3)!=0 &&
(tmp_txid==openTx.GetHash() || tx.GetHash()==openTx.GetHash()) && (tmp_txid==openTx.GetHash() || tx.GetHash()==openTx.GetHash()) && IsChannelsMarkervout(cp,tx,marker==1?srcpub:destpub,marker)>0 &&
(totalinputs=IsChannelsvout(cp,tx,srcpub,destpub,0)+IsChannelsMarkervout(cp,tx,srcpub,marker))>0) (totalinputs=IsChannelsvout(cp,tx,srcpub,destpub,0))>0)
{ {
txid = it->first.txhash; txid = it->first.txhash;
break; break;
@@ -443,7 +443,7 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C
tmp_txid==openTx.GetHash() && param1 < mindepth) tmp_txid==openTx.GetHash() && param1 < mindepth)
{ {
txid=hash; txid=hash;
totalinputs=txmempool.vout[0].nValue+txmempool.vout[1].nValue; totalinputs=txmempool.vout[0].nValue;
mindepth=param1; mindepth=param1;
} }
} }
@@ -502,6 +502,8 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64
if (tokenid!=zeroid && tokens>funds) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS,tokens-funds,mypk)); if (tokenid!=zeroid && tokens>funds) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS,tokens-funds,mypk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('O',tokenid,zeroid,mypk,destpub,numpayments,payment,hashchain))); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('O',tokenid,zeroid,mypk,destpub,numpayments,payment,hashchain)));
} }
CCerror = strprintf("error adding funds");
fprintf(stderr,"%s\n",CCerror.c_str());
return(""); return("");
} }
@@ -520,30 +522,34 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
if (GetTransaction(opentxid,channelOpenTx,hashblock,false) == 0) if (GetTransaction(opentxid,channelOpenTx,hashblock,false) == 0)
{ {
fprintf(stderr, "invalid channel open txid\n"); CCerror = strprintf("invalid channel open txid");
fprintf(stderr,"%s\n",CCerror.c_str());
return(""); return("");
} }
if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tokenid, txid, srcpub, destpub, totalnumpayments, payment, hashchain)=='O') if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tokenid, txid, srcpub, destpub, totalnumpayments, payment, hashchain)=='O')
{ {
if (mypk != srcpub && mypk != destpub) if (mypk != srcpub && mypk != destpub)
{ {
fprintf(stderr,"this is not our channel\n"); CCerror = strprintf("this is not our channel");
fprintf(stderr,"%s\n",CCerror.c_str());
return(""); return("");
} }
else if (amount % payment != 0 || amount<payment) else if (amount % payment != 0 || amount<payment)
{ {
fprintf(stderr,"invalid amount, not a magnitude of payment size\n"); CCerror = strprintf("invalid amount, not a magnitude of payment size");
fprintf(stderr,"%s\n",CCerror.c_str());
return (""); return ("");
} }
} }
else else
{ {
fprintf(stderr, "invalid channel open tx\n"); CCerror = strprintf("invalid channel open tx");
fprintf(stderr,"%s\n",CCerror.c_str());
return (""); return ("");
} }
if (AddNormalinputs(mtx,mypk,2*txfee,3) > 0) if (AddNormalinputs(mtx,mypk,2*txfee,3) > 0)
{ {
if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid,mypk)) !=0 && (change=funds-amount-txfee)>=0) if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid,mypk)) !=0 && (change=funds-amount)>=0)
{ {
numpayments=amount/payment; numpayments=amount/payment;
if (GetTransaction(prevtxid,prevTx,hashblock,false) != 0 && (numvouts=prevTx.vout.size()) > 0 && if (GetTransaction(prevtxid,prevTx,hashblock,false) != 0 && (numvouts=prevTx.vout.size()) > 0 &&
@@ -552,11 +558,13 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2
{ {
if (numpayments > prevdepth) if (numpayments > prevdepth)
{ {
fprintf(stderr,"not enough funds in channel for that amount\n"); CCerror = strprintf("not enough funds in channel for that amount");
fprintf(stderr,"%s\n",CCerror.c_str());
return (""); return ("");
} else if (numpayments == 0) } else if (numpayments == 0)
{ {
fprintf(stderr,"invalid amount\n"); CCerror = strprintf("invalid amount");
fprintf(stderr,"%s\n",CCerror.c_str());
return (""); return ("");
} }
if (secret!=zeroid) if (secret!=zeroid)
@@ -570,7 +578,8 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2
endiancpy((uint8_t * ) & gensecret, hashdest, 32); endiancpy((uint8_t * ) & gensecret, hashdest, 32);
if (gensecret!=hashchain) if (gensecret!=hashchain)
{ {
fprintf(stderr,"invalid secret supplied\n"); CCerror = strprintf("invalid secret supplied");
fprintf(stderr,"%s\n",CCerror.c_str());
return(""); return("");
} }
} }
@@ -592,7 +601,8 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2
} }
else else
{ {
fprintf(stderr,"invalid previous tx\n"); CCerror = strprintf("invalid previous tx");
fprintf(stderr,"%s\n",CCerror.c_str());
return(""); return("");
} }
if (tokenid!=zeroid) mtx.vout.push_back(MakeTokensCC1of2vout(EVAL_CHANNELS, change, srcpub, destpub)); if (tokenid!=zeroid) mtx.vout.push_back(MakeTokensCC1of2vout(EVAL_CHANNELS, change, srcpub, destpub));
@@ -605,11 +615,13 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2
} }
else else
{ {
fprintf(stderr,"error adding CC inputs\n"); CCerror = strprintf("error adding CC inputs");
fprintf(stderr,"%s\n",CCerror.c_str());
return(""); return("");
} }
} }
fprintf(stderr,"error adding normal inputs\n"); CCerror = strprintf("error adding normal inputs");
fprintf(stderr,"%s\n",CCerror.c_str());
return(""); return("");
} }
@@ -629,36 +641,41 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid)
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
if (GetTransaction(opentxid,channelOpenTx,hashblock,false) == 0) if (GetTransaction(opentxid,channelOpenTx,hashblock,false) == 0)
{ {
fprintf(stderr, "invalid channel open txid\n"); CCerror = strprintf("invalid channel open txid");
fprintf(stderr,"%s\n",CCerror.c_str());
return (""); return ("");
} }
if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,numpayments,payment,hashchain)!='O') if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,numpayments,payment,hashchain)!='O')
{ {
fprintf(stderr, "invalid channel open tx\n"); CCerror = strprintf("invalid channel open tx");
fprintf(stderr,"%s\n",CCerror.c_str());
return (""); return ("");
} }
if (mypk != srcpub) if (mypk != srcpub)
{ {
fprintf(stderr,"cannot close, you are not channel owner\n"); CCerror = strprintf("cannot close, you are not channel owner");
fprintf(stderr,"%s\n",CCerror.c_str());
return(""); return("");
} }
if ( AddNormalinputs(mtx,mypk,2*txfee,3) > 0 ) if ( AddNormalinputs(mtx,mypk,2*txfee,3) > 0 )
{ {
if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid,mypk)) !=0 && funds-txfee>0) if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid,mypk)) !=0 && funds>0)
{ {
if (tokenid!=zeroid) mtx.vout.push_back(MakeTokensCC1of2vout(EVAL_CHANNELS, funds-txfee, mypk, destpub)); if (tokenid!=zeroid) mtx.vout.push_back(MakeTokensCC1of2vout(EVAL_CHANNELS, funds, mypk, destpub));
else mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, funds-txfee, mypk, destpub)); else mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, funds, mypk, destpub));
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk));
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('C',tokenid,opentxid,mypk,destpub,(funds-txfee)/payment,payment,zeroid))); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('C',tokenid,opentxid,mypk,destpub,funds/payment,payment,zeroid)));
} }
else else
{ {
fprintf(stderr,"error adding CC inputs\n"); CCerror = strprintf("error adding CC inputs");
fprintf(stderr,"%s\n",CCerror.c_str());
return(""); return("");
} }
} }
fprintf(stderr,"error adding normal inputs\n"); CCerror = strprintf("error adding normal inputs");
fprintf(stderr,"%s\n",CCerror.c_str());
return(""); return("");
} }
@@ -678,61 +695,72 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid)
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
if (GetTransaction(closetxid,channelCloseTx,hashblock,false) == 0) if (GetTransaction(closetxid,channelCloseTx,hashblock,false) == 0)
{ {
fprintf(stderr, "invalid channel close txid\n"); CCerror = strprintf("invalid channel close txid");
fprintf(stderr,"%s\n",CCerror.c_str());
return (""); return ("");
} }
if ((numvouts=channelCloseTx.vout.size()) < 1 || DecodeChannelsOpRet(channelCloseTx.vout[numvouts-1].scriptPubKey,tokenid,txid,srcpub,destpub,param1,param2,param3)!='C') if ((numvouts=channelCloseTx.vout.size()) < 1 || DecodeChannelsOpRet(channelCloseTx.vout[numvouts-1].scriptPubKey,tokenid,txid,srcpub,destpub,param1,param2,param3)!='C')
{ {
fprintf(stderr, "invalid channel close tx\n"); CCerror = strprintf("invalid channel close tx");
fprintf(stderr,"%s\n",CCerror.c_str());
return (""); return ("");
} }
if (txid!=opentxid) if (txid!=opentxid)
{ {
fprintf(stderr, "open and close txid are not from same channel\n"); CCerror = strprintf("open and close txid are not from same channel");
fprintf(stderr,"%s\n",CCerror.c_str());
return (""); return ("");
} }
if (GetTransaction(opentxid,channelOpenTx,hashblock,false) == 0) if (GetTransaction(opentxid,channelOpenTx,hashblock,false) == 0)
{ {
fprintf(stderr, "invalid channel open txid\n"); CCerror = strprintf("invalid channel open txid");
fprintf(stderr,"%s\n",CCerror.c_str());
return (""); return ("");
} }
if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tokenid,txid,srcpub,destpub,numpayments,payment,hashchain)!='O') if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tokenid,txid,srcpub,destpub,numpayments,payment,hashchain)!='O')
{ {
fprintf(stderr, "invalid channel open tx\n"); CCerror = strprintf("invalid channel open tx");
fprintf(stderr,"%s\n",CCerror.c_str());
return (""); return ("");
} }
if (mypk != srcpub) if (mypk != srcpub)
{ {
fprintf(stderr,"cannot refund, you are not the channel owenr\n"); CCerror = strprintf("cannot refund, you are not the channel owner");
fprintf(stderr,"%s\n",CCerror.c_str());
return(""); return("");
} }
if ( AddNormalinputs(mtx,mypk,2*txfee,3) > 0 ) if ( AddNormalinputs(mtx,mypk,2*txfee,3) > 0 )
{ {
if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid,mypk)) !=0 && funds-txfee>0) if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid,mypk)) !=0 && funds>0)
{ {
if ((GetTransaction(prevtxid,prevTx,hashblock,false) != 0) && (numvouts=prevTx.vout.size()) > 0 && if ((GetTransaction(prevtxid,prevTx,hashblock,false) != 0) && (numvouts=prevTx.vout.size()) > 0 &&
DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, txid, srcpub, destpub, param1, param2, param3) != 0) DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, txid, srcpub, destpub, param1, param2, param3) != 0)
{ {
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk));
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub));
if (tokenid!=zeroid) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS,funds-txfee,mypk)); if (tokenid!=zeroid) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS,funds,mypk));
else mtx.vout.push_back(CTxOut(funds-txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); else mtx.vout.push_back(CTxOut(funds,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('R',tokenid,opentxid,mypk,destpub,param1,payment,closetxid))); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('R',tokenid,opentxid,mypk,destpub,funds/payment,payment,closetxid)));
} }
else else
{ {
fprintf(stderr,"previous tx is invalid\n"); CCerror = strprintf("previous tx is invalid");
fprintf(stderr,"%s\n",CCerror.c_str());
return(""); return("");
} }
} }
else else
{ {
fprintf(stderr,"error adding CC inputs\n"); CCerror = strprintf("error adding CC inputs");
fprintf(stderr,"%s\n",CCerror.c_str());
return(""); return("");
} }
} }
CCerror = strprintf("error adding normal inputs");
fprintf(stderr,"%s\n",CCerror.c_str());
return(""); return("");
} }
UniValue ChannelsList() UniValue ChannelsList()
{ {
UniValue result(UniValue::VOBJ); std::vector<std::pair<CAddressIndexKey, CAmount> > txids; struct CCcontract_info *cp,C; uint256 txid,hashBlock,tmp_txid,param3,tokenid; UniValue result(UniValue::VOBJ); std::vector<std::pair<CAddressIndexKey, CAmount> > txids; struct CCcontract_info *cp,C; uint256 txid,hashBlock,tmp_txid,param3,tokenid;

View File

@@ -27,6 +27,8 @@
#include "core_io.h" #include "core_io.h"
#include "crosschain.h" #include "crosschain.h"
bool CClib_Dispatch(const CC *cond,Eval *eval,std::vector<uint8_t> paramsNull,const CTransaction &txTo,unsigned int nIn);
char *CClib_name();
Eval* EVAL_TEST = 0; Eval* EVAL_TEST = 0;
struct CCcontract_info CCinfos[0x100]; struct CCcontract_info CCinfos[0x100];
@@ -65,13 +67,24 @@ bool Eval::Dispatch(const CC *cond, const CTransaction &txTo, unsigned int nIn)
return Invalid("empty-eval"); return Invalid("empty-eval");
uint8_t ecode = cond->code[0]; uint8_t ecode = cond->code[0];
if ( ASSETCHAINS_CCDISABLES[ecode] != 0 )
{
fprintf(stderr,"%s evalcode.%d %02x\n",txTo.GetHash().GetHex().c_str(),ecode,ecode);
return Invalid("disabled-code, -ac_ccenables didnt include this ecode");
}
std::vector<uint8_t> vparams(cond->code+1, cond->code+cond->codeLength);
if ( ecode >= EVAL_FIRSTUSER && ecode <= EVAL_LASTUSER )
{
if ( ASSETCHAINS_CCLIB.size() > 0 && ASSETCHAINS_CCLIB == CClib_name() )
return CClib_Dispatch(cond,this,vparams,txTo,nIn);
else return Invalid("mismatched -ac_cclib vs CClib_name");
}
cp = &CCinfos[(int32_t)ecode]; cp = &CCinfos[(int32_t)ecode];
if ( cp->didinit == 0 ) if ( cp->didinit == 0 )
{ {
CCinit(cp,ecode); CCinit(cp,ecode);
cp->didinit = 1; cp->didinit = 1;
} }
std::vector<uint8_t> vparams(cond->code+1, cond->code+cond->codeLength);
switch ( ecode ) switch ( ecode )
{ {
case EVAL_IMPORTPAYOUT: case EVAL_IMPORTPAYOUT:

View File

@@ -59,6 +59,10 @@
EVAL(EVAL_TOKENS, 0xf2) EVAL(EVAL_TOKENS, 0xf2)
// evalcodes 0x10 to 0x7f are reserved for cclib dynamic CC
#define EVAL_FIRSTUSER 0x10
#define EVAL_LASTUSER 0x7f
typedef uint8_t EvalCode; typedef uint8_t EvalCode;

View File

@@ -15,6 +15,7 @@
#include "CCHeir.h" #include "CCHeir.h"
#include "heir_validate.h" #include "heir_validate.h"
#include <iomanip>
class CoinHelper; class CoinHelper;
class TokenHelper; class TokenHelper;
@@ -56,13 +57,14 @@ template <typename Helper> bool RunValidationPlans(uint8_t funcId, struct CCcont
// only for tokens: // only for tokens:
CMyPubkeyVoutValidator<TokenHelper> ownerCCaddrValidator(cp, fundingOpretScript, false); // check if this correct owner's cc user addr corresponding to opret CMyPubkeyVoutValidator<TokenHelper> ownerCCaddrValidator(cp, fundingOpretScript, false); // check if this correct owner's cc user addr corresponding to opret
COpRetValidator<Helper> opRetValidator(cp, fundingOpretScript); // compare opRets in this and last tx COpRetValidator<Helper> opRetValidator(cp, fundingOpretScript); // compare opRets in this and last tx
CMarkerValidator<Helper> markerValidator(cp); // initial tx marker spending protection
CNullValidator<Helper> nullValidator(cp); CNullValidator<Helper> nullValidator(cp);
switch (funcId) { switch (funcId) {
case 'F': // fund tokens case 'F': // fund tokens (only for tokens)
// vin validation plan: // vin validation plan:
vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&normalInputIdentifier, &nullValidator); // txfee vin vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&normalInputIdentifier, &nullValidator); // txfee vin
vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&ccInputIdentifier, &ownerCCaddrValidator); // check cc owner addr vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&ccInputIdentifier, &markerValidator, &ownerCCaddrValidator); // check cc owner addr
// vout validation plan: // vout validation plan:
voutPlan.pushValidators<CValidatorBase>(0, &cc1of2ValidatorThis); // check 1of2 addr funding voutPlan.pushValidators<CValidatorBase>(0, &cc1of2ValidatorThis); // check 1of2 addr funding
@@ -70,10 +72,10 @@ template <typename Helper> bool RunValidationPlans(uint8_t funcId, struct CCcont
// no checking for opret yet // no checking for opret yet
break; break;
case 'A': // add tokens case 'A': // add tokens (only for tokens)
// vin validation plan: // vin validation plan:
vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&normalInputIdentifier, &nullValidator); // txfee vin vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&normalInputIdentifier, &nullValidator); // txfee vin
vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&ccInputIdentifier, &ownerCCaddrValidator); // check cc owner addr vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&ccInputIdentifier, &markerValidator, &ownerCCaddrValidator); // check cc owner addr
// vout validation plan: // vout validation plan:
voutPlan.pushValidators<CValidatorBase>(0, &cc1of2ValidatorThis); // check 1of2 addr funding voutPlan.pushValidators<CValidatorBase>(0, &cc1of2ValidatorThis); // check 1of2 addr funding
@@ -81,10 +83,10 @@ template <typename Helper> bool RunValidationPlans(uint8_t funcId, struct CCcont
voutPlan.pushValidators<CValidatorBase>(numvouts - 1, &opRetValidator); // opreturn check, NOTE: only for C or A: voutPlan.pushValidators<CValidatorBase>(numvouts - 1, &opRetValidator); // opreturn check, NOTE: only for C or A:
break; break;
case 'C': case 'C': // spend coins or tokens
// vin validation plan: // vin validation plan:
vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&normalInputIdentifier, &nullValidator); // txfee vin vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&normalInputIdentifier, &nullValidator); // txfee vin
vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&ccInputIdentifier, &cc1of2ValidatorThis); // cc1of2 funding addr vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&ccInputIdentifier, &markerValidator, &cc1of2ValidatorThis); // cc1of2 funding addr
// vout validation plan: // vout validation plan:
voutPlan.pushValidators<CValidatorBase>(0, &heirSpendValidator); // check if heir is allowed to spend voutPlan.pushValidators<CValidatorBase>(0, &heirSpendValidator); // check if heir is allowed to spend
@@ -400,6 +402,23 @@ uint8_t DecodeHeirEitherOpRet(CScript scriptPubKey, uint256 &tokenid, uint256 &f
return _DecodeHeirEitherOpRet(scriptPubKey, tokenid, dummyOwnerPubkey, dummyHeirPubkey, dummyInactivityTime, dummyHeirName, fundingTxidInOpret, hasHeirSpendingBegun, noLogging); return _DecodeHeirEitherOpRet(scriptPubKey, tokenid, dummyOwnerPubkey, dummyHeirPubkey, dummyInactivityTime, dummyHeirName, fundingTxidInOpret, hasHeirSpendingBegun, noLogging);
} }
// check if pubkey is in vins
void CheckVinPubkey(std::vector<CTxIn> vins, CPubKey pubkey, bool &hasPubkey, bool &hasOtherPubkey) {
hasPubkey = false;
hasOtherPubkey = false;
for (auto vin : vins) {
CPubKey vinPubkey = check_signing_pubkey(vin.scriptSig);
if (vinPubkey.IsValid()) {
if (vinPubkey == pubkey)
hasPubkey = true;
if (vinPubkey != pubkey)
hasOtherPubkey = true;
}
}
}
/** /**
* find the latest funding tx: it may be the first F tx or one of A or C tx's * find the latest funding tx: it may be the first F tx or one of A or C tx's
* Note: this function is also called from validation code (use non-locking calls) * Note: this function is also called from validation code (use non-locking calls)
@@ -471,10 +490,20 @@ uint256 _FindLatestFundingTx(uint256 fundingtxid, uint8_t& funcId, uint256 &toke
if (tmpFuncId != 0 && fundingtxid == fundingTxidInOpret && (tokenid == zeroid || tokenid == tokenidInOpret)) { // check tokenid also if (tmpFuncId != 0 && fundingtxid == fundingTxidInOpret && (tokenid == zeroid || tokenid == tokenidInOpret)) { // check tokenid also
if (blockHeight > maxBlockHeight) { if (blockHeight > maxBlockHeight) {
// check owner pubkey in vins
bool isOwner = false;
bool isNonOwner = false;
CheckVinPubkey(regtx.vin, ownerPubkey, isOwner, isNonOwner);
// we ignore 'donations' tx (with non-owner inputs) for calculating if heir is allowed to spend:
if (isOwner && !isNonOwner) {
hasHeirSpendingBegun = hasHeirSpendingBegunInOpret;
maxBlockHeight = blockHeight; maxBlockHeight = blockHeight;
latesttxid = txid; latesttxid = txid;
funcId = tmpFuncId; funcId = tmpFuncId;
hasHeirSpendingBegun = hasHeirSpendingBegunInOpret; }
//std::cerr << "FindLatestFundingTx() txid=" << latesttxid.GetHex() << " at blockHeight=" << maxBlockHeight //std::cerr << "FindLatestFundingTx() txid=" << latesttxid.GetHex() << " at blockHeight=" << maxBlockHeight
// << " opreturn type=" << (char)(funcId ? funcId : ' ') << " hasHeirSpendingBegun=" << (int)hasHeirSpendingBegun << " - set as current lasttxid" << '\n'; // << " opreturn type=" << (char)(funcId ? funcId : ' ') << " hasHeirSpendingBegun=" << (int)hasHeirSpendingBegun << " - set as current lasttxid" << '\n';
@@ -615,7 +644,7 @@ template <class Helper> int64_t LifetimeHeirContractFunds(struct CCcontract_info
* and also for setting spending plan for the funds' owner and heir * and also for setting spending plan for the funds' owner and heir
* @return fundingtxid handle for subsequent references to this heir funding plan * @return fundingtxid handle for subsequent references to this heir funding plan
*/ */
template <typename Helper> UniValue HeirFund(uint64_t txfee, int64_t amount, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid) template <typename Helper> UniValue _HeirFund(int64_t txfee, int64_t amount, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid)
{ {
UniValue result(UniValue::VOBJ); UniValue result(UniValue::VOBJ);
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
@@ -625,26 +654,32 @@ template <typename Helper> UniValue HeirFund(uint64_t txfee, int64_t amount, std
if (txfee == 0) if (txfee == 0)
txfee = 10000; txfee = 10000;
int64_t markerfee = 10000;
//std::cerr << "HeirFund() amount=" << amount << " txfee=" << txfee << " heirPubkey IsValid()=" << heirPubkey.IsValid() << " inactivityTime(sec)=" << inactivityTimeSec << " tokenid=" << tokenid.GetHex() << std::endl; //std::cerr << "HeirFund() amount=" << amount << " txfee=" << txfee << " heirPubkey IsValid()=" << heirPubkey.IsValid() << " inactivityTime(sec)=" << inactivityTimeSec << " tokenid=" << tokenid.GetHex() << std::endl;
if (!heirPubkey.IsValid()) { if (!heirPubkey.IsValid()) {
std::cerr << "HeirFund() heirPubkey is not valid!" << std::endl; std::cerr << "HeirFund() heirPubkey is not valid!" << std::endl;
return std::string(""); result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "invalid heir pubkey"));
} }
CPubKey myPubkey = pubkey2pk(Mypubkey()); CPubKey myPubkey = pubkey2pk(Mypubkey());
if (AddNormalinputs(mtx, myPubkey, txfee, 3) > 0) { // txfee for miners if (AddNormalinputs(mtx, myPubkey, markerfee, 3) > 0) {
int64_t inputs, change; int64_t inputs, change;
if ((inputs=Helper::addOwnerInputs(tokenid, mtx, myPubkey, amount, (int32_t)64)) > 0) { // 2 x txfee: 1st for marker vout, 2nd to miners if ((inputs=Helper::addOwnerInputs(tokenid, mtx, myPubkey, amount, (int32_t)64)) > 0) {
//mtx.vout.push_back(MakeTokensCC1of2vout(/*Helper::getMyEval()*/EVAL_HEIR, amount, myPubkey, heirPubkey)); // add cryptocondition to spend amount for either pk
mtx.vout.push_back(Helper::make1of2Vout(amount, myPubkey, heirPubkey)); mtx.vout.push_back(Helper::make1of2Vout(amount, myPubkey, heirPubkey));
// add a marker for finding all plans in HeirList() // add a marker for finding all plans in HeirList()
// TODO: change marker either to cc or normal txidaddr unspendable // TODO: change marker either to cc or normal txidaddr unspendable
CPubKey heirUnspendablePubKey = GetUnspendable(cp, 0); struct CCcontract_info *cpHeir, heirC;
mtx.vout.push_back(CTxOut(txfee, CScript() << ParseHex(HexStr(heirUnspendablePubKey)) << OP_CHECKSIG)); // TODO: do we need this marker? cpHeir = CCinit(&heirC, EVAL_HEIR);
CPubKey heirUnspendablePubKey = GetUnspendable(cpHeir, 0);
// mtx.vout.push_back(CTxOut(txfee, CScript() << ParseHex(HexStr(heirUnspendablePubKey)) << OP_CHECKSIG)); <-- bad marker cause it was spendable by anyone
mtx.vout.push_back(MakeCC1vout(EVAL_HEIR, markerfee, heirUnspendablePubKey)); // this marker spending is disabled in the validation code
// calc and add change vout: // calc and add change vout:
if (inputs > amount) if (inputs > amount)
@@ -656,6 +691,19 @@ template <typename Helper> UniValue HeirFund(uint64_t txfee, int64_t amount, std
mtx.vout.push_back(Helper::makeUserVout(change, myPubkey)); mtx.vout.push_back(Helper::makeUserVout(change, myPubkey));
} }
// check owner pubkey in vins
bool hasMypubkey = false;
bool hasNotMypubkey = false;
CheckVinPubkey(mtx.vin, myPubkey, hasMypubkey, hasNotMypubkey);
// for initial funding do not allow to sign by non-owner key:
if (hasNotMypubkey) {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "using non-owner inputs not allowed"));
return result;
}
// add 1of2 vout validation pubkeys: // add 1of2 vout validation pubkeys:
std::vector<CPubKey> voutTokenPubkeys; std::vector<CPubKey> voutTokenPubkeys;
voutTokenPubkeys.push_back(myPubkey); voutTokenPubkeys.push_back(myPubkey);
@@ -689,12 +737,12 @@ template <typename Helper> UniValue HeirFund(uint64_t txfee, int64_t amount, std
} }
// if no these callers - it could not link // if no these callers - it could not link
UniValue HeirFundCoinCaller(uint64_t txfee, int64_t funds, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid){ UniValue HeirFundCoinCaller(int64_t txfee, int64_t satoshis, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid){
return HeirFund<CoinHelper>(txfee, funds, heirName, heirPubkey, inactivityTimeSec, tokenid); return _HeirFund<CoinHelper>(txfee, satoshis, heirName, heirPubkey, inactivityTimeSec, tokenid);
} }
UniValue HeirFundTokenCaller(uint64_t txfee, int64_t funds, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid) { UniValue HeirFundTokenCaller(int64_t txfee, int64_t satoshis, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid) {
return HeirFund<TokenHelper>(txfee, funds, heirName, heirPubkey, inactivityTimeSec, tokenid); return _HeirFund<TokenHelper>(txfee, satoshis, heirName, heirPubkey, inactivityTimeSec, tokenid);
} }
/** /**
@@ -702,7 +750,7 @@ UniValue HeirFundTokenCaller(uint64_t txfee, int64_t funds, std::string heirName
* creates tx to add more funds to cryptocondition address for spending by either funds' owner or heir * creates tx to add more funds to cryptocondition address for spending by either funds' owner or heir
* @return result object with raw tx or error text * @return result object with raw tx or error text
*/ */
template <class Helper> UniValue _HeirAdd(uint256 fundingtxid, uint64_t txfee, int64_t amount, uint256 latesttxid, uint8_t funcId, uint256 tokenid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, uint8_t hasHeirSpendingBegun) template <class Helper> UniValue _HeirAdd(uint256 fundingtxid, int64_t txfee, int64_t amount, uint256 latesttxid, uint8_t funcId, uint256 tokenid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, uint8_t hasHeirSpendingBegun)
{ {
UniValue result(UniValue::VOBJ); UniValue result(UniValue::VOBJ);
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
@@ -715,6 +763,8 @@ template <class Helper> UniValue _HeirAdd(uint256 fundingtxid, uint64_t txfee, i
if (txfee == 0) if (txfee == 0)
txfee = 10000; txfee = 10000;
int64_t markerfee = 10000;
CPubKey myPubkey = pubkey2pk(Mypubkey()); CPubKey myPubkey = pubkey2pk(Mypubkey());
// check if it is the owner // check if it is the owner
@@ -724,7 +774,7 @@ template <class Helper> UniValue _HeirAdd(uint256 fundingtxid, uint64_t txfee, i
return result; return result;
} }
if (AddNormalinputs(mtx, myPubkey, txfee, 3) > 0) { // txfee for miners if (AddNormalinputs(mtx, myPubkey, markerfee, 3) > 0) { // some for marker
int64_t inputs, change; int64_t inputs, change;
@@ -740,6 +790,10 @@ template <class Helper> UniValue _HeirAdd(uint256 fundingtxid, uint64_t txfee, i
// add cryptocondition to spend this funded amount for either pk // add cryptocondition to spend this funded amount for either pk
mtx.vout.push_back(Helper::make1of2Vout(amount, ownerPubkey, heirPubkey)); mtx.vout.push_back(Helper::make1of2Vout(amount, ownerPubkey, heirPubkey));
char markeraddr[64];
CPubKey markerPubkey = CCtxidaddr(markeraddr, fundingtxid);
mtx.vout.push_back(CTxOut(markerfee, CScript() << ParseHex(HexStr(markerPubkey)) << OP_CHECKSIG)); // marker to prevent archiving of the funds add vouts
if (inputs > amount) if (inputs > amount)
change = (inputs - amount); // -txfee <-- txfee pays user change = (inputs - amount); // -txfee <-- txfee pays user
@@ -749,6 +803,28 @@ template <class Helper> UniValue _HeirAdd(uint256 fundingtxid, uint64_t txfee, i
mtx.vout.push_back(Helper::makeUserVout(change, myPubkey)); mtx.vout.push_back(Helper::makeUserVout(change, myPubkey));
} }
// check owner pubkey in vins
bool hasMypubkey = false;
bool hasNotMypubkey = false;
CheckVinPubkey(mtx.vin, myPubkey, hasMypubkey, hasNotMypubkey);
// for additional funding do not allow to sign by both owner and non-owner keys (is this a donation or not?):
if (hasMypubkey && hasNotMypubkey) {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "using both owner and non-owner inputs is not allowed"));
return result;
}
// warn the user he's making a donation if this is all non-owner keys:
if (hasNotMypubkey) {
result.push_back(Pair("result", "warning"));
result.push_back(Pair("warning", "you are about to make a donation to heir fund"));
}
else {
result.push_back(Pair("result", "success"));
}
// add 1of2 vout validation pubkeys - needed only for tokens: // add 1of2 vout validation pubkeys - needed only for tokens:
std::vector<CPubKey> voutTokenPubkeys; std::vector<CPubKey> voutTokenPubkeys;
voutTokenPubkeys.push_back(ownerPubkey); voutTokenPubkeys.push_back(ownerPubkey);
@@ -759,11 +835,11 @@ template <class Helper> UniValue _HeirAdd(uint256 fundingtxid, uint64_t txfee, i
Helper::makeAddOpRet(tokenid, voutTokenPubkeys, fundingtxid, hasHeirSpendingBegun))); Helper::makeAddOpRet(tokenid, voutTokenPubkeys, fundingtxid, hasHeirSpendingBegun)));
if (!rawhextx.empty()) { if (!rawhextx.empty()) {
result.push_back(Pair("result", "success"));
result.push_back(Pair("hextx", rawhextx)); result.push_back(Pair("hextx", rawhextx));
} }
else { else {
std::cerr << "HeirAdd error in FinalizeCCtx" << std::endl; std::cerr << "HeirAdd error in FinalizeCCtx" << std::endl;
result.clear();
result.push_back(Pair("result", "error")); result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "sign error")); result.push_back(Pair("error", "sign error"));
} }
@@ -781,13 +857,11 @@ template <class Helper> UniValue _HeirAdd(uint256 fundingtxid, uint64_t txfee, i
result.push_back(Pair("error", "can't find normal inputs for tx fee")); result.push_back(Pair("error", "can't find normal inputs for tx fee"));
} }
return result; return result;
} }
UniValue HeirAddCaller(uint256 fundingtxid, uint64_t txfee, int64_t amount) { UniValue HeirAddCaller(uint256 fundingtxid, int64_t txfee, std::string strAmount) {
CPubKey ownerPubkey, heirPubkey; CPubKey ownerPubkey, heirPubkey;
int64_t inactivityTimeSec; int64_t inactivityTimeSec;
@@ -798,11 +872,28 @@ UniValue HeirAddCaller(uint256 fundingtxid, uint64_t txfee, int64_t amount) {
uint8_t hasHeirSpendingBegun = 0; uint8_t hasHeirSpendingBegun = 0;
if ((latesttxid = FindLatestFundingTx(fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun)) != zeroid) { if ((latesttxid = FindLatestFundingTx(fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun)) != zeroid) {
if (tokenid == zeroid) if (tokenid == zeroid) {
int64_t amount = (int64_t)(atof(strAmount.c_str()) * COIN);
if (amount <= 0) {
UniValue result(UniValue::VOBJ);
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "invalid amount"));
return result;
}
return _HeirAdd<CoinHelper>(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun); return _HeirAdd<CoinHelper>(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun);
else }
else {
int64_t amount = atoll(strAmount.c_str());
if (amount <= 0) {
UniValue result(UniValue::VOBJ);
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "invalid amount"));
return result;
}
return _HeirAdd<TokenHelper>(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun); return _HeirAdd<TokenHelper>(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun);
} }
}
else { else {
UniValue result(UniValue::VOBJ); UniValue result(UniValue::VOBJ);
@@ -819,7 +910,7 @@ UniValue HeirAddCaller(uint256 fundingtxid, uint64_t txfee, int64_t amount) {
* creates tx to spend funds from cryptocondition address by either funds' owner or heir * creates tx to spend funds from cryptocondition address by either funds' owner or heir
* @return result object with raw tx or error text * @return result object with raw tx or error text
*/ */
template <typename Helper>UniValue _HeirClaim(uint256 fundingtxid, uint64_t txfee, int64_t amount, uint256 latesttxid, uint8_t funcId, uint256 tokenid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, uint8_t hasHeirSpendingBegun) template <typename Helper>UniValue _HeirClaim(uint256 fundingtxid, int64_t txfee, int64_t amount, uint256 latesttxid, uint8_t funcId, uint256 tokenid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, uint8_t hasHeirSpendingBegun)
{ {
UniValue result(UniValue::VOBJ); UniValue result(UniValue::VOBJ);
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
@@ -940,7 +1031,7 @@ template <typename Helper>UniValue _HeirClaim(uint256 fundingtxid, uint64_t txfe
return result; return result;
} }
UniValue HeirClaimCaller(uint256 fundingtxid, uint64_t txfee, int64_t amount) { UniValue HeirClaimCaller(uint256 fundingtxid, int64_t txfee, std::string strAmount) {
CPubKey ownerPubkey, heirPubkey; CPubKey ownerPubkey, heirPubkey;
int64_t inactivityTimeSec; int64_t inactivityTimeSec;
@@ -951,10 +1042,26 @@ UniValue HeirClaimCaller(uint256 fundingtxid, uint64_t txfee, int64_t amount) {
uint8_t hasHeirSpendingBegun = 0; uint8_t hasHeirSpendingBegun = 0;
if ((latesttxid = FindLatestFundingTx(fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun)) != zeroid) { if ((latesttxid = FindLatestFundingTx(fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun)) != zeroid) {
if( tokenid == zeroid ) if (tokenid == zeroid) {
int64_t amount = (int64_t)(atof(strAmount.c_str()) * COIN);
if (amount < 0) {
UniValue result(UniValue::VOBJ);
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "invalid amount"));
return result;
}
return _HeirClaim<CoinHelper>(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun); return _HeirClaim<CoinHelper>(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun);
else }
else {
int64_t amount = atoll(strAmount.c_str());
if (amount <= 0) {
UniValue result(UniValue::VOBJ);
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "invalid amount"));
return result;
}
return _HeirClaim<TokenHelper>(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun); return _HeirClaim<TokenHelper>(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun);
}
} }
else { else {
@@ -1022,6 +1129,8 @@ UniValue HeirInfo(uint256 fundingtxid)
std::ostringstream stream; std::ostringstream stream;
std::string msg; std::string msg;
//sleep(10);
result.push_back(Pair("fundingtxid", fundingtxid.GetHex())); result.push_back(Pair("fundingtxid", fundingtxid.GetHex()));
result.push_back(Pair("name", heirName.c_str())); result.push_back(Pair("name", heirName.c_str()));
@@ -1052,7 +1161,7 @@ UniValue HeirInfo(uint256 fundingtxid)
if (tokenid == zeroid) { if (tokenid == zeroid) {
msg = "funding total in coins"; msg = "funding total in coins";
stream << (double)total / COIN; stream << std::fixed << std::setprecision(8) << (double)total / COIN;
} }
else { else {
msg = "funding total in tokens"; msg = "funding total in tokens";
@@ -1070,7 +1179,7 @@ UniValue HeirInfo(uint256 fundingtxid)
if (tokenid == zeroid) { if (tokenid == zeroid) {
msg = "funding available in coins"; msg = "funding available in coins";
stream << (double)inputs / COIN; stream << std::fixed << std::setprecision(8) << (double)inputs / COIN;
} }
else { else {
msg = "funding available in tokens"; msg = "funding available in tokens";
@@ -1090,13 +1199,13 @@ UniValue HeirInfo(uint256 fundingtxid)
} }
stream << inactivityTimeSec; stream << inactivityTimeSec;
result.push_back(Pair("inactivity time setting", stream.str().c_str())); result.push_back(Pair("inactivity time setting, sec", stream.str().c_str()));
stream.str(""); stream.str("");
stream.clear(); stream.clear();
if (!hasHeirSpendingBegun) { // we do not need find duration if the spending already has begun if (!hasHeirSpendingBegun) { // we do not need find duration if the spending already has begun
durationSec = CCduration(numblocks, latestFundingTxid); durationSec = CCduration(numblocks, latestFundingTxid);
std::cerr << "HeirInfo() duration=" << durationSec << " inactivityTime=" << inactivityTimeSec << " numblocks=" << numblocks << '\n'; std::cerr << "HeirInfo() duration (sec)=" << durationSec << " inactivityTime (sec)=" << inactivityTimeSec << " numblocks=" << numblocks << '\n';
} }
stream << std::boolalpha << (hasHeirSpendingBegun || durationSec > inactivityTimeSec); stream << std::boolalpha << (hasHeirSpendingBegun || durationSec > inactivityTimeSec);
@@ -1104,6 +1213,14 @@ UniValue HeirInfo(uint256 fundingtxid)
stream.str(""); stream.str("");
stream.clear(); stream.clear();
// adding owner current inactivity time:
if (!hasHeirSpendingBegun && durationSec <= inactivityTimeSec) {
stream << durationSec;
result.push_back(Pair("owner inactivity time, sec", stream.str().c_str()));
stream.str("");
stream.clear();
}
result.push_back(Pair("result", "success")); result.push_back(Pair("result", "success"));
} }
else { else {
@@ -1123,15 +1240,15 @@ UniValue HeirInfo(uint256 fundingtxid)
* @return list of heir plan handles (fundingtxid) * @return list of heir plan handles (fundingtxid)
*/ */
template <typename Helper>void _HeirList(struct CCcontract_info *cp, UniValue &result) void _HeirList(struct CCcontract_info *cp, UniValue &result)
{ {
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue>> unspentOutputs; std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue>> unspentOutputs;
char coinaddr[64]; char markeraddr[64];
CPubKey ccPubKeyEmpty;
GetCCaddress(cp, coinaddr, ccPubKeyEmpty);
SetCCunspents(unspentOutputs, cp->normaladdr);
//std::cerr << "HeirList() finding heir marker from Heir contract addr=" << cp->normaladdr << " unspentOutputs.size()=" << unspentOutputs.size() << '\n'; GetCCaddress(cp, markeraddr, GetUnspendable(cp, NULL));
SetCCunspents(unspentOutputs, markeraddr);
//std::cerr << "HeirList() finding heir marker from unspendable addr=" << markeraddr << " unspentOutputs.size()=" << unspentOutputs.size() << '\n';
// TODO: move marker to special cc addr to prevent checking all tokens // TODO: move marker to special cc addr to prevent checking all tokens
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue>>::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue>>::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) {
@@ -1177,10 +1294,10 @@ UniValue HeirList()
struct CCcontract_info *cpHeir, *cpTokens, heirC, tokenC; // NOTE we must use a separate 'C' structure for each CCinit! struct CCcontract_info *cpHeir, *cpTokens, heirC, tokenC; // NOTE we must use a separate 'C' structure for each CCinit!
cpHeir = CCinit(&heirC, EVAL_HEIR); cpHeir = CCinit(&heirC, EVAL_HEIR);
cpTokens = CCinit(&tokenC, EVAL_TOKENS); //cpTokens = CCinit(&tokenC, EVAL_TOKENS);
_HeirList<CoinHelper>(cpHeir, result); _HeirList(cpHeir, result);
_HeirList<TokenHelper>(cpTokens, result); //_HeirList<TokenHelper>(cpTokens, result); not used anymore
return result; return result;
} }

View File

@@ -125,8 +125,8 @@ class CValidatorBase
public: public:
CValidatorBase(CCcontract_info* cp) : m_cp(cp) {} CValidatorBase(CCcontract_info* cp) : m_cp(cp) {}
virtual bool isVinValidator() const = 0; virtual bool isVinValidator() const = 0;
virtual bool validateVin(CTxIn vin, CTxOut prevVout, std::string& message) const = 0; virtual bool validateVin(CTxIn vin, std::vector<CTxOut> prevVout, int32_t prevN, std::string& message) const = 0;
virtual bool validateVout(CTxOut vout, std::string& message) const = 0; virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const = 0;
protected: protected:
CCcontract_info * m_cp; CCcontract_info * m_cp;
@@ -258,10 +258,10 @@ private:
if (v->isVinValidator()) if (v->isVinValidator())
// validate this vin and previous vout: // validate this vin and previous vout:
result = v->validateVin(pTx->vin[iv], pPrevTx->vout[pTx->vin[iv].prevout.n], refMessage); result = v->validateVin(pTx->vin[iv], pPrevTx->vout, pTx->vin[iv].prevout.n, refMessage);
else else
// if it is vout validator pass the previous tx vout: // if it is vout validator pass the previous tx vout:
result = v->validateVout( pPrevTx->vout[pTx->vin[iv].prevout.n], refMessage); result = v->validateVout( pPrevTx->vout[pTx->vin[iv].prevout.n], pTx->vin[iv].prevout.n, refMessage);
if (!result) { if (!result) {
return result; return result;
} }
@@ -359,7 +359,7 @@ private:
if (!v->isVinValidator()) { if (!v->isVinValidator()) {
// if this is a 'in' validation plan then pass the previous tx vout: // if this is a 'in' validation plan then pass the previous tx vout:
bool result = v->validateVout(pTx->vout[iv], refMessage); bool result = v->validateVout(pTx->vout[iv], iv, refMessage);
if (!result) if (!result)
return result; return result;
} }
@@ -402,7 +402,7 @@ public:
m_fundingOpretScript(opRetScript), m_customMessage(customMessage), CValidatorBase(cp) {} m_fundingOpretScript(opRetScript), m_customMessage(customMessage), CValidatorBase(cp) {}
virtual bool isVinValidator() const { return false; } virtual bool isVinValidator() const { return false; }
virtual bool validateVout(CTxOut vout, std::string& message) const virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const
{ {
//std::cerr << "CCC1of2AddressValidator::validateVout() entered" << std::endl; //std::cerr << "CCC1of2AddressValidator::validateVout() entered" << std::endl;
CPubKey ownerPubkey, heirPubkey; CPubKey ownerPubkey, heirPubkey;
@@ -438,7 +438,7 @@ public:
std::cerr << "CCC1of2AddressValidator::validateVout() exits with false: " << message << std::endl; std::cerr << "CCC1of2AddressValidator::validateVout() exits with false: " << message << std::endl;
return false; return false;
} }
virtual bool validateVin(CTxIn vin, CTxOut prevVout, std::string& message) const { return false; } virtual bool validateVin(CTxIn vin, std::vector<CTxOut> prevVout, int32_t prevN, std::string& message) const { return false; }
private: private:
CScript m_fundingOpretScript; CScript m_fundingOpretScript;
@@ -456,7 +456,7 @@ public:
: m_fundingOpretScript(opRetScript), m_checkNormals(checkNormals), CValidatorBase(cp) { } : m_fundingOpretScript(opRetScript), m_checkNormals(checkNormals), CValidatorBase(cp) { }
virtual bool isVinValidator() const { return false; } virtual bool isVinValidator() const { return false; }
virtual bool validateVout(CTxOut vout, std::string& message) const virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const
{ {
//std::cerr << "CMyPubkeyVoutValidator::validateVout() entered" << std::endl; //std::cerr << "CMyPubkeyVoutValidator::validateVout() entered" << std::endl;
@@ -498,7 +498,7 @@ public:
message = std::string("invalid pubkey"); message = std::string("invalid pubkey");
return false; return false;
} }
virtual bool validateVin(CTxIn vin, CTxOut prevVout, std::string& message) const { return true; } virtual bool validateVin(CTxIn vin, std::vector<CTxOut> prevVout, int32_t prevN, std::string& message) const { return true; }
private: private:
CScript m_fundingOpretScript; CScript m_fundingOpretScript;
@@ -516,7 +516,7 @@ public:
: m_fundingOpretScript(opRetScript), m_latesttxid(latesttxid), m_isHeirSpendingBegan(isHeirSpendingBegan), CValidatorBase(cp) {} : m_fundingOpretScript(opRetScript), m_latesttxid(latesttxid), m_isHeirSpendingBegan(isHeirSpendingBegan), CValidatorBase(cp) {}
virtual bool isVinValidator() const { return false; } virtual bool isVinValidator() const { return false; }
virtual bool validateVout(CTxOut vout, std::string& message) const virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const
{ {
//std::cerr << "CHeirSpendValidator::validateVout() entered" << std::endl; //std::cerr << "CHeirSpendValidator::validateVout() entered" << std::endl;
@@ -554,7 +554,7 @@ public:
// this is not heir: // this is not heir:
return true; return true;
} }
virtual bool validateVin(CTxIn vin, CTxOut prevVout, std::string& message) const { return true; } virtual bool validateVin(CTxIn vin, std::vector<CTxOut> prevVout, int32_t prevN, std::string& message) const { return true; }
private: private:
CScript m_fundingOpretScript; CScript m_fundingOpretScript;
@@ -572,7 +572,7 @@ public:
: m_fundingOpretScript(opret), CValidatorBase(cp) {} : m_fundingOpretScript(opret), CValidatorBase(cp) {}
virtual bool isVinValidator() const { return false; } virtual bool isVinValidator() const { return false; }
virtual bool validateVout(CTxOut vout, std::string& message) const virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const
{ {
//std::cerr << "COpRetValidator::validateVout() entered" << std::endl; //std::cerr << "COpRetValidator::validateVout() entered" << std::endl;
@@ -607,12 +607,48 @@ public:
//std::cerr << "COpRetValidator::validateVout() exits with true" << std::endl; //std::cerr << "COpRetValidator::validateVout() exits with true" << std::endl;
return true; return true;
} }
virtual bool validateVin(CTxIn vin, CTxOut prevVout, std::string& message) const { return true; } virtual bool validateVin(CTxIn vin, std::vector<CTxOut> prevVout, int32_t prevN, std::string& message) const { return true; }
private: private:
CScript m_fundingOpretScript; CScript m_fundingOpretScript;
}; };
/**
* marker spending prevention validator,
* returns false if for tx with funcid=F vout.1 is being tried to spend
*/
template <class Helper> class CMarkerValidator : CValidatorBase
{
public:
CMarkerValidator(CCcontract_info* cp)
: CValidatorBase(cp) { }
virtual bool isVinValidator() const { return true; } // this is vin validator
virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const { return true; }
virtual bool validateVin(CTxIn vin, std::vector<CTxOut> prevVout, int32_t prevN, std::string& message) const {
uint256 fundingTxidInOpret = zeroid, dummyTxid, tokenid = zeroid, initialTokenid = zeroid;
uint8_t dummyIsHeirSpendingBegan;
//std::cerr << "CMarkerValidator::validateVin() prevVout.size()=" << prevVout.size() << " prevN=" << prevN << std::endl;
if (prevVout.size() > 0) {
// get funcId for prev tx:
uint8_t funcId = DecodeHeirEitherOpRet(prevVout[prevVout.size()-1].scriptPubKey, tokenid, fundingTxidInOpret, dummyIsHeirSpendingBegan, true);
//std::cerr << "CMarkerValidator::validateVin() funcId=" << (funcId?funcId:' ') << std::endl;
if (funcId == 'F' && prevN == 1) { // do not allow to spend 'F' marker's vout
message = std::string("spending marker not allowed");
return false;
}
}
//std::cerr << "CMarkerValidator::validateVin() exits with true" << std::endl;
return true;
}
};
/** /**
* empty validator always returns true * empty validator always returns true
*/ */
@@ -623,8 +659,8 @@ public:
: CValidatorBase(cp) { } : CValidatorBase(cp) { }
virtual bool isVinValidator() const { return false; } virtual bool isVinValidator() const { return false; }
virtual bool validateVout(CTxOut vout, std::string& message) const { return true; } virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const { return true; }
virtual bool validateVin(CTxIn vin, CTxOut prevVout, std::string& message) const { return true; } virtual bool validateVin(CTxIn vin, std::vector<CTxOut> prevVout, int32_t prevN, std::string& message) const { return true; }
}; };

1
src/cc/makecclib Executable file
View File

@@ -0,0 +1 @@
gcc -std=c++11 -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o ../cclib.so cclib.cpp

View File

@@ -35,8 +35,14 @@
vout0 baton to next receiverpk (following the unspent baton back to original is the credit loop) vout0 baton to next receiverpk (following the unspent baton back to original is the credit loop)
'S' 'S'
vin0 'I' marker
vin1 baton
vins CC utxos from credit loop vins CC utxos from credit loop
'D' default/partial payment
'L' lockfunds
*/ */
// start of consensus code // start of consensus code
@@ -82,13 +88,13 @@ uint8_t DecodeMaramaraCoinbaseOpRet(const CScript scriptPubKey,CPubKey &pk,int32
} }
if ( vopret.size() > 2 && script[0] == EVAL_MARMARA ) if ( vopret.size() > 2 && script[0] == EVAL_MARMARA )
{ {
if ( script[1] == 'C' || script[1] == 'P' ) if ( script[1] == 'C' || script[1] == 'P' || script[1] == 'L' )
{ {
if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> pk; ss >> height; ss >> unlockht) != 0 ) if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> pk; ss >> height; ss >> unlockht) != 0 )
{ {
return(script[1]); return(script[1]);
} else fprintf(stderr,"DecodeMaramaraCoinbaseOpRet unmarshal error for %c\n",script[1]); } else fprintf(stderr,"DecodeMaramaraCoinbaseOpRet unmarshal error for %c\n",script[1]);
} else fprintf(stderr,"script[1] is %d != 'C' %d or 'P' %d\n",script[1],'C','P'); } //else fprintf(stderr,"script[1] is %d != 'C' %d or 'P' %d or 'L' %d\n",script[1],'C','P','L');
} else fprintf(stderr,"vopret.size() is %d\n",(int32_t)vopret.size()); } else fprintf(stderr,"vopret.size() is %d\n",(int32_t)vopret.size());
return(0); return(0);
} }
@@ -155,18 +161,25 @@ int32_t MarmaraGetbatontxid(std::vector<uint256> &creditloop,uint256 &batontxid,
if ( MarmaraGetcreatetxid(createtxid,txid) == 0 ) if ( MarmaraGetcreatetxid(createtxid,txid) == 0 )
{ {
txid = createtxid; txid = createtxid;
fprintf(stderr,"txid.%s -> createtxid %s\n",txid.GetHex().c_str(),createtxid.GetHex().c_str()); //fprintf(stderr,"txid.%s -> createtxid %s\n",txid.GetHex().c_str(),createtxid.GetHex().c_str());
while ( CCgetspenttxid(spenttxid,vini,height,txid,vout) == 0 ) while ( CCgetspenttxid(spenttxid,vini,height,txid,vout) == 0 )
{ {
creditloop.push_back(txid); creditloop.push_back(txid);
fprintf(stderr,"%d: %s\n",n,txid.GetHex().c_str()); //fprintf(stderr,"%d: %s\n",n,txid.GetHex().c_str());
n++; n++;
if ( (value= CCgettxout(spenttxid,vout,1)) > 0 ) if ( (value= CCgettxout(spenttxid,vout,1)) == 10000 )
{ {
batontxid = spenttxid; batontxid = spenttxid;
fprintf(stderr,"got baton %s %.8f\n",batontxid.GetHex().c_str(),(double)value/COIN); //fprintf(stderr,"got baton %s %.8f\n",batontxid.GetHex().c_str(),(double)value/COIN);
return(n); return(n);
} }
else if ( value > 0 )
{
batontxid = spenttxid;
fprintf(stderr,"n.%d got false baton %s/v%d %.8f\n",n,batontxid.GetHex().c_str(),vout,(double)value/COIN);
return(n);
}
// get funcid
txid = spenttxid; txid = spenttxid;
} }
} }
@@ -175,9 +188,16 @@ int32_t MarmaraGetbatontxid(std::vector<uint256> &creditloop,uint256 &batontxid,
CScript Marmara_scriptPubKey(int32_t height,CPubKey pk) CScript Marmara_scriptPubKey(int32_t height,CPubKey pk)
{ {
CTxOut ccvout; CTxOut ccvout; struct CCcontract_info *cp,C; CPubKey Marmarapk;
cp = CCinit(&C,EVAL_MARMARA);
Marmarapk = GetUnspendable(cp,0);
if ( height > 0 && (height & 1) == 0 && pk.size() == 33 ) if ( height > 0 && (height & 1) == 0 && pk.size() == 33 )
ccvout = MakeCC1vout(EVAL_MARMARA,0,pk); {
ccvout = MakeCC1of2vout(EVAL_MARMARA,0,Marmarapk,pk);
//char coinaddr[64];
//Getscriptaddress(coinaddr,ccvout.scriptPubKey);
//fprintf(stderr,"Marmara_scriptPubKey %s ht.%d -> %s\n",HexStr(pk).c_str(),height,coinaddr);
}
return(ccvout.scriptPubKey); return(ccvout.scriptPubKey);
} }
@@ -192,8 +212,9 @@ CScript MarmaraCoinbaseOpret(uint8_t funcid,int32_t height,CPubKey pk)
int32_t MarmaraValidateCoinbase(int32_t height,CTransaction tx) int32_t MarmaraValidateCoinbase(int32_t height,CTransaction tx)
{ {
struct CCcontract_info *cp,C; CPubKey pk; int32_t ht,unlockht; CTxOut ccvout; struct CCcontract_info *cp,C; CPubKey Marmarapk,pk; int32_t ht,unlockht; CTxOut ccvout;
cp = CCinit(&C,EVAL_MARMARA); cp = CCinit(&C,EVAL_MARMARA);
Marmarapk = GetUnspendable(cp,0);
if ( 0 ) if ( 0 )
{ {
int32_t d,histo[365*2+30]; int32_t d,histo[365*2+30];
@@ -221,19 +242,40 @@ int32_t MarmaraValidateCoinbase(int32_t height,CTransaction tx)
if ( ht == height && MarmaraUnlockht(height) == unlockht ) if ( ht == height && MarmaraUnlockht(height) == unlockht )
{ {
//fprintf(stderr,"ht.%d -> unlock.%d\n",ht,unlockht); //fprintf(stderr,"ht.%d -> unlock.%d\n",ht,unlockht);
ccvout = MakeCC1vout(EVAL_MARMARA,0,pk); ccvout = MakeCC1of2vout(EVAL_MARMARA,0,Marmarapk,pk);
if ( ccvout.scriptPubKey == tx.vout[0].scriptPubKey ) if ( ccvout.scriptPubKey == tx.vout[0].scriptPubKey )
return(0); return(0);
fprintf(stderr,"ht.%d mismatched CCvout scriptPubKey\n",height); char addr0[64],addr1[64];
Getscriptaddress(addr0,ccvout.scriptPubKey);
Getscriptaddress(addr1,tx.vout[0].scriptPubKey);
fprintf(stderr,"ht.%d mismatched CCvout scriptPubKey %s vs %s pk.%d %s\n",height,addr0,addr1,(int32_t)pk.size(),HexStr(pk).c_str());
} else fprintf(stderr,"ht.%d %d vs %d unlock.%d\n",height,MarmaraUnlockht(height),ht,unlockht); } else fprintf(stderr,"ht.%d %d vs %d unlock.%d\n",height,MarmaraUnlockht(height),ht,unlockht);
} else fprintf(stderr,"ht.%d error decoding coinbase opret\n",height); } else fprintf(stderr,"ht.%d error decoding coinbase opret\n",height);
} }
return(-1); return(-1);
} }
bool MarmaraPoScheck(char *destaddr,CScript opret,CTransaction staketx)
{
CPubKey Marmarapk,pk; int32_t height,unlockht; uint8_t funcid; char coinaddr[64]; struct CCcontract_info *cp,C;
//fprintf(stderr,"%s numvins.%d numvouts.%d %.8f opret[%d]\n",staketx.GetHash().ToString().c_str(),(int32_t)staketx.vin.size(),(int32_t)staketx.vout.size(),(double)staketx.vout[0].nValue/COIN,(int32_t)opret.size());
if ( staketx.vout.size() == 2 && opret == staketx.vout[1].scriptPubKey )
{
cp = CCinit(&C,EVAL_MARMARA);
funcid = DecodeMaramaraCoinbaseOpRet(opret,pk,height,unlockht);
Marmarapk = GetUnspendable(cp,0);
GetCCaddress1of2(cp,coinaddr,Marmarapk,pk);
//fprintf(stderr,"matched opret! funcid.%c ht.%d unlock.%d %s\n",funcid,height,unlockht,coinaddr);
return(strcmp(destaddr,coinaddr) == 0);
}
return(0);
}
bool MarmaraValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) bool MarmaraValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
{ {
std::vector<uint8_t> vopret; CTransaction vinTx; uint256 hashBlock; int32_t numvins,numvouts,i,ht,unlockht,vht,vunlockht; uint8_t funcid,vfuncid,*script; CPubKey pk,vpk; std::vector<uint8_t> vopret; CTransaction vinTx; uint256 hashBlock; int32_t numvins,numvouts,i,ht,unlockht,vht,vunlockht; uint8_t funcid,vfuncid,*script; CPubKey pk,vpk;
if ( ASSETCHAINS_MARMARA == 0 )
return eval->Invalid("-ac_marmara must be set for marmara CC");
numvins = tx.vin.size(); numvins = tx.vin.size();
numvouts = tx.vout.size(); numvouts = tx.vout.size();
if ( numvouts < 1 ) if ( numvouts < 1 )
@@ -284,9 +326,17 @@ bool MarmaraValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t
{ {
return(true); return(true);
} }
else if ( funcid == 'S' ) // collect -> automatically spend issuers locked funds, given 'I' else if ( funcid == 'S' ) // settlement -> automatically spend issuers locked funds, given 'I'
{ {
return(true); // iterate from issuer all remainder after maturity return(true);
}
else if ( funcid == 'D' ) // insufficient settlement
{
return(true);
}
else if ( funcid == 'C' ) // coinbase
{
return(true);
} }
// staking only for locked utxo // staking only for locked utxo
} }
@@ -298,9 +348,10 @@ bool MarmaraValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t
int64_t AddMarmaraCoinbases(struct CCcontract_info *cp,CMutableTransaction &mtx,int32_t firstheight,CPubKey poolpk,int32_t maxinputs) int64_t AddMarmaraCoinbases(struct CCcontract_info *cp,CMutableTransaction &mtx,int32_t firstheight,CPubKey poolpk,int32_t maxinputs)
{ {
char coinaddr[64]; CPubKey pk; int64_t nValue,totalinputs = 0; uint256 txid,hashBlock; CTransaction vintx; int32_t unlockht,ht,vout,unlocks,n = 0; char coinaddr[64]; CPubKey Marmarapk,pk; int64_t nValue,totalinputs = 0; uint256 txid,hashBlock; CTransaction vintx; int32_t unlockht,ht,vout,unlocks,n = 0;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
GetCCaddress(cp,coinaddr,poolpk); Marmarapk = GetUnspendable(cp,0);
GetCCaddress1of2(cp,coinaddr,Marmarapk,poolpk);
SetCCunspents(unspentOutputs,coinaddr); SetCCunspents(unspentOutputs,coinaddr);
unlocks = MarmaraUnlockht(firstheight); unlocks = MarmaraUnlockht(firstheight);
//fprintf(stderr,"check coinaddr.(%s)\n",coinaddr); //fprintf(stderr,"check coinaddr.(%s)\n",coinaddr);
@@ -332,13 +383,285 @@ int64_t AddMarmaraCoinbases(struct CCcontract_info *cp,CMutableTransaction &mtx,
return(totalinputs); return(totalinputs);
} }
int32_t MarmaraGetCreditloops(int64_t &totalamount,std::vector<uint256> &issuances,struct CCcontract_info *cp,int32_t firstheight,int32_t lastheight,int64_t minamount,int64_t maxamount,CPubKey refpk,std::string refcurrency) int64_t AddMarmarainputs(CMutableTransaction &mtx,std::vector<CPubKey> &pubkeys,char *coinaddr,int64_t total,int32_t maxinputs)
{
uint64_t threshold,nValue,totalinputs = 0; uint256 txid,hashBlock; CTransaction tx; int32_t numvouts,ht,unlockht,vout,i,n = 0; uint8_t funcid; CPubKey pk; std::vector<int64_t> vals;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
SetCCunspents(unspentOutputs,coinaddr);
threshold = total/(maxinputs+1);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
txid = it->first.txhash;
vout = (int32_t)it->first.index;
if ( it->second.satoshis < threshold )
continue;
if ( GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 && vout < numvouts && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 && myIsutxo_spentinmempool(txid,vout) == 0 )
{
if ( (funcid= DecodeMaramaraCoinbaseOpRet(tx.vout[numvouts-1].scriptPubKey,pk,ht,unlockht)) == 'C' || funcid == 'P' || funcid == 'L' )
{
//char str[64]; fprintf(stderr,"(%s) %s/v%d %.8f ht.%d unlockht.%d\n",coinaddr,uint256_str(str,txid),vout,(double)it->second.satoshis/COIN,ht,unlockht);
if ( total != 0 && maxinputs != 0 )
{
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
pubkeys.push_back(pk);
}
totalinputs += it->second.satoshis;
vals.push_back(it->second.satoshis);
n++;
if ( maxinputs != 0 && total == 0 )
continue;
if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) )
break;
} else fprintf(stderr,"null funcid\n");
}
}
if ( maxinputs != 0 && total == 0 )
{
std::sort(vals.begin(),vals.end());
totalinputs = 0;
for (i=0; i<maxinputs && i<vals.size(); i++)
totalinputs += vals[i];
}
return(totalinputs);
}
UniValue MarmaraLock(uint64_t txfee,int64_t amount,int32_t height)
{
CMutableTransaction tmpmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C; CPubKey Marmarapk,mypk,pk; int32_t unlockht,refunlockht,vout,ht,numvouts; int64_t nValue,val,inputsum=0,threshold,remains,change = 0; std::string rawtx,errorstr; char coinaddr[64]; uint256 txid,hashBlock; CTransaction tx; uint8_t funcid;
if ( txfee == 0 )
txfee = 10000;
if ( (height & 1) != 0 )
height++;
cp = CCinit(&C,EVAL_MARMARA);
mypk = pubkey2pk(Mypubkey());
Marmarapk = GetUnspendable(cp,0);
Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG);
if ( (val= CCaddress_balance(coinaddr)) < amount )
val -= txfee;
else val = amount;
if ( val > txfee )
inputsum = AddNormalinputs2(mtx,val,CC_MAXVINS/2);
//fprintf(stderr,"normal inputs %.8f val %.8f\n",(double)inputsum/COIN,(double)val/COIN);
mtx.vout.push_back(MakeCC1of2vout(EVAL_MARMARA,amount,Marmarapk,mypk));
if ( inputsum < amount+txfee )
{
refunlockht = MarmaraUnlockht(height);
result.push_back(Pair("normalfunds",ValueFromAmount(inputsum)));
result.push_back(Pair("height",height));
result.push_back(Pair("unlockht",refunlockht));
remains = (amount + txfee) - inputsum;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
GetCCaddress1of2(cp,coinaddr,Marmarapk,mypk);
SetCCunspents(unspentOutputs,coinaddr);
threshold = remains / (MARMARA_VINS+1);
CCaddr1of2set(cp,Marmarapk,mypk,coinaddr);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
txid = it->first.txhash;
vout = (int32_t)it->first.index;
if ( (nValue= it->second.satoshis) < threshold )
continue;
if ( GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 && vout < numvouts && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 && myIsutxo_spentinmempool(txid,vout) == 0 )
{
if ( (funcid= DecodeMaramaraCoinbaseOpRet(tx.vout[numvouts-1].scriptPubKey,pk,ht,unlockht)) == 'C' || funcid == 'P' || funcid == 'L' )
{
if ( unlockht < refunlockht )
{
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
//fprintf(stderr,"merge CC vout %s/v%d %.8f unlockht.%d < ref.%d\n",txid.GetHex().c_str(),vout,(double)nValue/COIN,unlockht,refunlockht);
inputsum += nValue;
remains -= nValue;
if ( inputsum >= amount + txfee )
{
//fprintf(stderr,"inputsum %.8f >= amount %.8f, update amount\n",(double)inputsum/COIN,(double)amount/COIN);
amount = inputsum - txfee;
break;
}
}
}
}
}
}
if ( inputsum >= amount+txfee )
{
if ( inputsum > amount+txfee )
{
change = (inputsum - amount);
mtx.vout.push_back(CTxOut(change,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
}
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraCoinbaseOpret('L',height,mypk));
if ( rawtx.size() == 0 )
errorstr = (char *)"couldnt finalize CCtx";
else
{
result.push_back(Pair("result",(char *)"success"));
result.push_back(Pair("rawtx",rawtx));
return(result);
}
} else errorstr = (char *)"insufficient funds";
result.push_back(Pair("result",(char *)"error"));
result.push_back(Pair("error",errorstr));
return(result);
}
int32_t MarmaraSignature(uint8_t *utxosig,CMutableTransaction &mtx)
{
uint256 txid,hashBlock; uint8_t *ptr; int32_t i,siglen,vout,numvouts; CTransaction tx; std::string rawtx; CPubKey mypk; std::vector<CPubKey> pubkeys; struct CCcontract_info *cp,C; uint64_t txfee;
txfee = 10000;
vout = mtx.vin[0].prevout.n;
if ( GetTransaction(mtx.vin[0].prevout.hash,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 1 && vout < numvouts )
{
cp = CCinit(&C,EVAL_MARMARA);
mypk = pubkey2pk(Mypubkey());
pubkeys.push_back(mypk);
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,tx.vout[numvouts - 1].scriptPubKey,pubkeys);
if ( rawtx.size() > 0 )
{
siglen = mtx.vin[0].scriptSig.size();
ptr = &mtx.vin[0].scriptSig[0];
for (i=0; i<siglen; i++)
{
utxosig[i] = ptr[i];
//fprintf(stderr,"%02x",ptr[i]);
}
//fprintf(stderr," got signed rawtx.%s siglen.%d\n",rawtx.c_str(),siglen);
return(siglen);
}
}
return(0);
}
// jl777: decide on what unlockht settlement change should have -> from utxo making change
UniValue MarmaraSettlement(uint64_t txfee,uint256 refbatontxid)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
UniValue result(UniValue::VOBJ),a(UniValue::VARR); std::vector<uint256> creditloop; uint256 batontxid,createtxid,refcreatetxid,hashBlock; uint8_t funcid; int32_t numerrs=0,i,n,numvouts,matures,refmatures,height; int64_t amount,refamount,remaining,inputsum,change; CPubKey Marmarapk,mypk,pk; std::string currency,refcurrency,rawtx; CTransaction tx,batontx; char coinaddr[64],myCCaddr[64],destaddr[64],batonCCaddr[64],str[2],txidaddr[64]; std::vector<CPubKey> pubkeys; struct CCcontract_info *cp,C;
if ( txfee == 0 )
txfee = 10000;
cp = CCinit(&C,EVAL_MARMARA);
mypk = pubkey2pk(Mypubkey());
Marmarapk = GetUnspendable(cp,0);
remaining = change = 0;
height = chainActive.LastTip()->GetHeight();
if ( (n= MarmaraGetbatontxid(creditloop,batontxid,refbatontxid)) > 0 )
{
if ( GetTransaction(batontxid,batontx,hashBlock,false) != 0 && (numvouts= batontx.vout.size()) > 1 )
{
if ( (funcid= MarmaraDecodeLoopOpret(batontx.vout[numvouts-1].scriptPubKey,refcreatetxid,pk,refamount,refmatures,refcurrency)) != 0 )
{
if ( refcreatetxid != creditloop[0] )
{
result.push_back(Pair("result",(char *)"error"));
result.push_back(Pair("error",(char *)"invalid refcreatetxid, setting to creditloop[0]"));
return(result);
}
else if ( chainActive.LastTip()->GetHeight() < refmatures )
{
fprintf(stderr,"doesnt mature for another %d blocks\n",refmatures - chainActive.LastTip()->GetHeight());
result.push_back(Pair("result",(char *)"error"));
result.push_back(Pair("error",(char *)"cant settle immature creditloop"));
return(result);
}
else if ( (refmatures & 1) == 0 )
{
result.push_back(Pair("result",(char *)"error"));
result.push_back(Pair("error",(char *)"cant automatic settle even maturity heights"));
return(result);
}
else if ( n < 1 )
{
result.push_back(Pair("result",(char *)"error"));
result.push_back(Pair("error",(char *)"creditloop too short"));
return(result);
}
remaining = refamount;
GetCCaddress(cp,myCCaddr,Mypubkey());
Getscriptaddress(batonCCaddr,batontx.vout[0].scriptPubKey);
if ( strcmp(myCCaddr,batonCCaddr) == 0 )
{
mtx.vin.push_back(CTxIn(n == 1 ? batontxid : creditloop[1],1,CScript())); // issuance marker
pubkeys.push_back(Marmarapk);
mtx.vin.push_back(CTxIn(batontxid,0,CScript()));
pubkeys.push_back(mypk);
for (i=1; i<n; i++)
{
if ( GetTransaction(creditloop[i],tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 1 )
{
if ( (funcid= MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,createtxid,pk,amount,matures,currency)) != 0 )
{
GetCCaddress1of2(cp,coinaddr,Marmarapk,pk);
if ( (inputsum= AddMarmarainputs(mtx,pubkeys,coinaddr,remaining,MARMARA_VINS)) >= remaining )
{
change = (inputsum - remaining);
mtx.vout.push_back(CTxOut(amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
if ( change > txfee )
mtx.vout.push_back(MakeCC1of2vout(EVAL_MARMARA,change,Marmarapk,pk));
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraLoopOpret('S',createtxid,mypk,0,refmatures,currency),pubkeys);
result.push_back(Pair("result",(char *)"success"));
result.push_back(Pair("rawtx",rawtx));
return(result);
} else remaining -= inputsum;
if ( mtx.vin.size() >= CC_MAXVINS - MARMARA_VINS )
break;
} else fprintf(stderr,"null funcid for creditloop[%d]\n",i);
} else fprintf(stderr,"couldnt get creditloop[%d]\n",i);
}
if ( refamount - remaining > 2*txfee )
{
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(CCtxidaddr(txidaddr,createtxid))) << OP_CHECKSIG)); // failure marker
if ( refamount-remaining > 3*txfee )
mtx.vout.push_back(CTxOut(refamount-remaining-2*txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraLoopOpret('D',createtxid,mypk,-remaining,refmatures,currency),pubkeys);
result.push_back(Pair("result",(char *)"error"));
result.push_back(Pair("error",(char *)"insufficient funds"));
result.push_back(Pair("rawtx",rawtx));
result.push_back(Pair("remaining",ValueFromAmount(remaining)));
}
else
{
// jl777: maybe fund a txfee to report no funds avail
result.push_back(Pair("result",(char *)"error"));
result.push_back(Pair("error",(char *)"no funds available at all"));
}
}
else
{
result.push_back(Pair("result",(char *)"error"));
result.push_back(Pair("error",(char *)"this node does not have the baton"));
result.push_back(Pair("myCCaddr",myCCaddr));
result.push_back(Pair("batonCCaddr",batonCCaddr));
}
}
else
{
result.push_back(Pair("result",(char *)"error"));
result.push_back(Pair("error",(char *)"couldnt get batontxid opret"));
}
}
else
{
result.push_back(Pair("result",(char *)"error"));
result.push_back(Pair("error",(char *)"couldnt find batontxid"));
}
}
else
{
result.push_back(Pair("result",(char *)"error"));
result.push_back(Pair("error",(char *)"couldnt get creditloop"));
}
return(result);
}
int32_t MarmaraGetCreditloops(int64_t &totalamount,std::vector<uint256> &issuances,int64_t &totalclosed,std::vector<uint256> &closed,struct CCcontract_info *cp,int32_t firstheight,int32_t lastheight,int64_t minamount,int64_t maxamount,CPubKey refpk,std::string refcurrency)
{ {
char coinaddr[64]; CPubKey Marmarapk,senderpk; int64_t amount; uint256 createtxid,txid,hashBlock; CTransaction tx; int32_t numvouts,vout,matures,n=0; std::string currency; char coinaddr[64]; CPubKey Marmarapk,senderpk; int64_t amount; uint256 createtxid,txid,hashBlock; CTransaction tx; int32_t numvouts,vout,matures,n=0; std::string currency;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
Marmarapk = GetUnspendable(cp,0); Marmarapk = GetUnspendable(cp,0);
GetCCaddress(cp,coinaddr,Marmarapk); GetCCaddress(cp,coinaddr,Marmarapk);
SetCCunspents(unspentOutputs,coinaddr); SetCCunspents(unspentOutputs,coinaddr);
// do all txid, conditional on spent/unspent
//fprintf(stderr,"check coinaddr.(%s)\n",coinaddr); //fprintf(stderr,"check coinaddr.(%s)\n",coinaddr);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{ {
@@ -364,21 +687,24 @@ int32_t MarmaraGetCreditloops(int64_t &totalamount,std::vector<uint256> &issuanc
return(n); return(n);
} }
UniValue MarmaraReceive(uint64_t txfee,CPubKey senderpk,int64_t amount,std::string currency,int32_t matures,uint256 batontxid) UniValue MarmaraReceive(uint64_t txfee,CPubKey senderpk,int64_t amount,std::string currency,int32_t matures,uint256 batontxid,bool automaticflag)
{ {
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
UniValue result(UniValue::VOBJ); CPubKey mypk; struct CCcontract_info *cp,C; std::string rawtx; char *errorstr=0; uint256 createtxid; int64_t batonamount; int32_t needbaton = 0; UniValue result(UniValue::VOBJ); CPubKey mypk; struct CCcontract_info *cp,C; std::string rawtx; char *errorstr=0; uint256 createtxid; int64_t batonamount; int32_t needbaton = 0;
cp = CCinit(&C,EVAL_MARMARA); cp = CCinit(&C,EVAL_MARMARA);
if ( txfee == 0 ) if ( txfee == 0 )
txfee = 10000; txfee = 10000;
// check for batonownership by senderpk and parameters match createtxid if ( automaticflag != 0 && (matures & 1) == 0 )
matures++;
else if ( automaticflag == 0 && (matures & 1) != 0 )
matures++;
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
memset(&createtxid,0,sizeof(createtxid)); memset(&createtxid,0,sizeof(createtxid));
if ( batontxid != zeroid && MarmaraGetcreatetxid(createtxid,batontxid) < 0 ) if ( batontxid != zeroid && MarmaraGetcreatetxid(createtxid,batontxid) < 0 )
errorstr = (char *)"cant get createtxid from batontxid"; errorstr = (char *)"cant get createtxid from batontxid";
else if ( currency != "MARMARA" ) else if ( currency != "MARMARA" )
errorstr = (char *)"for now, only MARMARA loops are supported"; errorstr = (char *)"for now, only MARMARA loops are supported";
else if ( amount < txfee ) else if ( amount <= txfee )
errorstr = (char *)"amount must be for more than txfee"; errorstr = (char *)"amount must be for more than txfee";
else if ( matures <= chainActive.LastTip()->GetHeight() ) else if ( matures <= chainActive.LastTip()->GetHeight() )
errorstr = (char *)"it must mature in the future"; errorstr = (char *)"it must mature in the future";
@@ -425,17 +751,14 @@ UniValue MarmaraIssue(uint64_t txfee,uint8_t funcid,CPubKey receiverpk,int64_t a
cp = CCinit(&C,EVAL_MARMARA); cp = CCinit(&C,EVAL_MARMARA);
if ( txfee == 0 ) if ( txfee == 0 )
txfee = 10000; txfee = 10000;
// make sure receiverpk is unique to creditloop
// make sure less than maxlength // make sure less than maxlength
Marmarapk = GetUnspendable(cp,0); Marmarapk = GetUnspendable(cp,0);
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
if ( MarmaraGetcreatetxid(createtxid,approvaltxid) < 0 ) if ( MarmaraGetcreatetxid(createtxid,approvaltxid) < 0 )
errorstr = (char *)"cant get createtxid from approvaltxid"; errorstr = (char *)"cant get createtxid from approvaltxid";
else if ( batontxid == zeroid )
errorstr = (char *)"null batontxid";
else if ( currency != "MARMARA" ) else if ( currency != "MARMARA" )
errorstr = (char *)"for now, only MARMARA loops are supported"; errorstr = (char *)"for now, only MARMARA loops are supported";
else if ( amount < txfee ) else if ( amount <= txfee )
errorstr = (char *)"amount must be for more than txfee"; errorstr = (char *)"amount must be for more than txfee";
else if ( matures <= chainActive.LastTip()->GetHeight() ) else if ( matures <= chainActive.LastTip()->GetHeight() )
errorstr = (char *)"it must mature in the future"; errorstr = (char *)"it must mature in the future";
@@ -479,69 +802,6 @@ UniValue MarmaraIssue(uint64_t txfee,uint8_t funcid,CPubKey receiverpk,int64_t a
return(result); return(result);
} }
UniValue MarmaraSettlement(uint64_t txfee,uint256 refbatontxid)
{
UniValue result(UniValue::VOBJ),a(UniValue::VARR); std::vector<uint256> creditloop; uint256 batontxid,createtxid,refcreatetxid,hashBlock; uint8_t funcid; int32_t numerrs=0,i,n,numvouts,matures,refmatures; int64_t amount,refamount; CPubKey Marmarapk,pk; std::string currency,refcurrency; CTransaction tx,batontx; char coinaddr[64],myCCaddr[64],destaddr[64],batonCCaddr[64],str[2]; struct CCcontract_info *cp,C;
if ( txfee == 0 )
txfee = 10000;
cp = CCinit(&C,EVAL_MARMARA);
Marmarapk = GetUnspendable(cp,0);
if ( (n= MarmaraGetbatontxid(creditloop,batontxid,refbatontxid)) > 0 )
{
if ( GetTransaction(batontxid,batontx,hashBlock,false) != 0 && (numvouts= batontx.vout.size()) > 1 )
{
if ( (funcid= MarmaraDecodeLoopOpret(batontx.vout[numvouts-1].scriptPubKey,refcreatetxid,pk,refamount,refmatures,refcurrency)) != 0 )
{
if ( refcreatetxid != creditloop[0] )
{
fprintf(stderr,"invalid refcreatetxid, setting to creditloop[0]\n");
refcreatetxid = creditloop[0];
numerrs++;
}
GetCCaddress(cp,myCCaddr,Mypubkey());
Getscriptaddress(batonCCaddr,batontx.vout[0].scriptPubKey);
if ( strcmp(myCCaddr,batonCCaddr) == 0 )
{
for (i=0; i<n; i++)
{
if ( GetTransaction(creditloop[i],tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 1 )
{
if ( (funcid= MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,createtxid,pk,amount,matures,currency)) != 0 )
{
GetCCaddress1of2(cp,coinaddr,Marmarapk,pk);
fprintf(stderr,"get locked funds of %s %.8f\n",coinaddr,(double)CCaddress_balance(coinaddr)/COIN);
} else fprintf(stderr,"null funcid for creditloop[%d]\n",i);
} else fprintf(stderr,"couldnt get creditloop[%d]\n",i);
}
}
else
{
result.push_back(Pair("result",(char *)"error"));
result.push_back(Pair("error",(char *)"this node does not have the baton"));
result.push_back(Pair("myCCaddr",myCCaddr));
result.push_back(Pair("batonCCaddr",batonCCaddr));
}
}
else
{
result.push_back(Pair("result",(char *)"error"));
result.push_back(Pair("error",(char *)"couldnt get batontxid opret"));
}
}
else
{
result.push_back(Pair("result",(char *)"error"));
result.push_back(Pair("error",(char *)"couldnt find batontxid"));
}
}
else
{
result.push_back(Pair("result",(char *)"error"));
result.push_back(Pair("error",(char *)"couldnt get creditloop"));
}
return(result);
}
UniValue MarmaraCreditloop(uint256 txid) UniValue MarmaraCreditloop(uint256 txid)
{ {
UniValue result(UniValue::VOBJ),a(UniValue::VARR); std::vector<uint256> creditloop; uint256 batontxid,createtxid,refcreatetxid,hashBlock; uint8_t funcid; int32_t numerrs=0,i,n,numvouts,matures,refmatures; int64_t amount,refamount; CPubKey pk; std::string currency,refcurrency; CTransaction tx; char coinaddr[64],myCCaddr[64],destaddr[64],batonCCaddr[64],str[2]; struct CCcontract_info *cp,C; UniValue result(UniValue::VOBJ),a(UniValue::VARR); std::vector<uint256> creditloop; uint256 batontxid,createtxid,refcreatetxid,hashBlock; uint8_t funcid; int32_t numerrs=0,i,n,numvouts,matures,refmatures; int64_t amount,refamount; CPubKey pk; std::string currency,refcurrency; CTransaction tx; char coinaddr[64],myCCaddr[64],destaddr[64],batonCCaddr[64],str[2]; struct CCcontract_info *cp,C;
@@ -555,21 +815,54 @@ UniValue MarmaraCreditloop(uint256 txid)
result.push_back(Pair("myaddress",coinaddr)); result.push_back(Pair("myaddress",coinaddr));
GetCCaddress(cp,myCCaddr,Mypubkey()); GetCCaddress(cp,myCCaddr,Mypubkey());
result.push_back(Pair("myCCaddress",myCCaddr)); result.push_back(Pair("myCCaddress",myCCaddr));
result.push_back(Pair("batontxid",batontxid.GetHex()));
if ( (funcid= MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,refcreatetxid,pk,refamount,refmatures,refcurrency)) != 0 ) if ( (funcid= MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,refcreatetxid,pk,refamount,refmatures,refcurrency)) != 0 )
{ {
str[0] = funcid, str[1] = 0; str[0] = funcid, str[1] = 0;
result.push_back(Pair("funcid",str)); result.push_back(Pair("funcid",str));
result.push_back(Pair("currency",refcurrency));
if ( funcid == 'S' )
{
refcreatetxid = creditloop[0];
result.push_back(Pair("settlement",batontxid.GetHex()));
result.push_back(Pair("createtxid",refcreatetxid.GetHex()));
result.push_back(Pair("remainder",ValueFromAmount(refamount)));
result.push_back(Pair("settled",refmatures));
result.push_back(Pair("pubkey",HexStr(pk)));
Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG);
result.push_back(Pair("coinaddr",coinaddr));
result.push_back(Pair("collected",ValueFromAmount(tx.vout[0].nValue)));
Getscriptaddress(destaddr,tx.vout[0].scriptPubKey);
if ( strcmp(coinaddr,destaddr) != 0 )
{
result.push_back(Pair("destaddr",destaddr));
numerrs++;
}
refamount = -1;
}
else if ( funcid == 'D' )
{
refcreatetxid = creditloop[0];
result.push_back(Pair("settlement",batontxid.GetHex()));
result.push_back(Pair("createtxid",refcreatetxid.GetHex()));
result.push_back(Pair("remainder",ValueFromAmount(refamount)));
result.push_back(Pair("settled",refmatures));
Getscriptaddress(destaddr,tx.vout[0].scriptPubKey);
result.push_back(Pair("txidaddr",destaddr));
if ( tx.vout.size() > 1 )
result.push_back(Pair("collected",ValueFromAmount(tx.vout[1].nValue)));
}
else
{
result.push_back(Pair("batontxid",batontxid.GetHex()));
result.push_back(Pair("createtxid",refcreatetxid.GetHex()));
result.push_back(Pair("amount",ValueFromAmount(refamount)));
result.push_back(Pair("matures",refmatures));
if ( refcreatetxid != creditloop[0] ) if ( refcreatetxid != creditloop[0] )
{ {
fprintf(stderr,"invalid refcreatetxid, setting to creditloop[0]\n"); fprintf(stderr,"invalid refcreatetxid, setting to creditloop[0]\n");
refcreatetxid = creditloop[0]; refcreatetxid = creditloop[0];
numerrs++; numerrs++;
} }
result.push_back(Pair("createtxid",refcreatetxid.GetHex()));
result.push_back(Pair("amount",ValueFromAmount(refamount)));
result.push_back(Pair("matures",refmatures));
result.push_back(Pair("currency",refcurrency));
result.push_back(Pair("batonpk",HexStr(pk))); result.push_back(Pair("batonpk",HexStr(pk)));
Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG); Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG);
result.push_back(Pair("batonaddr",coinaddr)); result.push_back(Pair("batonaddr",coinaddr));
@@ -584,6 +877,7 @@ UniValue MarmaraCreditloop(uint256 txid)
if ( strcmp(myCCaddr,coinaddr) == 0 ) if ( strcmp(myCCaddr,coinaddr) == 0 )
result.push_back(Pair("ismine",1)); result.push_back(Pair("ismine",1));
else result.push_back(Pair("ismine",0)); else result.push_back(Pair("ismine",0));
}
for (i=0; i<n; i++) for (i=0; i<n; i++)
{ {
if ( GetTransaction(creditloop[i],tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 1 ) if ( GetTransaction(creditloop[i],tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 1 )
@@ -617,6 +911,13 @@ UniValue MarmaraCreditloop(uint256 txid)
obj.push_back(Pair("vout0address",destaddr)); obj.push_back(Pair("vout0address",destaddr));
numerrs++; numerrs++;
} }
if ( i == 0 && refamount < 0 )
{
refamount = amount;
refmatures = matures;
result.push_back(Pair("amount",ValueFromAmount(refamount)));
result.push_back(Pair("matures",refmatures));
}
if ( createtxid != refcreatetxid || amount != refamount || matures != refmatures || currency != refcurrency ) if ( createtxid != refcreatetxid || amount != refamount || matures != refmatures || currency != refcurrency )
{ {
numerrs++; numerrs++;
@@ -654,43 +955,6 @@ UniValue MarmaraCreditloop(uint256 txid)
return(result); return(result);
} }
UniValue MarmaraInfo(CPubKey refpk,int32_t firstheight,int32_t lastheight,int64_t minamount,int64_t maxamount,std::string currency)
{
UniValue result(UniValue::VOBJ),a(UniValue::VARR); int32_t i,n,matches; int64_t totalamount=0; std::vector<uint256> issuances; char coinaddr[64];
CPubKey Marmarapk; struct CCcontract_info *cp,C;
result.push_back(Pair("result","success"));
Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(Mypubkey())) << OP_CHECKSIG);
result.push_back(Pair("myaddress",coinaddr));
GetCCaddress(cp,coinaddr,Mypubkey());
result.push_back(Pair("myCCaddress",coinaddr));
if ( refpk.size() == 33 )
result.push_back(Pair("issuer",HexStr(refpk)));
if ( currency.size() == 0 )
currency = (char *)"MARMARA";
if ( firstheight <= lastheight )
firstheight = 0, lastheight = (1 << 30);
if ( minamount <= maxamount )
minamount = 0, maxamount = (1LL << 60);
result.push_back(Pair("firstheight",firstheight));
result.push_back(Pair("lastheight",lastheight));
result.push_back(Pair("minamount",ValueFromAmount(minamount)));
result.push_back(Pair("maxamount",ValueFromAmount(maxamount)));
result.push_back(Pair("currency",currency));
cp = CCinit(&C,EVAL_MARMARA);
Marmarapk = GetUnspendable(cp,0);
if ( (n= MarmaraGetCreditloops(totalamount,issuances,cp,firstheight,lastheight,minamount,maxamount,refpk,currency)) > 0 )
{
result.push_back(Pair("n",n));
matches = (int32_t)issuances.size();
result.push_back(Pair("matches",matches));
for (i=0; i<matches; i++)
a.push_back(issuances[i].GetHex());
result.push_back(Pair("issuances",a));
result.push_back(Pair("totalamount",ValueFromAmount(totalamount)));
}
return(result);
}
UniValue MarmaraPoolPayout(uint64_t txfee,int32_t firstheight,double perc,char *jsonstr) // [[pk0, shares0], [pk1, shares1], ...] UniValue MarmaraPoolPayout(uint64_t txfee,int32_t firstheight,double perc,char *jsonstr) // [[pk0, shares0], [pk1, shares1], ...]
{ {
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
@@ -777,3 +1041,57 @@ UniValue MarmaraPoolPayout(uint64_t txfee,int32_t firstheight,double perc,char *
return(result); return(result);
} }
// get all tx, constrain by vout, issuances[] and closed[]
UniValue MarmaraInfo(CPubKey refpk,int32_t firstheight,int32_t lastheight,int64_t minamount,int64_t maxamount,std::string currency)
{
CMutableTransaction mtx; std::vector<CPubKey> pubkeys;
UniValue result(UniValue::VOBJ),a(UniValue::VARR),b(UniValue::VARR); int32_t i,n,matches; int64_t totalclosed=0,totalamount=0; std::vector<uint256> issuances,closed; char coinaddr[64];
CPubKey Marmarapk; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_MARMARA);
Marmarapk = GetUnspendable(cp,0);
result.push_back(Pair("result","success"));
Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(Mypubkey())) << OP_CHECKSIG);
result.push_back(Pair("myaddress",coinaddr));
result.push_back(Pair("normal",ValueFromAmount(CCaddress_balance(coinaddr))));
GetCCaddress1of2(cp,coinaddr,Marmarapk,Mypubkey());
result.push_back(Pair("myCCactivated",coinaddr));
result.push_back(Pair("activated",ValueFromAmount(CCaddress_balance(coinaddr))));
result.push_back(Pair("activated16",ValueFromAmount(AddMarmarainputs(mtx,pubkeys,coinaddr,0,MARMARA_VINS))));
GetCCaddress(cp,coinaddr,Mypubkey());
result.push_back(Pair("myCCaddress",coinaddr));
result.push_back(Pair("CCutxos",ValueFromAmount(CCaddress_balance(coinaddr))));
if ( refpk.size() == 33 )
result.push_back(Pair("issuer",HexStr(refpk)));
if ( currency.size() == 0 )
currency = (char *)"MARMARA";
if ( firstheight <= lastheight )
firstheight = 0, lastheight = (1 << 30);
if ( minamount <= maxamount )
minamount = 0, maxamount = (1LL << 60);
result.push_back(Pair("firstheight",firstheight));
result.push_back(Pair("lastheight",lastheight));
result.push_back(Pair("minamount",ValueFromAmount(minamount)));
result.push_back(Pair("maxamount",ValueFromAmount(maxamount)));
result.push_back(Pair("currency",currency));
if ( (n= MarmaraGetCreditloops(totalamount,issuances,totalclosed,closed,cp,firstheight,lastheight,minamount,maxamount,refpk,currency)) > 0 )
{
result.push_back(Pair("n",n));
matches = (int32_t)issuances.size();
result.push_back(Pair("pending",matches));
for (i=0; i<matches; i++)
a.push_back(issuances[i].GetHex());
result.push_back(Pair("issuances",a));
result.push_back(Pair("totalamount",ValueFromAmount(totalamount)));
matches = (int32_t)closed.size();
result.push_back(Pair("numclosed",matches));
for (i=0; i<matches; i++)
b.push_back(closed[i].GetHex());
result.push_back(Pair("closed",b));
result.push_back(Pair("totalclosed",ValueFromAmount(totalclosed)));
}
return(result);
}

View File

@@ -92,11 +92,6 @@ static CBlock CreateGenesisBlock(uint32_t nTime, const uint256& nNonce, const st
void *chainparams_commandline(void *ptr); void *chainparams_commandline(void *ptr);
#include "komodo_defs.h" #include "komodo_defs.h"
extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT;
extern uint32_t ASSETCHAIN_INIT, ASSETCHAINS_MAGIC;
extern int32_t VERUS_BLOCK_POSUNITS, ASSETCHAINS_LWMAPOS, ASSETCHAINS_SAPLING, ASSETCHAINS_OVERWINTER;
extern uint64_t ASSETCHAINS_SUPPLY, ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH, ASSETCHAINS_VERUSHASH;
const arith_uint256 maxUint = UintToArith256(uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); const arith_uint256 maxUint = UintToArith256(uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"));

View File

@@ -799,6 +799,11 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
uint64_t signedmask,voutmask; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; uint64_t signedmask,voutmask; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp;
uint8_t scriptbuf[10001],pubkeys[64][33],rmd160[20],scriptPubKey[35]; uint256 zero,btctxid,txhash; uint8_t scriptbuf[10001],pubkeys[64][33],rmd160[20],scriptPubKey[35]; uint256 zero,btctxid,txhash;
int32_t i,j,k,numnotaries,notarized,scriptlen,isratification,nid,numvalid,specialtx,notarizedheight,notaryid,len,numvouts,numvins,height,txn_count; int32_t i,j,k,numnotaries,notarized,scriptlen,isratification,nid,numvalid,specialtx,notarizedheight,notaryid,len,numvouts,numvins,height,txn_count;
if ( pindex == 0 )
{
fprintf(stderr,"komodo_connectblock null pindex\n");
return;
}
memset(&zero,0,sizeof(zero)); memset(&zero,0,sizeof(zero));
komodo_init(pindex->GetHeight()); komodo_init(pindex->GetHeight());
KOMODO_INITDONE = (uint32_t)time(NULL); KOMODO_INITDONE = (uint32_t)time(NULL);
@@ -942,6 +947,8 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
} }
} }
} }
if ( ASSETCHAINS_SYMBOL[0] != 0 || height < 100000 )
{
if ( ((signedmask & 1) != 0 && numvalid >= KOMODO_MINRATIFY) || bitweight(signedmask) > (numnotaries/3) ) if ( ((signedmask & 1) != 0 && numvalid >= KOMODO_MINRATIFY) || bitweight(signedmask) > (numnotaries/3) )
{ {
memset(&txhash,0,sizeof(txhash)); memset(&txhash,0,sizeof(txhash));
@@ -951,6 +958,7 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
} }
} }
} }
}
if ( IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 ) if ( IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 )
printf("%s ht.%d\n",ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL,height); printf("%s ht.%d\n",ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL,height);
if ( pindex->GetHeight() == hwmheight ) if ( pindex->GetHeight() == hwmheight )

View File

@@ -557,9 +557,9 @@ uint64_t komodo_seed(int32_t height)
return(seed); return(seed);
} }
uint32_t komodo_txtime(uint64_t *valuep,uint256 hash, int32_t n, char *destaddr) uint32_t komodo_txtime(CScript &opret,uint64_t *valuep,uint256 hash, int32_t n, char *destaddr)
{ {
CTxDestination address; CTransaction tx; uint256 hashBlock; CTxDestination address; CTransaction tx; uint256 hashBlock; int32_t numvouts;
*valuep = 0; *valuep = 0;
if (!GetTransaction(hash, tx, if (!GetTransaction(hash, tx,
#ifndef KOMODO_ZCASH #ifndef KOMODO_ZCASH
@@ -570,10 +570,12 @@ uint32_t komodo_txtime(uint64_t *valuep,uint256 hash, int32_t n, char *destaddr)
//fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); //fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
return(0); return(0);
} }
numvouts = tx.vout.size();
//fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); //fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
if ( n < tx.vout.size() ) if ( n < numvouts )
{ {
*valuep = tx.vout[n].nValue; *valuep = tx.vout[n].nValue;
opret = tx.vout[numvouts-1].scriptPubKey;
if (ExtractDestination(tx.vout[n].scriptPubKey, address)) if (ExtractDestination(tx.vout[n].scriptPubKey, address))
strcpy(destaddr,CBitcoinAddress(address).ToString().c_str()); strcpy(destaddr,CBitcoinAddress(address).ToString().c_str());
} }
@@ -614,12 +616,12 @@ uint32_t komodo_txtime2(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr)
int32_t komodo_WhoStaked(CBlock *pblock, CTxDestination &addressout) int32_t komodo_WhoStaked(CBlock *pblock, CTxDestination &addressout)
{ {
int32_t n,vout; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid; int32_t n,vout; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid; CScript opret;
if ( (n= pblock->vtx.size()) > 1 && pblock->vtx[n-1].vin.size() == 1 && pblock->vtx[n-1].vout.size() == 1 ) if ( (n= pblock->vtx.size()) > 1 && pblock->vtx[n-1].vin.size() == 1 && pblock->vtx[n-1].vout.size() == 1 )
{ {
txid = pblock->vtx[n-1].vin[0].prevout.hash; txid = pblock->vtx[n-1].vin[0].prevout.hash;
vout = pblock->vtx[n-1].vin[0].prevout.n; vout = pblock->vtx[n-1].vin[0].prevout.n;
txtime = komodo_txtime(&value,txid,vout,destaddr); txtime = komodo_txtime(opret,&value,txid,vout,destaddr);
if ( ExtractDestination(pblock->vtx[n-1].vout[0].scriptPubKey,voutaddress) ) if ( ExtractDestination(pblock->vtx[n-1].vout[0].scriptPubKey,voutaddress) )
{ {
strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str());
@@ -634,23 +636,41 @@ int32_t komodo_WhoStaked(CBlock *pblock, CTxDestination &addressout)
return(0); return(0);
} }
int32_t komodo_isPoS(CBlock *pblock) bool MarmaraPoScheck(char *destaddr,CScript opret,CTransaction staketx);
int32_t komodo_isPoS(CBlock *pblock,int32_t height)
{ {
int32_t n,vout; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid; int32_t n,vout,numvouts; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid; CScript opret;
if ( ASSETCHAINS_STAKED != 0 ) if ( ASSETCHAINS_STAKED != 0 )
{ {
if ( (n= pblock->vtx.size()) > 1 && pblock->vtx[n-1].vin.size() == 1 && pblock->vtx[n-1].vout.size() == 1 ) n = pblock->vtx.size();
//fprintf(stderr,"ht.%d check for PoS numtx.%d numvins.%d numvouts.%d\n",height,n,(int32_t)pblock->vtx[n-1].vin.size(),(int32_t)pblock->vtx[n-1].vout.size());
if ( n > 1 && pblock->vtx[n-1].vin.size() == 1 && pblock->vtx[n-1].vout.size() == 1+(ASSETCHAINS_MARMARA!=0) )
{ {
txid = pblock->vtx[n-1].vin[0].prevout.hash; txid = pblock->vtx[n-1].vin[0].prevout.hash;
vout = pblock->vtx[n-1].vin[0].prevout.n; vout = pblock->vtx[n-1].vin[0].prevout.n;
txtime = komodo_txtime(&value,txid,vout,destaddr); txtime = komodo_txtime(opret,&value,txid,vout,destaddr);
if ( ExtractDestination(pblock->vtx[n-1].vout[0].scriptPubKey,voutaddress) ) if ( ExtractDestination(pblock->vtx[n-1].vout[0].scriptPubKey,voutaddress) )
{ {
strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str());
if ( strcmp(destaddr,voutaddr) == 0 && pblock->vtx[n-1].vout[0].nValue == value ) //fprintf(stderr,"voutaddr.%s vs destaddr.%s\n",voutaddr,destaddr);
if ( pblock->vtx[n-1].vout[0].nValue == value && strcmp(destaddr,voutaddr) == 0 )
{ {
//fprintf(stderr,"is PoS block!\n"); if ( ASSETCHAINS_MARMARA == 0 )
return(1); return(1);
else
{
if ( pblock->vtx[n-1].vout[0].scriptPubKey.IsPayToCryptoCondition() != 0 && (numvouts= pblock->vtx[n-1].vout.size()) == 2 )
{
//fprintf(stderr,"validate proper %s %s signature and unlockht preservation\n",voutaddr,destaddr);
return(MarmaraPoScheck(destaddr,opret,pblock->vtx[n-1]));
}
else
{
fprintf(stderr,"reject ht.%d PoS block\n",height);
return(strcmp(ASSETCHAINS_SYMBOL,"MTST2") == 0); // allow until MTST3
}
}
} }
} }
} }
@@ -1190,7 +1210,7 @@ uint32_t komodo_segid32(char *coinaddr)
int8_t komodo_segid(int32_t nocache,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; CTxDestination voutaddress; CBlock block; CBlockIndex *pindex; uint64_t value; uint32_t txtime; char voutaddr[64],destaddr[64]; int32_t txn_count,vout; uint256 txid; CScript opret; int8_t segid = -1;
if ( height > 0 && (pindex= komodo_chainactive(height)) != 0 ) if ( height > 0 && (pindex= komodo_chainactive(height)) != 0 )
{ {
if ( nocache == 0 && pindex->segid >= -1 ) if ( nocache == 0 && pindex->segid >= -1 )
@@ -1202,7 +1222,7 @@ int8_t komodo_segid(int32_t nocache,int32_t height)
{ {
txid = block.vtx[txn_count-1].vin[0].prevout.hash; txid = block.vtx[txn_count-1].vin[0].prevout.hash;
vout = block.vtx[txn_count-1].vin[0].prevout.n; vout = block.vtx[txn_count-1].vin[0].prevout.n;
txtime = komodo_txtime(&value,txid,vout,destaddr); txtime = komodo_txtime(opret,&value,txid,vout,destaddr);
if ( ExtractDestination(block.vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) ) if ( ExtractDestination(block.vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) )
{ {
strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str());
@@ -1444,12 +1464,14 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_
pindex = it != mapBlockIndex.end() ? it->second : NULL; pindex = it != mapBlockIndex.end() ? it->second : NULL;
if ( pindex != 0 && pindex->segid >= -1 ) if ( pindex != 0 && pindex->segid >= -1 )
{ {
//fprintf(stderr,"isPoSblock segid.%d\n",pindex->segid);
if ( pindex->segid == -1 ) if ( pindex->segid == -1 )
return(0); return(0);
else return(1); else return(1);
} }
txn_count = pblock->vtx.size(); 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 ) //fprintf(stderr,"checkblock n.%d vins.%d vouts.%d %.8f %.8f\n",txn_count,(int32_t)pblock->vtx[txn_count-1].vin.size(),(int32_t)pblock->vtx[txn_count-1].vout.size(),(double)pblock->vtx[txn_count-1].vout[0].nValue/COIN,(double)pblock->vtx[txn_count-1].vout[1].nValue/COIN);
if ( txn_count > 1 && pblock->vtx[txn_count-1].vin.size() == 1 && pblock->vtx[txn_count-1].vout.size() == 1 + (ASSETCHAINS_MARMARA!=0) )
{ {
it = mapBlockIndex.find(pblock->hashPrevBlock); it = mapBlockIndex.find(pblock->hashPrevBlock);
if ( it != mapBlockIndex.end() && (previndex = it->second) != NULL ) if ( it != mapBlockIndex.end() && (previndex = it->second) != NULL )
@@ -1459,7 +1481,7 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_
vout = pblock->vtx[txn_count-1].vin[0].prevout.n; vout = pblock->vtx[txn_count-1].vin[0].prevout.n;
if ( prevtime != 0 ) if ( prevtime != 0 )
{ {
if ( komodo_isPoS(pblock) != 0 ) if ( komodo_isPoS(pblock,height) != 0 )
{ {
eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime+27,(char *)""); eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime+27,(char *)"");
} }
@@ -1495,7 +1517,7 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_
} }
if ( slowflag == 0 && isPoS == 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 ) if ( komodo_isPoS(pblock,height) != 0 )
isPoS = 1; isPoS = 1;
} }
if ( slowflag != 0 && isPoS != 0 ) if ( slowflag != 0 && isPoS != 0 )
@@ -1808,6 +1830,7 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
return(-1); return(-1);
} }
} }
//fprintf(stderr,"ASSETCHAINS_STAKED.%d ht.%d\n",(int32_t)ASSETCHAINS_STAKED,height);
if ( ASSETCHAINS_STAKED != 0 && height >= 2 ) // must PoS or have at least 16x better PoW 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,bhash)) == 0 ) if ( (is_PoSblock= komodo_is_PoSblock(slowflag,height,pblock,bnTarget,bhash)) == 0 )
@@ -2064,6 +2087,9 @@ uint32_t komodo_eligible(arith_uint256 bnTarget,arith_uint256 ratio,struct komod
return(0); return(0);
} }
int32_t MarmaraSignature(uint8_t *utxosig,CMutableTransaction &txNew);
uint8_t DecodeMaramaraCoinbaseOpRet(const CScript scriptPubKey,CPubKey &pk,int32_t &height,int32_t &unlockht);
int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig) int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig)
{ {
static struct komodo_staking *array; static int32_t numkp,maxkp; static uint32_t lasttime; static struct komodo_staking *array; static int32_t numkp,maxkp; static uint32_t lasttime;
@@ -2112,6 +2138,8 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
maxkp = numkp = 0; maxkp = numkp = 0;
lasttime = 0; lasttime = 0;
} }
if ( ASSETCHAINS_MARMARA == 0 )
{
BOOST_FOREACH(const COutput& out, vecOutputs) BOOST_FOREACH(const COutput& out, vecOutputs)
{ {
if ( (tipindex= chainActive.Tip()) == 0 || tipindex->GetHeight()+1 > nHeight ) if ( (tipindex= chainActive.Tip()) == 0 || tipindex->GetHeight()+1 > nHeight )
@@ -2140,6 +2168,33 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
} }
} }
} }
}
else
{
struct CCcontract_info *cp,C; uint256 txid; int32_t vout,ht,unlockht; CAmount nValue; char coinaddr[64]; CPubKey mypk,Marmarapk,pk;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
cp = CCinit(&C,EVAL_MARMARA);
mypk = pubkey2pk(Mypubkey());
Marmarapk = GetUnspendable(cp,0);
GetCCaddress1of2(cp,coinaddr,Marmarapk,mypk);
SetCCunspents(unspentOutputs,coinaddr);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
txid = it->first.txhash;
vout = (int32_t)it->first.index;
if ( (nValue= it->second.satoshis) < COIN )
continue;
if ( GetTransaction(txid,tx,hashBlock,true) != 0 && (pindex= komodo_getblockindex(hashBlock)) != 0 && myIsutxo_spentinmempool(txid,vout) == 0 )
{
const CScript &scriptPubKey = tx.vout[vout].scriptPubKey;
if ( DecodeMaramaraCoinbaseOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,pk,ht,unlockht) != 0 && pk == mypk )
{
array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,txid,vout,coinaddr,hashbuf,(CScript)scriptPubKey);
}
// else fprintf(stderr,"SKIP addutxo %.8f numkp.%d vs max.%d\n",(double)nValue/COIN,numkp,maxkp);
}
}
}
lasttime = (uint32_t)time(NULL); lasttime = (uint32_t)time(NULL);
//fprintf(stderr,"finished kp data of utxo for staking %u ht.%d numkp.%d maxkp.%d\n",(uint32_t)time(NULL),nHeight,numkp,maxkp); //fprintf(stderr,"finished kp data of utxo for staking %u ht.%d numkp.%d maxkp.%d\n",(uint32_t)time(NULL),nHeight,numkp,maxkp);
} }
@@ -2176,7 +2231,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
} }
else else
{ {
fprintf(stderr,"ht.%d error validating winning blocktime %u -> %.8f eligible.%u test prior\n",nHeight,*blocktimep,(double)kp->nValue/COIN,eligible); //fprintf(stderr,"ht.%d error validating winning blocktime %u -> %.8f eligible.%u test prior\n",nHeight,*blocktimep,(double)kp->nValue/COIN,eligible);
continue; continue;
} }
eligible = besttime; eligible = besttime;
@@ -2218,16 +2273,26 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
txNew.vout[0].nValue = *utxovaluep - txfee; txNew.vout[0].nValue = *utxovaluep - txfee;
txNew.nLockTime = earliest; txNew.nLockTime = earliest;
CTransaction txNewConst(txNew); CTransaction txNewConst(txNew);
signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, *utxovaluep, SIGHASH_ALL), best_scriptPubKey, sigdata, consensusBranchId); if ( ASSETCHAINS_MARMARA == 0 )
if (!signSuccess)
fprintf(stderr,"failed to create signature\n");
else
{ {
signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, *utxovaluep, SIGHASH_ALL), best_scriptPubKey, sigdata, consensusBranchId);
UpdateTransaction(txNew,0,sigdata); UpdateTransaction(txNew,0,sigdata);
ptr = (uint8_t *)&sigdata.scriptSig[0]; ptr = (uint8_t *)&sigdata.scriptSig[0];
siglen = sigdata.scriptSig.size(); siglen = sigdata.scriptSig.size();
for (i=0; i<siglen; i++) for (i=0; i<siglen; i++)
utxosig[i] = ptr[i];//, fprintf(stderr,"%02x",ptr[i]); utxosig[i] = ptr[i];//, fprintf(stderr,"%02x",ptr[i]);
}
else
{
siglen = MarmaraSignature(utxosig,txNew);
if ( siglen > 0 )
signSuccess = true;
else signSuccess = false;
}
if (!signSuccess)
fprintf(stderr,"failed to create signature\n");
else
{
//fprintf(stderr," siglen.%d\n",siglen); //fprintf(stderr," siglen.%d\n",siglen);
//fprintf(stderr,"best %u from %u, gap %d lag.%d\n",earliest,*blocktimep,(int32_t)(earliest - *blocktimep),(int32_t)(time(NULL) - *blocktimep)); //fprintf(stderr,"best %u from %u, gap %d lag.%d\n",earliest,*blocktimep,(int32_t)(earliest - *blocktimep),(int32_t)(time(NULL) - *blocktimep));
*blocktimep = earliest; *blocktimep = earliest;

View File

@@ -30,7 +30,49 @@
#define KOMODO_SAPLING_DEADLINE 1550188800 // Feb 15th, 2019 #define KOMODO_SAPLING_DEADLINE 1550188800 // Feb 15th, 2019
#define _COINBASE_MATURITY 100 #define _COINBASE_MATURITY 100
#define SETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] |= (1 << ((bitoffset) & 7)))
#define GETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] & (1 << ((bitoffset) & 7)))
#define CLEARBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] &= ~(1 << ((bitoffset) & 7)))
extern uint8_t ASSETCHAINS_TXPOW,ASSETCHAINS_PUBLIC; extern uint8_t ASSETCHAINS_TXPOW,ASSETCHAINS_PUBLIC;
int32_t MAX_BLOCK_SIZE(int32_t height); int32_t MAX_BLOCK_SIZE(int32_t height);
extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT;
extern uint32_t ASSETCHAIN_INIT, ASSETCHAINS_MAGIC;
extern int32_t VERUS_BLOCK_POSUNITS, ASSETCHAINS_LWMAPOS, ASSETCHAINS_SAPLING, ASSETCHAINS_OVERWINTER;
extern uint64_t ASSETCHAINS_SUPPLY;
extern uint64_t ASSETCHAINS_TIMELOCKGTE;
extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH,ASSETCHAINS_EQUIHASH,KOMODO_INITDONE;
extern int32_t KOMODO_MININGTHREADS,KOMODO_LONGESTCHAIN,ASSETCHAINS_SEED,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,KOMODO_ON_DEMAND,KOMODO_PASSPORT_INITDONE;
extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_STAKED;
extern bool VERUS_MINTBLOCKS;
extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[];
extern const char *ASSETCHAINS_ALGORITHMS[];
extern int32_t VERUS_MIN_STAKEAGE;
extern uint32_t ASSETCHAINS_VERUSHASH, ASSETCHAINS_LASTERA, ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[];
extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY,ASSETCHAINS_SCRIPTPUB;
extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_MARMARA;
extern char ASSETCHAINS_SYMBOL[65];
extern int32_t VERUS_BLOCK_POSUNITS, VERUS_CONSECUTIVE_POS_THRESHOLD, VERUS_NOPOS_THRESHHOLD;
extern int32_t KOMODO_CONNECTING,KOMODO_CCACTIVATE,KOMODO_DEALERNODE;
extern uint32_t ASSETCHAINS_CC;
extern char ASSETCHAINS_SYMBOL[];
extern std::string CCerror,ASSETCHAINS_CCLIB;
extern uint8_t ASSETCHAINS_CCDISABLES[256];
extern int32_t USE_EXTERNAL_PUBKEY;
extern std::string NOTARY_PUBKEY;
extern int32_t KOMODO_EXCHANGEWALLET;
extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
extern int32_t VERUS_MIN_STAKEAGE;
extern std::string DONATION_PUBKEY;
extern uint8_t ASSETCHAINS_PRIVATE;
extern int32_t USE_EXTERNAL_PUBKEY;
#endif #endif

View File

@@ -1388,7 +1388,7 @@ void komodo_passport_iteration()
{ {
static long lastpos[34]; static char userpass[33][1024]; static uint32_t lasttime,callcounter,lastinterest; static long lastpos[34]; static char userpass[33][1024]; static uint32_t lasttime,callcounter,lastinterest;
int32_t maxseconds = 10; int32_t maxseconds = 10;
FILE *fp; uint8_t *filedata; long fpos,datalen,lastfpos; int32_t baseid,limit,n,ht,isrealtime,expired,refid,blocks,longest; struct komodo_state *sp,*refsp; char *retstr,fname[512],*base,symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; uint32_t buf[3],starttime; cJSON *infoobj,*result; uint64_t RTmask = 0; //CBlockIndex *pindex; FILE *fp; uint8_t *filedata; long fpos,datalen,lastfpos; int32_t baseid,limit,n,ht,isrealtime,expired,refid,blocks,longest; struct komodo_state *sp,*refsp; char *retstr,fname[512],*base,symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; uint32_t buf[3],starttime; uint64_t RTmask = 0; //CBlockIndex *pindex;
expired = 0; expired = 0;
while ( KOMODO_INITDONE == 0 ) while ( KOMODO_INITDONE == 0 )
{ {

View File

@@ -48,7 +48,7 @@ unsigned int WITNESS_CACHE_SIZE = _COINBASE_MATURITY+10;
int32_t KOMODO_MININGTHREADS = -1,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE,KOMODO_PAX,KOMODO_EXCHANGEWALLET,KOMODO_REWIND,KOMODO_CONNECTING = -1,KOMODO_DEALERNODE,KOMODO_EXTRASATOSHI,ASSETCHAINS_FOUNDERS; int32_t KOMODO_MININGTHREADS = -1,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE,KOMODO_PAX,KOMODO_EXCHANGEWALLET,KOMODO_REWIND,KOMODO_CONNECTING = -1,KOMODO_DEALERNODE,KOMODO_EXTRASATOSHI,ASSETCHAINS_FOUNDERS;
int32_t KOMODO_INSYNC,KOMODO_LASTMINED,prevKOMODO_LASTMINED,KOMODO_CCACTIVATE,JUMBLR_PAUSE = 1; int32_t KOMODO_INSYNC,KOMODO_LASTMINED,prevKOMODO_LASTMINED,KOMODO_CCACTIVATE,JUMBLR_PAUSE = 1;
std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY,ASSETCHAINS_SCRIPTPUB,ASSETCHAINS_SELFIMPORT; std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY,ASSETCHAINS_SCRIPTPUB,ASSETCHAINS_SELFIMPORT,ASSETCHAINS_CCLIB;
uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEYHASH[20],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW,ASSETCHAINS_MARMARA; uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEYHASH[20],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW,ASSETCHAINS_MARMARA;
bool VERUS_MINTBLOCKS; bool VERUS_MINTBLOCKS;
@@ -71,6 +71,7 @@ uint64_t ASSETCHAINS_TIMEUNLOCKFROM = 0, ASSETCHAINS_TIMEUNLOCKTO = 0;
uint32_t ASSETCHAINS_LASTERA = 1; uint32_t ASSETCHAINS_LASTERA = 1;
uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_DECAY[ASSETCHAINS_MAX_ERAS]; uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_DECAY[ASSETCHAINS_MAX_ERAS];
uint8_t ASSETCHAINS_CCDISABLES[256];
#define _ASSETCHAINS_EQUIHASH 0 #define _ASSETCHAINS_EQUIHASH 0
uint32_t ASSETCHAINS_NUMALGOS = 2; uint32_t ASSETCHAINS_NUMALGOS = 2;

View File

@@ -629,7 +629,7 @@ uint64_t jumblr_increment(uint8_t r,int32_t height,uint64_t total,uint64_t bigge
void jumblr_iteration() void jumblr_iteration()
{ {
static int32_t lastheight; static uint32_t lasttime; static int32_t lastheight; static uint32_t lasttime;
char *zaddr,*addr,*retstr,secretaddr[64]; cJSON *array; int32_t i,iter,height,acpublic,counter,chosen_one,n; uint64_t smallest,medium,biggest,amount=0,total=0; double fee; struct jumblr_item *ptr,*tmp; uint16_t r,s; char *zaddr,*addr,*retstr=0,secretaddr[64]; cJSON *array; int32_t i,iter,height,acpublic,counter,chosen_one,n; uint64_t smallest,medium,biggest,amount=0,total=0; double fee; struct jumblr_item *ptr,*tmp; uint16_t r,s;
acpublic = ASSETCHAINS_PUBLIC; acpublic = ASSETCHAINS_PUBLIC;
if ( ASSETCHAINS_SYMBOL[0] == 0 && GetTime() >= KOMODO_SAPLING_DEADLINE ) if ( ASSETCHAINS_SYMBOL[0] == 0 && GetTime() >= KOMODO_SAPLING_DEADLINE )
acpublic = 1; acpublic = 1;
@@ -648,7 +648,7 @@ void jumblr_iteration()
} }
free_json(array); free_json(array);
} }
free(retstr); free(retstr), retstr = 0;
} }
} }
height = (int32_t)chainActive.LastTip()->GetHeight(); height = (int32_t)chainActive.LastTip()->GetHeight();
@@ -691,7 +691,7 @@ void jumblr_iteration()
if ( amount > 0 && (retstr= jumblr_sendt_to_z(Jumblr_deposit,addr,dstr(amount))) != 0 ) if ( amount > 0 && (retstr= jumblr_sendt_to_z(Jumblr_deposit,addr,dstr(amount))) != 0 )
{ {
printf("sendt_to_z.(%s)\n",retstr); printf("sendt_to_z.(%s)\n",retstr);
free(retstr); free(retstr), retstr = 0;
} }
free(zaddr); free(zaddr);
} else printf("no zaddr from jumblr_zgetnewaddress\n"); } else printf("no zaddr from jumblr_zgetnewaddress\n");
@@ -723,7 +723,7 @@ void jumblr_iteration()
if ( (retstr= jumblr_sendz_to_z(ptr->dest,addr,dstr(total))) != 0 ) if ( (retstr= jumblr_sendz_to_z(ptr->dest,addr,dstr(total))) != 0 )
{ {
printf("n.%d counter.%d chosen_one.%d send z_to_z.(%s)\n",n,counter,chosen_one,retstr); printf("n.%d counter.%d chosen_one.%d send z_to_z.(%s)\n",n,counter,chosen_one,retstr);
free(retstr); free(retstr), retstr = 0;
} }
ptr->spent = (uint32_t)time(NULL); ptr->spent = (uint32_t)time(NULL);
free(zaddr); free(zaddr);
@@ -768,7 +768,7 @@ void jumblr_iteration()
if ( (retstr= jumblr_sendz_to_t(ptr->dest,secretaddr,dstr(total))) != 0 ) if ( (retstr= jumblr_sendz_to_t(ptr->dest,secretaddr,dstr(total))) != 0 )
{ {
printf("%s send z_to_t.(%s)\n",secretaddr,retstr); printf("%s send z_to_t.(%s)\n",secretaddr,retstr);
free(retstr); free(retstr), retstr = 0;
} else printf("null return from jumblr_sendz_to_t\n"); } else printf("null return from jumblr_sendz_to_t\n");
ptr->spent = (uint32_t)time(NULL); ptr->spent = (uint32_t)time(NULL);
break; break;

View File

@@ -1654,9 +1654,10 @@ extern int64_t MAX_MONEY;
void komodo_args(char *argv0) void komodo_args(char *argv0)
{ {
extern const char *Notaries_elected1[][2]; extern const char *Notaries_elected1[][2];
std::string name,addn; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[8192],*extraptr=0; FILE *fp; uint64_t val; uint16_t port; int32_t i,baseid,len,n,extralen = 0; std::string name,addn; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[8192],disablebits[32],*extraptr=0; FILE *fp; uint64_t val; uint16_t port; int32_t i,nonz,baseid,len,n,extralen = 0; uint64_t ccenables[256];
IS_KOMODO_NOTARY = GetBoolArg("-notary", false); IS_KOMODO_NOTARY = GetBoolArg("-notary", false);
memset(ccenables,0,sizeof(ccenables));
memset(disablebits,0,sizeof(disablebits));
if ( GetBoolArg("-gen", false) != 0 ) if ( GetBoolArg("-gen", false) != 0 )
{ {
KOMODO_MININGTHREADS = GetArg("-genproclimit",-1); KOMODO_MININGTHREADS = GetArg("-genproclimit",-1);
@@ -1779,6 +1780,33 @@ void komodo_args(char *argv0)
ASSETCHAINS_BEAMPORT = GetArg("-ac_beam",0); ASSETCHAINS_BEAMPORT = GetArg("-ac_beam",0);
ASSETCHAINS_CODAPORT = GetArg("-ac_coda",0); ASSETCHAINS_CODAPORT = GetArg("-ac_coda",0);
ASSETCHAINS_MARMARA = GetArg("-ac_marmara",0); ASSETCHAINS_MARMARA = GetArg("-ac_marmara",0);
if ( ASSETCHAINS_CC != 0 )
{
ASSETCHAINS_CCLIB = GetArg("-ac_cclib","");
Split(GetArg("-ac_ccenable",""), ccenables, 0);
for (i=nonz=0; i<0x100; i++)
{
if ( ccenables[i] != 0 )
{
nonz++;
fprintf(stderr,"%d ",(uint8_t)(ccenables[i] & 0xff));
}
}
fprintf(stderr,"nonz.%d ccenables[]\n",nonz);
if ( nonz > 0 )
{
for (i=0; i<256; i++)
{
ASSETCHAINS_CCDISABLES[i] = 1;
SETBIT(disablebits,i);
}
for (i=0; i<256; i++)
{
CLEARBIT(disablebits,(ccenables[i] & 0xff));
ASSETCHAINS_CCDISABLES[ccenables[i] & 0xff] = 0;
}
}
}
if ( ASSETCHAINS_BEAMPORT != 0 && ASSETCHAINS_CODAPORT != 0 ) if ( ASSETCHAINS_BEAMPORT != 0 && ASSETCHAINS_CODAPORT != 0 )
{ {
fprintf(stderr,"can only have one of -ac_beam or -ac_coda\n"); fprintf(stderr,"can only have one of -ac_beam or -ac_coda\n");
@@ -1863,7 +1891,7 @@ void komodo_args(char *argv0)
fprintf(stderr,"-ac_script and -ac_marmara are mutually exclusive\n"); fprintf(stderr,"-ac_script and -ac_marmara are mutually exclusive\n");
exit(0); exit(0);
} }
if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1 || ASSETCHAINS_SELFIMPORT.size() > 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF|| ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LWMAPOS != 0 || ASSETCHAINS_LASTERA > 0 || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 || ASSETCHAINS_MARMARA != 0 ) if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1 || ASSETCHAINS_SELFIMPORT.size() > 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF|| ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LWMAPOS != 0 || ASSETCHAINS_LASTERA > 0 || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 || ASSETCHAINS_MARMARA != 0 || nonz > 0 || ASSETCHAINS_CCLIB.size() > 0 )
{ {
fprintf(stderr,"perc %.4f%% ac_pub=[%02x%02x%02x...] acsize.%d\n",dstr(ASSETCHAINS_COMMISSION)*100,ASSETCHAINS_OVERRIDE_PUBKEY33[0],ASSETCHAINS_OVERRIDE_PUBKEY33[1],ASSETCHAINS_OVERRIDE_PUBKEY33[2],(int32_t)ASSETCHAINS_SCRIPTPUB.size()); fprintf(stderr,"perc %.4f%% ac_pub=[%02x%02x%02x...] acsize.%d\n",dstr(ASSETCHAINS_COMMISSION)*100,ASSETCHAINS_OVERRIDE_PUBKEY33[0],ASSETCHAINS_OVERRIDE_PUBKEY33[1],ASSETCHAINS_OVERRIDE_PUBKEY33[2],(int32_t)ASSETCHAINS_SCRIPTPUB.size());
extraptr = extrabuf; extraptr = extrabuf;
@@ -1939,6 +1967,20 @@ void komodo_args(char *argv0)
extraptr[extralen++] = 'c'; extraptr[extralen++] = 'c';
if ( ASSETCHAINS_MARMARA != 0 ) if ( ASSETCHAINS_MARMARA != 0 )
extraptr[extralen++] = ASSETCHAINS_MARMARA; extraptr[extralen++] = ASSETCHAINS_MARMARA;
if ( nonz > 0 )
{
memcpy(&extraptr[extralen],disablebits,sizeof(disablebits));
extralen += sizeof(disablebits);
}
if ( ASSETCHAINS_CCLIB.size() > 1 )
{
for (i=0; i<ASSETCHAINS_CCLIB.size(); i++)
{
extraptr[extralen++] = ASSETCHAINS_CCLIB[i];
fprintf(stderr,"%c",ASSETCHAINS_CCLIB[i]);
}
fprintf(stderr," <- CCLIB name\n");
}
} }
addn = GetArg("-seednode",""); addn = GetArg("-seednode","");

View File

@@ -3497,6 +3497,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
CDiskBlockPos pos; CDiskBlockPos pos;
if (!FindUndoPos(state, pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40)) if (!FindUndoPos(state, pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40))
return error("ConnectBlock(): FindUndoPos failed"); return error("ConnectBlock(): FindUndoPos failed");
if ( pindex->pprev == 0 )
fprintf(stderr,"ConnectBlock: unexpected null pprev\n");
if (!UndoWriteToDisk(blockundo, pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart())) if (!UndoWriteToDisk(blockundo, pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart()))
return AbortNode(state, "Failed to write undo data"); return AbortNode(state, "Failed to write undo data");
@@ -3804,7 +3806,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
CValidationState stateDummy; CValidationState stateDummy;
// don't keep staking or invalid transactions // don't keep staking or invalid transactions
if (tx.IsCoinBase() || ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED && komodo_isPoS((CBlock *)&block) != 0)) || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL)) if (tx.IsCoinBase() || ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED && komodo_isPoS((CBlock *)&block,pindexDelete->GetHeight()) != 0)) || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL))
{ {
mempool.remove(tx, removed, true); mempool.remove(tx, removed, true);
} }
@@ -3835,7 +3837,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
{ {
CTransaction &tx = block.vtx[i]; CTransaction &tx = block.vtx[i];
//if ((i == (block.vtx.size() - 1)) && ((ASSETCHAINS_LWMAPOS && block.IsVerusPOSBlock()) || (ASSETCHAINS_STAKED != 0 && (komodo_isPoS((CBlock *)&block) != 0)))) //if ((i == (block.vtx.size() - 1)) && ((ASSETCHAINS_LWMAPOS && block.IsVerusPOSBlock()) || (ASSETCHAINS_STAKED != 0 && (komodo_isPoS((CBlock *)&block) != 0))))
if ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED != 0 && (komodo_isPoS((CBlock *)&block) != 0))) if ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED != 0 && (komodo_isPoS((CBlock *)&block,pindexDelete->GetHeight()) != 0)))
{ {
EraseFromWallets(tx.GetHash()); EraseFromWallets(tx.GetHash());
} }
@@ -4732,7 +4734,7 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C
CValidationState state; CValidationState state;
CTransaction Tx; CTransaction Tx;
const CTransaction &tx = (CTransaction)block.vtx[i]; const CTransaction &tx = (CTransaction)block.vtx[i];
if (tx.IsCoinBase() || !tx.vjoinsplit.empty() || !tx.vShieldedSpend.empty() || ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED && komodo_isPoS((CBlock *)&block) != 0))) if (tx.IsCoinBase() || !tx.vjoinsplit.empty() || !tx.vShieldedSpend.empty() || ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED && komodo_isPoS((CBlock *)&block,height) != 0)))
continue; continue;
Tx = tx; Tx = tx;
if ( myAddtomempool(Tx, &state, true) == false ) // happens with out of order tx in block on resync if ( myAddtomempool(Tx, &state, true) == false ) // happens with out of order tx in block on resync

View File

@@ -39,8 +39,7 @@
#endif #endif
#include <unistd.h> #include <unistd.h>
extern uint64_t ASSETCHAINS_TIMELOCKGTE; #include "komodo_defs.h"
extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH;
int64_t komodo_block_unlocktime(uint32_t nHeight); int64_t komodo_block_unlocktime(uint32_t nHeight);
void AtomicTimer::start() void AtomicTimer::start()

View File

@@ -132,17 +132,8 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams,
#include "komodo_defs.h" #include "komodo_defs.h"
extern CCriticalSection cs_metrics; extern CCriticalSection cs_metrics;
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_COMMISSION, ASSETCHAINS_STAKED;
extern bool VERUS_MINTBLOCKS;
extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[];
extern const char *ASSETCHAINS_ALGORITHMS[];
extern int32_t VERUS_MIN_STAKEAGE, ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH, ASSETCHAINS_VERUSHASH, ASSETCHAINS_LASTERA, ASSETCHAINS_LWMAPOS, ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[];
extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY,ASSETCHAINS_SCRIPTPUB;
void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len); void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len);
extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_MARMARA;
uint32_t Mining_start,Mining_height; uint32_t Mining_start,Mining_height;
int32_t My_notaryid = -1; int32_t My_notaryid = -1;
int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp);
@@ -158,6 +149,7 @@ int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33);
int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex);
CScript Marmara_scriptPubKey(int32_t height,CPubKey pk); CScript Marmara_scriptPubKey(int32_t height,CPubKey pk);
CScript MarmaraCoinbaseOpret(uint8_t funcid,int32_t height,CPubKey pk); CScript MarmaraCoinbaseOpret(uint8_t funcid,int32_t height,CPubKey pk);
bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey);
CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32_t gpucount, bool isStake) CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32_t gpucount, bool isStake)
{ {
@@ -486,7 +478,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
{ {
LEAVE_CRITICAL_SECTION(cs_main); LEAVE_CRITICAL_SECTION(cs_main);
LEAVE_CRITICAL_SECTION(mempool.cs); LEAVE_CRITICAL_SECTION(mempool.cs);
uint64_t txfees,utxovalue; uint32_t txtime; uint256 utxotxid; int32_t i,siglen,numsigs,utxovout; uint8_t utxosig[128],*ptr; uint64_t txfees,utxovalue; uint32_t txtime; uint256 utxotxid; int32_t i,siglen,numsigs,utxovout; uint8_t utxosig[512],*ptr;
CMutableTransaction txStaked = CreateNewContextualCMutableTransaction(Params().GetConsensus(), stakeHeight); CMutableTransaction txStaked = CreateNewContextualCMutableTransaction(Params().GetConsensus(), stakeHeight);
if (ASSETCHAINS_LWMAPOS != 0) if (ASSETCHAINS_LWMAPOS != 0)
@@ -520,7 +512,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txStaked)); pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txStaked));
nFees += txfees; nFees += txfees;
pblock->nTime = blocktime; pblock->nTime = blocktime;
//printf("staking PoS ht.%d t%u lag.%u\n",(int32_t)chainActive.LastTip()->GetHeight()+1,blocktime,(uint32_t)(GetAdjustedTime() - (blocktime-13))); printf("staking PoS ht.%d t%u lag.%u\n",(int32_t)chainActive.LastTip()->GetHeight()+1,blocktime,(uint32_t)(GetAdjustedTime() - (blocktime-13)));
} else return(0); //fprintf(stderr,"no utxos eligible for staking\n"); } else return(0); //fprintf(stderr,"no utxos eligible for staking\n");
} }
// Create coinbase tx // Create coinbase tx
@@ -540,11 +532,11 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
txNew.vout[0].nValue += 5000; txNew.vout[0].nValue += 5000;
pblock->vtx[0] = txNew; pblock->vtx[0] = txNew;
//fprintf(stderr,"ht.%d cmp.%d [%d %d %d %d %d]\n",nHeight,nHeight > 1 && ASSETCHAINS_SYMBOL[0] != 0 && (ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1) && ASSETCHAINS_COMMISSION != 0 && (commission= komodo_commission((CBlock*)&pblocktemplate->block,(int32_t)nHeight)) != 0,nHeight > 1,ASSETCHAINS_SYMBOL[0] != 0, (ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1), ASSETCHAINS_COMMISSION != 0,(commission= komodo_commission((CBlock*)&pblocktemplate->block,(int32_t)nHeight)) != 0);
// check if coinbase transactions must be time locked at current subsidy and prepend the time lock
// to transaction if so, cast for GTE operator
if ( ASSETCHAINS_MARMARA != 0 && nHeight > 0 && (nHeight & 1) == 0 ) if ( ASSETCHAINS_MARMARA != 0 && nHeight > 0 && (nHeight & 1) == 0 )
{ {
char checkaddr[64];
Getscriptaddress(checkaddr,txNew.vout[0].scriptPubKey);
//`fprintf(stderr,"set mining coinbase -> %s\n",checkaddr);
txNew.vout.resize(2); txNew.vout.resize(2);
txNew.vout[1].nValue = 0; txNew.vout[1].nValue = 0;
txNew.vout[1].scriptPubKey = MarmaraCoinbaseOpret('C',nHeight,pk); txNew.vout[1].scriptPubKey = MarmaraCoinbaseOpret('C',nHeight,pk);
@@ -1605,11 +1597,11 @@ void static BitcoinMiner()
int32_t percPoS,z; bool fNegative,fOverflow; int32_t percPoS,z; bool fNegative,fOverflow;
HASHTarget_POW = komodo_PoWtarget(&percPoS,HASHTarget,Mining_height,ASSETCHAINS_STAKED); HASHTarget_POW = komodo_PoWtarget(&percPoS,HASHTarget,Mining_height,ASSETCHAINS_STAKED);
HASHTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); HASHTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
if ( ASSETCHAINS_STAKED < 100 ) if ( ASSETCHAINS_STAKED < 100 && KOMODO_MININGTHREADS == 0 )
{ {
for (z=31; z>=0; z--) for (z=31; z>=0; z--)
fprintf(stderr,"%02x",((uint8_t *)&HASHTarget_POW)[z]); fprintf(stderr,"%02x",((uint8_t *)&HASHTarget_POW)[z]);
fprintf(stderr," PoW for staked coin PoS %d%% vs target %d%%\n",percPoS,(int32_t)ASSETCHAINS_STAKED); fprintf(stderr," PoW for staked coin PoS %d%% vs target %d%% ht.%d\n",percPoS,(int32_t)ASSETCHAINS_STAKED,Mining_height);
} }
} }
while (true) while (true)

View File

@@ -37,9 +37,8 @@
#endif // ENABLE_RUST #endif // ENABLE_RUST
uint32_t komodo_chainactive_timestamp(); uint32_t komodo_chainactive_timestamp();
extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH, ASSETCHAINS_STAKED; #include "komodo_defs.h"
extern char ASSETCHAINS_SYMBOL[65];
extern int32_t ASSETCHAINS_LWMAPOS,VERUS_BLOCK_POSUNITS, VERUS_CONSECUTIVE_POS_THRESHOLD, VERUS_NOPOS_THRESHHOLD;
unsigned int lwmaGetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params); unsigned int lwmaGetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params);
unsigned int lwmaCalculateNextWorkRequired(const CBlockIndex* pindexLast, const Consensus::Params& params); unsigned int lwmaCalculateNextWorkRequired(const CBlockIndex* pindexLast, const Consensus::Params& params);

View File

@@ -24,8 +24,8 @@
#include "tinyformat.h" #include "tinyformat.h"
#include "utilstrencodings.h" #include "utilstrencodings.h"
#include "crypto/common.h" #include "crypto/common.h"
#include "komodo_defs.h"
extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH;
// default hash algorithm for block // default hash algorithm for block
uint256 (CBlockHeader::*CBlockHeader::hashFunction)() const = &CBlockHeader::GetSHA256DHash; uint256 (CBlockHeader::*CBlockHeader::hashFunction)() const = &CBlockHeader::GetSHA256DHash;

View File

@@ -48,10 +48,8 @@
using namespace std; using namespace std;
extern int32_t ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH, ASSETCHAINS_LWMAPOS; #include "komodo_defs.h"
extern uint64_t ASSETCHAINS_STAKED;
extern int32_t KOMODO_MININGTHREADS;
extern bool VERUS_MINTBLOCKS;
arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc); arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc);
/** /**

View File

@@ -77,7 +77,8 @@ int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heig
extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT;
extern uint32_t ASSETCHAINS_CC; extern uint32_t ASSETCHAINS_CC;
extern uint32_t ASSETCHAINS_MAGIC; extern uint32_t ASSETCHAINS_MAGIC;
extern uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED,ASSETCHAINS_SUPPLY,ASSETCHAINS_LASTERA; extern uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED,ASSETCHAINS_SUPPLY;
extern uint32_t ASSETCHAINS_LASTERA;
extern int32_t ASSETCHAINS_LWMAPOS,ASSETCHAINS_SAPLING; extern int32_t ASSETCHAINS_LWMAPOS,ASSETCHAINS_SAPLING;
extern uint64_t ASSETCHAINS_ENDSUBSIDY[],ASSETCHAINS_REWARD[],ASSETCHAINS_HALVING[],ASSETCHAINS_DECAY[]; extern uint64_t ASSETCHAINS_ENDSUBSIDY[],ASSETCHAINS_REWARD[],ASSETCHAINS_HALVING[],ASSETCHAINS_DECAY[];
extern std::string NOTARY_PUBKEY; extern uint8_t NOTARY_PUBKEY33[]; extern std::string NOTARY_PUBKEY; extern uint8_t NOTARY_PUBKEY33[];
@@ -224,7 +225,7 @@ UniValue getinfo(const UniValue& params, bool fHelp)
} }
} }
if (ASSETCHAINS_LASTERA > 0) if (ASSETCHAINS_LASTERA > 0)
obj.push_back(Pair("eras", ASSETCHAINS_LASTERA + 1)); obj.push_back(Pair("eras", (int64_t)(ASSETCHAINS_LASTERA + 1)));
obj.push_back(Pair("reward", acReward)); obj.push_back(Pair("reward", acReward));
obj.push_back(Pair("halving", acHalving)); obj.push_back(Pair("halving", acHalving));
obj.push_back(Pair("decay", acDecay)); obj.push_back(Pair("decay", acDecay));

View File

@@ -458,10 +458,15 @@ static const CRPCCommand vRPCCommands[] =
{ "marmara", "marmarainfo", &marmara_info, true }, { "marmara", "marmarainfo", &marmara_info, true },
{ "marmara", "marmaracreditloop", &marmara_creditloop, true }, { "marmara", "marmaracreditloop", &marmara_creditloop, true },
{ "marmara", "marmarasettlement", &marmara_settlement, true }, { "marmara", "marmarasettlement", &marmara_settlement, true },
{ "marmara", "marmaralock", &marmara_lock, true },
// Payments // Payments
{ "payments", "paymentsaddress", &paymentsaddress, true }, { "payments", "paymentsaddress", &paymentsaddress, true },
{ "CClib", "cclibaddress", &cclibaddress, true },
{ "CClib", "cclibinfo", &cclibinfo, true },
{ "CClib", "cclib", &cclib, true },
// Gateways // Gateways
{ "gateways", "gatewaysaddress", &gatewaysaddress, true }, { "gateways", "gatewaysaddress", &gatewaysaddress, true },
{ "gateways", "gatewayslist", &gatewayslist, true }, { "gateways", "gatewayslist", &gatewayslist, true },
@@ -532,6 +537,9 @@ static const CRPCCommand vRPCCommands[] =
{ "util", "reconsiderblock", &reconsiderblock, true }, { "util", "reconsiderblock", &reconsiderblock, true },
/* Not shown in help */ /* Not shown in help */
{ "hidden", "setmocktime", &setmocktime, true }, { "hidden", "setmocktime", &setmocktime, true },
{ "hidden", "test_ac", &test_ac, true },
{ "hidden", "test_heirmarker", &test_heirmarker, true },
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
/* Wallet */ /* Wallet */
{ "wallet", "resendwallettransactions", &resendwallettransactions, true}, { "wallet", "resendwallettransactions", &resendwallettransactions, true},

View File

@@ -285,7 +285,11 @@ extern UniValue marmara_transfer(const UniValue& params, bool fHelp);
extern UniValue marmara_info(const UniValue& params, bool fHelp); extern UniValue marmara_info(const UniValue& params, bool fHelp);
extern UniValue marmara_creditloop(const UniValue& params, bool fHelp); extern UniValue marmara_creditloop(const UniValue& params, bool fHelp);
extern UniValue marmara_settlement(const UniValue& params, bool fHelp); extern UniValue marmara_settlement(const UniValue& params, bool fHelp);
extern UniValue marmara_lock(const UniValue& params, bool fHelp);
extern UniValue paymentsaddress(const UniValue& params, bool fHelp); extern UniValue paymentsaddress(const UniValue& params, bool fHelp);
extern UniValue cclibaddress(const UniValue& params, bool fHelp);
extern UniValue cclibinfo(const UniValue& params, bool fHelp);
extern UniValue cclib(const UniValue& params, bool fHelp);
extern UniValue gatewaysaddress(const UniValue& params, bool fHelp); extern UniValue gatewaysaddress(const UniValue& params, bool fHelp);
extern UniValue gatewayslist(const UniValue& params, bool fHelp); extern UniValue gatewayslist(const UniValue& params, bool fHelp);
extern UniValue gatewaysinfo(const UniValue& params, bool fHelp); extern UniValue gatewaysinfo(const UniValue& params, bool fHelp);
@@ -467,4 +471,8 @@ extern UniValue paxprices(const UniValue& params, bool fHelp);
extern UniValue paxdeposit(const UniValue& params, bool fHelp); extern UniValue paxdeposit(const UniValue& params, bool fHelp);
extern UniValue paxwithdraw(const UniValue& params, bool fHelp); extern UniValue paxwithdraw(const UniValue& params, bool fHelp);
// test rpc:
extern UniValue test_ac(const UniValue& params, bool fHelp);
extern UniValue test_heirmarker(const UniValue& params, bool fHelp);
#endif // BITCOIN_RPCSERVER_H #endif // BITCOIN_RPCSERVER_H

View File

@@ -647,3 +647,4 @@ bool DummySignatureCreator::CreateSig(
vchSig[6 + 33 + 32] = SIGHASH_ALL; vchSig[6 + 33 + 32] = SIGHASH_ALL;
return true; return true;
} }

View File

@@ -57,6 +57,7 @@
#include <numeric> #include <numeric>
#include "komodo_defs.h"
using namespace std; using namespace std;
@@ -67,8 +68,6 @@ const std::string ADDR_TYPE_SPROUT = "sprout";
const std::string ADDR_TYPE_SAPLING = "sapling"; const std::string ADDR_TYPE_SAPLING = "sapling";
extern UniValue TxJoinSplitToJSON(const CTransaction& tx); extern UniValue TxJoinSplitToJSON(const CTransaction& tx);
extern uint8_t ASSETCHAINS_PRIVATE;
extern int32_t USE_EXTERNAL_PUBKEY;
uint32_t komodo_segid32(char *coinaddr); uint32_t komodo_segid32(char *coinaddr);
int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); int32_t komodo_dpowconfs(int32_t height,int32_t numconfs);
int32_t komodo_isnotaryvout(char *coinaddr); // from ac_private chains only int32_t komodo_isnotaryvout(char *coinaddr); // from ac_private chains only
@@ -5094,8 +5093,8 @@ int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33)
if (!EnsureWalletIsAvailable(0)) if (!EnsureWalletIsAvailable(0))
return 0; return 0;
const CKeyStore& keystore = *pwalletMain;
assert(pwalletMain != NULL); assert(pwalletMain != NULL);
const CKeyStore& keystore = *pwalletMain;
LOCK2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet);
utxovalue = 0; utxovalue = 0;
memset(&utxotxid,0,sizeof(utxotxid)); memset(&utxotxid,0,sizeof(utxotxid));
@@ -5172,7 +5171,6 @@ int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits
int32_t ensure_CCrequirements() int32_t ensure_CCrequirements()
{ {
extern uint8_t NOTARY_PUBKEY33[];
CCerror = ""; CCerror = "";
if ( NOTARY_PUBKEY33[0] == 0 ) if ( NOTARY_PUBKEY33[0] == 0 )
return(-1); return(-1);
@@ -5262,8 +5260,6 @@ UniValue setpubkey(const UniValue& params, bool fHelp)
char Raddress[18]; char Raddress[18];
uint8_t pubkey33[33]; uint8_t pubkey33[33];
extern uint8_t NOTARY_PUBKEY33[];
extern std::string NOTARY_PUBKEY;
if ( NOTARY_PUBKEY33[0] == 0 ) { if ( NOTARY_PUBKEY33[0] == 0 ) {
if (strlen(params[0].get_str().c_str()) == 66) { if (strlen(params[0].get_str().c_str()) == 66) {
decode_hex(pubkey33,33,(char *)params[0].get_str().c_str()); decode_hex(pubkey33,33,(char *)params[0].get_str().c_str());
@@ -5327,6 +5323,43 @@ UniValue channelsaddress(const UniValue& params, bool fHelp)
return(result); return(result);
} }
UniValue cclibaddress(const UniValue& params, bool fHelp)
{
struct CCcontract_info *cp,C; std::vector<unsigned char> pubkey;
cp = CCinit(&C,EVAL_FIRSTUSER);
if ( fHelp || params.size() > 1 )
throw runtime_error("cclibaddress [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");
if ( params.size() == 1 )
pubkey = ParseHex(params[0].get_str().c_str());
return(CCaddress(cp,(char *)"CClib",pubkey));
}
UniValue cclibinfo(const UniValue& params, bool fHelp)
{
struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_FIRSTUSER);
if ( fHelp || params.size() > 0 )
throw runtime_error("cclibinfo\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");
return(CClib_info(cp));
}
UniValue cclib(const UniValue& params, bool fHelp)
{
struct CCcontract_info *cp,C; char *method; cJSON *jsonparams;
cp = CCinit(&C,EVAL_FIRSTUSER);
if ( fHelp || params.size() > 2 )
throw runtime_error("cclib method [JSON params]\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");
method = (char *)params[0].get_str().c_str();
jsonparams = cJSON_Parse(params[1].get_str().c_str());
return(CClib(cp,method,jsonparams));
}
UniValue oraclesaddress(const UniValue& params, bool fHelp) UniValue oraclesaddress(const UniValue& params, bool fHelp)
{ {
struct CCcontract_info *cp,C; std::vector<unsigned char> pubkey; struct CCcontract_info *cp,C; std::vector<unsigned char> pubkey;
@@ -5558,8 +5591,9 @@ UniValue marmara_receive(const UniValue& params, bool fHelp)
UniValue result(UniValue::VOBJ); uint256 batontxid; std::vector<uint8_t> senderpub; int64_t amount; int32_t matures; std::string currency; UniValue result(UniValue::VOBJ); uint256 batontxid; std::vector<uint8_t> senderpub; int64_t amount; int32_t matures; std::string currency;
if ( fHelp || (params.size() != 5 && params.size() != 4) ) if ( fHelp || (params.size() != 5 && params.size() != 4) )
{ {
// automatic flag -> lsb of matures
// 1st marmarareceive 028076d42eb20efc10007fafb5ca66a2052523c0d2221e607adf958d1a332159f6 7.5 MARMARA 1440 // 1st marmarareceive 028076d42eb20efc10007fafb5ca66a2052523c0d2221e607adf958d1a332159f6 7.5 MARMARA 1440
// after marmarareceive 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775 7.5 MARMARA 3903 bf6b4d42aa3ce974c853d73b06c78597dd3b5fb493d5d0d944f72c2017f561ad // after marmarareceive 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775 7.5 MARMARA 1168 d72d87aa0d50436de695c93e2bf3d7273c63c92ef6307913aa01a6ee6a16548b
throw runtime_error("marmarareceive senderpk amount currency matures batontxid\n"); throw runtime_error("marmarareceive senderpk amount currency matures batontxid\n");
} }
if ( ensure_CCrequirements() < 0 ) if ( ensure_CCrequirements() < 0 )
@@ -5578,7 +5612,7 @@ UniValue marmara_receive(const UniValue& params, bool fHelp)
matures = atol(params[3].get_str().c_str()); matures = atol(params[3].get_str().c_str());
batontxid = Parseuint256((char *)params[4].get_str().c_str()); batontxid = Parseuint256((char *)params[4].get_str().c_str());
} else matures = atol(params[3].get_str().c_str()) + chainActive.LastTip()->GetHeight() + 1; } else matures = atol(params[3].get_str().c_str()) + chainActive.LastTip()->GetHeight() + 1;
return(MarmaraReceive(0,pubkey2pk(senderpub),amount,currency,matures,batontxid)); return(MarmaraReceive(0,pubkey2pk(senderpub),amount,currency,matures,batontxid,true));
} }
UniValue marmara_issue(const UniValue& params, bool fHelp) UniValue marmara_issue(const UniValue& params, bool fHelp)
@@ -5586,7 +5620,9 @@ UniValue marmara_issue(const UniValue& params, bool fHelp)
UniValue result(UniValue::VOBJ); uint256 approvaltxid; std::vector<uint8_t> receiverpub; int64_t amount; int32_t matures; std::string currency; UniValue result(UniValue::VOBJ); uint256 approvaltxid; std::vector<uint8_t> receiverpub; int64_t amount; int32_t matures; std::string currency;
if ( fHelp || params.size() != 5 ) if ( fHelp || params.size() != 5 )
{ {
// marmaraissue 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775 7.5 MARMARA 3903 010ff7f9256cefe3b5dee3d72c0eeae9fc6f34884e6f32ffe5b60916df54a9be // marmaraissue 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775 7.5 MARMARA 1168 32da4cb3e886ee42de90b4a15042d71169077306badf909099c5c5c692df3f27
// marmaraissue 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775 700 MARMARA 2629 11fe8bf1de80c2ef69124d08907f259aef7f41e3a632ca2d48ad072a8c8f3078 -> 335df3a5dd6b92a3d020c9465d4d76e0d8242126106b83756dcecbad9813fdf3
throw runtime_error("marmaraissue receiverpk amount currency matures approvaltxid\n"); throw runtime_error("marmaraissue receiverpk amount currency matures approvaltxid\n");
} }
if ( ensure_CCrequirements() < 0 ) if ( ensure_CCrequirements() < 0 )
@@ -5609,7 +5645,7 @@ UniValue marmara_transfer(const UniValue& params, bool fHelp)
UniValue result(UniValue::VOBJ); uint256 approvaltxid,batontxid; std::vector<uint8_t> receiverpub; int64_t amount; int32_t matures; std::string currency; std::vector<uint256> creditloop; UniValue result(UniValue::VOBJ); uint256 approvaltxid,batontxid; std::vector<uint8_t> receiverpub; int64_t amount; int32_t matures; std::string currency; std::vector<uint256> creditloop;
if ( fHelp || params.size() != 5 ) if ( fHelp || params.size() != 5 )
{ {
// marmaratransfer 028076d42eb20efc10007fafb5ca66a2052523c0d2221e607adf958d1a332159f6 7.5 MARMARA 3903 748a4c80e6f6b725340fb0f52738f38a11c422d59b3034c8366b3d7b33c99a1e // marmaratransfer 028076d42eb20efc10007fafb5ca66a2052523c0d2221e607adf958d1a332159f6 7.5 MARMARA 1168 1506c774e4b2804a6e25260920840f4cfca8d1fb400e69fe6b74b8e593dbedc5
throw runtime_error("marmaratransfer receiverpk amount currency matures approvaltxid\n"); throw runtime_error("marmaratransfer receiverpk amount currency matures approvaltxid\n");
} }
if ( ensure_CCrequirements() < 0 ) if ( ensure_CCrequirements() < 0 )
@@ -5679,7 +5715,7 @@ UniValue marmara_settlement(const UniValue& params, bool fHelp)
if ( fHelp || params.size() != 1 ) if ( fHelp || params.size() != 1 )
{ {
// marmarasettlement 010ff7f9256cefe3b5dee3d72c0eeae9fc6f34884e6f32ffe5b60916df54a9be // marmarasettlement 010ff7f9256cefe3b5dee3d72c0eeae9fc6f34884e6f32ffe5b60916df54a9be
// marmarasettlement cc23bf81733556dc06db2fd9c9f4178cad44bdc237d6e62101cf0cdafb5195f7 // marmarasettlement ff3e259869196f3da9b5ea3f9e088a76c4fc063cf36ab586b652e121d441a603
throw runtime_error("marmarasettlement batontxid\n"); throw runtime_error("marmarasettlement batontxid\n");
} }
if ( ensure_CCrequirements() < 0 ) if ( ensure_CCrequirements() < 0 )
@@ -5689,6 +5725,20 @@ UniValue marmara_settlement(const UniValue& params, bool fHelp)
return(result); return(result);
} }
UniValue marmara_lock(const UniValue& params, bool fHelp)
{
UniValue result(UniValue::VOBJ); int64_t amount; int32_t height;
if ( fHelp || params.size() > 2 || params.size() == 0 )
{
throw runtime_error("marmaralock amount unlockht\n");
}
amount = atof(params[0].get_str().c_str()) * COIN + 0.00000000499999;
if ( params.size() == 2 )
height = atol(params[1].get_str().c_str());
else height = chainActive.LastTip()->GetHeight() + 1;
return(MarmaraLock(0,amount,height));
}
UniValue channelslist(const UniValue& params, bool fHelp) UniValue channelslist(const UniValue& params, bool fHelp)
{ {
if ( fHelp || params.size() > 0 ) if ( fHelp || params.size() > 0 )
@@ -7312,7 +7362,7 @@ UniValue heirfund(const UniValue& params, bool fHelp)
{ {
UniValue result(UniValue::VOBJ); UniValue result(UniValue::VOBJ);
uint256 tokenid = zeroid; uint256 tokenid = zeroid;
uint64_t txfee; int64_t txfee;
int64_t amount; int64_t amount;
int64_t inactivitytime; int64_t inactivitytime;
std::string hex; std::string hex;
@@ -7323,21 +7373,34 @@ UniValue heirfund(const UniValue& params, bool fHelp)
return NullUniValue; return NullUniValue;
if (fHelp || params.size() != 5 && params.size() != 6) if (fHelp || params.size() != 5 && params.size() != 6)
throw runtime_error("heirfundtokens fee funds heirname heirpubkey inactivitytime [tokenid]\n"); throw runtime_error("heirfund txfee funds heirname heirpubkey inactivitytime [tokenid]\n");
if (ensure_CCrequirements() < 0) 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"); throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
const CKeyStore& keystore = *pwalletMain; const CKeyStore& keystore = *pwalletMain;
LOCK2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet);
txfee = atoll((char*)params[0].get_str().c_str()); txfee = atoll(params[0].get_str().c_str());
amount = atoll((char*)params[1].get_str().c_str()); if (txfee < 0)
throw runtime_error("incorrect txfee param\n");
if(params.size() == 6) // tokens in satoshis:
amount = atoll(params[1].get_str().c_str());
else // coins:
amount = atof(params[1].get_str().c_str()) * COIN;
if( amount <= 0 )
throw runtime_error("incorrect amount\n");
name = params[2].get_str(); name = params[2].get_str();
pubkey = ParseHex(params[3].get_str().c_str()); pubkey = ParseHex(params[3].get_str().c_str());
if( !pubkey2pk(pubkey).IsValid() ) if( !pubkey2pk(pubkey).IsValid() )
throw runtime_error("incorrect pubkey\n"); throw runtime_error("incorrect pubkey\n");
inactivitytime = atof((char*)params[4].get_str().c_str()); inactivitytime = atoll(params[4].get_str().c_str());
if (inactivitytime <= 0)
throw runtime_error("incorrect inactivity time param\n");
if (params.size() == 6) { if (params.size() == 6) {
tokenid = Parseuint256((char*)params[5].get_str().c_str()); tokenid = Parseuint256((char*)params[5].get_str().c_str());
if(tokenid == zeroid) if(tokenid == zeroid)
@@ -7356,7 +7419,7 @@ UniValue heiradd(const UniValue& params, bool fHelp)
{ {
UniValue result; UniValue result;
uint256 fundingtxid; uint256 fundingtxid;
uint64_t txfee; int64_t txfee;
int64_t amount; int64_t amount;
int64_t inactivitytime; int64_t inactivitytime;
std::string hex; std::string hex;
@@ -7367,18 +7430,20 @@ UniValue heiradd(const UniValue& params, bool fHelp)
return NullUniValue; return NullUniValue;
if (fHelp || params.size() != 3) if (fHelp || params.size() != 3)
throw runtime_error("heiraddtokens fee funds fundingtxid\n"); throw runtime_error("heiradd txfee funds fundingtxid\n");
if (ensure_CCrequirements() < 0) 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"); throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
const CKeyStore& keystore = *pwalletMain; const CKeyStore& keystore = *pwalletMain;
LOCK2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet);
txfee = atoll((char*)params[0].get_str().c_str()); txfee = atoll(params[0].get_str().c_str());
amount = atoll((char*)params[1].get_str().c_str()); if (txfee < 0)
throw runtime_error("incorrect txfee param\n");
fundingtxid = Parseuint256((char*)params[2].get_str().c_str()); fundingtxid = Parseuint256((char*)params[2].get_str().c_str());
result = HeirAddCaller(fundingtxid, txfee, amount); result = HeirAddCaller(fundingtxid, txfee, params[1].get_str());
return result; return result;
} }
@@ -7387,7 +7452,6 @@ UniValue heirclaim(const UniValue& params, bool fHelp)
UniValue result; // result(UniValue::VOBJ); UniValue result; // result(UniValue::VOBJ);
uint256 fundingtxid; uint256 fundingtxid;
int64_t txfee; int64_t txfee;
int64_t amount;
int64_t inactivitytime; int64_t inactivitytime;
std::string hex; std::string hex;
std::vector<unsigned char> pubkey; std::vector<unsigned char> pubkey;
@@ -7398,18 +7462,20 @@ UniValue heirclaim(const UniValue& params, bool fHelp)
return NullUniValue; return NullUniValue;
if (fHelp || params.size() != 3) if (fHelp || params.size() != 3)
throw runtime_error("heirclaimtokens fee funds fundingtxid\n"); throw runtime_error("heirclaim txfee funds fundingtxid\n");
if (ensure_CCrequirements() < 0) 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"); throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
const CKeyStore& keystore = *pwalletMain; const CKeyStore& keystore = *pwalletMain;
LOCK2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet);
txfee = atoll((char*)params[0].get_str().c_str()); txfee = atoll(params[0].get_str().c_str());
amount = atoll((char*)params[1].get_str().c_str()); if (txfee < 0)
throw runtime_error("incorrect txfee param\n");
fundingtxid = Parseuint256((char*)params[2].get_str().c_str()); fundingtxid = Parseuint256((char*)params[2].get_str().c_str());
result = HeirClaimCaller(fundingtxid, txfee, amount); result = HeirClaimCaller(fundingtxid, txfee, params[1].get_str());
return result; return result;
} }
@@ -7531,3 +7597,79 @@ void RegisterWalletRPCCommands(CRPCTable &tableRPC)
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
} }
UniValue test_ac(const UniValue& params, bool fHelp)
{
// make fake token tx:
struct CCcontract_info *cp, C;
if (fHelp || (params.size() != 4))
throw runtime_error("incorrect params\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");
std::vector<unsigned char> pubkey1;
std::vector<unsigned char> pubkey2;
pubkey1 = ParseHex(params[0].get_str().c_str());
pubkey2 = ParseHex(params[1].get_str().c_str());
CPubKey pk1 = pubkey2pk(pubkey1);
CPubKey pk2 = pubkey2pk(pubkey2);
if(!pk1.IsValid() || !pk2.IsValid())
throw runtime_error("invalid pubkey\n");
int64_t txfee = 10000;
int64_t amount = atoll(params[2].get_str().c_str()) * COIN;
uint256 fundingtxid = Parseuint256((char *)params[3].get_str().c_str());
CPubKey myPubkey = pubkey2pk(Mypubkey());
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
int64_t normalInputs = AddNormalinputs(mtx, myPubkey, txfee + amount, 60);
if( normalInputs < txfee + amount)
throw runtime_error("not enough normals\n");
mtx.vout.push_back(MakeCC1of2vout(EVAL_HEIR, amount, pk1, pk2));
CScript opret;
fundingtxid = revuint256(fundingtxid);
opret << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'A' << fundingtxid << (uint8_t)0);
cp = CCinit(&C, EVAL_HEIR);
return(FinalizeCCTx(0, cp, mtx, myPubkey, txfee, opret));
}
UniValue test_heirmarker(const UniValue& params, bool fHelp)
{
// make fake token tx:
struct CCcontract_info *cp, C;
if (fHelp || (params.size() != 1))
throw runtime_error("incorrect params\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");
uint256 fundingtxid = Parseuint256((char *)params[0].get_str().c_str());
CPubKey myPubkey = pubkey2pk(Mypubkey());
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60);
if (normalInputs < 10000)
throw runtime_error("not enough normals\n");
mtx.vin.push_back(CTxIn(fundingtxid, 1));
mtx.vout.push_back(MakeCC1vout(EVAL_HEIR, 10000, myPubkey));
CScript opret;
fundingtxid = revuint256(fundingtxid);
opret << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'C' << fundingtxid << (uint8_t)0);
cp = CCinit(&C, EVAL_HEIR);
return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, opret));
}

View File

@@ -59,13 +59,7 @@ bool fSendFreeTransactions = false;
bool fPayAtLeastCustomFee = true; bool fPayAtLeastCustomFee = true;
#include "komodo_defs.h" #include "komodo_defs.h"
extern int32_t USE_EXTERNAL_PUBKEY;
extern std::string NOTARY_PUBKEY;
extern int32_t KOMODO_EXCHANGEWALLET;
extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
extern int32_t VERUS_MIN_STAKEAGE;
CBlockIndex *komodo_chainactive(int32_t height); CBlockIndex *komodo_chainactive(int32_t height);
extern std::string DONATION_PUBKEY;
/** /**
* Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) * Fees smaller than this (in satoshi) are considered zero fee (for transaction creation)

View File

@@ -42,6 +42,21 @@ PREFIX="$(pwd)/depends/$TRIPLET"
make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1
#BUILD CCLIB
WD=$PWD
cd src/cc
echo $PWD
if make "$@"; then
echo CCLIB BUILD SUCCESSFUL
else
echo CCLIB BUILD FAILED
exit 1
fi
cd $WD
./autogen.sh ./autogen.sh
CPPFLAGS="-I$PREFIX/include -arch x86_64" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ CPPFLAGS="-I$PREFIX/include -arch x86_64" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \
CXXFLAGS='-arch x86_64 -I/usr/local/Cellar/gcc\@6/6.4.0_2/include/c++/6.4.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Werror -g -Wl,-undefined -Wl,dynamic_lookup' \ CXXFLAGS='-arch x86_64 -I/usr/local/Cellar/gcc\@6/6.4.0_2/include/c++/6.4.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Werror -g -Wl,-undefined -Wl,dynamic_lookup' \

View File

@@ -101,6 +101,21 @@ eval "$MAKE" --version
as --version as --version
ld -v ld -v
#BUILD CCLIB
WD=$PWD
cd src/cc
echo $PWD
if make "$@"; then
echo CCLIB BUILD SUCCESSFUL
else
echo CCLIB BUILD FAILED
exit 1
fi
cd $WD
HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ V=1 HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ V=1
./autogen.sh ./autogen.sh