Merge pull request #124 from jl777/jl777

sync cclib_dyn->jl777:jl777
This commit is contained in:
ca333
2019-01-26 13:11:17 +01:00
committed by GitHub
45 changed files with 3061 additions and 1781 deletions

View File

@@ -13,12 +13,14 @@ 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'
'cryptoconditions_heir.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

@@ -0,0 +1,121 @@
#!/usr/bin/env python2
# Copyright (c) 2018 SuperNET developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
import time
from test_framework.test_framework import CryptoconditionsTestFramework
from test_framework.authproxy import JSONRPCException
from test_framework.util import assert_equal, assert_greater_than, \
initialize_chain_clean, initialize_chain, start_nodes, start_node, connect_nodes_bi, \
stop_nodes, sync_blocks, sync_mempools, wait_bitcoinds, rpc_port, assert_raises
from cryptoconditions import assert_success, assert_error, generate_random_string
class CryptoconditionsHeirTest(CryptoconditionsTestFramework):
def run_heir_tests(self):
rpc = self.nodes[0]
rpc1 = self.nodes[1]
result = rpc.heiraddress()
assert_success(result)
# verify all keys look like valid AC addrs, could be better
for x in ['myCCaddress', 'HeirCCaddress', 'Heirmarker', 'myaddress']:
assert_equal(result[x][0], 'R')
result = rpc.heiraddress(self.pubkey)
assert_success(result)
# test that additional CCaddress key is returned
for x in ['myCCaddress', 'HeirCCaddress', 'Heirmarker', 'myaddress', 'CCaddress']:
assert_equal(result[x][0], 'R')
# getting empty heir list
result = rpc.heirlist()
assert_equal(len(result), 1)
assert_success(result)
# valid heirfund case with coins
result = rpc.heirfund("0", "1000", "UNITHEIR", self.pubkey1, "10")
assert_success(result)
heir_fund_txid = self.send_and_mine(result["hextx"], rpc)
assert heir_fund_txid, "got heir funding txid"
# heir fund txid should be in heirlist now
result = rpc.heirlist()
assert_equal(len(result), 2)
assert_success(result)
assert_equal(result["fundingtxid"], heir_fund_txid)
# checking heirinfo
result = rpc.heirinfo(heir_fund_txid)
assert_success(result)
assert_equal(result["fundingtxid"], heir_fund_txid)
assert_equal(result["name"], "UNITHEIR")
assert_equal(result["owner"], self.pubkey)
assert_equal(result["heir"], self.pubkey1)
assert_equal(result["funding total in coins"], "1000.00000000")
assert_equal(result["funding available in coins"], "1000.00000000")
assert_equal(result["inactivity time setting, sec"], "10")
assert_equal(result["spending allowed for the heir"], "false")
# TODO: heirlist keys are duplicating now
# waiting for 11 seconds to be sure that needed time passed for heir claiming
time.sleep(11)
rpc.generate(1)
self.sync_all()
result = rpc.heirinfo(heir_fund_txid)
assert_equal(result["funding available in coins"], "1000.00000000")
assert_equal(result["spending allowed for the heir"], "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()
second_node_balance = rpc1.getbalance()
assert_greater_than(second_node_balance, 0.1)
# let's claim whole heir sum from second node
result = rpc1.heirclaim("0", "1000", heir_fund_txid)
assert_success(result)
heir_claim_txid = self.send_and_mine(result["hextx"], rpc1)
assert heir_claim_txid, "got claim txid"
# balance of second node after heirclaim should increase for 1000 coins - txfees
# + get one block reward when broadcasted heir_claim_txid
result = round(rpc1.getbalance()) - round(second_node_balance)
assert_greater_than(result, 100999)
self.sync_all()
# no more funds should be available for claiming
result = rpc.heirinfo(heir_fund_txid)
assert_equal(result["funding available in coins"], "0.00000000")
# TODO: valid heirfund case with tokens
def run_test(self):
print("Mining blocks...")
rpc = self.nodes[0]
rpc1 = self.nodes[1]
# utxos from block 1 become mature in block 101
if not self.options.noshutdown:
rpc.generate(101)
self.sync_all()
rpc.getinfo()
rpc1.getinfo()
# this corresponds to -pubkey above
print("Importing privkeys")
rpc.importprivkey(self.privkey)
rpc1.importprivkey(self.privkey1)
self.run_heir_tests()
if __name__ == '__main__':
CryptoconditionsHeirTest().main()

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

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

@@ -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,11 +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,ASSETCHAINS_CCLIB;
extern uint8_t ASSETCHAINS_CCDISABLES[256];
#define CC_MAXVINS 1024 #define CC_MAXVINS 1024
@@ -69,6 +64,7 @@ extern uint8_t ASSETCHAINS_CCDISABLES[256];
typedef union _bits256 bits256; typedef union _bits256 bits256;
#endif #endif
#include "../komodo_cJSON.h"
struct CC_utxo struct CC_utxo
{ {
@@ -134,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);
@@ -200,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);

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

@@ -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)
@@ -602,7 +573,6 @@ bool komodo_txnotarizedconfirmed(uint256 txid)
CPubKey check_signing_pubkey(CScript scriptSig) CPubKey check_signing_pubkey(CScript scriptSig)
{ {
bool found = false; bool found = false;
CPubKey pubkey; CPubKey pubkey;
@@ -630,3 +600,79 @@ CPubKey check_signing_pubkey(CScript scriptSig)
} }
return CPubKey(); 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");
}

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

View File

@@ -27,32 +27,291 @@
#include "core_io.h" #include "core_io.h"
#include "crosschain.h" #include "crosschain.h"
#define MYCCLIBNAME ((char *)"stub") #define FAUCET2SIZE COIN
char *CClib_name() { return(MYCCLIBNAME); } struct CClib_rpcinfo
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; char *method,*help;
if ( ASSETCHAINS_CCLIB != MYCCLIBNAME ) int32_t numrequiredargs,maxargs; // frontloaded with required
{ uint8_t funcid;
fprintf(stderr,"-ac_cclib=%s vs myname %s\n",ASSETCHAINS_CCLIB.c_str(),MYCCLIBNAME); }
return eval->Invalid("-ac_cclib name mismatches myname"); CClib_methods[] =
} {
height = KOMODO_CONNECTING; { (char *)"faucet2_fund", (char *)"amount", 1, 1, 'F' },
if ( KOMODO_CONNECTING < 0 ) // always comes back with > 0 for final confirmation { (char *)"faucet2_get", (char *)"<no args>", 0, 0, 'G' },
return(true); };
if ( ASSETCHAINS_CC == 0 || (height & ~(1<<30)) < KOMODO_CCACTIVATE )
return eval->Invalid("CC are disabled or not active yet"); std::string MYCCLIBNAME = (char *)"faucet2";
if ( (KOMODO_CONNECTING & (1<<30)) != 0 )
{ char *CClib_name() { return((char *)MYCCLIBNAME.c_str()); }
from_mempool = 1;
height &= ((1<<30) - 1); std::string CClib_rawtxgen(struct CCcontract_info *cp,uint8_t funcid,cJSON *params);
}
evalcode = cond->code[0]; UniValue CClib_info(struct CCcontract_info *cp)
if ( evalcode >= EVAL_FIRSTUSER && evalcode <= EVAL_LASTUSER ) {
{ UniValue result(UniValue::VOBJ),a(UniValue::VARR); int32_t i; char str[2];
return(true); result.push_back(Pair("result","success"));
} result.push_back(Pair("CClib",CClib_name()));
return eval->Invalid("cclib CC must have evalcode between 16 and 127"); 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

@@ -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,25 +522,29 @@ 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");
return (""); fprintf(stderr,"%s\n",CCerror.c_str());
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)
@@ -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

@@ -20,18 +20,18 @@
#include "cJSON.c" #include "cJSON.c"
/* /*
z_migrate: the purpose of z_migrate is to make converting of all sprout outputs into sapling. the usage would be for the user to specify a sapling address and call z_migrate zsaddr, until it returns that there is nothing left to be done. z_migrate: the purpose of z_migrate is to make converting of all sprout outputs into sapling. the usage would be for the user to specify a sapling address and call z_migrate zsaddr, until it returns that there is nothing left to be done.
its main functionality is quite similar to a z_mergetoaddress ANY_ZADDR -> onetime_taddr followed by a z_sendmany onetime_taddr -> zsaddr its main functionality is quite similar to a z_mergetoaddress ANY_ZADDR -> onetime_taddr followed by a z_sendmany onetime_taddr -> zsaddr
since the z_mergetoaddress will take time, it would just queue up an async operation. When it starts, it should see if there are any onetime_taddr with 10000.0001 funds in it, that is a signal for it to do the sapling tx and it can just do that without async as it is fast enough, especially with a taddr input. Maybe it limits itself to one, or it does all possible taddr -> sapling as fast as it can. either is fine as it will be called over and over anyway. since the z_mergetoaddress will take time, it would just queue up an async operation. When it starts, it should see if there are any onetime_taddr with 10000.0001 funds in it, that is a signal for it to do the sapling tx and it can just do that without async as it is fast enough, especially with a taddr input. Maybe it limits itself to one, or it does all possible taddr -> sapling as fast as it can. either is fine as it will be called over and over anyway.
It might be that there is nothing to do, but some operations are pending. in that case it would return such a status. as soon as the operation finishes, there would be more work to do. It might be that there is nothing to do, but some operations are pending. in that case it would return such a status. as soon as the operation finishes, there would be more work to do.
the amount sent to the taddr, should be 10000.0001 the amount sent to the taddr, should be 10000.0001
The GUI or user would be expected to generate a sapling address and then call z_migrate saplingaddr in a loop, until it returns that it is all done. this loop should pause for 10 seconds or so, if z_migrate is just waiting for opid to complete. The GUI or user would be expected to generate a sapling address and then call z_migrate saplingaddr in a loop, until it returns that it is all done. this loop should pause for 10 seconds or so, if z_migrate is just waiting for opid to complete.
*/ */
bits256 zeroid; bits256 zeroid;
@@ -649,21 +649,21 @@ int64_t z_getbalance(char *refcoin,char *acname,char *coinaddr)
int32_t z_exportkey(char *privkey,char *refcoin,char *acname,char *zaddr) int32_t z_exportkey(char *privkey,char *refcoin,char *acname,char *zaddr)
{ {
cJSON *retjson; char *retstr,cmpstr[64]; int64_t amount=0; int32_t retval = -1; cJSON *retjson; char *retstr,cmpstr[64]; int64_t amount=0;
privkey[0] = 0; privkey[0] = 0;
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"z_exportkey",zaddr,"","","")) != 0 ) if ( (retjson= get_komodocli(refcoin,&retstr,acname,"z_exportkey",zaddr,"","","")) != 0 )
{ {
fprintf(stderr,"z_exportkey.(%s) %s returned json!\n",refcoin,acname); fprintf(stderr,"z_exportkey.(%s) %s returned json!\n",refcoin,acname);
free_json(retjson); free_json(retjson);
return(-1);
} }
else if ( retstr != 0 ) else if ( retstr != 0 )
{ {
//printf("retstr %s -> %.8f\n",retstr,dstr(amount)); //printf("retstr %s -> %.8f\n",retstr,dstr(amount));
strcpy(privkey,retstr); strcpy(privkey,retstr);
free(retstr); free(retstr);
retval = 0; return(0);
} }
return(retval);
} }
int32_t getnewaddress(char *coinaddr,char *refcoin,char *acname) int32_t getnewaddress(char *coinaddr,char *refcoin,char *acname)
@@ -700,6 +700,23 @@ int32_t z_getnewaddress(char *coinaddr,char *refcoin,char *acname,char *typestr)
return(retval); return(retval);
} }
int32_t z_getnewaddress(char *coinaddr,char *refcoin,char *acname,char *typestr)
{
cJSON *retjson; char *retstr; int64_t amount=0;
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"z_getnewaddress",typestr,"","","")) != 0 )
{
fprintf(stderr,"z_getnewaddress.(%s) %s returned json!\n",refcoin,acname);
free_json(retjson);
return(-1);
}
else if ( retstr != 0 )
{
strcpy(coinaddr,retstr);
free(retstr);
return(0);
}
}
int64_t find_onetime_amount(char *coinstr,char *coinaddr) int64_t find_onetime_amount(char *coinstr,char *coinaddr)
{ {
cJSON *array,*item; int32_t i,n; char *addr; int64_t amount = 0; cJSON *array,*item; int32_t i,n; char *addr; int64_t amount = 0;
@@ -824,6 +841,39 @@ int32_t z_mergetoaddress(char *opidstr,char *coinstr,char *acname,char *destaddr
return(retval); return(retval);
} }
int32_t z_mergetoaddress(char *opidstr,char *coinstr,char *acname,char *destaddr)
{
cJSON *retjson; char *retstr,addr[128],*opstr; int32_t retval = -1;
sprintf(addr,"[\\\"ANY_SPROUT\\\"]");
//printf("z_sendmany from.(%s) -> %s\n",addr,destaddr);
if ( (retjson= get_komodocli(coinstr,&retstr,acname,"z_mergetoaddress",addr,destaddr,"","")) != 0 )
{
/*{
"remainingUTXOs": 0,
"remainingTransparentValue": 0.00000000,
"remainingNotes": 222,
"remainingShieldedValue": 5413.39093055,
"mergingUTXOs": 0,
"mergingTransparentValue": 0.00000000,
"mergingNotes": 10,
"mergingShieldedValue": 822.47447172,
"opid": "opid-f28f6261-4120-436c-aca5-859870a40a70"
}*/
if ( (opstr= jstr(retjson,"opid")) != 0 )
strcpy(opidstr,opstr);
retval = jint(retjson,"remainingNotes");
fprintf(stderr,"%s\n",jprint(retjson,0));
free_json(retjson);
}
else if ( retstr != 0 )
{
fprintf(stderr,"z_mergetoaddress.(%s) -> opid.(%s)\n",coinstr,retstr);
strcpy(opidstr,retstr);
free(retstr);
}
return(retval);
}
int32_t empty_mempool(char *coinstr,char *acname) int32_t empty_mempool(char *coinstr,char *acname)
{ {
cJSON *array; int32_t n; cJSON *array; int32_t n;

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;
@@ -28,7 +29,7 @@ class TokenHelper;
"The design requires the heir to spend all the funds at once" (this requirement was changed to "after the inactivity time both the heir and owner may freely spend available funds") "The design requires the heir to spend all the funds at once" (this requirement was changed to "after the inactivity time both the heir and owner may freely spend available funds")
After the first heir spending a flag is set that spending is allowed for the heir whether the owner adds more funds or spends them. After the first heir spending a flag is set that spending is allowed for the heir whether the owner adds more funds or spends them.
This Heir contract supports both coins and tokens. This Heir contract supports both coins and tokens.
*/ */
// tx validation code // tx validation code
@@ -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
@@ -234,9 +236,9 @@ bool HeirValidate(struct CCcontract_info* cpHeir, Eval* eval, const CTransaction
// helper functions used in implementations of rpc calls (in rpcwallet.cpp) or validation code // helper functions used in implementations of rpc calls (in rpcwallet.cpp) or validation code
/** /**
* Checks if vout is to cryptocondition address * Checks if vout is to cryptocondition address
* @return vout value in satoshis * @return vout value in satoshis
*/ */
template <class Helper> int64_t IsHeirFundingVout(struct CCcontract_info* cp, const CTransaction& tx, int32_t voutIndex, CPubKey ownerPubkey, CPubKey heirPubkey) template <class Helper> int64_t IsHeirFundingVout(struct CCcontract_info* cp, const CTransaction& tx, int32_t voutIndex, CPubKey ownerPubkey, CPubKey heirPubkey)
{ {
char destaddr[65], heirFundingAddr[65]; char destaddr[65], heirFundingAddr[65];
@@ -321,9 +323,9 @@ uint8_t _DecodeHeirOpRet(std::vector<uint8_t> vopret, CPubKey& ownerPubkey, CPub
} }
/* not used, see DecodeHeirOpRet(vopret,...) /* not used, see DecodeHeirOpRet(vopret,...)
// overload for 'F' opret // overload for 'F' opret
uint8_t DecodeHeirOpRet(CScript scriptPubKey, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, bool noLogging) uint8_t DecodeHeirOpRet(CScript scriptPubKey, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, bool noLogging)
{ {
uint256 dummytxid; uint256 dummytxid;
uint8_t dummyHasHeirSpendingBegun; uint8_t dummyHasHeirSpendingBegun;
std::vector<uint8_t> vopret; std::vector<uint8_t> vopret;
@@ -334,13 +336,13 @@ uint8_t DecodeHeirOpRet(CScript scriptPubKey, CPubKey& ownerPubkey, CPubKey& hei
return (uint8_t)0; return (uint8_t)0;
} }
return _DecodeHeirOpRet(vopret, ownerPubkey, heirPubkey, inactivityTime, heirName, dummytxid, dummyHasHeirSpendingBegun, noLogging); return _DecodeHeirOpRet(vopret, ownerPubkey, heirPubkey, inactivityTime, heirName, dummytxid, dummyHasHeirSpendingBegun, noLogging);
}*/ }*/
/* not used, see DecodeHeirOpRet(vopret,...) /* not used, see DecodeHeirOpRet(vopret,...)
// overload for A, C oprets and AddHeirContractInputs // overload for A, C oprets and AddHeirContractInputs
uint8_t DecodeHeirOpRet(CScript scriptPubKey, uint256& fundingtxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging) uint8_t DecodeHeirOpRet(CScript scriptPubKey, uint256& fundingtxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging)
{ {
CPubKey dummyOwnerPubkey, dummyHeirPubkey; CPubKey dummyOwnerPubkey, dummyHeirPubkey;
int64_t dummyInactivityTime; int64_t dummyInactivityTime;
std::string dummyHeirName; std::string dummyHeirName;
@@ -353,7 +355,7 @@ uint8_t DecodeHeirOpRet(CScript scriptPubKey, uint256& fundingtxidInOpret, uint8
} }
return _DecodeHeirOpRet(vopret, dummyOwnerPubkey, dummyHeirPubkey, dummyInactivityTime, dummyHeirName, fundingtxidInOpret, hasHeirSpendingBegun, noLogging); return _DecodeHeirOpRet(vopret, dummyOwnerPubkey, dummyHeirPubkey, dummyInactivityTime, dummyHeirName, fundingtxidInOpret, hasHeirSpendingBegun, noLogging);
} */ } */
// decode combined opret: // decode combined opret:
uint8_t _DecodeHeirEitherOpRet(CScript scriptPubKey, uint256 &tokenid, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, uint256& fundingTxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging) uint8_t _DecodeHeirEitherOpRet(CScript scriptPubKey, uint256 &tokenid, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, uint256& fundingTxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging)
@@ -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

@@ -43,7 +43,7 @@ public:
static CTxOut makeUserVout(int64_t amount, CPubKey myPubkey) { static CTxOut makeUserVout(int64_t amount, CPubKey myPubkey) {
return CTxOut(amount, CScript() << ParseHex(HexStr(myPubkey)) << OP_CHECKSIG); return CTxOut(amount, CScript() << ParseHex(HexStr(myPubkey)) << OP_CHECKSIG);
} }
/* static CTxOut makeClaimerVout(int64_t amount, CPubKey myPubkey) { /* static CTxOut makeClaimerVout(int64_t amount, CPubKey myPubkey) {
return CTxOut(amount, CScript() << ParseHex(HexStr(myPubkey)) << OP_CHECKSIG); return CTxOut(amount, CScript() << ParseHex(HexStr(myPubkey)) << OP_CHECKSIG);
} */ } */
static bool GetCoinsOrTokensCCaddress1of2(char *coinaddr, CPubKey ownerPubkey, CPubKey heirPubkey) { static bool GetCoinsOrTokensCCaddress1of2(char *coinaddr, CPubKey ownerPubkey, CPubKey heirPubkey) {
@@ -85,7 +85,7 @@ public:
static CTxOut makeUserVout(int64_t amount, CPubKey myPubkey) { static CTxOut makeUserVout(int64_t amount, CPubKey myPubkey) {
return MakeCC1vout(EVAL_TOKENS, amount, myPubkey); // yes EVAL_TOKENS return MakeCC1vout(EVAL_TOKENS, amount, myPubkey); // yes EVAL_TOKENS
} }
/* static CTxOut makeClaimerVout(int64_t amount, CPubKey myPubkey) { /* static CTxOut makeClaimerVout(int64_t amount, CPubKey myPubkey) {
return MakeCC1vout(EVAL_TOKENS, amount, myPubkey); // yes EVAL_TOKENS return MakeCC1vout(EVAL_TOKENS, amount, myPubkey); // yes EVAL_TOKENS
} */ } */
static bool GetCoinsOrTokensCCaddress1of2(char *coinaddr, CPubKey ownerPubkey, CPubKey heirPubkey) { static bool GetCoinsOrTokensCCaddress1of2(char *coinaddr, CPubKey ownerPubkey, CPubKey heirPubkey) {
@@ -102,20 +102,20 @@ public:
/** /**
* Small framework for vins and vouts validation implementing a variation of 'chain of responsibility' pattern: * Small framework for vins and vouts validation implementing a variation of 'chain of responsibility' pattern:
* It consists of two classes CInputValidationPlan and COutputValidationPlan which both are configured with an array of vectors of validators * It consists of two classes CInputValidationPlan and COutputValidationPlan which both are configured with an array of vectors of validators
* (These validators are derived from the class CValidatorBase). * (These validators are derived from the class CValidatorBase).
* *
* A example of a validator may verify for a vout if its public key corresponds to the public key which is stored in opreturn. * A example of a validator may verify for a vout if its public key corresponds to the public key which is stored in opreturn.
* Or, vin validator may check if this vin depicts correctly to the CC contract's address. * Or, vin validator may check if this vin depicts correctly to the CC contract's address.
* *
* For validating vins CInputValidator additionally is provided with an instance of a class derived from the CInputIdentifierBase class. * For validating vins CInputValidator additionally is provided with an instance of a class derived from the CInputIdentifierBase class.
* this identifier class allows to select identical vins (for example, normal vins or cc input vins) and apply validators from the corresponding vector to it. * this identifier class allows to select identical vins (for example, normal vins or cc input vins) and apply validators from the corresponding vector to it.
* Note: CInputValidator treats that at least one identified vin should be present, otherwise it returns eval->invalid() and false. * Note: CInputValidator treats that at least one identified vin should be present, otherwise it returns eval->invalid() and false.
* *
* For validating vouts COutputValidator is configured for each vector of validators with the vout index to which these validators are applied * For validating vouts COutputValidator is configured for each vector of validators with the vout index to which these validators are applied
* (see constructors of both CInputValidator and COutputValidator) * (see constructors of both CInputValidator and COutputValidator)
*/ */
/** /**
* base class for all validators * base class for all validators
@@ -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;
@@ -146,10 +146,10 @@ protected:
}; };
/** /**
* Encapsulates an array containing rows of validators * Encapsulates an array containing rows of validators
* Each row is a vector of validators (zero is possible) for validating vins or prev tx's vouts * Each row is a vector of validators (zero is possible) for validating vins or prev tx's vouts
* this validation plan is used for validating tx inputs * this validation plan is used for validating tx inputs
*/ */
template <typename TValidatorBase> template <typename TValidatorBase>
class CInputValidationPlan class CInputValidationPlan
{ {
@@ -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;
} }
@@ -278,10 +278,10 @@ private:
/** /**
* Encapsulates an array containing rows of validators * Encapsulates an array containing rows of validators
* Each row is a vector of validators (zero is possible) for validating vouts * Each row is a vector of validators (zero is possible) for validating vouts
* this validation plan is used for validating tx outputs * this validation plan is used for validating tx outputs
*/ */
template <typename TValidatorBase> template <typename TValidatorBase>
class COutputValidationPlan class COutputValidationPlan
{ {
@@ -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;
} }
@@ -393,8 +393,8 @@ public:
/** /**
* Validates 1of2address for vout (may be used for either this or prev tx) * Validates 1of2address for vout (may be used for either this or prev tx)
*/ */
template <class Helper> class CCC1of2AddressValidator : CValidatorBase template <class Helper> class CCC1of2AddressValidator : CValidatorBase
{ {
public: public:
@@ -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;
@@ -447,8 +447,8 @@ private:
/** /**
* Validates if this is vout to owner or heir from opret (funding or change) * Validates if this is vout to owner or heir from opret (funding or change)
*/ */
template <class Helper> class CMyPubkeyVoutValidator : CValidatorBase template <class Helper> class CMyPubkeyVoutValidator : CValidatorBase
{ {
public: public:
@@ -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;
@@ -507,8 +507,8 @@ private:
}; };
/** /**
* Check if the user is the heir and the heir is allowed to spend (duration > inactivityTime) * Check if the user is the heir and the heir is allowed to spend (duration > inactivityTime)
*/ */
template <class Helper> class CHeirSpendValidator : CValidatorBase template <class Helper> class CHeirSpendValidator : CValidatorBase
{ {
public: public:
@@ -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;
@@ -563,8 +563,8 @@ private:
}; };
/** /**
* Validates this opreturn and compares it with the opreturn from the previous tx * Validates this opreturn and compares it with the opreturn from the previous tx
*/ */
template <class Helper> class COpRetValidator : CValidatorBase template <class Helper> class COpRetValidator : CValidatorBase
{ {
public: public:
@@ -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,15 +607,51 @@ 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;
}; };
/** /**
* empty validator always returns true * 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
*/
template <class Helper> class CNullValidator : CValidatorBase template <class Helper> class CNullValidator : CValidatorBase
{ {
public: public:
@@ -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; }
}; };

View File

@@ -94,7 +94,7 @@ uint8_t DecodeMaramaraCoinbaseOpRet(const CScript scriptPubKey,CPubKey &pk,int32
{ {
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 or 'L' %d\n",script[1],'C','P','L'); } //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);
} }
@@ -255,6 +255,22 @@ int32_t MarmaraValidateCoinbase(int32_t height,CTransaction tx)
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;
@@ -318,6 +334,10 @@ bool MarmaraValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t
{ {
return(true); return(true);
} }
else if ( funcid == 'C' ) // coinbase
{
return(true);
}
// staking only for locked utxo // staking only for locked utxo
} }
return eval->Invalid("fall through error"); return eval->Invalid("fall through error");
@@ -476,7 +496,7 @@ UniValue MarmaraLock(uint64_t txfee,int64_t amount,int32_t height)
else else
{ {
result.push_back(Pair("result",(char *)"success")); result.push_back(Pair("result",(char *)"success"));
result.push_back(Pair("rawtx",rawtx)); result.push_back(Pair("hex",rawtx));
return(result); return(result);
} }
} else errorstr = (char *)"insufficient funds"; } else errorstr = (char *)"insufficient funds";
@@ -485,7 +505,34 @@ UniValue MarmaraLock(uint64_t txfee,int64_t amount,int32_t height)
return(result); return(result);
} }
// jl777: decide on what unlockht settlement change should have 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) UniValue MarmaraSettlement(uint64_t txfee,uint256 refbatontxid)
{ {
@@ -553,7 +600,7 @@ UniValue MarmaraSettlement(uint64_t txfee,uint256 refbatontxid)
mtx.vout.push_back(MakeCC1of2vout(EVAL_MARMARA,change,Marmarapk,pk)); 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); 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("result",(char *)"success"));
result.push_back(Pair("rawtx",rawtx)); result.push_back(Pair("hex",rawtx));
return(result); return(result);
} else remaining -= inputsum; } else remaining -= inputsum;
if ( mtx.vin.size() >= CC_MAXVINS - MARMARA_VINS ) if ( mtx.vin.size() >= CC_MAXVINS - MARMARA_VINS )
@@ -569,7 +616,7 @@ UniValue MarmaraSettlement(uint64_t txfee,uint256 refbatontxid)
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraLoopOpret('D',createtxid,mypk,-remaining,refmatures,currency),pubkeys); 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("result",(char *)"error"));
result.push_back(Pair("error",(char *)"insufficient funds")); result.push_back(Pair("error",(char *)"insufficient funds"));
result.push_back(Pair("rawtx",rawtx)); result.push_back(Pair("hex",rawtx));
result.push_back(Pair("remaining",ValueFromAmount(remaining))); result.push_back(Pair("remaining",ValueFromAmount(remaining)));
} }
else else
@@ -684,7 +731,7 @@ UniValue MarmaraReceive(uint64_t txfee,CPubKey senderpk,int64_t amount,std::stri
else else
{ {
result.push_back(Pair("result",(char *)"success")); result.push_back(Pair("result",(char *)"success"));
result.push_back(Pair("rawtx",rawtx)); result.push_back(Pair("hex",rawtx));
result.push_back(Pair("funcid","R")); result.push_back(Pair("funcid","R"));
result.push_back(Pair("createtxid",createtxid.GetHex())); result.push_back(Pair("createtxid",createtxid.GetHex()));
if ( batontxid != zeroid ) if ( batontxid != zeroid )
@@ -740,7 +787,7 @@ UniValue MarmaraIssue(uint64_t txfee,uint8_t funcid,CPubKey receiverpk,int64_t a
else else
{ {
result.push_back(Pair("result",(char *)"success")); result.push_back(Pair("result",(char *)"success"));
result.push_back(Pair("rawtx",rawtx)); result.push_back(Pair("hex",rawtx));
char str[2]; str[0] = funcid, str[1] = 0; char str[2]; str[0] = funcid, str[1] = 0;
result.push_back(Pair("funcid",str)); result.push_back(Pair("funcid",str));
result.push_back(Pair("createtxid",createtxid.GetHex())); result.push_back(Pair("createtxid",createtxid.GetHex()));
@@ -978,7 +1025,7 @@ UniValue MarmaraPoolPayout(uint64_t txfee,int32_t firstheight,double perc,char *
else else
{ {
result.push_back(Pair("result",(char *)"success")); result.push_back(Pair("result",(char *)"success"));
result.push_back(Pair("rawtx",rawtx)); result.push_back(Pair("hex",rawtx));
if ( totalpayout > 0 && total > totalpayout-txfee ) if ( totalpayout > 0 && total > totalpayout-txfee )
{ {
result.push_back(Pair("firstheight",firstheight)); result.push_back(Pair("firstheight",firstheight));

View File

@@ -115,6 +115,7 @@ enum BlockStatus: uint32_t {
BLOCK_FAILED_MASK = BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD, BLOCK_FAILED_MASK = BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD,
BLOCK_ACTIVATES_UPGRADE = 128, //! block activates a network upgrade BLOCK_ACTIVATES_UPGRADE = 128, //! block activates a network upgrade
BLOCK_IN_TMPFILE = 256
}; };
//! Short-hand for the highest consensus validity we implement. //! Short-hand for the highest consensus validity we implement.
@@ -350,7 +351,7 @@ public:
nSolution = block.nSolution; nSolution = block.nSolution;
} }
int32_t SetHeight(int32_t height) void SetHeight(int32_t height)
{ {
this->chainPower.nHeight = height; this->chainPower.nHeight = height;
} }

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"));
@@ -230,11 +225,32 @@ void CChainParams::SetCheckpointData(CChainParams::CCheckpointData checkpointDat
CChainParams::checkpointData = checkpointData; CChainParams::checkpointData = checkpointData;
} }
int32_t MAX_BLOCK_SIZE(int32_t height) // make sure to change MAX_PROTOCOL_MESSAGE_LENGTH also!!!! /*
To change the max block size, all that needs to be updated is the #define _MAX_BLOCK_SIZE in utils.h
However, doing that without any other changes will allow forking non-updated nodes by creating a larger block. So, make sure to height activate the new blocksize properly.
Assuming it is 8MB, then:
#define _OLD_MAX_BLOCK_SIZE (4096 * 1024)
#define _MAX_BLOCK_SIZE (2 * 4096 * 1024)
change the body of if:
{
if ( height < saplinght+1000000 ) // activates 8MB blocks 1 million blocks after saplinght
return(_OLD_MAX_BLOCK_SIZE);
else return(_MAX_BLOCK_SIZE);
}
*/
int32_t MAX_BLOCK_SIZE(int32_t height)
{ {
int32_t saplinght = mainParams.consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight;
//fprintf(stderr,"MAX_BLOCK_SIZE %d vs. %d\n",height,mainParams.consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight); //fprintf(stderr,"MAX_BLOCK_SIZE %d vs. %d\n",height,mainParams.consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight);
if ( height <= 0 || (mainParams.consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight > 0 && height >= mainParams.consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight) ) if ( height <= 0 || (saplinght > 0 && height >= saplinght) )
return(4096 * 1024); {
return(_MAX_BLOCK_SIZE);
}
else return(2000000); else return(2000000);
} }

View File

@@ -130,8 +130,8 @@ struct Params {
int64_t AveragingWindowTimespan() const { return nPowAveragingWindow * nPowTargetSpacing; } int64_t AveragingWindowTimespan() const { return nPowAveragingWindow * nPowTargetSpacing; }
int64_t MinActualTimespan() const { return (AveragingWindowTimespan() * (100 - nPowMaxAdjustUp )) / 100; } int64_t MinActualTimespan() const { return (AveragingWindowTimespan() * (100 - nPowMaxAdjustUp )) / 100; }
int64_t MaxActualTimespan() const { return (AveragingWindowTimespan() * (100 + nPowMaxAdjustDown)) / 100; } int64_t MaxActualTimespan() const { return (AveragingWindowTimespan() * (100 + nPowMaxAdjustDown)) / 100; }
int32_t SetSaplingHeight(int32_t height) { vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = height; } void SetSaplingHeight(int32_t height) { vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = height; }
int32_t SetOverwinterHeight(int32_t height) { vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = height; } void SetOverwinterHeight(int32_t height) { vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = height; }
uint256 nMinimumChainWork; uint256 nMinimumChainWork;
}; };
} // namespace Consensus } // namespace Consensus

View File

@@ -86,6 +86,7 @@ class CVerusHashV2
result = buf2; result = buf2;
curPos = 0; curPos = 0;
std::fill(buf1, buf1 + sizeof(buf1), 0); std::fill(buf1, buf1 + sizeof(buf1), 0);
return *this;
} }
int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); } int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); }

View File

@@ -707,6 +707,10 @@ int32_t komodo_voutupdate(int32_t *isratificationp,int32_t notaryid,uint8_t *scr
komodo_stateupdate(height,0,0,0,zero,0,0,0,0,0,0,0,0,0,0,sp->MoM,sp->MoMdepth); komodo_stateupdate(height,0,0,0,zero,0,0,0,0,0,0,0,0,0,0,sp->MoM,sp->MoMdepth);
if ( ASSETCHAINS_SYMBOL[0] != 0 ) if ( ASSETCHAINS_SYMBOL[0] != 0 )
printf("[%s] ht.%d NOTARIZED.%d %s.%s %sTXID.%s lens.(%d %d) MoM.%s %d\n",ASSETCHAINS_SYMBOL,height,*notarizedheightp,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),ASSETCHAINS_SYMBOL[0]==0?"BTC":"KMD",desttxid.ToString().c_str(),opretlen,len,sp->MoM.ToString().c_str(),sp->MoMdepth); printf("[%s] ht.%d NOTARIZED.%d %s.%s %sTXID.%s lens.(%d %d) MoM.%s %d\n",ASSETCHAINS_SYMBOL,height,*notarizedheightp,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),ASSETCHAINS_SYMBOL[0]==0?"BTC":"KMD",desttxid.ToString().c_str(),opretlen,len,sp->MoM.ToString().c_str(),sp->MoMdepth);
if (RemoveOrphanedBlocks(*notarizedheightp))
{
//fprintf(stderr, "Sucessfully removed all known orphaned blocks before height %d\n",*notarizedheightp);
}
if ( ASSETCHAINS_SYMBOL[0] == 0 ) if ( ASSETCHAINS_SYMBOL[0] == 0 )
{ {
if ( signedfp == 0 ) if ( signedfp == 0 )
@@ -947,6 +951,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));
@@ -956,6 +962,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,27 +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;
if ( ASSETCHAINS_MARMARA != 0 ) txtime = komodo_txtime(opret,&value,txid,vout,destaddr);
{
// need to verify it was signed by the non-Marmarapk of the 1of2
}
txtime = komodo_txtime(&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
}
}
} }
} }
} }
@@ -1194,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 )
@@ -1206,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());
@@ -1448,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 )
@@ -1463,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 *)"");
} }
@@ -1499,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 )
@@ -1812,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 )
@@ -2068,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;
@@ -2098,7 +2120,9 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
{ {
CBlockIndex* pblockindex = chainActive[tipindex->GetHeight()]; CBlockIndex* pblockindex = chainActive[tipindex->GetHeight()];
CBlock block; CTxDestination addressout; CBlock block; CTxDestination addressout;
if( ReadBlockFromDisk(block, pblockindex, 1) && komodo_WhoStaked(&block, addressout) != 0 && IsMine(*pwalletMain,addressout) != 0 ) if ( ASSETCHAINS_MARMARA != 0 )
resetstaker = true;
else if( ReadBlockFromDisk(block, pblockindex, 1) && komodo_WhoStaked(&block, addressout) != 0 && IsMine(*pwalletMain,addressout) != 0 )
{ {
resetstaker = true; resetstaker = true;
fprintf(stderr, "Reset ram staker after mining a block!\n"); fprintf(stderr, "Reset ram staker after mining a block!\n");
@@ -2116,7 +2140,7 @@ 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 || 1 ) if ( ASSETCHAINS_MARMARA == 0 )
{ {
BOOST_FOREACH(const COutput& out, vecOutputs) BOOST_FOREACH(const COutput& out, vecOutputs)
{ {
@@ -2149,8 +2173,29 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
} }
else else
{ {
// calc 1of2 address struct CCcontract_info *cp,C; uint256 txid; int32_t vout,ht,unlockht; CAmount nValue; char coinaddr[64]; CPubKey mypk,Marmarapk,pk;
// iterate all unspents not spent in mempool and komodo_addutxo 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);
@@ -2230,24 +2275,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);
if ( ASSETCHAINS_MARMARA == 0 || 1 ) if ( ASSETCHAINS_MARMARA == 0 )
{ {
signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, *utxovaluep, SIGHASH_ALL), best_scriptPubKey, sigdata, consensusBranchId); signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, *utxovaluep, SIGHASH_ALL), best_scriptPubKey, sigdata, consensusBranchId);
}
else
{
// add opreturn
// signSuccess = CCFinalizetx(...)
}
if (!signSuccess)
fprintf(stderr,"failed to create signature\n");
else
{
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

@@ -36,5 +36,43 @@
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

@@ -1654,7 +1654,7 @@ 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],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]; 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=0,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(ccenables,0,sizeof(ccenables));
memset(disablebits,0,sizeof(disablebits)); memset(disablebits,0,sizeof(disablebits));
@@ -1704,7 +1704,6 @@ void komodo_args(char *argv0)
KOMODO_STOPAT = GetArg("-stopat",0); KOMODO_STOPAT = GetArg("-stopat",0);
MAX_REORG_LENGTH = GetArg("-maxreorg",MAX_REORG_LENGTH); MAX_REORG_LENGTH = GetArg("-maxreorg",MAX_REORG_LENGTH);
WITNESS_CACHE_SIZE = MAX_REORG_LENGTH+10; WITNESS_CACHE_SIZE = MAX_REORG_LENGTH+10;
ASSETCHAINS_CC = GetArg("-ac_cc",0); ASSETCHAINS_CC = GetArg("-ac_cc",0);
KOMODO_CCACTIVATE = GetArg("-ac_ccactivate",0); KOMODO_CCACTIVATE = GetArg("-ac_ccactivate",0);
ASSETCHAINS_PUBLIC = GetArg("-ac_public",0); ASSETCHAINS_PUBLIC = GetArg("-ac_public",0);

View File

@@ -76,6 +76,7 @@ using namespace std;
* Global state * Global state
*/ */
#define TMPFILE_START 100000000
CCriticalSection cs_main; CCriticalSection cs_main;
extern uint8_t NOTARY_PUBKEY33[33]; extern uint8_t NOTARY_PUBKEY33[33];
extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN,KOMODO_INSYNC,KOMODO_CONNECTING,KOMODO_EXTRASATOSHI; extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN,KOMODO_INSYNC,KOMODO_CONNECTING,KOMODO_EXTRASATOSHI;
@@ -182,8 +183,9 @@ namespace {
multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked; multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked;
CCriticalSection cs_LastBlockFile; CCriticalSection cs_LastBlockFile;
std::vector<CBlockFileInfo> vinfoBlockFile; std::vector<CBlockFileInfo> vinfoBlockFile,tmpBlockFiles;
int nLastBlockFile = 0; int nLastBlockFile = 0;
int nLastTmpFile = 0;
/** Global flag to indicate we should check to see if there are /** Global flag to indicate we should check to see if there are
* block/undo files that should be deleted. Set on startup * block/undo files that should be deleted. Set on startup
* or if we allocate more file space when we're in prune mode * or if we allocate more file space when we're in prune mode
@@ -1979,6 +1981,73 @@ bool GetAddressUnspent(uint160 addressHash, int type,
return true; return true;
} }
struct CompareBlocksByHeightMain
{
bool operator()(const CBlockIndex* a, const CBlockIndex* b) const
{
/* Make sure that unequal blocks with the same height do not compare
equal. Use the pointers themselves to make a distinction. */
if (a->GetHeight() != b->GetHeight())
return (a->GetHeight() > b->GetHeight());
return a < b;
}
};
bool RemoveOrphanedBlocks(int32_t notarized_height)
{
LOCK(cs_main);
std::vector<const CBlockIndex*> prunedblocks;
std::set<const CBlockIndex*, CompareBlocksByHeightMain> setTips;
int32_t m=0,n = 0;
// get notarised timestamp and use this as a backup incase the forked block has no height.
// we -600 to make sure the time is within future block constraints.
uint32_t notarized_timestamp = komodo_heightstamp(notarized_height)-600;
// Most of this code is a direct copy from GetChainTips RPC. Which gives a return of all
// blocks that are not in the main chain.
BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
{
n++;
setTips.insert(item.second);
}
n = 0;
BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
{
const CBlockIndex* pprev=0;
n++;
if ( item.second != 0 )
pprev = item.second->pprev;
if (pprev)
setTips.erase(pprev);
}
const CBlockIndex *forked;
BOOST_FOREACH(const CBlockIndex* block, setTips)
{
// We skip anything over notarised height to avoid breaking normal consensus rules.
if ( block->GetHeight() > notarized_height || block->nTime > notarized_timestamp )
continue;
// We can also check if the block is in the active chain as a backup test.
forked = chainActive.FindFork(block);
// Here we save each forked block to a vector for removal later.
if ( forked != 0 )
prunedblocks.push_back(block);
}
if (prunedblocks.size() > 0 && pblocktree->EraseBatchSync(prunedblocks))
{
// Blocks cleared from disk succesfully, using internal DB batch erase function. Which exists, but has never been used before.
// We need to try and clear the block index from mapBlockIndex now, otherwise node will need a restart.
BOOST_FOREACH(const CBlockIndex* block, prunedblocks)
{
m++;
mapBlockIndex.erase(block->GetBlockHash());
}
fprintf(stderr, "%s removed %d orphans from %d blocks before %d\n",ASSETCHAINS_SYMBOL,m,n, notarized_height);
return true;
}
return false;
}
/*uint64_t myGettxout(uint256 hash,int32_t n) /*uint64_t myGettxout(uint256 hash,int32_t n)
{ {
CCoins coins; CCoins coins;
@@ -2126,7 +2195,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
// CBlock and CBlockIndex // CBlock and CBlockIndex
// //
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart) bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart)
{ {
// Open history file to append // Open history file to append
CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION); CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION);
@@ -3157,9 +3226,12 @@ static int64_t nTimeConnect = 0;
static int64_t nTimeIndex = 0; static int64_t nTimeIndex = 0;
static int64_t nTimeCallbacks = 0; static int64_t nTimeCallbacks = 0;
static int64_t nTimeTotal = 0; static int64_t nTimeTotal = 0;
bool FindBlockPos(int32_t tmpflag,CValidationState &state, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false);
bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos);
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck,bool fCheckPOW) bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck,bool fCheckPOW)
{ {
CDiskBlockPos blockPos;
const CChainParams& chainparams = Params(); const CChainParams& chainparams = Params();
if ( KOMODO_STOPAT != 0 && pindex->GetHeight() > KOMODO_STOPAT ) if ( KOMODO_STOPAT != 0 && pindex->GetHeight() > KOMODO_STOPAT )
return(false); return(false);
@@ -3189,6 +3261,21 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
return false; return false;
fprintf(stderr,"grandfathered exception, until jan 15th 2019\n"); fprintf(stderr,"grandfathered exception, until jan 15th 2019\n");
} }
if ( (pindex->nStatus & BLOCK_IN_TMPFILE) != 0 )
{
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
if (!FindBlockPos(0,state, blockPos, nBlockSize+8, pindex->GetHeight(), block.GetBlockTime(),false))
return error("ConnectBlock(): FindBlockPos failed");
if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart()))
return error("ConnectBlock(): FindBlockPos failed");
pindex->nStatus &= (~BLOCK_IN_TMPFILE);
pindex->nFile = blockPos.nFile;
pindex->nDataPos = blockPos.nPos;
if (!ReceivedBlockTransactions(block, state, pindex, blockPos))
return error("AcceptBlock(): ReceivedBlockTransactions failed");
setDirtyFileInfo.insert(blockPos.nFile);
fprintf(stderr,"added ht.%d copy of tmpfile to %d.%d\n",pindex->GetHeight(),blockPos.nFile,blockPos.nPos);
}
// verify that the view's current state corresponds to the previous block // verify that the view's current state corresponds to the previous block
uint256 hashPrevBlock = pindex->pprev == NULL ? uint256() : pindex->pprev->GetBlockHash(); uint256 hashPrevBlock = pindex->pprev == NULL ? uint256() : pindex->pprev->GetBlockHash();
if ( hashPrevBlock != view.GetBestBlock() ) if ( hashPrevBlock != view.GetBestBlock() )
@@ -3806,7 +3893,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);
} }
@@ -3837,7 +3924,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());
} }
@@ -3853,7 +3940,8 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
int32_t komodo_activate_sapling(CBlockIndex *pindex) int32_t komodo_activate_sapling(CBlockIndex *pindex)
{ {
uint32_t blocktime,prevtime; CBlockIndex *prev; int32_t i,transition=0,height,prevht,activation = 0; uint32_t blocktime,prevtime; CBlockIndex *prev; int32_t i,transition=0,height,prevht;
int32_t activation = 0;
if ( pindex == 0 ) if ( pindex == 0 )
{ {
fprintf(stderr,"komodo_activate_sapling null pindex\n"); fprintf(stderr,"komodo_activate_sapling null pindex\n");
@@ -3911,6 +3999,7 @@ int32_t komodo_activate_sapling(CBlockIndex *pindex)
fprintf(stderr,"%s sapling activation at %d\n",ASSETCHAINS_SYMBOL,activation); fprintf(stderr,"%s sapling activation at %d\n",ASSETCHAINS_SYMBOL,activation);
ASSETCHAINS_SAPLING = activation; ASSETCHAINS_SAPLING = activation;
} }
return activation;
} }
static int64_t nTimeReadFromDisk = 0; static int64_t nTimeReadFromDisk = 0;
@@ -4483,43 +4572,57 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
return true; return true;
} }
bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false) bool FindBlockPos(int32_t tmpflag,CValidationState &state, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown)
{ {
std::vector<CBlockFileInfo> *ptr; int *lastfilep;
LOCK(cs_LastBlockFile); LOCK(cs_LastBlockFile);
unsigned int nFile = fKnown ? pos.nFile : nLastBlockFile; unsigned int nFile;
if ( tmpflag != 0 )
{
ptr = &tmpBlockFiles;
nFile = nLastTmpFile;
lastfilep = &nLastTmpFile;
}
else
{
ptr = &vinfoBlockFile;
lastfilep = &nLastBlockFile;
nFile = fKnown ? pos.nFile : nLastBlockFile;
if (vinfoBlockFile.size() <= nFile) { if (vinfoBlockFile.size() <= nFile) {
vinfoBlockFile.resize(nFile + 1); vinfoBlockFile.resize(nFile + 1);
} }
}
if (!fKnown) { if (!fKnown) {
while (vinfoBlockFile[nFile].nSize + nAddSize >= MAX_BLOCKFILE_SIZE) { while ((*ptr)[nFile].nSize + nAddSize >= MAX_BLOCKFILE_SIZE) {
nFile++; nFile++;
if (vinfoBlockFile.size() <= nFile) { if ((*ptr).size() <= nFile) {
vinfoBlockFile.resize(nFile + 1); (*ptr).resize(nFile + 1);
} }
} }
pos.nFile = nFile; pos.nFile = nFile + tmpflag*TMPFILE_START;
pos.nPos = vinfoBlockFile[nFile].nSize; pos.nPos = (*ptr)[nFile].nSize;
if ( 0 && tmpflag != 0 )
fprintf(stderr,"pos.nFile %d nPos %u\n",pos.nFile,pos.nPos);
} }
if (nFile != nLastBlockFile) { if (nFile != *lastfilep) {
if (!fKnown) { if (!fKnown) {
LogPrintf("Leaving block file %i: %s\n", nFile, vinfoBlockFile[nFile].ToString()); LogPrintf("Leaving block file %i: %s\n", nFile, (*ptr)[nFile].ToString());
} }
FlushBlockFile(!fKnown); FlushBlockFile(!fKnown);
nLastBlockFile = nFile; *lastfilep = nFile;
} }
vinfoBlockFile[nFile].AddBlock(nHeight, nTime); (*ptr)[nFile].AddBlock(nHeight, nTime);
if (fKnown) if (fKnown)
vinfoBlockFile[nFile].nSize = std::max(pos.nPos + nAddSize, vinfoBlockFile[nFile].nSize); (*ptr)[nFile].nSize = std::max(pos.nPos + nAddSize, (*ptr)[nFile].nSize);
else else
vinfoBlockFile[nFile].nSize += nAddSize; (*ptr)[nFile].nSize += nAddSize;
if (!fKnown) { if (!fKnown) {
unsigned int nOldChunks = (pos.nPos + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE; unsigned int nOldChunks = (pos.nPos + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE;
unsigned int nNewChunks = (vinfoBlockFile[nFile].nSize + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE; unsigned int nNewChunks = ((*ptr)[nFile].nSize + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE;
if (nNewChunks > nOldChunks) { if (nNewChunks > nOldChunks) {
if (fPruneMode) if (fPruneMode)
fCheckForPruning = true; fCheckForPruning = true;
@@ -4536,19 +4639,26 @@ bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAdd
} }
} }
setDirtyFileInfo.insert(nFile); setDirtyFileInfo.insert(nFile + tmpflag*TMPFILE_START);
return true; return true;
} }
bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize) bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize)
{ {
pos.nFile = nFile; std::vector<CBlockFileInfo> *ptr; int *lastfilep;
LOCK(cs_LastBlockFile); LOCK(cs_LastBlockFile);
pos.nFile = nFile;
if ( nFile >= TMPFILE_START )
{
fprintf(stderr,"skip tmp undo\n");
return(false);
nFile %= TMPFILE_START;
ptr = &tmpBlockFiles;
} else ptr = &vinfoBlockFile;
unsigned int nNewSize; unsigned int nNewSize;
pos.nPos = vinfoBlockFile[nFile].nUndoSize; pos.nPos = (*ptr)[nFile].nUndoSize;
nNewSize = vinfoBlockFile[nFile].nUndoSize += nAddSize; nNewSize = (*ptr)[nFile].nUndoSize += nAddSize;
setDirtyFileInfo.insert(nFile); setDirtyFileInfo.insert(nFile);
unsigned int nOldChunks = (pos.nPos + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE; unsigned int nOldChunks = (pos.nPos + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE;
@@ -4592,7 +4702,7 @@ bool CheckBlockHeader(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,
*futureblockp = 0; *futureblockp = 0;
if (blockhdr.GetBlockTime() > GetAdjustedTime() + 60) if (blockhdr.GetBlockTime() > GetAdjustedTime() + 60)
{ {
CBlockIndex *tipindex; /*CBlockIndex *tipindex;
//fprintf(stderr,"ht.%d future block %u vs time.%u + 60\n",height,(uint32_t)blockhdr.GetBlockTime(),(uint32_t)GetAdjustedTime()); //fprintf(stderr,"ht.%d future block %u vs time.%u + 60\n",height,(uint32_t)blockhdr.GetBlockTime(),(uint32_t)GetAdjustedTime());
if ( (tipindex= chainActive.Tip()) != 0 && tipindex->GetBlockHash() == blockhdr.hashPrevBlock && blockhdr.GetBlockTime() < GetAdjustedTime() + 60 + 5 ) if ( (tipindex= chainActive.Tip()) != 0 && tipindex->GetBlockHash() == blockhdr.hashPrevBlock && blockhdr.GetBlockTime() < GetAdjustedTime() + 60 + 5 )
{ {
@@ -4601,9 +4711,9 @@ bool CheckBlockHeader(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,
sleep(1); sleep(1);
//fprintf(stderr,"now its valid\n"); //fprintf(stderr,"now its valid\n");
} }
else else*/
{ {
if (blockhdr.GetBlockTime() < GetAdjustedTime() + 600) if (blockhdr.GetBlockTime() < GetAdjustedTime() + 300)
*futureblockp = 1; *futureblockp = 1;
//LogPrintf("CheckBlockHeader block from future %d error",blockhdr.GetBlockTime() - GetAdjustedTime()); //LogPrintf("CheckBlockHeader block from future %d error",blockhdr.GetBlockTime() - GetAdjustedTime());
return false; //state.Invalid(error("CheckBlockHeader(): block timestamp too far in the future"),REJECT_INVALID, "time-too-new"); return false; //state.Invalid(error("CheckBlockHeader(): block timestamp too far in the future"),REJECT_INVALID, "time-too-new");
@@ -4734,7 +4844,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
@@ -5098,19 +5208,22 @@ bool AcceptBlock(int32_t *futureblockp,CBlock& block, CValidationState& state, C
} }
int nHeight = pindex->GetHeight(); int nHeight = pindex->GetHeight();
int32_t usetmp = 0;
// Write block to history file // Write block to history file
try { try {
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
CDiskBlockPos blockPos; CDiskBlockPos blockPos;
if (dbp != NULL) if (dbp != NULL)
blockPos = *dbp; blockPos = *dbp;
if (!FindBlockPos(state, blockPos, nBlockSize+8, nHeight, block.GetBlockTime(), dbp != NULL)) if (!FindBlockPos(usetmp,state, blockPos, nBlockSize+8, nHeight, block.GetBlockTime(), dbp != NULL))
return error("AcceptBlock(): FindBlockPos failed"); return error("AcceptBlock(): FindBlockPos failed");
if (dbp == NULL) if (dbp == NULL)
if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart()))
AbortNode(state, "Failed to write block"); AbortNode(state, "Failed to write block");
if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) if (!ReceivedBlockTransactions(block, state, pindex, blockPos))
return error("AcceptBlock(): ReceivedBlockTransactions failed"); return error("AcceptBlock(): ReceivedBlockTransactions failed");
if ( usetmp != 0 ) // not during initialdownload or if futureflag==0 and contextchecks ok
pindex->nStatus |= BLOCK_IN_TMPFILE;
} catch (const std::runtime_error& e) { } catch (const std::runtime_error& e) {
return AbortNode(state, std::string("System error: ") + e.what()); return AbortNode(state, std::string("System error: ") + e.what());
} }
@@ -5428,7 +5541,7 @@ bool CheckDiskSpace(uint64_t nAdditionalBytes)
FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly) FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly)
{ {
static int32_t didinit[64]; static int32_t didinit[256];
if (pos.IsNull()) if (pos.IsNull())
return NULL; return NULL;
boost::filesystem::path path = GetBlockPosFilename(pos, prefix); boost::filesystem::path path = GetBlockPosFilename(pos, prefix);
@@ -5572,6 +5685,7 @@ bool static LoadBlockIndexDB()
// Load block file info // Load block file info
pblocktree->ReadLastBlockFile(nLastBlockFile); pblocktree->ReadLastBlockFile(nLastBlockFile);
vinfoBlockFile.resize(nLastBlockFile + 1); vinfoBlockFile.resize(nLastBlockFile + 1);
tmpBlockFiles.resize(nLastTmpFile + 1);
LogPrintf("%s: last block file = %i\n", __func__, nLastBlockFile); LogPrintf("%s: last block file = %i\n", __func__, nLastBlockFile);
for (int nFile = 0; nFile <= nLastBlockFile; nFile++) { for (int nFile = 0; nFile <= nLastBlockFile; nFile++) {
pblocktree->ReadBlockFileInfo(nFile, vinfoBlockFile[nFile]); pblocktree->ReadBlockFileInfo(nFile, vinfoBlockFile[nFile]);
@@ -5595,7 +5709,6 @@ bool static LoadBlockIndexDB()
if (pindex->nStatus & BLOCK_HAVE_DATA) { if (pindex->nStatus & BLOCK_HAVE_DATA) {
setBlkDataFiles.insert(pindex->nFile); setBlkDataFiles.insert(pindex->nFile);
} }
//komodo_pindex_init(pindex,(int32_t)pindex->GetHeight());
} }
//fprintf(stderr,"load blockindexDB %u\n",(uint32_t)time(NULL)); //fprintf(stderr,"load blockindexDB %u\n",(uint32_t)time(NULL));
for (std::set<int>::iterator it = setBlkDataFiles.begin(); it != setBlkDataFiles.end(); it++) for (std::set<int>::iterator it = setBlkDataFiles.begin(); it != setBlkDataFiles.end(); it++)
@@ -5936,6 +6049,7 @@ void UnloadBlockIndex()
nSyncStarted = 0; nSyncStarted = 0;
mapBlocksUnlinked.clear(); mapBlocksUnlinked.clear();
vinfoBlockFile.clear(); vinfoBlockFile.clear();
tmpBlockFiles.clear();
nLastBlockFile = 0; nLastBlockFile = 0;
nBlockSequenceId = 1; nBlockSequenceId = 1;
mapBlockSource.clear(); mapBlockSource.clear();
@@ -5971,6 +6085,7 @@ bool LoadBlockIndex()
bool InitBlockIndex() { bool InitBlockIndex() {
const CChainParams& chainparams = Params(); const CChainParams& chainparams = Params();
LOCK(cs_main); LOCK(cs_main);
tmpBlockFiles.clear();
// Initialize global variables that cannot be constructed at startup. // Initialize global variables that cannot be constructed at startup.
recentRejects.reset(new CRollingBloomFilter(120000, 0.000001)); recentRejects.reset(new CRollingBloomFilter(120000, 0.000001));
@@ -6003,7 +6118,7 @@ bool InitBlockIndex() {
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
CDiskBlockPos blockPos; CDiskBlockPos blockPos;
CValidationState state; CValidationState state;
if (!FindBlockPos(state, blockPos, nBlockSize+8, 0, block.GetBlockTime())) if (!FindBlockPos(0,state, blockPos, nBlockSize+8, 0, block.GetBlockTime()))
return error("LoadBlockIndex(): FindBlockPos failed"); return error("LoadBlockIndex(): FindBlockPos failed");
if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart()))
return error("LoadBlockIndex(): writing genesis block to disk failed"); return error("LoadBlockIndex(): writing genesis block to disk failed");

View File

@@ -78,7 +78,7 @@ static const bool DEFAULT_ALERTS = true;
/** Minimum alert priority for enabling safe mode. */ /** Minimum alert priority for enabling safe mode. */
static const int ALERT_PRIORITY_SAFE_MODE = 4000; static const int ALERT_PRIORITY_SAFE_MODE = 4000;
/** Maximum reorg length we will accept before we shut down and alert the user. */ /** Maximum reorg length we will accept before we shut down and alert the user. */
static unsigned int MAX_REORG_LENGTH = (_COINBASE_MATURITY - 1); static unsigned int MAX_REORG_LENGTH = _COINBASE_MATURITY - 1;
/** Maximum number of signature check operations in an IsStandard() P2SH script */ /** Maximum number of signature check operations in an IsStandard() P2SH script */
static const unsigned int MAX_P2SH_SIGOPS = 15; static const unsigned int MAX_P2SH_SIGOPS = 15;
/** The maximum number of sigops we're willing to relay/mine in a single tx */ /** The maximum number of sigops we're willing to relay/mine in a single tx */
@@ -803,10 +803,10 @@ bool GetAddressUnspent(uint160 addressHash, int type,
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs); std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs);
/** Functions for disk access for blocks */ /** Functions for disk access for blocks */
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart); bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart);
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos,bool checkPOW); bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos,bool checkPOW);
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex,bool checkPOW); bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex,bool checkPOW);
bool RemoveOrphanedBlocks(int32_t notarized_height);
/** Functions for validating blocks and updating the block tree */ /** Functions for validating blocks and updating the block tree */

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);
@@ -487,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)
@@ -521,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
@@ -1405,6 +1396,8 @@ void static BitcoinMiner_noeq()
miningTimer.stop(); miningTimer.stop();
} }
int32_t gotinvalid;
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
void static BitcoinMiner(CWallet *pwallet) void static BitcoinMiner(CWallet *pwallet)
#else #else
@@ -1613,16 +1606,12 @@ void static BitcoinMiner()
fprintf(stderr," PoW for staked coin PoS %d%% vs target %d%% ht.%d\n",percPoS,(int32_t)ASSETCHAINS_STAKED,Mining_height); fprintf(stderr," PoW for staked coin PoS %d%% vs target %d%% ht.%d\n",percPoS,(int32_t)ASSETCHAINS_STAKED,Mining_height);
} }
} }
gotinvalid = 0;
while (true) while (true)
{ {
/*if ( KOMODO_INSYNC == 0 ) //fprintf(stderr,"gotinvalid.%d\n",gotinvalid);
{ if ( gotinvalid != 0 )
KOMODO_LONGESTCHAIN = komodo_longestchain(); break;
fprintf(stderr,"Mining when blockchain might not be in sync longest.%d vs %d\n",KOMODO_LONGESTCHAIN,Mining_height);
if ( KOMODO_LONGESTCHAIN != 0 && Mining_height >= KOMODO_LONGESTCHAIN )
KOMODO_INSYNC = Mining_height;
sleep(3);
}*/
komodo_longestchain(); komodo_longestchain();
// Hash state // Hash state
KOMODO_CHOSEN_ONE = 0; KOMODO_CHOSEN_ONE = 0;
@@ -1716,6 +1705,7 @@ void static BitcoinMiner()
for (z=31; z>=0; z--) for (z=31; z>=0; z--)
fprintf(stderr,"%02x",((uint8_t *)&h)[z]); fprintf(stderr,"%02x",((uint8_t *)&h)[z]);
fprintf(stderr," Invalid block mined, try again\n"); fprintf(stderr," Invalid block mined, try again\n");
gotinvalid = 1;
return(false); return(false);
} }
KOMODO_CHOSEN_ONE = 1; KOMODO_CHOSEN_ONE = 1;

View File

@@ -33,6 +33,7 @@
#include "sync.h" #include "sync.h"
#include "uint256.h" #include "uint256.h"
#include "utilstrencodings.h" #include "utilstrencodings.h"
#include "util.h"
#include <deque> #include <deque>
#include <stdint.h> #include <stdint.h>
@@ -63,7 +64,7 @@ static const unsigned int MAX_INV_SZ = 50000;
/** The maximum number of new addresses to accumulate before announcing. */ /** The maximum number of new addresses to accumulate before announcing. */
static const unsigned int MAX_ADDR_TO_SEND = 1000; static const unsigned int MAX_ADDR_TO_SEND = 1000;
/** Maximum length of incoming protocol messages (no message over 2 MiB is currently acceptable). */ /** Maximum length of incoming protocol messages (no message over 2 MiB is currently acceptable). */
static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 4 * 1024 * 1024; // depends on MAX_BLOCK_SIZE static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = (_MAX_BLOCK_SIZE + 24); // 24 is msgheader size
/** Maximum length of strSubVer in `version` message */ /** Maximum length of strSubVer in `version` message */
static const unsigned int MAX_SUBVERSION_LENGTH = 256; static const unsigned int MAX_SUBVERSION_LENGTH = 256;
/** -listen default */ /** -listen default */

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

@@ -463,6 +463,10 @@ static const CRPCCommand vRPCCommands[] =
// 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 },
@@ -533,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

@@ -287,6 +287,9 @@ 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 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);
@@ -468,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

@@ -523,8 +523,8 @@ static vector<valtype> CombineMultisig(const CScript& scriptPubKey, const BaseSi
namespace namespace
{ {
struct Stacks struct Stacks
{ {
std::vector<valtype> script; std::vector<valtype> script;
Stacks() {} Stacks() {}
@@ -538,7 +538,7 @@ struct Stacks
result.scriptSig = PushAll(script); result.scriptSig = PushAll(script);
return result; return result;
} }
}; };
} }
static Stacks CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, static Stacks CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
@@ -603,10 +603,10 @@ SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignature
} }
namespace { namespace {
/** Dummy signature checker which accepts all signatures. */ /** Dummy signature checker which accepts all signatures. */
class DummySignatureChecker : public BaseSignatureChecker class DummySignatureChecker : public BaseSignatureChecker
{ {
public: public:
DummySignatureChecker() {} DummySignatureChecker() {}
bool CheckSig( bool CheckSig(
@@ -617,8 +617,8 @@ public:
{ {
return true; return true;
} }
}; };
const DummySignatureChecker dummyChecker; const DummySignatureChecker dummyChecker;
} }
const BaseSignatureChecker& DummySignatureCreator::Checker() const const BaseSignatureChecker& DummySignatureCreator::Checker() const
@@ -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

@@ -103,7 +103,7 @@ void ThreadSendAlert()
// 4000 or higher will put the RPC into safe mode // 4000 or higher will put the RPC into safe mode
alert.nPriority = 4000; alert.nPriority = 4000;
alert.strComment = ""; alert.strComment = "";
alert.strStatusBar = "Your client version has degraded networking behavior. Please update to the most recent version of Verus (0.3.2 or later)."; alert.strStatusBar = "Your client version has degraded networking behavior. Please update to the most recent version of Komodo (0.3.3 or later).";
alert.strRPCError = alert.strStatusBar; alert.strRPCError = alert.strStatusBar;
// Set specific client version/versions here. If setSubVer is empty, no filtering on subver is done: // Set specific client version/versions here. If setSubVer is empty, no filtering on subver is done:

View File

@@ -686,7 +686,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
pindexNew->nTx = diskindex.nTx; pindexNew->nTx = diskindex.nTx;
pindexNew->nSproutValue = diskindex.nSproutValue; pindexNew->nSproutValue = diskindex.nSproutValue;
pindexNew->nSaplingValue = diskindex.nSaplingValue; pindexNew->nSaplingValue = diskindex.nSaplingValue;
//fprintf(stderr,"loadguts ht.%d\n",pindexNew->GetHeight());
// Consistency checks // Consistency checks
auto header = pindexNew->GetBlockHeader(); auto header = pindexNew->GetBlockHeader();
if (header.GetHash() != pindexNew->GetBlockHash()) if (header.GetHash() != pindexNew->GetBlockHash())

View File

@@ -3,6 +3,21 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
/******************************************************************************
* 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. *
* *
******************************************************************************/
/** /**
* Server/client environment: argument handling, config file parsing, * Server/client environment: argument handling, config file parsing,
* logging, thread wrappers * logging, thread wrappers
@@ -29,6 +44,8 @@
#include <boost/signals2/signal.hpp> #include <boost/signals2/signal.hpp>
#include <boost/thread/exceptions.hpp> #include <boost/thread/exceptions.hpp>
#define _MAX_BLOCK_SIZE (4096 * 1024) // changing just _MAX_BLOCK_SIZE will hardfork to that size
static const bool DEFAULT_LOGTIMEMICROS = false; static const bool DEFAULT_LOGTIMEMICROS = false;
static const bool DEFAULT_LOGIPS = false; static const bool DEFAULT_LOGIPS = false;
static const bool DEFAULT_LOGTIMESTAMPS = true; static const bool DEFAULT_LOGTIMESTAMPS = 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
@@ -4887,10 +4886,11 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
if (useAnySprout || useAnySapling || zaddrs.size() > 0) { if (useAnySprout || useAnySapling || zaddrs.size() > 0) {
// Get available notes // Get available notes
std::vector<CSproutNotePlaintextEntry> sproutEntries,skipsprout; std::vector<CSproutNotePlaintextEntry> sproutEntries;
//std::vector<SaplingNoteEntry> saplingEntries;
//pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs);
std::vector<SaplingNoteEntry> saplingEntries,skipsapling; std::vector<SaplingNoteEntry> saplingEntries,skipsapling;
pwalletMain->GetFilteredNotes(sproutEntries, useAnySprout == 0 ? saplingEntries : skipsapling, zaddrs); pwalletMain->GetFilteredNotes(sproutEntries, useAnySprout == 0 ? saplingEntries : skipsapling, zaddrs);
// If Sapling is not active, do not allow sending from a sapling addresses. // If Sapling is not active, do not allow sending from a sapling addresses.
if (!saplingActive && saplingEntries.size() > 0) { if (!saplingActive && saplingEntries.size() > 0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated"); throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated");
@@ -5172,7 +5172,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 +5261,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 +5324,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;
@@ -7329,7 +7363,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;
@@ -7340,21 +7374,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)
@@ -7373,7 +7420,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;
@@ -7384,18 +7431,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;
} }
@@ -7404,7 +7453,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;
@@ -7415,18 +7463,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;
} }
@@ -7548,3 +7598,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

@@ -77,7 +77,6 @@ static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000;
// unless there is some exceptional network disruption. // unless there is some exceptional network disruption.
extern unsigned int WITNESS_CACHE_SIZE; extern unsigned int WITNESS_CACHE_SIZE;
//! Size of HD seed in bytes //! Size of HD seed in bytes
static const size_t HD_WALLET_SEED_LENGTH = 32; static const size_t HD_WALLET_SEED_LENGTH = 32;