@@ -13,12 +13,14 @@ export BITCOIND=${REAL_BITCOIND}
|
||||
|
||||
testScripts=(
|
||||
'cryptoconditions_faucet.py'
|
||||
'cryptoconditions_channels.py'
|
||||
'cryptoconditions_dice.py'
|
||||
'cryptoconditions_oracles.py'
|
||||
'cryptoconditions_rewards.py'
|
||||
'cryptoconditions_token.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"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
# 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, \
|
||||
@@ -71,6 +72,58 @@ class CryptoconditionsChannelsTest(CryptoconditionsTestFramework):
|
||||
result = rpc.channelsinfo(channel_txid)
|
||||
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
|
||||
result = rpc.channelsclose(channel_txid)
|
||||
assert_success(result)
|
||||
@@ -82,7 +135,7 @@ class CryptoconditionsChannelsTest(CryptoconditionsTestFramework):
|
||||
|
||||
# now in channelinfo closed flag should appear
|
||||
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
|
||||
result = rpc.channelsrefund(channel_txid, channel_close_txid)
|
||||
@@ -90,6 +143,92 @@ class CryptoconditionsChannelsTest(CryptoconditionsTestFramework):
|
||||
refund_txid = self.send_and_mine(result["hex"], rpc)
|
||||
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):
|
||||
print("Mining blocks...")
|
||||
rpc = self.nodes[0]
|
||||
|
||||
121
qa/rpc-tests/cryptoconditions_heir.py
Executable file
121
qa/rpc-tests/cryptoconditions_heir.py
Executable 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()
|
||||
@@ -15,21 +15,35 @@ from cryptoconditions import assert_success, assert_error, generate_random_strin
|
||||
class CryptoconditionsTokenTest(CryptoconditionsTestFramework):
|
||||
|
||||
def run_token_tests(self):
|
||||
rpc = self.nodes[0]
|
||||
|
||||
rpc = self.nodes[0]
|
||||
rpc1 = self.nodes[1]
|
||||
|
||||
result = rpc.tokenaddress()
|
||||
assert_success(result)
|
||||
for x in ['AssetsCCaddress', 'myCCaddress', 'Assetsmarker', 'myaddress']:
|
||||
for x in ['TokensCCaddress', 'myCCaddress', 'Tokensmarker', 'myaddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
result = rpc.tokenaddress(self.pubkey)
|
||||
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']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
# there are no tokens created yet
|
||||
result = rpc.tokenlist()
|
||||
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")
|
||||
assert_error(result)
|
||||
|
||||
@@ -50,12 +64,9 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework):
|
||||
result = rpc.tokenorders()
|
||||
assert_equal(result, [])
|
||||
|
||||
# getting token balance for pubkey
|
||||
# getting token balance for non existing tokenid
|
||||
result = rpc.tokenbalance(self.pubkey)
|
||||
assert_success(result)
|
||||
assert_equal(result['balance'], 0)
|
||||
assert_equal(result['CCaddress'], 'RCRsm3VBXz8kKTsYaXKpy7pSEzrtNNQGJC')
|
||||
assert_equal(result['tokenid'], self.pubkey)
|
||||
assert_error(result)
|
||||
|
||||
# get token balance for token with pubkey
|
||||
result = rpc.tokenbalance(tokenid, self.pubkey)
|
||||
@@ -131,11 +142,25 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework):
|
||||
# checking ask cancellation
|
||||
testorder = rpc.tokenask("100", tokenid, "7.77")
|
||||
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)
|
||||
self.send_and_mine(cancel["hex"], rpc)
|
||||
result = rpc.tokenorders()
|
||||
assert_equal(result, [])
|
||||
|
||||
|
||||
# invalid numtokens bid
|
||||
result = rpc.tokenbid("-1", tokenid, "1")
|
||||
assert_error(result)
|
||||
@@ -184,6 +209,15 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework):
|
||||
# checking bid cancellation
|
||||
testorder = rpc.tokenbid("100", tokenid, "7.77")
|
||||
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)
|
||||
self.send_and_mine(cancel["hex"], rpc)
|
||||
result = rpc.tokenorders()
|
||||
@@ -220,5 +254,6 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework):
|
||||
rpc1.importprivkey(self.privkey1)
|
||||
self.run_token_tests()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
CryptoconditionsTokenTest().main()
|
||||
|
||||
@@ -94,7 +94,8 @@ void WaitForShutdown(boost::thread_group* threadGroup)
|
||||
//
|
||||
// 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;
|
||||
int32_t komodo_is_issuer();
|
||||
void komodo_passport_iteration();
|
||||
|
||||
@@ -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)
|
||||
|
||||
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)
|
||||
|
||||
|
||||
@@ -27,10 +27,10 @@ bool HeirValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,
|
||||
class CoinHelper;
|
||||
class TokenHelper;
|
||||
|
||||
UniValue HeirFundCoinCaller(uint64_t txfee, int64_t funds, 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 HeirClaimCaller(uint256 fundingtxid, uint64_t txfee, int64_t amount);
|
||||
UniValue HeirAddCaller(uint256 fundingtxid, uint64_t txfee, int64_t amount);
|
||||
UniValue HeirFundCoinCaller(int64_t txfee, int64_t satoshis, 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, int64_t txfee, std::string amount);
|
||||
UniValue HeirAddCaller(uint256 fundingtxid, int64_t txfee, std::string amount);
|
||||
|
||||
UniValue HeirInfo(uint256 fundingtxid);
|
||||
UniValue HeirList();
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
CTransaction vintx;
|
||||
uint64_t mask;
|
||||
uint256 hashBlock;
|
||||
int64_t bidamount;
|
||||
CPubKey mypk;
|
||||
struct CCcontract_info *cpAssets, C;
|
||||
|
||||
uint8_t dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; std::vector<uint8_t> dummyOrigpubkey;
|
||||
CTransaction vintx; uint64_t mask;
|
||||
uint256 hashBlock; int64_t bidamount;
|
||||
CPubKey mypk; struct CCcontract_info *cpAssets, C;
|
||||
uint8_t funcid,dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; std::vector<uint8_t> dummyOrigpubkey;
|
||||
|
||||
cpAssets = CCinit(&C, EVAL_ASSETS);
|
||||
|
||||
@@ -501,9 +497,12 @@ std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid)
|
||||
bidamount = vintx.vout[0].nValue;
|
||||
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')
|
||||
mtx.vin.push_back(CTxIn(bidtxid, 1, CScript())); // spend marker if funcid='b' (not 'B')
|
||||
// TODO: spend it also in FillBuyOffer?
|
||||
if((funcid=DecodeAssetTokenOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey))!=0)
|
||||
{
|
||||
|
||||
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(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());
|
||||
CTransaction vintx; uint64_t mask;
|
||||
uint256 hashBlock;
|
||||
int64_t askamount;
|
||||
CPubKey mypk;
|
||||
struct CCcontract_info *cpTokens, *cpAssets, tokensC, assetsC;
|
||||
|
||||
uint8_t dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; std::vector<uint8_t> dummyOrigpubkey;
|
||||
uint256 hashBlock; int64_t askamount;
|
||||
CPubKey mypk; struct CCcontract_info *cpTokens, *cpAssets, tokensC, assetsC;
|
||||
uint8_t funcid,dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; std::vector<uint8_t> dummyOrigpubkey;
|
||||
|
||||
cpAssets = CCinit(&assetsC, EVAL_ASSETS);
|
||||
|
||||
@@ -545,9 +541,11 @@ std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid)
|
||||
askamount = vintx.vout[0].nValue;
|
||||
mtx.vin.push_back(CTxIn(asktxid, 0, CScript()));
|
||||
|
||||
if (DecodeAssetTokenOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey) == 's')
|
||||
mtx.vin.push_back(CTxIn(asktxid, 1, CScript())); // marker if funcid='s' (not 'S')
|
||||
// TODO: spend it also in FillSell?
|
||||
if ((funcid=DecodeAssetTokenOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey))!=0)
|
||||
{
|
||||
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(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());
|
||||
|
||||
if (AddNormalinputs(mtx, mypk, txfee, 3) > 0)
|
||||
if (AddNormalinputs(mtx, mypk, 2*txfee, 3) > 0)
|
||||
{
|
||||
mask = ~((1LL << mtx.vin.size()) - 1);
|
||||
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(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_ASSETS,txfee,origpubkey)); // vout3 marker to origpubkey
|
||||
|
||||
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);
|
||||
|
||||
@@ -698,7 +697,7 @@ std::string FillSell(int64_t txfee, uint256 assetid, uint256 assetid2, uint256 a
|
||||
txfee = 10000;
|
||||
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
if (AddNormalinputs(mtx, mypk, txfee, 3) > 0)
|
||||
if (AddNormalinputs(mtx, mypk, 2*txfee, 3) > 0)
|
||||
{
|
||||
mask = ~((1LL << mtx.vin.size()) - 1);
|
||||
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;
|
||||
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
|
||||
if (CCchange != 0) {
|
||||
|
||||
@@ -234,6 +234,34 @@ uint8_t TokensCCpriv[32] = { 0x1d, 0x0d, 0x0d, 0xce, 0x2d, 0xd2, 0xe1, 0x9d, 0xf
|
||||
#undef FUNCNAME
|
||||
#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)
|
||||
{
|
||||
@@ -369,6 +397,10 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode)
|
||||
cp->validate = TokensValidate;
|
||||
cp->ismyvin = IsTokensInput;
|
||||
break;
|
||||
default:
|
||||
if ( CClib_initcp(cp,evalcode) < 0 )
|
||||
return(0);
|
||||
break;
|
||||
}
|
||||
return(cp);
|
||||
}
|
||||
|
||||
@@ -51,11 +51,6 @@ one other technical note is that komodod has the insight-explorer extensions bui
|
||||
#include "../utlist.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
|
||||
|
||||
@@ -69,6 +64,7 @@ extern uint8_t ASSETCHAINS_CCDISABLES[256];
|
||||
typedef union _bits256 bits256;
|
||||
#endif
|
||||
|
||||
#include "../komodo_cJSON.h"
|
||||
|
||||
struct CC_utxo
|
||||
{
|
||||
@@ -134,6 +130,9 @@ CBlockIndex *komodo_getblockindex(uint256 hash);
|
||||
int32_t komodo_nextheight();
|
||||
|
||||
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;
|
||||
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 GetTokensCCaddress1of2(struct CCcontract_info *cp, char *destaddr, CPubKey pk, CPubKey pk2);
|
||||
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);
|
||||
int32_t unstringbits(char *buf,uint64_t bits);
|
||||
|
||||
@@ -404,7 +404,6 @@ int64_t IsTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *c
|
||||
|
||||
uint8_t evalCodeInOpret;
|
||||
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];
|
||||
}
|
||||
else {
|
||||
@@ -766,4 +765,4 @@ UniValue TokenList()
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,39 +493,10 @@ CPubKey GetUnspendable(struct CCcontract_info *cp,uint8_t *unspendablepriv)
|
||||
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->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)
|
||||
@@ -602,7 +573,6 @@ bool komodo_txnotarizedconfirmed(uint256 txid)
|
||||
|
||||
CPubKey check_signing_pubkey(CScript scriptSig)
|
||||
{
|
||||
|
||||
bool found = false;
|
||||
CPubKey pubkey;
|
||||
|
||||
@@ -630,3 +600,79 @@ CPubKey check_signing_pubkey(CScript scriptSig)
|
||||
}
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -153,8 +153,9 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti
|
||||
return eval->Invalid("AssetValidate: invalid opreturn payload");
|
||||
|
||||
// find dual-eval tokens unspendable addr:
|
||||
char tokensUnspendableAddr[64];
|
||||
char tokensUnspendableAddr[64],origpubkeyCCaddr[64];
|
||||
GetTokensCCaddress(cpAssets, tokensUnspendableAddr, GetUnspendable(cpAssets, NULL));
|
||||
GetCCaddress(cpAssets, origpubkeyCCaddr, origpubkey);
|
||||
|
||||
// we need this for validating single-eval tokens' vins/vous:
|
||||
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 )
|
||||
return(false);
|
||||
else if( numvouts < 3 )
|
||||
else if( numvouts < 4 )
|
||||
return eval->Invalid("not enough vouts for fillbuy");
|
||||
else if( tmporigpubkey != origpubkey )
|
||||
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 )
|
||||
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
|
||||
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");
|
||||
}
|
||||
else if( ConstrainVout(tx.vout[2], 1, assetsCCaddr, inputs) == 0 ) // tokens on user cc addr
|
||||
return eval->Invalid("vout2 doesnt match inputs fillbuy");
|
||||
else if( ConstrainVout(tx.vout[1],0,0,0) == 0 )
|
||||
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 )
|
||||
return eval->Invalid("mismatched remainder for fillbuy");
|
||||
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 )
|
||||
return(false);
|
||||
else if( numvouts < 3 )
|
||||
else if( numvouts < 4 )
|
||||
return eval->Invalid("not enough vouts for fillask");
|
||||
else if( tmporigpubkey != origpubkey )
|
||||
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");
|
||||
else if( ConstrainVout(tx.vout[2], 0, origaddr, 0) == 0 )
|
||||
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 )
|
||||
{
|
||||
//char tokensUnspendableAddr[64];
|
||||
|
||||
311
src/cc/cclib.cpp
311
src/cc/cclib.cpp
@@ -27,32 +27,291 @@
|
||||
#include "core_io.h"
|
||||
#include "crosschain.h"
|
||||
|
||||
#define MYCCLIBNAME ((char *)"stub")
|
||||
#define FAUCET2SIZE COIN
|
||||
|
||||
char *CClib_name() { return(MYCCLIBNAME); }
|
||||
|
||||
bool CClib_Dispatch(const CC *cond,Eval *eval,std::vector<uint8_t> paramsNull,const CTransaction &txTo,unsigned int nIn)
|
||||
struct CClib_rpcinfo
|
||||
{
|
||||
uint8_t evalcode; int32_t height,from_mempool;
|
||||
if ( ASSETCHAINS_CCLIB != MYCCLIBNAME )
|
||||
{
|
||||
fprintf(stderr,"-ac_cclib=%s vs myname %s\n",ASSETCHAINS_CCLIB.c_str(),MYCCLIBNAME);
|
||||
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 )
|
||||
{
|
||||
return(true);
|
||||
}
|
||||
return eval->Invalid("cclib CC must have evalcode between 16 and 127");
|
||||
char *method,*help;
|
||||
int32_t numrequiredargs,maxargs; // frontloaded with required
|
||||
uint8_t funcid;
|
||||
}
|
||||
CClib_methods[] =
|
||||
{
|
||||
{ (char *)"faucet2_fund", (char *)"amount", 1, 1, 'F' },
|
||||
{ (char *)"faucet2_get", (char *)"<no args>", 0, 0, 'G' },
|
||||
};
|
||||
|
||||
std::string MYCCLIBNAME = (char *)"faucet2";
|
||||
|
||||
char *CClib_name() { return((char *)MYCCLIBNAME.c_str()); }
|
||||
|
||||
std::string CClib_rawtxgen(struct CCcontract_info *cp,uint8_t funcid,cJSON *params);
|
||||
|
||||
UniValue CClib_info(struct CCcontract_info *cp)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ),a(UniValue::VARR); int32_t i; char str[2];
|
||||
result.push_back(Pair("result","success"));
|
||||
result.push_back(Pair("CClib",CClib_name()));
|
||||
for (i=0; i<sizeof(CClib_methods)/sizeof(*CClib_methods); i++)
|
||||
{
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
if ( CClib_methods[i].funcid < ' ' || CClib_methods[i].funcid >= 128 )
|
||||
obj.push_back(Pair("funcid",CClib_methods[i].funcid));
|
||||
else
|
||||
{
|
||||
str[0] = CClib_methods[i].funcid;
|
||||
str[1] = 0;
|
||||
obj.push_back(Pair("funcid",str));
|
||||
}
|
||||
obj.push_back(Pair("name",CClib_methods[i].method));
|
||||
obj.push_back(Pair("help",CClib_methods[i].help));
|
||||
obj.push_back(Pair("params_required",CClib_methods[i].numrequiredargs));
|
||||
obj.push_back(Pair("params_max",CClib_methods[i].maxargs));
|
||||
a.push_back(obj);
|
||||
}
|
||||
result.push_back(Pair("methods",a));
|
||||
return(result);
|
||||
}
|
||||
|
||||
UniValue CClib(struct CCcontract_info *cp,char *method,cJSON *params)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ); int32_t i; std::string rawtx;
|
||||
for (i=0; i<sizeof(CClib_methods)/sizeof(*CClib_methods); i++)
|
||||
{
|
||||
if ( strcmp(method,CClib_methods[i].method) == 0 )
|
||||
{
|
||||
result.push_back(Pair("result","success"));
|
||||
result.push_back(Pair("method",CClib_methods[i].method));
|
||||
rawtx = CClib_rawtxgen(cp,CClib_methods[i].funcid,params);
|
||||
result.push_back(Pair("rawtx",rawtx));
|
||||
return(result);
|
||||
}
|
||||
}
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("method",CClib_methods[i].method));
|
||||
result.push_back(Pair("error","method not found"));
|
||||
return(result);
|
||||
}
|
||||
|
||||
int64_t IsCClibvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v)
|
||||
{
|
||||
char destaddr[64];
|
||||
if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 )
|
||||
{
|
||||
if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 )
|
||||
return(tx.vout[v].nValue);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
bool CClibExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee)
|
||||
{
|
||||
static uint256 zerohash;
|
||||
CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis;
|
||||
numvins = tx.vin.size();
|
||||
numvouts = tx.vout.size();
|
||||
for (i=0; i<numvins; i++)
|
||||
{
|
||||
//fprintf(stderr,"vini.%d\n",i);
|
||||
if ( (*cp->ismyvin)(tx.vin[i].scriptSig) != 0 )
|
||||
{
|
||||
//fprintf(stderr,"vini.%d check mempool\n",i);
|
||||
if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 )
|
||||
return eval->Invalid("cant find vinTx");
|
||||
else
|
||||
{
|
||||
//fprintf(stderr,"vini.%d check hash and vout\n",i);
|
||||
if ( hashBlock == zerohash )
|
||||
return eval->Invalid("cant faucet2 from mempool");
|
||||
if ( (assetoshis= IsCClibvout(cp,vinTx,tx.vin[i].prevout.n)) != 0 )
|
||||
inputs += assetoshis;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i=0; i<numvouts; i++)
|
||||
{
|
||||
//fprintf(stderr,"i.%d of numvouts.%d\n",i,numvouts);
|
||||
if ( (assetoshis= IsCClibvout(cp,tx,i)) != 0 )
|
||||
outputs += assetoshis;
|
||||
}
|
||||
if ( inputs != outputs+FAUCET2SIZE+txfee )
|
||||
{
|
||||
fprintf(stderr,"inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs);
|
||||
return eval->Invalid("mismatched inputs != outputs + FAUCET2SIZE + txfee");
|
||||
}
|
||||
else return(true);
|
||||
}
|
||||
|
||||
bool CClib_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx,unsigned int nIn)
|
||||
{
|
||||
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64];
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > txids;
|
||||
numvins = tx.vin.size();
|
||||
numvouts = tx.vout.size();
|
||||
preventCCvins = preventCCvouts = -1;
|
||||
if ( numvouts < 1 )
|
||||
return eval->Invalid("no vouts");
|
||||
else
|
||||
{
|
||||
for (i=0; i<numvins; i++)
|
||||
{
|
||||
if ( IsCCInput(tx.vin[0].scriptSig) == 0 )
|
||||
{
|
||||
fprintf(stderr,"faucetget invalid vini\n");
|
||||
return eval->Invalid("illegal normal vini");
|
||||
}
|
||||
}
|
||||
//fprintf(stderr,"check amounts\n");
|
||||
if ( CClibExactAmounts(cp,eval,tx,1,10000) == false )
|
||||
{
|
||||
fprintf(stderr,"faucetget invalid amount\n");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
preventCCvouts = 1;
|
||||
if ( IsCClibvout(cp,tx,0) != 0 )
|
||||
{
|
||||
preventCCvouts++;
|
||||
i = 1;
|
||||
} else i = 0;
|
||||
txid = tx.GetHash();
|
||||
memcpy(hash,&txid,sizeof(hash));
|
||||
fprintf(stderr,"check faucetget txid %s %02x/%02x\n",uint256_str(str,txid),hash[0],hash[31]);
|
||||
if ( tx.vout[i].nValue != FAUCET2SIZE )
|
||||
return eval->Invalid("invalid faucet output");
|
||||
else if ( (hash[0] & 0xff) != 0 || (hash[31] & 0xff) != 0 )
|
||||
return eval->Invalid("invalid faucetget txid");
|
||||
Getscriptaddress(destaddr,tx.vout[i].scriptPubKey);
|
||||
SetCCtxids(txids,destaddr);
|
||||
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=txids.begin(); it!=txids.end(); it++)
|
||||
{
|
||||
//int height = it->first.blockHeight;
|
||||
if ( CCduration(numblocks,it->first.txhash) > 0 && numblocks > 3 )
|
||||
{
|
||||
//fprintf(stderr,"would return error %s numblocks.%d ago\n",uint256_str(str,it->first.txhash),numblocks);
|
||||
return eval->Invalid("faucet2 is only for brand new addresses");
|
||||
}
|
||||
}
|
||||
retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts);
|
||||
if ( retval != 0 )
|
||||
fprintf(stderr,"faucet2get validated\n");
|
||||
else fprintf(stderr,"faucet2get invalid\n");
|
||||
return(retval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int64_t AddCClibInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs)
|
||||
{
|
||||
char coinaddr[64]; int64_t threshold,nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector<uint8_t> origpubkey; CTransaction vintx; int32_t vout,n = 0;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
GetCCaddress(cp,coinaddr,pk);
|
||||
SetCCunspents(unspentOutputs,coinaddr);
|
||||
threshold = total/(maxinputs+1);
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
{
|
||||
txid = it->first.txhash;
|
||||
vout = (int32_t)it->first.index;
|
||||
if ( it->second.satoshis < threshold )
|
||||
continue;
|
||||
//char str[65]; fprintf(stderr,"check %s/v%d %.8f`\n",uint256_str(str,txid),vout,(double)it->second.satoshis/COIN);
|
||||
// no need to prevent dup
|
||||
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
|
||||
{
|
||||
if ( (nValue= IsCClibvout(cp,vintx,vout)) > 1000000 && myIsutxo_spentinmempool(txid,vout) == 0 )
|
||||
{
|
||||
if ( total != 0 && maxinputs != 0 )
|
||||
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
|
||||
nValue = it->second.satoshis;
|
||||
totalinputs += nValue;
|
||||
n++;
|
||||
if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) )
|
||||
break;
|
||||
} else fprintf(stderr,"nValue too small or already spent in mempool\n");
|
||||
} else fprintf(stderr,"couldnt get tx\n");
|
||||
}
|
||||
return(totalinputs);
|
||||
}
|
||||
|
||||
|
||||
std::string Faucet2Fund(struct CCcontract_info *cp,uint64_t txfee,int64_t funds)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
CPubKey mypk,cclibpk; CScript opret;
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
cclibpk = GetUnspendable(cp,0);
|
||||
if ( AddNormalinputs(mtx,mypk,funds+txfee,64) > 0 )
|
||||
{
|
||||
mtx.vout.push_back(MakeCC1vout(cp->evalcode,funds,cclibpk));
|
||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret));
|
||||
}
|
||||
return("");
|
||||
}
|
||||
|
||||
/*UniValue FaucetInfo()
|
||||
{
|
||||
UniValue result(UniValue::VOBJ); char numstr[64];
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
CPubKey faucetpk; struct CCcontract_info *cp,C; int64_t funding;
|
||||
result.push_back(Pair("result","success"));
|
||||
result.push_back(Pair("name","Faucet"));
|
||||
cp = CCinit(&C,EVAL_FAUCET);
|
||||
faucetpk = GetUnspendable(cp,0);
|
||||
funding = AddFaucetInputs(cp,mtx,faucetpk,0,0);
|
||||
sprintf(numstr,"%.8f",(double)funding/COIN);
|
||||
result.push_back(Pair("funding",numstr));
|
||||
return(result);
|
||||
}*/
|
||||
|
||||
std::string CClib_rawtxgen(struct CCcontract_info *cp,uint8_t funcid,cJSON *params)
|
||||
{
|
||||
CMutableTransaction tmpmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
CPubKey mypk,cclibpk; int64_t funds,txfee=0,inputs,CCchange=0,nValue=FAUCET2SIZE; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash;
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
if ( funcid == 'F' )
|
||||
{
|
||||
if ( cJSON_GetArraySize(params) > 0 )
|
||||
{
|
||||
funds = (int64_t)jdouble(jitem(params,0),0)*COIN + 0.0000000049;
|
||||
return(Faucet2Fund(cp,0,funds));
|
||||
} else return("");
|
||||
}
|
||||
else if ( funcid != 'G' )
|
||||
return("");
|
||||
cclibpk = GetUnspendable(cp,0);
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
if ( (inputs= AddCClibInputs(cp,mtx,cclibpk,nValue+txfee,60)) > 0 )
|
||||
{
|
||||
if ( inputs > nValue )
|
||||
CCchange = (inputs - nValue - txfee);
|
||||
if ( CCchange != 0 )
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_FIRSTUSER,CCchange,cclibpk));
|
||||
mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
|
||||
fprintf(stderr,"start at %u\n",(uint32_t)time(NULL));
|
||||
j = rand() & 0xfffffff;
|
||||
for (i=0; i<1000000; i++,j++)
|
||||
{
|
||||
tmpmtx = mtx;
|
||||
rawhex = FinalizeCCTx(-1LL,cp,tmpmtx,mypk,txfee,CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_FIRSTUSER << (uint8_t)'G' << j));
|
||||
if ( (len= (int32_t)rawhex.size()) > 0 && len < 65536 )
|
||||
{
|
||||
len >>= 1;
|
||||
decode_hex(buf,len,(char *)rawhex.c_str());
|
||||
hash = bits256_doublesha256(0,buf,len);
|
||||
if ( (hash.bytes[0] & 0xff) == 0 && (hash.bytes[31] & 0xff) == 0 )
|
||||
{
|
||||
fprintf(stderr,"found valid txid after %d iterations %u\n",i,(uint32_t)time(NULL));
|
||||
return(rawhex);
|
||||
}
|
||||
//fprintf(stderr,"%02x%02x ",hash.bytes[0],hash.bytes[31]);
|
||||
}
|
||||
}
|
||||
fprintf(stderr,"couldnt generate valid txid %u\n",(uint32_t)time(NULL));
|
||||
return("");
|
||||
} else fprintf(stderr,"cant find faucet inputs\n");
|
||||
return("");
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
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("");
|
||||
}
|
||||
|
||||
@@ -520,25 +522,29 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
if (GetTransaction(opentxid,channelOpenTx,hashblock,false) == 0)
|
||||
{
|
||||
fprintf(stderr, "invalid channel open txid\n");
|
||||
return ("");
|
||||
CCerror = strprintf("invalid channel open txid");
|
||||
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 (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("");
|
||||
}
|
||||
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 ("");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "invalid channel open tx\n");
|
||||
CCerror = strprintf("invalid channel open tx");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return ("");
|
||||
}
|
||||
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)
|
||||
{
|
||||
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 ("");
|
||||
} else if (numpayments == 0)
|
||||
{
|
||||
fprintf(stderr,"invalid amount\n");
|
||||
CCerror = strprintf("invalid amount");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return ("");
|
||||
}
|
||||
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);
|
||||
if (gensecret!=hashchain)
|
||||
{
|
||||
fprintf(stderr,"invalid secret supplied\n");
|
||||
CCerror = strprintf("invalid secret supplied");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return("");
|
||||
}
|
||||
}
|
||||
@@ -592,7 +601,8 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"invalid previous tx\n");
|
||||
CCerror = strprintf("invalid previous tx");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return("");
|
||||
}
|
||||
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
|
||||
{
|
||||
fprintf(stderr,"error adding CC inputs\n");
|
||||
CCerror = strprintf("error adding CC inputs");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return("");
|
||||
}
|
||||
}
|
||||
fprintf(stderr,"error adding normal inputs\n");
|
||||
CCerror = strprintf("error adding normal inputs");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return("");
|
||||
}
|
||||
|
||||
@@ -629,36 +641,41 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid)
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
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 ("");
|
||||
}
|
||||
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 ("");
|
||||
}
|
||||
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("");
|
||||
}
|
||||
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));
|
||||
else mtx.vout.push_back(MakeCC1of2vout(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, mypk, destpub));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk));
|
||||
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
|
||||
{
|
||||
fprintf(stderr,"error adding CC inputs\n");
|
||||
CCerror = strprintf("error adding CC inputs");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return("");
|
||||
}
|
||||
}
|
||||
fprintf(stderr,"error adding normal inputs\n");
|
||||
CCerror = strprintf("error adding normal inputs");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return("");
|
||||
}
|
||||
|
||||
@@ -678,61 +695,72 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid)
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
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 ("");
|
||||
}
|
||||
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 ("");
|
||||
}
|
||||
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 ("");
|
||||
}
|
||||
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 ("");
|
||||
}
|
||||
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 ("");
|
||||
}
|
||||
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("");
|
||||
}
|
||||
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 &&
|
||||
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,destpub));
|
||||
if (tokenid!=zeroid) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS,funds-txfee,mypk));
|
||||
else mtx.vout.push_back(CTxOut(funds-txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
|
||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('R',tokenid,opentxid,mypk,destpub,param1,payment,closetxid)));
|
||||
if (tokenid!=zeroid) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS,funds,mypk));
|
||||
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,funds/payment,payment,closetxid)));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"previous tx is invalid\n");
|
||||
CCerror = strprintf("previous tx is invalid");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return("");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"error adding CC inputs\n");
|
||||
CCerror = strprintf("error adding CC inputs");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return("");
|
||||
}
|
||||
}
|
||||
CCerror = strprintf("error adding normal inputs");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return("");
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -20,18 +20,18 @@
|
||||
#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.
|
||||
|
||||
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.
|
||||
|
||||
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 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.
|
||||
*/
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
bits256 zeroid;
|
||||
|
||||
@@ -331,7 +331,7 @@ cJSON *get_komodocli(char *refcoin,char **retstrp,char *acname,char *method,char
|
||||
system(cmdstr);
|
||||
*retstrp = 0;
|
||||
if ( (jsonstr= filestr(&fsize,fname)) != 0 )
|
||||
{
|
||||
{
|
||||
jsonstr[strlen(jsonstr)-1]='\0';
|
||||
//fprintf(stderr,"%s -> jsonstr.(%s)\n",cmdstr,jsonstr);
|
||||
if ( (jsonstr[0] != '{' && jsonstr[0] != '[') || (retjson= cJSON_Parse(jsonstr)) == 0 )
|
||||
@@ -599,13 +599,13 @@ int32_t validateaddress(char *refcoin,char *acname,char *depositaddr, char* comp
|
||||
cJSON *retjson; char *retstr; int32_t res=0;
|
||||
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"validateaddress",depositaddr,"","","")) != 0 )
|
||||
{
|
||||
if (is_cJSON_True(jobj(retjson,compare)) != 0 ) res=1;
|
||||
if (is_cJSON_True(jobj(retjson,compare)) != 0 ) res=1;
|
||||
free_json(retjson);
|
||||
}
|
||||
else if ( retstr != 0 )
|
||||
{
|
||||
fprintf(stderr,"validateaddress.(%s) %s error.(%s)\n",refcoin,acname,retstr);
|
||||
free(retstr);
|
||||
free(retstr);
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
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;
|
||||
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"z_exportkey",zaddr,"","","")) != 0 )
|
||||
{
|
||||
fprintf(stderr,"z_exportkey.(%s) %s returned json!\n",refcoin,acname);
|
||||
free_json(retjson);
|
||||
return(-1);
|
||||
}
|
||||
else if ( retstr != 0 )
|
||||
{
|
||||
//printf("retstr %s -> %.8f\n",retstr,dstr(amount));
|
||||
strcpy(privkey,retstr);
|
||||
free(retstr);
|
||||
retval = 0;
|
||||
return(0);
|
||||
}
|
||||
return(retval);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
cJSON *array; int32_t n;
|
||||
@@ -872,7 +922,7 @@ int32_t tx_has_voutaddress(char *refcoin,char *acname,bits256 txid,char *coinadd
|
||||
if ( (vouts= jarray(&numarray,txobj,"vout")) != 0 )
|
||||
{
|
||||
for (i=0; i<numarray; i++)
|
||||
{
|
||||
{
|
||||
if ((vout = jitem(vouts,i)) !=0 && (sobj= jobj(vout,"scriptPubKey")) != 0 )
|
||||
{
|
||||
if ( (addresses= jarray(&n,sobj,"addresses")) != 0 )
|
||||
@@ -893,7 +943,7 @@ int32_t tx_has_voutaddress(char *refcoin,char *acname,bits256 txid,char *coinadd
|
||||
}
|
||||
}
|
||||
// if (hasvout==1 && (vins=jarray(&numarray,txobj,"vin"))!=0)
|
||||
// {
|
||||
// {
|
||||
// for (int i=0;i<numarray;i++)
|
||||
// {
|
||||
// if ((vin=jitem(vins,i))!=0 && validateaddress(refcoin,acname,jstr(vin,"address"),"ismine")!=0)
|
||||
@@ -901,7 +951,7 @@ int32_t tx_has_voutaddress(char *refcoin,char *acname,bits256 txid,char *coinadd
|
||||
// retval=1;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
free_json(txobj);
|
||||
}
|
||||
|
||||
1697
src/cc/heir.cpp
1697
src/cc/heir.cpp
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -94,7 +94,7 @@ uint8_t DecodeMaramaraCoinbaseOpRet(const CScript scriptPubKey,CPubKey &pk,int32
|
||||
{
|
||||
return(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());
|
||||
return(0);
|
||||
}
|
||||
@@ -255,6 +255,22 @@ int32_t MarmaraValidateCoinbase(int32_t height,CTransaction tx)
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else if ( funcid == 'C' ) // coinbase
|
||||
{
|
||||
return(true);
|
||||
}
|
||||
// staking only for locked utxo
|
||||
}
|
||||
return eval->Invalid("fall through error");
|
||||
@@ -476,7 +496,7 @@ UniValue MarmaraLock(uint64_t txfee,int64_t amount,int32_t height)
|
||||
else
|
||||
{
|
||||
result.push_back(Pair("result",(char *)"success"));
|
||||
result.push_back(Pair("rawtx",rawtx));
|
||||
result.push_back(Pair("hex",rawtx));
|
||||
return(result);
|
||||
}
|
||||
} else errorstr = (char *)"insufficient funds";
|
||||
@@ -485,7 +505,34 @@ UniValue MarmaraLock(uint64_t txfee,int64_t amount,int32_t height)
|
||||
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)
|
||||
{
|
||||
@@ -553,7 +600,7 @@ UniValue MarmaraSettlement(uint64_t txfee,uint256 refbatontxid)
|
||||
mtx.vout.push_back(MakeCC1of2vout(EVAL_MARMARA,change,Marmarapk,pk));
|
||||
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraLoopOpret('S',createtxid,mypk,0,refmatures,currency),pubkeys);
|
||||
result.push_back(Pair("result",(char *)"success"));
|
||||
result.push_back(Pair("rawtx",rawtx));
|
||||
result.push_back(Pair("hex",rawtx));
|
||||
return(result);
|
||||
} else remaining -= inputsum;
|
||||
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);
|
||||
result.push_back(Pair("result",(char *)"error"));
|
||||
result.push_back(Pair("error",(char *)"insufficient funds"));
|
||||
result.push_back(Pair("rawtx",rawtx));
|
||||
result.push_back(Pair("hex",rawtx));
|
||||
result.push_back(Pair("remaining",ValueFromAmount(remaining)));
|
||||
}
|
||||
else
|
||||
@@ -684,7 +731,7 @@ UniValue MarmaraReceive(uint64_t txfee,CPubKey senderpk,int64_t amount,std::stri
|
||||
else
|
||||
{
|
||||
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("createtxid",createtxid.GetHex()));
|
||||
if ( batontxid != zeroid )
|
||||
@@ -740,7 +787,7 @@ UniValue MarmaraIssue(uint64_t txfee,uint8_t funcid,CPubKey receiverpk,int64_t a
|
||||
else
|
||||
{
|
||||
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;
|
||||
result.push_back(Pair("funcid",str));
|
||||
result.push_back(Pair("createtxid",createtxid.GetHex()));
|
||||
@@ -978,7 +1025,7 @@ UniValue MarmaraPoolPayout(uint64_t txfee,int32_t firstheight,double perc,char *
|
||||
else
|
||||
{
|
||||
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 )
|
||||
{
|
||||
result.push_back(Pair("firstheight",firstheight));
|
||||
|
||||
@@ -115,6 +115,7 @@ enum BlockStatus: uint32_t {
|
||||
BLOCK_FAILED_MASK = BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD,
|
||||
|
||||
BLOCK_ACTIVATES_UPGRADE = 128, //! block activates a network upgrade
|
||||
BLOCK_IN_TMPFILE = 256
|
||||
};
|
||||
|
||||
//! Short-hand for the highest consensus validity we implement.
|
||||
@@ -350,7 +351,7 @@ public:
|
||||
nSolution = block.nSolution;
|
||||
}
|
||||
|
||||
int32_t SetHeight(int32_t height)
|
||||
void SetHeight(int32_t height)
|
||||
{
|
||||
this->chainPower.nHeight = height;
|
||||
}
|
||||
|
||||
@@ -92,11 +92,6 @@ static CBlock CreateGenesisBlock(uint32_t nTime, const uint256& nNonce, const st
|
||||
void *chainparams_commandline(void *ptr);
|
||||
#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"));
|
||||
|
||||
@@ -230,11 +225,32 @@ void CChainParams::SetCheckpointData(CChainParams::CCheckpointData checkpointDat
|
||||
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);
|
||||
if ( height <= 0 || (mainParams.consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight > 0 && height >= mainParams.consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight) )
|
||||
return(4096 * 1024);
|
||||
if ( height <= 0 || (saplinght > 0 && height >= saplinght) )
|
||||
{
|
||||
return(_MAX_BLOCK_SIZE);
|
||||
}
|
||||
else return(2000000);
|
||||
}
|
||||
|
||||
|
||||
@@ -130,8 +130,8 @@ struct Params {
|
||||
int64_t AveragingWindowTimespan() const { return nPowAveragingWindow * nPowTargetSpacing; }
|
||||
int64_t MinActualTimespan() const { return (AveragingWindowTimespan() * (100 - nPowMaxAdjustUp )) / 100; }
|
||||
int64_t MaxActualTimespan() const { return (AveragingWindowTimespan() * (100 + nPowMaxAdjustDown)) / 100; }
|
||||
int32_t SetSaplingHeight(int32_t height) { vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = height; }
|
||||
int32_t SetOverwinterHeight(int32_t height) { vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = height; }
|
||||
void SetSaplingHeight(int32_t height) { vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = height; }
|
||||
void SetOverwinterHeight(int32_t height) { vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = height; }
|
||||
uint256 nMinimumChainWork;
|
||||
};
|
||||
} // namespace Consensus
|
||||
|
||||
@@ -86,6 +86,7 @@ class CVerusHashV2
|
||||
result = buf2;
|
||||
curPos = 0;
|
||||
std::fill(buf1, buf1 + sizeof(buf1), 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); }
|
||||
|
||||
17
src/komodo.h
17
src/komodo.h
@@ -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);
|
||||
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);
|
||||
if (RemoveOrphanedBlocks(*notarizedheightp))
|
||||
{
|
||||
//fprintf(stderr, "Sucessfully removed all known orphaned blocks before height %d\n",*notarizedheightp);
|
||||
}
|
||||
if ( ASSETCHAINS_SYMBOL[0] == 0 )
|
||||
{
|
||||
if ( signedfp == 0 )
|
||||
@@ -947,12 +951,15 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ((signedmask & 1) != 0 && numvalid >= KOMODO_MINRATIFY) || bitweight(signedmask) > (numnotaries/3) )
|
||||
if ( ASSETCHAINS_SYMBOL[0] != 0 || height < 100000 )
|
||||
{
|
||||
memset(&txhash,0,sizeof(txhash));
|
||||
komodo_stateupdate(height,pubkeys,numvalid,0,txhash,0,0,0,0,0,0,0,0,0,0,zero,0);
|
||||
printf("RATIFIED! >>>>>>>>>> new notaries.%d newheight.%d from height.%d\n",numvalid,(((height+KOMODO_ELECTION_GAP/2)/KOMODO_ELECTION_GAP)+1)*KOMODO_ELECTION_GAP,height);
|
||||
} else printf("signedmask.%llx numvalid.%d wt.%d numnotaries.%d\n",(long long)signedmask,numvalid,bitweight(signedmask),numnotaries);
|
||||
if ( ((signedmask & 1) != 0 && numvalid >= KOMODO_MINRATIFY) || bitweight(signedmask) > (numnotaries/3) )
|
||||
{
|
||||
memset(&txhash,0,sizeof(txhash));
|
||||
komodo_stateupdate(height,pubkeys,numvalid,0,txhash,0,0,0,0,0,0,0,0,0,0,zero,0);
|
||||
printf("RATIFIED! >>>>>>>>>> new notaries.%d newheight.%d from height.%d\n",numvalid,(((height+KOMODO_ELECTION_GAP/2)/KOMODO_ELECTION_GAP)+1)*KOMODO_ELECTION_GAP,height);
|
||||
} else printf("signedmask.%llx numvalid.%d wt.%d numnotaries.%d\n",(long long)signedmask,numvalid,bitweight(signedmask),numnotaries);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -557,9 +557,9 @@ uint64_t komodo_seed(int32_t height)
|
||||
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;
|
||||
if (!GetTransaction(hash, tx,
|
||||
#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);
|
||||
return(0);
|
||||
}
|
||||
numvouts = tx.vout.size();
|
||||
//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;
|
||||
opret = tx.vout[numvouts-1].scriptPubKey;
|
||||
if (ExtractDestination(tx.vout[n].scriptPubKey, address))
|
||||
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 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 )
|
||||
{
|
||||
txid = pblock->vtx[n-1].vin[0].prevout.hash;
|
||||
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) )
|
||||
{
|
||||
strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str());
|
||||
@@ -634,27 +636,41 @@ int32_t komodo_WhoStaked(CBlock *pblock, CTxDestination &addressout)
|
||||
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 ( (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;
|
||||
vout = pblock->vtx[n-1].vin[0].prevout.n;
|
||||
if ( ASSETCHAINS_MARMARA != 0 )
|
||||
{
|
||||
// need to verify it was signed by the non-Marmarapk of the 1of2
|
||||
}
|
||||
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) )
|
||||
{
|
||||
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");
|
||||
return(1);
|
||||
if ( ASSETCHAINS_MARMARA == 0 )
|
||||
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)
|
||||
{
|
||||
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 ( 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;
|
||||
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) )
|
||||
{
|
||||
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;
|
||||
if ( pindex != 0 && pindex->segid >= -1 )
|
||||
{
|
||||
//fprintf(stderr,"isPoSblock segid.%d\n",pindex->segid);
|
||||
if ( pindex->segid == -1 )
|
||||
return(0);
|
||||
else return(1);
|
||||
}
|
||||
txn_count = pblock->vtx.size();
|
||||
if ( txn_count > 1 && pblock->vtx[txn_count-1].vin.size() == 1 && pblock->vtx[txn_count-1].vout.size() == 1 )
|
||||
//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);
|
||||
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;
|
||||
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 *)"");
|
||||
}
|
||||
@@ -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 ( komodo_isPoS(pblock) != 0 )
|
||||
if ( komodo_isPoS(pblock,height) != 0 )
|
||||
isPoS = 1;
|
||||
}
|
||||
if ( slowflag != 0 && isPoS != 0 )
|
||||
@@ -1812,6 +1830,7 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
|
||||
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 ( (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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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()];
|
||||
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;
|
||||
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;
|
||||
lasttime = 0;
|
||||
}
|
||||
if ( ASSETCHAINS_MARMARA == 0 || 1 )
|
||||
if ( ASSETCHAINS_MARMARA == 0 )
|
||||
{
|
||||
BOOST_FOREACH(const COutput& out, vecOutputs)
|
||||
{
|
||||
@@ -2149,8 +2173,29 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
|
||||
}
|
||||
else
|
||||
{
|
||||
// calc 1of2 address
|
||||
// iterate all unspents not spent in mempool and komodo_addutxo
|
||||
struct CCcontract_info *cp,C; uint256 txid; int32_t vout,ht,unlockht; CAmount nValue; char coinaddr[64]; CPubKey mypk,Marmarapk,pk;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
cp = CCinit(&C,EVAL_MARMARA);
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
Marmarapk = GetUnspendable(cp,0);
|
||||
GetCCaddress1of2(cp,coinaddr,Marmarapk,mypk);
|
||||
SetCCunspents(unspentOutputs,coinaddr);
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
{
|
||||
txid = it->first.txhash;
|
||||
vout = (int32_t)it->first.index;
|
||||
if ( (nValue= it->second.satoshis) < COIN )
|
||||
continue;
|
||||
if ( GetTransaction(txid,tx,hashBlock,true) != 0 && (pindex= komodo_getblockindex(hashBlock)) != 0 && myIsutxo_spentinmempool(txid,vout) == 0 )
|
||||
{
|
||||
const CScript &scriptPubKey = tx.vout[vout].scriptPubKey;
|
||||
if ( DecodeMaramaraCoinbaseOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,pk,ht,unlockht) != 0 && pk == mypk )
|
||||
{
|
||||
array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,txid,vout,coinaddr,hashbuf,(CScript)scriptPubKey);
|
||||
}
|
||||
// else fprintf(stderr,"SKIP addutxo %.8f numkp.%d vs max.%d\n",(double)nValue/COIN,numkp,maxkp);
|
||||
}
|
||||
}
|
||||
}
|
||||
lasttime = (uint32_t)time(NULL);
|
||||
//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.nLockTime = earliest;
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
// add opreturn
|
||||
// signSuccess = CCFinalizetx(...)
|
||||
}
|
||||
if (!signSuccess)
|
||||
fprintf(stderr,"failed to create signature\n");
|
||||
else
|
||||
{
|
||||
UpdateTransaction(txNew,0,sigdata);
|
||||
ptr = (uint8_t *)&sigdata.scriptSig[0];
|
||||
siglen = sigdata.scriptSig.size();
|
||||
for (i=0; i<siglen; 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,"best %u from %u, gap %d lag.%d\n",earliest,*blocktimep,(int32_t)(earliest - *blocktimep),(int32_t)(time(NULL) - *blocktimep));
|
||||
*blocktimep = earliest;
|
||||
|
||||
@@ -36,5 +36,43 @@
|
||||
|
||||
extern uint8_t ASSETCHAINS_TXPOW,ASSETCHAINS_PUBLIC;
|
||||
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
|
||||
|
||||
@@ -1654,7 +1654,7 @@ extern int64_t MAX_MONEY;
|
||||
void komodo_args(char *argv0)
|
||||
{
|
||||
extern const char *Notaries_elected1[][2];
|
||||
std::string name,addn; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[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);
|
||||
memset(ccenables,0,sizeof(ccenables));
|
||||
memset(disablebits,0,sizeof(disablebits));
|
||||
@@ -1704,7 +1704,6 @@ void komodo_args(char *argv0)
|
||||
KOMODO_STOPAT = GetArg("-stopat",0);
|
||||
MAX_REORG_LENGTH = GetArg("-maxreorg",MAX_REORG_LENGTH);
|
||||
WITNESS_CACHE_SIZE = MAX_REORG_LENGTH+10;
|
||||
|
||||
ASSETCHAINS_CC = GetArg("-ac_cc",0);
|
||||
KOMODO_CCACTIVATE = GetArg("-ac_ccactivate",0);
|
||||
ASSETCHAINS_PUBLIC = GetArg("-ac_public",0);
|
||||
|
||||
185
src/main.cpp
185
src/main.cpp
@@ -76,6 +76,7 @@ using namespace std;
|
||||
* Global state
|
||||
*/
|
||||
|
||||
#define TMPFILE_START 100000000
|
||||
CCriticalSection cs_main;
|
||||
extern uint8_t NOTARY_PUBKEY33[33];
|
||||
extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN,KOMODO_INSYNC,KOMODO_CONNECTING,KOMODO_EXTRASATOSHI;
|
||||
@@ -182,8 +183,9 @@ namespace {
|
||||
multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked;
|
||||
|
||||
CCriticalSection cs_LastBlockFile;
|
||||
std::vector<CBlockFileInfo> vinfoBlockFile;
|
||||
std::vector<CBlockFileInfo> vinfoBlockFile,tmpBlockFiles;
|
||||
int nLastBlockFile = 0;
|
||||
int nLastTmpFile = 0;
|
||||
/** Global flag to indicate we should check to see if there are
|
||||
* block/undo files that should be deleted. Set on startup
|
||||
* 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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
CCoins coins;
|
||||
@@ -2126,7 +2195,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
|
||||
// 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
|
||||
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 nTimeCallbacks = 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)
|
||||
{
|
||||
CDiskBlockPos blockPos;
|
||||
const CChainParams& chainparams = Params();
|
||||
if ( KOMODO_STOPAT != 0 && pindex->GetHeight() > KOMODO_STOPAT )
|
||||
return(false);
|
||||
@@ -3189,6 +3261,21 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||
return false;
|
||||
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
|
||||
uint256 hashPrevBlock = pindex->pprev == NULL ? uint256() : pindex->pprev->GetBlockHash();
|
||||
if ( hashPrevBlock != view.GetBestBlock() )
|
||||
@@ -3806,7 +3893,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
|
||||
CValidationState stateDummy;
|
||||
|
||||
// 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);
|
||||
}
|
||||
@@ -3837,7 +3924,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
|
||||
{
|
||||
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_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());
|
||||
}
|
||||
@@ -3853,7 +3940,8 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
|
||||
|
||||
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 )
|
||||
{
|
||||
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);
|
||||
ASSETCHAINS_SAPLING = activation;
|
||||
}
|
||||
return activation;
|
||||
}
|
||||
|
||||
static int64_t nTimeReadFromDisk = 0;
|
||||
@@ -4483,43 +4572,57 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
|
||||
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);
|
||||
|
||||
unsigned int nFile = fKnown ? pos.nFile : nLastBlockFile;
|
||||
if (vinfoBlockFile.size() <= nFile) {
|
||||
vinfoBlockFile.resize(nFile + 1);
|
||||
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) {
|
||||
vinfoBlockFile.resize(nFile + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!fKnown) {
|
||||
while (vinfoBlockFile[nFile].nSize + nAddSize >= MAX_BLOCKFILE_SIZE) {
|
||||
while ((*ptr)[nFile].nSize + nAddSize >= MAX_BLOCKFILE_SIZE) {
|
||||
nFile++;
|
||||
if (vinfoBlockFile.size() <= nFile) {
|
||||
vinfoBlockFile.resize(nFile + 1);
|
||||
if ((*ptr).size() <= nFile) {
|
||||
(*ptr).resize(nFile + 1);
|
||||
}
|
||||
}
|
||||
pos.nFile = nFile;
|
||||
pos.nPos = vinfoBlockFile[nFile].nSize;
|
||||
pos.nFile = nFile + tmpflag*TMPFILE_START;
|
||||
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) {
|
||||
LogPrintf("Leaving block file %i: %s\n", nFile, vinfoBlockFile[nFile].ToString());
|
||||
LogPrintf("Leaving block file %i: %s\n", nFile, (*ptr)[nFile].ToString());
|
||||
}
|
||||
FlushBlockFile(!fKnown);
|
||||
nLastBlockFile = nFile;
|
||||
*lastfilep = nFile;
|
||||
}
|
||||
|
||||
vinfoBlockFile[nFile].AddBlock(nHeight, nTime);
|
||||
(*ptr)[nFile].AddBlock(nHeight, nTime);
|
||||
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
|
||||
vinfoBlockFile[nFile].nSize += nAddSize;
|
||||
(*ptr)[nFile].nSize += nAddSize;
|
||||
|
||||
if (!fKnown) {
|
||||
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 (fPruneMode)
|
||||
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;
|
||||
}
|
||||
|
||||
bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize)
|
||||
{
|
||||
pos.nFile = nFile;
|
||||
|
||||
std::vector<CBlockFileInfo> *ptr; int *lastfilep;
|
||||
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;
|
||||
pos.nPos = vinfoBlockFile[nFile].nUndoSize;
|
||||
nNewSize = vinfoBlockFile[nFile].nUndoSize += nAddSize;
|
||||
pos.nPos = (*ptr)[nFile].nUndoSize;
|
||||
nNewSize = (*ptr)[nFile].nUndoSize += nAddSize;
|
||||
setDirtyFileInfo.insert(nFile);
|
||||
|
||||
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;
|
||||
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());
|
||||
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);
|
||||
//fprintf(stderr,"now its valid\n");
|
||||
}
|
||||
else
|
||||
else*/
|
||||
{
|
||||
if (blockhdr.GetBlockTime() < GetAdjustedTime() + 600)
|
||||
if (blockhdr.GetBlockTime() < GetAdjustedTime() + 300)
|
||||
*futureblockp = 1;
|
||||
//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");
|
||||
@@ -4734,7 +4844,7 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C
|
||||
CValidationState state;
|
||||
CTransaction Tx;
|
||||
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;
|
||||
Tx = tx;
|
||||
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();
|
||||
int32_t usetmp = 0;
|
||||
// Write block to history file
|
||||
try {
|
||||
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
|
||||
CDiskBlockPos blockPos;
|
||||
if (dbp != NULL)
|
||||
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");
|
||||
if (dbp == NULL)
|
||||
if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart()))
|
||||
AbortNode(state, "Failed to write block");
|
||||
if (!ReceivedBlockTransactions(block, state, pindex, blockPos))
|
||||
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) {
|
||||
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)
|
||||
{
|
||||
static int32_t didinit[64];
|
||||
static int32_t didinit[256];
|
||||
if (pos.IsNull())
|
||||
return NULL;
|
||||
boost::filesystem::path path = GetBlockPosFilename(pos, prefix);
|
||||
@@ -5572,6 +5685,7 @@ bool static LoadBlockIndexDB()
|
||||
// Load block file info
|
||||
pblocktree->ReadLastBlockFile(nLastBlockFile);
|
||||
vinfoBlockFile.resize(nLastBlockFile + 1);
|
||||
tmpBlockFiles.resize(nLastTmpFile + 1);
|
||||
LogPrintf("%s: last block file = %i\n", __func__, nLastBlockFile);
|
||||
for (int nFile = 0; nFile <= nLastBlockFile; nFile++) {
|
||||
pblocktree->ReadBlockFileInfo(nFile, vinfoBlockFile[nFile]);
|
||||
@@ -5595,7 +5709,6 @@ bool static LoadBlockIndexDB()
|
||||
if (pindex->nStatus & BLOCK_HAVE_DATA) {
|
||||
setBlkDataFiles.insert(pindex->nFile);
|
||||
}
|
||||
//komodo_pindex_init(pindex,(int32_t)pindex->GetHeight());
|
||||
}
|
||||
//fprintf(stderr,"load blockindexDB %u\n",(uint32_t)time(NULL));
|
||||
for (std::set<int>::iterator it = setBlkDataFiles.begin(); it != setBlkDataFiles.end(); it++)
|
||||
@@ -5936,6 +6049,7 @@ void UnloadBlockIndex()
|
||||
nSyncStarted = 0;
|
||||
mapBlocksUnlinked.clear();
|
||||
vinfoBlockFile.clear();
|
||||
tmpBlockFiles.clear();
|
||||
nLastBlockFile = 0;
|
||||
nBlockSequenceId = 1;
|
||||
mapBlockSource.clear();
|
||||
@@ -5971,6 +6085,7 @@ bool LoadBlockIndex()
|
||||
bool InitBlockIndex() {
|
||||
const CChainParams& chainparams = Params();
|
||||
LOCK(cs_main);
|
||||
tmpBlockFiles.clear();
|
||||
|
||||
// Initialize global variables that cannot be constructed at startup.
|
||||
recentRejects.reset(new CRollingBloomFilter(120000, 0.000001));
|
||||
@@ -6003,7 +6118,7 @@ bool InitBlockIndex() {
|
||||
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
|
||||
CDiskBlockPos blockPos;
|
||||
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");
|
||||
if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart()))
|
||||
return error("LoadBlockIndex(): writing genesis block to disk failed");
|
||||
|
||||
@@ -78,7 +78,7 @@ static const bool DEFAULT_ALERTS = true;
|
||||
/** Minimum alert priority for enabling safe mode. */
|
||||
static const int ALERT_PRIORITY_SAFE_MODE = 4000;
|
||||
/** 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 */
|
||||
static const unsigned int MAX_P2SH_SIGOPS = 15;
|
||||
/** 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);
|
||||
|
||||
/** 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 CBlockIndex* pindex,bool checkPOW);
|
||||
|
||||
bool RemoveOrphanedBlocks(int32_t notarized_height);
|
||||
|
||||
/** Functions for validating blocks and updating the block tree */
|
||||
|
||||
|
||||
@@ -39,8 +39,7 @@
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
|
||||
extern uint64_t ASSETCHAINS_TIMELOCKGTE;
|
||||
extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH;
|
||||
#include "komodo_defs.h"
|
||||
int64_t komodo_block_unlocktime(uint32_t nHeight);
|
||||
|
||||
void AtomicTimer::start()
|
||||
|
||||
@@ -132,17 +132,8 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams,
|
||||
#include "komodo_defs.h"
|
||||
|
||||
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);
|
||||
|
||||
extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_MARMARA;
|
||||
uint32_t Mining_start,Mining_height;
|
||||
int32_t My_notaryid = -1;
|
||||
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(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);
|
||||
|
||||
if (ASSETCHAINS_LWMAPOS != 0)
|
||||
@@ -521,7 +512,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
|
||||
pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txStaked));
|
||||
nFees += txfees;
|
||||
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");
|
||||
}
|
||||
// Create coinbase tx
|
||||
@@ -1405,6 +1396,8 @@ void static BitcoinMiner_noeq()
|
||||
miningTimer.stop();
|
||||
}
|
||||
|
||||
int32_t gotinvalid;
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
void static BitcoinMiner(CWallet *pwallet)
|
||||
#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);
|
||||
}
|
||||
}
|
||||
gotinvalid = 0;
|
||||
while (true)
|
||||
{
|
||||
/*if ( KOMODO_INSYNC == 0 )
|
||||
{
|
||||
KOMODO_LONGESTCHAIN = komodo_longestchain();
|
||||
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);
|
||||
}*/
|
||||
//fprintf(stderr,"gotinvalid.%d\n",gotinvalid);
|
||||
if ( gotinvalid != 0 )
|
||||
break;
|
||||
komodo_longestchain();
|
||||
// Hash state
|
||||
KOMODO_CHOSEN_ONE = 0;
|
||||
@@ -1716,6 +1705,7 @@ void static BitcoinMiner()
|
||||
for (z=31; z>=0; z--)
|
||||
fprintf(stderr,"%02x",((uint8_t *)&h)[z]);
|
||||
fprintf(stderr," Invalid block mined, try again\n");
|
||||
gotinvalid = 1;
|
||||
return(false);
|
||||
}
|
||||
KOMODO_CHOSEN_ONE = 1;
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "sync.h"
|
||||
#include "uint256.h"
|
||||
#include "utilstrencodings.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <deque>
|
||||
#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. */
|
||||
static const unsigned int MAX_ADDR_TO_SEND = 1000;
|
||||
/** 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 */
|
||||
static const unsigned int MAX_SUBVERSION_LENGTH = 256;
|
||||
/** -listen default */
|
||||
|
||||
@@ -37,9 +37,8 @@
|
||||
#endif // ENABLE_RUST
|
||||
uint32_t komodo_chainactive_timestamp();
|
||||
|
||||
extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH, ASSETCHAINS_STAKED;
|
||||
extern char ASSETCHAINS_SYMBOL[65];
|
||||
extern int32_t ASSETCHAINS_LWMAPOS,VERUS_BLOCK_POSUNITS, VERUS_CONSECUTIVE_POS_THRESHOLD, VERUS_NOPOS_THRESHHOLD;
|
||||
#include "komodo_defs.h"
|
||||
|
||||
unsigned int lwmaGetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params);
|
||||
unsigned int lwmaCalculateNextWorkRequired(const CBlockIndex* pindexLast, const Consensus::Params& params);
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
#include "tinyformat.h"
|
||||
#include "utilstrencodings.h"
|
||||
#include "crypto/common.h"
|
||||
#include "komodo_defs.h"
|
||||
|
||||
extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH;
|
||||
|
||||
// default hash algorithm for block
|
||||
uint256 (CBlockHeader::*CBlockHeader::hashFunction)() const = &CBlockHeader::GetSHA256DHash;
|
||||
|
||||
@@ -48,10 +48,8 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
extern int32_t ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH, ASSETCHAINS_LWMAPOS;
|
||||
extern uint64_t ASSETCHAINS_STAKED;
|
||||
extern int32_t KOMODO_MININGTHREADS;
|
||||
extern bool VERUS_MINTBLOCKS;
|
||||
#include "komodo_defs.h"
|
||||
|
||||
arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc);
|
||||
|
||||
/**
|
||||
|
||||
@@ -77,7 +77,8 @@ int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heig
|
||||
extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT;
|
||||
extern uint32_t ASSETCHAINS_CC;
|
||||
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 uint64_t ASSETCHAINS_ENDSUBSIDY[],ASSETCHAINS_REWARD[],ASSETCHAINS_HALVING[],ASSETCHAINS_DECAY[];
|
||||
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)
|
||||
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("halving", acHalving));
|
||||
obj.push_back(Pair("decay", acDecay));
|
||||
|
||||
@@ -463,6 +463,10 @@ static const CRPCCommand vRPCCommands[] =
|
||||
// Payments
|
||||
{ "payments", "paymentsaddress", &paymentsaddress, true },
|
||||
|
||||
{ "CClib", "cclibaddress", &cclibaddress, true },
|
||||
{ "CClib", "cclibinfo", &cclibinfo, true },
|
||||
{ "CClib", "cclib", &cclib, true },
|
||||
|
||||
// Gateways
|
||||
{ "gateways", "gatewaysaddress", &gatewaysaddress, true },
|
||||
{ "gateways", "gatewayslist", &gatewayslist, true },
|
||||
@@ -533,6 +537,9 @@ static const CRPCCommand vRPCCommands[] =
|
||||
{ "util", "reconsiderblock", &reconsiderblock, true },
|
||||
/* Not shown in help */
|
||||
{ "hidden", "setmocktime", &setmocktime, true },
|
||||
{ "hidden", "test_ac", &test_ac, true },
|
||||
{ "hidden", "test_heirmarker", &test_heirmarker, true },
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
/* Wallet */
|
||||
{ "wallet", "resendwallettransactions", &resendwallettransactions, true},
|
||||
|
||||
@@ -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_lock(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 gatewayslist(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 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
|
||||
|
||||
@@ -45,14 +45,14 @@ bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig,
|
||||
key = *pprivKey;
|
||||
else if (!keystore || !keystore->GetKey(address, key))
|
||||
return false;
|
||||
|
||||
|
||||
uint256 hash;
|
||||
try {
|
||||
hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, consensusBranchId);
|
||||
} catch (logic_error ex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (scriptCode.IsPayToCryptoCondition())
|
||||
{
|
||||
CC *cc = (CC *)extraData;
|
||||
@@ -75,9 +75,9 @@ bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig,
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
vchSig.push_back((unsigned char)nHashType);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ std::vector<CCcontract_info> &GetCryptoConditions()
|
||||
static bool initialized = false;
|
||||
static std::vector<CCcontract_info> vCC = std::vector<CCcontract_info>();
|
||||
CCcontract_info C;
|
||||
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
// this should initialize any desired auto-signed crypto-conditions
|
||||
@@ -140,7 +140,7 @@ bool GetCCByUnspendableAddress(struct CCcontract_info *cp, char *addrstr)
|
||||
{
|
||||
std::vector<CCcontract_info> &vCC = GetCryptoConditions();
|
||||
bool found = false;
|
||||
|
||||
|
||||
for (int i = 0; i < vCC.size(); i++)
|
||||
{
|
||||
if (strcmp(addrstr, vCC[i].unspendableCCaddr) == 0)
|
||||
@@ -157,7 +157,7 @@ bool CCinitLite(struct CCcontract_info *cp, uint8_t evalcode)
|
||||
{
|
||||
std::vector<CCcontract_info> &vCC = GetCryptoConditions();
|
||||
bool found = false;
|
||||
|
||||
|
||||
for (int i = 0; i < vCC.size(); i++)
|
||||
{
|
||||
if (vCC[i].evalcode == evalcode)
|
||||
@@ -172,7 +172,7 @@ bool CCinitLite(struct CCcontract_info *cp, uint8_t evalcode)
|
||||
|
||||
bool _Getscriptaddress(char *destaddr, const CScript &scriptPubKey)
|
||||
{
|
||||
CTxDestination address;
|
||||
CTxDestination address;
|
||||
txnouttype whichType;
|
||||
std::vector<std::vector<unsigned char>> vvch = std::vector<std::vector<unsigned char>>();
|
||||
if (Solver(scriptPubKey, whichType, vvch) && vvch[0].size() == 20)
|
||||
@@ -199,10 +199,10 @@ static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scrip
|
||||
vector<CPubKey> vPK;
|
||||
vector<valtype> vParams = vector<valtype>();
|
||||
COptCCParams p;
|
||||
|
||||
|
||||
// get information to sign with
|
||||
CCcontract_info C;
|
||||
|
||||
|
||||
scriptPubKey.IsPayToCryptoCondition(&subScript, vParams);
|
||||
if (vParams.empty())
|
||||
{
|
||||
@@ -219,12 +219,12 @@ static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scrip
|
||||
{
|
||||
p = COptCCParams(vParams[0]);
|
||||
}
|
||||
|
||||
|
||||
if (p.IsValid() && p.vKeys.size() >= p.n)
|
||||
{
|
||||
bool is1of2 = (p.m == 1 && p.n == 2);
|
||||
CKey privKey;
|
||||
|
||||
|
||||
// must be a valid cc eval code
|
||||
if (CCinitLite(&C, p.evalCode))
|
||||
{
|
||||
@@ -232,7 +232,7 @@ static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scrip
|
||||
if (!is1of2)
|
||||
{
|
||||
bool havePriv = creator.KeyStore().GetKey(p.vKeys[0].GetID(), privKey);
|
||||
|
||||
|
||||
// if we don't have the private key, it must be the unspendable address
|
||||
if (!havePriv && (p.vKeys[0] == CPubKey(ParseHex(C.CChexstr))))
|
||||
{
|
||||
@@ -240,9 +240,9 @@ static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scrip
|
||||
std::vector<unsigned char> vch(&(C.CCpriv[0]), C.CCpriv + sizeof(C.CCpriv));
|
||||
privKey.Set(vch.begin(), vch.end(), false);
|
||||
}
|
||||
|
||||
|
||||
CC *cc = CCcond1(p.evalCode, p.vKeys[0]);
|
||||
|
||||
|
||||
if (cc)
|
||||
{
|
||||
vector<unsigned char> vch;
|
||||
@@ -254,7 +254,7 @@ static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scrip
|
||||
{
|
||||
fprintf(stderr,"vin has 1of1 CC signing error with address.(%s)\n", p.vKeys[0].GetID().ToString().c_str());
|
||||
}
|
||||
|
||||
|
||||
cc_free(cc);
|
||||
return ret.size() != 0;
|
||||
}
|
||||
@@ -266,7 +266,7 @@ static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scrip
|
||||
{
|
||||
if (creator.IsKeystoreValid() && creator.KeyStore().GetKey(pk.GetID(), privKey) && privKey.IsValid())
|
||||
break;
|
||||
|
||||
|
||||
if (pk == CPubKey(ParseHex(C.CChexstr)))
|
||||
{
|
||||
privKey = CKey();
|
||||
@@ -275,12 +275,12 @@ static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scrip
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!privKey.IsValid())
|
||||
return false;
|
||||
|
||||
|
||||
CC *cc = CCcond1of2(p.evalCode, p.vKeys[0], p.vKeys[1]);
|
||||
|
||||
|
||||
if (cc)
|
||||
{
|
||||
vector<unsigned char> vch;
|
||||
@@ -292,7 +292,7 @@ static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scrip
|
||||
{
|
||||
fprintf(stderr,"vin has 1of2 CC signing error with addresses.(%s)\n(%s)\n", p.vKeys[0].GetID().ToString().c_str(), p.vKeys[1].GetID().ToString().c_str());
|
||||
}
|
||||
|
||||
|
||||
cc_free(cc);
|
||||
return ret.size() != 0;
|
||||
}
|
||||
@@ -314,9 +314,9 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP
|
||||
CScript scriptRet;
|
||||
uint160 h160;
|
||||
ret.clear();
|
||||
|
||||
|
||||
vector<valtype> vSolutions;
|
||||
|
||||
|
||||
if (!Solver(scriptPubKey, whichTypeRet, vSolutions))
|
||||
{
|
||||
// if this is a CLTV script, solve for the destination after CLTV
|
||||
@@ -324,10 +324,10 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP
|
||||
{
|
||||
uint8_t pushOp = scriptPubKey[0];
|
||||
uint32_t scriptStart = pushOp + 3;
|
||||
|
||||
|
||||
// check post CLTV script
|
||||
CScript postfix = CScript(scriptPubKey.size() > scriptStart ? scriptPubKey.begin() + scriptStart : scriptPubKey.end(), scriptPubKey.end());
|
||||
|
||||
|
||||
// check again with only postfix subscript
|
||||
if (!Solver(postfix, whichTypeRet, vSolutions))
|
||||
return false;
|
||||
@@ -335,44 +335,44 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
CKeyID keyID;
|
||||
|
||||
|
||||
switch (whichTypeRet)
|
||||
{
|
||||
case TX_NONSTANDARD:
|
||||
case TX_NULL_DATA:
|
||||
return false;
|
||||
case TX_PUBKEY:
|
||||
keyID = CPubKey(vSolutions[0]).GetID();
|
||||
return Sign1(keyID, creator, scriptPubKey, ret, consensusBranchId);
|
||||
case TX_PUBKEYHASH:
|
||||
keyID = CKeyID(uint160(vSolutions[0]));
|
||||
if (!Sign1(keyID, creator, scriptPubKey, ret, consensusBranchId))
|
||||
case TX_NONSTANDARD:
|
||||
case TX_NULL_DATA:
|
||||
return false;
|
||||
else
|
||||
{
|
||||
CPubKey vch;
|
||||
creator.KeyStore().GetPubKey(keyID, vch);
|
||||
ret.push_back(ToByteVector(vch));
|
||||
}
|
||||
return true;
|
||||
case TX_SCRIPTHASH:
|
||||
if (creator.KeyStore().GetCScript(uint160(vSolutions[0]), scriptRet)) {
|
||||
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
|
||||
case TX_PUBKEY:
|
||||
keyID = CPubKey(vSolutions[0]).GetID();
|
||||
return Sign1(keyID, creator, scriptPubKey, ret, consensusBranchId);
|
||||
case TX_PUBKEYHASH:
|
||||
keyID = CKeyID(uint160(vSolutions[0]));
|
||||
if (!Sign1(keyID, creator, scriptPubKey, ret, consensusBranchId))
|
||||
return false;
|
||||
else
|
||||
{
|
||||
CPubKey vch;
|
||||
creator.KeyStore().GetPubKey(keyID, vch);
|
||||
ret.push_back(ToByteVector(vch));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case TX_CRYPTOCONDITION:
|
||||
return SignStepCC(creator, scriptPubKey, vSolutions, ret, consensusBranchId);
|
||||
|
||||
case TX_MULTISIG:
|
||||
ret.push_back(valtype()); // workaround CHECKMULTISIG bug
|
||||
return (SignN(vSolutions, creator, scriptPubKey, ret, consensusBranchId));
|
||||
|
||||
default:
|
||||
return false;
|
||||
case TX_SCRIPTHASH:
|
||||
if (creator.KeyStore().GetCScript(uint160(vSolutions[0]), scriptRet)) {
|
||||
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case TX_CRYPTOCONDITION:
|
||||
return SignStepCC(creator, scriptPubKey, vSolutions, ret, consensusBranchId);
|
||||
|
||||
case TX_MULTISIG:
|
||||
ret.push_back(valtype()); // workaround CHECKMULTISIG bug
|
||||
return (SignN(vSolutions, creator, scriptPubKey, ret, consensusBranchId));
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -399,7 +399,7 @@ bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPu
|
||||
txnouttype whichType;
|
||||
solved = SignStep(creator, script, result, whichType, consensusBranchId);
|
||||
CScript subscript;
|
||||
|
||||
|
||||
if (solved && whichType == TX_SCRIPTHASH)
|
||||
{
|
||||
// Solver returns the subscript that needs to be evaluated;
|
||||
@@ -409,9 +409,9 @@ bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPu
|
||||
solved = solved && SignStep(creator, script, result, whichType, consensusBranchId) && whichType != TX_SCRIPTHASH;
|
||||
result.push_back(std::vector<unsigned char>(subscript.begin(), subscript.end()));
|
||||
}
|
||||
|
||||
|
||||
sigdata.scriptSig = PushAll(result);
|
||||
|
||||
|
||||
// Test solution
|
||||
return solved && VerifyScript(sigdata.scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker(), consensusBranchId);
|
||||
}
|
||||
@@ -431,19 +431,19 @@ void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const Signatur
|
||||
}
|
||||
|
||||
bool SignSignature(
|
||||
const CKeyStore &keystore,
|
||||
const CScript& fromPubKey,
|
||||
CMutableTransaction& txTo,
|
||||
unsigned int nIn,
|
||||
const CAmount& amount,
|
||||
int nHashType,
|
||||
uint32_t consensusBranchId)
|
||||
const CKeyStore &keystore,
|
||||
const CScript& fromPubKey,
|
||||
CMutableTransaction& txTo,
|
||||
unsigned int nIn,
|
||||
const CAmount& amount,
|
||||
int nHashType,
|
||||
uint32_t consensusBranchId)
|
||||
{
|
||||
assert(nIn < txTo.vin.size());
|
||||
|
||||
|
||||
CTransaction txToConst(txTo);
|
||||
TransactionSignatureCreator creator(&keystore, &txToConst, nIn, amount, nHashType);
|
||||
|
||||
|
||||
SignatureData sigdata;
|
||||
bool ret = ProduceSignature(creator, fromPubKey, sigdata, consensusBranchId);
|
||||
UpdateTransaction(txTo, nIn, sigdata);
|
||||
@@ -451,24 +451,24 @@ bool SignSignature(
|
||||
}
|
||||
|
||||
bool SignSignature(
|
||||
const CKeyStore &keystore,
|
||||
const CTransaction& txFrom,
|
||||
CMutableTransaction& txTo,
|
||||
unsigned int nIn,
|
||||
int nHashType,
|
||||
uint32_t consensusBranchId)
|
||||
const CKeyStore &keystore,
|
||||
const CTransaction& txFrom,
|
||||
CMutableTransaction& txTo,
|
||||
unsigned int nIn,
|
||||
int nHashType,
|
||||
uint32_t consensusBranchId)
|
||||
{
|
||||
assert(nIn < txTo.vin.size());
|
||||
CTxIn& txin = txTo.vin[nIn];
|
||||
assert(txin.prevout.n < txFrom.vout.size());
|
||||
const CTxOut& txout = txFrom.vout[txin.prevout.n];
|
||||
|
||||
|
||||
return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType, consensusBranchId);
|
||||
}
|
||||
|
||||
static vector<valtype> CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
|
||||
const vector<valtype>& vSolutions,
|
||||
const vector<valtype>& sigs1, const vector<valtype>& sigs2, uint32_t consensusBranchId)
|
||||
const vector<valtype>& vSolutions,
|
||||
const vector<valtype>& sigs1, const vector<valtype>& sigs2, uint32_t consensusBranchId)
|
||||
{
|
||||
// Combine all the signatures we've got:
|
||||
set<valtype> allsigs;
|
||||
@@ -482,7 +482,7 @@ static vector<valtype> CombineMultisig(const CScript& scriptPubKey, const BaseSi
|
||||
if (!v.empty())
|
||||
allsigs.insert(v);
|
||||
}
|
||||
|
||||
|
||||
// Build a map of pubkey -> signature by matching sigs to pubkeys:
|
||||
assert(vSolutions.size() > 1);
|
||||
unsigned int nSigsRequired = vSolutions.front()[0];
|
||||
@@ -495,7 +495,7 @@ static vector<valtype> CombineMultisig(const CScript& scriptPubKey, const BaseSi
|
||||
const valtype& pubkey = vSolutions[i+1];
|
||||
if (sigs.count(pubkey))
|
||||
continue; // Already got a sig for this pubkey
|
||||
|
||||
|
||||
if (checker.CheckSig(sig, pubkey, scriptPubKey, consensusBranchId))
|
||||
{
|
||||
sigs[pubkey] = sig;
|
||||
@@ -517,108 +517,108 @@ static vector<valtype> CombineMultisig(const CScript& scriptPubKey, const BaseSi
|
||||
// Fill any missing with OP_0:
|
||||
for (unsigned int i = nSigsHave; i < nSigsRequired; i++)
|
||||
result.push_back(valtype());
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct Stacks
|
||||
{
|
||||
std::vector<valtype> script;
|
||||
|
||||
Stacks() {}
|
||||
explicit Stacks(const std::vector<valtype>& scriptSigStack_) : script(scriptSigStack_) {}
|
||||
explicit Stacks(const SignatureData& data, uint32_t consensusBranchId) {
|
||||
EvalScript(script, data.scriptSig, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), consensusBranchId);
|
||||
}
|
||||
|
||||
SignatureData Output() const {
|
||||
SignatureData result;
|
||||
result.scriptSig = PushAll(script);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
struct Stacks
|
||||
{
|
||||
std::vector<valtype> script;
|
||||
|
||||
Stacks() {}
|
||||
explicit Stacks(const std::vector<valtype>& scriptSigStack_) : script(scriptSigStack_) {}
|
||||
explicit Stacks(const SignatureData& data, uint32_t consensusBranchId) {
|
||||
EvalScript(script, data.scriptSig, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), consensusBranchId);
|
||||
}
|
||||
|
||||
SignatureData Output() const {
|
||||
SignatureData result;
|
||||
result.scriptSig = PushAll(script);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static Stacks CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
|
||||
const txnouttype txType, const vector<valtype>& vSolutions,
|
||||
Stacks sigs1, Stacks sigs2, uint32_t consensusBranchId)
|
||||
const txnouttype txType, const vector<valtype>& vSolutions,
|
||||
Stacks sigs1, Stacks sigs2, uint32_t consensusBranchId)
|
||||
{
|
||||
switch (txType)
|
||||
{
|
||||
case TX_NONSTANDARD:
|
||||
case TX_NULL_DATA:
|
||||
// Don't know anything about this, assume bigger one is correct:
|
||||
if (sigs1.script.size() >= sigs2.script.size())
|
||||
return sigs1;
|
||||
return sigs2;
|
||||
case TX_PUBKEY:
|
||||
case TX_PUBKEYHASH:
|
||||
case TX_CRYPTOCONDITION:
|
||||
// Signatures are bigger than placeholders or empty scripts:
|
||||
if (sigs1.script.empty() || sigs1.script[0].empty())
|
||||
case TX_NONSTANDARD:
|
||||
case TX_NULL_DATA:
|
||||
// Don't know anything about this, assume bigger one is correct:
|
||||
if (sigs1.script.size() >= sigs2.script.size())
|
||||
return sigs1;
|
||||
return sigs2;
|
||||
return sigs1;
|
||||
case TX_SCRIPTHASH:
|
||||
if (sigs1.script.empty() || sigs1.script.back().empty())
|
||||
return sigs2;
|
||||
else if (sigs2.script.empty() || sigs2.script.back().empty())
|
||||
case TX_PUBKEY:
|
||||
case TX_PUBKEYHASH:
|
||||
case TX_CRYPTOCONDITION:
|
||||
// Signatures are bigger than placeholders or empty scripts:
|
||||
if (sigs1.script.empty() || sigs1.script[0].empty())
|
||||
return sigs2;
|
||||
return sigs1;
|
||||
else
|
||||
{
|
||||
// Recur to combine:
|
||||
valtype spk = sigs1.script.back();
|
||||
CScript pubKey2(spk.begin(), spk.end());
|
||||
|
||||
txnouttype txType2;
|
||||
vector<vector<unsigned char> > vSolutions2;
|
||||
Solver(pubKey2, txType2, vSolutions2);
|
||||
sigs1.script.pop_back();
|
||||
sigs2.script.pop_back();
|
||||
Stacks result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2, consensusBranchId);
|
||||
result.script.push_back(spk);
|
||||
return result;
|
||||
}
|
||||
case TX_MULTISIG:
|
||||
return Stacks(CombineMultisig(scriptPubKey, checker, vSolutions, sigs1.script, sigs2.script, consensusBranchId));
|
||||
default:
|
||||
return Stacks();
|
||||
case TX_SCRIPTHASH:
|
||||
if (sigs1.script.empty() || sigs1.script.back().empty())
|
||||
return sigs2;
|
||||
else if (sigs2.script.empty() || sigs2.script.back().empty())
|
||||
return sigs1;
|
||||
else
|
||||
{
|
||||
// Recur to combine:
|
||||
valtype spk = sigs1.script.back();
|
||||
CScript pubKey2(spk.begin(), spk.end());
|
||||
|
||||
txnouttype txType2;
|
||||
vector<vector<unsigned char> > vSolutions2;
|
||||
Solver(pubKey2, txType2, vSolutions2);
|
||||
sigs1.script.pop_back();
|
||||
sigs2.script.pop_back();
|
||||
Stacks result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2, consensusBranchId);
|
||||
result.script.push_back(spk);
|
||||
return result;
|
||||
}
|
||||
case TX_MULTISIG:
|
||||
return Stacks(CombineMultisig(scriptPubKey, checker, vSolutions, sigs1.script, sigs2.script, consensusBranchId));
|
||||
default:
|
||||
return Stacks();
|
||||
}
|
||||
}
|
||||
|
||||
SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
|
||||
const SignatureData& scriptSig1, const SignatureData& scriptSig2,
|
||||
uint32_t consensusBranchId)
|
||||
const SignatureData& scriptSig1, const SignatureData& scriptSig2,
|
||||
uint32_t consensusBranchId)
|
||||
{
|
||||
txnouttype txType;
|
||||
vector<vector<unsigned char> > vSolutions;
|
||||
Solver(scriptPubKey, txType, vSolutions);
|
||||
|
||||
|
||||
return CombineSignatures(
|
||||
scriptPubKey, checker, txType, vSolutions,
|
||||
Stacks(scriptSig1, consensusBranchId),
|
||||
Stacks(scriptSig2, consensusBranchId),
|
||||
consensusBranchId).Output();
|
||||
scriptPubKey, checker, txType, vSolutions,
|
||||
Stacks(scriptSig1, consensusBranchId),
|
||||
Stacks(scriptSig2, consensusBranchId),
|
||||
consensusBranchId).Output();
|
||||
}
|
||||
|
||||
namespace {
|
||||
/** Dummy signature checker which accepts all signatures. */
|
||||
class DummySignatureChecker : public BaseSignatureChecker
|
||||
{
|
||||
public:
|
||||
DummySignatureChecker() {}
|
||||
|
||||
bool CheckSig(
|
||||
const std::vector<unsigned char>& scriptSig,
|
||||
const std::vector<unsigned char>& vchPubKey,
|
||||
const CScript& scriptCode,
|
||||
uint32_t consensusBranchId) const
|
||||
/** Dummy signature checker which accepts all signatures. */
|
||||
class DummySignatureChecker : public BaseSignatureChecker
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
const DummySignatureChecker dummyChecker;
|
||||
public:
|
||||
DummySignatureChecker() {}
|
||||
|
||||
bool CheckSig(
|
||||
const std::vector<unsigned char>& scriptSig,
|
||||
const std::vector<unsigned char>& vchPubKey,
|
||||
const CScript& scriptCode,
|
||||
uint32_t consensusBranchId) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
const DummySignatureChecker dummyChecker;
|
||||
}
|
||||
|
||||
const BaseSignatureChecker& DummySignatureCreator::Checker() const
|
||||
@@ -627,12 +627,12 @@ const BaseSignatureChecker& DummySignatureCreator::Checker() const
|
||||
}
|
||||
|
||||
bool DummySignatureCreator::CreateSig(
|
||||
std::vector<unsigned char>& vchSig,
|
||||
const CKeyID& keyid,
|
||||
const CScript& scriptCode,
|
||||
uint32_t consensusBranchId,
|
||||
CKey *key,
|
||||
void *extraData) const
|
||||
std::vector<unsigned char>& vchSig,
|
||||
const CKeyID& keyid,
|
||||
const CScript& scriptCode,
|
||||
uint32_t consensusBranchId,
|
||||
CKey *key,
|
||||
void *extraData) const
|
||||
{
|
||||
// Create a dummy signature that is a valid DER-encoding
|
||||
vchSig.assign(72, '\000');
|
||||
@@ -647,3 +647,4 @@ bool DummySignatureCreator::CreateSig(
|
||||
vchSig[6 + 33 + 32] = SIGHASH_ALL;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ void ThreadSendAlert()
|
||||
// 4000 or higher will put the RPC into safe mode
|
||||
alert.nPriority = 4000;
|
||||
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;
|
||||
|
||||
// Set specific client version/versions here. If setSubVer is empty, no filtering on subver is done:
|
||||
|
||||
@@ -686,7 +686,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
|
||||
pindexNew->nTx = diskindex.nTx;
|
||||
pindexNew->nSproutValue = diskindex.nSproutValue;
|
||||
pindexNew->nSaplingValue = diskindex.nSaplingValue;
|
||||
|
||||
//fprintf(stderr,"loadguts ht.%d\n",pindexNew->GetHeight());
|
||||
// Consistency checks
|
||||
auto header = pindexNew->GetBlockHeader();
|
||||
if (header.GetHash() != pindexNew->GetBlockHash())
|
||||
|
||||
17
src/util.h
17
src/util.h
@@ -3,6 +3,21 @@
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// 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,
|
||||
* logging, thread wrappers
|
||||
@@ -29,6 +44,8 @@
|
||||
#include <boost/signals2/signal.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_LOGIPS = false;
|
||||
static const bool DEFAULT_LOGTIMESTAMPS = true;
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
|
||||
#include <numeric>
|
||||
|
||||
#include "komodo_defs.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -67,8 +68,6 @@ const std::string ADDR_TYPE_SPROUT = "sprout";
|
||||
const std::string ADDR_TYPE_SAPLING = "sapling";
|
||||
|
||||
extern UniValue TxJoinSplitToJSON(const CTransaction& tx);
|
||||
extern uint8_t ASSETCHAINS_PRIVATE;
|
||||
extern int32_t USE_EXTERNAL_PUBKEY;
|
||||
uint32_t komodo_segid32(char *coinaddr);
|
||||
int32_t komodo_dpowconfs(int32_t height,int32_t numconfs);
|
||||
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) {
|
||||
// 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;
|
||||
pwalletMain->GetFilteredNotes(sproutEntries, useAnySprout == 0 ? saplingEntries : skipsapling, zaddrs);
|
||||
|
||||
// If Sapling is not active, do not allow sending from a sapling addresses.
|
||||
if (!saplingActive && saplingEntries.size() > 0) {
|
||||
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()
|
||||
{
|
||||
extern uint8_t NOTARY_PUBKEY33[];
|
||||
CCerror = "";
|
||||
if ( NOTARY_PUBKEY33[0] == 0 )
|
||||
return(-1);
|
||||
@@ -5262,8 +5261,6 @@ UniValue setpubkey(const UniValue& params, bool fHelp)
|
||||
|
||||
char Raddress[18];
|
||||
uint8_t pubkey33[33];
|
||||
extern uint8_t NOTARY_PUBKEY33[];
|
||||
extern std::string NOTARY_PUBKEY;
|
||||
if ( NOTARY_PUBKEY33[0] == 0 ) {
|
||||
if (strlen(params[0].get_str().c_str()) == 66) {
|
||||
decode_hex(pubkey33,33,(char *)params[0].get_str().c_str());
|
||||
@@ -5327,6 +5324,43 @@ UniValue channelsaddress(const UniValue& params, bool fHelp)
|
||||
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)
|
||||
{
|
||||
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);
|
||||
uint256 tokenid = zeroid;
|
||||
uint64_t txfee;
|
||||
int64_t txfee;
|
||||
int64_t amount;
|
||||
int64_t inactivitytime;
|
||||
std::string hex;
|
||||
@@ -7340,21 +7374,34 @@ UniValue heirfund(const UniValue& params, bool fHelp)
|
||||
return NullUniValue;
|
||||
|
||||
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)
|
||||
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;
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
txfee = atoll((char*)params[0].get_str().c_str());
|
||||
amount = atoll((char*)params[1].get_str().c_str());
|
||||
txfee = atoll(params[0].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();
|
||||
pubkey = ParseHex(params[3].get_str().c_str());
|
||||
if( !pubkey2pk(pubkey).IsValid() )
|
||||
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) {
|
||||
tokenid = Parseuint256((char*)params[5].get_str().c_str());
|
||||
if(tokenid == zeroid)
|
||||
@@ -7373,7 +7420,7 @@ UniValue heiradd(const UniValue& params, bool fHelp)
|
||||
{
|
||||
UniValue result;
|
||||
uint256 fundingtxid;
|
||||
uint64_t txfee;
|
||||
int64_t txfee;
|
||||
int64_t amount;
|
||||
int64_t inactivitytime;
|
||||
std::string hex;
|
||||
@@ -7384,18 +7431,20 @@ UniValue heiradd(const UniValue& params, bool fHelp)
|
||||
return NullUniValue;
|
||||
|
||||
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)
|
||||
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;
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
txfee = atoll((char*)params[0].get_str().c_str());
|
||||
amount = atoll((char*)params[1].get_str().c_str());
|
||||
txfee = atoll(params[0].get_str().c_str());
|
||||
if (txfee < 0)
|
||||
throw runtime_error("incorrect txfee param\n");
|
||||
|
||||
fundingtxid = Parseuint256((char*)params[2].get_str().c_str());
|
||||
|
||||
result = HeirAddCaller(fundingtxid, txfee, amount);
|
||||
result = HeirAddCaller(fundingtxid, txfee, params[1].get_str());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -7404,7 +7453,6 @@ UniValue heirclaim(const UniValue& params, bool fHelp)
|
||||
UniValue result; // result(UniValue::VOBJ);
|
||||
uint256 fundingtxid;
|
||||
int64_t txfee;
|
||||
int64_t amount;
|
||||
int64_t inactivitytime;
|
||||
std::string hex;
|
||||
std::vector<unsigned char> pubkey;
|
||||
@@ -7415,18 +7463,20 @@ UniValue heirclaim(const UniValue& params, bool fHelp)
|
||||
return NullUniValue;
|
||||
|
||||
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)
|
||||
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;
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
txfee = atoll((char*)params[0].get_str().c_str());
|
||||
amount = atoll((char*)params[1].get_str().c_str());
|
||||
txfee = atoll(params[0].get_str().c_str());
|
||||
if (txfee < 0)
|
||||
throw runtime_error("incorrect txfee param\n");
|
||||
|
||||
fundingtxid = Parseuint256((char*)params[2].get_str().c_str());
|
||||
|
||||
result = HeirClaimCaller(fundingtxid, txfee, amount);
|
||||
result = HeirClaimCaller(fundingtxid, txfee, params[1].get_str());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -7548,3 +7598,79 @@ void RegisterWalletRPCCommands(CRPCTable &tableRPC)
|
||||
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(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));
|
||||
}
|
||||
@@ -59,13 +59,7 @@ bool fSendFreeTransactions = false;
|
||||
bool fPayAtLeastCustomFee = true;
|
||||
#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);
|
||||
extern std::string DONATION_PUBKEY;
|
||||
|
||||
/**
|
||||
* Fees smaller than this (in satoshi) are considered zero fee (for transaction creation)
|
||||
|
||||
@@ -77,7 +77,6 @@ static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000;
|
||||
// unless there is some exceptional network disruption.
|
||||
extern unsigned int WITNESS_CACHE_SIZE;
|
||||
|
||||
|
||||
//! Size of HD seed in bytes
|
||||
static const size_t HD_WALLET_SEED_LENGTH = 32;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user