49
qa/rpc-tests/cryptoconditions.py
Executable file → Normal file
49
qa/rpc-tests/cryptoconditions.py
Executable file → Normal file
@@ -3,7 +3,6 @@
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.authproxy import JSONRPCException
|
||||
from test_framework.util import assert_equal, assert_greater_than, \
|
||||
@@ -25,7 +24,6 @@ def generate_random_string(length):
|
||||
random_string = ''.join(choice(ascii_uppercase) for i in range(length))
|
||||
return random_string
|
||||
|
||||
|
||||
class CryptoConditionsTest (BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
@@ -105,13 +103,13 @@ class CryptoConditionsTest (BitcoinTestFramework):
|
||||
faucet = rpc.faucetaddress()
|
||||
assert_equal(faucet['result'], 'success')
|
||||
# verify all keys look like valid AC addrs, could be better
|
||||
for x in ['myCCaddress', 'FaucetCCaddress', 'Faucetmarker', 'myaddress']:
|
||||
for x in ['myCCAddress(Faucet)', 'FaucetCCAddress', 'FaucetCCTokensAddress', 'myaddress', 'FaucetNormalAddress']:
|
||||
assert_equal(faucet[x][0], 'R')
|
||||
|
||||
|
||||
result = rpc.faucetaddress(self.pubkey)
|
||||
assert_success(result)
|
||||
# test that additional CCaddress key is returned
|
||||
for x in ['myCCaddress', 'FaucetCCaddress', 'Faucetmarker', 'myaddress', 'CCaddress']:
|
||||
for x in ['myCCAddress(Faucet)', 'FaucetCCAddress', 'FaucetCCTokensAddress', 'myaddress', 'FaucetNormalAddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
# no funds in the faucet yet
|
||||
@@ -179,12 +177,12 @@ class CryptoConditionsTest (BitcoinTestFramework):
|
||||
|
||||
dice = rpc.diceaddress()
|
||||
assert_equal(dice['result'], 'success')
|
||||
for x in ['myCCaddress', 'DiceCCaddress', 'Dicemarker', 'myaddress']:
|
||||
for x in ['myCCAddress(Dice)', 'DiceCCAddress', 'DiceCCTokensAddress', 'myaddress', 'DiceNormalAddress']:
|
||||
assert_equal(dice[x][0], 'R')
|
||||
|
||||
dice = rpc.diceaddress(self.pubkey)
|
||||
assert_equal(dice['result'], 'success')
|
||||
for x in ['myCCaddress', 'DiceCCaddress', 'Dicemarker', 'myaddress', 'CCaddress']:
|
||||
for x in ['myCCAddress(Dice)', 'DiceCCAddress', 'DiceCCTokensAddress', 'myaddress', 'DiceNormalAddress']:
|
||||
assert_equal(dice[x][0], 'R')
|
||||
|
||||
# no dice created yet
|
||||
@@ -333,12 +331,12 @@ class CryptoConditionsTest (BitcoinTestFramework):
|
||||
rpc = self.nodes[0]
|
||||
result = rpc.tokenaddress()
|
||||
assert_success(result)
|
||||
for x in ['AssetsCCaddress', 'myCCaddress', 'Assetsmarker', 'myaddress']:
|
||||
for x in ['myCCAddress(Tokens)', 'TokensNormalAddress', 'TokensNormalAddress', 'myaddress','TokensCCAddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
result = rpc.tokenaddress(self.pubkey)
|
||||
assert_success(result)
|
||||
for x in ['AssetsCCaddress', 'myCCaddress', 'Assetsmarker', 'myaddress', 'CCaddress']:
|
||||
for x in ['myCCAddress(Tokens)', 'TokensNormalAddress', 'TokensNormalAddress', 'myaddress','TokensCCAddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
# there are no tokens created yet
|
||||
result = rpc.tokenlist()
|
||||
@@ -361,17 +359,6 @@ class CryptoConditionsTest (BitcoinTestFramework):
|
||||
result = rpc.tokenlist()
|
||||
assert_equal(result[0], tokenid)
|
||||
|
||||
# there are no token orders yet
|
||||
result = rpc.tokenorders()
|
||||
assert_equal(result, [])
|
||||
|
||||
# getting token balance for pubkey
|
||||
result = rpc.tokenbalance(self.pubkey)
|
||||
assert_success(result)
|
||||
assert_equal(result['balance'], 0)
|
||||
assert_equal(result['CCaddress'], 'RCRsm3VBXz8kKTsYaXKpy7pSEzrtNNQGJC')
|
||||
assert_equal(result['tokenid'], self.pubkey)
|
||||
|
||||
# get token balance for token with pubkey
|
||||
result = rpc.tokenbalance(tokenid, self.pubkey)
|
||||
assert_success(result)
|
||||
@@ -421,7 +408,7 @@ class CryptoConditionsTest (BitcoinTestFramework):
|
||||
tokenask = rpc.tokenask("100", tokenid, "7.77")
|
||||
tokenaskhex = tokenask['hex']
|
||||
tokenaskid = self.send_and_mine(tokenask['hex'], rpc)
|
||||
result = rpc.tokenorders()
|
||||
result = rpc.tokenorders(tokenid)
|
||||
order = result[0]
|
||||
assert order, "found order"
|
||||
|
||||
@@ -440,7 +427,7 @@ class CryptoConditionsTest (BitcoinTestFramework):
|
||||
assert txid, "found txid"
|
||||
|
||||
# should be no token orders
|
||||
result = rpc.tokenorders()
|
||||
result = rpc.tokenorders(tokenid)
|
||||
assert_equal(result, [])
|
||||
|
||||
# checking ask cancellation
|
||||
@@ -448,7 +435,7 @@ class CryptoConditionsTest (BitcoinTestFramework):
|
||||
testorderid = self.send_and_mine(testorder['hex'], rpc)
|
||||
cancel = rpc.tokencancelask(tokenid, testorderid)
|
||||
self.send_and_mine(cancel["hex"], rpc)
|
||||
result = rpc.tokenorders()
|
||||
result = rpc.tokenorders(tokenid)
|
||||
assert_equal(result, [])
|
||||
|
||||
# invalid numtokens bid
|
||||
@@ -474,7 +461,7 @@ class CryptoConditionsTest (BitcoinTestFramework):
|
||||
tokenbid = rpc.tokenbid("100", tokenid, "10")
|
||||
tokenbidhex = tokenbid['hex']
|
||||
tokenbidid = self.send_and_mine(tokenbid['hex'], rpc)
|
||||
result = rpc.tokenorders()
|
||||
result = rpc.tokenorders(tokenid)
|
||||
order = result[0]
|
||||
assert order, "found order"
|
||||
|
||||
@@ -493,7 +480,7 @@ class CryptoConditionsTest (BitcoinTestFramework):
|
||||
assert txid, "found txid"
|
||||
|
||||
# should be no token orders
|
||||
result = rpc.tokenorders()
|
||||
result = rpc.tokenorders(tokenid)
|
||||
assert_equal(result, [])
|
||||
|
||||
# checking bid cancellation
|
||||
@@ -501,7 +488,7 @@ class CryptoConditionsTest (BitcoinTestFramework):
|
||||
testorderid = self.send_and_mine(testorder['hex'], rpc)
|
||||
cancel = rpc.tokencancelbid(tokenid, testorderid)
|
||||
self.send_and_mine(cancel["hex"], rpc)
|
||||
result = rpc.tokenorders()
|
||||
result = rpc.tokenorders(tokenid)
|
||||
assert_equal(result, [])
|
||||
|
||||
# invalid token transfer amount (have to add status to CC code!)
|
||||
@@ -522,11 +509,11 @@ class CryptoConditionsTest (BitcoinTestFramework):
|
||||
def run_rewards_tests(self):
|
||||
rpc = self.nodes[0]
|
||||
result = rpc.rewardsaddress()
|
||||
for x in ['RewardsCCaddress', 'myCCaddress', 'Rewardsmarker', 'myaddress']:
|
||||
for x in ['myCCAddress(Rewards)', 'myaddress', 'RewardsCCAddress', 'RewardsCCTokensAddress', 'RewardsNormalAddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
result = rpc.rewardsaddress(self.pubkey)
|
||||
for x in ['RewardsCCaddress', 'myCCaddress', 'Rewardsmarker', 'myaddress', 'CCaddress']:
|
||||
for x in ['myCCAddress(Rewards)', 'myaddress', 'RewardsCCAddress', 'RewardsCCTokensAddress', 'RewardsNormalAddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
# no rewards yet
|
||||
@@ -637,12 +624,13 @@ class CryptoConditionsTest (BitcoinTestFramework):
|
||||
|
||||
result = rpc.oraclesaddress()
|
||||
assert_success(result)
|
||||
for x in ['OraclesCCaddress', 'Oraclesmarker', 'myCCaddress', 'myaddress']:
|
||||
|
||||
for x in ['OraclesCCAddress', 'OraclesNormalAddress', 'myCCAddress(Oracles)','OraclesCCTokensAddress', 'myaddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
result = rpc.oraclesaddress(self.pubkey)
|
||||
assert_success(result)
|
||||
for x in ['OraclesCCaddress', 'Oraclesmarker', 'myCCaddress', 'myaddress']:
|
||||
for x in ['OraclesCCAddress', 'OraclesNormalAddress', 'myCCAddress(Oracles)','OraclesCCTokensAddress', 'myaddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
# there are no oracles created yet
|
||||
@@ -674,7 +662,6 @@ class CryptoConditionsTest (BitcoinTestFramework):
|
||||
# assert_success(result)
|
||||
# globals()["oracle_{}".format(f)] = self.send_and_mine(result['hex'], rpc)
|
||||
|
||||
|
||||
def run_test (self):
|
||||
print("Mining blocks...")
|
||||
rpc = self.nodes[0]
|
||||
|
||||
@@ -27,13 +27,14 @@ class CryptoconditionsChannelsTest(CryptoconditionsTestFramework):
|
||||
rpc1 = self.nodes[1]
|
||||
|
||||
# checking channelsaddress call
|
||||
|
||||
|
||||
result = rpc.channelsaddress(self.pubkey)
|
||||
assert_success(result)
|
||||
# test that additional CCaddress key is returned
|
||||
for x in ['ChannelsCC1of2TokensAddress', 'myCCAddress(Channels)', 'ChannelsCC1of2Address', 'myAddress', \
|
||||
'myCCaddress', 'ChannelsNormalAddress', 'PubkeyCCaddress(Channels)', 'ChannelsCCAddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
for x in result.keys():
|
||||
if x.find('ddress') > 0:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
# getting empty channels list
|
||||
result = rpc.channelslist()
|
||||
@@ -80,7 +81,7 @@ class CryptoconditionsChannelsTest(CryptoconditionsTestFramework):
|
||||
# now in channelinfo payment information should appear
|
||||
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)
|
||||
|
||||
@@ -25,18 +25,20 @@ class CryptoconditionsDiceTest(CryptoconditionsTestFramework):
|
||||
assert_greater_than(result, 100000)
|
||||
|
||||
result = rpc.diceaddress()
|
||||
for x in result.keys():
|
||||
print(x+": "+str(result[x]))
|
||||
assert_equal(result['result'], 'success')
|
||||
for x in ['myCCaddress', 'DiceCCAddress', 'myaddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
for x in result.keys():
|
||||
if x.find('ddress') > 0:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
result = rpc.diceaddress(self.pubkey)
|
||||
for x in result.keys():
|
||||
print(x+": "+str(result[x]))
|
||||
assert_equal(result['result'], 'success')
|
||||
for x in ['myCCaddress', 'DiceCCAddress', 'myaddress', 'DiceCCTokensAddress', 'DiceNormalAddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
for x in result.keys():
|
||||
if x.find('ddress') > 0:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
# no dice created yet
|
||||
result = rpc.dicelist()
|
||||
|
||||
@@ -26,19 +26,21 @@ class CryptoconditionsFaucetTest(CryptoconditionsTestFramework):
|
||||
|
||||
result = rpc.faucetaddress()
|
||||
assert_equal(result['result'], 'success')
|
||||
for x in result.keys():
|
||||
print(x+": "+str(result[x]))
|
||||
|
||||
# verify all keys look like valid AC addrs, could be better
|
||||
for x in ['myCCaddress', 'FaucetCCTokensAddress', 'FaucetNormalAddress', 'myaddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
for x in result.keys():
|
||||
if x.find('ddress') > 0:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
result = rpc.faucetaddress(self.pubkey)
|
||||
assert_success(result)
|
||||
for x in result.keys():
|
||||
print(x+": "+str(result[x]))
|
||||
# test that additional CCaddress key is returned
|
||||
for x in ['myCCaddress', 'FaucetCCTokensAddress', 'FaucetNormalAddress', 'myaddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
for x in result.keys():
|
||||
if x.find('ddress') > 0:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
# no funds in the faucet yet
|
||||
result = rpc.faucetget()
|
||||
|
||||
@@ -20,8 +20,10 @@ class CryptoconditionsGatewaysTest(CryptoconditionsTestFramework):
|
||||
|
||||
result = rpc.gatewaysaddress()
|
||||
assert_success(result)
|
||||
for x in ['GatewaysCCaddress', 'myCCaddress', 'Gatewaysmarker', 'myaddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
for x in result.keys():
|
||||
if x.find('ddress') > 0:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
assert_equal("03ea9c062b9652d8eff34879b504eda0717895d27597aaeb60347d65eed96ccb40", result["GatewaysPubkey"])
|
||||
|
||||
|
||||
@@ -22,15 +22,19 @@ class CryptoconditionsHeirTest(CryptoconditionsTestFramework):
|
||||
|
||||
result = rpc.heiraddress('')
|
||||
assert_success(result)
|
||||
|
||||
# verify all keys look like valid AC addrs, could be better
|
||||
for x in ['HeirNormalAddress', 'HeirCCTokensAddress', 'myaddress', 'myCCaddress', 'HeirCCAddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
for x in result.keys():
|
||||
if x.find('ddress') > 0:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
result = rpc.heiraddress(self.pubkey)
|
||||
assert_success(result)
|
||||
|
||||
# test that additional CCaddress key is returned
|
||||
for x in ['HeirNormalAddress', 'myCCaddress', 'myaddress', 'HeirCC1of2Address', 'HeirCCAddress', 'HeirCC1of2TokensAddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
for x in result.keys():
|
||||
if x.find('ddress') > 0:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
# getting empty heir list
|
||||
result = rpc.heirlist()
|
||||
|
||||
@@ -22,13 +22,17 @@ class CryptoconditionsOraclesTest(CryptoconditionsTestFramework):
|
||||
|
||||
result = rpc.oraclesaddress()
|
||||
assert_success(result)
|
||||
for x in ['myCCaddress', 'OraclesCCAddress', 'OraclesNormalAddress', 'myaddress', 'OraclesCCTokensAddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
for x in result.keys():
|
||||
if x.find('ddress') > 0:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
result = rpc.oraclesaddress(self.pubkey)
|
||||
assert_success(result)
|
||||
for x in ['myCCaddress', 'OraclesCCAddress', 'OraclesNormalAddress', 'myaddress', 'OraclesCCTokensAddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
for x in result.keys():
|
||||
if x.find('ddress') > 0:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
# there are no oracles created yet
|
||||
result = rpc.oracleslist()
|
||||
|
||||
@@ -19,12 +19,14 @@ class CryptoconditionsRewardsTest(CryptoconditionsTestFramework):
|
||||
rpc = self.nodes[0]
|
||||
|
||||
result = rpc.rewardsaddress()
|
||||
for x in ['myCCaddress', 'myaddress', 'RewardsCCAddress', 'RewardsCCTokensAddress', 'RewardsNormalAddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
for x in result.keys():
|
||||
if x.find('ddress') > 0:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
result = rpc.rewardsaddress(self.pubkey)
|
||||
for x in ['myCCaddress', 'myaddress', 'RewardsCCAddress', 'RewardsCCTokensAddress', 'RewardsNormalAddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
for x in result.keys():
|
||||
if x.find('ddress') > 0:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
# no rewards yet
|
||||
result = rpc.rewardslist()
|
||||
|
||||
@@ -21,23 +21,27 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework):
|
||||
|
||||
result = rpc.tokenaddress()
|
||||
assert_success(result)
|
||||
for x in ['TokensCCAddress', 'myCCaddress', 'myCCAddress(Tokens)', 'myaddress', 'TokensNormalAddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
for x in result.keys():
|
||||
if x.find('ddress') > 0:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
result = rpc.tokenaddress(self.pubkey)
|
||||
assert_success(result)
|
||||
for x in ['TokensCCAddress', 'myCCaddress', 'myCCAddress(Tokens)', 'myaddress', 'TokensNormalAddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
for x in result.keys():
|
||||
if x.find('ddress') > 0:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
result = rpc.assetsaddress()
|
||||
assert_success(result)
|
||||
for x in ['AssetsCCAddress', 'myCCaddress', 'myCCAddress(Assets)', 'myaddress', 'AssetsNormalAddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
for x in result.keys():
|
||||
if x.find('ddress') > 0:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
result = rpc.assetsaddress(self.pubkey)
|
||||
assert_success(result)
|
||||
for x in ['AssetsCCAddress', 'myCCaddress', 'myCCAddress(Assets)', 'myaddress', 'AssetsNormalAddress']:
|
||||
assert_equal(result[x][0], 'R')
|
||||
for x in result.keys():
|
||||
if x.find('ddress') > 0:
|
||||
assert_equal(result[x][0], 'R')
|
||||
|
||||
# there are no tokens created yet
|
||||
result = rpc.tokenlist()
|
||||
|
||||
@@ -288,6 +288,7 @@ libbitcoin_server_a_SOURCES = \
|
||||
bloom.cpp \
|
||||
cc/eval.cpp \
|
||||
cc/import.cpp \
|
||||
cc/importgateway.cpp \
|
||||
cc/CCassetsCore.cpp \
|
||||
cc/CCcustom.cpp \
|
||||
cc/CCtx.cpp \
|
||||
|
||||
@@ -59,13 +59,16 @@ static bool fDaemon;
|
||||
#include "komodo_defs.h"
|
||||
#define KOMODO_ASSETCHAIN_MAXLEN 65
|
||||
extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
|
||||
extern int32_t ASSETCHAINS_BLOCKTIME;
|
||||
extern uint64_t ASSETCHAINS_CBOPRET;
|
||||
void komodo_passport_iteration();
|
||||
uint64_t komodo_interestsum();
|
||||
int32_t komodo_longestchain();
|
||||
void komodo_cbopretupdate(int32_t forceflag);
|
||||
|
||||
void WaitForShutdown(boost::thread_group* threadGroup)
|
||||
{
|
||||
bool fShutdown = ShutdownRequested();
|
||||
int32_t i; bool fShutdown = ShutdownRequested();
|
||||
// Tell the main threads to shutdown.
|
||||
while (!fShutdown)
|
||||
{
|
||||
@@ -73,13 +76,27 @@ void WaitForShutdown(boost::thread_group* threadGroup)
|
||||
if ( ASSETCHAINS_SYMBOL[0] == 0 )
|
||||
{
|
||||
komodo_passport_iteration();
|
||||
MilliSleep(10000);
|
||||
for (i=0; i<10; i++)
|
||||
{
|
||||
fShutdown = ShutdownRequested();
|
||||
if ( fShutdown != 0 )
|
||||
break;
|
||||
MilliSleep(1000);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//komodo_interestsum();
|
||||
//komodo_longestchain();
|
||||
MilliSleep(20000);
|
||||
if ( ASSETCHAINS_CBOPRET != 0 )
|
||||
komodo_cbopretupdate(0);
|
||||
for (i=0; i<=ASSETCHAINS_BLOCKTIME/5; i++)
|
||||
{
|
||||
fShutdown = ShutdownRequested();
|
||||
if ( fShutdown != 0 )
|
||||
break;
|
||||
MilliSleep(1000);
|
||||
}
|
||||
}
|
||||
fShutdown = ShutdownRequested();
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#define CC_GATEWAYS_H
|
||||
|
||||
#include "CCinclude.h"
|
||||
#include "../merkleblock.h"
|
||||
|
||||
bool GatewaysValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t totalsupply,uint256 oracletxid,uint8_t M,uint8_t N,std::vector<CPubKey> pubkeys,uint8_t p1,uint8_t p2,uint8_t p3,uint8_t p4);
|
||||
|
||||
38
src/cc/CCImportGateway.h
Normal file
38
src/cc/CCImportGateway.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2018 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. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#ifndef CC_IMPORTGATEWAY_H
|
||||
#define CC_IMPORTGATEWAY_H
|
||||
|
||||
#include "CCinclude.h"
|
||||
|
||||
// CCcustom
|
||||
bool ImportGatewayValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx, uint32_t nIn);
|
||||
bool ImportGatewayExactAmounts(bool goDeeper, struct CCcontract_info *cpTokens, int64_t &inputs, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 tokenid);
|
||||
std::string ImportGatewayBind(uint64_t txfee,std::string coin,uint256 oracletxid,uint8_t M,uint8_t N,std::vector<CPubKey> pubkeys,uint8_t p1,uint8_t p2,uint8_t p3,uint8_t p4);
|
||||
std::string ImportGatewayDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 burntxid,int32_t burnvout,std::string rawburntx,std::vector<uint8_t>proof,CPubKey destpub);
|
||||
std::string ImportGatewayWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,CPubKey withdrawpub,int64_t amount);
|
||||
std::string ImportGatewayPartialSign(uint64_t txfee,uint256 lasttxid,std::string refcoin, std::string hex);
|
||||
std::string ImportGatewayCompleteSigning(uint64_t txfee,uint256 lasttxid,std::string refcoin,std::string hex);
|
||||
std::string ImportGatewayMarkDone(uint64_t txfee,uint256 completetxid,std::string refcoin);
|
||||
UniValue ImportGatewayPendingDeposits(uint256 bindtxid,std::string refcoin);
|
||||
UniValue ImportGatewayPendingWithdraws(uint256 bindtxid,std::string refcoin);
|
||||
UniValue ImportGatewayProcessedWithdraws(uint256 bindtxid,std::string refcoin);
|
||||
UniValue ImportGatewayExternalAddress(uint256 bindtxid,CPubKey pubkey);
|
||||
UniValue ImportGatewayDumpPrivKey(uint256 bindtxid,CKey key);
|
||||
UniValue ImportGatewayList();
|
||||
UniValue ImportGatewayInfo(uint256 bindtxid);
|
||||
#endif
|
||||
@@ -19,9 +19,16 @@
|
||||
|
||||
#include "CCinclude.h"
|
||||
|
||||
#define PAYMENTS_TXFEE 10000
|
||||
|
||||
bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
|
||||
// CCcustom
|
||||
UniValue PaymentsInfo();
|
||||
UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr);
|
||||
UniValue PaymentsFund(struct CCcontract_info *cp,char *jsonstr);
|
||||
UniValue PaymentsTxidopret(struct CCcontract_info *cp,char *jsonstr);
|
||||
UniValue PaymentsCreate(struct CCcontract_info *cp,char *jsonstr);
|
||||
UniValue PaymentsInfo(struct CCcontract_info *cp,char *jsonstr);
|
||||
UniValue PaymentsList(struct CCcontract_info *cp,char *jsonstr);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,17 +18,33 @@
|
||||
#define CC_PRICES_H
|
||||
|
||||
#include "CCinclude.h"
|
||||
int32_t prices_extract(int64_t *pricedata,int32_t firstheight,int32_t numblocks,int32_t ind);
|
||||
|
||||
#define PRICES_DAYWINDOW ((3600*24/ASSETCHAINS_BLOCKTIME) + 1)
|
||||
#define PRICES_TXFEE 10000
|
||||
#define PRICES_MAXLEVERAGE 777
|
||||
#define PRICES_SMOOTHWIDTH 1
|
||||
#define KOMODO_MAXPRICES 2048 // must be power of 2 and less than 8192
|
||||
#define KOMODO_PRICEMASK (~(KOMODO_MAXPRICES - 1))
|
||||
#define PRICES_WEIGHT (KOMODO_MAXPRICES * 1)
|
||||
#define PRICES_MULT (KOMODO_MAXPRICES * 2)
|
||||
#define PRICES_DIV (KOMODO_MAXPRICES * 3)
|
||||
#define PRICES_INV (KOMODO_MAXPRICES * 4)
|
||||
#define PRICES_MDD (KOMODO_MAXPRICES * 5)
|
||||
#define PRICES_MMD (KOMODO_MAXPRICES * 6)
|
||||
#define PRICES_MMM (KOMODO_MAXPRICES * 7)
|
||||
#define PRICES_DDD (KOMODO_MAXPRICES * 8)
|
||||
|
||||
bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
|
||||
// CCcustom
|
||||
UniValue PricesBet(uint64_t txfee,int64_t amount,int16_t leverage,std::vector<std::string> synthetic);
|
||||
UniValue PricesAddFunding(uint64_t txfee,uint256 bettxid,int64_t amount);
|
||||
UniValue PricesSetcostbasis(uint64_t txfee,uint256 bettxid);
|
||||
UniValue PricesRekt(uint64_t txfee,uint256 bettxid,int32_t rektheight);
|
||||
UniValue PricesCashout(uint64_t txfee,uint256 bettxid);
|
||||
UniValue PricesInfo(uint256 bettxid,int32_t refheight);
|
||||
UniValue PricesList();
|
||||
UniValue PricesInfo(uint256 fundingtxid);
|
||||
UniValue PricesStatus(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,uint256 bettxid);
|
||||
std::string PricesCreateFunding(uint64_t txfee,uint256 bettoken,uint256 oracletxid,uint64_t margin,uint64_t mode,uint256 longtoken,uint256 shorttoken,int32_t maxleverage,int64_t funding,std::vector<CPubKey> pubkeys);
|
||||
std::string PricesAddFunding(uint64_t txfee,uint256 bettoken,uint256 fundingtxid,int64_t amount);
|
||||
std::string PricesBet(uint64_t txfee,uint256 bettoken,uint256 fundingtxid,int64_t amount,int32_t leverage);
|
||||
std::string PricesFinish(uint64_t txfee,uint256 bettoken,uint256 fundingtxid,uint256 bettxid);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "CCPayments.h"
|
||||
#include "CCGateways.h"
|
||||
#include "CCtokens.h"
|
||||
#include "CCImportGateway.h"
|
||||
|
||||
/*
|
||||
CCcustom has most of the functions that need to be extended to create a new CC contract.
|
||||
@@ -63,7 +64,6 @@ const char *AssetsCCaddr = "RGKRjeTBw4LYFotSDLT6RWzMHbhXri6BG6";
|
||||
const char *AssetsNormaladdr = "RFYE2yL3KknWdHK6uNhvWacYsCUtwzjY3u";
|
||||
char AssetsCChexstr[67] = { "02adf84e0e075cf90868bd4e3d34a03420e034719649c41f371fc70d8e33aa2702" };
|
||||
uint8_t AssetsCCpriv[32] = { 0x9b, 0x17, 0x66, 0xe5, 0x82, 0x66, 0xac, 0xb6, 0xba, 0x43, 0x83, 0x74, 0xf7, 0x63, 0x11, 0x3b, 0xf0, 0xf3, 0x50, 0x6f, 0xd9, 0x6b, 0x67, 0x85, 0xf9, 0x7a, 0xf0, 0x54, 0x4d, 0xb1, 0x30, 0x77 };
|
||||
|
||||
#include "CCcustom.inc"
|
||||
#undef FUNCNAME
|
||||
#undef EVALCODE
|
||||
@@ -75,7 +75,6 @@ const char *FaucetCCaddr = "R9zHrofhRbub7ER77B7NrVch3A63R39GuC";
|
||||
const char *FaucetNormaladdr = "RKQV4oYs4rvxAWx1J43VnT73rSTVtUeckk";
|
||||
char FaucetCChexstr[67] = { "03682b255c40d0cde8faee381a1a50bbb89980ff24539cb8518e294d3a63cefe12" };
|
||||
uint8_t FaucetCCpriv[32] = { 0xd4, 0x4f, 0xf2, 0x31, 0x71, 0x7d, 0x28, 0x02, 0x4b, 0xc7, 0xdd, 0x71, 0xa0, 0x39, 0xc4, 0xbe, 0x1a, 0xfe, 0xeb, 0xc2, 0x46, 0xda, 0x76, 0xf8, 0x07, 0x53, 0x3d, 0x96, 0xb4, 0xca, 0xa0, 0xe9 };
|
||||
|
||||
#include "CCcustom.inc"
|
||||
#undef FUNCNAME
|
||||
#undef EVALCODE
|
||||
@@ -243,6 +242,17 @@ uint8_t CClibCCpriv[32] = { 0x57, 0xcf, 0x49, 0x71, 0x7d, 0xb4, 0x15, 0x1b, 0x4f
|
||||
#undef FUNCNAME
|
||||
#undef EVALCODE
|
||||
|
||||
// ImportGateway
|
||||
#define FUNCNAME IsImportGatewayInput
|
||||
#define EVALCODE EVAL_IMPORTGATEWAY
|
||||
const char *ImportGatewayCCaddr = "RXJT6CRAXHFuQ2UjqdxMj7EfrayF6UJpzZ";
|
||||
const char *ImportGatewayNormaladdr = "RNFRho63Ddz1Rh2eGPETykrU4fA8r67S4Y";
|
||||
char ImportGatewayCChexstr[67] = { "0397231cfe04ea32d5fafb2206773ec9fba6e15c5a4e86064468bca195f7542714" };
|
||||
uint8_t ImportGatewayCCpriv[32] = { 0x65, 0xef, 0x27, 0xeb, 0x3d, 0xb0, 0xb4, 0xae, 0x0f, 0xbc, 0x77, 0xdb, 0xf8, 0x40, 0x48, 0x90, 0x52, 0x20, 0x9e, 0x45, 0x3b, 0x49, 0xd8, 0x97, 0x60, 0x8c, 0x27, 0x4c, 0x59, 0x46, 0xe1, 0xdf };
|
||||
#include "CCcustom.inc"
|
||||
#undef FUNCNAME
|
||||
#undef EVALCODE
|
||||
|
||||
int32_t CClib_initcp(struct CCcontract_info *cp,uint8_t evalcode)
|
||||
{
|
||||
CPubKey pk; int32_t i; uint8_t pub33[33],check33[33],hash[32]; char CCaddr[64],checkaddr[64],str[67];
|
||||
@@ -425,6 +435,14 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode)
|
||||
cp->validate = TokensValidate;
|
||||
cp->ismyvin = IsTokensInput;
|
||||
break;
|
||||
case EVAL_IMPORTGATEWAY:
|
||||
strcpy(cp->unspendableCCaddr, ImportGatewayCCaddr);
|
||||
strcpy(cp->normaladdr, ImportGatewayNormaladdr);
|
||||
strcpy(cp->CChexstr, ImportGatewayCChexstr);
|
||||
memcpy(cp->CCpriv, ImportGatewayCCpriv, 32);
|
||||
cp->validate = ImportGatewayValidate;
|
||||
cp->ismyvin = IsImportGatewayInput;
|
||||
break;
|
||||
default:
|
||||
if ( CClib_initcp(cp,evalcode) < 0 )
|
||||
return(0);
|
||||
|
||||
@@ -51,6 +51,7 @@ one other technical note is that komodod has the insight-explorer extensions bui
|
||||
#include "../komodo_defs.h"
|
||||
#include "../utlist.h"
|
||||
#include "../uthash.h"
|
||||
#include "merkleblock.h"
|
||||
|
||||
#define CC_BURNPUBKEY "02deaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddead"
|
||||
#define CC_MAXVINS 1024
|
||||
@@ -185,9 +186,12 @@ bool GetCCParams(Eval* eval, const CTransaction &tx, uint32_t nIn,
|
||||
CTransaction &txOut, std::vector<std::vector<unsigned char>> &preConditions, std::vector<std::vector<unsigned char>> ¶ms);
|
||||
|
||||
int64_t OraclePrice(int32_t height,uint256 reforacletxid,char *markeraddr,char *format);
|
||||
uint8_t DecodeOraclesCreateOpRet(const CScript &scriptPubKey,std::string &name,std::string &description,std::string &format);
|
||||
uint256 OracleMerkle(int32_t height,uint256 reforacletxid,char *format,std::vector<struct oracle_merklepair>publishers);
|
||||
uint256 OraclesBatontxid(uint256 oracletxid,CPubKey pk);
|
||||
uint8_t DecodeOraclesCreateOpRet(const CScript &scriptPubKey,std::string &name,std::string &description,std::string &format);
|
||||
uint8_t DecodeOraclesOpRet(const CScript &scriptPubKey,uint256 &oracletxid,CPubKey &pk,int64_t &num);
|
||||
uint8_t DecodeOraclesData(const CScript &scriptPubKey,uint256 &oracletxid,uint256 &batontxid,CPubKey &pk,std::vector <uint8_t>&data);
|
||||
int32_t oracle_format(uint256 *hashp,int64_t *valp,char *str,uint8_t fmt,uint8_t *data,int32_t offset,int32_t datalen);
|
||||
|
||||
//int64_t AddAssetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 assetid,int64_t total,int32_t maxinputs);
|
||||
int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 tokenid, int64_t total, int32_t maxinputs);
|
||||
@@ -195,6 +199,9 @@ int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, C
|
||||
int64_t IsTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 reftokenid);
|
||||
|
||||
bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx);
|
||||
void komodo_sendmessage(int32_t minpeers,int32_t maxpeers,const char *message,std::vector<uint8_t> payload);
|
||||
int32_t payments_parsehexdata(std::vector<uint8_t> &hexdata,cJSON *item,int32_t len);
|
||||
int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex);
|
||||
|
||||
CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector<uint8_t> origpubkey, std::string name, std::string description, vscript_t vopretNonfungible);
|
||||
CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector<uint8_t> origpubkey, std::string name, std::string description, std::vector<std::pair<uint8_t, vscript_t>> oprets);
|
||||
@@ -209,11 +216,6 @@ uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCodeTokens, ui
|
||||
void GetNonfungibleData(uint256 tokenid, vscript_t &vopretNonfungible);
|
||||
bool ExtractTokensCCVinPubkeys(const CTransaction &tx, std::vector<CPubKey> &vinPubkeys);
|
||||
|
||||
uint8_t DecodeOraclesData(const CScript &scriptPubKey,uint256 &oracletxid,uint256 &batontxid,CPubKey &pk,std::vector <uint8_t>&data);
|
||||
int32_t oracle_format(uint256 *hashp,int64_t *valp,char *str,uint8_t fmt,uint8_t *data,int32_t offset,int32_t datalen);
|
||||
|
||||
|
||||
|
||||
// CCcustom
|
||||
CPubKey GetUnspendable(struct CCcontract_info *cp,uint8_t *unspendablepriv);
|
||||
//uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCodeTokens, uint256 &tokenid, std::vector<CPubKey> &voutPubkeys, std::vector<uint8_t> &vopret1, std::vector<uint8_t> &vopret2);
|
||||
@@ -245,6 +247,7 @@ void CCaddrTokens1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, c
|
||||
int32_t CClib_initcp(struct CCcontract_info *cp,uint8_t evalcode);
|
||||
|
||||
bool IsCCInput(CScript const& scriptSig);
|
||||
bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_t blocktime);
|
||||
int32_t unstringbits(char *buf,uint64_t bits);
|
||||
uint64_t stringbits(char *str);
|
||||
uint256 revuint256(uint256 txid);
|
||||
@@ -266,6 +269,9 @@ bool GetCustomscriptaddress(char *destaddr,const CScript &scriptPubKey,uint8_t t
|
||||
std::vector<uint8_t> Mypubkey();
|
||||
bool Myprivkey(uint8_t myprivkey[]);
|
||||
int64_t CCduration(int32_t &numblocks,uint256 txid);
|
||||
uint256 CCOraclesReverseScan(char const *logcategory,uint256 &txid,int32_t height,uint256 reforacletxid,uint256 batontxid);
|
||||
int32_t CCCointxidExists(char const *logcategory,uint256 cointxid);
|
||||
uint256 BitcoinGetProofMerkleRoot(const std::vector<uint8_t> &proofData, std::vector<uint256> &txids);
|
||||
bool komodo_txnotarizedconfirmed(uint256 txid);
|
||||
CPubKey check_signing_pubkey(CScript scriptSig);
|
||||
// CCtx
|
||||
|
||||
@@ -586,8 +586,7 @@ int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, C
|
||||
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "AddTokenCCInputs() no utxos for token dual/three eval addr=" << tokenaddr << " evalcode=" << (int)cp->evalcode << " additionalTokensEvalcode2=" << (int)cp->additionalTokensEvalcode2 << std::endl);
|
||||
}
|
||||
|
||||
threshold = total / (maxinputs != 0 ? maxinputs : 64); // TODO: maxinputs really could not be over 64? what if i want to calc total balance for all available uxtos?
|
||||
// maybe it is better to add all uxtos if maxinputs == 0
|
||||
threshold = total / (maxinputs != 0 ? maxinputs : CC_MAXVINS);
|
||||
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++)
|
||||
{
|
||||
|
||||
@@ -48,7 +48,7 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
|
||||
int32_t i,flag,utxovout,n,err = 0;
|
||||
char myaddr[64], destaddr[64], unspendable[64], mytokensaddr[64], mysingletokensaddr[64], unspendabletokensaddr[64],CC1of2CCaddr[64];
|
||||
uint8_t *privkey, myprivkey[32], unspendablepriv[32], /*tokensunspendablepriv[32],*/ *msg32 = 0;
|
||||
CC *mycond=0, *othercond=0, *othercond2=0,*othercond4=0, *othercond3=0, *othercond1of2=NULL, *othercond1of2tokens = NULL, *cond, *condCC2=0,*mytokenscond = NULL, *mysingletokenscond = NULL, *othertokenscond = NULL;
|
||||
CC *mycond=0, *othercond=0, *othercond2=0,*othercond4=0, *othercond3=0, *othercond1of2=NULL, *othercond1of2tokens = NULL, *cond=0, *condCC2=0,*mytokenscond = NULL, *mysingletokenscond = NULL, *othertokenscond = NULL;
|
||||
CPubKey unspendablepk /*, tokensunspendablepk*/;
|
||||
struct CCcontract_info *cpTokens, tokensC;
|
||||
globalpk = GetUnspendable(cp,0);
|
||||
@@ -75,7 +75,7 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
|
||||
othercond = MakeCCcond1(cp->evalcode, unspendablepk);
|
||||
GetCCaddress1of2(cp,CC1of2CCaddr,unspendablepk,unspendablepk);
|
||||
|
||||
//printf("evalcode.%d (%s)\n",cp->evalcode,unspendable);
|
||||
//fprintf(stderr,"evalcode.%d (%s)\n",cp->evalcode,unspendable);
|
||||
|
||||
// tokens support:
|
||||
// to spend from dual/three-eval mypk vout
|
||||
@@ -277,7 +277,7 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
|
||||
}
|
||||
}
|
||||
} else fprintf(stderr,"FinalizeCCTx couldnt find %s\n",mtx.vin[i].prevout.hash.ToString().c_str());
|
||||
}
|
||||
}
|
||||
if ( mycond != 0 )
|
||||
cc_free(mycond);
|
||||
if ( condCC2 != 0 )
|
||||
@@ -509,16 +509,18 @@ int32_t CC_vinselect(int32_t *aboveip,int64_t *abovep,int32_t *belowip,int64_t *
|
||||
|
||||
int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs)
|
||||
{
|
||||
int32_t abovei,belowi,ind,vout,i,n = 0,maxutxos=CC_MAXVINS; int64_t sum,threshold,above,below; int64_t remains,nValue,totalinputs = 0; uint256 txid,hashBlock; std::vector<COutput> vecOutputs; CTransaction tx; struct CC_utxo *utxos,*up;
|
||||
int32_t abovei,belowi,ind,vout,i,n = 0; int64_t sum,threshold,above,below; int64_t remains,nValue,totalinputs = 0; uint256 txid,hashBlock; std::vector<COutput> vecOutputs; CTransaction tx; struct CC_utxo *utxos,*up;
|
||||
#ifdef ENABLE_WALLET
|
||||
assert(pwalletMain != NULL);
|
||||
const CKeyStore& keystore = *pwalletMain;
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
|
||||
utxos = (struct CC_utxo *)calloc(maxutxos,sizeof(*utxos));
|
||||
threshold = total/(maxinputs+1);
|
||||
if ( maxinputs > maxutxos )
|
||||
maxutxos = maxinputs;
|
||||
utxos = (struct CC_utxo *)calloc(CC_MAXVINS,sizeof(*utxos));
|
||||
if ( maxinputs > CC_MAXVINS )
|
||||
maxinputs = CC_MAXVINS;
|
||||
if ( maxinputs > 0 )
|
||||
threshold = total/maxinputs;
|
||||
else threshold = total;
|
||||
sum = 0;
|
||||
BOOST_FOREACH(const COutput& out, vecOutputs)
|
||||
{
|
||||
@@ -553,7 +555,7 @@ int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int3
|
||||
up->vout = vout;
|
||||
sum += up->nValue;
|
||||
//fprintf(stderr,"add %.8f to vins array.%d of %d\n",(double)up->nValue/COIN,n,maxutxos);
|
||||
if ( n >= maxutxos || sum >= total )
|
||||
if ( n >= maxinputs || sum >= total )
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -599,15 +601,16 @@ int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int3
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int64_t AddNormalinputs2(CMutableTransaction &mtx,int64_t total,int32_t maxinputs)
|
||||
{
|
||||
int32_t abovei,belowi,ind,vout,i,n = 0,maxutxos=CC_MAXVINS; int64_t sum,threshold,above,below; int64_t remains,nValue,totalinputs = 0; char coinaddr[64]; uint256 txid,hashBlock; CTransaction tx; struct CC_utxo *utxos,*up;
|
||||
int32_t abovei,belowi,ind,vout,i,n = 0; int64_t sum,threshold,above,below; int64_t remains,nValue,totalinputs = 0; char coinaddr[64]; uint256 txid,hashBlock; CTransaction tx; struct CC_utxo *utxos,*up;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
utxos = (struct CC_utxo *)calloc(maxutxos,sizeof(*utxos));
|
||||
threshold = total/(maxinputs+1);
|
||||
if ( maxinputs > maxutxos )
|
||||
maxutxos = maxinputs;
|
||||
utxos = (struct CC_utxo *)calloc(CC_MAXVINS,sizeof(*utxos));
|
||||
if ( maxinputs > CC_MAXVINS )
|
||||
maxinputs = CC_MAXVINS;
|
||||
if ( maxinputs > 0 )
|
||||
threshold = total/maxinputs;
|
||||
else threshold = total;
|
||||
sum = 0;
|
||||
Getscriptaddress(coinaddr,CScript() << Mypubkey() << OP_CHECKSIG);
|
||||
SetCCunspents(unspentOutputs,coinaddr);
|
||||
@@ -644,7 +647,7 @@ int64_t AddNormalinputs2(CMutableTransaction &mtx,int64_t total,int32_t maxinput
|
||||
up->vout = vout;
|
||||
sum += up->nValue;
|
||||
//fprintf(stderr,"add %.8f to vins array.%d of %d\n",(double)up->nValue/COIN,n,maxutxos);
|
||||
if ( n >= maxutxos || sum >= total )
|
||||
if ( n >= maxinputs || sum >= total )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,6 +168,18 @@ bool IsCCInput(CScript const& scriptSig)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_t blocktime)
|
||||
{
|
||||
int64_t interest; uint64_t valuein;
|
||||
CCoinsViewCache &view = *pcoinsTip;
|
||||
valuein = view.GetValueIn(height,&interest,tx,blocktime);
|
||||
if ( valuein-tx.GetValueOut() > txfee )
|
||||
{
|
||||
//fprintf(stderr, "txfee.%li vs txfee.%li\n", valuein-tx.GetValueOut(), txfee);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// set additional 'unspendable' addr
|
||||
void CCaddr2set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr)
|
||||
@@ -520,6 +532,95 @@ int64_t CCduration(int32_t &numblocks,uint256 txid)
|
||||
return(duration);
|
||||
}
|
||||
|
||||
uint256 CCOraclesReverseScan(char const *logcategory,uint256 &txid,int32_t height,uint256 reforacletxid,uint256 batontxid)
|
||||
{
|
||||
CTransaction tx; uint256 hash,mhash,bhash,hashBlock,oracletxid; int32_t len,len2,numvouts;
|
||||
int64_t val,merkleht; CPubKey pk; std::vector<uint8_t>data; char str[65],str2[65];
|
||||
|
||||
txid = zeroid;
|
||||
LogPrint(logcategory,"start reverse scan %s\n",uint256_str(str,batontxid));
|
||||
while ( myGetTransaction(batontxid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 0 )
|
||||
{
|
||||
LogPrint(logcategory,"check %s\n",uint256_str(str,batontxid));
|
||||
if ( DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,bhash,pk,data) == 'D' && oracletxid == reforacletxid )
|
||||
{
|
||||
LogPrint(logcategory,"decoded %s\n",uint256_str(str,batontxid));
|
||||
if ( oracle_format(&hash,&merkleht,0,'I',(uint8_t *)data.data(),0,(int32_t)data.size()) == sizeof(int32_t) && merkleht == height )
|
||||
{
|
||||
len = oracle_format(&hash,&val,0,'h',(uint8_t *)data.data(),sizeof(int32_t),(int32_t)data.size());
|
||||
len2 = oracle_format(&mhash,&val,0,'h',(uint8_t *)data.data(),(int32_t)(sizeof(int32_t)+sizeof(uint256)),(int32_t)data.size());
|
||||
|
||||
LogPrint(logcategory,"found merkleht.%d len.%d len2.%d %s %s\n",(int32_t)merkleht,len,len2,uint256_str(str,hash),uint256_str(str2,mhash));
|
||||
if ( len == sizeof(hash)+sizeof(int32_t) && len2 == 2*sizeof(mhash)+sizeof(int32_t) && mhash != zeroid )
|
||||
{
|
||||
txid = batontxid;
|
||||
LogPrint(logcategory,"set txid\n");
|
||||
return(mhash);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint(logcategory,"missing hash\n");
|
||||
return(zeroid);
|
||||
}
|
||||
}
|
||||
else LogPrint(logcategory,"height.%d vs search ht.%d\n",(int32_t)merkleht,(int32_t)height);
|
||||
batontxid = bhash;
|
||||
LogPrint(logcategory,"new hash %s\n",uint256_str(str,batontxid));
|
||||
} else break;
|
||||
}
|
||||
LogPrint(logcategory,"end of loop\n");
|
||||
return(zeroid);
|
||||
}
|
||||
|
||||
int32_t myIs_coinaddr_inmempoolvout(char const *logcategory,char *coinaddr)
|
||||
{
|
||||
int32_t i,n; char destaddr[64];
|
||||
BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx)
|
||||
{
|
||||
const CTransaction &tx = e.GetTx();
|
||||
if ( (n= tx.vout.size()) > 0 )
|
||||
{
|
||||
const uint256 &txid = tx.GetHash();
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
Getscriptaddress(destaddr,tx.vout[i].scriptPubKey);
|
||||
if ( strcmp(destaddr,coinaddr) == 0 )
|
||||
{
|
||||
LogPrint(logcategory,"found (%s) vout in mempool\n",coinaddr);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t CCCointxidExists(char const *logcategory,uint256 cointxid)
|
||||
{
|
||||
char txidaddr[64]; std::string coin; int32_t numvouts; uint256 hashBlock;
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
|
||||
CCtxidaddr(txidaddr,cointxid);
|
||||
SetCCtxids(addressIndex,txidaddr);
|
||||
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++)
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
return(myIs_coinaddr_inmempoolvout(logcategory,txidaddr));
|
||||
}
|
||||
|
||||
/* Get the block merkle root for a proof
|
||||
* IN: proofData
|
||||
* OUT: merkle root
|
||||
* OUT: transaction IDS
|
||||
*/
|
||||
uint256 BitcoinGetProofMerkleRoot(const std::vector<uint8_t> &proofData, std::vector<uint256> &txids)
|
||||
{
|
||||
CMerkleBlock merkleBlock;
|
||||
if (!E_UNMARSHAL(proofData, ss >> merkleBlock))
|
||||
return uint256();
|
||||
return merkleBlock.txn.ExtractMatches(txids);
|
||||
}
|
||||
|
||||
bool komodo_txnotarizedconfirmed(uint256 txid)
|
||||
{
|
||||
char str[65];
|
||||
@@ -668,4 +769,4 @@ bool CClib_Dispatch(const CC *cond,Eval *eval,std::vector<uint8_t> paramsNull,co
|
||||
return(false); //eval->Invalid("error in CClib_validate");
|
||||
}
|
||||
return eval->Invalid("cclib CC must have evalcode between 16 and 127");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,9 @@ std::string MYCCLIBNAME = (char *)"rogue";
|
||||
#elif BUILD_CUSTOMCC
|
||||
#include "customcc.h"
|
||||
|
||||
#elif BUILD_GAMESCC
|
||||
#include "gamescc.h"
|
||||
|
||||
#else
|
||||
#define EVAL_SUDOKU 17
|
||||
#define EVAL_MUSIG 18
|
||||
@@ -45,6 +48,12 @@ std::string MYCCLIBNAME = (char *)"rogue";
|
||||
std::string MYCCLIBNAME = (char *)"sudoku";
|
||||
#endif
|
||||
|
||||
#ifndef BUILD_GAMESCC
|
||||
void komodo_netevent(std::vector<uint8_t> payload) {}
|
||||
#endif
|
||||
|
||||
extern std::string MYCCLIBNAME;
|
||||
|
||||
char *CClib_name() { return((char *)MYCCLIBNAME.c_str()); }
|
||||
|
||||
struct CClib_rpcinfo
|
||||
@@ -73,6 +82,8 @@ CClib_methods[] =
|
||||
{ (char *)"rogue", (char *)"extract", (char *)"gametxid [pubkey]", 1, 2, 'X', EVAL_ROGUE },
|
||||
#elif BUILD_CUSTOMCC
|
||||
RPC_FUNCS
|
||||
#elif BUILD_GAMESCC
|
||||
RPC_FUNCS
|
||||
#else
|
||||
{ (char *)"sudoku", (char *)"gen", (char *)"<no args>", 0, 0, 'G', EVAL_SUDOKU },
|
||||
{ (char *)"sudoku", (char *)"txidinfo", (char *)"txid", 1, 1, 'T', EVAL_SUDOKU },
|
||||
@@ -184,7 +195,7 @@ cJSON *cclib_reparse(int32_t *nump,char *jsonstr) // assumes origparams will be
|
||||
UniValue CClib_method(struct CCcontract_info *cp,char *method,char *jsonstr)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ); uint64_t txfee = 10000; int32_t m; cJSON *params = cclib_reparse(&m,jsonstr);
|
||||
//fprintf(stderr,"method.(%s) -> (%s)\n",jsonstr!=0?jsonstr:"",params!=0?jprint(params,0):"");
|
||||
fprintf(stderr,"method.(%s) -> (%s)\n",jsonstr!=0?jsonstr:"",params!=0?jprint(params,0):"");
|
||||
#ifdef BUILD_ROGUE
|
||||
if ( cp->evalcode == EVAL_ROGUE )
|
||||
{
|
||||
@@ -222,6 +233,8 @@ UniValue CClib_method(struct CCcontract_info *cp,char *method,char *jsonstr)
|
||||
}
|
||||
#elif BUILD_CUSTOMCC
|
||||
CUSTOM_DISPATCH
|
||||
#elif BUILD_GAMESCC
|
||||
CUSTOM_DISPATCH
|
||||
#else
|
||||
if ( cp->evalcode == EVAL_SUDOKU )
|
||||
{
|
||||
@@ -338,7 +351,7 @@ UniValue CClib_info(struct CCcontract_info *cp)
|
||||
UniValue CClib(struct CCcontract_info *cp,char *method,char *jsonstr)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ); int32_t i; std::string rawtx; cJSON *params;
|
||||
//printf("CClib params.(%s)\n",jsonstr!=0?jsonstr:"");
|
||||
//printf("CClib params.(%s)\n",jsonstr!=0?jsonstr:"");
|
||||
for (i=0; i<sizeof(CClib_methods)/sizeof(*CClib_methods); i++)
|
||||
{
|
||||
if ( cp->evalcode == CClib_methods[i].evalcode && strcmp(method,CClib_methods[i].method) == 0 )
|
||||
@@ -356,7 +369,7 @@ UniValue CClib(struct CCcontract_info *cp,char *method,char *jsonstr)
|
||||
}
|
||||
}
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("method",CClib_methods[i].method));
|
||||
result.push_back(Pair("method",method));
|
||||
result.push_back(Pair("error","method not found"));
|
||||
return(result);
|
||||
}
|
||||
@@ -420,6 +433,8 @@ bool CClib_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const C
|
||||
return(rogue_validate(cp,height,eval,tx));
|
||||
#elif BUILD_CUSTOMCC
|
||||
return(custom_validate(cp,height,eval,tx));
|
||||
#elif BUILD_GAMESCC
|
||||
return(games_validate(cp,height,eval,tx));
|
||||
#else
|
||||
if ( cp->evalcode == EVAL_SUDOKU )
|
||||
return(sudoku_validate(cp,height,eval,tx));
|
||||
@@ -492,6 +507,8 @@ int64_t AddCClibInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubK
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
GetCCaddress(cp,coinaddr,pk);
|
||||
SetCCunspents(unspentOutputs,coinaddr);
|
||||
if ( maxinputs > CC_MAXVINS )
|
||||
maxinputs = CC_MAXVINS;
|
||||
if ( maxinputs != 0 )
|
||||
threshold = total/maxinputs;
|
||||
else threshold = total;
|
||||
@@ -675,6 +692,10 @@ int32_t cclib_parsehash(uint8_t *hash32,cJSON *item,int32_t len)
|
||||
#elif BUILD_CUSTOMCC
|
||||
#include "customcc.cpp"
|
||||
|
||||
#elif BUILD_GAMESCC
|
||||
#include "rogue/cursesd.c"
|
||||
#include "gamescc.cpp"
|
||||
|
||||
#else
|
||||
#include "sudoku.cpp"
|
||||
#include "musig.cpp"
|
||||
|
||||
@@ -62,6 +62,8 @@ Possible third iteration:
|
||||
|
||||
// start of consensus code
|
||||
|
||||
#define CC_MARKER_VALUE 10000
|
||||
|
||||
int64_t IsChannelsvout(struct CCcontract_info *cp,const CTransaction& tx,CPubKey srcpub, CPubKey destpub,int32_t v)
|
||||
{
|
||||
char destaddr[65],channeladdr[65],tokenschanneladdr[65];
|
||||
@@ -126,8 +128,8 @@ uint8_t DecodeChannelsOpRet(const CScript &scriptPubKey, uint256 &tokenid, uint2
|
||||
{
|
||||
return(f);
|
||||
}
|
||||
} else fprintf(stderr,"script[0] %02x != EVAL_CHANNELS\n",script[0]);
|
||||
} else fprintf(stderr,"not enough opret.[%d]\n",(int32_t)vopret.size());
|
||||
} else LOGSTREAM("channelscc",CCLOG_DEBUG1, stream << "script[0] " << script[0] << " != EVAL_CHANNELS" << std::endl);
|
||||
} else LOGSTREAM("channelscc",CCLOG_DEBUG1, stream << "not enough opret.[" << vopret.size() << "]" << std::endl);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -167,7 +169,7 @@ bool ChannelsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransacti
|
||||
}
|
||||
if ( inputs != outputs )
|
||||
{
|
||||
fprintf(stderr,"inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs);
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << "inputs " << inputs << " vs outputs " << outputs << std::endl);
|
||||
return eval->Invalid("mismatched inputs != outputs");
|
||||
}
|
||||
else return (true);
|
||||
@@ -183,7 +185,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
{
|
||||
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numpayments,p1,param1; bool retval;
|
||||
uint256 txid,hashblock,p3,param3,opentxid,tmp_txid,genhashchain,hashchain,tokenid;
|
||||
uint8_t funcid,hash[32],hashdest[32];
|
||||
uint8_t funcid,hash[32],hashdest[32]; char channeladdress[65],srcmarker[65],destmarker[65],destaddr[65],srcaddr[65],desttokensaddr[65],srctokensaddr[65];
|
||||
int64_t p2,param2,payment;
|
||||
CPubKey srcpub, destpub;
|
||||
CTransaction channelOpenTx,channelCloseTx,prevTx;
|
||||
@@ -202,9 +204,20 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
else
|
||||
{
|
||||
txid = tx.GetHash();
|
||||
memcpy(hash,&txid,sizeof(hash));
|
||||
memcpy(hash,&txid,sizeof(hash));
|
||||
if ( (funcid = DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey, tokenid, opentxid, srcpub, destpub, param1, param2, param3)) != 0)
|
||||
{
|
||||
if (myGetTransaction(opentxid,channelOpenTx,hashblock)== 0)
|
||||
return eval->Invalid("invalid channelopen tx!");
|
||||
else if ((numvouts=channelOpenTx.vout.size()) > 0 && (DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, numpayments, payment, hashchain)) != 'O')
|
||||
return eval->Invalid("invalid channelopen OP_RETURN data!");
|
||||
GetCCaddress1of2(cp,channeladdress,srcpub,destpub);
|
||||
GetCCaddress(cp,srcmarker,srcpub);
|
||||
GetCCaddress(cp,destmarker,destpub);
|
||||
Getscriptaddress(srcaddr,CScript() << ParseHex(HexStr(srcpub)) << OP_CHECKSIG);
|
||||
Getscriptaddress(destaddr,CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG);
|
||||
_GetCCaddress(srctokensaddr,EVAL_TOKENS,srcpub);
|
||||
_GetCCaddress(desttokensaddr,EVAL_TOKENS,destpub);
|
||||
switch ( funcid )
|
||||
{
|
||||
case 'O':
|
||||
@@ -225,56 +238,53 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
//vout.3: normal output of payment amount to receiver pubkey
|
||||
//vout.n-2: normal change
|
||||
//vout.n-1: opreturn - 'P' opentxid senderspubkey receiverspubkey depth numpayments secret
|
||||
if (komodo_txnotarizedconfirmed(opentxid) == 0)
|
||||
return eval->Invalid("channelOpen is not yet confirmed(notarised)!");
|
||||
if ( IsCCInput(channelOpenTx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for channelopen!");
|
||||
else if ( ConstrainVout(channelOpenTx.vout[0],1,channeladdress,numpayments*payment)==0 )
|
||||
return eval->Invalid("vout.0 is CC or invalid amount for channelopen!");
|
||||
else if ( ConstrainVout(channelOpenTx.vout[1],1,srcmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.1 is CC marker to srcpub or invalid amount for channelopen!");
|
||||
else if ( ConstrainVout(channelOpenTx.vout[2],1,destmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.2 is CC marker to destpub or invalid amount for channelopen!");
|
||||
else if (komodo_txnotarizedconfirmed(opentxid) == 0)
|
||||
return eval->Invalid("channelopen is not yet confirmed(notarised)!");
|
||||
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for channelPayment!");
|
||||
return eval->Invalid("vin.0 is normal for channelpayment!");
|
||||
else if ( IsCCInput(tx.vin[1].scriptSig) == 0 )
|
||||
return eval->Invalid("vin.1 is CC for channelPayment!");
|
||||
return eval->Invalid("vin.1 is CC for channelpayment!");
|
||||
else if ( IsCCInput(tx.vin[2].scriptSig) == 0 )
|
||||
return eval->Invalid("vin.2 is CC for channelPayment!");
|
||||
else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition()==0 )
|
||||
return eval->Invalid("vout.0 is CC for channelPayment!");
|
||||
else if ( IsChannelsMarkervout(cp,tx,srcpub,1)==0 )
|
||||
return eval->Invalid("vout.1 is CC for channelPayment (marker to srcPub)!");
|
||||
else if ( IsChannelsMarkervout(cp,tx,destpub,2)==0 )
|
||||
return eval->Invalid("vout.2 is CC for channelPayment (marker to dstPub)!");
|
||||
else if ( tokenid!=zeroid && tx.vout[3].scriptPubKey.IsPayToCryptoCondition() == 0 )
|
||||
return eval->Invalid("vout.3 is CC for channelPayment!");
|
||||
else if ( tokenid==zeroid && tx.vout[3].scriptPubKey.IsPayToCryptoCondition() != 0 )
|
||||
return eval->Invalid("vout.3 is normal for channelPayment!");
|
||||
else if ( tokenid!=zeroid && tx.vout[3].scriptPubKey!=MakeCC1vout(EVAL_TOKENS,tx.vout[3].nValue,destpub).scriptPubKey)
|
||||
return eval->Invalid("payment funds do not go to receiver!");
|
||||
else if ( tokenid==zeroid && tx.vout[3].scriptPubKey!=CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG)
|
||||
return eval->Invalid("payment funds do not go to receiver!");
|
||||
return eval->Invalid("vin.2 is CC for channelpayment!");
|
||||
else if ( ConstrainVout(tx.vout[1],1,srcmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.1 is CC marker to srcpub or invalid amount for channelpayment!");
|
||||
else if ( ConstrainVout(tx.vout[2],1,destmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.2 is CC marker to destpub or invalid amount for channelpayment!");
|
||||
else if ( tokenid!=zeroid && ConstrainVout(tx.vout[3],1,desttokensaddr,param2*payment)==0 )
|
||||
return eval->Invalid("vout.3 is CC or invalid amount or invalid receiver for channelpayment!");
|
||||
else if ( tokenid==zeroid && ConstrainVout(tx.vout[3],0,destaddr,param2*payment)==0 )
|
||||
return eval->Invalid("vout.3 is normal or invalid amount or invalid receiver for channelpayment!");
|
||||
else if ( param1 > CHANNELS_MAXPAYMENTS)
|
||||
return eval->Invalid("too many payment increments!");
|
||||
else
|
||||
{
|
||||
if (myGetTransaction(opentxid,channelOpenTx,hashblock) != 0)
|
||||
{
|
||||
endiancpy(hash, (uint8_t * ) & param3, 32);
|
||||
for (i = 0; i < numpayments-param1; i++)
|
||||
{
|
||||
if ((numvouts=channelOpenTx.vout.size()) > 0 && (funcid=DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, numpayments, payment, hashchain)) != 0 && funcid!='O')
|
||||
return eval->Invalid("invalid channelopen OP_RETURN data!");
|
||||
endiancpy(hash, (uint8_t * ) & param3, 32);
|
||||
for (i = 0; i < numpayments-param1; i++)
|
||||
{
|
||||
vcalc_sha256(0, hashdest, hash, 32);
|
||||
memcpy(hash, hashdest, 32);
|
||||
}
|
||||
endiancpy((uint8_t*)&genhashchain,hashdest,32);
|
||||
if (hashchain!=genhashchain)
|
||||
return eval->Invalid("invalid secret for payment, does not reach final hashchain!");
|
||||
else if (tx.vout[3].nValue != param2*payment)
|
||||
return eval->Invalid("vout amount does not match number_of_payments*payment!");
|
||||
vcalc_sha256(0, hashdest, hash, 32);
|
||||
memcpy(hash, hashdest, 32);
|
||||
}
|
||||
endiancpy((uint8_t*)&genhashchain,hashdest,32);
|
||||
if (hashchain!=genhashchain)
|
||||
return eval->Invalid("invalid secret for payment, does not reach final hashchain!");
|
||||
else if (tx.vout[3].nValue != param2*payment)
|
||||
return eval->Invalid("vout amount does not match number_of_payments*payment!");
|
||||
if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0)
|
||||
{
|
||||
if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, p1, p2, p3) == 0)
|
||||
return eval->Invalid("invalid previous tx OP_RETURN data!");
|
||||
else if (tx.vout[1].scriptPubKey != prevTx.vout[1].scriptPubKey)
|
||||
return eval->Invalid("invalid destination for sender marker!");
|
||||
else if (tx.vout[2].scriptPubKey != prevTx.vout[2].scriptPubKey)
|
||||
return eval->Invalid("invalid destination for receiver marker!");
|
||||
else if ( ConstrainVout(tx.vout[0],1,channeladdress,(p1-param2)*payment)==0 )
|
||||
return eval->Invalid("vout.0 is CC or invalid CC change amount for channelpayment!");
|
||||
else if ((*cp->ismyvin)(tx.vin[2].scriptSig) == 0 || prevTx.vout[tx.vin[2].prevout.n].nValue!=CC_MARKER_VALUE)
|
||||
return eval->Invalid("vin.2 is CC marker or invalid marker amount for channelpayment!");
|
||||
else if (param1+param2!=p1)
|
||||
return eval->Invalid("invalid payment depth!");
|
||||
else if (tx.vout[3].nValue > prevTx.vout[0].nValue)
|
||||
@@ -290,37 +300,37 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
//vout.1: CC vout marker to senders pubKey
|
||||
//vout.2: CC vout marker to receiver pubkey
|
||||
//vout.n-2: normal change
|
||||
//vout.n-1: opreturn - 'C' opentxid senderspubkey receiverspubkey 0 0 0
|
||||
if (komodo_txnotarizedconfirmed(opentxid) == 0)
|
||||
return eval->Invalid("channelOpen is not yet confirmed(notarised)!");
|
||||
//vout.n-1: opreturn - 'C' opentxid senderspubkey receiverspubkey numpayments payment 0
|
||||
if ( IsCCInput(channelOpenTx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for channelopen!");
|
||||
else if ( ConstrainVout(channelOpenTx.vout[0],1,channeladdress,numpayments*payment)==0 )
|
||||
return eval->Invalid("vout.0 is CC or invalid amount for channelopen!");
|
||||
else if ( ConstrainVout(channelOpenTx.vout[1],1,srcmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.1 is CC marker to srcpub or invalid amount for channelopen!");
|
||||
else if ( ConstrainVout(channelOpenTx.vout[2],1,destmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.2 is CC marker to destpub or invalid amount for channelopen!");
|
||||
else if (komodo_txnotarizedconfirmed(opentxid) == 0)
|
||||
return eval->Invalid("channelopen is not yet confirmed(notarised)!");
|
||||
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for channelClose!");
|
||||
return eval->Invalid("vin.0 is normal for channelclose!");
|
||||
else if ( IsCCInput(tx.vin[1].scriptSig) == 0 )
|
||||
return eval->Invalid("vin.1 is CC for channelClose!");
|
||||
return eval->Invalid("vin.1 is CC for channelclose!");
|
||||
else if ( IsCCInput(tx.vin[2].scriptSig) == 0 )
|
||||
return eval->Invalid("vin.2 is CC for channelClose!");
|
||||
else if ( IsChannelsvout(cp,tx,srcpub,destpub,0)==0 )
|
||||
return eval->Invalid("vout.0 is CC for channelClose!");
|
||||
else if ( IsChannelsMarkervout(cp,tx,srcpub,1)==0 )
|
||||
return eval->Invalid("vout.1 is CC for channelClose (marker to srcPub)!");
|
||||
else if ( IsChannelsMarkervout(cp,tx,destpub,2)==0 )
|
||||
return eval->Invalid("vout.2 is CC for channelClose (marker to dstPub)!");
|
||||
return eval->Invalid("vin.2 is CC for channelclose!");
|
||||
else if ( ConstrainVout(tx.vout[0],1,channeladdress,0)==0 )
|
||||
return eval->Invalid("vout.0 is CC for channelclose!");
|
||||
else if ( ConstrainVout(tx.vout[1],1,srcmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.1 is CC marker to srcpub or invalid amount for channelclose!");
|
||||
else if ( ConstrainVout(tx.vout[2],1,destmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.2 is CC marker to destpub or invalid amount for channelclose!");
|
||||
else if ( param1 > CHANNELS_MAXPAYMENTS)
|
||||
return eval->Invalid("too many payment increments!");
|
||||
else if (myGetTransaction(opentxid,channelOpenTx,hashblock) == 0)
|
||||
return eval->Invalid("invalid open txid!");
|
||||
else if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, numpayments, payment, hashchain) != 'O')
|
||||
return eval->Invalid("invalid channelopen OP_RETURN data!");
|
||||
else if (tx.vout[0].nValue != param1*payment)
|
||||
return eval->Invalid("vout amount does not match number_of_payments*payment!");
|
||||
else if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0)
|
||||
{
|
||||
if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, p1, p2, p3) == 0)
|
||||
return eval->Invalid("invalid previous tx OP_RETURN data!");
|
||||
else if (tx.vout[1].scriptPubKey != prevTx.vout[1].scriptPubKey)
|
||||
return eval->Invalid("invalid destination for sender marker!");
|
||||
else if (tx.vout[2].scriptPubKey != prevTx.vout[2].scriptPubKey)
|
||||
return eval->Invalid("invalid destination for receiver marker!");
|
||||
else if ((*cp->ismyvin)(tx.vin[2].scriptSig) == 0 || prevTx.vout[tx.vin[2].prevout.n].nValue!=CC_MARKER_VALUE)
|
||||
return eval->Invalid("vin.2 is CC marker or invalid marker amount for channelclose!");
|
||||
else if (tx.vout[0].nValue != prevTx.vout[0].nValue)
|
||||
return eval->Invalid("invalid CC amount, amount must match funds in channel");
|
||||
}
|
||||
@@ -334,50 +344,40 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
//vout.2: normal output of CC input to senders pubkey
|
||||
//vout.n-2: normal change
|
||||
//vout.n-1: opreturn - 'R' opentxid senderspubkey receiverspubkey numpayments payment closetxid
|
||||
if (komodo_txnotarizedconfirmed(opentxid) == 0)
|
||||
return eval->Invalid("channelOpen is not yet confirmed(notarised)!");
|
||||
if ( IsCCInput(channelOpenTx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for channelopen!");
|
||||
else if ( ConstrainVout(channelOpenTx.vout[0],1,channeladdress,numpayments*payment)==0 )
|
||||
return eval->Invalid("vout.0 is CC or invalid amount for channelopen!");
|
||||
else if ( ConstrainVout(channelOpenTx.vout[1],1,srcmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.1 is CC marker to srcpub or invalid amount for channelopen!");
|
||||
else if ( ConstrainVout(channelOpenTx.vout[2],1,destmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.2 is CC marker to destpub or invalid amount for channelopen!");
|
||||
else if (komodo_txnotarizedconfirmed(opentxid) == 0)
|
||||
return eval->Invalid("channelopen is not yet confirmed(notarised)!");
|
||||
else if (komodo_txnotarizedconfirmed(param3) == 0)
|
||||
return eval->Invalid("channelClose is not yet confirmed(notarised)!");
|
||||
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for channelRefund!");
|
||||
return eval->Invalid("vin.0 is normal for channelrefund!");
|
||||
else if ( IsCCInput(tx.vin[1].scriptSig) == 0 )
|
||||
return eval->Invalid("vin.1 is CC for channelRefund!");
|
||||
return eval->Invalid("vin.1 is CC for channelrefund!");
|
||||
else if ( IsCCInput(tx.vin[2].scriptSig) == 0 )
|
||||
return eval->Invalid("vin.2 is CC for channelRefund!");
|
||||
else if ( IsChannelsMarkervout(cp,tx,srcpub,0)==0 )
|
||||
return eval->Invalid("vout.0 is CC for channelRefund (marker to srcPub)!");
|
||||
else if ( IsChannelsMarkervout(cp,tx,destpub,1)==0 )
|
||||
return eval->Invalid("vout.1 is CC for channelRefund (marker to dstPub)!");
|
||||
else if ( tokenid!=zeroid && tx.vout[2].scriptPubKey.IsPayToCryptoCondition() == 0 )
|
||||
return eval->Invalid("vout.2 is CC for channelPayment!");
|
||||
else if ( tokenid==zeroid && tx.vout[2].scriptPubKey.IsPayToCryptoCondition() != 0 )
|
||||
return eval->Invalid("vout.2 is normal for channelPayment!");
|
||||
else if ( tokenid!=zeroid && tx.vout[2].scriptPubKey!=MakeCC1vout(EVAL_TOKENS,tx.vout[2].nValue,srcpub).scriptPubKey)
|
||||
return eval->Invalid("payment funds do not go to sender!");
|
||||
else if ( tokenid==zeroid && tx.vout[2].scriptPubKey!=CScript() << ParseHex(HexStr(srcpub)) << OP_CHECKSIG)
|
||||
return eval->Invalid("payment funds do not go to sender!");
|
||||
return eval->Invalid("vin.2 is CC for channelrefund!");
|
||||
else if ( ConstrainVout(tx.vout[0],1,srcmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.0 is CC marker to srcpub or invalid amount for channelrefund!");
|
||||
else if ( ConstrainVout(tx.vout[1],1,destmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.1 is CC marker to destpub or invalid amount for channelrefund!");
|
||||
else if ( tokenid!=zeroid && ConstrainVout(tx.vout[2],1,srctokensaddr,param1*payment)==0 )
|
||||
return eval->Invalid("vout.2 is CC or invalid amount or invalid receiver for channelrefund!");
|
||||
else if ( tokenid==zeroid && ConstrainVout(tx.vout[2],0,srcaddr,param1*payment)==0 )
|
||||
return eval->Invalid("vout.2 is normal or invalid amount or invalid receiver for channelrefund!");
|
||||
else if ( param1 > CHANNELS_MAXPAYMENTS)
|
||||
return eval->Invalid("too many payment increments!");
|
||||
else if (myGetTransaction(opentxid,channelOpenTx,hashblock) == 0)
|
||||
return eval->Invalid("invalid open txid!");
|
||||
else if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, numpayments, payment, hashchain) != 'O')
|
||||
return eval->Invalid("invalid channelopen OP_RETURN data!");
|
||||
else if (myGetTransaction(param3,channelCloseTx,hashblock) == 0)
|
||||
return eval->Invalid("invalid close txid!");
|
||||
else if ((numvouts=channelCloseTx.vout.size()) > 0 && DecodeChannelsOpRet(channelCloseTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, param1, param2, param3) != 'C')
|
||||
return eval->Invalid("invalid channelclose OP_RETURN data!");
|
||||
else if (tmp_txid!=opentxid)
|
||||
return eval->Invalid("invalid close tx, opentxid do not match on close and refund!");
|
||||
else if (tx.vout[2].nValue != param1*payment)
|
||||
return eval->Invalid("vout amount does not match number_of_payments*payment!");
|
||||
else if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0)
|
||||
{
|
||||
if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, p1, p2, p3) == 0)
|
||||
return eval->Invalid("invalid previous tx OP_RETURN data!");
|
||||
else if (tx.vout[0].scriptPubKey != prevTx.vout[1].scriptPubKey)
|
||||
return eval->Invalid("invalid destination for sender marker!");
|
||||
else if (tx.vout[1].scriptPubKey != prevTx.vout[2].scriptPubKey)
|
||||
return eval->Invalid("invalid destination for receiver marker!");
|
||||
else if ((*cp->ismyvin)(tx.vin[2].scriptSig) == 0 || prevTx.vout[tx.vin[2].prevout.n].nValue!=CC_MARKER_VALUE)
|
||||
return eval->Invalid("vin.2 is CC marker or invalid marker amount for channelrefund!");
|
||||
else if (tx.vout[2].nValue != prevTx.vout[0].nValue)
|
||||
return eval->Invalid("invalid amount, refund amount and funds in channel must match!");
|
||||
}
|
||||
@@ -390,8 +390,8 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
else return eval->Invalid("unexpected channels missing funcid");
|
||||
retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts);
|
||||
if ( retval != 0 )
|
||||
fprintf(stderr,"Channel tx validated\n");
|
||||
else fprintf(stderr,"Channel tx invalid\n");
|
||||
LOGSTREAM("channels",CCLOG_INFO, stream << "Channels tx validated" << std::endl);
|
||||
else fprintf(stderr,"Channels tx invalid\n");
|
||||
return(retval);
|
||||
}
|
||||
}
|
||||
@@ -415,7 +415,7 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"invalid channel open txid\n");
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << "invalid channel open txid" << std::endl);
|
||||
return 0;
|
||||
}
|
||||
if (srcpub==mypk) marker=1;
|
||||
@@ -473,7 +473,7 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64
|
||||
if ( numpayments <= 0 || payment <= 0 || numpayments > CHANNELS_MAXPAYMENTS )
|
||||
{
|
||||
CCerror = strprintf("invalid ChannelOpen param numpayments.%d max.%d payment.%lld\n",numpayments,CHANNELS_MAXPAYMENTS,(long long)payment);
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
cp = CCinit(&C,EVAL_CHANNELS);
|
||||
@@ -484,11 +484,11 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64
|
||||
funds = numpayments * payment;
|
||||
if (tokenid!=zeroid)
|
||||
{
|
||||
amount=AddNormalinputs(mtx,mypk,3*txfee,5);
|
||||
amount=AddNormalinputs(mtx,mypk,txfee+2*CC_MARKER_VALUE,5);
|
||||
tokens=AddTokenCCInputs(cpTokens, mtx, mypk, tokenid, funds, 64);
|
||||
}
|
||||
else amount=AddNormalinputs(mtx,mypk,funds+3*txfee,64);
|
||||
if (amount+tokens >= funds+2*txfee)
|
||||
else amount=AddNormalinputs(mtx,mypk,funds+txfee+2*CC_MARKER_VALUE,64);
|
||||
if (amount+tokens >= funds+txfee+2*CC_MARKER_VALUE)
|
||||
{
|
||||
hentropy = DiceHashEntropy(entropy,mtx.vin[0].prevout.hash,mtx.vin[0].prevout.n,1);
|
||||
endiancpy(hash,(uint8_t *)&hentropy,32);
|
||||
@@ -500,13 +500,13 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64
|
||||
endiancpy((uint8_t *)&hashchain,hashdest,32);
|
||||
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));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CC_MARKER_VALUE,mypk));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CC_MARKER_VALUE,destpub));
|
||||
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());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
|
||||
@@ -526,7 +526,7 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2
|
||||
if (GetTransaction(opentxid,channelOpenTx,hashblock,false) == 0)
|
||||
{
|
||||
CCerror = strprintf("invalid channel open txid");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tokenid, txid, srcpub, destpub, totalnumpayments, payment, hashchain)=='O')
|
||||
@@ -534,23 +534,29 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2
|
||||
if (mypk != srcpub && mypk != destpub)
|
||||
{
|
||||
CCerror = strprintf("this is not our channel");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
else if (amount % payment != 0 || amount<payment)
|
||||
{
|
||||
CCerror = strprintf("invalid amount, not a magnitude of payment size");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return ("");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CCerror = strprintf("invalid channel open tx");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return ("");
|
||||
}
|
||||
if (AddNormalinputs(mtx,mypk,2*txfee,3) > 0)
|
||||
if (komodo_txnotarizedconfirmed(opentxid)==false)
|
||||
{
|
||||
CCerror = strprintf("channelsopen tx not yet confirmed/notarized");
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
if (AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,3) > 0)
|
||||
{
|
||||
if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid,mypk)) !=0 && (change=funds-amount)>=0)
|
||||
{
|
||||
@@ -562,12 +568,12 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2
|
||||
if (numpayments > prevdepth)
|
||||
{
|
||||
CCerror = strprintf("not enough funds in channel for that amount");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return ("");
|
||||
} else if (numpayments == 0)
|
||||
{
|
||||
CCerror = strprintf("invalid amount");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return ("");
|
||||
}
|
||||
if (secret!=zeroid)
|
||||
@@ -582,7 +588,7 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2
|
||||
if (gensecret!=hashchain)
|
||||
{
|
||||
CCerror = strprintf("invalid secret supplied");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
}
|
||||
@@ -605,13 +611,13 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2
|
||||
else
|
||||
{
|
||||
CCerror = strprintf("invalid previous tx");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
if (tokenid!=zeroid) mtx.vout.push_back(MakeTokensCC1of2vout(EVAL_CHANNELS, change, srcpub, destpub));
|
||||
else mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, change, srcpub, destpub));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,srcpub));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CC_MARKER_VALUE,srcpub));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CC_MARKER_VALUE,destpub));
|
||||
if (tokenid!=zeroid) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, amount, destpub));
|
||||
else mtx.vout.push_back(CTxOut(amount, CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG));
|
||||
return (FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeChannelsOpRet('P', tokenid, opentxid, srcpub, destpub, prevdepth-numpayments, numpayments, secret)));
|
||||
@@ -619,12 +625,12 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2
|
||||
else
|
||||
{
|
||||
CCerror = strprintf("error adding CC inputs");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
}
|
||||
CCerror = strprintf("error adding normal inputs");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
|
||||
@@ -645,40 +651,46 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid)
|
||||
if (GetTransaction(opentxid,channelOpenTx,hashblock,false) == 0)
|
||||
{
|
||||
CCerror = strprintf("invalid channel open txid");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return ("");
|
||||
}
|
||||
if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,numpayments,payment,hashchain)!='O')
|
||||
{
|
||||
CCerror = strprintf("invalid channel open tx");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return ("");
|
||||
}
|
||||
if (komodo_txnotarizedconfirmed(opentxid)==false)
|
||||
{
|
||||
CCerror = strprintf("channelsopen tx not yet confirmed/notarized");
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
if (mypk != srcpub)
|
||||
{
|
||||
CCerror = strprintf("cannot close, you are not channel owner");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
if ( AddNormalinputs(mtx,mypk,2*txfee,3) > 0 )
|
||||
if ( AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,3) > 0 )
|
||||
{
|
||||
if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid,mypk)) !=0 && funds>0)
|
||||
{
|
||||
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));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CC_MARKER_VALUE,mypk));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CC_MARKER_VALUE,destpub));
|
||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('C',tokenid,opentxid,mypk,destpub,funds/payment,payment,zeroid)));
|
||||
}
|
||||
else
|
||||
{
|
||||
CCerror = strprintf("error adding CC inputs");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
}
|
||||
CCerror = strprintf("error adding normal inputs");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
|
||||
@@ -699,48 +711,60 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid)
|
||||
if (GetTransaction(closetxid,channelCloseTx,hashblock,false) == 0)
|
||||
{
|
||||
CCerror = strprintf("invalid channel close txid");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return ("");
|
||||
}
|
||||
if ((numvouts=channelCloseTx.vout.size()) < 1 || DecodeChannelsOpRet(channelCloseTx.vout[numvouts-1].scriptPubKey,tokenid,txid,srcpub,destpub,param1,param2,param3)!='C')
|
||||
{
|
||||
CCerror = strprintf("invalid channel close tx");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return ("");
|
||||
}
|
||||
if (komodo_txnotarizedconfirmed(closetxid)==false)
|
||||
{
|
||||
CCerror = strprintf("channelsclose tx not yet confirmed/notarized");
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
if (txid!=opentxid)
|
||||
{
|
||||
CCerror = strprintf("open and close txid are not from same channel");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return ("");
|
||||
}
|
||||
if (GetTransaction(opentxid,channelOpenTx,hashblock,false) == 0)
|
||||
{
|
||||
CCerror = strprintf("invalid channel open txid");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return ("");
|
||||
}
|
||||
if (komodo_txnotarizedconfirmed(opentxid)==false)
|
||||
{
|
||||
CCerror = strprintf("channelsopen tx not yet confirmed/notarized");
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tokenid,txid,srcpub,destpub,numpayments,payment,hashchain)!='O')
|
||||
{
|
||||
CCerror = strprintf("invalid channel open tx");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return ("");
|
||||
}
|
||||
if (mypk != srcpub)
|
||||
{
|
||||
CCerror = strprintf("cannot refund, you are not the channel owner");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
if ( AddNormalinputs(mtx,mypk,2*txfee,3) > 0 )
|
||||
if ( AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,3) > 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));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CC_MARKER_VALUE,mypk));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CC_MARKER_VALUE,destpub));
|
||||
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)));
|
||||
@@ -748,19 +772,19 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid)
|
||||
else
|
||||
{
|
||||
CCerror = strprintf("previous tx is invalid");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CCerror = strprintf("error adding CC inputs");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
}
|
||||
CCerror = strprintf("error adding normal inputs");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
|
||||
@@ -781,7 +805,7 @@ UniValue ChannelsList()
|
||||
txid = it->first.txhash;
|
||||
vout = (int32_t)it->first.index;
|
||||
nValue = (int64_t)it->second;
|
||||
if ( (vout == 1 || vout == 2) && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 )
|
||||
if ( (vout == 1 || vout == 2) && nValue == CC_MARKER_VALUE && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 )
|
||||
{
|
||||
if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3) == 'O')
|
||||
{
|
||||
|
||||
1119
src/cc/dapps/dappstd.c
Normal file
1119
src/cc/dapps/dappstd.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -450,10 +450,12 @@ int32_t get_coinheader(char *refcoin,char *acname,bits256 *blockhashp,bits256 *m
|
||||
return(0);
|
||||
}
|
||||
|
||||
cJSON *get_gatewayspending(char *refcoin,char *acname,char *bindtxidstr)
|
||||
cJSON *get_gatewayspending(int8_t type,char *refcoin,char *acname,char *bindtxidstr)
|
||||
{
|
||||
cJSON *retjson; char *retstr;
|
||||
if ( (retjson= get_cli(refcoin,&retstr,acname,"gatewayspendingwithdraws",bindtxidstr,refcoin,"","")) != 0 )
|
||||
cJSON *retjson; char *retstr; char function[64];
|
||||
if (type==0) sprintf(function,"%s","gatewayspendingwithdraws");
|
||||
else if (type==1) sprintf(function,"%s","importgatewaypendingwithdraws");
|
||||
if ( (retjson= get_cli(refcoin,&retstr,acname,function,bindtxidstr,refcoin,"","")) != 0 )
|
||||
{
|
||||
//printf("pending.(%s)\n",jprint(retjson,0));
|
||||
return(retjson);
|
||||
@@ -466,10 +468,13 @@ cJSON *get_gatewayspending(char *refcoin,char *acname,char *bindtxidstr)
|
||||
return(0);
|
||||
}
|
||||
|
||||
cJSON *get_gatewaysprocessed(char *refcoin,char *acname,char *bindtxidstr)
|
||||
cJSON *get_gatewaysprocessed(int8_t type,char *refcoin,char *acname,char *bindtxidstr)
|
||||
{
|
||||
cJSON *retjson; char *retstr;
|
||||
if ( (retjson= get_cli(refcoin,&retstr,acname,"gatewaysprocessed",bindtxidstr,refcoin,"","")) != 0 )
|
||||
char function[64];
|
||||
if (type==0) sprintf(function,"%s","gatewaysprocessed");
|
||||
else if (type==1) sprintf(function,"%s","importgatewayprocessed");
|
||||
if ( (retjson= get_cli(refcoin,&retstr,acname,function,bindtxidstr,refcoin,"","")) != 0 )
|
||||
{
|
||||
//printf("pending.(%s)\n",jprint(retjson,0));
|
||||
return(retjson);
|
||||
@@ -692,10 +697,12 @@ cJSON *addsignature(char *refcoin,char *acname,char *rawtx, int M)
|
||||
return(0);
|
||||
}
|
||||
|
||||
bits256 gatewayspartialsign(char *refcoin,char *acname,bits256 txid,char *hex)
|
||||
bits256 gatewayspartialsign(int8_t type,char *refcoin,char *acname,bits256 txid,char *hex)
|
||||
{
|
||||
char str[65],*retstr; cJSON *retjson;
|
||||
if ( (retjson= get_cli(refcoin,&retstr,acname,"gatewayspartialsign",bits256_str(str,txid),refcoin,hex,"")) != 0 )
|
||||
char str[65],*retstr; cJSON *retjson; char function[64];
|
||||
if (type==0) sprintf(function,"%s","gatewayspartialsign");
|
||||
else if (type==1) sprintf(function,"%s","importgatewaypartialsign");
|
||||
if ( (retjson= get_cli(refcoin,&retstr,acname,function,bits256_str(str,txid),refcoin,hex,"")) != 0 )
|
||||
{
|
||||
if (strcmp("error",jstr(retjson,"result"))!=0) txid=broadcasttx(refcoin,acname,retjson);
|
||||
else printf("%s\n",jstr(retjson,"error"));
|
||||
@@ -710,10 +717,13 @@ bits256 gatewayspartialsign(char *refcoin,char *acname,bits256 txid,char *hex)
|
||||
return (zeroid);
|
||||
}
|
||||
|
||||
bits256 gatewayscompletesigning(char *refcoin,char *acname,bits256 withtxid,char *hex)
|
||||
bits256 gatewayscompletesigning(int8_t type,char *refcoin,char *acname,bits256 withtxid,char *hex)
|
||||
{
|
||||
char str[65],*retstr; cJSON *retjson; bits256 txid;
|
||||
if ( (retjson= get_cli(refcoin,&retstr,acname,"gatewayscompletesigning",bits256_str(str,withtxid),refcoin,hex,"")) != 0 )
|
||||
char str[65],*retstr; cJSON *retjson; bits256 txid; char function[64];
|
||||
|
||||
if (type==0) sprintf(function,"%s","gatewayscompletesigning");
|
||||
else if (type==1) sprintf(function,"%s","importgatewaycompletesigning");
|
||||
if ( (retjson= get_cli(refcoin,&retstr,acname,function,bits256_str(str,withtxid),refcoin,hex,"")) != 0 )
|
||||
{
|
||||
if (strcmp("error",jstr(retjson,"result"))!=0) txid=broadcasttx(refcoin,acname,retjson);
|
||||
else printf("%s\n",jstr(retjson,"error"));
|
||||
@@ -728,10 +738,13 @@ bits256 gatewayscompletesigning(char *refcoin,char *acname,bits256 withtxid,char
|
||||
return (zeroid);
|
||||
}
|
||||
|
||||
bits256 gatewaysmarkdone(char *refcoin,char *acname,bits256 withtxid)
|
||||
bits256 gatewaysmarkdone(int8_t type,char *refcoin,char *acname,bits256 withtxid)
|
||||
{
|
||||
char str[65],str2[65],*retstr; cJSON *retjson; bits256 txid;
|
||||
if ( (retjson= get_cli(refcoin,&retstr,acname,"gatewaysmarkdone",bits256_str(str,withtxid),refcoin,"","")) != 0 )
|
||||
char str[65],str2[65],*retstr; cJSON *retjson; bits256 txid; ; char function[64];
|
||||
|
||||
if (type==0) sprintf(function,"%s","gatewaysmarkdone");
|
||||
else if (type==1) sprintf(function,"%s","importgatewaymarkdone");
|
||||
if ( (retjson= get_cli(refcoin,&retstr,acname,function,bits256_str(str,withtxid),refcoin,"","")) != 0 )
|
||||
{
|
||||
if (strcmp("error",jstr(retjson,"result"))!=0) txid=broadcasttx(refcoin,acname,retjson);
|
||||
else printf("%s\n",jstr(retjson,"error"));
|
||||
@@ -746,10 +759,13 @@ bits256 gatewaysmarkdone(char *refcoin,char *acname,bits256 withtxid)
|
||||
return (zeroid);
|
||||
}
|
||||
|
||||
int32_t get_gatewaysinfo(char *refcoin,char *acname,char *depositaddr,int32_t *Mp,int32_t *Np,char *bindtxidstr,char *coin,char *oraclestr, char **pubkeys)
|
||||
int32_t get_gatewaysinfo(int8_t type,char *refcoin,char *acname,char *depositaddr,int32_t *Mp,int32_t *Np,char *bindtxidstr,char *coin,char *oraclestr, char **pubkeys)
|
||||
{
|
||||
char *oracle,*retstr,*name,*deposit,temp[128]; cJSON *retjson,*pubarray; int32_t n;
|
||||
if ( (retjson= get_cli(refcoin,&retstr,acname,"gatewaysinfo",bindtxidstr,"","","")) != 0 )
|
||||
char *oracle,*retstr,*name,*deposit,temp[128]; cJSON *retjson,*pubarray; int32_t n; char function[64];
|
||||
|
||||
if (type==0) sprintf(function,"%s","gatewaysinfo");
|
||||
else if (type==1) sprintf(function,"%s","importgatewayinfo");
|
||||
if ( (retjson= get_cli(refcoin,&retstr,acname,function,bindtxidstr,"","","")) != 0 )
|
||||
{
|
||||
if ( (oracle= jstr(retjson,"oracletxid")) != 0 && strcmp(oracle,oraclestr) == 0 && (deposit= jstr(retjson,"deposit")) != 0 )
|
||||
{
|
||||
@@ -774,7 +790,6 @@ int32_t get_gatewaysinfo(char *refcoin,char *acname,char *depositaddr,int32_t *M
|
||||
strcat(*pubkeys,temp);
|
||||
}
|
||||
}
|
||||
else printf("%s != %s\n",oracle,oraclestr);
|
||||
free_json(retjson);
|
||||
}
|
||||
else if ( retstr != 0 )
|
||||
@@ -851,7 +866,7 @@ int32_t markerexists(char *refcoin,char *acname,char *coinaddr)
|
||||
|
||||
}
|
||||
|
||||
void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t M,int32_t N)
|
||||
void update_gatewayspending(int8_t type,char *refcoin,char *acname,char *bindtxidstr,int32_t M,int32_t N)
|
||||
{
|
||||
// check queue to prevent duplicate
|
||||
// check KMD chain and mempool for txidaddr
|
||||
@@ -864,7 +879,7 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t
|
||||
int32_t i,j,n,K,retval,processed = 0; bits256 txid,cointxid,withdrawtxid,lasttxid,completetxid; int64_t satoshis;
|
||||
|
||||
memset(&zeroid,0,sizeof(zeroid));
|
||||
if ( (retjson= get_gatewayspending(refcoin,acname,bindtxidstr)) != 0 )
|
||||
if ( (retjson= get_gatewayspending(type,refcoin,acname,bindtxidstr)) != 0 )
|
||||
{
|
||||
if ( jint(retjson,"queueflag") != 0 && (coinstr= jstr(retjson,"coin")) != 0 && strcmp(coinstr,refcoin) == 0 )
|
||||
{
|
||||
@@ -888,7 +903,7 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t
|
||||
{
|
||||
if ( (clijson=addsignature(refcoin,"",rawtx,M)) != 0 && is_cJSON_True(jobj(clijson,"complete")) != 0)
|
||||
{
|
||||
txid=gatewayscompletesigning(refcoin,acname,withdrawtxid,jstr(clijson,"hex"));
|
||||
txid=gatewayscompletesigning(type,refcoin,acname,withdrawtxid,jstr(clijson,"hex"));
|
||||
if (txid.txid!=zeroid.txid) fprintf(stderr,"### SIGNING withdraw %s 1of1\n",bits256_str(str,withdrawtxid));
|
||||
else fprintf(stderr,"### SIGNING error broadcasting tx on %s",acname);
|
||||
free_json(clijson);
|
||||
@@ -910,13 +925,13 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t
|
||||
{
|
||||
if ( is_cJSON_True(jobj(clijson,"complete")) != 0 )
|
||||
{
|
||||
txid=gatewayscompletesigning(refcoin,acname,lasttxid,jstr(clijson,"hex"));
|
||||
txid=gatewayscompletesigning(type,refcoin,acname,lasttxid,jstr(clijson,"hex"));
|
||||
if (txid.txid!=zeroid.txid) fprintf(stderr,"### SIGNING withdraw %s %dof%d\n",bits256_str(str,withdrawtxid),K+1,N);
|
||||
else fprintf(stderr,"### SIGNING error broadcasting tx on %s\n",acname);
|
||||
}
|
||||
else if ( jint(clijson,"partialtx") != 0 )
|
||||
{
|
||||
txid=gatewayspartialsign(refcoin,acname,lasttxid,jstr(clijson,"hex"));
|
||||
txid=gatewayspartialsign(type,refcoin,acname,lasttxid,jstr(clijson,"hex"));
|
||||
if (txid.txid!=zeroid.txid) fprintf(stderr,"### SIGNING withdraw %s %d/%dof%d\n",bits256_str(str,withdrawtxid),K+1,M,N);
|
||||
else fprintf(stderr,"### SIGNING error broadcasting tx on %s\n",acname);
|
||||
}
|
||||
@@ -932,7 +947,7 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t
|
||||
}
|
||||
free_json(retjson);
|
||||
}
|
||||
if ( (retjson= get_gatewaysprocessed(refcoin,acname,bindtxidstr)) != 0 )
|
||||
if ( (retjson= get_gatewaysprocessed(type,refcoin,acname,bindtxidstr)) != 0 )
|
||||
{
|
||||
if ( jint(retjson,"queueflag") != 0 && (coinstr= jstr(retjson,"coin")) != 0 && strcmp(coinstr,refcoin) == 0 )
|
||||
{
|
||||
@@ -954,7 +969,7 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t
|
||||
{
|
||||
withdrawaddr = jstr(item,"withdrawaddr");
|
||||
fprintf(stderr,"### WITHDRAW %.8f %s sent to %s\n",amount,refcoin,withdrawaddr);
|
||||
txid=gatewaysmarkdone(refcoin,acname,completetxid);
|
||||
txid=gatewaysmarkdone(type,refcoin,acname,completetxid);
|
||||
if (txid.txid!=zeroid.txid) fprintf(stderr,"### MARKDONE withdraw %s\n",bits256_str(str,withdrawtxid));
|
||||
else fprintf(stderr,"### MARKDONE error broadcasting tx on %s\n",refcoin);
|
||||
}
|
||||
@@ -1024,7 +1039,7 @@ oraclesdata 17a841a919c284cea8a676f34e793da002e606f19a9258a3190bed12d5aaa3ff 034
|
||||
|
||||
int32_t main(int32_t argc,char **argv)
|
||||
{
|
||||
cJSON *clijson,*clijson2,*regjson,*item; int32_t acheight,i,retval,M,N,n,height,prevheight = 0; char *pubkeys,*format,*acname,*oraclestr,*bindtxidstr,*pkstr,*pubstr,*retstr,*retstr2,depositaddr[64],hexstr[4096],refcoin[64]; uint64_t price; bits256 txid;
|
||||
cJSON *clijson,*clijson2,*regjson,*item; int32_t type,i,retval,M,N,n,height,prevheight = 0; char *pubkeys,*format,*acname,*oraclestr,*bindtxidstr,*pkstr,*pubstr,*retstr,*retstr2,depositaddr[64],hexstr[4096],refcoin[64]; uint64_t price; bits256 txid;
|
||||
if ( argc < 6 )
|
||||
{
|
||||
printf("usage: oraclefeed $ACNAME $ORACLETXID $MYPUBKEY $FORMAT $BINDTXID [refcoin_cli]\n");
|
||||
@@ -1044,8 +1059,7 @@ int32_t main(int32_t argc,char **argv)
|
||||
printf("only formats of L and Ihh are supported now\n");
|
||||
return(-1);
|
||||
}
|
||||
M = N = 1;
|
||||
acheight = 0;
|
||||
M = N = 0;
|
||||
refcoin[0] = 0;
|
||||
while ( 1 )
|
||||
{
|
||||
@@ -1061,7 +1075,9 @@ int32_t main(int32_t argc,char **argv)
|
||||
exit(0);
|
||||
}
|
||||
pubkeys=0;
|
||||
if ( get_gatewaysinfo(refcoin,acname,depositaddr,&M,&N,bindtxidstr,refcoin,oraclestr,&pubkeys) < 0 )
|
||||
if ( get_gatewaysinfo(0,refcoin,acname,depositaddr,&M,&N,bindtxidstr,refcoin,oraclestr,&pubkeys) == 0 ) type=0;
|
||||
else if ( get_gatewaysinfo(1,refcoin,acname,depositaddr,&M,&N,bindtxidstr,refcoin,oraclestr,&pubkeys) == 0 ) type=1;
|
||||
else
|
||||
{
|
||||
printf("cant find bindtxid.(%s)\n",bindtxidstr);
|
||||
exit(0);
|
||||
@@ -1089,9 +1105,8 @@ int32_t main(int32_t argc,char **argv)
|
||||
if ( bits256_nonz(txid) != 0 )
|
||||
{
|
||||
prevheight = height;
|
||||
acheight = get_coinheight(refcoin,"");
|
||||
printf("%s ht.%d <- %s\n",refcoin,height,hexstr);
|
||||
update_gatewayspending(refcoin,acname,bindtxidstr,M,N);
|
||||
update_gatewayspending(type,refcoin,acname,bindtxidstr,M,N);
|
||||
}
|
||||
free_json(clijson2);
|
||||
}
|
||||
|
||||
@@ -1052,9 +1052,11 @@ uint64_t AddDiceInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubK
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
GetCCaddress(cp,coinaddr,pk);
|
||||
SetCCunspents(unspentOutputs,coinaddr);
|
||||
if ( maxinputs > CC_MAXVINS )
|
||||
maxinputs = CC_MAXVINS;
|
||||
if ( maxinputs > 0 )
|
||||
threshold = total / maxinputs;
|
||||
else threshold = total / 64;
|
||||
else threshold = total;
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
{
|
||||
txid = it->first.txhash;
|
||||
|
||||
@@ -3340,7 +3340,11 @@ int64_t dilithium_inputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPu
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
GetCCaddress(cp,coinaddr,pk);
|
||||
SetCCunspents(unspentOutputs,coinaddr);
|
||||
threshold = total/(maxinputs+1);
|
||||
if ( maxinputs > CC_MAXVINS )
|
||||
maxinputs = CC_MAXVINS;
|
||||
if ( maxinputs > 0 )
|
||||
threshold = total/maxinputs;
|
||||
else threshold = total;
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
{
|
||||
txid = it->first.txhash;
|
||||
|
||||
@@ -56,7 +56,8 @@
|
||||
EVAL(EVAL_MARMARA, 0xef) \
|
||||
EVAL(EVAL_PAYMENTS, 0xf0) \
|
||||
EVAL(EVAL_GATEWAYS, 0xf1) \
|
||||
EVAL(EVAL_TOKENS, 0xf2)
|
||||
EVAL(EVAL_TOKENS, 0xf2) \
|
||||
EVAL(EVAL_IMPORTGATEWAY, 0xf3) \
|
||||
|
||||
|
||||
// evalcodes 0x10 to 0x7f are reserved for cclib dynamic CC
|
||||
|
||||
@@ -146,7 +146,11 @@ int64_t AddFaucetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPub
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
GetCCaddress(cp,coinaddr,pk);
|
||||
SetCCunspents(unspentOutputs,coinaddr);
|
||||
threshold = total/(maxinputs+1);
|
||||
if ( maxinputs > CC_MAXVINS )
|
||||
maxinputs = CC_MAXVINS;
|
||||
if ( maxinputs > 0 )
|
||||
threshold = total/maxinputs;
|
||||
else threshold = total;
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
{
|
||||
txid = it->first.txhash;
|
||||
|
||||
289
src/cc/games/prices.c
Normal file
289
src/cc/games/prices.c
Normal file
@@ -0,0 +1,289 @@
|
||||
|
||||
#include "prices.h"
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#ifdef BUILD_GAMESCC
|
||||
#include "../rogue/cursesd.h"
|
||||
#else
|
||||
#include <curses.h>
|
||||
#endif
|
||||
|
||||
#define SATOSHIDEN ((uint64_t)100000000L)
|
||||
#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"prices",cmdstr,0,0,0)
|
||||
extern int64_t Net_change,Betsize;
|
||||
|
||||
int random_tetromino(struct games_state *rs)
|
||||
{
|
||||
rs->seed = _games_rngnext(rs->seed);
|
||||
return(rs->seed % NUM_TETROMINOS);
|
||||
}
|
||||
|
||||
int32_t pricesdata(struct games_player *P,void *ptr)
|
||||
{
|
||||
tetris_game *tg = (tetris_game *)ptr;
|
||||
P->gold = tg->points;
|
||||
P->dungeonlevel = tg->level;
|
||||
//fprintf(stderr,"score.%d level.%d\n",tg->points,tg->level);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void sleep_milli(int milliseconds)
|
||||
{
|
||||
struct timespec ts;
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = milliseconds * 1000 * 1000;
|
||||
nanosleep(&ts, NULL);
|
||||
}
|
||||
|
||||
struct games_state globalR;
|
||||
extern char Gametxidstr[];
|
||||
int32_t issue_games_events(struct games_state *rs,char *gametxidstr,uint32_t eventid,gamesevent c);
|
||||
uint64_t get_btcusd();
|
||||
int32_t issue_bet(struct games_state *rs,int64_t x,int64_t betsize);
|
||||
|
||||
void *gamesiterate(struct games_state *rs)
|
||||
{
|
||||
bool running = true; uint32_t eventid = 0; int64_t price;
|
||||
if ( rs->guiflag != 0 || rs->sleeptime != 0 )
|
||||
{
|
||||
initscr(); // initialize curses
|
||||
cbreak(); // pass key presses to program, but not signals
|
||||
noecho(); // don't echo key presses to screen
|
||||
timeout(0);
|
||||
}
|
||||
while ( running != 0 )
|
||||
{
|
||||
//running = tg_tick(rs,tg,move);
|
||||
if ( rs->guiflag != 0 || rs->sleeptime != 0 )
|
||||
{
|
||||
}
|
||||
if ( rs->guiflag != 0 )
|
||||
{
|
||||
#ifdef STANDALONE
|
||||
price = get_btcusd();
|
||||
//fprintf(stderr,"%llu -> t%u %.4f\n",(long long)price,(uint32_t)(price >> 32),(double)(price & 0xffffffff)/10000);
|
||||
//issue_games_events(rs,Gametxidstr,eventid,price);
|
||||
issue_bet(rs,price,Betsize);
|
||||
eventid++;
|
||||
doupdate();
|
||||
sleep(10);
|
||||
switch ( getch() )
|
||||
{
|
||||
case '+': Net_change++; break;
|
||||
case '-': Net_change--; break;
|
||||
case '0': Net_change = 0; break;
|
||||
case '$': Betsize = SATOSHIDEN; break;
|
||||
case '^': Betsize += (Betsize >> 3); break;
|
||||
case '/': Betsize -= (Betsize >> 3); break;
|
||||
}
|
||||
/*if ( (counter++ % 10) == 0 )
|
||||
doupdate();
|
||||
c = games_readevent(rs);
|
||||
if ( c <= 0x7f || skipcount == 0x3fff )
|
||||
{
|
||||
if ( skipcount > 0 )
|
||||
issue_games_events(rs,Gametxidstr,eventid-skipcount,skipcount | 0x4000);
|
||||
if ( c <= 0x7f )
|
||||
issue_games_events(rs,Gametxidstr,eventid,c);
|
||||
if ( tg->level != prevlevel )
|
||||
{
|
||||
flushkeystrokes(rs,0);
|
||||
prevlevel = tg->level;
|
||||
}
|
||||
skipcount = 0;
|
||||
} else skipcount++;*/
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( rs->replaydone != 0 )
|
||||
break;
|
||||
if ( rs->sleeptime != 0 )
|
||||
{
|
||||
sleep_milli(1);
|
||||
}
|
||||
/*if ( skipcount == 0 )
|
||||
{
|
||||
c = games_readevent(rs);
|
||||
//fprintf(stderr,"%04x score.%d level.%d\n",c,tg->points,tg->level);
|
||||
if ( (c & 0x4000) == 0x4000 )
|
||||
{
|
||||
skipcount = (c & 0x3fff);
|
||||
c = 'S';
|
||||
}
|
||||
}
|
||||
if ( skipcount > 0 )
|
||||
skipcount--;*/
|
||||
}
|
||||
eventid++;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
#ifdef STANDALONE
|
||||
#include <ncurses.h>
|
||||
#include "dapps/dappstd.c"
|
||||
int64_t Net_change,Betsize = SATOSHIDEN;
|
||||
|
||||
char *send_curl(char *url,char *fname)
|
||||
{
|
||||
char *retstr;
|
||||
retstr = issue_curl(url);
|
||||
return(retstr);
|
||||
}
|
||||
|
||||
cJSON *get_urljson(char *url,char *fname)
|
||||
{
|
||||
char *jsonstr; cJSON *json = 0;
|
||||
if ( (jsonstr= send_curl(url,fname)) != 0 )
|
||||
{
|
||||
//printf("(%s) -> (%s)\n",url,jsonstr);
|
||||
json = cJSON_Parse(jsonstr);
|
||||
free(jsonstr);
|
||||
}
|
||||
return(json);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// start of dapp
|
||||
//////////////////////////////////////////////
|
||||
|
||||
uint64_t get_btcusd()
|
||||
{
|
||||
cJSON *pjson,*bpi,*usd; char str[512]; uint64_t x,newprice,mult,btcusd = 0;
|
||||
if ( (pjson= get_urljson((char *)"http://api.coindesk.com/v1/bpi/currentprice.json",(char *)"/tmp/oraclefeed.json")) != 0 )
|
||||
{
|
||||
if ( (bpi= jobj(pjson,(char *)"bpi")) != 0 && (usd= jobj(bpi,(char *)"USD")) != 0 )
|
||||
{
|
||||
btcusd = jdouble(usd,(char *)"rate_float") * SATOSHIDEN;
|
||||
mult = 10000 + Net_change*10;
|
||||
newprice = (btcusd * mult) / 10000;
|
||||
x = ((uint64_t)time(NULL) << 32) | ((newprice / 10000) & 0xffffffff);
|
||||
sprintf(str,"BTC/USD %.4f -> Betsize %.8f (^ / to change) && %.4f Net %.1f%% [+ - to change]\n",dstr(btcusd),dstr(Betsize),dstr(newprice),(double)100*(mult-10000)/10000);
|
||||
mvaddstr(0, 0, str);
|
||||
clrtoeol();
|
||||
doupdate();
|
||||
}
|
||||
free_json(pjson);
|
||||
}
|
||||
return(x);
|
||||
}
|
||||
|
||||
char *clonestr(char *str)
|
||||
{
|
||||
char *clone; int32_t len;
|
||||
if ( str == 0 || str[0] == 0 )
|
||||
{
|
||||
printf("warning cloning nullstr.%p\n",str);
|
||||
#ifdef __APPLE__
|
||||
while ( 1 ) sleep(1);
|
||||
#endif
|
||||
str = (char *)"<nullstr>";
|
||||
}
|
||||
len = strlen(str);
|
||||
clone = (char *)calloc(1,len+16);
|
||||
strcpy(clone,str);
|
||||
return(clone);
|
||||
}
|
||||
|
||||
int32_t issue_games_events(struct games_state *rs,char *gametxidstr,uint32_t eventid,gamesevent c)
|
||||
{
|
||||
static FILE *fp;
|
||||
char params[512],*retstr; cJSON *retjson,*resobj; int32_t retval = -1;
|
||||
if ( fp == 0 )
|
||||
fp = fopen("events.log","wb");
|
||||
rs->buffered[rs->num++] = c;
|
||||
if ( 1 )
|
||||
{
|
||||
if ( sizeof(c) == 1 )
|
||||
sprintf(params,"[\"events\",\"17\",\"[%%22%02x%%22,%%22%s%%22,%u]\"]",(uint8_t)c&0xff,gametxidstr,eventid);
|
||||
else if ( sizeof(c) == 2 )
|
||||
sprintf(params,"[\"events\",\"17\",\"[%%22%04x%%22,%%22%s%%22,%u]\"]",(uint16_t)c&0xffff,gametxidstr,eventid);
|
||||
else if ( sizeof(c) == 4 )
|
||||
sprintf(params,"[\"events\",\"17\",\"[%%22%08x%%22,%%22%s%%22,%u]\"]",(uint32_t)c&0xffffffff,gametxidstr,eventid);
|
||||
else if ( sizeof(c) == 8 )
|
||||
sprintf(params,"[\"events\",\"17\",\"[%%22%016llx%%22,%%22%s%%22,%u]\"]",(long long)c,gametxidstr,eventid);
|
||||
if ( (retstr= komodo_issuemethod(USERPASS,(char *)"cclib",params,GAMES_PORT)) != 0 )
|
||||
{
|
||||
if ( (retjson= cJSON_Parse(retstr)) != 0 )
|
||||
{
|
||||
if ( (resobj= jobj(retjson,(char *)"result")) != 0 )
|
||||
{
|
||||
retval = 0;
|
||||
if ( fp != 0 )
|
||||
{
|
||||
fprintf(fp,"%s\n",jprint(resobj,0));
|
||||
fflush(fp);
|
||||
}
|
||||
}
|
||||
free_json(retjson);
|
||||
} else fprintf(fp,"error parsing %s\n",retstr);
|
||||
free(retstr);
|
||||
} else fprintf(fp,"error issuing method %s\n",params);
|
||||
return(retval);
|
||||
} else return(0);
|
||||
}
|
||||
|
||||
int32_t issue_bet(struct games_state *rs,int64_t x,int64_t betsize)
|
||||
{
|
||||
char params[512],hexstr[64],*retstr; cJSON *retjson,*resobj; int32_t i,retval = -1;
|
||||
memset(hexstr,0,sizeof(hexstr));
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
sprintf(&hexstr[i<<1],"%02x",(uint8_t)(x & 0xff));
|
||||
x >>= 8;
|
||||
}
|
||||
sprintf(params,"[\"bet\",\"17\",\"[%.8f,%%22%s%%22]\"]",dstr(betsize),hexstr);
|
||||
if ( (retstr= komodo_issuemethod(USERPASS,(char *)"cclib",params,GAMES_PORT)) != 0 )
|
||||
{
|
||||
if ( (retjson= cJSON_Parse(retstr)) != 0 )
|
||||
{
|
||||
if ( (resobj= jobj(retjson,(char *)"result")) != 0 )
|
||||
{
|
||||
retval = 0;
|
||||
//fprintf(stderr,"%s\n",jprint(resobj,0));
|
||||
}
|
||||
free_json(retjson);
|
||||
}
|
||||
free(retstr);
|
||||
}
|
||||
return(retval);
|
||||
}
|
||||
|
||||
int prices(int argc, char **argv)
|
||||
{
|
||||
struct games_state *rs = &globalR;
|
||||
int32_t c,skipcount=0; uint32_t eventid = 0;
|
||||
memset(rs,0,sizeof(*rs));
|
||||
rs->guiflag = 1;
|
||||
rs->sleeptime = 1; // non-zero to allow refresh()
|
||||
if ( argc >= 2 && strlen(argv[2]) == 64 )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
#ifdef _MSC_VER
|
||||
rs->origseed = _strtoui64(argv[1], NULL, 10);
|
||||
#else
|
||||
rs->origseed = atol(argv[1]); // windows, but not MSVC
|
||||
#endif // _MSC_VER
|
||||
#else
|
||||
rs->origseed = atol(argv[1]); // non-windows
|
||||
#endif // _WIN32
|
||||
rs->seed = rs->origseed;
|
||||
if ( argc >= 3 )
|
||||
{
|
||||
strcpy(Gametxidstr,argv[2]);
|
||||
fprintf(stderr,"setplayerdata %s\n",Gametxidstr);
|
||||
if ( games_setplayerdata(rs,Gametxidstr) < 0 )
|
||||
{
|
||||
fprintf(stderr,"invalid gametxid, or already started\n");
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
} else rs->seed = 777;
|
||||
gamesiterate(rs);
|
||||
//gamesbailout(rs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
281
src/cc/games/prices.cpp
Normal file
281
src/cc/games/prices.cpp
Normal file
@@ -0,0 +1,281 @@
|
||||
|
||||
/******************************************************************************
|
||||
* 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. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
std::string MYCCLIBNAME = (char *)"prices";
|
||||
|
||||
#define PRICES_BETPERIOD 3
|
||||
UniValue games_rawtxresult(UniValue &result,std::string rawtx,int32_t broadcastflag);
|
||||
extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33];
|
||||
|
||||
#define bstr(x) ((double)((uint32_t)x) / 10000.)
|
||||
|
||||
struct prices_bar
|
||||
{
|
||||
uint64_t open,high,low,close,sum;
|
||||
int32_t num;
|
||||
};
|
||||
|
||||
int32_t prices_barupdate(struct prices_bar *bar,uint64_t pricebits)
|
||||
{
|
||||
uint32_t uprice,timestamp;
|
||||
timestamp = (uint32_t)(pricebits >> 32);
|
||||
uprice = (uint32_t)pricebits;
|
||||
bar->sum += uprice, bar->num++;
|
||||
if ( bar->open == 0 )
|
||||
bar->open = bar->high = bar->low = pricebits;
|
||||
if ( uprice > (uint32_t)bar->high )
|
||||
bar->high = pricebits;
|
||||
else if ( uprice < (uint32_t)bar->low )
|
||||
bar->low = pricebits;
|
||||
bar->close = pricebits;
|
||||
return(0);
|
||||
}
|
||||
|
||||
int64_t prices_bardist(struct prices_bar *bar,uint32_t aveprice,uint64_t pricebits)
|
||||
{
|
||||
int64_t a,dist = 0;
|
||||
if ( aveprice != 0 )
|
||||
{
|
||||
a = (pricebits & 0xffffffff);
|
||||
dist = (a - aveprice);
|
||||
dist *= dist;
|
||||
//fprintf(stderr,"dist.%lld (u %u - ave %u) %d\n",(long long)dist,uprice,aveprice,uprice-aveprice);
|
||||
}
|
||||
return(dist);
|
||||
}
|
||||
|
||||
void prices_bardisp(struct prices_bar *bar)
|
||||
{
|
||||
if ( bar->num == 0 )
|
||||
fprintf(stderr,"BAR null\n");
|
||||
else fprintf(stderr,"BAR ave %.4f (O %.4f, H %.4f, L %.4f, C %.4f)\n",bstr(bar->sum/bar->num),bstr(bar->open),bstr(bar->high),bstr(bar->low),bstr(bar->close));
|
||||
}
|
||||
|
||||
int64_t prices_blockinfo(int32_t height,char *acaddr)
|
||||
{
|
||||
std::vector<uint8_t> vopret; CBlockIndex *pindex; CBlock block; CTransaction tx,vintx; uint64_t pricebits; char destaddr[64]; uint32_t aveprice=0,timestamp,uprice; uint256 hashBlock; int64_t dist,mindist=(1LL<<60),prizefund = 0; int32_t mini=-1,i,n,vini,numvouts,iter; struct prices_bar refbar;
|
||||
if ( (pindex= komodo_chainactive(height)) != 0 )
|
||||
{
|
||||
if ( komodo_blockload(block,pindex) == 0 )
|
||||
{
|
||||
n = block.vtx.size();
|
||||
vini = 0;
|
||||
memset(&refbar,0,sizeof(refbar));
|
||||
for (iter=0; iter<2; iter++)
|
||||
{
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
tx = block.vtx[i];
|
||||
if ( myGetTransaction(tx.vin[vini].prevout.hash,vintx,hashBlock) == 0 )
|
||||
continue;
|
||||
else if ( tx.vin[vini].prevout.n >= vintx.vout.size() || Getscriptaddress(destaddr,vintx.vout[tx.vin[vini].prevout.n].scriptPubKey) == 0 )
|
||||
continue;
|
||||
else if ( (numvouts= tx.vout.size()) > 1 && tx.vout[numvouts-1].scriptPubKey[0] == 0x6a )
|
||||
{
|
||||
GetOpReturnData(tx.vout[numvouts-1].scriptPubKey,vopret);
|
||||
if ( vopret.size() == 8 )
|
||||
{
|
||||
E_UNMARSHAL(vopret,ss >> pricebits);
|
||||
timestamp = (uint32_t)(pricebits >> 32);
|
||||
uprice = (uint32_t)pricebits;
|
||||
if ( iter == 0 )
|
||||
{
|
||||
prizefund += tx.vout[0].nValue;
|
||||
if ( strcmp(acaddr,destaddr) == 0 )
|
||||
{
|
||||
//fprintf(stderr,"REF ");
|
||||
prices_barupdate(&refbar,pricebits);
|
||||
}
|
||||
}
|
||||
else if ( strcmp(acaddr,destaddr) != 0 )
|
||||
{
|
||||
dist = prices_bardist(&refbar,aveprice,pricebits);
|
||||
if ( dist < mindist )
|
||||
{
|
||||
mindist = dist;
|
||||
mini = i;
|
||||
}
|
||||
fprintf(stderr,"mini.%d i.%d %.8f t%u %.4f v.%d %s lag.%d i.%d dist.%lld\n",mini,i,(double)tx.vout[0].nValue/COIN,timestamp,(double)uprice/10000,numvouts,destaddr,(int32_t)(pindex->nTime-timestamp),iter,(long long)dist);
|
||||
}
|
||||
} else return(-3);
|
||||
}
|
||||
}
|
||||
if ( iter == 0 )
|
||||
{
|
||||
prices_bardisp(&refbar);
|
||||
if ( refbar.num != 0 )
|
||||
aveprice = (uint32_t)refbar.sum / refbar.num;
|
||||
}
|
||||
}
|
||||
return(prizefund);
|
||||
} else return(-2);
|
||||
} else return(-1);
|
||||
}
|
||||
|
||||
UniValue games_settle(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ); char acaddr[64]; CPubKey acpk,mypk,gamespk; int64_t prizefund = 0; int32_t height,nextheight = komodo_nextheight();
|
||||
if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] == 0 )
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error"," no -ac_pubkey for price reference"));
|
||||
return(result);
|
||||
}
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
gamespk = GetUnspendable(cp,0);
|
||||
acpk = buf2pk(ASSETCHAINS_OVERRIDE_PUBKEY33);
|
||||
Getscriptaddress(acaddr,CScript() << ParseHex(HexStr(acpk)) << OP_CHECKSIG);
|
||||
if ( params != 0 && cJSON_GetArraySize(params) == 1 )
|
||||
{
|
||||
height = juint(jitem(params,0),0);
|
||||
result.push_back(Pair("height",(int64_t)height));
|
||||
if ( (prizefund= prices_blockinfo(height,acaddr)) < 0 )
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("errorcode",prizefund));
|
||||
result.push_back(Pair("error","blockinfo error"));
|
||||
}
|
||||
else
|
||||
{
|
||||
// display bets
|
||||
if ( height <= nextheight-PRICES_BETPERIOD )
|
||||
{
|
||||
// settle bets by first nonzero reference bar
|
||||
}
|
||||
result.push_back(Pair("prizefund",ValueFromAmount(prizefund)));
|
||||
result.push_back(Pair("result","success"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","couldnt parse"));
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
UniValue games_bet(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
UniValue result(UniValue::VOBJ); std::string rawtx; int64_t amount,inputsum; uint64_t price; CPubKey gamespk,mypk,acpk;
|
||||
if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] == 0 )
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error"," no -ac_pubkey for price reference"));
|
||||
return(result);
|
||||
}
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
gamespk = GetUnspendable(cp,0);
|
||||
acpk = buf2pk(ASSETCHAINS_OVERRIDE_PUBKEY33);
|
||||
if ( params != 0 && cJSON_GetArraySize(params) == 2 )
|
||||
{
|
||||
amount = jdouble(jitem(params,0),0) * COIN + 0.0000000049;
|
||||
if ( cclib_parsehash((uint8_t *)&price,jitem(params,1),8) < 0 )
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","couldnt parsehash"));
|
||||
return(result);
|
||||
}
|
||||
if ( mypk == acpk )
|
||||
{
|
||||
amount = 0; // i am the reference price feed
|
||||
//fprintf(stderr,"i am the reference\n");
|
||||
}
|
||||
//fprintf(stderr,"amount %llu price %llx\n",(long long)amount,(long long)price);
|
||||
if ( (inputsum= AddNormalinputs(mtx,mypk,amount+GAMES_TXFEE,64)) >= amount+GAMES_TXFEE )
|
||||
{
|
||||
mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,gamespk));
|
||||
rawtx = FinalizeCCTx(0,cp,mtx,mypk,GAMES_TXFEE,CScript() << OP_RETURN << price);
|
||||
return(games_rawtxresult(result,rawtx,1));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","not enough funds"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","couldnt parse"));
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
void prices_update(uint32_t timestamp,uint32_t uprice,int32_t ismine)
|
||||
{
|
||||
//fprintf(stderr,"%s t%u %.4f %16llx\n",ismine!=0?"mine":"ext ",timestamp,(double)uprice/10000,(long long)((uint64_t)timestamp<<32) | uprice);
|
||||
}
|
||||
|
||||
// game specific code for daemon
|
||||
void games_packitemstr(char *packitemstr,struct games_packitem *item)
|
||||
{
|
||||
strcpy(packitemstr,"");
|
||||
}
|
||||
|
||||
int64_t games_cashout(struct games_player *P)
|
||||
{
|
||||
int32_t dungeonlevel = P->dungeonlevel; int64_t mult=1000,cashout = 0;
|
||||
cashout = (uint64_t)P->gold * mult * dungeonlevel * dungeonlevel;
|
||||
return(cashout);
|
||||
}
|
||||
|
||||
void pricesplayerjson(UniValue &obj,struct games_player *P)
|
||||
{
|
||||
obj.push_back(Pair("packsize",(int64_t)P->packsize));
|
||||
obj.push_back(Pair("hitpoints",(int64_t)P->hitpoints));
|
||||
obj.push_back(Pair("strength",(int64_t)(P->strength&0xffff)));
|
||||
obj.push_back(Pair("maxstrength",(int64_t)(P->strength>>16)));
|
||||
obj.push_back(Pair("level",(int64_t)P->level));
|
||||
obj.push_back(Pair("experience",(int64_t)P->experience));
|
||||
obj.push_back(Pair("dungeonlevel",(int64_t)P->dungeonlevel));
|
||||
}
|
||||
|
||||
int32_t disp_gamesplayer(char *str,struct games_player *P)
|
||||
{
|
||||
str[0] = 0;
|
||||
//if ( P->gold <= 0 )//|| P->hitpoints <= 0 || (P->strength&0xffff) <= 0 || P->level <= 0 || P->experience <= 0 || P->dungeonlevel <= 0 )
|
||||
// return(-1);
|
||||
sprintf(str," <- playerdata: gold.%d hp.%d strength.%d/%d level.%d exp.%d dl.%d",P->gold,P->hitpoints,P->strength&0xffff,P->strength>>16,P->level,P->experience,P->dungeonlevel);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t games_payloadrecv(CPubKey pk,uint32_t timestamp,std::vector<uint8_t> payload)
|
||||
{
|
||||
uint256 gametxid; int32_t i,len; char str[67]; int64_t price; uint32_t eventid = 0;
|
||||
if ( (len= payload.size()) > 36 )
|
||||
{
|
||||
len -= 36;
|
||||
for (i=0; i<32; i++)
|
||||
((uint8_t *)&gametxid)[i] = payload[len+i];
|
||||
eventid = (uint32_t)payload[len+32];
|
||||
eventid |= (uint32_t)payload[len+33] << 8;
|
||||
eventid |= (uint32_t)payload[len+34] << 16;
|
||||
eventid |= (uint32_t)payload[len+35] << 24;
|
||||
for (i=0; i<len&&i<sizeof(price); i++)
|
||||
((uint8_t *)&price)[7-i] = payload[i];
|
||||
prices_update((uint32_t)(price >> 32),(uint32_t)(price & 0xffffffff),pk == pubkey2pk(Mypubkey()));
|
||||
//fprintf(stderr,"%llu -> t%u %.4f ",(long long)price,(uint32_t)(price >> 32),(double)(price & 0xffffffff)/10000);
|
||||
//fprintf(stderr," got payload, from %s %s/e%d\n",pubkey33_str(str,(uint8_t *)&pk),gametxid.GetHex().c_str(),eventid);
|
||||
return(0);
|
||||
} else return(-1);
|
||||
}
|
||||
|
||||
bool games_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx)
|
||||
{
|
||||
return(true);
|
||||
}
|
||||
|
||||
208
src/cc/games/prices.h
Normal file
208
src/cc/games/prices.h
Normal file
@@ -0,0 +1,208 @@
|
||||
|
||||
#ifndef H_PRICES_H
|
||||
#define H_PRICES_H
|
||||
|
||||
/***************************************************************************/
|
||||
/** https://github.com/brenns10/tetris
|
||||
@file main.c
|
||||
@author Stephen Brennan
|
||||
@date Created Wednesday, 10 June 2015
|
||||
@brief Main program for tetris.
|
||||
@copyright Copyright (c) 2015, Stephen Brennan. Released under the Revised
|
||||
BSD License. See LICENSE.txt for details.
|
||||
*******************************************************************************/
|
||||
|
||||
/*
|
||||
Convert a tetromino type to its corresponding cell.
|
||||
*/
|
||||
#define TYPE_TO_CELL(x) ((x)+1)
|
||||
|
||||
/*
|
||||
Strings for how you would print a tetris board.
|
||||
*/
|
||||
#define TC_EMPTY_STR " "
|
||||
#define TC_BLOCK_STR "\u2588"
|
||||
|
||||
/*
|
||||
Questions about a tetris cell.
|
||||
*/
|
||||
#define TC_IS_EMPTY(x) ((x) == TC_EMPTY)
|
||||
#define TC_IS_FILLED(x) (!TC_IS_EMPTY(x))
|
||||
|
||||
/*
|
||||
How many cells in a tetromino?
|
||||
*/
|
||||
#define TETRIS 4
|
||||
/*
|
||||
How many tetrominos?
|
||||
*/
|
||||
#define NUM_TETROMINOS 7
|
||||
/*
|
||||
How many orientations of a tetromino?
|
||||
*/
|
||||
#define NUM_ORIENTATIONS 4
|
||||
|
||||
/*
|
||||
Level constants.
|
||||
*/
|
||||
#define MAX_LEVEL 19
|
||||
#define LINES_PER_LEVEL 10
|
||||
|
||||
/*
|
||||
A "cell" is a 1x1 block within a tetris board.
|
||||
*/
|
||||
typedef enum {
|
||||
TC_EMPTY, TC_CELLI, TC_CELLJ, TC_CELLL, TC_CELLO, TC_CELLS, TC_CELLT, TC_CELLZ
|
||||
} tetris_cell;
|
||||
|
||||
/*
|
||||
A "type" is a type/shape of a tetromino. Not including orientation.
|
||||
*/
|
||||
typedef enum {
|
||||
TET_I, TET_J, TET_L, TET_O, TET_S, TET_T, TET_Z
|
||||
} tetris_type;
|
||||
|
||||
/*
|
||||
A row,column pair. Negative numbers allowed, because we need them for
|
||||
offsets.
|
||||
*/
|
||||
typedef struct {
|
||||
int row;
|
||||
int col;
|
||||
} tetris_location;
|
||||
|
||||
/*
|
||||
A "block" is a struct that contains information about a tetromino.
|
||||
Specifically, what type it is, what orientation it has, and where it is.
|
||||
*/
|
||||
typedef struct {
|
||||
int typ;
|
||||
int ori;
|
||||
tetris_location loc;
|
||||
} tetris_block;
|
||||
|
||||
/*
|
||||
All possible moves to give as input to the game.
|
||||
*/
|
||||
typedef enum {
|
||||
TM_LEFT, TM_RIGHT, TM_CLOCK, TM_COUNTER, TM_DROP, TM_HOLD, TM_NONE
|
||||
} tetris_move;
|
||||
|
||||
/*
|
||||
A game object!
|
||||
*/
|
||||
typedef struct {
|
||||
/*
|
||||
Game board stuff:
|
||||
*/
|
||||
int rows;
|
||||
int cols;
|
||||
/*
|
||||
Scoring information:
|
||||
*/
|
||||
int points;
|
||||
int level;
|
||||
/*
|
||||
Falling block is the one currently going down. Next block is the one that
|
||||
will be falling after this one. Stored is the block that you can swap out.
|
||||
*/
|
||||
tetris_block falling;
|
||||
tetris_block next;
|
||||
tetris_block stored;
|
||||
/*
|
||||
Number of game ticks until the block will move down.
|
||||
*/
|
||||
int ticks_till_gravity;
|
||||
/*
|
||||
Number of lines until you advance to the next level.
|
||||
*/
|
||||
int lines_remaining;
|
||||
char board[];
|
||||
} tetris_game;
|
||||
|
||||
/*
|
||||
This array stores all necessary information about the cells that are filled by
|
||||
each tetromino. The first index is the type of the tetromino (i.e. shape,
|
||||
e.g. I, J, Z, etc.). The next index is the orientation (0-3). The final
|
||||
array contains 4 tetris_location objects, each mapping to an offset from a
|
||||
point on the upper left that is the tetromino "origin".
|
||||
*/
|
||||
extern const tetris_location TETROMINOS[NUM_TETROMINOS][NUM_ORIENTATIONS][TETRIS];
|
||||
|
||||
/*
|
||||
This array tells you how many ticks per gravity by level. Decreases as level
|
||||
increases, to add difficulty.
|
||||
*/
|
||||
extern const int GRAVITY_LEVEL[MAX_LEVEL+1];
|
||||
|
||||
// Data structure manipulation.
|
||||
void tg_init(tetris_game *obj, int rows, int cols);
|
||||
tetris_game *tg_create(struct games_state *rs,int rows, int cols);
|
||||
void tg_destroy(tetris_game *obj);
|
||||
void tg_delete(tetris_game *obj);
|
||||
tetris_game *tg_load(FILE *f);
|
||||
void tg_save(tetris_game *obj, FILE *f);
|
||||
|
||||
// Public methods not related to memory:
|
||||
char tg_get(tetris_game *obj, int row, int col);
|
||||
bool tg_check(tetris_game *obj, int row, int col);
|
||||
bool tg_tick(struct games_state *rs,tetris_game *obj, tetris_move move);
|
||||
void tg_print(tetris_game *obj, FILE *f);
|
||||
|
||||
/******************************************************************************
|
||||
* 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. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
#define GAMENAME "prices" // name of executable
|
||||
#define GAMEMAIN prices // main program of game
|
||||
#define GAMEPLAYERJSON pricesplayerjson // displays game specific json
|
||||
#define GAMEDATA pricesdata // extracts data from game specific variables into games_state
|
||||
#define CHAINNAME "PRICES" // -ac_name=
|
||||
typedef uint64_t gamesevent; // can be 8, 16, 32, or 64 bits
|
||||
|
||||
#define MAXPACK 23
|
||||
struct games_packitem
|
||||
{
|
||||
int32_t type,launch,count,which,hplus,dplus,arm,flags,group;
|
||||
char damage[8],hurldmg[8];
|
||||
};
|
||||
|
||||
struct games_player
|
||||
{
|
||||
int32_t gold,hitpoints,strength,level,experience,packsize,dungeonlevel,amulet;
|
||||
struct games_packitem gamespack[MAXPACK];
|
||||
};
|
||||
|
||||
struct games_state
|
||||
{
|
||||
uint64_t seed,origseed;
|
||||
char *keystrokeshex;
|
||||
uint32_t needflush,replaydone;
|
||||
int32_t numkeys,ind,num,guiflag,counter,sleeptime,playersize,restoring,lastnum;
|
||||
FILE *logfp;
|
||||
struct games_player P;
|
||||
gamesevent buffered[5000],*keystrokes;
|
||||
uint8_t playerdata[8192];
|
||||
};
|
||||
extern struct games_state globalR;
|
||||
void *gamesiterate(struct games_state *rs);
|
||||
int32_t flushkeystrokes(struct games_state *rs,int32_t waitflag);
|
||||
|
||||
void games_packitemstr(char *packitemstr,struct games_packitem *item);
|
||||
uint64_t _games_rngnext(uint64_t initseed);
|
||||
int32_t games_replay2(uint8_t *newdata,uint64_t seed,gamesevent *keystrokes,int32_t num,struct games_player *player,int32_t sleepmillis);
|
||||
gamesevent games_revendian(gamesevent revx);
|
||||
int32_t disp_gamesplayer(char *str,struct games_player *P);
|
||||
|
||||
#endif
|
||||
|
||||
904
src/cc/games/tetris.c
Normal file
904
src/cc/games/tetris.c
Normal file
@@ -0,0 +1,904 @@
|
||||
|
||||
#include "tetris.h"
|
||||
|
||||
/*
|
||||
In order to port a game into gamesCC, the RNG needs to be seeded with the gametxid seed, also events needs to be broadcast using issue_games_events. Also the game engine needs to be daemonized, preferably by putting all globals into a single data structure.
|
||||
|
||||
also, the standalone game needs to support argv of seed gametxid, along with replay args
|
||||
*/
|
||||
|
||||
int random_tetromino(struct games_state *rs)
|
||||
{
|
||||
rs->seed = _games_rngnext(rs->seed);
|
||||
return(rs->seed % NUM_TETROMINOS);
|
||||
}
|
||||
|
||||
int32_t tetrisdata(struct games_player *P,void *ptr)
|
||||
{
|
||||
tetris_game *tg = (tetris_game *)ptr;
|
||||
P->gold = tg->points;
|
||||
P->dungeonlevel = tg->level;
|
||||
//fprintf(stderr,"score.%d level.%d\n",tg->points,tg->level);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/** https://github.com/brenns10/tetris
|
||||
@file main.c
|
||||
@author Stephen Brennan
|
||||
@date Created Wednesday, 10 June 2015
|
||||
@brief Main program for tetris.
|
||||
@copyright Copyright (c) 2015, Stephen Brennan. Released under the Revised
|
||||
BSD License. See LICENSE.txt for details.
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#include <stdio.h> // for FILE
|
||||
#include <stdbool.h> // for bool
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef BUILD_GAMESCC
|
||||
#include "../rogue/cursesd.h"
|
||||
#else
|
||||
#include <curses.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
|
||||
#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
|
||||
|
||||
/*******************************************************************************
|
||||
Array Definitions
|
||||
*******************************************************************************/
|
||||
|
||||
const tetris_location TETROMINOS[NUM_TETROMINOS][NUM_ORIENTATIONS][TETRIS] =
|
||||
{
|
||||
// I
|
||||
{{{1, 0}, {1, 1}, {1, 2}, {1, 3}},
|
||||
{{0, 2}, {1, 2}, {2, 2}, {3, 2}},
|
||||
{{3, 0}, {3, 1}, {3, 2}, {3, 3}},
|
||||
{{0, 1}, {1, 1}, {2, 1}, {3, 1}}},
|
||||
// J
|
||||
{{{0, 0}, {1, 0}, {1, 1}, {1, 2}},
|
||||
{{0, 1}, {0, 2}, {1, 1}, {2, 1}},
|
||||
{{1, 0}, {1, 1}, {1, 2}, {2, 2}},
|
||||
{{0, 1}, {1, 1}, {2, 0}, {2, 1}}},
|
||||
// L
|
||||
{{{0, 2}, {1, 0}, {1, 1}, {1, 2}},
|
||||
{{0, 1}, {1, 1}, {2, 1}, {2, 2}},
|
||||
{{1, 0}, {1, 1}, {1, 2}, {2, 0}},
|
||||
{{0, 0}, {0, 1}, {1, 1}, {2, 1}}},
|
||||
// O
|
||||
{{{0, 1}, {0, 2}, {1, 1}, {1, 2}},
|
||||
{{0, 1}, {0, 2}, {1, 1}, {1, 2}},
|
||||
{{0, 1}, {0, 2}, {1, 1}, {1, 2}},
|
||||
{{0, 1}, {0, 2}, {1, 1}, {1, 2}}},
|
||||
// S
|
||||
{{{0, 1}, {0, 2}, {1, 0}, {1, 1}},
|
||||
{{0, 1}, {1, 1}, {1, 2}, {2, 2}},
|
||||
{{1, 1}, {1, 2}, {2, 0}, {2, 1}},
|
||||
{{0, 0}, {1, 0}, {1, 1}, {2, 1}}},
|
||||
// T
|
||||
{{{0, 1}, {1, 0}, {1, 1}, {1, 2}},
|
||||
{{0, 1}, {1, 1}, {1, 2}, {2, 1}},
|
||||
{{1, 0}, {1, 1}, {1, 2}, {2, 1}},
|
||||
{{0, 1}, {1, 0}, {1, 1}, {2, 1}}},
|
||||
// Z
|
||||
{{{0, 0}, {0, 1}, {1, 1}, {1, 2}},
|
||||
{{0, 2}, {1, 1}, {1, 2}, {2, 1}},
|
||||
{{1, 0}, {1, 1}, {2, 1}, {2, 2}},
|
||||
{{0, 1}, {1, 0}, {1, 1}, {2, 0}}},
|
||||
};
|
||||
|
||||
const int GRAVITY_LEVEL[MAX_LEVEL+1] = {
|
||||
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
50, 48, 46, 44, 42, 40, 38, 36, 34, 32,
|
||||
//10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
||||
30, 28, 26, 24, 22, 20, 16, 12, 8, 4
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
Helper Functions for Blocks
|
||||
*******************************************************************************/
|
||||
|
||||
void sleep_milli(int milliseconds)
|
||||
{
|
||||
struct timespec ts;
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = milliseconds * 1000 * 1000;
|
||||
nanosleep(&ts, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
Return the block at the given row and column.
|
||||
*/
|
||||
char tg_get(tetris_game *obj, int row, int column)
|
||||
{
|
||||
return obj->board[obj->cols * row + column];
|
||||
}
|
||||
|
||||
/*
|
||||
Set the block at the given row and column.
|
||||
*/
|
||||
static void tg_set(tetris_game *obj, int row, int column, char value)
|
||||
{
|
||||
obj->board[obj->cols * row + column] = value;
|
||||
}
|
||||
|
||||
/*
|
||||
Check whether a row and column are in bounds.
|
||||
*/
|
||||
bool tg_check(tetris_game *obj, int row, int col)
|
||||
{
|
||||
return 0 <= row && row < obj->rows && 0 <= col && col < obj->cols;
|
||||
}
|
||||
|
||||
/*
|
||||
Place a block onto the board.
|
||||
*/
|
||||
static void tg_put(tetris_game *obj, tetris_block block)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < TETRIS; i++) {
|
||||
tetris_location cell = TETROMINOS[block.typ][block.ori][i];
|
||||
tg_set(obj, block.loc.row + cell.row, block.loc.col + cell.col,
|
||||
TYPE_TO_CELL(block.typ));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Clear a block out of the board.
|
||||
*/
|
||||
static void tg_remove(tetris_game *obj, tetris_block block)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < TETRIS; i++) {
|
||||
tetris_location cell = TETROMINOS[block.typ][block.ori][i];
|
||||
tg_set(obj, block.loc.row + cell.row, block.loc.col + cell.col, TC_EMPTY);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Check if a block can be placed on the board.
|
||||
*/
|
||||
static bool tg_fits(tetris_game *obj, tetris_block block)
|
||||
{
|
||||
int i, r, c;
|
||||
for (i = 0; i < TETRIS; i++) {
|
||||
tetris_location cell = TETROMINOS[block.typ][block.ori][i];
|
||||
r = block.loc.row + cell.row;
|
||||
c = block.loc.col + cell.col;
|
||||
if (!tg_check(obj, r, c) || TC_IS_FILLED(tg_get(obj, r, c))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Create a new falling block and populate the next falling block with a random
|
||||
one.
|
||||
*/
|
||||
static void tg_new_falling(struct games_state *rs,tetris_game *obj)
|
||||
{
|
||||
// Put in a new falling tetromino.
|
||||
obj->falling = obj->next;
|
||||
obj->next.typ = random_tetromino(rs);
|
||||
obj->next.ori = 0;
|
||||
obj->next.loc.row = 0;
|
||||
obj->next.loc.col = obj->cols/2 - 2;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Game Turn Helpers
|
||||
*******************************************************************************/
|
||||
|
||||
/*
|
||||
Tick gravity, and move the block down if gravity should act.
|
||||
*/
|
||||
static void tg_do_gravity_tick(struct games_state *rs,tetris_game *obj)
|
||||
{
|
||||
obj->ticks_till_gravity--;
|
||||
if (obj->ticks_till_gravity <= 0) {
|
||||
tg_remove(obj, obj->falling);
|
||||
obj->falling.loc.row++;
|
||||
if (tg_fits(obj, obj->falling)) {
|
||||
obj->ticks_till_gravity = GRAVITY_LEVEL[obj->level];
|
||||
} else {
|
||||
obj->falling.loc.row--;
|
||||
tg_put(obj, obj->falling);
|
||||
|
||||
tg_new_falling(rs,obj);
|
||||
}
|
||||
tg_put(obj, obj->falling);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Move the falling tetris block left (-1) or right (+1).
|
||||
*/
|
||||
static void tg_move(tetris_game *obj, int direction)
|
||||
{
|
||||
tg_remove(obj, obj->falling);
|
||||
obj->falling.loc.col += direction;
|
||||
if (!tg_fits(obj, obj->falling)) {
|
||||
obj->falling.loc.col -= direction;
|
||||
}
|
||||
tg_put(obj, obj->falling);
|
||||
}
|
||||
|
||||
/*
|
||||
Send the falling tetris block to the bottom.
|
||||
*/
|
||||
static void tg_down(struct games_state *rs,tetris_game *obj)
|
||||
{
|
||||
tg_remove(obj, obj->falling);
|
||||
while (tg_fits(obj, obj->falling)) {
|
||||
obj->falling.loc.row++;
|
||||
}
|
||||
obj->falling.loc.row--;
|
||||
tg_put(obj, obj->falling);
|
||||
tg_new_falling(rs,obj);
|
||||
}
|
||||
|
||||
/*
|
||||
Rotate the falling block in either direction (+/-1).
|
||||
*/
|
||||
static void tg_rotate(tetris_game *obj, int direction)
|
||||
{
|
||||
tg_remove(obj, obj->falling);
|
||||
|
||||
while (true) {
|
||||
obj->falling.ori = (obj->falling.ori + direction) % NUM_ORIENTATIONS;
|
||||
|
||||
// If the new orientation fits, we're done.
|
||||
if (tg_fits(obj, obj->falling))
|
||||
break;
|
||||
|
||||
// Otherwise, try moving left to make it fit.
|
||||
obj->falling.loc.col--;
|
||||
if (tg_fits(obj, obj->falling))
|
||||
break;
|
||||
|
||||
// Finally, try moving right to make it fit.
|
||||
obj->falling.loc.col += 2;
|
||||
if (tg_fits(obj, obj->falling))
|
||||
break;
|
||||
|
||||
// Put it back in its original location and try the next orientation.
|
||||
obj->falling.loc.col--;
|
||||
// Worst case, we come back to the original orientation and it fits, so this
|
||||
// loop will terminate.
|
||||
}
|
||||
|
||||
tg_put(obj, obj->falling);
|
||||
}
|
||||
|
||||
/*
|
||||
Swap the falling block with the block in the hold buffer.
|
||||
*/
|
||||
static void tg_hold(struct games_state *rs,tetris_game *obj)
|
||||
{
|
||||
tg_remove(obj, obj->falling);
|
||||
if (obj->stored.typ == -1) {
|
||||
obj->stored = obj->falling;
|
||||
tg_new_falling(rs,obj);
|
||||
} else {
|
||||
int typ = obj->falling.typ, ori = obj->falling.ori;
|
||||
obj->falling.typ = obj->stored.typ;
|
||||
obj->falling.ori = obj->stored.ori;
|
||||
obj->stored.typ = typ;
|
||||
obj->stored.ori = ori;
|
||||
while (!tg_fits(obj, obj->falling)) {
|
||||
obj->falling.loc.row--;
|
||||
if (tg_fits(obj, obj->falling)) {
|
||||
break;
|
||||
}
|
||||
obj->falling.loc.col--;
|
||||
if (tg_fits(obj, obj->falling)) {
|
||||
break;
|
||||
}
|
||||
obj->falling.loc.col += 2;
|
||||
}
|
||||
}
|
||||
tg_put(obj, obj->falling);
|
||||
}
|
||||
|
||||
/*
|
||||
Perform the action specified by the move.
|
||||
*/
|
||||
static void tg_handle_move(struct games_state *rs,tetris_game *obj, tetris_move move)
|
||||
{
|
||||
switch (move) {
|
||||
case TM_LEFT:
|
||||
//fprintf(stderr,"LEFT ");
|
||||
tg_move(obj, -1);
|
||||
break;
|
||||
case TM_RIGHT:
|
||||
//fprintf(stderr,"RIGHT ");
|
||||
tg_move(obj, 1);
|
||||
break;
|
||||
case TM_DROP:
|
||||
tg_down(rs,obj);
|
||||
break;
|
||||
case TM_CLOCK:
|
||||
tg_rotate(obj, 1);
|
||||
break;
|
||||
case TM_COUNTER:
|
||||
tg_rotate(obj, -1);
|
||||
break;
|
||||
case TM_HOLD:
|
||||
tg_hold(rs,obj);
|
||||
break;
|
||||
default:
|
||||
// pass
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Return true if line i is full.
|
||||
*/
|
||||
static bool tg_line_full(tetris_game *obj, int i)
|
||||
{
|
||||
int j;
|
||||
for (j = 0; j < obj->cols; j++) {
|
||||
if (TC_IS_EMPTY(tg_get(obj, i, j)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Shift every row above r down one.
|
||||
*/
|
||||
static void tg_shift_lines(tetris_game *obj, int r)
|
||||
{
|
||||
int i, j;
|
||||
for (i = r-1; i >= 0; i--) {
|
||||
for (j = 0; j < obj->cols; j++) {
|
||||
tg_set(obj, i+1, j, tg_get(obj, i, j));
|
||||
tg_set(obj, i, j, TC_EMPTY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Find rows that are filled, remove them, shift, and return the number of
|
||||
cleared rows.
|
||||
*/
|
||||
static int tg_check_lines(tetris_game *obj)
|
||||
{
|
||||
int i, nlines = 0;
|
||||
tg_remove(obj, obj->falling); // don't want to mess up falling block
|
||||
|
||||
for (i = obj->rows-1; i >= 0; i--) {
|
||||
if (tg_line_full(obj, i)) {
|
||||
tg_shift_lines(obj, i);
|
||||
i++; // do this line over again since they're shifted
|
||||
nlines++;
|
||||
}
|
||||
}
|
||||
|
||||
tg_put(obj, obj->falling); // replace
|
||||
return nlines;
|
||||
}
|
||||
|
||||
/*
|
||||
Adjust the score for the game, given how many lines were just cleared.
|
||||
*/
|
||||
static void tg_adjust_score(tetris_game *obj, int lines_cleared)
|
||||
{
|
||||
static int line_multiplier[] = {0, 40, 100, 300, 1200};
|
||||
obj->points += line_multiplier[lines_cleared] * (obj->level + 1);
|
||||
if (lines_cleared >= obj->lines_remaining) {
|
||||
obj->level = MIN(MAX_LEVEL, obj->level + 1);
|
||||
lines_cleared -= obj->lines_remaining;
|
||||
obj->lines_remaining = LINES_PER_LEVEL - lines_cleared;
|
||||
} else {
|
||||
obj->lines_remaining -= lines_cleared;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Return true if the game is over.
|
||||
*/
|
||||
static bool tg_game_over(tetris_game *obj)
|
||||
{
|
||||
int i, j;
|
||||
bool over = false;
|
||||
tg_remove(obj, obj->falling);
|
||||
for (i = 0; i < 2; i++) {
|
||||
for (j = 0; j < obj->cols; j++) {
|
||||
if (TC_IS_FILLED(tg_get(obj, i, j))) {
|
||||
over = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
tg_put(obj, obj->falling);
|
||||
return over;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Main Public Functions
|
||||
*******************************************************************************/
|
||||
|
||||
/*
|
||||
Do a single game tick: process gravity, user input, and score. Return true if
|
||||
the game is still running, false if it is over.
|
||||
*/
|
||||
bool tg_tick(struct games_state *rs,tetris_game *obj, tetris_move move)
|
||||
{
|
||||
int lines_cleared;
|
||||
// Handle gravity.
|
||||
tg_do_gravity_tick(rs,obj);
|
||||
|
||||
// Handle input.
|
||||
tg_handle_move(rs,obj, move);
|
||||
|
||||
// Check for cleared lines
|
||||
lines_cleared = tg_check_lines(obj);
|
||||
|
||||
tg_adjust_score(obj, lines_cleared);
|
||||
|
||||
// Return whether the game will continue (NOT whether it's over)
|
||||
return !tg_game_over(obj);
|
||||
}
|
||||
|
||||
void tg_init(struct games_state *rs,tetris_game *obj, int rows, int cols)
|
||||
{
|
||||
// Initialization logic
|
||||
obj->rows = rows;
|
||||
obj->cols = cols;
|
||||
//obj->board = (char *)malloc(rows * cols);
|
||||
memset(obj->board, TC_EMPTY, rows * cols);
|
||||
obj->points = 0;
|
||||
obj->level = 0;
|
||||
obj->ticks_till_gravity = GRAVITY_LEVEL[obj->level];
|
||||
obj->lines_remaining = LINES_PER_LEVEL;
|
||||
//srand(time(NULL));
|
||||
tg_new_falling(rs,obj);
|
||||
tg_new_falling(rs,obj);
|
||||
obj->stored.typ = -1;
|
||||
obj->stored.ori = 0;
|
||||
obj->stored.loc.row = 0;
|
||||
obj->next.loc.col = obj->cols/2 - 2;
|
||||
//printf("%d", obj->falling.loc.col);
|
||||
}
|
||||
|
||||
tetris_game *tg_create(struct games_state *rs,int rows, int cols)
|
||||
{
|
||||
tetris_game *obj = (tetris_game *)malloc(sizeof(tetris_game) + rows*cols);
|
||||
tg_init(rs,obj, rows, cols);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/*void tg_destroy(tetris_game *obj)
|
||||
{
|
||||
// Cleanup logic
|
||||
free(obj->board);
|
||||
}*/
|
||||
|
||||
void tg_delete(tetris_game *obj) {
|
||||
//tg_destroy(obj);
|
||||
free(obj);
|
||||
}
|
||||
|
||||
/*
|
||||
Load a game from a file.
|
||||
|
||||
tetris_game *tg_load(FILE *f)
|
||||
{
|
||||
tetris_game *obj = (tetris_game *)malloc(sizeof(tetris_game));
|
||||
if (fread(obj, sizeof(tetris_game), 1, f) != 1 )
|
||||
{
|
||||
fprintf(stderr,"read game error\n");
|
||||
free(obj);
|
||||
obj = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
obj->board = (char *)malloc(obj->rows * obj->cols);
|
||||
if (fread(obj->board, sizeof(char), obj->rows * obj->cols, f) != obj->rows * obj->cols )
|
||||
{
|
||||
fprintf(stderr,"fread error\n");
|
||||
free(obj->board);
|
||||
free(obj);
|
||||
obj = 0;
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}*/
|
||||
|
||||
/*
|
||||
Save a game to a file.
|
||||
|
||||
void tg_save(tetris_game *obj, FILE *f)
|
||||
{
|
||||
if (fwrite(obj, sizeof(tetris_game), 1, f) != 1 )
|
||||
fprintf(stderr,"error writing tetrisgame\n");
|
||||
else if (fwrite(obj->board, sizeof(char), obj->rows * obj->cols, f) != obj->rows * obj->cols )
|
||||
fprintf(stderr,"error writing board\n");
|
||||
}*/
|
||||
|
||||
/*
|
||||
Print a game board to a file. Really just for early debugging.
|
||||
*/
|
||||
void tg_print(tetris_game *obj, FILE *f) {
|
||||
int i, j;
|
||||
for (i = 0; i < obj->rows; i++) {
|
||||
for (j = 0; j < obj->cols; j++) {
|
||||
if (TC_IS_EMPTY(tg_get(obj, i, j))) {
|
||||
fputs(TC_EMPTY_STR, f);
|
||||
} else {
|
||||
fputs(TC_BLOCK_STR, f);
|
||||
}
|
||||
}
|
||||
fputc('\n', f);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
2 columns per cell makes the game much nicer.
|
||||
*/
|
||||
#define COLS_PER_CELL 2
|
||||
/*
|
||||
Macro to print a cell of a specific type to a window.
|
||||
*/
|
||||
#define ADD_BLOCK(w,x) waddch((w),' '|A_REVERSE|COLOR_PAIR(x)); \
|
||||
waddch((w),' '|A_REVERSE|COLOR_PAIR(x))
|
||||
#define ADD_EMPTY(w) waddch((w), ' '); waddch((w), ' ')
|
||||
|
||||
/*
|
||||
Print the tetris board onto the ncurses window.
|
||||
*/
|
||||
void display_board(WINDOW *w, tetris_game *obj)
|
||||
{
|
||||
int i, j;
|
||||
box(w, 0, 0);
|
||||
for (i = 0; i < obj->rows; i++) {
|
||||
wmove(w, 1 + i, 1);
|
||||
for (j = 0; j < obj->cols; j++) {
|
||||
if (TC_IS_FILLED(tg_get(obj, i, j))) {
|
||||
ADD_BLOCK(w,tg_get(obj, i, j));
|
||||
} else {
|
||||
ADD_EMPTY(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
wnoutrefresh(w);
|
||||
}
|
||||
|
||||
/*
|
||||
Display a tetris piece in a dedicated window.
|
||||
*/
|
||||
void display_piece(WINDOW *w, tetris_block block)
|
||||
{
|
||||
int b;
|
||||
tetris_location c;
|
||||
wclear(w);
|
||||
box(w, 0, 0);
|
||||
if (block.typ == -1) {
|
||||
wnoutrefresh(w);
|
||||
return;
|
||||
}
|
||||
for (b = 0; b < TETRIS; b++) {
|
||||
c = TETROMINOS[block.typ][block.ori][b];
|
||||
wmove(w, c.row + 1, c.col * COLS_PER_CELL + 1);
|
||||
ADD_BLOCK(w, TYPE_TO_CELL(block.typ));
|
||||
}
|
||||
wnoutrefresh(w);
|
||||
}
|
||||
|
||||
/*
|
||||
Display score information in a dedicated window.
|
||||
*/
|
||||
void display_score(WINDOW *w, tetris_game *tg)
|
||||
{
|
||||
wclear(w);
|
||||
box(w, 0, 0);
|
||||
wprintw(w, (char *)"Score\n%d\n", tg->points);
|
||||
wprintw(w, (char *)"Level\n%d\n", tg->level);
|
||||
wprintw(w, (char *)"Lines\n%d\n", tg->lines_remaining);
|
||||
wnoutrefresh(w);
|
||||
}
|
||||
|
||||
/*
|
||||
Save and exit the game.
|
||||
|
||||
void save(tetris_game *game, WINDOW *w)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
wclear(w);
|
||||
box(w, 0, 0); // return the border
|
||||
wmove(w, 1, 1);
|
||||
wprintw(w, (char *)"Save and exit? [Y/n] ");
|
||||
wrefresh(w);
|
||||
timeout(-1);
|
||||
if (getch() == 'n') {
|
||||
timeout(0);
|
||||
return;
|
||||
}
|
||||
f = fopen("tetris.save", "w");
|
||||
tg_save(game, f);
|
||||
fclose(f);
|
||||
tg_delete(game);
|
||||
endwin();
|
||||
fprintf(stderr,"Game saved to \"tetris.save\".\n");
|
||||
fprintf(stderr,"Resume by passing the filename as an argument to this program.\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
}*/
|
||||
|
||||
/*
|
||||
Do the NCURSES initialization steps for color blocks.
|
||||
*/
|
||||
void init_colors(void)
|
||||
{
|
||||
start_color();
|
||||
//init_color(COLOR_ORANGE, 1000, 647, 0);
|
||||
init_pair(TC_CELLI, COLOR_CYAN, COLOR_BLACK);
|
||||
init_pair(TC_CELLJ, COLOR_BLUE, COLOR_BLACK);
|
||||
init_pair(TC_CELLL, COLOR_WHITE, COLOR_BLACK);
|
||||
init_pair(TC_CELLO, COLOR_YELLOW, COLOR_BLACK);
|
||||
init_pair(TC_CELLS, COLOR_GREEN, COLOR_BLACK);
|
||||
init_pair(TC_CELLT, COLOR_MAGENTA, COLOR_BLACK);
|
||||
init_pair(TC_CELLZ, COLOR_RED, COLOR_BLACK);
|
||||
}
|
||||
|
||||
struct games_state globalR;
|
||||
extern char Gametxidstr[];
|
||||
int32_t issue_games_events(struct games_state *rs,char *gametxidstr,uint32_t eventid,gamesevent c);
|
||||
gamesevent games_readevent(struct games_state *rs);
|
||||
|
||||
void *gamesiterate(struct games_state *rs)
|
||||
{
|
||||
uint32_t counter = 0; bool running = true; tetris_move move = TM_NONE;
|
||||
gamesevent c; uint16_t skipcount=0; int32_t prevlevel; uint32_t eventid = 0; tetris_game *tg;
|
||||
WINDOW *board, *next, *hold, *score;
|
||||
if ( rs->guiflag != 0 || rs->sleeptime != 0 )
|
||||
{
|
||||
// NCURSES initialization:
|
||||
initscr(); // initialize curses
|
||||
cbreak(); // pass key presses to program, but not signals
|
||||
noecho(); // don't echo key presses to screen
|
||||
keypad(stdscr, TRUE); // allow arrow keys
|
||||
timeout(0); // no blocking on getch()
|
||||
curs_set(0); // set the cursor to invisible
|
||||
init_colors(); // setup tetris colors
|
||||
}
|
||||
tg = tg_create(rs,22, 10);
|
||||
prevlevel = tg->level;
|
||||
// Create windows for each section of the interface.
|
||||
board = newwin(tg->rows + 2, 2 * tg->cols + 2, 0, 0);
|
||||
next = newwin(6, 10, 0, 2 * (tg->cols + 1) + 1);
|
||||
hold = newwin(6, 10, 7, 2 * (tg->cols + 1) + 1);
|
||||
score = newwin(6, 10, 14, 2 * (tg->cols + 1 ) + 1);
|
||||
while ( running != 0 )
|
||||
{
|
||||
running = tg_tick(rs,tg,move);
|
||||
if ( 1 && (rs->guiflag != 0 || rs->sleeptime != 0) )
|
||||
{
|
||||
display_board(board,tg);
|
||||
display_piece(next,tg->next);
|
||||
display_piece(hold,tg->stored);
|
||||
display_score(score,tg);
|
||||
}
|
||||
if ( rs->guiflag != 0 )
|
||||
{
|
||||
#ifdef STANDALONE
|
||||
sleep_milli(15);
|
||||
if ( (counter++ % 10) == 0 )
|
||||
doupdate();
|
||||
c = games_readevent(rs);
|
||||
if ( c <= 0x7f || skipcount == 0x3fff )
|
||||
{
|
||||
if ( skipcount > 0 )
|
||||
issue_games_events(rs,Gametxidstr,eventid-skipcount,skipcount | 0x4000);
|
||||
if ( c <= 0x7f )
|
||||
issue_games_events(rs,Gametxidstr,eventid,c);
|
||||
if ( tg->level != prevlevel )
|
||||
{
|
||||
flushkeystrokes(rs,0);
|
||||
prevlevel = tg->level;
|
||||
}
|
||||
skipcount = 0;
|
||||
} else skipcount++;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( rs->replaydone != 0 )
|
||||
break;
|
||||
if ( rs->sleeptime != 0 )
|
||||
{
|
||||
sleep_milli(1);
|
||||
if ( (counter++ % 20) == 0 )
|
||||
doupdate();
|
||||
}
|
||||
if ( skipcount == 0 )
|
||||
{
|
||||
c = games_readevent(rs);
|
||||
//fprintf(stderr,"%04x score.%d level.%d\n",c,tg->points,tg->level);
|
||||
if ( (c & 0x4000) == 0x4000 )
|
||||
{
|
||||
skipcount = (c & 0x3fff);
|
||||
c = 'S';
|
||||
}
|
||||
}
|
||||
if ( skipcount > 0 )
|
||||
skipcount--;
|
||||
}
|
||||
eventid++;
|
||||
switch ( c )
|
||||
{
|
||||
case 'h':
|
||||
move = TM_LEFT;
|
||||
break;
|
||||
case 'l':
|
||||
move = TM_RIGHT;
|
||||
break;
|
||||
case 'k':
|
||||
move = TM_CLOCK;
|
||||
break;
|
||||
case 'j':
|
||||
move = TM_DROP;
|
||||
break;
|
||||
case 'q':
|
||||
running = false;
|
||||
move = TM_NONE;
|
||||
break;
|
||||
/*case 'p':
|
||||
wclear(board);
|
||||
box(board, 0, 0);
|
||||
wmove(board, tg->rows/2, (tg->cols*COLS_PER_CELL-6)/2);
|
||||
wprintw(board, "PAUSED");
|
||||
wrefresh(board);
|
||||
timeout(-1);
|
||||
getch();
|
||||
timeout(0);
|
||||
move = TM_NONE;
|
||||
break;
|
||||
case 's':
|
||||
save(tg, board);
|
||||
move = TM_NONE;
|
||||
break;*/
|
||||
case ' ':
|
||||
move = TM_HOLD;
|
||||
break;
|
||||
default:
|
||||
move = TM_NONE;
|
||||
}
|
||||
}
|
||||
return(tg);
|
||||
}
|
||||
|
||||
#ifdef STANDALONE
|
||||
/*
|
||||
Main tetris game!
|
||||
*/
|
||||
#include "dapps/dappstd.c"
|
||||
|
||||
|
||||
char *clonestr(char *str)
|
||||
{
|
||||
char *clone; int32_t len;
|
||||
if ( str == 0 || str[0] == 0 )
|
||||
{
|
||||
printf("warning cloning nullstr.%p\n",str);
|
||||
#ifdef __APPLE__
|
||||
while ( 1 ) sleep(1);
|
||||
#endif
|
||||
str = (char *)"<nullstr>";
|
||||
}
|
||||
len = strlen(str);
|
||||
clone = (char *)calloc(1,len+16);
|
||||
strcpy(clone,str);
|
||||
return(clone);
|
||||
}
|
||||
|
||||
int32_t issue_games_events(struct games_state *rs,char *gametxidstr,uint32_t eventid,gamesevent c)
|
||||
{
|
||||
static FILE *fp;
|
||||
char params[512],*retstr; cJSON *retjson,*resobj; int32_t retval = -1;
|
||||
if ( fp == 0 )
|
||||
fp = fopen("events.log","wb");
|
||||
rs->buffered[rs->num++] = c;
|
||||
if ( 0 )
|
||||
{
|
||||
if ( sizeof(c) == 1 )
|
||||
sprintf(params,"[\"events\",\"17\",\"[%%22%02x%%22,%%22%s%%22,%u]\"]",(uint8_t)c&0xff,gametxidstr,eventid);
|
||||
else if ( sizeof(c) == 2 )
|
||||
sprintf(params,"[\"events\",\"17\",\"[%%22%04x%%22,%%22%s%%22,%u]\"]",(uint16_t)c&0xffff,gametxidstr,eventid);
|
||||
else if ( sizeof(c) == 4 )
|
||||
sprintf(params,"[\"events\",\"17\",\"[%%22%08x%%22,%%22%s%%22,%u]\"]",(uint32_t)c&0xffffffff,gametxidstr,eventid);
|
||||
else if ( sizeof(c) == 8 )
|
||||
sprintf(params,"[\"events\",\"17\",\"[%%22%016llx%%22,%%22%s%%22,%u]\"]",(long long)c,gametxidstr,eventid);
|
||||
if ( (retstr= komodo_issuemethod(USERPASS,(char *)"cclib",params,GAMES_PORT)) != 0 )
|
||||
{
|
||||
if ( (retjson= cJSON_Parse(retstr)) != 0 )
|
||||
{
|
||||
if ( (resobj= jobj(retjson,(char *)"result")) != 0 )
|
||||
{
|
||||
retval = 0;
|
||||
if ( fp != 0 )
|
||||
{
|
||||
fprintf(fp,"%s\n",jprint(resobj,0));
|
||||
fflush(fp);
|
||||
}
|
||||
}
|
||||
free_json(retjson);
|
||||
} else fprintf(fp,"error parsing %s\n",retstr);
|
||||
free(retstr);
|
||||
} else fprintf(fp,"error issuing method %s\n",params);
|
||||
return(retval);
|
||||
} else return(0);
|
||||
}
|
||||
|
||||
int tetris(int argc, char **argv)
|
||||
{
|
||||
struct games_state *rs = &globalR;
|
||||
int32_t c,skipcount=0; uint32_t eventid = 0; tetris_game *tg = 0;
|
||||
memset(rs,0,sizeof(*rs));
|
||||
rs->guiflag = 1;
|
||||
rs->sleeptime = 1; // non-zero to allow refresh()
|
||||
if ( argc >= 2 && strlen(argv[2]) == 64 )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
#ifdef _MSC_VER
|
||||
rs->origseed = _strtoui64(argv[1], NULL, 10);
|
||||
#else
|
||||
rs->origseed = atol(argv[1]); // windows, but not MSVC
|
||||
#endif // _MSC_VER
|
||||
#else
|
||||
rs->origseed = atol(argv[1]); // non-windows
|
||||
#endif // _WIN32
|
||||
rs->seed = rs->origseed;
|
||||
if ( argc >= 3 )
|
||||
{
|
||||
strcpy(Gametxidstr,argv[2]);
|
||||
fprintf(stderr,"setplayerdata %s\n",Gametxidstr);
|
||||
if ( games_setplayerdata(rs,Gametxidstr) < 0 )
|
||||
{
|
||||
fprintf(stderr,"invalid gametxid, or already started\n");
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
} else rs->seed = 777;
|
||||
|
||||
/* Load file if given a filename.
|
||||
if (argc >= 2) {
|
||||
FILE *f = fopen(argv[1], "r");
|
||||
if (f == NULL) {
|
||||
perror("tetris");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
tg = tg_load(f);
|
||||
fclose(f);
|
||||
} else {
|
||||
// Otherwise create new game.
|
||||
tg = tg_create(rs,22, 10);
|
||||
}*/
|
||||
|
||||
// Game loop
|
||||
tg = (tetris_game *)gamesiterate(rs);
|
||||
gamesbailout(rs);
|
||||
// Deinitialize NCurses
|
||||
wclear(stdscr);
|
||||
endwin();
|
||||
// Output ending message.
|
||||
printf("Game over!\n");
|
||||
printf("You finished with %d points on level %d.\n", tg->points, tg->level);
|
||||
|
||||
// Deinitialize Tetris
|
||||
tg_delete(tg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
87
src/cc/games/tetris.cpp
Normal file
87
src/cc/games/tetris.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
|
||||
/******************************************************************************
|
||||
* 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. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
std::string MYCCLIBNAME = (char *)"gamescc";
|
||||
|
||||
// game specific code for daemon
|
||||
void games_packitemstr(char *packitemstr,struct games_packitem *item)
|
||||
{
|
||||
strcpy(packitemstr,"");
|
||||
}
|
||||
|
||||
int64_t games_cashout(struct games_player *P)
|
||||
{
|
||||
int32_t dungeonlevel = P->dungeonlevel; int64_t mult=10000,cashout = 0;
|
||||
cashout = (uint64_t)P->gold * mult;
|
||||
return(cashout);
|
||||
}
|
||||
|
||||
void tetrisplayerjson(UniValue &obj,struct games_player *P)
|
||||
{
|
||||
obj.push_back(Pair("packsize",(int64_t)P->packsize));
|
||||
obj.push_back(Pair("hitpoints",(int64_t)P->hitpoints));
|
||||
obj.push_back(Pair("strength",(int64_t)(P->strength&0xffff)));
|
||||
obj.push_back(Pair("maxstrength",(int64_t)(P->strength>>16)));
|
||||
obj.push_back(Pair("level",(int64_t)P->level));
|
||||
obj.push_back(Pair("experience",(int64_t)P->experience));
|
||||
obj.push_back(Pair("dungeonlevel",(int64_t)P->dungeonlevel));
|
||||
}
|
||||
|
||||
int32_t disp_gamesplayer(char *str,struct games_player *P)
|
||||
{
|
||||
str[0] = 0;
|
||||
//if ( P->gold <= 0 )//|| P->hitpoints <= 0 || (P->strength&0xffff) <= 0 || P->level <= 0 || P->experience <= 0 || P->dungeonlevel <= 0 )
|
||||
// return(-1);
|
||||
sprintf(str," <- playerdata: gold.%d hp.%d strength.%d/%d level.%d exp.%d dl.%d",P->gold,P->hitpoints,P->strength&0xffff,P->strength>>16,P->level,P->experience,P->dungeonlevel);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t games_payloadrecv(CPubKey pk,uint32_t timestamp,std::vector<uint8_t> payload)
|
||||
{
|
||||
uint256 gametxid; int32_t i,len; char str[67]; uint32_t eventid = 0;
|
||||
if ( (len= payload.size()) > 36 )
|
||||
{
|
||||
len -= 36;
|
||||
for (i=0; i<32; i++)
|
||||
((uint8_t *)&gametxid)[i] = payload[len+i];
|
||||
eventid = (uint32_t)payload[len+32];
|
||||
eventid |= (uint32_t)payload[len+33] << 8;
|
||||
eventid |= (uint32_t)payload[len+34] << 16;
|
||||
eventid |= (uint32_t)payload[len+35] << 24;
|
||||
//for (i=0; i<len; i++)
|
||||
// fprintf(stderr,"%02x",payload[i]);
|
||||
//fprintf(stderr," got payload, from %s %s/e%d\n",pubkey33_str(str,(uint8_t *)&pk),gametxid.GetHex().c_str(),eventid);
|
||||
return(0);
|
||||
} else return(-1);
|
||||
}
|
||||
|
||||
UniValue games_bet(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
|
||||
{
|
||||
UniValue result;
|
||||
return(result);
|
||||
}
|
||||
|
||||
UniValue games_settle(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
|
||||
{
|
||||
UniValue result;
|
||||
return(result);
|
||||
}
|
||||
|
||||
bool games_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx)
|
||||
{
|
||||
return(true);
|
||||
}
|
||||
|
||||
208
src/cc/games/tetris.h
Normal file
208
src/cc/games/tetris.h
Normal file
@@ -0,0 +1,208 @@
|
||||
|
||||
#ifndef H_TETRIS_H
|
||||
#define H_TETRIS_H
|
||||
|
||||
/***************************************************************************/
|
||||
/** https://github.com/brenns10/tetris
|
||||
@file main.c
|
||||
@author Stephen Brennan
|
||||
@date Created Wednesday, 10 June 2015
|
||||
@brief Main program for tetris.
|
||||
@copyright Copyright (c) 2015, Stephen Brennan. Released under the Revised
|
||||
BSD License. See LICENSE.txt for details.
|
||||
*******************************************************************************/
|
||||
|
||||
/*
|
||||
Convert a tetromino type to its corresponding cell.
|
||||
*/
|
||||
#define TYPE_TO_CELL(x) ((x)+1)
|
||||
|
||||
/*
|
||||
Strings for how you would print a tetris board.
|
||||
*/
|
||||
#define TC_EMPTY_STR " "
|
||||
#define TC_BLOCK_STR "\u2588"
|
||||
|
||||
/*
|
||||
Questions about a tetris cell.
|
||||
*/
|
||||
#define TC_IS_EMPTY(x) ((x) == TC_EMPTY)
|
||||
#define TC_IS_FILLED(x) (!TC_IS_EMPTY(x))
|
||||
|
||||
/*
|
||||
How many cells in a tetromino?
|
||||
*/
|
||||
#define TETRIS 4
|
||||
/*
|
||||
How many tetrominos?
|
||||
*/
|
||||
#define NUM_TETROMINOS 7
|
||||
/*
|
||||
How many orientations of a tetromino?
|
||||
*/
|
||||
#define NUM_ORIENTATIONS 4
|
||||
|
||||
/*
|
||||
Level constants.
|
||||
*/
|
||||
#define MAX_LEVEL 19
|
||||
#define LINES_PER_LEVEL 10
|
||||
|
||||
/*
|
||||
A "cell" is a 1x1 block within a tetris board.
|
||||
*/
|
||||
typedef enum {
|
||||
TC_EMPTY, TC_CELLI, TC_CELLJ, TC_CELLL, TC_CELLO, TC_CELLS, TC_CELLT, TC_CELLZ
|
||||
} tetris_cell;
|
||||
|
||||
/*
|
||||
A "type" is a type/shape of a tetromino. Not including orientation.
|
||||
*/
|
||||
typedef enum {
|
||||
TET_I, TET_J, TET_L, TET_O, TET_S, TET_T, TET_Z
|
||||
} tetris_type;
|
||||
|
||||
/*
|
||||
A row,column pair. Negative numbers allowed, because we need them for
|
||||
offsets.
|
||||
*/
|
||||
typedef struct {
|
||||
int row;
|
||||
int col;
|
||||
} tetris_location;
|
||||
|
||||
/*
|
||||
A "block" is a struct that contains information about a tetromino.
|
||||
Specifically, what type it is, what orientation it has, and where it is.
|
||||
*/
|
||||
typedef struct {
|
||||
int typ;
|
||||
int ori;
|
||||
tetris_location loc;
|
||||
} tetris_block;
|
||||
|
||||
/*
|
||||
All possible moves to give as input to the game.
|
||||
*/
|
||||
typedef enum {
|
||||
TM_LEFT, TM_RIGHT, TM_CLOCK, TM_COUNTER, TM_DROP, TM_HOLD, TM_NONE
|
||||
} tetris_move;
|
||||
|
||||
/*
|
||||
A game object!
|
||||
*/
|
||||
typedef struct {
|
||||
/*
|
||||
Game board stuff:
|
||||
*/
|
||||
int rows;
|
||||
int cols;
|
||||
/*
|
||||
Scoring information:
|
||||
*/
|
||||
int points;
|
||||
int level;
|
||||
/*
|
||||
Falling block is the one currently going down. Next block is the one that
|
||||
will be falling after this one. Stored is the block that you can swap out.
|
||||
*/
|
||||
tetris_block falling;
|
||||
tetris_block next;
|
||||
tetris_block stored;
|
||||
/*
|
||||
Number of game ticks until the block will move down.
|
||||
*/
|
||||
int ticks_till_gravity;
|
||||
/*
|
||||
Number of lines until you advance to the next level.
|
||||
*/
|
||||
int lines_remaining;
|
||||
char board[];
|
||||
} tetris_game;
|
||||
|
||||
/*
|
||||
This array stores all necessary information about the cells that are filled by
|
||||
each tetromino. The first index is the type of the tetromino (i.e. shape,
|
||||
e.g. I, J, Z, etc.). The next index is the orientation (0-3). The final
|
||||
array contains 4 tetris_location objects, each mapping to an offset from a
|
||||
point on the upper left that is the tetromino "origin".
|
||||
*/
|
||||
extern const tetris_location TETROMINOS[NUM_TETROMINOS][NUM_ORIENTATIONS][TETRIS];
|
||||
|
||||
/*
|
||||
This array tells you how many ticks per gravity by level. Decreases as level
|
||||
increases, to add difficulty.
|
||||
*/
|
||||
extern const int GRAVITY_LEVEL[MAX_LEVEL+1];
|
||||
|
||||
// Data structure manipulation.
|
||||
void tg_init(tetris_game *obj, int rows, int cols);
|
||||
tetris_game *tg_create(struct games_state *rs,int rows, int cols);
|
||||
void tg_destroy(tetris_game *obj);
|
||||
void tg_delete(tetris_game *obj);
|
||||
tetris_game *tg_load(FILE *f);
|
||||
void tg_save(tetris_game *obj, FILE *f);
|
||||
|
||||
// Public methods not related to memory:
|
||||
char tg_get(tetris_game *obj, int row, int col);
|
||||
bool tg_check(tetris_game *obj, int row, int col);
|
||||
bool tg_tick(struct games_state *rs,tetris_game *obj, tetris_move move);
|
||||
void tg_print(tetris_game *obj, FILE *f);
|
||||
|
||||
/******************************************************************************
|
||||
* 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. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
#define GAMENAME "tetris" // name of executable
|
||||
#define GAMEMAIN tetris // main program of game
|
||||
#define GAMEPLAYERJSON tetrisplayerjson // displays game specific json
|
||||
#define GAMEDATA tetrisdata // extracts data from game specific variables into games_state
|
||||
#define CHAINNAME "GTEST" // -ac_name=
|
||||
typedef uint16_t gamesevent; // can be 8, 16, 32, or 64 bits
|
||||
|
||||
#define MAXPACK 23
|
||||
struct games_packitem
|
||||
{
|
||||
int32_t type,launch,count,which,hplus,dplus,arm,flags,group;
|
||||
char damage[8],hurldmg[8];
|
||||
};
|
||||
|
||||
struct games_player
|
||||
{
|
||||
int32_t gold,hitpoints,strength,level,experience,packsize,dungeonlevel,amulet;
|
||||
struct games_packitem gamespack[MAXPACK];
|
||||
};
|
||||
|
||||
struct games_state
|
||||
{
|
||||
uint64_t seed,origseed;
|
||||
char *keystrokeshex;
|
||||
uint32_t needflush,replaydone;
|
||||
int32_t numkeys,ind,num,guiflag,counter,sleeptime,playersize,restoring,lastnum;
|
||||
FILE *logfp;
|
||||
struct games_player P;
|
||||
gamesevent buffered[5000],*keystrokes;
|
||||
uint8_t playerdata[8192];
|
||||
};
|
||||
extern struct games_state globalR;
|
||||
void *gamesiterate(struct games_state *rs);
|
||||
int32_t flushkeystrokes(struct games_state *rs,int32_t waitflag);
|
||||
|
||||
void games_packitemstr(char *packitemstr,struct games_packitem *item);
|
||||
uint64_t _games_rngnext(uint64_t initseed);
|
||||
int32_t games_replay2(uint8_t *newdata,uint64_t seed,gamesevent *keystrokes,int32_t num,struct games_player *player,int32_t sleepmillis);
|
||||
gamesevent games_revendian(gamesevent revx);
|
||||
int32_t disp_gamesplayer(char *str,struct games_player *P);
|
||||
|
||||
#endif
|
||||
|
||||
1811
src/cc/gamescc.cpp
Normal file
1811
src/cc/gamescc.cpp
Normal file
File diff suppressed because it is too large
Load Diff
120
src/cc/gamescc.h
Normal file
120
src/cc/gamescc.h
Normal file
@@ -0,0 +1,120 @@
|
||||
#ifndef H_GAMESCC_H
|
||||
#define H_GAMESCC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#define GAMES_RNGMULT 11109
|
||||
#define GAMES_RNGOFFSET 13849
|
||||
#define GAMES_MAXRNGS 10000
|
||||
|
||||
#ifndef STANDALONE
|
||||
|
||||
#define ENABLE_WALLET
|
||||
extern CWallet* pwalletMain;
|
||||
|
||||
#include "CCinclude.h"
|
||||
#include "secp256k1.h"
|
||||
|
||||
|
||||
#define EVAL_GAMES (EVAL_FAUCET2+1)
|
||||
#define GAMES_TXFEE 10000
|
||||
#define GAMES_MAXITERATIONS 777
|
||||
#define GAMES_MAXKEYSTROKESGAP 60
|
||||
#define GAMES_MAXPLAYERS 64
|
||||
#define GAMES_REGISTRATIONSIZE (100 * 10000)
|
||||
#define GAMES_REGISTRATION 1
|
||||
|
||||
|
||||
#define MYCCNAME "games"
|
||||
|
||||
std::string Games_pname;
|
||||
|
||||
#define RPC_FUNCS \
|
||||
{ (char *)MYCCNAME, (char *)"rng", (char *)"hash,playerid", 1, 2, ' ', EVAL_GAMES }, \
|
||||
{ (char *)MYCCNAME, (char *)"rngnext", (char *)"seed", 1, 1, ' ', EVAL_GAMES }, \
|
||||
{ (char *)MYCCNAME, (char *)"fund", (char *)"amount", 1, 1, ' ', EVAL_GAMES }, \
|
||||
{ (char *)MYCCNAME, (char *)"players", (char *)"no params", 0, 0, ' ', EVAL_GAMES }, \
|
||||
{ (char *)MYCCNAME, (char *)"games", (char *)"no params", 0, 0, ' ', EVAL_GAMES }, \
|
||||
{ (char *)MYCCNAME, (char *)"pending", (char *)"no params", 0, 0, ' ', EVAL_GAMES }, \
|
||||
{ (char *)MYCCNAME, (char *)"setname", (char *)"pname", 1, 1, ' ', EVAL_GAMES }, \
|
||||
{ (char *)MYCCNAME, (char *)"newgame", (char *)"maxplayers,buyin", 2, 2, 'C', EVAL_GAMES }, \
|
||||
{ (char *)MYCCNAME, (char *)"playerinfo", (char *)"playertxid", 1, 1, ' ', EVAL_GAMES }, \
|
||||
{ (char *)MYCCNAME, (char *)"gameinfo", (char *)"gametxid", 1, 1, ' ', EVAL_GAMES }, \
|
||||
{ (char *)MYCCNAME, (char *)"keystrokes", (char *)"txid,hexstr", 2, 2, 'K', EVAL_GAMES }, \
|
||||
{ (char *)MYCCNAME, (char *)"bailout", (char *)"gametxid", 1, 1, 'Q', EVAL_GAMES }, \
|
||||
{ (char *)MYCCNAME, (char *)"highlander", (char *)"gametxid", 1, 1, 'H', EVAL_GAMES }, \
|
||||
{ (char *)MYCCNAME, (char *)"events", (char *)"eventshex [gametxid [eventid]]", 1, 3, ' ', EVAL_GAMES }, \
|
||||
{ (char *)MYCCNAME, (char *)"extract", (char *)"gametxid [pubkey]", 1, 2, ' ', EVAL_GAMES }, \
|
||||
{ (char *)MYCCNAME, (char *)"bet", (char *)"amount hexstr", 2, 2, ' ', EVAL_GAMES }, \
|
||||
{ (char *)MYCCNAME, (char *)"settle", (char *)"height", 1, 1, ' ', EVAL_GAMES }, \
|
||||
{ (char *)MYCCNAME, (char *)"register", (char *)"gametxid [playertxid]", 1, 2, 'R', EVAL_GAMES },
|
||||
|
||||
bool games_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx);
|
||||
UniValue games_rng(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
|
||||
UniValue games_rngnext(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
|
||||
UniValue games_fund(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
|
||||
UniValue games_players(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
|
||||
UniValue games_games(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
|
||||
UniValue games_pending(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
|
||||
UniValue games_setname(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
|
||||
UniValue games_newgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
|
||||
UniValue games_playerinfo(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
|
||||
UniValue games_gameinfo(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
|
||||
UniValue games_keystrokes(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
|
||||
UniValue games_bailout(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
|
||||
UniValue games_highlander(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
|
||||
UniValue games_events(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
|
||||
UniValue games_extract(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
|
||||
UniValue games_register(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
|
||||
UniValue games_bet(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
|
||||
UniValue games_settle(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
|
||||
|
||||
#define CUSTOM_DISPATCH \
|
||||
if ( cp->evalcode == EVAL_GAMES ) \
|
||||
{ \
|
||||
if ( strcmp(method,"rng") == 0 ) \
|
||||
return(games_rng(txfee,cp,params)); \
|
||||
else if ( strcmp(method,"rngnext") == 0 ) \
|
||||
return(games_rngnext(txfee,cp,params)); \
|
||||
else if ( strcmp(method,"newgame") == 0 ) \
|
||||
return(games_newgame(txfee,cp,params)); \
|
||||
else if ( strcmp(method,"gameinfo") == 0 ) \
|
||||
return(games_gameinfo(txfee,cp,params)); \
|
||||
else if ( strcmp(method,"register") == 0 ) \
|
||||
return(games_register(txfee,cp,params)); \
|
||||
else if ( strcmp(method,"events") == 0 ) \
|
||||
return(games_events(txfee,cp,params)); \
|
||||
else if ( strcmp(method,"players") == 0 ) \
|
||||
return(games_players(txfee,cp,params)); \
|
||||
else if ( strcmp(method,"games") == 0 ) \
|
||||
return(games_games(txfee,cp,params)); \
|
||||
else if ( strcmp(method,"pending") == 0 ) \
|
||||
return(games_pending(txfee,cp,params)); \
|
||||
else if ( strcmp(method,"setname") == 0 ) \
|
||||
return(games_setname(txfee,cp,params)); \
|
||||
else if ( strcmp(method,"playerinfo") == 0 ) \
|
||||
return(games_playerinfo(txfee,cp,params)); \
|
||||
else if ( strcmp(method,"keystrokes") == 0 ) \
|
||||
return(games_keystrokes(txfee,cp,params)); \
|
||||
else if ( strcmp(method,"extract") == 0 ) \
|
||||
return(games_extract(txfee,cp,params)); \
|
||||
else if ( strcmp(method,"bailout") == 0 ) \
|
||||
return(games_bailout(txfee,cp,params)); \
|
||||
else if ( strcmp(method,"highlander") == 0 ) \
|
||||
return(games_highlander(txfee,cp,params)); \
|
||||
else if ( strcmp(method,"fund") == 0 ) \
|
||||
return(games_fund(txfee,cp,params)); \
|
||||
else if ( strcmp(method,"bet") == 0 ) \
|
||||
return(games_bet(txfee,cp,params)); \
|
||||
else if ( strcmp(method,"settle") == 0 ) \
|
||||
return(games_settle(txfee,cp,params)); \
|
||||
else \
|
||||
{ \
|
||||
result.push_back(Pair("result","error")); \
|
||||
result.push_back(Pair("error","invalid gamescc method")); \
|
||||
return(result); \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -152,6 +152,7 @@
|
||||
#define KMD_P2SHTYPE 85
|
||||
#define KMD_WIFTYPE 188
|
||||
#define KMD_TADDR 0
|
||||
#define CC_MARKER_VALUE 10000
|
||||
|
||||
CScript EncodeGatewaysBindOpRet(uint8_t funcid,uint256 tokenid,std::string coin,int64_t totalsupply,uint256 oracletxid,uint8_t M,uint8_t N,std::vector<CPubKey> gatewaypubkeys,uint8_t taddr,uint8_t prefix,uint8_t prefix2,uint8_t wiftype)
|
||||
{
|
||||
@@ -185,7 +186,7 @@ uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,ui
|
||||
if ( N > 1 )
|
||||
{
|
||||
strcpy(depositaddr,CBitcoinAddress(CScriptID(GetScriptForMultisig(M,gatewaypubkeys))).ToString().c_str());
|
||||
LOGSTREAM("gatewayscc", CCLOG_DEBUG1, stream << "f." << f << " M." << M << " of N." << N << " size." << (int32_t)gatewaypubkeys.size() << " -> " << depositaddr << std::endl);
|
||||
LOGSTREAM("gatewayscc", CCLOG_DEBUG1, stream << "f." << f << " M." << (int)M << " of N." << (int)N << " size." << (int32_t)gatewaypubkeys.size() << " -> " << depositaddr << std::endl);
|
||||
} else Getscriptaddress(depositaddr,CScript() << ParseHex(HexStr(gatewaypubkeys[0])) << OP_CHECKSIG);
|
||||
}
|
||||
else
|
||||
@@ -411,91 +412,6 @@ bool GatewaysExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransacti
|
||||
else return(true);
|
||||
}
|
||||
|
||||
static int32_t myIs_coinaddr_inmempoolvout(char *coinaddr)
|
||||
{
|
||||
int32_t i,n; char destaddr[64];
|
||||
BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx)
|
||||
{
|
||||
const CTransaction &tx = e.GetTx();
|
||||
if ( (n= tx.vout.size()) > 0 )
|
||||
{
|
||||
const uint256 &txid = tx.GetHash();
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
Getscriptaddress(destaddr,tx.vout[i].scriptPubKey);
|
||||
if ( strcmp(destaddr,coinaddr) == 0 )
|
||||
{
|
||||
LOGSTREAM("gatewayscc",CCLOG_DEBUG1, stream << "found (" << coinaddr << ") vout in mempool" << std::endl);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
uint256 GatewaysReverseScan(uint256 &txid,int32_t height,uint256 reforacletxid,uint256 batontxid)
|
||||
{
|
||||
CTransaction tx; uint256 hash,mhash,bhash,hashBlock,oracletxid; int32_t len,len2,numvouts; int64_t val,merkleht; CPubKey pk; std::vector<uint8_t>data;
|
||||
txid = zeroid;
|
||||
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "start reverse scan " << batontxid.GetHex() << std::endl);
|
||||
while ( myGetTransaction(batontxid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 0 )
|
||||
{
|
||||
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "check " << batontxid.GetHex() << std::endl);
|
||||
if ( DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,bhash,pk,data) == 'D' && oracletxid == reforacletxid )
|
||||
{
|
||||
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "decoded " << batontxid.GetHex() << std::endl);
|
||||
if ( oracle_format(&hash,&merkleht,0,'I',(uint8_t *)data.data(),0,(int32_t)data.size()) == sizeof(int32_t) && merkleht == height )
|
||||
{
|
||||
len = oracle_format(&hash,&val,0,'h',(uint8_t *)data.data(),sizeof(int32_t),(int32_t)data.size());
|
||||
len2 = oracle_format(&mhash,&val,0,'h',(uint8_t *)data.data(),(int32_t)(sizeof(int32_t)+sizeof(uint256)),(int32_t)data.size());
|
||||
LOGSTREAM("gatewayscc",CCLOG_DEBUG1, stream << "found merkleht." << (int32_t)merkleht << " len." << len << " len2." << len2 << " " << hash.GetHex() << " " << mhash.GetHex() << std::endl);
|
||||
if ( len == sizeof(hash)+sizeof(int32_t) && len2 == 2*sizeof(mhash)+sizeof(int32_t) && mhash != zeroid )
|
||||
{
|
||||
txid = batontxid;
|
||||
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "set txid" << std::endl);
|
||||
return(mhash);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "missing hash" << std::endl);
|
||||
return(zeroid);
|
||||
}
|
||||
} else LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "height." << (int32_t)merkleht << " vs search ht." << (int32_t)height << std::endl);
|
||||
batontxid = bhash;
|
||||
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "new hash " << batontxid.GetHex() << std::endl);
|
||||
} else break;
|
||||
}
|
||||
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "end of loop\n");
|
||||
return(zeroid);
|
||||
}
|
||||
|
||||
int32_t GatewaysCointxidExists(struct CCcontract_info *cp,uint256 cointxid)
|
||||
{
|
||||
char txidaddr[64]; std::string coin; int32_t numvouts; uint256 hashBlock;
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
|
||||
CCtxidaddr(txidaddr,cointxid);
|
||||
SetCCtxids(addressIndex,txidaddr);
|
||||
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++)
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
return(myIs_coinaddr_inmempoolvout(txidaddr));
|
||||
}
|
||||
|
||||
/* Get the block merkle root for a proof
|
||||
* IN: proofData
|
||||
* OUT: merkle root
|
||||
* OUT: transaction IDS
|
||||
*/
|
||||
uint256 BitcoinGetProofMerkleRoot(const std::vector<uint8_t> &proofData, std::vector<uint256> &txids)
|
||||
{
|
||||
CMerkleBlock merkleBlock;
|
||||
if (!E_UNMARSHAL(proofData, ss >> merkleBlock))
|
||||
return uint256();
|
||||
return merkleBlock.txn.ExtractMatches(txids);
|
||||
}
|
||||
|
||||
int64_t GatewaysVerify(char *refdepositaddr,uint256 oracletxid,int32_t claimvout,std::string refcoin,uint256 cointxid,const std::string deposithex,std::vector<uint8_t>proof,uint256 merkleroot,CPubKey destpub,uint8_t taddr,uint8_t prefix,uint8_t prefix2)
|
||||
{
|
||||
std::vector<uint256> txids; uint256 proofroot,hashBlock,txid = zeroid; CTransaction tx; std::string name,description,format;
|
||||
@@ -600,7 +516,7 @@ int32_t GatewaysBindExists(struct CCcontract_info *cp,CPubKey gatewayspk,uint256
|
||||
bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks,height,claimvout; bool retval; uint8_t funcid,hash[32],K,M,N,taddr,prefix,prefix2,wiftype;
|
||||
char str[65],destaddr[64],depositaddr[65],validationError[512];
|
||||
char str[65],destaddr[65],depositaddr[65],gatewaystokensaddr[65],validationError[512];
|
||||
std::vector<uint256> txids; std::vector<CPubKey> pubkeys,publishers,tmppublishers; std::vector<uint8_t> proof; int64_t fullsupply,totalsupply,amount,tmpamount;
|
||||
uint256 hashblock,txid,bindtxid,deposittxid,withdrawtxid,completetxid,tokenid,tmptokenid,oracletxid,bindtokenid,cointxid,tmptxid,merkleroot,mhash; CTransaction bindtx,tmptx;
|
||||
std::string refcoin,tmprefcoin,hex,name,description,format; CPubKey pubkey,tmppubkey,gatewayspk;
|
||||
@@ -619,7 +535,8 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
gatewayspk = GetUnspendable(cp,0);
|
||||
gatewayspk = GetUnspendable(cp,0);
|
||||
GetTokensCCaddress(cp, gatewaystokensaddr, gatewayspk);
|
||||
if ( (funcid = DecodeGatewaysOpRet(tx.vout[numvouts-1].scriptPubKey)) != 0)
|
||||
{
|
||||
switch ( funcid )
|
||||
@@ -628,14 +545,14 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
|
||||
//vin.0: normal input
|
||||
//vin.1: CC input of tokens
|
||||
//vout.0: CC vout of gateways tokens to gateways tokens CC address
|
||||
//vout.1: CC vout txfee marker
|
||||
//vout.1: CC vout marker
|
||||
//vout.n-1: opreturn - 'B' tokenid coin totalsupply oracletxid M N pubkeys taddr prefix prefix2 wiftype
|
||||
return eval->Invalid("unexpected GatewaysValidate for gatewaysbind!");
|
||||
break;
|
||||
case 'D':
|
||||
//vin.0: normal input
|
||||
//vout.0: CC vout txfee marker to destination pubkey
|
||||
//vout.1: normal output txfee marker to txidaddr
|
||||
//vout.0: CC vout marker to destination pubkey
|
||||
//vout.1: normal output marker to txidaddr
|
||||
//vout.n-1: opreturn - 'D' bindtxid coin publishers txids height cointxid claimvout deposithex proof destpub amount
|
||||
return eval->Invalid("unexpected GatewaysValidate for gatewaysdeposit!");
|
||||
break;
|
||||
@@ -647,19 +564,19 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
|
||||
//vout.1: CC vout change of gateways tokens to gateways tokens CC address (if any)
|
||||
//vout.n-1: opreturn - 'C' tokenid bindtxid coin deposittxid destpub amount
|
||||
if ((numvouts=tx.vout.size()) < 1 || DecodeGatewaysClaimOpRet(tx.vout[numvouts-1].scriptPubKey,tmptokenid,bindtxid,refcoin,deposittxid,pubkey,amount)!='C')
|
||||
return eval->Invalid("invalid gatewaysClaim OP_RETURN data!");
|
||||
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for gatewaysClaim!");
|
||||
else if ( IsCCInput(tx.vin[1].scriptSig) == 0 )
|
||||
return eval->Invalid("vin.1 is CC for gatewaysClaim!");
|
||||
else if ( IsCCInput(tx.vin[2].scriptSig) == 0 )
|
||||
return eval->Invalid("vin.2 is CC for gatewaysClaim!");
|
||||
else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 )
|
||||
return eval->Invalid("vout.0 is CC for gatewaysClaim!");
|
||||
return eval->Invalid("invalid gatewaysclaim OP_RETURN data!");
|
||||
else if (myGetTransaction(bindtxid,tmptx,hashblock) == 0)
|
||||
return eval->Invalid("invalid gatewaysbind txid!");
|
||||
else if ((numvouts=tmptx.vout.size()) < 1 || DecodeGatewaysBindOpRet(depositaddr,tmptx.vout[numvouts-1].scriptPubKey,tokenid,tmprefcoin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B')
|
||||
return eval->Invalid("invalid gatewaysbind OP_RETURN data!");
|
||||
else if ( IsCCInput(tmptx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for gatewaysbind!");
|
||||
else if ( IsCCInput(tmptx.vin[1].scriptSig) == 0 )
|
||||
return eval->Invalid("vin.1 is CC for gatewaysbind!");
|
||||
else if ( ConstrainVout(tmptx.vout[0],1,gatewaystokensaddr,totalsupply)==0)
|
||||
return eval->Invalid("invalid tokens to gateways vout for gatewaysbind!");
|
||||
else if ( ConstrainVout(tmptx.vout[1],1,cp->unspendableCCaddr,CC_MARKER_VALUE)==0)
|
||||
return eval->Invalid("invalid marker vout for gatewaysbind!");
|
||||
else if (tmprefcoin!=refcoin)
|
||||
return eval->Invalid("refcoin different than in bind tx");
|
||||
else if (tmptokenid!=tokenid)
|
||||
@@ -697,6 +614,12 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
|
||||
return eval->Invalid("invalid gatewaysdeposittxid!");
|
||||
else if ((numvouts=tmptx.vout.size()) < 1 || DecodeGatewaysDepositOpRet(tmptx.vout[numvouts-1].scriptPubKey,tmptxid,tmprefcoin,tmppublishers,txids,height,cointxid,claimvout,hex,proof,tmppubkey,tmpamount) != 'D')
|
||||
return eval->Invalid("invalid gatewaysdeposit OP_RETURN data!");
|
||||
else if ( IsCCInput(tmptx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for gatewaysdeposit!");
|
||||
else if ( GetCCaddress(cp,destaddr,tmppubkey)==0 || ConstrainVout(tmptx.vout[0],1,destaddr,CC_MARKER_VALUE)==0)
|
||||
return eval->Invalid("invalid CC marker vout for gatewaysdeposit!");
|
||||
else if ( CCtxidaddr(destaddr,cointxid)==CPubKey() || ConstrainVout(tmptx.vout[1],0,destaddr,CC_MARKER_VALUE)==0)
|
||||
return eval->Invalid("invalid normal marker vout for gatewaysdeposit!");
|
||||
else if (tmprefcoin!=refcoin)
|
||||
return eval->Invalid("refcoin different than in deposit tx");
|
||||
else if (bindtxid!=tmptxid)
|
||||
@@ -705,6 +628,18 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
|
||||
return eval->Invalid("deposit amount greater then bind total supply");
|
||||
else if (komodo_txnotarizedconfirmed(deposittxid) == false)
|
||||
return eval->Invalid("gatewaysdeposit tx is not yet confirmed(notarised)!");
|
||||
else if (myGetTransaction(tx.vin[2].prevout.hash,tmptx,hashblock) == 0)
|
||||
return eval->Invalid("invalid gatewaysdeposittxid!");
|
||||
else if (IsCCInput(tx.vin[0].scriptSig) != 0)
|
||||
return eval->Invalid("vin.0 is normal for gatewaysclaim!");
|
||||
else if (IsCCInput(tx.vin[1].scriptSig) == 0)
|
||||
return eval->Invalid("vin.1 is CC for gatewaysclaim!");
|
||||
else if ((*cp->ismyvin)(tx.vin[2].scriptSig) == 0 || myGetTransaction(tx.vin[2].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[2].prevout.n].nValue!=CC_MARKER_VALUE)
|
||||
return eval->Invalid("vin.2 is CC marker for gatewaysclaim or invalid marker amount!");
|
||||
else if (_GetCCaddress(destaddr,EVAL_TOKENS,pubkey)==0 || ConstrainVout(tx.vout[0],1,destaddr,amount)==0)
|
||||
return eval->Invalid("invalid vout tokens to destpub for gatewaysclaim!");
|
||||
else if (numvouts>2 && (myGetTransaction(tx.vin[1].prevout.hash,tmptx,hashblock)==0 || ConstrainVout(tx.vout[1],1,gatewaystokensaddr,tmptx.vout[tx.vin[1].prevout.n].nValue-amount)==0))
|
||||
return eval->Invalid("invalid CC change vout for gatewaysclaim!");
|
||||
else if (amount!=tmpamount)
|
||||
return eval->Invalid("claimed amount different then deposit amount");
|
||||
else if (tx.vout[0].nValue!=amount)
|
||||
@@ -717,7 +652,7 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
|
||||
merkleroot = zeroid;
|
||||
for (i=m=0; i<N; i++)
|
||||
{
|
||||
if ( (mhash= GatewaysReverseScan(txid,height,oracletxid,OraclesBatontxid(oracletxid,pubkeys[i]))) != zeroid )
|
||||
if ( (mhash= CCOraclesReverseScan("gatewayscc-2",txid,height,oracletxid,OraclesBatontxid(oracletxid,pubkeys[i]))) != zeroid )
|
||||
{
|
||||
if ( merkleroot == zeroid )
|
||||
merkleroot = mhash, m = 1;
|
||||
@@ -739,7 +674,7 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
|
||||
case 'W':
|
||||
//vin.0: normal input
|
||||
//vin.1: CC input of tokens
|
||||
//vout.0: CC vout txfee marker to gateways CC address
|
||||
//vout.0: CC vout marker to gateways CC address
|
||||
//vout.1: CC vout of gateways tokens back to gateways tokens CC address
|
||||
//vout.2: CC vout change of tokens back to owners pubkey (if any)
|
||||
//vout.n-1: opreturn - 'W' tokenid bindtxid refcoin withdrawpub amount
|
||||
@@ -748,16 +683,10 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
|
||||
case 'P':
|
||||
//vin.0: normal input
|
||||
//vin.1: CC input of marker from previous tx (withdraw or partialsing)
|
||||
//vout.0: CC vout txfee marker to gateways CC address
|
||||
//vout.0: CC vout marker to gateways CC address
|
||||
//vout.n-1: opreturn - 'P' withdrawtxid refcoin number_of_signs mypk hex
|
||||
if ((numvouts=tx.vout.size()) > 0 && DecodeGatewaysPartialOpRet(tx.vout[numvouts-1].scriptPubKey,withdrawtxid,refcoin,K,pubkey,hex)!='P')
|
||||
return eval->Invalid("invalid gatewaysPartialSign OP_RETURN data!");
|
||||
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for gatewaysPartialSign!");
|
||||
else if ( IsCCInput(tx.vin[1].scriptSig) == 0 )
|
||||
return eval->Invalid("vin.1 is CC for gatewaysPartialSign!");
|
||||
else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 )
|
||||
return eval->Invalid("vout.0 is CC for gatewaysPartialSign!");
|
||||
return eval->Invalid("invalid gatewaysPartialSign OP_RETURN data!");
|
||||
else if (myGetTransaction(withdrawtxid,tmptx,hashblock) == 0)
|
||||
return eval->Invalid("invalid withdraw txid!");
|
||||
else if ((numvouts=tmptx.vout.size()) > 0 && DecodeGatewaysWithdrawOpRet(tmptx.vout[numvouts-1].scriptPubKey,tmptokenid,bindtxid,tmprefcoin,pubkey,amount)!='W')
|
||||
@@ -768,10 +697,10 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
|
||||
return eval->Invalid("vin.0 is normal for gatewaysWithdraw!");
|
||||
else if ( IsCCInput(tmptx.vin[1].scriptSig) == 0 )
|
||||
return eval->Invalid("vin.1 is CC for gatewaysWithdraw!");
|
||||
else if ( tmptx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 )
|
||||
return eval->Invalid("vout.0 is CC for gatewaysWithdraw!");
|
||||
else if ( tmptx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 )
|
||||
return eval->Invalid("vout.1 is CC for gatewaysWithdraw!");
|
||||
else if ( ConstrainVout(tmptx.vout[0],1,cp->unspendableCCaddr,CC_MARKER_VALUE)==0)
|
||||
return eval->Invalid("invalid marker vout for gatewaysWithdraw!");
|
||||
else if ( ConstrainVout(tmptx.vout[1],1,gatewaystokensaddr,amount)==0)
|
||||
return eval->Invalid("invalid tokens to gateways vout for gatewaysWithdraw!");
|
||||
else if (tmptx.vout[1].nValue!=amount)
|
||||
return eval->Invalid("amount in opret not matching tx tokens amount!");
|
||||
else if (komodo_txnotarizedconfirmed(withdrawtxid) == false)
|
||||
@@ -785,23 +714,23 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
|
||||
else if (tmptokenid!=tokenid)
|
||||
return eval->Invalid("tokenid does not match tokenid from gatewaysbind");
|
||||
else if (komodo_txnotarizedconfirmed(bindtxid) == false)
|
||||
return eval->Invalid("gatewaysbind tx is not yet confirmed(notarised)!");
|
||||
return eval->Invalid("gatewaysbind tx is not yet confirmed(notarised)!");
|
||||
else if (IsCCInput(tx.vin[0].scriptSig) != 0)
|
||||
return eval->Invalid("vin.0 is normal for gatewayspartialsign!");
|
||||
else if ((*cp->ismyvin)(tx.vin[1].scriptSig) == 0 || myGetTransaction(tx.vin[1].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[1].prevout.n].nValue!=CC_MARKER_VALUE)
|
||||
return eval->Invalid("vin.1 is CC marker for gatewayspartialsign or invalid marker amount!");
|
||||
else if (ConstrainVout(tx.vout[0],1,cp->unspendableCCaddr,CC_MARKER_VALUE) == 0 )
|
||||
return eval->Invalid("vout.0 invalid marker for gatewayspartialsign!");
|
||||
else if (K>M)
|
||||
return eval->Invalid("invalid number of signs!");
|
||||
break;
|
||||
case 'S':
|
||||
//vin.0: normal input
|
||||
//vin.1: CC input of marker from previous tx (withdraw or partialsing)
|
||||
//vout.0: CC vout txfee marker to gateways CC address
|
||||
//vout.0: CC vout marker to gateways CC address
|
||||
//vout.n-1: opreturn - 'S' withdrawtxid refcoin hex
|
||||
if ((numvouts=tx.vout.size()) > 0 && DecodeGatewaysCompleteSigningOpRet(tx.vout[numvouts-1].scriptPubKey,withdrawtxid,refcoin,K,hex)!='S')
|
||||
return eval->Invalid("invalid gatewayscompletesigning OP_RETURN data!");
|
||||
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for gatewayscompletesigning!");
|
||||
else if ( IsCCInput(tx.vin[1].scriptSig) == 0 )
|
||||
return eval->Invalid("vin.1 is CC for gatewayscompletesigning!");
|
||||
else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 )
|
||||
return eval->Invalid("vout.0 is CC for gatewayscompletesigning!");
|
||||
else if (myGetTransaction(withdrawtxid,tmptx,hashblock) == 0)
|
||||
return eval->Invalid("invalid withdraw txid!");
|
||||
else if ((numvouts=tmptx.vout.size()) > 0 && DecodeGatewaysWithdrawOpRet(tmptx.vout[numvouts-1].scriptPubKey,tmptokenid,bindtxid,tmprefcoin,pubkey,amount)!='W')
|
||||
@@ -812,10 +741,10 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
|
||||
return eval->Invalid("vin.0 is normal for gatewaysWithdraw!");
|
||||
else if ( IsCCInput(tmptx.vin[1].scriptSig) == 0 )
|
||||
return eval->Invalid("vin.1 is CC for gatewaysWithdraw!");
|
||||
else if ( tmptx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 )
|
||||
return eval->Invalid("vout.0 is CC for gatewaysWithdraw!");
|
||||
else if ( tmptx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 )
|
||||
return eval->Invalid("vout.1 is CC for gatewaysWithdraw!");
|
||||
else if ( ConstrainVout(tmptx.vout[0],1,cp->unspendableCCaddr,CC_MARKER_VALUE)==0)
|
||||
return eval->Invalid("invalid marker vout for gatewaysWithdraw!");
|
||||
else if ( ConstrainVout(tmptx.vout[1],1,gatewaystokensaddr,amount)==0)
|
||||
return eval->Invalid("invalid tokens to gateways vout for gatewaysWithdraw!");
|
||||
else if (tmptx.vout[1].nValue!=amount)
|
||||
return eval->Invalid("amount in opret not matching tx tokens amount!");
|
||||
else if (komodo_txnotarizedconfirmed(withdrawtxid) == false)
|
||||
@@ -829,21 +758,22 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
|
||||
else if (tmptokenid!=tokenid)
|
||||
return eval->Invalid("tokenid does not match tokenid from gatewaysbind");
|
||||
else if (komodo_txnotarizedconfirmed(bindtxid) == false)
|
||||
return eval->Invalid("gatewaysbind tx is not yet confirmed(notarised)!");
|
||||
return eval->Invalid("gatewaysbind tx is not yet confirmed(notarised)!");
|
||||
else if (IsCCInput(tx.vin[0].scriptSig) != 0)
|
||||
return eval->Invalid("vin.0 is normal for gatewayscompletesigning!");
|
||||
else if ((*cp->ismyvin)(tx.vin[1].scriptSig) == 0 || myGetTransaction(tx.vin[1].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[1].prevout.n].nValue!=CC_MARKER_VALUE)
|
||||
return eval->Invalid("vin.1 is CC marker for gatewayscompletesigning or invalid marker amount!");
|
||||
else if (ConstrainVout(tx.vout[0],1,cp->unspendableCCaddr,CC_MARKER_VALUE) == 0 )
|
||||
return eval->Invalid("vout.0 invalid marker for gatewayscompletesigning!");
|
||||
else if (K<M)
|
||||
return eval->Invalid("invalid number of signs!");
|
||||
break;
|
||||
case 'M':
|
||||
//vin.0: CC input of gatewayscompletesigning tx marker to gateways CC address
|
||||
//vin.0: normal input
|
||||
//vin.1: CC input of gatewayscompletesigning tx marker to gateways CC address
|
||||
//vout.0: opreturn - 'M' withdrawtxid refcoin completetxid
|
||||
if ((numvouts=tx.vout.size()) > 0 && DecodeGatewaysMarkDoneOpRet(tx.vout[numvouts-1].scriptPubKey,withdrawtxid,refcoin,completetxid)!='M')
|
||||
return eval->Invalid("invalid gatewaysmarkdone OP_RETURN data!");
|
||||
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for gatewaysmarkdone!");
|
||||
else if ( IsCCInput(tx.vin[1].scriptSig) == 0 )
|
||||
return eval->Invalid("vin.1 is CC for gatewaysmarkdone!");
|
||||
else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() != 0 )
|
||||
return eval->Invalid("vout.0 is normal for gatewaysmarkdone!");
|
||||
return eval->Invalid("invalid gatewaysmarkdone OP_RETURN data!");
|
||||
else if (myGetTransaction(completetxid,tmptx,hashblock) == 0)
|
||||
return eval->Invalid("invalid gatewayscompletesigning txid!");
|
||||
else if ((numvouts=tmptx.vout.size()) > 0 && DecodeGatewaysCompleteSigningOpRet(tmptx.vout[numvouts-1].scriptPubKey,withdrawtxid,tmprefcoin,K,hex)!='S')
|
||||
@@ -867,7 +797,11 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
|
||||
else if (tmptokenid!=tokenid)
|
||||
return eval->Invalid("tokenid does not match tokenid from gatewaysbind");
|
||||
else if (komodo_txnotarizedconfirmed(bindtxid) == false)
|
||||
return eval->Invalid("gatewaysbind tx is not yet confirmed(notarised)!");
|
||||
return eval->Invalid("gatewaysbind tx is not yet confirmed(notarised)!");
|
||||
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for gatewaysmarkdone!");
|
||||
else if ((*cp->ismyvin)(tx.vin[1].scriptSig) == 0 || myGetTransaction(tx.vin[1].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[1].prevout.n].nValue!=CC_MARKER_VALUE)
|
||||
return eval->Invalid("vin.1 is CC marker for gatewaysmarkdone or invalid marker amount!");
|
||||
else if (K<M)
|
||||
return eval->Invalid("invalid number of signs!");
|
||||
break;
|
||||
@@ -898,7 +832,11 @@ int64_t AddGatewaysInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CP
|
||||
{
|
||||
GetTokensCCaddress(cp,coinaddr,pk);
|
||||
SetCCunspents(unspentOutputs,coinaddr);
|
||||
threshold = total/(maxinputs+1);
|
||||
if ( maxinputs > CC_MAXVINS )
|
||||
maxinputs = CC_MAXVINS;
|
||||
if ( maxinputs > 0 )
|
||||
threshold = total/maxinputs;
|
||||
else threshold = total;
|
||||
LOGSTREAM("gatewayscc",CCLOG_DEBUG1, stream << "check " << coinaddr << " for gateway inputs" << std::endl);
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
{
|
||||
@@ -907,29 +845,17 @@ int64_t AddGatewaysInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CP
|
||||
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
|
||||
{
|
||||
funcid=DecodeGatewaysOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey);
|
||||
if (vout==0 && funcid=='B' && bindtxid==txid && total != 0 && maxinputs != 0)
|
||||
if ((vout==0 && funcid=='B' && bindtxid==txid && total != 0 && maxinputs != 0) ||
|
||||
(vout==1 && funcid=='W' && DecodeGatewaysWithdrawOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,tmptokenid,tmpbindtxid,tmprefcoin,withdrawpub,amount) == 'W' &&
|
||||
tmpbindtxid==bindtxid && tmprefcoin==refcoin && tmptokenid==tokenid && total != 0 && maxinputs != 0) ||
|
||||
(vout==1 && funcid=='C' && DecodeGatewaysClaimOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,tmptokenid,tmpbindtxid,tmprefcoin,deposittxid,destpub,amount) == 'C' &&
|
||||
tmpbindtxid==bindtxid && tmprefcoin==refcoin && tmptokenid==tokenid && total != 0 && maxinputs != 0))
|
||||
{
|
||||
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
|
||||
totalinputs += it->second.satoshis;
|
||||
n++;
|
||||
if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs)) break;
|
||||
}
|
||||
else if (vout==1 && funcid=='W' && DecodeGatewaysWithdrawOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,tmptokenid,tmpbindtxid,tmprefcoin,withdrawpub,amount) == 'W' &&
|
||||
tmpbindtxid==bindtxid && tmprefcoin==refcoin && tmptokenid==tokenid && total != 0 && maxinputs != 0)
|
||||
{
|
||||
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
|
||||
totalinputs += it->second.satoshis;
|
||||
n++;
|
||||
if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs)) break;
|
||||
}
|
||||
else if (vout==1 && funcid=='C' && DecodeGatewaysClaimOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,tmptokenid,tmpbindtxid,tmprefcoin,deposittxid,destpub,amount) == 'C' &&
|
||||
tmpbindtxid==bindtxid && tmprefcoin==refcoin && tmptokenid==tokenid && total != 0 && maxinputs != 0)
|
||||
{
|
||||
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
|
||||
totalinputs += it->second.satoshis;
|
||||
n++;
|
||||
if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs)) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(totalinputs);
|
||||
@@ -1033,12 +959,12 @@ std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
if ( AddNormalinputs(mtx,mypk,2*txfee,3) > 0 )
|
||||
if ( AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,3) > 0 )
|
||||
{
|
||||
if (AddTokenCCInputs(cpTokens, mtx, mypk, tokenid, totalsupply, 64)>0)
|
||||
{
|
||||
mtx.vout.push_back(MakeTokensCC1vout(cp->evalcode,totalsupply,gatewayspk));
|
||||
mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,gatewayspk));
|
||||
mtx.vout.push_back(MakeCC1vout(cp->evalcode,CC_MARKER_VALUE,gatewayspk));
|
||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysBindOpRet('B',tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype)));
|
||||
}
|
||||
}
|
||||
@@ -1083,7 +1009,7 @@ std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::
|
||||
{
|
||||
pubkey33_str(str,(uint8_t *)&pubkeys[i]);
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << "pubkeys[" << i << "] " << str << std::endl);
|
||||
if ( (mhash= GatewaysReverseScan(txid,height,oracletxid,OraclesBatontxid(oracletxid,pubkeys[i]))) != zeroid )
|
||||
if ( (mhash= CCOraclesReverseScan("gatewayscc-2",txid,height,oracletxid,OraclesBatontxid(oracletxid,pubkeys[i]))) != zeroid )
|
||||
{
|
||||
if ( merkleroot == zeroid )
|
||||
merkleroot = mhash, m = 1;
|
||||
@@ -1100,7 +1026,7 @@ std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
if ( GatewaysCointxidExists(cp,cointxid) != 0 )
|
||||
if ( CCCointxidExists("gatewayscc-1",cointxid) != 0 )
|
||||
{
|
||||
CCerror = strprintf("cointxid.%s already exists",uint256_str(str,cointxid));
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
@@ -1112,10 +1038,10 @@ std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
}
|
||||
if ( AddNormalinputs(mtx,mypk,3*txfee,4) > 0 )
|
||||
if ( AddNormalinputs(mtx,mypk,txfee+2*CC_MARKER_VALUE,4) > 0 )
|
||||
{
|
||||
mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,destpub));
|
||||
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(CCtxidaddr(txidaddr,cointxid))) << OP_CHECKSIG));
|
||||
mtx.vout.push_back(MakeCC1vout(cp->evalcode,CC_MARKER_VALUE,destpub));
|
||||
mtx.vout.push_back(CTxOut(CC_MARKER_VALUE,CScript() << ParseHex(HexStr(CCtxidaddr(txidaddr,cointxid))) << OP_CHECKSIG));
|
||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysDepositOpRet('D',bindtxid,coin,publishers,txids,height,cointxid,claimvout,deposithex,proof,destpub,amount)));
|
||||
}
|
||||
CCerror = strprintf("cant find enough inputs");
|
||||
@@ -1262,12 +1188,12 @@ std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin
|
||||
}
|
||||
}
|
||||
}
|
||||
if( AddNormalinputs(mtx, mypk, 3*txfee, 4) > 0 )
|
||||
if( AddNormalinputs(mtx, mypk, txfee+CC_MARKER_VALUE, 4) > 0 )
|
||||
{
|
||||
if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, tokenid, amount, 60)) > 0)
|
||||
{
|
||||
if ( inputs > amount ) CCchange = (inputs - amount);
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,txfee,gatewayspk));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CC_MARKER_VALUE,gatewayspk));
|
||||
mtx.vout.push_back(MakeTokensCC1vout(EVAL_GATEWAYS,amount,gatewayspk));
|
||||
if ( CCchange != 0 ) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, CCchange, mypk));
|
||||
return(FinalizeCCTx(0, cpTokens, mtx, mypk, txfee,EncodeGatewaysWithdrawOpRet('W',tokenid,bindtxid,refcoin,withdrawpub,amount)));
|
||||
@@ -1377,7 +1303,7 @@ std::string GatewaysPartialSign(uint64_t txfee,uint256 lasttxid,std::string refc
|
||||
if (AddNormalinputs(mtx,mypk,txfee,3)!=0)
|
||||
{
|
||||
mtx.vin.push_back(CTxIn(tx.GetHash(),0,CScript()));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,txfee,gatewayspk));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CC_MARKER_VALUE,gatewayspk));
|
||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysPartialOpRet('P',withdrawtxid,refcoin,K+1,mypk,hex)));
|
||||
}
|
||||
CCerror = strprintf("error adding funds for partialsign");
|
||||
@@ -1476,7 +1402,7 @@ std::string GatewaysCompleteSigning(uint64_t txfee,uint256 lasttxid,std::string
|
||||
if (AddNormalinputs(mtx,mypk,txfee,3)!=0)
|
||||
{
|
||||
mtx.vin.push_back(CTxIn(lasttxid,0,CScript()));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,txfee,gatewayspk));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CC_MARKER_VALUE,gatewayspk));
|
||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysCompleteSigningOpRet('S',withdrawtxid,refcoin,K+1,hex)));
|
||||
}
|
||||
CCerror = strprintf("error adding funds for completesigning");
|
||||
@@ -1541,7 +1467,7 @@ std::string GatewaysMarkDone(uint64_t txfee,uint256 completetxid,std::string ref
|
||||
if (AddNormalinputs(mtx,mypk,txfee,3)!=0)
|
||||
{
|
||||
mtx.vin.push_back(CTxIn(completetxid,0,CScript()));
|
||||
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
|
||||
mtx.vout.push_back(CTxOut(CC_MARKER_VALUE,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
|
||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysMarkDoneOpRet('M',withdrawtxid,refcoin,completetxid)));
|
||||
}
|
||||
CCerror = strprintf("error adding funds for markdone");
|
||||
@@ -1563,16 +1489,16 @@ UniValue GatewaysPendingDeposits(uint256 bindtxid,std::string refcoin)
|
||||
gatewayspk = GetUnspendable(cp,0);
|
||||
_GetCCaddress(coinaddr,EVAL_GATEWAYS,mypk);
|
||||
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
|
||||
{
|
||||
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error",strprintf("cant find bindtxid %s",uint256_str(str,bindtxid))));
|
||||
return(result);
|
||||
}
|
||||
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B' || refcoin != coin)
|
||||
{
|
||||
CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error",strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str())));
|
||||
return(result);
|
||||
}
|
||||
SetCCunspents(unspentOutputs,coinaddr);
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
@@ -1619,15 +1545,15 @@ UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin)
|
||||
GetTokensCCaddress(cp,tokensaddr,gatewayspk);
|
||||
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
|
||||
{
|
||||
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error",strprintf("cant find bindtxid %s",uint256_str(str,bindtxid))));
|
||||
return(result);
|
||||
}
|
||||
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B' || refcoin != coin )
|
||||
{
|
||||
CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error",strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str())));
|
||||
return(result);
|
||||
}
|
||||
n = msigpubkeys.size();
|
||||
queueflag = 0;
|
||||
@@ -1706,16 +1632,16 @@ UniValue GatewaysProcessedWithdraws(uint256 bindtxid,std::string refcoin)
|
||||
gatewayspk = GetUnspendable(cp,0);
|
||||
_GetCCaddress(coinaddr,EVAL_GATEWAYS,gatewayspk);
|
||||
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
|
||||
{
|
||||
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error",strprintf("cant find bindtxid %s",uint256_str(str,bindtxid))));
|
||||
return(result);
|
||||
}
|
||||
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B' || refcoin != coin)
|
||||
{
|
||||
CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error",strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str())));
|
||||
return(result);
|
||||
}
|
||||
n = msigpubkeys.size();
|
||||
queueflag = 0;
|
||||
@@ -1784,16 +1710,16 @@ UniValue GatewaysExternalAddress(uint256 bindtxid,CPubKey pubkey)
|
||||
|
||||
cp = CCinit(&C,EVAL_GATEWAYS);
|
||||
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
|
||||
{
|
||||
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error",strprintf("cant find bindtxid %s",uint256_str(str,bindtxid))));
|
||||
return(result);
|
||||
}
|
||||
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B')
|
||||
{
|
||||
CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error",strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str())));
|
||||
return(result);
|
||||
}
|
||||
GetCustomscriptaddress(addr,CScript() << ParseHex(HexStr(pubkey)) << OP_CHECKSIG,taddr,prefix,prefix2);
|
||||
result.push_back(Pair("result","success"));
|
||||
@@ -1808,16 +1734,16 @@ UniValue GatewaysDumpPrivKey(uint256 bindtxid,CKey key)
|
||||
|
||||
cp = CCinit(&C,EVAL_GATEWAYS);
|
||||
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
|
||||
{
|
||||
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error",strprintf("cant find bindtxid %s",uint256_str(str,bindtxid))));
|
||||
return(result);
|
||||
}
|
||||
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B')
|
||||
{
|
||||
CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error",strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str())));
|
||||
return(result);
|
||||
}
|
||||
|
||||
priv=EncodeCustomSecret(key,wiftype);
|
||||
@@ -1837,16 +1763,16 @@ UniValue GatewaysInfo(uint256 bindtxid)
|
||||
Gatewayspk = GetUnspendable(cp,0);
|
||||
GetTokensCCaddress(cp,gatewaystokens,Gatewayspk);
|
||||
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
|
||||
{
|
||||
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error",strprintf("cant find bindtxid %s",uint256_str(str,bindtxid))));
|
||||
return(result);
|
||||
}
|
||||
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B')
|
||||
{
|
||||
CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
|
||||
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return("");
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error",strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str())));
|
||||
return(result);
|
||||
}
|
||||
if ( GetTransaction(bindtxid,tx,hashBlock,false) != 0 )
|
||||
{
|
||||
@@ -1855,19 +1781,17 @@ UniValue GatewaysInfo(uint256 bindtxid)
|
||||
depositaddr[0] = 0;
|
||||
if ( tx.vout.size() > 0 && DecodeGatewaysBindOpRet(depositaddr,tx.vout[tx.vout.size()-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 0 && M <= N && N > 0 )
|
||||
{
|
||||
if ( N > 1 )
|
||||
{
|
||||
result.push_back(Pair("M",M));
|
||||
result.push_back(Pair("N",N));
|
||||
for (i=0; i<N; i++)
|
||||
a.push_back(pubkey33_str(str,(uint8_t *)&pubkeys[i]));
|
||||
result.push_back(Pair("pubkeys",a));
|
||||
} else result.push_back(Pair("pubkey",pubkey33_str(str,(uint8_t *)&pubkeys[0])));
|
||||
result.push_back(Pair("M",M));
|
||||
result.push_back(Pair("N",N));
|
||||
for (i=0; i<N; i++)
|
||||
a.push_back(pubkey33_str(str,(uint8_t *)&pubkeys[i]));
|
||||
result.push_back(Pair("pubkeys",a));
|
||||
result.push_back(Pair("coin",coin));
|
||||
result.push_back(Pair("oracletxid",uint256_str(str,oracletxid)));
|
||||
result.push_back(Pair("taddr",taddr));
|
||||
result.push_back(Pair("prefix",prefix));
|
||||
result.push_back(Pair("prefix2",prefix2));
|
||||
result.push_back(Pair("wiftype",wiftype));
|
||||
result.push_back(Pair("deposit",depositaddr));
|
||||
result.push_back(Pair("tokenid",uint256_str(str,tokenid)));
|
||||
sprintf(numstr,"%.8f",(double)totalsupply/COIN);
|
||||
|
||||
@@ -19,19 +19,10 @@
|
||||
#include "crosschain.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "cc/CCinclude.h"
|
||||
#include <openssl/sha.h>
|
||||
|
||||
//#define LEV_INFO 0
|
||||
//#define LEV_DEBUG1 1
|
||||
//#define LOGSTREAM(category, level, logoperator) { std::ostringstream stream; logoperator; for(int i = 0; i < level; i ++) if( LogAcceptCategory( (std::string(category) + (level > 0 ? std::string("-")+std::to_string(level) : std::string("") )).c_str() ) ) LogPrintStr(stream.str()); }
|
||||
|
||||
/*
|
||||
* CC Eval method for import coin.
|
||||
*
|
||||
* This method should control every parameter of the ImportCoin transaction, since it has no signature
|
||||
* to protect it from malleability.
|
||||
|
||||
##### 0xffffffff is a special CCid for single chain/dual daemon imports
|
||||
*/
|
||||
#include "key_io.h"
|
||||
#define CODA_BURN_ADDRESS "KPrrRoPfHOnNpZZQ6laHXdQDkSQDkVHaN0V+LizLlHxz7NaA59sBAAAA"
|
||||
|
||||
extern std::string ASSETCHAINS_SELFIMPORT;
|
||||
extern uint16_t ASSETCHAINS_CODAPORT,ASSETCHAINS_BEAMPORT;
|
||||
@@ -41,10 +32,21 @@ extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33];
|
||||
uint256 BitcoinGetProofMerkleRoot(const std::vector<uint8_t> &proofData, std::vector<uint256> &txids);
|
||||
uint256 GatewaysReverseScan(uint256 &txid, int32_t height, uint256 reforacletxid, uint256 batontxid);
|
||||
int32_t GatewaysCointxidExists(struct CCcontract_info *cp, uint256 cointxid);
|
||||
uint8_t DecodeGatewaysBindOpRet(char *depositaddr, const CScript &scriptPubKey, std::string &coin, uint256 &tokenid, int64_t &totalsupply, uint256 &oracletxid, uint8_t &M, uint8_t &N, std::vector<CPubKey> &pubkeys, uint8_t &taddr, uint8_t &prefix, uint8_t &prefix2);
|
||||
uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,uint256 &tokenid,std::string &coin,int64_t &totalsupply,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector<CPubKey> &gatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype);
|
||||
char *nonportable_path(char *str);
|
||||
char *portable_path(char *str);
|
||||
void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep);
|
||||
void *filestr(long *allocsizep,char *_fname);
|
||||
|
||||
// ac_import=chain support:
|
||||
// encode opret for gateways import
|
||||
CScript EncodeImportTxOpRet(uint32_t targetCCid, std::string coin, std::vector<CPubKey> publishers, std::vector<uint256>txids, int32_t height, uint256 cointxid, int32_t claimvout, std::string rawburntx, std::vector<uint8_t>proof, CPubKey destpub, int64_t amount)
|
||||
{
|
||||
CScript opret;
|
||||
opret << OP_RETURN << E_MARSHAL(ss << targetCCid << coin << publishers << txids << height << cointxid << claimvout << rawburntx << proof << destpub << amount);
|
||||
return(opret);
|
||||
}
|
||||
|
||||
CScript EncodeGatewaysImportTxOpRet(uint32_t targetCCid, std::string coin, uint256 bindtxid, std::vector<CPubKey> publishers, std::vector<uint256>txids, int32_t height, uint256 cointxid, int32_t claimvout, std::string rawburntx, std::vector<uint8_t>proof, CPubKey destpub, int64_t amount)
|
||||
{
|
||||
CScript opret;
|
||||
@@ -52,169 +54,132 @@ CScript EncodeGatewaysImportTxOpRet(uint32_t targetCCid, std::string coin, uint2
|
||||
return(opret);
|
||||
}
|
||||
|
||||
bool ImportCoinGatewaysVerify(char *refdepositaddr, uint256 oracletxid, int32_t claimvout, std::string refcoin, uint256 burntxid, const std::string rawburntx, std::vector<uint8_t>proof, uint256 merkleroot)
|
||||
CScript EncodeCodaImportTxOpRet(uint32_t targetCCid, std::string coin, std::string burntx, uint256 bindtxid, CPubKey destpub, int64_t amount)
|
||||
{
|
||||
CScript opret;
|
||||
opret << OP_RETURN << E_MARSHAL(ss << targetCCid << burntx << bindtxid << destpub << amount);
|
||||
return(opret);
|
||||
}
|
||||
|
||||
cJSON* CodaRPC(char **retstr,char const *arg0,char const *arg1,char const *arg2,char const *arg3,char const *arg4,char const *arg5)
|
||||
{
|
||||
char cmdstr[5000],fname[256],*jsonstr;
|
||||
long fsize;
|
||||
cJSON *retjson=NULL;
|
||||
|
||||
sprintf(fname,"/tmp/coda.%s",arg0);
|
||||
sprintf(cmdstr,"coda.exe client %s %s %s %s %s %s > %s 2>&1",arg0,arg1,arg2,arg3,arg4,arg5,fname);
|
||||
*retstr = 0;
|
||||
if (system(cmdstr)<0) return (retjson);
|
||||
if ( (jsonstr=(char *)filestr(&fsize,fname)) != 0 )
|
||||
{
|
||||
jsonstr[strlen(jsonstr)-1]='\0';
|
||||
if ( (strncmp(jsonstr,"Merkle List of transactions:",28)!=0) || (retjson= cJSON_Parse(jsonstr+29)) == 0)
|
||||
*retstr=jsonstr;
|
||||
else free(jsonstr);
|
||||
}
|
||||
return(retjson);
|
||||
}
|
||||
|
||||
bool ImportCoinGatewaysVerify(CTransaction oracletx, int32_t claimvout, std::string refcoin, uint256 burntxid, const std::string rawburntx, std::vector<uint8_t>proof, uint256 merkleroot)
|
||||
{
|
||||
std::vector<uint256> txids;
|
||||
uint256 proofroot, hashBlock, foundtxid = zeroid;
|
||||
CTransaction oracletx, burntx;
|
||||
uint256 proofroot;
|
||||
std::string name, description, format;
|
||||
char destaddr[64], destpubaddr[64], claimaddr[64];
|
||||
int32_t i, numvouts;
|
||||
int64_t nValue = 0;
|
||||
|
||||
if (myGetTransaction(oracletxid, oracletx, hashBlock) == 0 || (numvouts = oracletx.vout.size()) <= 0)
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "ImportCoinGatewaysVerify can't find oracletxid=" << oracletxid.GetHex() << std::endl);
|
||||
return false;
|
||||
}
|
||||
if (DecodeOraclesCreateOpRet(oracletx.vout[numvouts - 1].scriptPubKey, name, description, format) != 'C' || name != refcoin)
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "ImportCoinGatewaysVerify mismatched oracle name=" << name.c_str() << " != " << refcoin.c_str() << std::endl);
|
||||
return false;
|
||||
}
|
||||
proofroot = BitcoinGetProofMerkleRoot(proof, txids);
|
||||
if (proofroot != merkleroot)
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "ImportCoinGatewaysVerify mismatched proof merkleroot=" << proofroot.GetHex() << " and oracles merkleroot=" << merkleroot.GetHex() << std::endl);
|
||||
return false;
|
||||
}
|
||||
|
||||
// check the burntxid is in the proof:
|
||||
if (std::find(txids.begin(), txids.end(), burntxid) == txids.end()) {
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "ImportCoinGatewaysVerify invalid proof for this burntxid=" << burntxid.GetHex() << std::endl);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
if (DecodeHexTx(burntx, rawburntx) != 0)
|
||||
{
|
||||
Getscriptaddress(claimaddr, burntx.vout[claimvout].scriptPubKey);
|
||||
Getscriptaddress(destpubaddr, CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG);
|
||||
if (strcmp(claimaddr, destpubaddr) == 0)
|
||||
{
|
||||
for (i = 0; i<numvouts; i++)
|
||||
{
|
||||
Getscriptaddress(destaddr, burntx.vout[i].scriptPubKey);
|
||||
if (strcmp(refdepositaddr, destaddr) == 0)
|
||||
{
|
||||
foundtxid = burntx.GetHash();
|
||||
nValue = burntx.vout[i].nValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else fprintf(stderr, "claimaddr.(%s) != destpubaddr.(%s)\n", claimaddr, destpubaddr);
|
||||
}*/
|
||||
|
||||
/*
|
||||
if (foundtxid == burntxid) {
|
||||
LOGSTREAM("importcoin", LEV_DEBUG1, stream << "verified proof for burntxid=" << burntxid.GetHex() << " in merkleroot merkleroot" << std::endl);
|
||||
return(nValue);
|
||||
}
|
||||
else {
|
||||
LOGSTREAM("importcoin", LEV_INFO, stream << "verified proof for burntxid=" << burntxid.GetHex() << " in merkleroot merkleroot" << std::endl);
|
||||
|
||||
fprintf(stderr, "(%s) != (%s) or txid %s mismatch.%d or script mismatch\n", refdepositaddr, destaddr, uint256_str(str, foundtxid), foundtxid != burntxid);
|
||||
*/
|
||||
|
||||
|
||||
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "verified proof for burntxid=" << burntxid.GetHex() << " in trusted merkleroot" << std::endl);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// make import tx with burntx and its proof of existence
|
||||
std::string MakeGatewaysImportTx(uint64_t txfee, uint256 bindtxid, int32_t height, std::string refcoin, std::vector<uint8_t>proof, std::string rawburntx, int32_t ivout, uint256 burntxid)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
CTransaction burntx, bindtx;
|
||||
CPubKey mypk, gatewayspk;
|
||||
uint256 oracletxid, merkleroot, mhash, hashBlock, tokenid, txid;
|
||||
int64_t totalsupply;
|
||||
int32_t i, m, n, numvouts;
|
||||
uint8_t M, N, taddr, prefix, prefix2;
|
||||
std::string coin;
|
||||
struct CCcontract_info *cp, C;
|
||||
std::vector<CPubKey> pubkeys, publishers;
|
||||
std::vector<uint256>txids;
|
||||
char depositaddr[64], txidaddr[64];
|
||||
// std::string MakeGatewaysImportTx(uint64_t txfee, uint256 oracletxid, int32_t height, std::string refcoin, std::vector<uint8_t> proof, std::string rawburntx, int32_t ivout, uint256 burntxid,std::string destaddr)
|
||||
// {
|
||||
// CMutableTransaction burntx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
// CTransaction oracletx,regtx; CPubKey regpk;
|
||||
// uint256 proofroot,txid,tmporacletxid,merkleroot,mhash,hashBlock; int32_t i,m,n=0,numvouts;
|
||||
// std::string name,desc,format; std::vector<CTxOut> vouts;
|
||||
// std::vector<CPubKey> pubkeys; std::vector<uint256>txids;
|
||||
// char markeraddr[64]; int64_t datafee;
|
||||
// std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
|
||||
cp = CCinit(&C, EVAL_GATEWAYS);
|
||||
/*if (txfee == 0)
|
||||
txfee = 10000;
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
gatewayspk = GetUnspendable(cp, 0); */
|
||||
|
||||
if (!E_UNMARSHAL(ParseHex(rawburntx), ss >> burntx))
|
||||
return std::string("");
|
||||
|
||||
CAmount amount = GetCoinImportValue(burntx); // equal to int64_t
|
||||
|
||||
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeGatewaysImportTx height=" << height << " coin=" << refcoin << " amount=" << (double)amount / COIN << " pubkeys num=" << pubkeys.size() << std::endl);
|
||||
|
||||
if (GetTransaction(bindtxid, bindtx, hashBlock, false) == 0 || (numvouts = bindtx.vout.size()) <= 0)
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx cant find bindtxid=" << bindtxid.GetHex() << std::endl);
|
||||
return("");
|
||||
}
|
||||
/* if (DecodeGatewaysBindOpRet(depositaddr, bindtx.vout[numvouts - 1].scriptPubKey, coin, tokenid, totalsupply, oracletxid, M, N, pubkeys, taddr, prefix, prefix2) != 'B' || refcoin != coin)
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx invalid coin - bindtxid=" << bindtxid.GetHex() << " coin=" << coin.c_str() << std::endl);
|
||||
return("");
|
||||
} eliminate link err */
|
||||
n = (int32_t)pubkeys.size();
|
||||
merkleroot = zeroid;
|
||||
for (i = m = 0; i < n; i++)
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx using pubkeys[" << i << "]=" << HexStr(pubkeys[i]) << std::endl);
|
||||
if ((mhash = GatewaysReverseScan(txid, height, oracletxid, OraclesBatontxid(oracletxid, pubkeys[i]))) != zeroid)
|
||||
{
|
||||
if (merkleroot == zeroid)
|
||||
merkleroot = mhash, m = 1;
|
||||
else if (mhash == merkleroot)
|
||||
m ++;
|
||||
publishers.push_back(pubkeys[i]);
|
||||
txids.push_back(txid);
|
||||
}
|
||||
}
|
||||
|
||||
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeGatewaysImportTx burntxid=" << burntxid.GetHex() << " nodes m=" << m << " of n=" << n << std::endl);
|
||||
if (merkleroot == zeroid || m < n / 2) // none or less than half oracle nodes sent merkleroot
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx couldnt find merkleroot for block height=" << height << "coin=" << coin.c_str() << " oracleid=" << oracletxid.GetHex() << " m=" << m << " vs n=" << n << std::endl );
|
||||
return("");
|
||||
}
|
||||
if (GatewaysCointxidExists(cp, burntxid) != 0)
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx burntxid=" << burntxid.GetHex() << " already exists" << std::endl);
|
||||
return("");
|
||||
}
|
||||
if (!ImportCoinGatewaysVerify(depositaddr, oracletxid, ivout, coin, burntxid, rawburntx, proof, merkleroot))
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx could not validate burntx, txid=" << burntxid.GetHex() << std::endl);
|
||||
return("");
|
||||
}
|
||||
|
||||
|
||||
std::vector<uint256> leaftxids;
|
||||
BitcoinGetProofMerkleRoot(proof, leaftxids);
|
||||
MerkleBranch newBranch(0, leaftxids);
|
||||
TxProof txProof = std::make_pair(burntxid, newBranch);
|
||||
|
||||
std::vector<CTxOut> vouts;
|
||||
|
||||
|
||||
|
||||
return HexStr(E_MARSHAL(ss << MakeImportCoinTransaction(txProof, burntx, vouts)));
|
||||
|
||||
/*if (AddNormalinputs(mtx, mypk, 3 * txfee, 4) > 0)
|
||||
{
|
||||
mtx.vout.push_back(MakeCC1vout(cp->evalcode, txfee, destpub));
|
||||
mtx.vout.push_back(CTxOut(txfee, CScript() << ParseHex(HexStr(CCtxidaddr(txidaddr, burntxid))) << OP_CHECKSIG));
|
||||
return(FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeGatewaysImportTxOpRet(0xFFFFFFFF, coin, bindtxid, publishers, txids, height, burntxid, ivout, rawburntx, proof, destpub, amount)));
|
||||
}
|
||||
LOGSTREAM("importcoin", LEV_INFO, stream << "MakeGatewaysImportTx coud not find normal imputs" << std::endl);*/
|
||||
return("");
|
||||
}
|
||||
// if (!E_UNMARSHAL(ParseHex(rawburntx), ss >> burntx))
|
||||
// return std::string("");
|
||||
// CAmount amount = GetCoinImportValue(burntx); // equal to int64_t
|
||||
// LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeGatewaysImportTx height=" << height << " coin=" << refcoin << " amount=" << (double)amount / COIN << " pubkeys num=" << pubkeys.size() << std::endl);
|
||||
// if (GetTransaction(oracletxid, oracletx, hashBlock, false) == 0 || (numvouts = oracletx.vout.size()) <= 0)
|
||||
// {
|
||||
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx cant find oracletxid=" << oracletxid.GetHex() << std::endl);
|
||||
// return("");
|
||||
// }
|
||||
// if (DecodeOraclesCreateOpRet(oracletx.vout[numvouts - 1].scriptPubKey,name,desc,format) != 'C')
|
||||
// {
|
||||
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx invalid oracle tx. oracletxid=" << oracletxid.GetHex() << std::endl);
|
||||
// return("");
|
||||
// }
|
||||
// if (name!=refcoin || format!="Ihh")
|
||||
// {
|
||||
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx invalid oracle name or format tx. oracletxid=" << oracletxid.GetHex() << " name=" << name << " format=" << format << std::endl);
|
||||
// return("");
|
||||
// }
|
||||
// CCtxidaddr(markeraddr,oracletxid);
|
||||
// SetCCunspents(unspentOutputs,markeraddr);
|
||||
// for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
// {
|
||||
// txid = it->first.txhash;
|
||||
// if ( GetTransaction(txid,regtx,hashBlock,false) != 0 && regtx.vout.size() > 0
|
||||
// && DecodeOraclesOpRet(regtx.vout[regtx.vout.size()-1].scriptPubKey,tmporacletxid,regpk,datafee) == 'R' && oracletxid == tmporacletxid )
|
||||
// {
|
||||
// pubkeys.push_back(regpk);
|
||||
// n++;
|
||||
// }
|
||||
// }
|
||||
// merkleroot = zeroid;
|
||||
// for (i = m = 0; i < n; i++)
|
||||
// {
|
||||
// LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeGatewaysImportTx using pubkeys[" << i << "]=" << HexStr(pubkeys[i]) << std::endl);
|
||||
// if ((mhash = CCOraclesReverseScan("importcoind-1",txid, height, oracletxid, OraclesBatontxid(oracletxid, pubkeys[i]))) != zeroid)
|
||||
// {
|
||||
// if (merkleroot == zeroid)
|
||||
// merkleroot = mhash, m = 1;
|
||||
// else if (mhash == merkleroot)
|
||||
// m ++;
|
||||
// txids.push_back(txid);
|
||||
// }
|
||||
// }
|
||||
// LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeGatewaysImportTx burntxid=" << burntxid.GetHex() << " nodes m=" << m << " of n=" << n << std::endl);
|
||||
// if (merkleroot == zeroid || m < n / 2) // none or less than half oracle nodes sent merkleroot
|
||||
// {
|
||||
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx couldnt find merkleroot for block height=" << height << "coin=" << refcoin.c_str() << " oracleid=" << oracletxid.GetHex() << " m=" << m << " vs n=" << n << std::endl );
|
||||
// return("");
|
||||
// }
|
||||
// proofroot = BitcoinGetProofMerkleRoot(proof, txids);
|
||||
// if (proofroot != merkleroot)
|
||||
// {
|
||||
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx mismatched proof merkleroot=" << proofroot.GetHex() << " and oracles merkleroot=" << merkleroot.GetHex() << std::endl);
|
||||
// return("");
|
||||
// }
|
||||
// // check the burntxid is in the proof:
|
||||
// if (std::find(txids.begin(), txids.end(), burntxid) == txids.end()) {
|
||||
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx invalid proof for this burntxid=" << burntxid.GetHex() << std::endl);
|
||||
// return("");
|
||||
// }
|
||||
// burntx.vout.push_back(MakeBurnOutput(amount,0xffffffff,refcoin,vouts,proof,oracletxid,height));
|
||||
// std::vector<uint256> leaftxids;
|
||||
// BitcoinGetProofMerkleRoot(proof, leaftxids);
|
||||
// MerkleBranch newBranch(0, leaftxids);
|
||||
// TxProof txProof = std::make_pair(burntxid, newBranch);
|
||||
// CTxDestination dest = DecodeDestination(destaddr.c_str());
|
||||
// CScript scriptPubKey = GetScriptForDestination(dest);
|
||||
// vouts.push_back(CTxOut(amount,scriptPubKey));
|
||||
// return HexStr(E_MARSHAL(ss << MakeImportCoinTransaction(txProof, burntx, vouts)));
|
||||
// }
|
||||
|
||||
// makes source tx for self import tx
|
||||
std::string MakeSelfImportSourceTx(CTxDestination &dest, int64_t amount, CMutableTransaction &mtx)
|
||||
@@ -332,6 +297,90 @@ int32_t GetSelfimportProof(std::string source, CMutableTransaction &mtx, CScript
|
||||
return 0;
|
||||
}
|
||||
|
||||
// make import tx with burntx and dual daemon
|
||||
std::string MakeCodaImportTx(uint64_t txfee, std::string receipt, std::string srcaddr, std::vector<CTxOut> vouts)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()),burntx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
CPubKey mypk; uint256 codaburntxid; std::vector<unsigned char> dummyproof;
|
||||
int32_t i,numvouts,n,m; std::string coin,error; struct CCcontract_info *cp, C;
|
||||
cJSON *result,*tmp,*tmp1; unsigned char hash[SHA256_DIGEST_LENGTH+1];
|
||||
char out[SHA256_DIGEST_LENGTH*2+1],*retstr,*destaddr,*receiver; TxProof txProof; uint64_t amount;
|
||||
|
||||
cp = CCinit(&C, EVAL_GATEWAYS);
|
||||
if (txfee == 0)
|
||||
txfee = 10000;
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
SHA256_CTX sha256;
|
||||
SHA256_Init(&sha256);
|
||||
SHA256_Update(&sha256, receipt.c_str(), receipt.size());
|
||||
SHA256_Final(hash, &sha256);
|
||||
for(i = 0; i < SHA256_DIGEST_LENGTH; i++)
|
||||
{
|
||||
sprintf(out + (i * 2), "%02x", hash[i]);
|
||||
}
|
||||
out[65]='\0';
|
||||
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeCodaImportTx: hash=" << out << std::endl);
|
||||
codaburntxid.SetHex(out);
|
||||
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeCodaImportTx: receipt=" << receipt << " codaburntxid=" << codaburntxid.GetHex().data() << " amount=" << (double)amount / COIN << std::endl);
|
||||
result=CodaRPC(&retstr,"prove-payment","-address",srcaddr.c_str(),"-receipt-chain-hash",receipt.c_str(),"");
|
||||
if (result==0)
|
||||
{
|
||||
if (retstr!=0)
|
||||
{
|
||||
CCerror=std::string("CodaRPC: ")+retstr;
|
||||
free(retstr);
|
||||
}
|
||||
return("");
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((tmp=jobj(jitem(jarray(&n,result,(char *)"payments"),0),(char *)"payload"))!=0 && (destaddr=jstr(jobj(tmp,(char *)"common"),(char *)"memo"))!=0 &&
|
||||
(receiver=jstr(jitem(jarray(&m,tmp,(char *)"body"),1),(char *)"receiver"))!=0 && (amount=j64bits(jitem(jarray(&m,tmp,(char *)"body"),1),(char *)"amount"))!=0)
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeCodaImportTx: receiver=" << receiver << " destaddr=" << destaddr << " amount=" << amount << std::endl);
|
||||
if (strcmp(receiver,CODA_BURN_ADDRESS)!=0)
|
||||
{
|
||||
CCerror="MakeCodaImportTx: invalid burn address, coins do not go to predefined burn address - ";
|
||||
CCerror+=CODA_BURN_ADDRESS;
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << CCerror << std::endl);
|
||||
free(result);
|
||||
return("");
|
||||
}
|
||||
CTxDestination dest = DecodeDestination(destaddr);
|
||||
CScript scriptPubKey = GetScriptForDestination(dest);
|
||||
if (vouts[0]!=CTxOut(amount*COIN,scriptPubKey))
|
||||
{
|
||||
CCerror="MakeCodaImportTx: invalid destination address, burnTx memo!=importTx destination";
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << CCerror << std::endl);
|
||||
free(result);
|
||||
return("");
|
||||
}
|
||||
if (amount*COIN!=vouts[0].nValue)
|
||||
{
|
||||
CCerror="MakeCodaImportTx: invalid amount, burnTx amount!=importTx amount";
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << CCerror << std::endl);
|
||||
free(result);
|
||||
return("");
|
||||
}
|
||||
burntx.vin.push_back(CTxIn(codaburntxid,0,CScript()));
|
||||
burntx.vout.push_back(MakeBurnOutput(amount*COIN,0xffffffff,"CODA",vouts,dummyproof,srcaddr,receipt));
|
||||
return HexStr(E_MARSHAL(ss << MakeImportCoinTransaction(txProof,burntx,vouts)));
|
||||
}
|
||||
else
|
||||
{
|
||||
CCerror="MakeCodaImportTx: invalid Coda burn tx";
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << CCerror << std::endl);
|
||||
free(result);
|
||||
return("");
|
||||
}
|
||||
|
||||
}
|
||||
CCerror="MakeCodaImportTx: error fetching Coda tx";
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << CCerror << std::endl);
|
||||
free(result);
|
||||
return("");
|
||||
}
|
||||
|
||||
// use proof from the above functions to validate the import
|
||||
|
||||
int32_t CheckBEAMimport(TxProof proof,std::vector<uint8_t> rawproof,CTransaction burnTx,std::vector<CTxOut> payouts)
|
||||
@@ -340,17 +389,135 @@ int32_t CheckBEAMimport(TxProof proof,std::vector<uint8_t> rawproof,CTransaction
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int32_t CheckCODAimport(TxProof proof,std::vector<uint8_t> rawproof,CTransaction burnTx,std::vector<CTxOut> payouts)
|
||||
int32_t CheckCODAimport(CTransaction importTx,CTransaction burnTx,std::vector<CTxOut> payouts,std::string srcaddr,std::string receipt)
|
||||
{
|
||||
cJSON *result,*tmp,*tmp1; char *retstr,out[SHA256_DIGEST_LENGTH*2+1]; unsigned char hash[SHA256_DIGEST_LENGTH+1]; int i,n,m;
|
||||
SHA256_CTX sha256; uint256 codaburntxid; char *destaddr,*receiver; uint64_t amount;
|
||||
|
||||
// check with dual-CODA daemon via ASSETCHAINS_CODAPORT for validity of burnTx
|
||||
return(-1);
|
||||
SHA256_Init(&sha256);
|
||||
SHA256_Update(&sha256, receipt.c_str(), receipt.size());
|
||||
SHA256_Final(hash, &sha256);
|
||||
for(i = 0; i < SHA256_DIGEST_LENGTH; i++)
|
||||
{
|
||||
sprintf(out + (i * 2), "%02x", hash[i]);
|
||||
}
|
||||
out[65]='\0';
|
||||
codaburntxid.SetHex(out);
|
||||
result=CodaRPC(&retstr,"prove-payment","-address",srcaddr.c_str(),"-receipt-chain-hash",receipt.c_str(),"");
|
||||
if (result==0)
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "CodaRPC error: " << retstr << std::endl);
|
||||
free(retstr);
|
||||
return (-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((tmp=jobj(jitem(jarray(&n,result,(char *)"payments"),0),(char *)"payload"))==0 || (destaddr=jstr(jobj(tmp,(char *)"common"),(char *)"memo"))==0 ||
|
||||
(receiver=jstr(jitem(jarray(&m,tmp,(char *)"body"),1),(char *)"receiver"))==0 || (amount=j64bits(jitem(jarray(&m,tmp,(char *)"body"),1),(char *)"amount"))==0)
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "Invalid Coda burn tx" << jprint(result,1) << std::endl);
|
||||
free(result);
|
||||
return (-1);
|
||||
}
|
||||
CTxDestination dest = DecodeDestination(destaddr);
|
||||
CScript scriptPubKey = GetScriptForDestination(dest);
|
||||
if (payouts[0]!=CTxOut(amount*COIN,scriptPubKey));
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "Destination address in burn tx does not match destination in import tx" << std::endl);
|
||||
free(result);
|
||||
return (-1);
|
||||
}
|
||||
if (strcmp(receiver,CODA_BURN_ADDRESS)!=0)
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "Invalid burn address " << jstr(tmp1,(char *)"receiver") << std::endl);
|
||||
free(result);
|
||||
return (-1);
|
||||
}
|
||||
if (amount*COIN!=payouts[0].nValue)
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "Burn amount and import amount not matching, " << j64bits(tmp,(char *)"amount") << " - " << payouts[0].nValue/COIN << std::endl);
|
||||
free(result);
|
||||
return (-1);
|
||||
}
|
||||
if (burnTx.vin[0].prevout.hash!=codaburntxid || importTx.vin[0].prevout.hash!=burnTx.GetHash())
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "Invalid import/burn tx vin" << std::endl);
|
||||
free(result);
|
||||
return (-1);
|
||||
}
|
||||
free(result);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t CheckGATEWAYimport(TxProof proof,std::vector<uint8_t> rawproof,CTransaction burnTx,std::vector<CTxOut> payouts)
|
||||
int32_t CheckGATEWAYimport(CTransaction importTx,CTransaction burnTx,std::string refcoin,std::vector<uint8_t> proof,
|
||||
uint256 bindtxid,std::vector<CPubKey> publishers,std::vector<uint256> txids,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub)
|
||||
{
|
||||
// CTransaction oracletx,regtx; CPubKey regpk;
|
||||
// uint256 proofroot,txid,tmporacletxid,merkleroot,mhash,hashBlock; int32_t i,m,n=0,numvouts;
|
||||
// std::string name,desc,format; std::vector<CTxOut> vouts;
|
||||
// std::vector<CPubKey> pubkeys; std::vector<uint256>txids;
|
||||
// char markeraddr[64]; int64_t datafee;
|
||||
// std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
// ASSETCHAINS_SELFIMPORT is coin
|
||||
// check for valid burn from external coin blockchain and if valid return(0);
|
||||
return(-1);
|
||||
// if (GetTransaction(oracletxid, oracletx, hashBlock, false) == 0 || (numvouts = oracletx.vout.size()) <= 0)
|
||||
// {
|
||||
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport cant find oracletxid=" << oracletxid.GetHex() << std::endl);
|
||||
// return(-1);
|
||||
// }
|
||||
// if (DecodeOraclesCreateOpRet(oracletx.vout[numvouts - 1].scriptPubKey,name,desc,format) != 'C')
|
||||
// {
|
||||
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport invalid oracle tx. oracletxid=" << oracletxid.GetHex() << std::endl);
|
||||
// return(-1);
|
||||
// }
|
||||
// if (name!=refcoin || format!="Ihh")
|
||||
// {
|
||||
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport invalid oracle name or format tx. oracletxid=" << oracletxid.GetHex() << " name=" << name << " format=" << format << std::endl);
|
||||
// return(-1);
|
||||
// }
|
||||
// CCtxidaddr(markeraddr,oracletxid);
|
||||
// SetCCunspents(unspentOutputs,markeraddr);
|
||||
// for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
// {
|
||||
// txid = it->first.txhash;
|
||||
// if ( GetTransaction(txid,regtx,hashBlock,false) != 0 && regtx.vout.size() > 0
|
||||
// && DecodeOraclesOpRet(regtx.vout[regtx.vout.size()-1].scriptPubKey,tmporacletxid,regpk,datafee) == 'R' && oracletxid == tmporacletxid )
|
||||
// {
|
||||
// pubkeys.push_back(regpk);
|
||||
// n++;
|
||||
// }
|
||||
// }
|
||||
// merkleroot = zeroid;
|
||||
// for (i = m = 0; i < n; i++)
|
||||
// {
|
||||
// if ((mhash = CCOraclesReverseScan("importcoind-1",txid, height, oracletxid, OraclesBatontxid(oracletxid, pubkeys[i]))) != zeroid)
|
||||
// {
|
||||
// if (merkleroot == zeroid)
|
||||
// merkleroot = mhash, m = 1;
|
||||
// else if (mhash == merkleroot)
|
||||
// m ++;
|
||||
// txids.push_back(txid);
|
||||
// }
|
||||
// }
|
||||
// if (merkleroot == zeroid || m < n / 2) // none or less than half oracle nodes sent merkleroot
|
||||
// {
|
||||
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport couldnt find merkleroot for block height=" << height << "coin=" << refcoin.c_str() << " oracleid=" << oracletxid.GetHex() << " m=" << m << " vs n=" << n << std::endl );
|
||||
// return(-1);
|
||||
// }
|
||||
// proofroot = BitcoinGetProofMerkleRoot(proof, txids);
|
||||
// if (proofroot != merkleroot)
|
||||
// {
|
||||
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport mismatched proof merkleroot=" << proofroot.GetHex() << " and oracles merkleroot=" << merkleroot.GetHex() << std::endl);
|
||||
// return(-1);
|
||||
// }
|
||||
// // check the burntxid is in the proof:
|
||||
// if (std::find(txids.begin(), txids.end(), burnTx.GetHash()) == txids.end()) {
|
||||
// LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport invalid proof for this burntxid=" << burnTx.GetHash().GetHex() << std::endl);
|
||||
// return(-1);
|
||||
// }
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t CheckPUBKEYimport(TxProof proof,std::vector<uint8_t> rawproof,CTransaction burnTx,std::vector<CTxOut> payouts)
|
||||
@@ -404,10 +571,20 @@ int32_t CheckPUBKEYimport(TxProof proof,std::vector<uint8_t> rawproof,CTransacti
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* CC Eval method for import coin.
|
||||
*
|
||||
* This method should control every parameter of the ImportCoin transaction, since it has no signature
|
||||
* to protect it from malleability.
|
||||
|
||||
##### 0xffffffff is a special CCid for single chain/dual daemon imports
|
||||
*/
|
||||
bool Eval::ImportCoin(const std::vector<uint8_t> params,const CTransaction &importTx,unsigned int nIn)
|
||||
{
|
||||
TxProof proof; CTransaction burnTx; std::vector<CTxOut> payouts; uint64_t txfee = 10000;
|
||||
uint32_t targetCcid; std::string targetSymbol; uint256 payoutsHash; std::vector<uint8_t> rawproof;
|
||||
TxProof proof; CTransaction burnTx; std::vector<CTxOut> payouts; uint64_t txfee = 10000; int32_t height,burnvout; std::vector<CPubKey> publishers;
|
||||
uint32_t targetCcid; std::string targetSymbol,srcaddr,destaddr,receipt,rawburntx; uint256 payoutsHash,bindtxid; std::vector<uint8_t> rawproof;
|
||||
std::vector<uint256> txids; CPubKey destpub;
|
||||
|
||||
if ( importTx.vout.size() < 2 )
|
||||
return Invalid("too-few-vouts");
|
||||
// params
|
||||
@@ -458,7 +635,7 @@ bool Eval::ImportCoin(const std::vector<uint8_t> params,const CTransaction &impo
|
||||
{
|
||||
if ( ASSETCHAINS_CODAPORT == 0 )
|
||||
return Invalid("CODA-import-without-port");
|
||||
else if ( CheckCODAimport(proof,rawproof,burnTx,payouts) < 0 )
|
||||
else if ( UnmarshalBurnTx(burnTx,srcaddr,receipt)==0 || CheckCODAimport(importTx,burnTx,payouts,srcaddr,receipt) < 0 )
|
||||
return Invalid("CODA-import-failure");
|
||||
}
|
||||
else if ( targetSymbol == "PUBKEY" )
|
||||
@@ -472,7 +649,7 @@ bool Eval::ImportCoin(const std::vector<uint8_t> params,const CTransaction &impo
|
||||
{
|
||||
if ( targetSymbol != ASSETCHAINS_SELFIMPORT )
|
||||
return Invalid("invalid-gateway-import-coin");
|
||||
else if ( CheckGATEWAYimport(proof,rawproof,burnTx,payouts) < 0 )
|
||||
else if ( UnmarshalBurnTx(burnTx,bindtxid,publishers,txids,height,burnvout,rawburntx,destpub)==0 || CheckGATEWAYimport(importTx,burnTx,targetSymbol,rawproof,bindtxid,publishers,txids,height,burnvout,rawburntx,destpub) < 0 )
|
||||
return Invalid("GATEWAY-import-failure");
|
||||
}
|
||||
}
|
||||
|
||||
1292
src/cc/importgateway.cpp
Normal file
1292
src/cc/importgateway.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,2 +1,19 @@
|
||||
#!/bin/sh
|
||||
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o ../libcc.so cclib.cpp
|
||||
rm *.so rogue/rogue games/tetris games/prices
|
||||
|
||||
echo rogue
|
||||
make -f Makefile_rogue
|
||||
./makerogue
|
||||
|
||||
echo sudoku/musig/dilithium
|
||||
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o sudokucc.so cclib.cpp
|
||||
|
||||
echo games tetris
|
||||
./maketetris
|
||||
|
||||
echo games prices
|
||||
./makeprices
|
||||
|
||||
echo customcc stub
|
||||
gcc -O3 -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o customcc.so cclib.cpp
|
||||
|
||||
|
||||
7
src/cc/makegames
Executable file
7
src/cc/makegames
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
gcc -O3 -DBUILD_GAMESCC -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o gamescc.so cclib.cpp
|
||||
cp gamescc.so ../libcc.so
|
||||
cd ..
|
||||
make
|
||||
cd cc
|
||||
|
||||
8
src/cc/makeprices
Executable file
8
src/cc/makeprices
Executable file
@@ -0,0 +1,8 @@
|
||||
echo pricescc.so
|
||||
gcc -O3 -DBUILD_GAMESCC -DBUILD_PRICES -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o pricescc.so cclib.cpp
|
||||
echo prices
|
||||
cd games
|
||||
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -DSTANDALONE -DBUILD_PRICES ../gamescc.cpp -lncurses -lcurl -o prices
|
||||
cd ..
|
||||
|
||||
|
||||
@@ -1,2 +1,7 @@
|
||||
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -DSTANDALONE tetris.cpp -lncurses -o tetris
|
||||
echo gamescc.so with tetris
|
||||
gcc -O3 -DBUILD_GAMESCC -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o gamescc.so cclib.cpp
|
||||
echo tetris dapp
|
||||
cd games
|
||||
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -DSTANDALONE ../gamescc.cpp -lncurses -lcurl -o tetris
|
||||
cd ..
|
||||
|
||||
|
||||
@@ -388,7 +388,11 @@ int64_t AddMarmarainputs(CMutableTransaction &mtx,std::vector<CPubKey> &pubkeys,
|
||||
uint64_t threshold,nValue,totalinputs = 0; uint256 txid,hashBlock; CTransaction tx; int32_t numvouts,ht,unlockht,vout,i,n = 0; uint8_t funcid; CPubKey pk; std::vector<int64_t> vals;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
SetCCunspents(unspentOutputs,coinaddr);
|
||||
threshold = total/(maxinputs+1);
|
||||
if ( maxinputs > CC_MAXVINS )
|
||||
maxinputs = CC_MAXVINS;
|
||||
if ( maxinputs > 0 )
|
||||
threshold = total/maxinputs;
|
||||
else threshold = total;
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
{
|
||||
txid = it->first.txhash;
|
||||
|
||||
@@ -971,7 +971,8 @@ UniValue OracleInfo(uint256 origtxid)
|
||||
UniValue result(UniValue::VOBJ),a(UniValue::VARR);
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
CTransaction regtx,tx; std::string name,description,format; uint256 hashBlock,txid,oracletxid,batontxid; CPubKey pk; struct CCcontract_info *cp,C; int64_t datafee,funding; char str[67],markeraddr[64],numstr[64],batonaddr[64]; std::vector <uint8_t> data;
|
||||
CTransaction regtx,tx; std::string name,description,format; uint256 hashBlock,txid,oracletxid,batontxid; CPubKey pk;
|
||||
struct CCcontract_info *cp,C; int64_t datafee,funding; char str[67],markeraddr[64],numstr[64],batonaddr[64]; std::vector <uint8_t> data;
|
||||
cp = CCinit(&C,EVAL_ORACLES);
|
||||
CCtxidaddr(markeraddr,origtxid);
|
||||
if ( GetTransaction(origtxid,tx,hashBlock,false) == 0 )
|
||||
|
||||
1007
src/cc/payments.cpp
1007
src/cc/payments.cpp
File diff suppressed because it is too large
Load Diff
@@ -16,17 +16,72 @@
|
||||
#include "CCPegs.h"
|
||||
|
||||
/*
|
||||
Pegs CC builds on top of Prices CC and would bind a pricefeed to a token bid/ask automated marketmaking.
|
||||
pegs CC is able to create a coin backed (by any supported coin with gateways CC deposits) and pegged to any synthetic price that is able to be calculated based on prices CC
|
||||
|
||||
Funds deposited into CC address for a specific peg would then be used to fund the bid/ask as the pricefeed changes the price. Profits/losses would accumulate in the associated address.
|
||||
First, the prices CC needs to be understood, so the extensive comments at the top of ~/src/cc/prices.cpp needs to be understood.
|
||||
|
||||
In the event funds exceed a specified level, it can be spent into a collection address. The idea is that the collection address can further be used for revshares.
|
||||
The second aspect is the ability to import coins, as used by the crosschain burn/import and the -ac_import chains.
|
||||
|
||||
int64_t OraclePrice(int32_t height,uint256 reforacletxid,char *markeraddr,char *format);
|
||||
<one hour later...>
|
||||
|
||||
OK, now we are ready to describe the pegs CC. Let us imagine an -ac_import sidechain with KMD gateways CC. Now we have each native coin fungible with the real KMD via the gateways deposit/withdraw mechanism. Let us start with that and make a pegged and backed USD chain.
|
||||
|
||||
<alternatively we can start from a CC enabled chain with external value>
|
||||
|
||||
Here the native coin is KMD, but we want USD, so there needs to be a way to convert the KMD amounts into USD amounts. Something like "KMDBTC, BTCUSD, *, 1" which is the prices CC syntax to calculate KMD/USD, which is exactly what we need. So now we can assume that we have a block by block usable KMD/USD price. implementationwise, there can be an -ac option like -ac_peg="KMDBTC, BTCUSD, *, 1" and in conjunction with -ac_import=KMD gateways CC sidechain, we now have a chain where deposit of KMD issues the correct USD coins and redeem of USD coins releases the correct number of KMD coins.
|
||||
|
||||
Are we done yet?
|
||||
|
||||
Not quite, as the prices of KMD will be quite volatile relative to USD, which is good during bull markets, not so happy during bear markets. There are 2 halves to this problem, how to deal with massive price increase (easy to solve), how to solve 90% price drop (a lot harder).
|
||||
|
||||
In order to solve both, what is needed is an "account" based tracking which updates based on both price change, coins issued, payments made. So let us create an account that is based on a specific pubkey, where all relevant deposits, issuances, withdraws are tracked via appropriate vin/vout markers.
|
||||
|
||||
Let us modify the USD chain above so that only 80% of the possible USD is issued and 20% held in reserve. This 80% should be at least some easily changeable #define, or even an -ac parameter. We want the issued coins to be released without any encumberances, but the residual 20% value is still controlled (owned) but the depositor. This account has the amount of KMD deposited and USD issued. At the moment of deposit, there will still be 20% equity left. Let us start with 1000 KMD deposit, $1.5 per KMD -> 800 KMD converted to 1200 USD into depositor pubkey and the account of (1000 KMD, -1200 USD) = 200 KMD or $300 equity.
|
||||
|
||||
Now it becomes easy for the bull market case, which is to allow (for a fee like 1%) issuance of more USD as the equity increases, so let us imagine KMD at $10:
|
||||
|
||||
(1000 KMD, -1200 USD, 200KMD reserve) -> $2000 equity, issue 80% -> $1600 using 160 KMD
|
||||
(1000 KMD, -1200 USD, 200KMD reserve, -160KMD, issue $1600 USD, 40 KMD reserve)
|
||||
|
||||
we have $2800 USD in circulation, 40 KMD reserve left against $10000 marketcap of the original deposit. It it easy to see that there are never any problems with lack of KMD to redeem the issued USD in a world where prices only go up. Total USD issuance can be limited by using a decentralized account tracking based on each deposit.
|
||||
|
||||
What is evident though is that with the constantly changing price and the various times that all the various deposits issue USD, the global reserves are something that will be hard to predict and in fact needs to be specifically tracked. Let us combine all accounts exposure in to a global reserves factor. This factor will control various max/min/ allowed and fee percentages.
|
||||
|
||||
Now we are prepared to handle the price goes down scenario. We can rely on the global equity/reserve ratio to be changing relatively slowly as the reference price is the smooted trustless oracles price. This means there will be enough blocks to adjust the global reserves percentage. What we need to do is liquidate specific positions that have the least reserves.
|
||||
|
||||
What does liquidation mean? It means a specific account will be purchased at below its current value and the KMD withdrawn. Let us assume the price drops to $5:
|
||||
|
||||
(1000 KMD, -1200 USD, 200KMD reserve, -160KMD, issue $1600 USD, 40 KMD reserve) 1000 KMD with 2800 USD issued so $2200 reserves. Let us assume it can be liquidated at a 10% discount, so for $2000 in addition to the $2800, the 5000 KMD is able to be withdrawn. This removes 4800 USD coins for 1000 KMD, which is a very low reserve amount of 4%. If a low reserve amount is removed from the system, then the global reserve amount must be improved.
|
||||
|
||||
In addition to the global reserves calculation, there needs to be a trigger percentage that enables positions to be liquidated. We also want to liquidate the worst positions, so in addition to the trigger percentage, there should be a liquidation threshold, and the liquidator would need to find 3 or more better positions that are beyond the liquidation threshold, to be able to liquidate. This will get us to at most 3 accounts that could be liquidated but are not able to, so some method to allow those to also be liquidated. The liquidating nodes are making instant profits, so they should be expected to do whatever blockchain scanning and proving to make things easy for the rest of the nodes.
|
||||
|
||||
One last issue is the normal redemption case where we are not liquidating. In this case, it should be done at the current marketprice, should improve the global reserves metrics and not cause anybody whose position was modified to have cause for complaint. Ideally, there would be an account that has the identical to the global reserve percentage and also at the same price as current marketprice, but this is not realistic, so we need to identify classes of accounts and consider which ones can be fully or partially liquidated to satisfy the constraints.
|
||||
|
||||
looking at our example account:
|
||||
(1000 KMD, -1200 USD, 200KMD reserve, -160KMD, issue $1600 USD, 40 KMD reserve)
|
||||
|
||||
OraclePrice is very useful for pegs.
|
||||
what sort of non-liquidation withdraw would be acceptable? if the base amount 1000 KMD is reduced along with USD owed, then the reserve status will go up for the account. but that would seem to allow extra USD to be able to be issued. there should be no disadvantage from funding a withdraw, but also not any large advantage. it needs to be a neutral event....
|
||||
|
||||
*/
|
||||
One solution is to allow for the chance for any account to be liquidated, but the equity compensated for with a premium based on the account reserves. So in the above case, a premium of 5% on the 40KMD reserve is paid to liquidate its account. Instead of 5% premium, a lower 1% can be done if based on the MAX(correlated[daywindow],smoothed) so we get something that is close to the current marketprice. To prevent people taking advantage of the slowness of the smoothed price to adjust, there would need to be a one day delay in the withdraw.
|
||||
|
||||
From a practical sense, it seems a day is a long time, so maybe having a way to pay a premium like 10%, or wait a day to get the MAX(correlated[daywindow],smoothed) price. This price "jumping" might also be taken advantage of in the deposit side, so similar to prices CC it seems good to have the MAX(correlated[daywindow],smoothed) method.
|
||||
|
||||
Now, we have a decentralized mechanism to handle the price going lower! Combined with the fully decentralized method new USD coins are issued, makes this argubably the first decentralized blockchain that is both backed and pegged. There is the reliance on the gateways CC multisig signers, so there is a fundamental federated trust for chains without intrinsic value.
|
||||
|
||||
Also, notice that the flexibly syntax of prices CC allows to define pegs easily for virtually any type of synthetic, and all the ECB fiats can easily get a backed and pegged coin.
|
||||
|
||||
Let us now consider how to enforce a peg onto a specific gateways CC token. If this can also be achieved, then a full DEX for all the different gateways CC supported coins can be created onto a single fiat denominated chain.
|
||||
|
||||
I think just having a pegscreate rpc call that binds an existing gateways create to a price CC syntax price will be almost enough to support this. Let us assume a USD stablechain and we have a BTC token, then pegscreate <btc gateways txid> "BTCUSD, 1"
|
||||
that will specify using the BTCUSD price, so now we need to create a <txid> based way to do tokenbid/tokenask. For a <txid> based price, the smoothed price is substituted.
|
||||
|
||||
There is the issue of the one day delay, so it might make sense to allow specific bid/ask to be based on some simple combinations of the three possible prices. it might even be possible to go a bit overboard and make a forth like syntax to define the dynamic price for a bid, which maybe at times wont be valid, like it is only valid if the three prices are within 1% of each other. But all that seems over complex and for initial release it can just use the mined, correlated or smoothed price, with some specified percentage offset
|
||||
|
||||
Implementation notes:
|
||||
make sure that fees and markers that can be sent to an unspendable address are sent to: RNdqHx26GWy9bk8MtmH1UiXjQcXE4RKK2P, this is the address for BOTS
|
||||
|
||||
|
||||
*/
|
||||
|
||||
// start of consensus code
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -255,15 +255,23 @@ bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t
|
||||
if ( (*cp->ismyvin)(tx.vin[i].scriptSig) == 0 )
|
||||
return eval->Invalid("unexpected normal vin for unlock");
|
||||
}
|
||||
if ( numvouts == 2 && numvins == 1 )
|
||||
if ( !CheckTxFee(tx, txfee, chainActive.LastTip()->GetHeight(), chainActive.LastTip()->nTime) )
|
||||
return eval->Invalid("txfee is too high");
|
||||
amount = vinTx.vout[0].nValue;
|
||||
reward = RewardsCalc(amount,tx.vin[0].prevout.hash,APR,minseconds,maxseconds,mindeposit);
|
||||
if ( reward == 0 )
|
||||
return eval->Invalid("no eligible rewards");
|
||||
if ( numvins == 1 && tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 )
|
||||
{
|
||||
if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() != 0 )
|
||||
return eval->Invalid("unlock recover tx vout.0 is not normal output");
|
||||
if ( tx.vout[1].nValue != 10000 )
|
||||
return eval->Invalid("wrong marker vout value");
|
||||
else if ( tx.vout[1].scriptPubKey != tx.vout[0].scriptPubKey )
|
||||
return eval->Invalid("unlock recover tx vout.1 mismatched scriptPubKey");
|
||||
else if ( tx.vout[0].scriptPubKey != vinTx.vout[1].scriptPubKey )
|
||||
return eval->Invalid("unlock recover tx vout.0 mismatched scriptPubKey");
|
||||
else if ( tx.vout[0].nValue > vinTx.vout[0].nValue )
|
||||
return eval->Invalid("unlock recover tx vout.0 mismatched amounts");
|
||||
else if ( tx.vout[1].nValue > 0 )
|
||||
else if ( tx.vout[2].nValue > 0 )
|
||||
return eval->Invalid("unlock recover tx vout.1 nonz amount");
|
||||
else return(true);
|
||||
}
|
||||
@@ -277,8 +285,6 @@ bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t
|
||||
return eval->Invalid("unlock tx vout.1 is CC output");
|
||||
else if ( tx.vout[1].scriptPubKey != vinTx.vout[1].scriptPubKey )
|
||||
return eval->Invalid("unlock tx vout.1 mismatched scriptPubKey");
|
||||
amount = vinTx.vout[0].nValue;
|
||||
reward = RewardsCalc(amount,tx.vin[0].prevout.hash,APR,minseconds,maxseconds,mindeposit);
|
||||
if ( RewardsExactAmounts(cp,eval,tx,txfee+tx.vout[1].nValue,sbits,fundingtxid) == 0 )
|
||||
return false;
|
||||
else if ( tx.vout[1].nValue > amount+reward )
|
||||
@@ -333,7 +339,11 @@ int64_t AddRewardsInputs(CScript &scriptPubKey,uint64_t maxseconds,struct CCcont
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
GetCCaddress(cp,coinaddr,pk);
|
||||
SetCCunspents(unspentOutputs,coinaddr);
|
||||
threshold = total/(maxinputs+1);
|
||||
if ( maxinputs > CC_MAXVINS )
|
||||
maxinputs = CC_MAXVINS;
|
||||
if ( maxinputs > 0 )
|
||||
threshold = total/maxinputs;
|
||||
else threshold = total;
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
{
|
||||
txid = it->first.txhash;
|
||||
@@ -677,8 +687,7 @@ std::string RewardsUnlock(uint64_t txfee,char *planstr,uint256 fundingtxid,uint2
|
||||
}
|
||||
else
|
||||
{
|
||||
firstmtx.vout.push_back(CTxOut(amount-txfee,scriptPubKey));
|
||||
//CCerror = "cant find enough rewards inputs";
|
||||
firstmtx.vout.push_back(CTxOut(amount-txfee*2,scriptPubKey));
|
||||
fprintf(stderr,"not enough rewards funds to payout %.8f, recover mode tx\n",(double)(reward+txfee)/COIN);
|
||||
return(FinalizeCCTx(-1LL,cp,firstmtx,mypk,txfee,EncodeRewardsOpRet('U',sbits,fundingtxid)));
|
||||
}
|
||||
@@ -703,4 +712,3 @@ std::string RewardsUnlock(uint64_t txfee,char *planstr,uint256 fundingtxid,uint2
|
||||
fprintf(stderr,"amount %.8f -> reward %.8f\n",(double)amount/COIN,(double)reward/COIN);
|
||||
return("");
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,31 @@
|
||||
#ifndef H_CURSESD_H
|
||||
#define H_CURSESD_H
|
||||
|
||||
#define KEY_OFFSET 0x100
|
||||
#define KEY_DOWN (KEY_OFFSET + 0x02) /* Down arrow key */
|
||||
#define KEY_UP (KEY_OFFSET + 0x03) /* Up arrow key */
|
||||
#define KEY_LEFT (KEY_OFFSET + 0x04) /* Left arrow key */
|
||||
#define KEY_RIGHT (KEY_OFFSET + 0x05) /* Right arrow key */
|
||||
|
||||
|
||||
#define COLOR_BLACK 0
|
||||
|
||||
#ifdef PDC_RGB /* RGB */
|
||||
# define COLOR_RED 1
|
||||
# define COLOR_GREEN 2
|
||||
# define COLOR_BLUE 4
|
||||
#else /* BGR */
|
||||
# define COLOR_BLUE 1
|
||||
# define COLOR_GREEN 2
|
||||
# define COLOR_RED 4
|
||||
#endif
|
||||
|
||||
#define COLOR_CYAN (COLOR_BLUE | COLOR_GREEN)
|
||||
#define COLOR_MAGENTA (COLOR_RED | COLOR_BLUE)
|
||||
#define COLOR_YELLOW (COLOR_RED | COLOR_GREEN)
|
||||
|
||||
#define COLOR_WHITE 7
|
||||
|
||||
#define LINES 24
|
||||
#define COLS 80
|
||||
|
||||
@@ -150,6 +175,17 @@ char *unctrl(char c);
|
||||
#define leaveok(win,bf) 0
|
||||
#define halfdelay(x) 0
|
||||
#define nocbreak() 0
|
||||
#define cbreak() 0
|
||||
#define curs_set(x) 0
|
||||
|
||||
// for tetris
|
||||
#define init_pair(a,b,c) 0
|
||||
#define start_color() 0
|
||||
#define box(a,b,c) 0
|
||||
#define A_REVERSE 0
|
||||
#define COLOR_PAIR(a) 0
|
||||
#define timeout(x) 0
|
||||
// end for tetris
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
|
||||
@@ -784,9 +784,9 @@ int32_t rogue_sendrawtransaction(char *rawtx)
|
||||
return(retval);
|
||||
}
|
||||
|
||||
void rogue_progress(struct rogue_state *rs,int32_t waitflag,uint64_t seed,char *keystrokes,int32_t num)
|
||||
int32_t rogue_progress(struct rogue_state *rs,int32_t waitflag,uint64_t seed,char *keystrokes,int32_t num)
|
||||
{
|
||||
char cmd[16384],hexstr[16384],params[32768],*retstr,*rawtx,*pastkeys,*pastcmp,*keys; int32_t i,len,numpastkeys; cJSON *retjson,*resobj;
|
||||
char cmd[16384],hexstr[16384],params[32768],*retstr,*errstr,*rawtx,*pastkeys,*pastcmp,*keys; int32_t i,len,numpastkeys,retflag = -1; cJSON *retjson,*resobj;
|
||||
//fprintf(stderr,"rogue_progress num.%d\n",num);
|
||||
if ( rs->guiflag != 0 && Gametxidstr[0] != 0 )
|
||||
{
|
||||
@@ -795,7 +795,7 @@ void rogue_progress(struct rogue_state *rs,int32_t waitflag,uint64_t seed,char *
|
||||
if ( rogue_sendrawtransaction(rs->keystrokeshex) == 0 )
|
||||
{
|
||||
if ( waitflag == 0 )
|
||||
return;
|
||||
return(0);
|
||||
else if ( 0 )
|
||||
{
|
||||
while ( rogue_sendrawtransaction(rs->keystrokeshex) == 0 )
|
||||
@@ -866,8 +866,12 @@ void rogue_progress(struct rogue_state *rs,int32_t waitflag,uint64_t seed,char *
|
||||
{
|
||||
if ( rs->keystrokeshex != 0 )
|
||||
free(rs->keystrokeshex);
|
||||
rs->keystrokeshex = (char *)malloc(strlen(rawtx)+1);
|
||||
strcpy(rs->keystrokeshex,rawtx);
|
||||
if ( (errstr= jstr(resobj,"error")) == 0 )
|
||||
{
|
||||
rs->keystrokeshex = (char *)malloc(strlen(rawtx)+1);
|
||||
strcpy(rs->keystrokeshex,rawtx);
|
||||
retflag = 1;
|
||||
} else fprintf(stderr,"error sending keystrokes tx\n"), sleep(1);
|
||||
//fprintf(stderr,"set keystrokestx <- %s\n",rs->keystrokeshex);
|
||||
}
|
||||
free_json(retjson);
|
||||
@@ -885,6 +889,7 @@ void rogue_progress(struct rogue_state *rs,int32_t waitflag,uint64_t seed,char *
|
||||
}
|
||||
}
|
||||
}
|
||||
return(retflag);
|
||||
}
|
||||
|
||||
int32_t rogue_setplayerdata(struct rogue_state *rs,char *gametxidstr)
|
||||
|
||||
@@ -158,7 +158,7 @@ int32_t flushkeystrokes_local(struct rogue_state *rs,int32_t waitflag)
|
||||
#ifdef BUILD_ROGUE
|
||||
// stubs for inside daemon
|
||||
|
||||
void rogue_progress(struct rogue_state *rs,int32_t waitflag,uint64_t seed,char *keystrokes,int32_t num)
|
||||
int32_t rogue_progress(struct rogue_state *rs,int32_t waitflag,uint64_t seed,char *keystrokes,int32_t num)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -172,15 +172,11 @@ int32_t flushkeystrokes(struct rogue_state *rs,int32_t waitflag)
|
||||
{
|
||||
if ( rs->num > 0 )
|
||||
{
|
||||
// need to get existing keystrokes including mempool
|
||||
// create keystrokes that are not saved
|
||||
//rs->keytxid = rogue_progress(rs,waitflag,rs->seed,&rs->buffered[rs->lastnum],rs->num - rs->lastnum);
|
||||
//rs->lastnum = rs->num;
|
||||
rogue_progress(rs,waitflag,rs->seed,rs->buffered,rs->num);
|
||||
flushkeystrokes_local(rs,waitflag);
|
||||
memset(rs->buffered,0,sizeof(rs->buffered));
|
||||
//rs->num = 0;
|
||||
//rs->counter++;
|
||||
if ( rogue_progress(rs,waitflag,rs->seed,rs->buffered,rs->num) > 0 )
|
||||
{
|
||||
flushkeystrokes_local(rs,waitflag);
|
||||
memset(rs->buffered,0,sizeof(rs->buffered));
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -380,7 +380,7 @@ int32_t rogue_restorepack(struct rogue_state *rs);
|
||||
void restore_player(struct rogue_state *rs);
|
||||
int32_t rogue_replay2(uint8_t *newdata,uint64_t seed,char *keystrokes,int32_t num,struct rogue_player *player,int32_t sleepmillis);
|
||||
void rogue_bailout(struct rogue_state *rs);
|
||||
void rogue_progress(struct rogue_state *rs,int32_t waitflag,uint64_t seed,char *keystrokes,int32_t num);
|
||||
int32_t rogue_progress(struct rogue_state *rs,int32_t waitflag,uint64_t seed,char *keystrokes,int32_t num);
|
||||
int32_t rogue_setplayerdata(struct rogue_state *rs,char *gametxidstr);
|
||||
|
||||
#define ROGUE_MAXTOTAL (pstats.s_str*2)
|
||||
|
||||
@@ -527,6 +527,7 @@ add_line(struct rogue_state *rs,char *fmt, char *arg)
|
||||
touchwin(tw);
|
||||
wrefresh(tw);
|
||||
wait_for(rs,' ');
|
||||
|
||||
if (md_hasclreol())
|
||||
{
|
||||
werase(tw);
|
||||
@@ -543,16 +544,31 @@ add_line(struct rogue_state *rs,char *fmt, char *arg)
|
||||
}
|
||||
else
|
||||
{
|
||||
char *promptex = "--Wait 5 sec.--";
|
||||
wmove(hw, LINES - 1, 0);
|
||||
waddstr(hw, prompt);
|
||||
waddstr(hw, newpage ? promptex : prompt);
|
||||
wrefresh(hw);
|
||||
wait_for(rs,' ');
|
||||
|
||||
if (newpage) {
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef _MSC_VER
|
||||
#define sleep(x) Sleep(1000*(x))
|
||||
#endif
|
||||
#endif
|
||||
sleep(5);
|
||||
|
||||
} else
|
||||
wait_for(rs, ' ');
|
||||
|
||||
clearok(curscr, TRUE);
|
||||
wclear(hw);
|
||||
|
||||
touchwin(stdscr);
|
||||
}
|
||||
newpage = TRUE;
|
||||
line_cnt = 0;
|
||||
|
||||
maxlen = (int) strlen(prompt);
|
||||
}
|
||||
if (fmt != NULL && !(line_cnt == 0 && *fmt == '\0'))
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#define ROGUE_MAXPLAYERS 64 // need to send unused fees back to globalCC address to prevent leeching
|
||||
#define ROGUE_MAXKEYSTROKESGAP 60
|
||||
#define ROGUE_MAXITERATIONS 777
|
||||
#define ROGUE_MAXCASHOUT (777 * COIN)
|
||||
|
||||
#include "rogue/rogue_player.h"
|
||||
|
||||
@@ -282,6 +283,24 @@ int32_t rogue_iamregistered(int32_t maxplayers,uint256 gametxid,CTransaction tx,
|
||||
return(0);
|
||||
}
|
||||
|
||||
int64_t rogue_buyins(uint256 gametxid,int32_t maxplayers)
|
||||
{
|
||||
int32_t i,vout; uint256 spenttxid,hashBlock; CTransaction spenttx; int64_t buyins = 0;
|
||||
for (i=0; i<maxplayers; i++)
|
||||
{
|
||||
vout = i+1;
|
||||
if ( myIsutxo_spent(spenttxid,gametxid,vout) >= 0 )
|
||||
{
|
||||
if ( myGetTransaction(spenttxid,spenttx,hashBlock) != 0 && spenttx.vout.size() > 0 )
|
||||
{
|
||||
if ( spenttx.vout[0].nValue > ROGUE_REGISTRATIONSIZE )
|
||||
buyins += (spenttx.vout[0].nValue - ROGUE_REGISTRATIONSIZE);
|
||||
} //else fprintf(stderr,"cant find spenttxid.%s\n",spenttxid.GetHex().c_str());
|
||||
} //else fprintf(stderr,"vout %d is unspent\n",vout);
|
||||
}
|
||||
return(buyins);
|
||||
}
|
||||
|
||||
int32_t rogue_isvalidgame(struct CCcontract_info *cp,int32_t &gameheight,CTransaction &tx,int64_t &buyin,int32_t &maxplayers,uint256 txid,int32_t unspentv0)
|
||||
{
|
||||
uint256 hashBlock; int32_t i,numvouts; char coinaddr[64]; CPubKey roguepk; uint64_t txfee = 10000;
|
||||
@@ -689,6 +708,7 @@ uint64_t rogue_gamefields(UniValue &obj,int64_t maxplayers,int64_t buyin,uint256
|
||||
obj.push_back(Pair("alive",rogue_playersalive(openslots,numplayers,gametxid,maxplayers,ht,tx)));
|
||||
obj.push_back(Pair("openslots",openslots));
|
||||
obj.push_back(Pair("numplayers",numplayers));
|
||||
obj.push_back(Pair("buyins",ValueFromAmount(rogue_buyins(gametxid,maxplayers))));
|
||||
}
|
||||
obj.push_back(Pair("maxplayers",maxplayers));
|
||||
obj.push_back(Pair("buyin",ValueFromAmount(buyin)));
|
||||
@@ -917,8 +937,8 @@ UniValue rogue_keystrokes(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
|
||||
int32_t nextheight = komodo_nextheight();
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(),nextheight);
|
||||
UniValue result(UniValue::VOBJ); CPubKey roguepk,mypk; uint256 gametxid,playertxid,batontxid; int64_t batonvalue,buyin; std::vector<uint8_t> keystrokes,playerdata; int32_t numplayers,regslot,numkeys,batonht,batonvout,n,elapsed,gameheight,maxplayers; CTransaction tx; CTxOut txout; char *keystrokestr,destaddr[64]; std::string rawtx,symbol,pname; bits256 t; uint8_t mypriv[32];
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
// if ( txfee == 0 )
|
||||
txfee = 1000; // smaller than normal on purpose
|
||||
rogue_univalue(result,"keystrokes",-1,-1);
|
||||
if ( params != 0 && (n= cJSON_GetArraySize(params)) == 2 && (keystrokestr= jstr(jitem(params,1),0)) != 0 )
|
||||
{
|
||||
@@ -1092,6 +1112,20 @@ UniValue rogue_extract(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
|
||||
return(result);
|
||||
}
|
||||
|
||||
int64_t rogue_cashout(struct rogue_player *P)
|
||||
{
|
||||
int32_t dungeonlevel; int64_t cashout,mult = 10;
|
||||
if ( P->amulet != 0 )
|
||||
mult *= 5;
|
||||
dungeonlevel = P->dungeonlevel;
|
||||
if ( P->amulet != 0 && dungeonlevel < 26 )
|
||||
dungeonlevel = 26;
|
||||
if ( dungeonlevel > 42 )
|
||||
dungeonlevel = 42;
|
||||
cashout = (uint64_t)P->gold * P->gold * mult * dungeonlevel;
|
||||
return(cashout);
|
||||
}
|
||||
|
||||
int32_t rogue_playerdata_validate(int64_t *cashoutp,uint256 &playertxid,struct CCcontract_info *cp,std::vector<uint8_t> playerdata,uint256 gametxid,CPubKey pk)
|
||||
{
|
||||
static uint32_t good,bad; static uint256 prevgame;
|
||||
@@ -1104,15 +1138,9 @@ int32_t rogue_playerdata_validate(int64_t *cashoutp,uint256 &playertxid,struct C
|
||||
free(keystrokes);
|
||||
sprintf(fname,"rogue.%llu.pack",(long long)seed);
|
||||
remove(fname);
|
||||
|
||||
for (i=0; i<newdata.size(); i++)
|
||||
((uint8_t *)&P)[i] = newdata[i];
|
||||
if ( P.amulet != 0 )
|
||||
mult *= 5;
|
||||
dungeonlevel = P.dungeonlevel;
|
||||
if ( P.amulet != 0 && dungeonlevel < 26 )
|
||||
dungeonlevel = 26;
|
||||
*cashoutp = (uint64_t)P.gold * P.gold * mult * dungeonlevel;
|
||||
*cashoutp = rogue_cashout(&P);
|
||||
if ( newdata == playerdata )
|
||||
{
|
||||
if ( gametxid != prevgame )
|
||||
@@ -1203,16 +1231,10 @@ UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
|
||||
result.push_back(Pair("name","rogue"));
|
||||
result.push_back(Pair("method",method));
|
||||
result.push_back(Pair("myrogueaddr",myrogueaddr));
|
||||
mult = 10; //100000;
|
||||
if ( strcmp(method,"bailout") == 0 )
|
||||
{
|
||||
funcid = 'Q';
|
||||
mult = 10; //100000;
|
||||
}
|
||||
else
|
||||
{
|
||||
funcid = 'H';
|
||||
mult = 20; //200000;
|
||||
}
|
||||
else funcid = 'H';
|
||||
if ( params != 0 && (n= cJSON_GetArraySize(params)) > 0 )
|
||||
{
|
||||
if ( n > 0 )
|
||||
@@ -1261,13 +1283,10 @@ UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
|
||||
cpTokens = CCinit(&tokensC, EVAL_TOKENS);
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, txfee, GetUnspendable(cpTokens,NULL))); // marker to token cc addr, burnable and validated
|
||||
mtx.vout.push_back(MakeTokensCC1vout(cp->evalcode,1,mypk));
|
||||
if ( P.amulet != 0 )
|
||||
mult *= 5;
|
||||
dungeonlevel = P.dungeonlevel;
|
||||
if ( P.amulet != 0 && dungeonlevel < 26 )
|
||||
dungeonlevel = 26;
|
||||
cashout = (uint64_t)P.gold * P.gold * mult * dungeonlevel;
|
||||
cashout = rogue_cashout(&P);
|
||||
fprintf(stderr,"\nextracted $$$gold.%d -> %.8f ROGUE hp.%d strength.%d/%d level.%d exp.%d dl.%d n.%d amulet.%d\n",P.gold,(double)cashout/COIN,P.hitpoints,P.strength&0xffff,P.strength>>16,P.level,P.experience,P.dungeonlevel,n,P.amulet);
|
||||
if ( komodo_nextheight() > 77777 && cashout > ROGUE_MAXCASHOUT )
|
||||
cashout = ROGUE_MAXCASHOUT;
|
||||
if ( funcid == 'H' && maxplayers > 1 )
|
||||
{
|
||||
if ( P.amulet == 0 )
|
||||
@@ -1277,6 +1296,7 @@ UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
|
||||
else if ( rogue_playersalive(tmp,tmp,gametxid,maxplayers,gameheight,gametx) > 1 )
|
||||
return(cclib_error(result,"highlander must be a winner or last one standing"));
|
||||
}
|
||||
cashout *= 2;
|
||||
cashout += numplayers * buyin;
|
||||
}
|
||||
if ( cashout > 0 )
|
||||
@@ -1321,12 +1341,12 @@ UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
|
||||
|
||||
UniValue rogue_bailout(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
|
||||
{
|
||||
return(rogue_finishgame(txfee,cp,params,"bailout"));
|
||||
return(rogue_finishgame(txfee,cp,params,(char *)"bailout"));
|
||||
}
|
||||
|
||||
UniValue rogue_highlander(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
|
||||
{
|
||||
return(rogue_finishgame(txfee,cp,params,"highlander"));
|
||||
return(rogue_finishgame(txfee,cp,params,(char *)"highlander"));
|
||||
}
|
||||
|
||||
UniValue rogue_gameinfo(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
|
||||
@@ -1501,7 +1521,7 @@ bool rogue_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const C
|
||||
if ( (numvouts= tx.vout.size()) > 1 )
|
||||
{
|
||||
txid = tx.GetHash();
|
||||
if ( txid == Parseuint256("1ae04dc0c5f2fca2053819a3a1b2efe5d355c34f58d6f16d59e5e2573e7baf7f") ) // osx rogue chain ht.50902
|
||||
if ( txid == Parseuint256("1ae04dc0c5f2fca2053819a3a1b2efe5d355c34f58d6f16d59e5e2573e7baf7f") || txid == Parseuint256("2a34b36cc1292aecfaabdad79b42cab9989fa6dcc87ac8ca88aa6162dab1e2c4") ) // osx rogue chain ht.50902, 69522
|
||||
enabled = 0;
|
||||
scriptPubKey = tx.vout[numvouts-1].scriptPubKey;
|
||||
GetOpReturnData(scriptPubKey,vopret);
|
||||
@@ -1593,8 +1613,13 @@ bool rogue_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const C
|
||||
if ( enabled != 0 )
|
||||
return eval->Invalid("mismatched playerdata");
|
||||
}
|
||||
if ( height > 777777 && cashout > ROGUE_MAXCASHOUT )
|
||||
cashout = ROGUE_MAXCASHOUT;
|
||||
if ( funcid == 'H' )
|
||||
{
|
||||
cashout *= 2;
|
||||
cashout += rogue_buyins(gametxid,maxplayers);
|
||||
}
|
||||
sprintf(cashstr,"tokentx.(%c) decoded.%d ht.%d txid.%s %.8f vs vout2 %.8f",tokentx,decoded,height,txid.GetHex().c_str(),(double)cashout/COIN,(double)tx.vout[2].nValue/COIN);
|
||||
if ( strcmp(laststr,cashstr) != 0 )
|
||||
{
|
||||
|
||||
2411
src/cc/tetris.cpp
2411
src/cc/tetris.cpp
File diff suppressed because it is too large
Load Diff
@@ -102,6 +102,9 @@ enum BlockStatus: uint32_t {
|
||||
//! Scripts & signatures ok. Implies all parents are also at least SCRIPTS.
|
||||
BLOCK_VALID_SCRIPTS = 5,
|
||||
|
||||
// flag to check if contextual check block has passed in Accept block, if it has not check at connect block.
|
||||
BLOCK_VALID_CONTEXT = 6,
|
||||
|
||||
//! All validity bits.
|
||||
BLOCK_VALID_MASK = BLOCK_VALID_HEADER | BLOCK_VALID_TREE | BLOCK_VALID_TRANSACTIONS |
|
||||
BLOCK_VALID_CHAIN | BLOCK_VALID_SCRIPTS,
|
||||
@@ -115,7 +118,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
|
||||
BLOCK_IN_TMPFILE = 256
|
||||
};
|
||||
|
||||
//! Short-hand for the highest consensus validity we implement.
|
||||
|
||||
@@ -91,7 +91,7 @@ static CBlock CreateGenesisBlock(uint32_t nTime, const uint256& nNonce, const st
|
||||
*/
|
||||
void *chainparams_commandline(void *ptr);
|
||||
#include "komodo_defs.h"
|
||||
uint32_t ASSETCHAINS_BLOCKTIME = 60;
|
||||
int32_t ASSETCHAINS_BLOCKTIME = 60;
|
||||
|
||||
const arith_uint256 maxUint = UintToArith256(uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"));
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
* for both bitcoind and bitcoin-core, to make it harder for attackers to
|
||||
* target servers or GUI users specifically.
|
||||
*/
|
||||
const std::string CLIENT_NAME = GetArg("-ac_clientname", "MagicBean");
|
||||
const std::string CLIENT_NAME = GetArg("-clientname", "MagicBean");
|
||||
|
||||
/**
|
||||
* Client version number
|
||||
|
||||
27
src/gui/komodoku/README.md
Normal file
27
src/gui/komodoku/README.md
Normal file
@@ -0,0 +1,27 @@
|
||||
About
|
||||
-----
|
||||
Komodo SudokuCC GUI
|
||||
|
||||
Just solve Sudoku and earn SUDOKU coins!
|
||||
|
||||

|
||||
|
||||
To run you need up and running SUDOKU chain daemon built from latest https://github.com/jl777/komodo/tree/FSM and started with valid for your wallet pubkey in `-pubkey=` param.
|
||||
|
||||
SUDOKU chain params:
|
||||
```./komodod -ac_name=SUDOKU -ac_supply=1000000 -pubkey=<yourpubkey> -addnode=5.9.102.210 -gen -genproclimit=1 -ac_cclib=sudoku -ac_perc=10000000 -ac_reward=100000000 -ac_cc=60000 -ac_script=2ea22c80203d1579313abe7d8ea85f48c65ea66fc512c878c0d0e6f6d54036669de940febf8103120c008203000401cc &```
|
||||
|
||||
1) install dependencies:
|
||||
|
||||
```
|
||||
$ sudo apt-get install python-pygame libgnutls28-dev
|
||||
$ pip install requests wheel slick-bitcoinrpc pygame
|
||||
```
|
||||
|
||||
2) and then start:
|
||||
|
||||
```
|
||||
$ git clone https://github.com/tonymorony/Komodoku
|
||||
$ cd Komodoku
|
||||
$ python Sudoku.py
|
||||
```
|
||||
BIN
src/gui/komodoku/Roboto-Light.ttf
Executable file
BIN
src/gui/komodoku/Roboto-Light.ttf
Executable file
Binary file not shown.
362
src/gui/komodoku/Sudoku.py
Normal file
362
src/gui/komodoku/Sudoku.py
Normal file
@@ -0,0 +1,362 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (C) 2010 Paul Bourke <pauldbourke@gmail.com>
|
||||
# Copyright (C) 2019 Anton Lysakov <tlysakov@gmail.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pygame
|
||||
import sys
|
||||
import random
|
||||
import sudoku_kmdlib
|
||||
import time
|
||||
|
||||
class PyGameBoard():
|
||||
"""Represents the game's frontend using pygame"""
|
||||
|
||||
def __init__(self, engine, windowSize, gridValues, timestampValues):
|
||||
pygame.init()
|
||||
pygame.display.set_caption('Sudoku')
|
||||
self.__engine = engine
|
||||
self.__gridValues = gridValues
|
||||
self.__timestampValues = timestampValues
|
||||
self.__screen = pygame.display.set_mode(windowSize)
|
||||
background = pygame.image.load(sys.path[0] + '/background.png').convert()
|
||||
board = pygame.image.load(sys.path[0] + '/board.png')
|
||||
boardX = boardY = 10
|
||||
self.__screen.blit(background, (0, 0))
|
||||
self.__screen.blit(board, (boardX, boardY))
|
||||
self.__tiles = self.__createTiles(boardX, boardY)
|
||||
self.__drawUI()
|
||||
self.__draw()
|
||||
|
||||
def __draw(self):
|
||||
"""Handles events and updates display buffer"""
|
||||
while True:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
sys.exit()
|
||||
elif event.type == pygame.MOUSEBUTTONUP and event.button == 1:
|
||||
self.__handleMouse(event.pos)
|
||||
elif (event.type == pygame.KEYUP):
|
||||
self.__handleKeyboard(event.key)
|
||||
pygame.display.flip()
|
||||
|
||||
def __drawUI(self):
|
||||
'''Draws the text buttons along the right panel'''
|
||||
font = pygame.font.Font(sys.path[0] + '/Roboto-Light.ttf', 28)
|
||||
font.set_underline(True)
|
||||
self.__titleText = font.render('Sudoku', 1, (0, 0, 0))
|
||||
self.__titleTextRect = self.__titleText.get_rect()
|
||||
self.__titleTextRect.centerx = 445
|
||||
self.__titleTextRect.centery = 30
|
||||
self.__screen.blit(self.__titleText, self.__titleTextRect)
|
||||
|
||||
font = pygame.font.Font(sys.path[0] + '/Roboto-Light.ttf', 14)
|
||||
self.__titleText = font.render('TonyL 2019', 1, (0, 0, 0))
|
||||
self.__titleTextRect = self.__titleText.get_rect()
|
||||
self.__titleTextRect.centerx = 445
|
||||
self.__titleTextRect.centery = 55
|
||||
self.__screen.blit(self.__titleText, self.__titleTextRect)
|
||||
|
||||
font = pygame.font.Font(sys.path[0] + '/Roboto-Light.ttf', 24)
|
||||
self.__newGameText = font.render('-New Game-', 1, (0, 0, 0))
|
||||
self.__newGameTextRect = self.__newGameText.get_rect()
|
||||
self.__newGameTextRect.centerx = 495
|
||||
self.__newGameTextRect.centery = 180
|
||||
self.__screen.blit(self.__newGameText, self.__newGameTextRect)
|
||||
|
||||
self.__solveText = font.render('-Check Balance-', 1, (0, 0, 0))
|
||||
self.__solveTextRect = self.__solveText.get_rect()
|
||||
self.__solveTextRect.centerx = 495
|
||||
self.__solveTextRect.centery = 220
|
||||
self.__screen.blit(self.__solveText, self.__solveTextRect)
|
||||
|
||||
font = pygame.font.Font(sys.path[0] + '/Roboto-Light.ttf', 24)
|
||||
self.__checkText = font.render('-Check Solution-', 1, (0, 0, 0))
|
||||
self.__checkTextRect = self.__checkText.get_rect()
|
||||
self.__checkTextRect.centerx = 495
|
||||
self.__checkTextRect.centery = 260
|
||||
self.__screen.blit(self.__checkText, self.__checkTextRect)
|
||||
|
||||
def __handleKeyboard(self, key):
|
||||
"""Get key pressed and update the game board"""
|
||||
validKeys = {pygame.K_0: "0", pygame.K_1: "1", pygame.K_2: "2",
|
||||
pygame.K_3: "3", pygame.K_4: "4", pygame.K_5: "5",
|
||||
pygame.K_6: "6", pygame.K_7: "7", pygame.K_8: "8",
|
||||
pygame.K_9: "9", pygame.K_BACKSPACE: "", pygame.K_DELETE: ""}
|
||||
if key == pygame.K_ESCAPE:
|
||||
sys.exit()
|
||||
elif key in validKeys:
|
||||
i = self.__currentTile.getGridLoc()[0]
|
||||
j = self.__currentTile.getGridLoc()[1]
|
||||
cell_num = 9 * i + (j + 1)
|
||||
self.__currentTile.setFontColor(pygame.color.THECOLORS['blue'])
|
||||
self.__currentTile.updateValue(validKeys[key])
|
||||
self.__gridValues[i][j] = self.__currentTile.getValue()
|
||||
self.__timestampValues[cell_num] = int(round(time.time()))
|
||||
|
||||
def __handleMouse(self, (x, y)):
|
||||
for row in self.__tiles:
|
||||
for tile in row:
|
||||
if tile.getRect().collidepoint(x, y):
|
||||
if not tile.isReadOnly():
|
||||
tile.highlight(pygame.color.THECOLORS['lightyellow'])
|
||||
if self.__currentTile.isCorrect():
|
||||
self.__currentTile.unhighlight()
|
||||
else:
|
||||
self.__currentTile.highlight((255, 164, 164))
|
||||
self.__currentTile = tile
|
||||
if self.__newGameTextRect.collidepoint(x, y):
|
||||
self.__engine.startNewGame()
|
||||
elif self.__solveTextRect.collidepoint(x, y):
|
||||
self.__engine.getSolution()
|
||||
elif self.__checkTextRect.collidepoint(x, y):
|
||||
ret = self.__engine.checkSolution(self.__gridValues, self.__timestampValues)
|
||||
|
||||
def __updateBoard(self, gridValues):
|
||||
for i in range(9):
|
||||
for j in range(9):
|
||||
self.__tiles[i][j].updateValue(gridValues[i][j])
|
||||
|
||||
def __unhightlightBoard(self):
|
||||
for i in range(9):
|
||||
for j in range(9):
|
||||
self.__tiles[i][j].unhighlight()
|
||||
|
||||
def __createTiles(self, initX=0, initY=0):
|
||||
"""Set up a list of tiles corresponding to the grid, along with
|
||||
each ones location coordinates on the board"""
|
||||
square_size = 40
|
||||
tiles = list()
|
||||
x = y = 0
|
||||
for i in range(0, 9):
|
||||
row = list()
|
||||
for j in range(0, 9):
|
||||
if j in (0, 1, 2):
|
||||
x = (j * 41) + (initX + 2)
|
||||
if j in (3, 4, 5):
|
||||
x = (j * 41) + (initX + 6)
|
||||
if j in (6, 7, 8):
|
||||
x = (j * 41) + (initX + 10)
|
||||
if i in (0, 1, 2):
|
||||
y = (i * 41) + (initY + 2)
|
||||
if i in (3, 4, 5):
|
||||
y = (i * 41) + (initY + 6)
|
||||
if i in (6, 7, 8):
|
||||
y = (i * 41) + (initY + 10)
|
||||
tile = Tile(self.__gridValues[i][j], (x, y), (i, j), square_size)
|
||||
row.append(tile)
|
||||
tiles.append(row)
|
||||
self.__currentTile = tiles[0][0]
|
||||
return tiles
|
||||
|
||||
|
||||
class Tile():
|
||||
"""Represents a graphical tile on the board"""
|
||||
|
||||
def __init__(self, value, coords, gridLoc, size):
|
||||
xpos = coords[0]
|
||||
ypos = coords[1]
|
||||
self.__fontColor = pygame.color.THECOLORS["black"]
|
||||
self.__readOnly = False
|
||||
self.__colorSquare = pygame.Surface((size, size)).convert()
|
||||
self.__colorSquare.fill(pygame.color.THECOLORS['white'], None, pygame.BLEND_RGB_ADD)
|
||||
self.__colorSquareRect = self.__colorSquare.get_rect()
|
||||
self.__colorSquareRect = self.__colorSquareRect.move(xpos + 1, ypos + 1)
|
||||
self.__value = value
|
||||
self.__gridLoc = gridLoc
|
||||
self.__screen = pygame.display.get_surface()
|
||||
self.__rect = pygame.Rect(xpos, ypos, size, size)
|
||||
self.__isCorrect = True
|
||||
if self.__value is not '-':
|
||||
self.__readOnly = True
|
||||
self.__draw()
|
||||
|
||||
def updateValue(self, value):
|
||||
self.__value = value
|
||||
self.__draw()
|
||||
|
||||
def isCorrect(self):
|
||||
return self.__isCorrect
|
||||
|
||||
def setCorrect(self, isCorrect):
|
||||
self.__isCorrect = isCorrect
|
||||
|
||||
def setFontColor(self, fontColor):
|
||||
self.__fontColor = fontColor
|
||||
|
||||
def getValue(self):
|
||||
return self.__value
|
||||
|
||||
def getRect(self):
|
||||
return self.__rect
|
||||
|
||||
def getGridLoc(self):
|
||||
return self.__gridLoc
|
||||
|
||||
def isReadOnly(self):
|
||||
return self.__readOnly
|
||||
|
||||
def highlight(self, color):
|
||||
if self.__readOnly is True:
|
||||
return
|
||||
self.__colorSquare.fill(color)
|
||||
self.__draw()
|
||||
|
||||
def unhighlight(self):
|
||||
self.__colorSquare.fill((255, 225, 255), None, pygame.BLEND_RGB_ADD)
|
||||
self.__draw()
|
||||
|
||||
def __draw(self):
|
||||
value = self.__value
|
||||
if self.__value == '-':
|
||||
value = ''
|
||||
font = pygame.font.Font(sys.path[0] + '/Roboto-Light.ttf', 24)
|
||||
text = font.render(str(value), 1, self.__fontColor)
|
||||
textpos = text.get_rect()
|
||||
textpos.centerx = self.__rect.centerx
|
||||
textpos.centery = self.__rect.centery
|
||||
self.__screen.blit(self.__colorSquare, self.__colorSquareRect)
|
||||
self.__screen.blit(text, textpos)
|
||||
|
||||
|
||||
class Sudoku:
|
||||
"""Represents the game's backend and logic"""
|
||||
|
||||
def __init__(self, puzzleFile, rpc_connection):
|
||||
self.__puzzleFile = puzzleFile
|
||||
self.__rpc_connection = rpc_connection
|
||||
self.startNewGame()
|
||||
|
||||
def startNewGame(self):
|
||||
self.__linePuzzle = self.__loadPuzzle(self.__puzzleFile)
|
||||
gridValues = self.lineToGrid(self.__linePuzzle)
|
||||
# prefill 0 timestamps for already known numbers
|
||||
timestampValues = self.prefill_timestamps(gridValues)
|
||||
board = PyGameBoard(self, (600, 400), gridValues, timestampValues)
|
||||
board.setValues(gridValues)
|
||||
|
||||
def __loadPuzzle(self, listName):
|
||||
self.__chosen_puzzle = random.choice(listName)
|
||||
puzzle = self.__rpc_connection.cclib("txidinfo", "17", '"%22' + self.__chosen_puzzle + '%22"')["unsolved"]
|
||||
print "Puzzle ID: " + self.__chosen_puzzle
|
||||
print "Reward amount: " + str(self.__rpc_connection.cclib("txidinfo", "17", '"%22' + self.__chosen_puzzle + '%22"')["amount"])
|
||||
ret = []
|
||||
linePuzzle = str(puzzle)
|
||||
for i in linePuzzle:
|
||||
ret.append(i)
|
||||
return ret
|
||||
|
||||
def gridToLine(self, grid):
|
||||
linePuzzle = ''
|
||||
for i in range(9):
|
||||
for j in range(9):
|
||||
linePuzzle += grid[i][j]
|
||||
return linePuzzle
|
||||
|
||||
def lineToGrid(self, linePuzzle):
|
||||
assert (len(linePuzzle) == 81)
|
||||
grid = []
|
||||
for i in xrange(0, 81, 9):
|
||||
grid.append(linePuzzle[i:i + 9])
|
||||
return grid
|
||||
|
||||
def getSolution(self):
|
||||
balance = self.__rpc_connection.cclibaddress("17")["mybalance"]
|
||||
print "Your balance: " + str(balance)
|
||||
|
||||
def __solve(self, linePuzzle):
|
||||
linePuzzle = ''.join(linePuzzle)
|
||||
i = linePuzzle.find('-')
|
||||
if i == -1:
|
||||
return linePuzzle
|
||||
|
||||
excluded_numbers = set()
|
||||
for j in range(81):
|
||||
if self.sameRow(i, j) or self.sameCol(i, j) or self.sameBlock(i, j):
|
||||
excluded_numbers.add(linePuzzle[j])
|
||||
|
||||
for m in '123456789':
|
||||
if m not in excluded_numbers:
|
||||
funcRet = self.__solve(linePuzzle[:i] + m + linePuzzle[i + 1:])
|
||||
if funcRet is not None:
|
||||
return funcRet
|
||||
|
||||
def prefill_timestamps(self, grid):
|
||||
timestamps = {}
|
||||
for i in range(9):
|
||||
for j in range(9):
|
||||
if grid[i][j] != '-':
|
||||
cell_num = 9 * i + ( j + 1 )
|
||||
timestamps[cell_num] = 0
|
||||
return timestamps
|
||||
|
||||
def sameRow(self, i, j):
|
||||
return (i / 9 == j / 9)
|
||||
|
||||
def sameCol(self, i, j):
|
||||
return (i - j) % 9 == 0
|
||||
|
||||
def sameBlock(self, i, j):
|
||||
return (i / 27 == j / 27 and i % 9 / 3 == j % 9 / 3)
|
||||
|
||||
def checkSolution(self, attemptGrid, timestampValues):
|
||||
# [%22<txid>%22,%22<solution>%22,t0,t1,t2,...]
|
||||
attemptLine = self.gridToLine(attemptGrid)
|
||||
|
||||
#print attemptLine
|
||||
#print timestampValues
|
||||
timestampsline = ""
|
||||
for timestamp in timestampValues.values():
|
||||
timestampsline += ","
|
||||
timestampsline += str(timestamp)
|
||||
arg_line = "[%22"+self.__chosen_puzzle+"%22,%22"+attemptLine+"%22"+timestampsline+"]"
|
||||
print arg_line
|
||||
try:
|
||||
solution_info = self.__rpc_connection.cclib("solution", "17", '"' + arg_line + '"')
|
||||
print solution_info
|
||||
solution_txid = self.__rpc_connection.sendrawtransaction(solution_info["hex"])
|
||||
print "Solution accepted!"
|
||||
print solution_txid
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print(solution_info)
|
||||
solution_txid = 'error'
|
||||
return solution_txid
|
||||
|
||||
def main():
|
||||
while True:
|
||||
# Assetchain hardcoded here
|
||||
chain = 'SUDOKU'
|
||||
try:
|
||||
print 'Welcome to the Komodo SudokuCC'
|
||||
rpc_connection = sudoku_kmdlib.def_credentials(chain)
|
||||
pending_puzzles = rpc_connection.cclib("pending", "17")["pending"]
|
||||
puzzle_list = []
|
||||
for puzzle in pending_puzzles:
|
||||
puzzle_list.append(puzzle["txid"])
|
||||
|
||||
except Exception as e:
|
||||
#print rpc_connection
|
||||
print e
|
||||
print 'Cant connect to SUDOKU Daemon! Please re-check if it up'
|
||||
sys.exit()
|
||||
else:
|
||||
print 'Succesfully connected!\n'
|
||||
break
|
||||
newGame = Sudoku(puzzle_list, rpc_connection)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
BIN
src/gui/komodoku/background.png
Normal file
BIN
src/gui/komodoku/background.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 301 KiB |
BIN
src/gui/komodoku/board.png
Normal file
BIN
src/gui/komodoku/board.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
41
src/gui/komodoku/sudoku_kmdlib.py
Normal file
41
src/gui/komodoku/sudoku_kmdlib.py
Normal file
@@ -0,0 +1,41 @@
|
||||
import platform
|
||||
import os
|
||||
import re
|
||||
import random
|
||||
from slickrpc import Proxy
|
||||
|
||||
|
||||
# define function that fetchs rpc creds from .conf
|
||||
def def_credentials(chain):
|
||||
rpcport ='';
|
||||
operating_system = platform.system()
|
||||
if operating_system == 'Darwin':
|
||||
ac_dir = os.environ['HOME'] + '/Library/Application Support/Komodo'
|
||||
elif operating_system == 'Linux':
|
||||
ac_dir = os.environ['HOME'] + '/.komodo'
|
||||
elif operating_system == 'Windows':
|
||||
ac_dir = '%s/komodo/' % os.environ['APPDATA']
|
||||
if chain == 'KMD':
|
||||
coin_config_file = str(ac_dir + '/komodo.conf')
|
||||
else:
|
||||
coin_config_file = str(ac_dir + '/' + chain + '/' + chain + '.conf')
|
||||
with open(coin_config_file, 'r') as f:
|
||||
for line in f:
|
||||
l = line.rstrip()
|
||||
if re.search('rpcuser', l):
|
||||
rpcuser = l.replace('rpcuser=', '')
|
||||
elif re.search('rpcpassword', l):
|
||||
rpcpassword = l.replace('rpcpassword=', '')
|
||||
elif re.search('rpcport', l):
|
||||
rpcport = l.replace('rpcport=', '')
|
||||
if len(rpcport) == 0:
|
||||
if chain == 'KMD':
|
||||
rpcport = 7771
|
||||
else:
|
||||
print("rpcport not in conf file, exiting")
|
||||
print("check "+coin_config_file)
|
||||
exit(1)
|
||||
|
||||
return(Proxy("http://%s:%s@127.0.0.1:%d"%(rpcuser, rpcpassword, int(rpcport))))
|
||||
|
||||
|
||||
@@ -35,8 +35,7 @@ CTransaction MakeImportCoinTransaction(const TxProof proof, const CTransaction b
|
||||
mtx.vin.push_back(CTxIn(COutPoint(burnTx.GetHash(), 10e8), CScript() << payload));
|
||||
mtx.vout = payouts;
|
||||
auto importData = E_MARSHAL(ss << proof; ss << burnTx);
|
||||
mtx.vout.insert(mtx.vout.begin(), CTxOut(0, CScript() << OP_RETURN << importData));
|
||||
|
||||
mtx.vout.push_back(CTxOut(0, CScript() << OP_RETURN << importData));
|
||||
if (nExpiryHeightOverride != 0)
|
||||
mtx.nExpiryHeight = nExpiryHeightOverride; //this is for construction of the tx used for validating importtx
|
||||
return CTransaction(mtx);
|
||||
@@ -53,29 +52,97 @@ CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymb
|
||||
return CTxOut(value, CScript() << OP_RETURN << opret);
|
||||
}
|
||||
|
||||
CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector<CTxOut> payouts,std::vector<uint8_t> rawproof,
|
||||
uint256 bindtxid,std::vector<CPubKey> publishers,std::vector<uint256> txids,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub)
|
||||
{
|
||||
std::vector<uint8_t> opret;
|
||||
opret = E_MARSHAL(ss << VARINT(targetCCid);
|
||||
ss << targetSymbol;
|
||||
ss << SerializeHash(payouts);
|
||||
ss << rawproof;
|
||||
ss << bindtxid;
|
||||
ss << publishers;
|
||||
ss << txids;
|
||||
ss << height;
|
||||
ss << burnvout;
|
||||
ss << rawburntx;
|
||||
ss << destpub);
|
||||
|
||||
return CTxOut(value, CScript() << OP_RETURN << opret);
|
||||
}
|
||||
|
||||
bool UnmarshalImportTx(const CTransaction &importTx, TxProof &proof, CTransaction &burnTx,
|
||||
CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector<CTxOut> payouts,std::vector<uint8_t> rawproof,std::string srcaddr,
|
||||
std::string receipt)
|
||||
{
|
||||
std::vector<uint8_t> opret;
|
||||
opret = E_MARSHAL(ss << VARINT(targetCCid);
|
||||
ss << targetSymbol;
|
||||
ss << SerializeHash(payouts);
|
||||
ss << rawproof;
|
||||
ss << srcaddr;
|
||||
ss << receipt);
|
||||
return CTxOut(value, CScript() << OP_RETURN << opret);
|
||||
}
|
||||
|
||||
|
||||
bool UnmarshalImportTx(const CTransaction importTx, TxProof &proof, CTransaction &burnTx,
|
||||
std::vector<CTxOut> &payouts)
|
||||
{
|
||||
std::vector<uint8_t> vData;
|
||||
GetOpReturnData(importTx.vout[0].scriptPubKey, vData);
|
||||
GetOpReturnData(importTx.vout[importTx.vout.size()-1].scriptPubKey, vData);
|
||||
if (importTx.vout.size() < 1) return false;
|
||||
payouts = std::vector<CTxOut>(importTx.vout.begin()+1, importTx.vout.end());
|
||||
payouts = std::vector<CTxOut>(importTx.vout.begin(), importTx.vout.end()-1);
|
||||
return importTx.vin.size() == 1 &&
|
||||
importTx.vin[0].scriptSig == (CScript() << E_MARSHAL(ss << EVAL_IMPORTCOIN)) &&
|
||||
E_UNMARSHAL(vData, ss >> proof; ss >> burnTx);
|
||||
}
|
||||
|
||||
|
||||
bool UnmarshalBurnTx(const CTransaction &burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash,std::vector<uint8_t>&rawproof)
|
||||
bool UnmarshalBurnTx(const CTransaction burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash,std::vector<uint8_t>&rawproof)
|
||||
{
|
||||
std::vector<uint8_t> burnOpret; uint32_t ccid = 0;
|
||||
std::vector<uint8_t> burnOpret; uint32_t ccid = 0; bool isEof=true;
|
||||
|
||||
if (burnTx.vout.size() == 0) return false;
|
||||
GetOpReturnData(burnTx.vout.back().scriptPubKey, burnOpret);
|
||||
return E_UNMARSHAL(burnOpret, ss >> VARINT(*targetCCid);
|
||||
ss >> targetSymbol;
|
||||
ss >> payoutsHash;
|
||||
ss >> rawproof);
|
||||
ss >> rawproof; isEof=ss.eof();) || !isEof;
|
||||
}
|
||||
|
||||
bool UnmarshalBurnTx(const CTransaction burnTx, std::string &srcaddr, std::string &receipt)
|
||||
{
|
||||
std::vector<uint8_t> burnOpret,rawproof; bool isEof=true;
|
||||
std::string targetSymbol; uint32_t targetCCid; uint256 payoutsHash;
|
||||
|
||||
if (burnTx.vout.size() == 0) return false;
|
||||
GetOpReturnData(burnTx.vout.back().scriptPubKey, burnOpret);
|
||||
return (E_UNMARSHAL(burnOpret, ss >> VARINT(targetCCid);
|
||||
ss >> targetSymbol;
|
||||
ss >> payoutsHash;
|
||||
ss >> rawproof;
|
||||
ss >> srcaddr;
|
||||
ss >> receipt));
|
||||
}
|
||||
|
||||
bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &bindtxid,std::vector<CPubKey> &publishers,std::vector<uint256> &txids,int32_t &height,int32_t &burnvout,std::string &rawburntx,CPubKey &destpub)
|
||||
{
|
||||
std::vector<uint8_t> burnOpret,rawproof; bool isEof=true;
|
||||
uint32_t targetCCid; uint256 payoutsHash; std::string targetSymbol;
|
||||
|
||||
if (burnTx.vout.size() == 0) return false;
|
||||
GetOpReturnData(burnTx.vout.back().scriptPubKey, burnOpret);
|
||||
return (E_UNMARSHAL(burnOpret, ss >> VARINT(targetCCid);
|
||||
ss >> targetSymbol;
|
||||
ss >> payoutsHash;
|
||||
ss >> rawproof;
|
||||
ss >> bindtxid;
|
||||
ss >> publishers;
|
||||
ss >> txids;
|
||||
ss >> height;
|
||||
ss >> burnvout;
|
||||
ss >> rawburntx;
|
||||
ss >> destpub));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -29,10 +29,15 @@ CTransaction MakeImportCoinTransaction(const TxProof proof,
|
||||
const CTransaction burnTx, const std::vector<CTxOut> payouts, uint32_t nExpiryHeightOverride = 0);
|
||||
|
||||
CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector<CTxOut> payouts,std::vector<uint8_t> rawproof);
|
||||
CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector<CTxOut> payouts,std::vector<uint8_t> rawproof,
|
||||
uint256 bindtxid,std::vector<CPubKey> publishers,std::vector<uint256>txids,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub);
|
||||
CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector<CTxOut> payouts,std::vector<uint8_t> rawproof,std::string srcaddr,
|
||||
std::string receipt);
|
||||
|
||||
bool UnmarshalBurnTx(const CTransaction &burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash,std::vector<uint8_t> &rawproof);
|
||||
bool UnmarshalImportTx(const CTransaction &importTx, TxProof &proof, CTransaction &burnTx,
|
||||
std::vector<CTxOut> &payouts);
|
||||
bool UnmarshalBurnTx(const CTransaction burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash,std::vector<uint8_t> &rawproof);
|
||||
bool UnmarshalBurnTx(const CTransaction burnTx, std::string &srcaddr, std::string &receipt);
|
||||
bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &bindtxid,std::vector<CPubKey> &publishers,std::vector<uint256> &txids,int32_t &height,int32_t &burnvout,std::string &rawburntx,CPubKey &destpub);
|
||||
bool UnmarshalImportTx(const CTransaction importTx, TxProof &proof, CTransaction &burnTx,std::vector<CTxOut> &payouts);
|
||||
|
||||
bool VerifyCoinImport(const CScript& scriptSig, TransactionSignatureChecker& checker, CValidationState &state);
|
||||
|
||||
|
||||
@@ -367,6 +367,7 @@ std::string HelpMessage(HelpMessageMode mode)
|
||||
strUsage += HelpMessageOpt("-blocknotify=<cmd>", _("Execute command when the best block changes (%s in cmd is replaced by block hash)"));
|
||||
strUsage += HelpMessageOpt("-checkblocks=<n>", strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), 288));
|
||||
strUsage += HelpMessageOpt("-checklevel=<n>", strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"), 3));
|
||||
strUsage += HelpMessageOpt("-clientname=<SomeName>", _("Full node client name, default 'MagicBean'"));
|
||||
strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), "komodo.conf"));
|
||||
if (mode == HMM_BITCOIND)
|
||||
{
|
||||
@@ -571,7 +572,6 @@ std::string HelpMessage(HelpMessageMode mode)
|
||||
strUsage += HelpMessageOpt("-ac_cclib", _("Cryptoconditions dynamicly loadable library"));
|
||||
strUsage += HelpMessageOpt("-ac_ccenable", _("Cryptoconditions to enable"));
|
||||
strUsage += HelpMessageOpt("-ac_ccactivate", _("Block height to enable Cryptoconditions"));
|
||||
strUsage += HelpMessageOpt("-ac_clientname", _("Full node client name, default 'MagicBean'"));
|
||||
strUsage += HelpMessageOpt("-ac_decay", _("Percentage of block reward decrease at each halving"));
|
||||
strUsage += HelpMessageOpt("-ac_end", _("Block height at which block rewards will end"));
|
||||
strUsage += HelpMessageOpt("-ac_eras", _("Block reward eras"));
|
||||
|
||||
10
src/komodo.h
10
src/komodo.h
@@ -836,16 +836,6 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block)
|
||||
int8_t numSN = numStakedNotaries(tmp_pubkeys,staked_era);
|
||||
UpdateNotaryAddrs(tmp_pubkeys,numSN);
|
||||
STAKED_ERA = staked_era;
|
||||
if ( NOTARYADDRS[0][0] != 0 && NOTARY_PUBKEY33[0] != 0 )
|
||||
{
|
||||
if ( (IS_STAKED_NOTARY= updateStakedNotary()) > -1 )
|
||||
{
|
||||
IS_KOMODO_NOTARY = 0;
|
||||
if ( MIN_RECV_SATS == -1 )
|
||||
MIN_RECV_SATS = 100000000;
|
||||
fprintf(stderr, "Staked Notary Protection Active! NotaryID.%d RADD.%s ERA.%d MIN_TX_VALUE.%lu \n",IS_STAKED_NOTARY,NOTARY_ADDRESS.c_str(),staked_era,MIN_RECV_SATS);
|
||||
}
|
||||
}
|
||||
lastStakedEra = staked_era;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,6 +201,9 @@ try_again:
|
||||
curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback
|
||||
curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL, 1L); // supposed to fix "Alarm clock" and long jump crash
|
||||
curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback
|
||||
//curl_easy_setopt(curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
||||
//curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, 2);
|
||||
|
||||
if ( strncmp(url,"https",5) == 0 )
|
||||
{
|
||||
curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0);
|
||||
@@ -247,13 +250,13 @@ try_again:
|
||||
numretries++;
|
||||
if ( specialcase != 0 )
|
||||
{
|
||||
printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res);
|
||||
fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res);
|
||||
free(s.ptr);
|
||||
return(0);
|
||||
}
|
||||
else if ( numretries >= 1 )
|
||||
{
|
||||
//printf("Maximum number of retries exceeded!\n");
|
||||
fprintf(stderr,"Maximum number of retries exceeded!\n");
|
||||
free(s.ptr);
|
||||
return(0);
|
||||
}
|
||||
@@ -1914,33 +1917,37 @@ uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector<int8_t> &Notar
|
||||
return(total);
|
||||
}
|
||||
|
||||
uint64_t komodo_checknotarypay(CBlock *pblock,int32_t height)
|
||||
bool GetNotarisationNotaries(uint8_t notarypubkeys[64][33], int8_t &numNN, const std::vector<CTxIn> &vin, std::vector<int8_t> &NotarisationNotaries)
|
||||
{
|
||||
std::vector<int8_t> NotarisationNotaries;
|
||||
uint32_t timestamp = pblock->nTime;
|
||||
int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0};
|
||||
numSN = komodo_notaries(notarypubkeys, height, timestamp);
|
||||
|
||||
// No point going further, no notaries can be paid.
|
||||
if ( notarypubkeys[0][0] == 0 )
|
||||
return(0);
|
||||
|
||||
uint8_t *script; int32_t scriptlen;
|
||||
// Loop over the notarisation and extract the position of the participating notaries in the array of pukeys for this era.
|
||||
BOOST_FOREACH(const CTxIn& txin, pblock->vtx[1].vin)
|
||||
if ( notarypubkeys[0][0] == 0 )
|
||||
return false;
|
||||
BOOST_FOREACH(const CTxIn& txin, vin)
|
||||
{
|
||||
uint256 hash; CTransaction tx1;
|
||||
if ( GetTransaction(txin.prevout.hash,tx1,hash,false) )
|
||||
{
|
||||
for (int8_t i = 0; i < numSN; i++)
|
||||
for (int8_t i = 0; i < numNN; i++)
|
||||
{
|
||||
script = (uint8_t *)&tx1.vout[txin.prevout.n].scriptPubKey[0];
|
||||
scriptlen = (int32_t)tx1.vout[txin.prevout.n].scriptPubKey.size();
|
||||
if ( scriptlen == 35 && script[0] == 33 && script[34] == OP_CHECKSIG && memcmp(script+1,notarypubkeys[i],33) == 0 )
|
||||
NotarisationNotaries.push_back(i);
|
||||
}
|
||||
}
|
||||
} else return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t komodo_checknotarypay(CBlock *pblock,int32_t height)
|
||||
{
|
||||
std::vector<int8_t> NotarisationNotaries; uint8_t *script; int32_t scriptlen;
|
||||
uint64_t timestamp = pblock->nTime;
|
||||
int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0};
|
||||
numSN = komodo_notaries(notarypubkeys, height, timestamp);
|
||||
if ( !GetNotarisationNotaries(notarypubkeys, numSN, pblock->vtx[1].vin, NotarisationNotaries) )
|
||||
return(0);
|
||||
|
||||
// check a notary didnt sign twice (this would be an invalid notarisation later on and cause problems)
|
||||
std::set<int> checkdupes( NotarisationNotaries.begin(), NotarisationNotaries.end() );
|
||||
if ( checkdupes.size() != NotarisationNotaries.size() ) {
|
||||
|
||||
@@ -37,20 +37,21 @@
|
||||
#define KOMODO_MAXNVALUE (((uint64_t)1 << 63) - 1)
|
||||
#define KOMODO_BIT63SET(x) ((x) & ((uint64_t)1 << 63))
|
||||
#define KOMODO_VALUETOOBIG(x) ((x) > (uint64_t)10000000001*COIN)
|
||||
#define PRICES_DAYWINDOW ((3600*24/ASSETCHAINS_BLOCKTIME) + 1)
|
||||
|
||||
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,ASSETCHAINS_BLOCKTIME;
|
||||
extern int32_t VERUS_BLOCK_POSUNITS, ASSETCHAINS_LWMAPOS, ASSETCHAINS_SAPLING, ASSETCHAINS_OVERWINTER;
|
||||
extern uint32_t ASSETCHAIN_INIT, ASSETCHAINS_MAGIC;
|
||||
extern int32_t VERUS_BLOCK_POSUNITS, ASSETCHAINS_LWMAPOS, ASSETCHAINS_SAPLING, ASSETCHAINS_OVERWINTER,ASSETCHAINS_BLOCKTIME;
|
||||
extern uint64_t ASSETCHAINS_SUPPLY, ASSETCHAINS_FOUNDERS_REWARD;
|
||||
|
||||
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,ASSETCHAINS_STAKED;
|
||||
extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_LASTERA;
|
||||
extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_LASTERA,ASSETCHAINS_CBOPRET;
|
||||
extern bool VERUS_MINTBLOCKS;
|
||||
extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[];
|
||||
extern const char *ASSETCHAINS_ALGORITHMS[];
|
||||
@@ -59,6 +60,7 @@ extern uint32_t ASSETCHAINS_VERUSHASH, ASSETCHAINS_VERUSHASHV1_1, ASSETCHAINS_NO
|
||||
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 std::vector<std::string> ASSETCHAINS_PRICES;
|
||||
|
||||
extern char ASSETCHAINS_SYMBOL[65];
|
||||
extern int32_t VERUS_BLOCK_POSUNITS, VERUS_CONSECUTIVE_POS_THRESHOLD, VERUS_NOPOS_THRESHHOLD;
|
||||
@@ -78,8 +80,10 @@ extern int32_t VERUS_MIN_STAKEAGE;
|
||||
extern std::string DONATION_PUBKEY;
|
||||
extern uint8_t ASSETCHAINS_PRIVATE;
|
||||
extern int32_t USE_EXTERNAL_PUBKEY;
|
||||
extern char NOTARYADDRS[64][64];
|
||||
int tx_height( const uint256 &hash );
|
||||
extern char NOTARYADDRS[64][36];
|
||||
extern uint8_t NUM_NOTARIES;
|
||||
extern std::vector<std::string> vWhiteListAddress;
|
||||
void komodo_netevent(std::vector<uint8_t> payload);
|
||||
int32_t komodo_priceind(char *symbol);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1547,3 +1547,982 @@ void komodo_passport_iteration()
|
||||
printf("READY for %s RPC calls at %u! done PASSPORT %s refid.%d\n",ASSETCHAINS_SYMBOL,(uint32_t)time(NULL),ASSETCHAINS_SYMBOL,refid);
|
||||
}
|
||||
}
|
||||
|
||||
extern std::vector<uint8_t> Mineropret; // opreturn data set by the data gathering code
|
||||
#define PRICES_MAXCHANGE (COIN / 100) // maximum acceptable change, set at 1%
|
||||
#define PRICES_SIZEBIT0 (sizeof(uint32_t) * 4) // 4 uint32_t unixtimestamp, BTCUSD, BTCGBP and BTCEUR
|
||||
#define KOMODO_LOCALPRICE_CACHESIZE 13
|
||||
#define KOMODO_MAXPRICES 2048
|
||||
|
||||
#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"CBCOINBASE",cmdstr,0,0,0)
|
||||
|
||||
const char *Cryptos[] = { "KMD", "ETH" }; // must be on binance (for now)
|
||||
// "LTC", "BCHABC", "XMR", "IOTA", "ZEC", "WAVES", "LSK", "DCR", "RVN", "DASH", "XEM", "BTS", "ICX", "HOT", "STEEM", "ENJ", "STRAT"
|
||||
const char *Forex[] =
|
||||
{ "BGN","NZD","ILS","RUB","CAD","PHP","CHF","AUD","JPY","TRY","HKD","MYR","HRK","CZK","IDR","DKK","NOK","HUF","GBP","MXN","THB","ISK","ZAR","BRL","SGD","PLN","INR","KRW","RON","CNY","SEK","EUR"
|
||||
}; // must be in ECB list
|
||||
|
||||
uint32_t PriceCache[KOMODO_LOCALPRICE_CACHESIZE][KOMODO_MAXPRICES];//4+sizeof(Cryptos)/sizeof(*Cryptos)+sizeof(Forex)/sizeof(*Forex)];
|
||||
int64_t PriceMult[KOMODO_MAXPRICES];
|
||||
int32_t komodo_cbopretsize(uint64_t flags);
|
||||
|
||||
void komodo_PriceCache_shift()
|
||||
{
|
||||
int32_t i;
|
||||
for (i=KOMODO_LOCALPRICE_CACHESIZE-1; i>0; i--)
|
||||
memcpy(PriceCache[i],PriceCache[i-1],sizeof(PriceCache[i]));
|
||||
memcpy(PriceCache[0],Mineropret.data(),Mineropret.size());
|
||||
}
|
||||
|
||||
// komodo_heightpricebits() extracts the price data in the coinbase for nHeight
|
||||
int32_t komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHeight)
|
||||
{
|
||||
CBlockIndex *pindex; CBlock block; CTransaction tx; int32_t numvouts; std::vector<uint8_t> vopret;
|
||||
if ( seedp != 0 )
|
||||
*seedp = 0;
|
||||
if ( (pindex= komodo_chainactive(nHeight)) != 0 )
|
||||
{
|
||||
if ( komodo_blockload(block,pindex) == 0 )
|
||||
{
|
||||
tx = block.vtx[0];
|
||||
numvouts = (int32_t)tx.vout.size();
|
||||
GetOpReturnData(tx.vout[numvouts-1].scriptPubKey,vopret);
|
||||
if ( vopret.size() >= PRICES_SIZEBIT0 )
|
||||
{
|
||||
if ( seedp != 0 )
|
||||
memcpy(seedp,&pindex->hashMerkleRoot,sizeof(*seedp));
|
||||
memcpy(heightbits,vopret.data(),vopret.size());
|
||||
return((int32_t)(vopret.size()/sizeof(uint32_t)));
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(stderr,"couldnt get pricebits for %d\n",nHeight);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
komodo_pricenew() is passed in a reference price, the change tolerance and the proposed price. it needs to return a clipped price if it is too big and also set a flag if it is at or above the limit
|
||||
*/
|
||||
uint32_t komodo_pricenew(char *maxflagp,uint32_t price,uint32_t refprice,int64_t tolerance)
|
||||
{
|
||||
uint64_t highprice,lowprice;
|
||||
if ( refprice < 2 )
|
||||
return(0);
|
||||
highprice = ((uint64_t)refprice * (COIN + tolerance)) / COIN; // calc highest acceptable price
|
||||
lowprice = ((uint64_t)refprice * (COIN - tolerance)) / COIN; // and lowest
|
||||
if ( highprice == refprice )
|
||||
highprice++;
|
||||
if ( lowprice == refprice )
|
||||
lowprice--;
|
||||
if ( price >= highprice )
|
||||
{
|
||||
//fprintf(stderr,"high %u vs h%llu l%llu tolerance.%llu\n",price,(long long)highprice,(long long)lowprice,(long long)tolerance);
|
||||
if ( price > highprice ) // return non-zero only if we violate the tolerance
|
||||
{
|
||||
*maxflagp = 2;
|
||||
return(highprice);
|
||||
}
|
||||
*maxflagp = 1;
|
||||
}
|
||||
else if ( price <= lowprice )
|
||||
{
|
||||
//fprintf(stderr,"low %u vs h%llu l%llu tolerance.%llu\n",price,(long long)highprice,(long long)lowprice,(long long)tolerance);
|
||||
if ( price < lowprice )
|
||||
{
|
||||
*maxflagp = -2;
|
||||
return(lowprice);
|
||||
}
|
||||
*maxflagp = -1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
// komodo_pricecmp() returns -1 if any of the prices are beyond the tolerance
|
||||
int32_t komodo_pricecmp(int32_t nHeight,int32_t n,char *maxflags,uint32_t *pricebitsA,uint32_t *pricebitsB,int64_t tolerance)
|
||||
{
|
||||
int32_t i; uint32_t newprice;
|
||||
for (i=1; i<n; i++)
|
||||
{
|
||||
if ( (newprice= komodo_pricenew(&maxflags[i],pricebitsA[i],pricebitsB[i],tolerance)) != 0 )
|
||||
{
|
||||
fprintf(stderr,"ht.%d i.%d/%d %u vs %u -> newprice.%u out of tolerance maxflag.%d\n",nHeight,i,n,pricebitsB[i],pricebitsA[i],newprice,maxflags[i]);
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
// komodo_priceclamp() clamps any price that is beyond tolerance
|
||||
int32_t komodo_priceclamp(int32_t n,uint32_t *pricebits,uint32_t *refprices,int64_t tolerance)
|
||||
{
|
||||
int32_t i; uint32_t newprice; char maxflags[KOMODO_MAXPRICES];
|
||||
memset(maxflags,0,sizeof(maxflags));
|
||||
for (i=1; i<n; i++)
|
||||
{
|
||||
if ( (newprice= komodo_pricenew(&maxflags[i],pricebits[i],refprices[i],tolerance)) != 0 )
|
||||
{
|
||||
fprintf(stderr,"priceclamped[%d of %d] %u vs %u -> %u\n",i,n,refprices[i],pricebits[i],newprice);
|
||||
pricebits[i] = newprice;
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
// komodo_mineropret() returns a valid pricedata to add to the coinbase opreturn for nHeight
|
||||
CScript komodo_mineropret(int32_t nHeight)
|
||||
{
|
||||
CScript opret; char maxflags[KOMODO_MAXPRICES]; uint32_t pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES]; int32_t maxflag,i,n,numzero=0;
|
||||
if ( Mineropret.size() >= PRICES_SIZEBIT0 )
|
||||
{
|
||||
n = (int32_t)(Mineropret.size() / sizeof(uint32_t));
|
||||
numzero = 1;
|
||||
while ( numzero > 0 )
|
||||
{
|
||||
memcpy(pricebits,Mineropret.data(),Mineropret.size());
|
||||
for (i=numzero=0; i<n; i++)
|
||||
if ( pricebits[i] == 0 )
|
||||
{
|
||||
fprintf(stderr,"%d ",i);
|
||||
numzero++;
|
||||
}
|
||||
if ( numzero != 0 )
|
||||
{
|
||||
fprintf(stderr," komodo_mineropret numzero.%d vs n.%d\n",numzero,n);
|
||||
komodo_cbopretupdate(1);
|
||||
sleep(61);
|
||||
}
|
||||
}
|
||||
if ( komodo_heightpricebits(0,prevbits,nHeight-1) > 0 )
|
||||
{
|
||||
memcpy(pricebits,Mineropret.data(),Mineropret.size());
|
||||
memset(maxflags,0,sizeof(maxflags));
|
||||
if ( komodo_pricecmp(0,n,maxflags,pricebits,prevbits,PRICES_MAXCHANGE) < 0 )
|
||||
{
|
||||
// if the new prices are outside tolerance, update Mineropret with clamped prices
|
||||
komodo_priceclamp(n,pricebits,prevbits,PRICES_MAXCHANGE);
|
||||
//fprintf(stderr,"update Mineropret to clamped prices\n");
|
||||
memcpy(Mineropret.data(),pricebits,Mineropret.size());
|
||||
}
|
||||
}
|
||||
int32_t i;
|
||||
for (i=0; i<Mineropret.size(); i++)
|
||||
fprintf(stderr,"%02x",Mineropret[i]);
|
||||
fprintf(stderr," <- Mineropret\n");
|
||||
return(opret << OP_RETURN << Mineropret);
|
||||
}
|
||||
return(opret);
|
||||
}
|
||||
|
||||
/*
|
||||
komodo_opretvalidate() is the entire price validation!
|
||||
it prints out some useful info for debugging, like the lag from current time and prev block and the prices encoded in the opreturn.
|
||||
|
||||
The only way komodo_opretvalidate() doesnt return an error is if maxflag is set or it is within tolerance of both the prior block and the local data. The local data validation only happens if it is a recent block and not a block from the past as the local node is only getting the current price data.
|
||||
|
||||
*/
|
||||
|
||||
struct komodo_extremeprice
|
||||
{
|
||||
uint256 blockhash;
|
||||
uint32_t pricebits,timestamp;
|
||||
int32_t height;
|
||||
int16_t dir,ind;
|
||||
} ExtremePrice;
|
||||
|
||||
void komodo_queuelocalprice(int32_t dir,int32_t height,uint32_t timestamp,uint256 blockhash,int32_t ind,uint32_t pricebits)
|
||||
{
|
||||
ExtremePrice.dir = dir;
|
||||
ExtremePrice.height = height;
|
||||
ExtremePrice.blockhash = blockhash;
|
||||
ExtremePrice.ind = ind;
|
||||
ExtremePrice.timestamp = timestamp;
|
||||
ExtremePrice.pricebits = pricebits;
|
||||
}
|
||||
|
||||
int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,int32_t nHeight,CScript scriptPubKey)
|
||||
{
|
||||
int32_t testchain_exemption = 0;
|
||||
std::vector<uint8_t> vopret; char maxflags[KOMODO_MAXPRICES]; uint256 bhash; double btcusd,btcgbp,btceur; uint32_t localbits[KOMODO_MAXPRICES],pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES],newprice; int32_t i,j,prevtime,maxflag,lag,lag2,lag3,n,errflag,iter; uint32_t now;
|
||||
now = (uint32_t)time(NULL);
|
||||
if ( ASSETCHAINS_CBOPRET != 0 && nHeight > 0 )
|
||||
{
|
||||
bhash = block->GetHash();
|
||||
GetOpReturnData(scriptPubKey,vopret);
|
||||
if ( vopret.size() >= PRICES_SIZEBIT0 )
|
||||
{
|
||||
n = (int32_t)(vopret.size() / sizeof(uint32_t));
|
||||
memcpy(pricebits,vopret.data(),Mineropret.size());
|
||||
memset(maxflags,0,sizeof(maxflags));
|
||||
if ( nHeight > 2 )
|
||||
{
|
||||
prevtime = previndex->nTime;
|
||||
lag = (int32_t)(now - pricebits[0]);
|
||||
lag2 = (int32_t)(pricebits[0] - prevtime);
|
||||
lag3 = (int32_t)(block->nTime - pricebits[0]);
|
||||
if ( lag < -60 ) // avoid data from future
|
||||
{
|
||||
fprintf(stderr,"A ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d\n",nHeight,now,prevtime,block->nTime,pricebits[0],lag,lag2,lag3);
|
||||
return(-1);
|
||||
}
|
||||
if ( lag2 < -60 ) //testchain_exemption ) // must be close to last block timestamp
|
||||
{
|
||||
fprintf(stderr,"B ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d vs %d cmp.%d\n",nHeight,now,prevtime,block->nTime,pricebits[0],lag,lag2,lag3,ASSETCHAINS_BLOCKTIME,lag2<-ASSETCHAINS_BLOCKTIME);
|
||||
if ( nHeight > testchain_exemption )
|
||||
return(-1);
|
||||
}
|
||||
if ( lag3 < -60 || lag3 > ASSETCHAINS_BLOCKTIME )
|
||||
{
|
||||
fprintf(stderr,"C ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d\n",nHeight,now,prevtime,block->nTime,pricebits[0],lag,lag2,lag3);
|
||||
if ( nHeight > testchain_exemption )
|
||||
return(-1);
|
||||
}
|
||||
btcusd = (double)pricebits[1]/10000;
|
||||
btcgbp = (double)pricebits[2]/10000;
|
||||
btceur = (double)pricebits[3]/10000;
|
||||
fprintf(stderr,"ht.%d: lag.%d %.4f USD, %.4f GBP, %.4f EUR, GBPUSD %.6f, EURUSD %.6f, EURGBP %.6f [%d]\n",nHeight,lag,btcusd,btcgbp,btceur,btcusd/btcgbp,btcusd/btceur,btcgbp/btceur,lag2);
|
||||
if ( komodo_heightpricebits(0,prevbits,nHeight-1) > 0 )
|
||||
{
|
||||
if ( nHeight < testchain_exemption )
|
||||
{
|
||||
for (i=0; i<n; i++)
|
||||
if ( pricebits[i] == 0 )
|
||||
pricebits[i] = prevbits[i];
|
||||
}
|
||||
if ( komodo_pricecmp(nHeight,n,maxflags,pricebits,prevbits,PRICES_MAXCHANGE) < 0 )
|
||||
{
|
||||
for (i=1; i<n; i++)
|
||||
fprintf(stderr,"%.4f ",(double)prevbits[i]/10000);
|
||||
fprintf(stderr," oldprices.%d\n",nHeight);
|
||||
for (i=1; i<n; i++)
|
||||
fprintf(stderr,"%.4f ",(double)pricebits[i]/10000);
|
||||
fprintf(stderr," newprices.%d\n",nHeight);
|
||||
|
||||
fprintf(stderr,"vs prev maxflag.%d cmp error\n",maxflag);
|
||||
return(-1);
|
||||
} // else this is the good case we hope to happen
|
||||
} else return(-1);
|
||||
if ( lag < ASSETCHAINS_BLOCKTIME && Mineropret.size() >= PRICES_SIZEBIT0 )
|
||||
{
|
||||
memcpy(localbits,Mineropret.data(),Mineropret.size());
|
||||
if ( nHeight < testchain_exemption )
|
||||
{
|
||||
for (i=0; i<n; i++)
|
||||
if ( localbits[i] == 0 )
|
||||
localbits[i] = prevbits[i];
|
||||
}
|
||||
for (iter=0; iter<2; iter++) // first iter should just refresh prices if out of tolerance
|
||||
{
|
||||
for (i=1; i<n; i++)
|
||||
{
|
||||
if ( (maxflag= maxflags[i]) != 0 && localbits[i] != 0 )
|
||||
{
|
||||
// make sure local price is moving in right direction
|
||||
fprintf(stderr,"maxflag.%d i.%d localbits.%u vs pricebits.%u prevbits.%u\n",maxflag,i,localbits[i],pricebits[i],prevbits[i]);
|
||||
if ( maxflag > 0 && localbits[i] < prevbits[i] )
|
||||
{
|
||||
if ( iter == 0 )
|
||||
break;
|
||||
// second iteration checks recent prices to see if within local volatility
|
||||
for (j=0; j<KOMODO_LOCALPRICE_CACHESIZE; j++)
|
||||
if ( PriceCache[j][i] >= prevbits[i] )
|
||||
{
|
||||
fprintf(stderr,"i.%d within recent localprices[%d] %u >= %u\n",i,j,PriceCache[j][i],prevbits[i]);
|
||||
break;
|
||||
}
|
||||
if ( j == KOMODO_LOCALPRICE_CACHESIZE )
|
||||
{
|
||||
komodo_queuelocalprice(1,nHeight,block->nTime,bhash,i,prevbits[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ( maxflag < 0 && localbits[i] > prevbits[i] )
|
||||
{
|
||||
if ( iter == 0 )
|
||||
break;
|
||||
for (j=0; j<KOMODO_LOCALPRICE_CACHESIZE; j++)
|
||||
if ( PriceCache[j][i] <= prevbits[i] )
|
||||
{
|
||||
fprintf(stderr,"i.%d within recent localprices[%d] %u <= prev %u\n",i,j,PriceCache[j][i],prevbits[i]);
|
||||
break;
|
||||
}
|
||||
if ( j == KOMODO_LOCALPRICE_CACHESIZE )
|
||||
{
|
||||
komodo_queuelocalprice(-1,nHeight,block->nTime,bhash,i,prevbits[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( i != n )
|
||||
{
|
||||
if ( iter == 0 )
|
||||
{
|
||||
fprintf(stderr,"force update prices\n");
|
||||
komodo_cbopretupdate(1);
|
||||
memcpy(localbits,Mineropret.data(),Mineropret.size());
|
||||
} else return(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( bhash == ExtremePrice.blockhash )
|
||||
{
|
||||
fprintf(stderr,"approved a previously extreme price based on new data ht.%d vs %u vs %u\n",ExtremePrice.height,ExtremePrice.timestamp,(uint32_t)block->nTime);
|
||||
memset(&ExtremePrice,0,sizeof(ExtremePrice));
|
||||
}
|
||||
return(0);
|
||||
} else fprintf(stderr,"wrong size %d vs %d, scriptPubKey size %d [%02x]\n",(int32_t)vopret.size(),(int32_t)Mineropret.size(),(int32_t)scriptPubKey.size(),scriptPubKey[0]);
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
char *nonportable_path(char *str)
|
||||
{
|
||||
int32_t i;
|
||||
for (i=0; str[i]!=0; i++)
|
||||
if ( str[i] == '/' )
|
||||
str[i] = '\\';
|
||||
return(str);
|
||||
}
|
||||
|
||||
char *portable_path(char *str)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return(nonportable_path(str));
|
||||
#else
|
||||
#ifdef __PNACL
|
||||
/*int32_t i,n;
|
||||
if ( str[0] == '/' )
|
||||
return(str);
|
||||
else
|
||||
{
|
||||
n = (int32_t)strlen(str);
|
||||
for (i=n; i>0; i--)
|
||||
str[i] = str[i-1];
|
||||
str[0] = '/';
|
||||
str[n+1] = 0;
|
||||
}*/
|
||||
#endif
|
||||
return(str);
|
||||
#endif
|
||||
}
|
||||
|
||||
void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep)
|
||||
{
|
||||
FILE *fp;
|
||||
long filesize,buflen = *allocsizep;
|
||||
uint8_t *buf = *bufp;
|
||||
*lenp = 0;
|
||||
if ( (fp= fopen(portable_path(fname),"rb")) != 0 )
|
||||
{
|
||||
fseek(fp,0,SEEK_END);
|
||||
filesize = ftell(fp);
|
||||
if ( filesize == 0 )
|
||||
{
|
||||
fclose(fp);
|
||||
*lenp = 0;
|
||||
//printf("loadfile null size.(%s)\n",fname);
|
||||
return(0);
|
||||
}
|
||||
if ( filesize > buflen )
|
||||
{
|
||||
*allocsizep = filesize;
|
||||
*bufp = buf = (uint8_t *)realloc(buf,(long)*allocsizep+64);
|
||||
}
|
||||
rewind(fp);
|
||||
if ( buf == 0 )
|
||||
printf("Null buf ???\n");
|
||||
else
|
||||
{
|
||||
if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize )
|
||||
printf("error reading filesize.%ld\n",(long)filesize);
|
||||
buf[filesize] = 0;
|
||||
}
|
||||
fclose(fp);
|
||||
*lenp = filesize;
|
||||
//printf("loaded.(%s)\n",buf);
|
||||
} //else printf("OS_loadfile couldnt load.(%s)\n",fname);
|
||||
return(buf);
|
||||
}
|
||||
|
||||
void *filestr(long *allocsizep,char *_fname)
|
||||
{
|
||||
long filesize = 0; char *fname,*buf = 0; void *retptr;
|
||||
*allocsizep = 0;
|
||||
fname = (char *)malloc(strlen(_fname)+1);
|
||||
strcpy(fname,_fname);
|
||||
retptr = loadfile(fname,(uint8_t **)&buf,&filesize,allocsizep);
|
||||
free(fname);
|
||||
return(retptr);
|
||||
}
|
||||
|
||||
cJSON *send_curl(char *url,char *fname)
|
||||
{
|
||||
long fsize; char curlstr[1024],*jsonstr; cJSON *json=0;
|
||||
sprintf(curlstr,"wget -q \"%s\" -O %s",url,fname);
|
||||
if ( system(curlstr) == 0 )
|
||||
{
|
||||
if ( (jsonstr= (char *)filestr((long *)&fsize,fname)) != 0 )
|
||||
{
|
||||
json = cJSON_Parse(jsonstr);
|
||||
free(jsonstr);
|
||||
}
|
||||
}
|
||||
return(json);
|
||||
}
|
||||
|
||||
// get_urljson just returns the JSON returned by the URL using issue_curl
|
||||
|
||||
|
||||
/*
|
||||
const char *Techstocks[] =
|
||||
{ "AAPL","ADBE","ADSK","AKAM","AMD","AMZN","ATVI","BB","CDW","CRM","CSCO","CYBR","DBX","EA","FB","GDDY","GOOG","GRMN","GSAT","HPQ","IBM","INFY","INTC","INTU","JNPR","MSFT","MSI","MU","MXL","NATI","NCR","NFLX","NTAP","NVDA","ORCL","PANW","PYPL","QCOM","RHT","S","SHOP","SNAP","SPOT","SYMC","SYNA","T","TRIP","TWTR","TXN","VMW","VOD","VRSN","VZ","WDC","XRX","YELP","YNDX","ZEN"
|
||||
};
|
||||
const char *Metals[] = { "XAU", "XAG", "XPT", "XPD", };
|
||||
|
||||
const char *Markets[] = { "DJIA", "SPX", "NDX", "VIX" };
|
||||
*/
|
||||
|
||||
cJSON *get_urljson(char *url)
|
||||
{
|
||||
char *jsonstr; cJSON *json = 0;
|
||||
if ( (jsonstr= issue_curl(url)) != 0 )
|
||||
{
|
||||
//fprintf(stderr,"(%s) -> (%s)\n",url,jsonstr);
|
||||
json = cJSON_Parse(jsonstr);
|
||||
free(jsonstr);
|
||||
}
|
||||
return(json);
|
||||
}
|
||||
|
||||
uint32_t get_stockprice(const char *symbol)
|
||||
{
|
||||
char url[512]; cJSON *json,*obj; uint32_t high,low,price = 0;
|
||||
sprintf(url,"https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=%s&interval=15min&apikey=%s",symbol,NOTARY_PUBKEY.data()+50);
|
||||
if ( (json= get_urljson(url)) != 0 )
|
||||
{
|
||||
if ( (obj= jobj(json,(char *)"Time Series (15min)")) != 0 )
|
||||
{
|
||||
high = jdouble(jitem(obj,0),(char *)"2. high")*10000 + 0.000049;
|
||||
low = jdouble(jitem(obj,0),(char *)"3. low")*10000 + 0.000049;
|
||||
price = (high + low) / 2;
|
||||
}
|
||||
free_json(json);
|
||||
}
|
||||
return(price);
|
||||
}
|
||||
|
||||
uint32_t get_dailyfx(uint32_t *prices)
|
||||
{
|
||||
//{"base":"USD","rates":{"BGN":1.74344803,"NZD":1.471652701,"ILS":3.6329113924,"RUB":65.1997682296,"CAD":1.3430201462,"USD":1.0,"PHP":52.8641469068,"CHF":0.9970582992,"AUD":1.4129078267,"JPY":110.6792654662,"TRY":5.6523444464,"HKD":7.8499732573,"MYR":4.0824567659,"HRK":6.6232840078,"CZK":22.9862720628,"IDR":14267.4986628633,"DKK":6.6551078624,"NOK":8.6806917454,"HUF":285.131039401,"GBP":0.7626582278,"MXN":19.4183455161,"THB":31.8702085933,"ISK":122.5708682475,"ZAR":14.7033339276,"BRL":3.9750401141,"SGD":1.3573720806,"PLN":3.8286682118,"INR":69.33187734,"KRW":1139.1602781244,"RON":4.2423783206,"CNY":6.7387234801,"SEK":9.3385630237,"EUR":0.8914244963},"date":"2019-03-28"}
|
||||
char url[512],*datestr; cJSON *json,*rates; int32_t i; uint32_t datenum=0,price = 0;
|
||||
sprintf(url,"https://api.openrates.io/latest?base=USD");
|
||||
if ( (json= send_curl(url,(char *)"dailyfx")) != 0 )
|
||||
{
|
||||
if ( (rates= jobj(json,(char *)"rates")) != 0 )
|
||||
{
|
||||
for (i=0; i<sizeof(Forex)/sizeof(*Forex); i++)
|
||||
{
|
||||
price = jdouble(rates,(char *)Forex[i]) * 10000 + 0.000049;
|
||||
fprintf(stderr,"(%s %.4f) ",Forex[i],(double)price/10000);
|
||||
prices[i] = price;
|
||||
}
|
||||
}
|
||||
if ( (datestr= jstr(json,(char *)"date")) != 0 )
|
||||
fprintf(stderr,"(%s)",datestr);
|
||||
fprintf(stderr,"\n");
|
||||
free_json(json);
|
||||
}
|
||||
return(datenum);
|
||||
}
|
||||
|
||||
uint32_t get_binanceprice(const char *symbol)
|
||||
{
|
||||
char url[512]; cJSON *json; uint32_t price = 0;
|
||||
sprintf(url,"https://api.binance.com/api/v1/ticker/price?symbol=%sBTC",symbol);
|
||||
if ( (json= send_curl(url,(char *)"bnbprice")) != 0 )
|
||||
{
|
||||
price = jdouble(json,(char *)"price")*SATOSHIDEN + 0.0000000049;
|
||||
free_json(json);
|
||||
}
|
||||
usleep(100000);
|
||||
return(price);
|
||||
}
|
||||
|
||||
int32_t get_cryptoprices(uint32_t *prices,const char *list[],int32_t n,std::vector<std::string> strvec)
|
||||
{
|
||||
int32_t i,errs=0; uint32_t price; char *symbol;
|
||||
for (i=0; i<n+strvec.size(); i++)
|
||||
{
|
||||
if ( i < n )
|
||||
symbol = (char *)list[i];
|
||||
else symbol = (char *)strvec[i - n].c_str();
|
||||
if ( (price= get_binanceprice(symbol)) == 0 )
|
||||
errs++;
|
||||
fprintf(stderr,"(%s %.8f) ",symbol,(double)price/SATOSHIDEN);
|
||||
prices[i] = price;
|
||||
}
|
||||
fprintf(stderr," errs.%d\n",errs);
|
||||
return(-errs);
|
||||
}
|
||||
|
||||
uint32_t get_currencyprice(const char *symbol)
|
||||
{
|
||||
char url[512]; cJSON *json,*obj; uint32_t price = 0;
|
||||
sprintf(url,"https://www.alphavantage.co/query?function=CURRENCY_EXCHANGE_RATE&from_currency=%s&to_currency=USD&apikey=%s",symbol,NOTARY_PUBKEY.data()+50);
|
||||
if ( (json= send_curl(url,(char *)"curldata")) != 0 )//get_urljson(url)) != 0 )
|
||||
{
|
||||
if ( (obj= jobj(jitem(json,0),0)) != 0 )
|
||||
price = jdouble(obj,(char *)"5. Exchange Rate")*10000 + 0.000049;
|
||||
free_json(json);
|
||||
}
|
||||
return(price);
|
||||
}
|
||||
|
||||
int32_t get_stocks(const char *list[],int32_t n)
|
||||
{
|
||||
int32_t i,errs=0; uint32_t price;
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
if ( (price= get_stockprice(list[i])) == 0 )
|
||||
errs++;
|
||||
else fprintf(stderr,"(%s %.4f) ",list[i],(double)price/10000);
|
||||
}
|
||||
fprintf(stderr," errs.%d\n",errs);
|
||||
return(-errs);
|
||||
}
|
||||
|
||||
// parse the coindesk specific data. yes, if this changes, it will require an update. However, regardless if the format from the data source changes, then the code that extracts it must be changed. One way to mitigate this is to have a large variety of data sources so that there is only a very remote chance that all of them are not available. Certainly the data gathering needs to be made more robust, but it doesnt really affect the proof of concept for the decentralized trustless oracle. The trustlessness is achieved by having all nodes get the oracle data.
|
||||
|
||||
int32_t get_btcusd(uint32_t pricebits[4])
|
||||
{
|
||||
cJSON *pjson,*bpi,*obj; char str[512]; double dbtcgbp,dbtcusd,dbtceur; uint64_t btcusd = 0,btcgbp = 0,btceur = 0;
|
||||
if ( (pjson= get_urljson((char *)"http://api.coindesk.com/v1/bpi/currentprice.json")) != 0 )
|
||||
{
|
||||
if ( (bpi= jobj(pjson,(char *)"bpi")) != 0 )
|
||||
{
|
||||
pricebits[0] = (uint32_t)time(NULL);
|
||||
if ( (obj= jobj(bpi,(char *)"USD")) != 0 )
|
||||
{
|
||||
btcusd = jdouble(obj,(char *)"rate_float") * SATOSHIDEN;
|
||||
pricebits[1] = ((btcusd / 10000) & 0xffffffff);
|
||||
}
|
||||
if ( (obj= jobj(bpi,(char *)"GBP")) != 0 )
|
||||
{
|
||||
btcgbp = jdouble(obj,(char *)"rate_float") * SATOSHIDEN;
|
||||
pricebits[2] = ((btcgbp / 10000) & 0xffffffff);
|
||||
}
|
||||
if ( (obj= jobj(bpi,(char *)"EUR")) != 0 )
|
||||
{
|
||||
btceur = jdouble(obj,(char *)"rate_float") * SATOSHIDEN;
|
||||
pricebits[3] = ((btceur / 10000) & 0xffffffff);
|
||||
}
|
||||
}
|
||||
free_json(pjson);
|
||||
dbtcusd = (double)pricebits[1]/10000;
|
||||
dbtcgbp = (double)pricebits[2]/10000;
|
||||
dbtceur = (double)pricebits[3]/10000;
|
||||
fprintf(stderr,"BTC/USD %.4f, BTC/GBP %.4f, BTC/EUR %.4f GBPUSD %.6f, EURUSD %.6f EURGBP %.6f\n",dbtcusd,dbtcgbp,dbtceur,dbtcusd/dbtcgbp,dbtcusd/dbtceur,dbtcgbp/dbtceur);
|
||||
return(0);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// komodo_cbopretupdate() obtains the external price data and encodes it into Mineropret, which will then be used by the miner and validation
|
||||
// save history, use new data to approve past rejection, where is the auto-reconsiderblock?
|
||||
|
||||
int32_t komodo_cbopretsize(uint64_t flags)
|
||||
{
|
||||
int32_t size = 0;
|
||||
if ( (ASSETCHAINS_CBOPRET & 1) != 0 )
|
||||
{
|
||||
size = PRICES_SIZEBIT0;
|
||||
if ( (ASSETCHAINS_CBOPRET & 2) != 0 )
|
||||
size += (sizeof(Forex)/sizeof(*Forex)) * sizeof(uint32_t);
|
||||
if ( (ASSETCHAINS_CBOPRET & 4) != 0 )
|
||||
size += (sizeof(Cryptos)/sizeof(*Cryptos) + ASSETCHAINS_PRICES.size())*sizeof(uint32_t);
|
||||
}
|
||||
return(size);
|
||||
}
|
||||
|
||||
void komodo_cbopretupdate(int32_t forceflag)
|
||||
{
|
||||
static uint32_t lasttime,lastcrypto,lastbtc,pending;
|
||||
static uint32_t pricebits[4],cryptoprices[KOMODO_MAXPRICES],forexprices[sizeof(Forex)/sizeof(*Forex)];
|
||||
int32_t size; uint32_t flags=0,now; CBlockIndex *pindex;
|
||||
if ( forceflag != 0 && pending != 0 )
|
||||
{
|
||||
while ( pending != 0 )
|
||||
fprintf(stderr,"pricewait "), sleep(1);
|
||||
return;
|
||||
}
|
||||
pending = 1;
|
||||
now = (uint32_t)time(NULL);
|
||||
if ( (ASSETCHAINS_CBOPRET & 1) != 0 )
|
||||
{
|
||||
//if ( komodo_nextheight() > 333 ) // for debug only!
|
||||
// ASSETCHAINS_CBOPRET = 7;
|
||||
size = komodo_cbopretsize(ASSETCHAINS_CBOPRET);
|
||||
if ( Mineropret.size() < size )
|
||||
Mineropret.resize(size);
|
||||
size = PRICES_SIZEBIT0;
|
||||
if ( (forceflag != 0 || now > lastbtc+120) && get_btcusd(pricebits) == 0 )
|
||||
{
|
||||
if ( flags == 0 )
|
||||
komodo_PriceCache_shift();
|
||||
memcpy(PriceCache[0],pricebits,PRICES_SIZEBIT0);
|
||||
flags |= 1;
|
||||
}
|
||||
if ( (ASSETCHAINS_CBOPRET & 2) != 0 )
|
||||
{
|
||||
if ( now > lasttime+3600*5 || forexprices[0] == 0 ) // cant assume timestamp is valid for forex price as it is a daily weekday changing thing anyway.
|
||||
{
|
||||
get_dailyfx(forexprices);
|
||||
if ( flags == 0 )
|
||||
komodo_PriceCache_shift();
|
||||
flags |= 2;
|
||||
memcpy(&PriceCache[0][size/sizeof(uint32_t)],forexprices,sizeof(forexprices));
|
||||
}
|
||||
size += (sizeof(Forex)/sizeof(*Forex)) * sizeof(uint32_t);
|
||||
}
|
||||
if ( (ASSETCHAINS_CBOPRET & 4) != 0 )
|
||||
{
|
||||
if ( forceflag != 0 || flags != 0 )
|
||||
{
|
||||
get_cryptoprices(cryptoprices,Cryptos,(int32_t)(sizeof(Cryptos)/sizeof(*Cryptos)),ASSETCHAINS_PRICES);
|
||||
if ( flags == 0 )
|
||||
komodo_PriceCache_shift();
|
||||
memcpy(&PriceCache[0][size/sizeof(uint32_t)],cryptoprices,(sizeof(Cryptos)/sizeof(*Cryptos)+ASSETCHAINS_PRICES.size()) * sizeof(uint32_t));
|
||||
flags |= 4; // very rarely we can see flags == 6 case
|
||||
}
|
||||
size += (sizeof(Cryptos)/sizeof(*Cryptos)+ASSETCHAINS_PRICES.size()) * sizeof(uint32_t);
|
||||
}
|
||||
if ( flags != 0 )
|
||||
{
|
||||
now = (uint32_t)time(NULL);
|
||||
if ( (flags & 1) != 0 )
|
||||
lastbtc = now;
|
||||
if ( (flags & 2) != 0 )
|
||||
lasttime = now;
|
||||
if ( (flags & 4) != 0 )
|
||||
lastcrypto = now;
|
||||
memcpy(Mineropret.data(),PriceCache[0],size);
|
||||
if ( ExtremePrice.dir != 0 && ExtremePrice.ind > 0 && ExtremePrice.ind < size/sizeof(uint32_t) && now < ExtremePrice.timestamp+3600 )
|
||||
{
|
||||
if ( (ExtremePrice.dir > 0 && PriceCache[0][ExtremePrice.ind] >= ExtremePrice.pricebits) || (ExtremePrice.dir < 0 && PriceCache[0][ExtremePrice.ind] <= ExtremePrice.pricebits) )
|
||||
{
|
||||
fprintf(stderr,"future price is close enough to allow approving previously rejected block ind.%d %u vs %u\n",ExtremePrice.ind,PriceCache[0][ExtremePrice.ind],ExtremePrice.pricebits);
|
||||
if ( (pindex= komodo_blockindex(ExtremePrice.blockhash)) != 0 )
|
||||
pindex->nStatus &= ~BLOCK_FAILED_MASK;
|
||||
else fprintf(stderr,"couldnt find block.%s\n",ExtremePrice.blockhash.GetHex().c_str());
|
||||
}
|
||||
}
|
||||
// high volatility still strands nodes so we need to check new prices to approve a stuck block
|
||||
// scan list of stuck blocks (one?) and auto reconsiderblock if it changed state
|
||||
|
||||
//int32_t i; for (i=0; i<Mineropret.size(); i++)
|
||||
// fprintf(stderr,"%02x",Mineropret[i]);
|
||||
//fprintf(stderr," <- set Mineropret[%d] size.%d %ld\n",(int32_t)Mineropret.size(),size,sizeof(PriceCache[0]));
|
||||
}
|
||||
/*
|
||||
if ( (ASSETCHAINS_CBOPRET & 4) != 0 )
|
||||
{
|
||||
get_currencies(Metals,(int32_t)(sizeof(Metals)/sizeof(*Metals)));
|
||||
}
|
||||
if ( (ASSETCHAINS_CBOPRET & 32) != 0 )
|
||||
{
|
||||
get_stocks(Markets,(int32_t)(sizeof(Markets)/sizeof(*Markets)));
|
||||
}
|
||||
if ( (ASSETCHAINS_CBOPRET & 64) != 0 )
|
||||
{
|
||||
get_stocks(Techstocks,(int32_t)(sizeof(Techstocks)/sizeof(*Techstocks)));
|
||||
}*/
|
||||
}
|
||||
pending = 0;
|
||||
}
|
||||
|
||||
int64_t komodo_pricemult(int32_t ind)
|
||||
{
|
||||
int32_t i,j;
|
||||
if ( (ASSETCHAINS_CBOPRET & 1) != 0 && ind < KOMODO_MAXPRICES )
|
||||
{
|
||||
if ( PriceMult[0] == 0 )
|
||||
{
|
||||
for (i=0; i<4; i++)
|
||||
PriceMult[i] = 10000;
|
||||
if ( (ASSETCHAINS_CBOPRET & 2) != 0 )
|
||||
{
|
||||
for (j=0; j<sizeof(Forex)/sizeof(*Forex); j++)
|
||||
PriceMult[i++] = 10000;
|
||||
}
|
||||
if ( (ASSETCHAINS_CBOPRET & 4) != 0 )
|
||||
{
|
||||
for (j=0; j<sizeof(Cryptos)/sizeof(*Cryptos)+ASSETCHAINS_PRICES.size(); j++)
|
||||
PriceMult[i++] = 1;
|
||||
}
|
||||
}
|
||||
return(PriceMult[ind]);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
char *komodo_pricename(char *name,int32_t ind)
|
||||
{
|
||||
strcpy(name,"error");
|
||||
if ( (ASSETCHAINS_CBOPRET & 1) != 0 && ind < KOMODO_MAXPRICES )
|
||||
{
|
||||
if ( ind < 4 )
|
||||
{
|
||||
switch ( ind )
|
||||
{
|
||||
case 0: strcpy(name,"timestamp"); break;
|
||||
case 1: strcpy(name,"BTCUSD"); break;
|
||||
case 2: strcpy(name,"BTCGBP"); break;
|
||||
case 3: strcpy(name,"BTCEUR"); break;
|
||||
default: return(0); break;
|
||||
}
|
||||
return(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
ind -= 4;
|
||||
if ( (ASSETCHAINS_CBOPRET & 2) != 0 )
|
||||
{
|
||||
if ( ind < 0 )
|
||||
return(0);
|
||||
if ( ind < sizeof(Forex)/sizeof(*Forex) )
|
||||
{
|
||||
name[0] = 'U', name[1] = 'S', name[2] = 'D';
|
||||
strcpy(name+3,Forex[ind]);
|
||||
return(name);
|
||||
} else ind -= sizeof(Forex)/sizeof(*Forex);
|
||||
}
|
||||
if ( (ASSETCHAINS_CBOPRET & 4) != 0 )
|
||||
{
|
||||
if ( ind < 0 )
|
||||
return(0);
|
||||
if ( ind < sizeof(Cryptos)/sizeof(*Cryptos) + ASSETCHAINS_PRICES.size() )
|
||||
{
|
||||
if ( ind < sizeof(Cryptos)/sizeof(*Cryptos) )
|
||||
strcpy(name,Cryptos[ind]);
|
||||
else
|
||||
{
|
||||
ind -= (sizeof(Cryptos)/sizeof(*Cryptos));
|
||||
strcpy(name,ASSETCHAINS_PRICES[ind].c_str());
|
||||
}
|
||||
strcat(name,"BTC");
|
||||
return(name);
|
||||
} else ind -= (sizeof(Cryptos)/sizeof(*Cryptos) + ASSETCHAINS_PRICES.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t komodo_priceind(char *symbol)
|
||||
{
|
||||
char name[65]; int32_t i,n = (int32_t)(komodo_cbopretsize(ASSETCHAINS_CBOPRET) / sizeof(uint32_t));
|
||||
for (i=1; i<n; i++)
|
||||
{
|
||||
komodo_pricename(name,i);
|
||||
if ( strcmp(name,symbol) == 0 )
|
||||
return(i);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int32_t rawskip,uint32_t *nonzprices,int32_t smoothwidth)
|
||||
{
|
||||
int32_t i,j,k,n,iter,correlation,maxcorrelation=0; int64_t firstprice,price,sum,den,mult,refprice,lowprice,highprice;
|
||||
if ( PRICES_DAYWINDOW < 2 || ind >= KOMODO_MAXPRICES )
|
||||
return(-1);
|
||||
mult = PriceMult[ind];
|
||||
if ( nonzprices != 0 )
|
||||
memset(nonzprices,0,sizeof(*nonzprices)*PRICES_DAYWINDOW);
|
||||
for (iter=0; iter<PRICES_DAYWINDOW; iter++)
|
||||
{
|
||||
correlation = 0;
|
||||
i = (iter + seed) % PRICES_DAYWINDOW;
|
||||
refprice = rawprices[i*rawskip];
|
||||
highprice = (refprice * (COIN + PRICES_MAXCHANGE*5)) / COIN;
|
||||
lowprice = (refprice * (COIN - PRICES_MAXCHANGE*5)) / COIN;
|
||||
if ( highprice == refprice )
|
||||
highprice++;
|
||||
if ( lowprice == refprice )
|
||||
lowprice--;
|
||||
sum = 0;
|
||||
//fprintf(stderr,"firsti.%d: ",i);
|
||||
for (j=0; j<PRICES_DAYWINDOW; j++,i++)
|
||||
{
|
||||
if ( i >= PRICES_DAYWINDOW )
|
||||
i = 0;
|
||||
if ( (price= rawprices[i*rawskip]) == 0 )
|
||||
{
|
||||
fprintf(stderr,"null rawprice.[%d]\n",i);
|
||||
return(-1);
|
||||
}
|
||||
if ( price >= lowprice && price <= highprice )
|
||||
{
|
||||
//fprintf(stderr,"%.1f ",(double)price/10000);
|
||||
sum += price;
|
||||
correlation++;
|
||||
if ( correlation > (PRICES_DAYWINDOW>>1) )
|
||||
{
|
||||
if ( nonzprices == 0 )
|
||||
return(refprice * mult);
|
||||
//fprintf(stderr,"-> %.4f\n",(double)sum*mult/correlation);
|
||||
//return(sum*mult/correlation);
|
||||
n = 0;
|
||||
i = (iter + seed) % PRICES_DAYWINDOW;
|
||||
for (k=0; k<PRICES_DAYWINDOW; k++,i++)
|
||||
{
|
||||
if ( i >= PRICES_DAYWINDOW )
|
||||
i = 0;
|
||||
if ( n > (PRICES_DAYWINDOW>>1) )
|
||||
nonzprices[i] = 0;
|
||||
else
|
||||
{
|
||||
price = rawprices[i*rawskip];
|
||||
if ( price < lowprice || price > highprice )
|
||||
nonzprices[i] = 0;
|
||||
else
|
||||
{
|
||||
nonzprices[i] = price;
|
||||
//fprintf(stderr,"(%d %u) ",i,rawprices[i*rawskip]);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
//fprintf(stderr,"ind.%d iter.%d j.%d i.%d n.%d correlation.%d ref %llu -> %llu\n",ind,iter,j,i,n,correlation,(long long)refprice,(long long)sum/correlation);
|
||||
if ( n != correlation )
|
||||
return(-1);
|
||||
sum = den = n = 0;
|
||||
for (i=0; i<PRICES_DAYWINDOW; i++)
|
||||
if ( nonzprices[i] != 0 )
|
||||
break;
|
||||
firstprice = nonzprices[i];
|
||||
//fprintf(stderr,"firsti.%d: ",i);
|
||||
for (i=0; i<PRICES_DAYWINDOW; i++)
|
||||
{
|
||||
if ( (price= nonzprices[i]) != 0 )
|
||||
{
|
||||
den += (PRICES_DAYWINDOW - i);
|
||||
sum += ((PRICES_DAYWINDOW - i) * (price + firstprice*4)) / 5;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
if ( n != correlation || sum == 0 || den == 0 )
|
||||
{
|
||||
fprintf(stderr,"seed.%llu n.%d vs correlation.%d sum %llu, den %llu\n",(long long)seed,n,correlation,(long long)sum,(long long)den);
|
||||
return(-1);
|
||||
}
|
||||
//fprintf(stderr,"firstprice.%llu weighted -> %.8f\n",(long long)firstprice,((double)(sum*mult) / den) / COIN);
|
||||
return((sum * mult) / den);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( correlation > maxcorrelation )
|
||||
maxcorrelation = correlation;
|
||||
}
|
||||
fprintf(stderr,"ind.%d iter.%d maxcorrelation.%d ref.%llu high.%llu low.%llu\n",ind,iter,maxcorrelation,(long long)refprice,(long long)highprice,(long long)lowprice);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int64_t _pairave64(int64_t valA,int64_t valB)
|
||||
{
|
||||
if ( valA != 0 && valB != 0 )
|
||||
return((valA + valB) / 2);
|
||||
else if ( valA != 0 ) return(valA);
|
||||
else return(valB);
|
||||
}
|
||||
|
||||
int64_t _pairdiff64(register int64_t valA,register int64_t valB)
|
||||
{
|
||||
if ( valA != 0 && valB != 0 )
|
||||
return(valA - valB);
|
||||
else return(0);
|
||||
}
|
||||
|
||||
int64_t balanced_ave64(int64_t buf[],int32_t i,int32_t width)
|
||||
{
|
||||
register int32_t nonz,j; register int64_t sum,price;
|
||||
nonz = 0;
|
||||
sum = 0;
|
||||
for (j=-width; j<=width; j++)
|
||||
{
|
||||
price = buf[i + j];
|
||||
if ( price != 0 )
|
||||
{
|
||||
sum += price;
|
||||
nonz++;
|
||||
}
|
||||
}
|
||||
if ( nonz != 0 )
|
||||
sum /= nonz;
|
||||
return(sum);
|
||||
}
|
||||
|
||||
void buf_trioave64(int64_t dest[],int64_t src[],int32_t n)
|
||||
{
|
||||
register int32_t i,j,width = 3;
|
||||
for (i=0; i<128; i++)
|
||||
src[i] = 0;
|
||||
//for (i=n-width-1; i>width; i--)
|
||||
// dest[i] = balanced_ave(src,i,width);
|
||||
//for (i=width; i>0; i--)
|
||||
// dest[i] = balanced_ave(src,i,i);
|
||||
for (i=1; i<width; i++)
|
||||
dest[i] = balanced_ave64(src,i,i);
|
||||
for (i=width; i<n-width; i++)
|
||||
dest[i] = balanced_ave64(src,i,width);
|
||||
dest[0] = _pairave64(dest[0],dest[1] - _pairdiff64(dest[2],dest[1]));
|
||||
j = width-1;
|
||||
for (i=n-width; i<n-1; i++,j--)
|
||||
dest[i] = balanced_ave64(src,i,j);
|
||||
if ( dest[n-3] != 0. && dest[n-2] != 0. )
|
||||
dest[n-1] = ((2 * dest[n-2]) - dest[n-3]);
|
||||
else dest[n-1] = 0;
|
||||
}
|
||||
|
||||
void smooth64(int64_t dest[],int64_t src[],int32_t width,int32_t smoothiters)
|
||||
{
|
||||
int64_t smoothbufA[1024],smoothbufB[1024]; int32_t i;
|
||||
if ( width < sizeof(smoothbufA)/sizeof(*smoothbufA) )
|
||||
{
|
||||
buf_trioave64(smoothbufA,src,width);
|
||||
for (i=0; i<smoothiters; i++)
|
||||
{
|
||||
buf_trioave64(smoothbufB,smoothbufA,width);
|
||||
buf_trioave64(smoothbufA,smoothbufB,width);
|
||||
}
|
||||
buf_trioave64(dest,smoothbufA,width);
|
||||
} else memcpy(dest,src,width*sizeof(*dest));
|
||||
}
|
||||
|
||||
int64_t komodo_pricesmoothed(int64_t *correlated,int32_t cskip,int64_t *rawprices,int32_t numprices)
|
||||
{
|
||||
//const int64_t coeffs[7] = { -2, 0, 18, 32, 18, 0, -2 };
|
||||
int32_t i; int64_t sum=0,nonzprice,price;
|
||||
if ( PRICES_DAYWINDOW < 2 )
|
||||
return(0);
|
||||
for (i=0; i<PRICES_DAYWINDOW; i++)
|
||||
{
|
||||
if ( (nonzprice= correlated[i*cskip]) != 0 )
|
||||
break;
|
||||
}
|
||||
if ( nonzprice == 0 )
|
||||
return(-1);
|
||||
for (i=0; i<PRICES_DAYWINDOW; i++)
|
||||
{
|
||||
if ( (price= correlated[i*cskip]) != 0 )
|
||||
nonzprice = price;
|
||||
//correlated2[i] = nonzprice / PRICES_DAYWINDOW; // reduce precision
|
||||
sum += nonzprice;
|
||||
}
|
||||
price = sum / PRICES_DAYWINDOW;
|
||||
// improve smoothing with correlated2 processing
|
||||
// price = smooth(correlated2,PRICES_DAYWINDOW,price/daywindow) * PRICES_DAYWINDOW;
|
||||
return(price);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,11 +47,14 @@ unsigned int WITNESS_CACHE_SIZE = _COINBASE_MATURITY+10;
|
||||
|
||||
int32_t KOMODO_MININGTHREADS = -1,IS_KOMODO_NOTARY,IS_STAKED_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE,KOMODO_PAX,KOMODO_EXCHANGEWALLET,KOMODO_REWIND,STAKED_ERA,KOMODO_CONNECTING = -1,KOMODO_DEALERNODE,KOMODO_EXTRASATOSHI,ASSETCHAINS_FOUNDERS;
|
||||
int32_t KOMODO_INSYNC,KOMODO_LASTMINED,prevKOMODO_LASTMINED,KOMODO_CCACTIVATE,JUMBLR_PAUSE = 1;
|
||||
std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY,ASSETCHAINS_SCRIPTPUB,NOTARY_ADDRESS,WHITELIST_ADDRESS,ASSETCHAINS_SELFIMPORT,ASSETCHAINS_CCLIB;
|
||||
uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEYHASH[20],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW,NUM_NOTARIES,ASSETCHAINS_MARMARA;
|
||||
std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY,ASSETCHAINS_SCRIPTPUB,NOTARY_ADDRESS,ASSETCHAINS_SELFIMPORT,ASSETCHAINS_CCLIB;
|
||||
uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEYHASH[20],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW,ASSETCHAINS_MARMARA;
|
||||
bool VERUS_MINTBLOCKS;
|
||||
std::vector<uint8_t> Mineropret;
|
||||
std::vector<std::string> vWhiteListAddress;
|
||||
char NOTARYADDRS[64][64];
|
||||
|
||||
char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],ASSETCHAINS_USERPASS[4096],NOTARYADDRS[64][36];
|
||||
char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],ASSETCHAINS_USERPASS[4096];
|
||||
uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,ASSETCHAINS_BEAMPORT,ASSETCHAINS_CODAPORT;
|
||||
uint32_t ASSETCHAIN_INIT,ASSETCHAINS_CC,KOMODO_STOPAT,KOMODO_DPOWCONFS = 1,STAKING_MIN_DIFF;
|
||||
uint32_t ASSETCHAINS_MAGIC = 2387029918;
|
||||
@@ -66,11 +69,12 @@ int64_t MAX_MONEY = 200000000 * 100000000LL;
|
||||
// spec will use an op_return with CLTV at front and anything after |OP_RETURN|PUSH of rest|OPRETTYPE_TIMELOCK|script|
|
||||
#define _ASSETCHAINS_TIMELOCKOFF 0xffffffffffffffff
|
||||
uint64_t ASSETCHAINS_TIMELOCKGTE = _ASSETCHAINS_TIMELOCKOFF;
|
||||
uint64_t ASSETCHAINS_TIMEUNLOCKFROM = 0, ASSETCHAINS_TIMEUNLOCKTO = 0;
|
||||
uint64_t ASSETCHAINS_TIMEUNLOCKFROM = 0, ASSETCHAINS_TIMEUNLOCKTO = 0,ASSETCHAINS_CBOPRET=0;
|
||||
|
||||
uint64_t ASSETCHAINS_LASTERA = 1;
|
||||
uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_DECAY[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS];
|
||||
uint8_t ASSETCHAINS_CCDISABLES[256];
|
||||
std::vector<std::string> ASSETCHAINS_PRICES;
|
||||
|
||||
#define _ASSETCHAINS_EQUIHASH 0
|
||||
uint32_t ASSETCHAINS_NUMALGOS = 3;
|
||||
@@ -97,7 +101,7 @@ int32_t ASSETCHAINS_OVERWINTER = -1;
|
||||
|
||||
uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE;
|
||||
int32_t ASSETCHAINS_STAKED;
|
||||
uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY = 10,MIN_RECV_SATS,ASSETCHAINS_FOUNDERS_REWARD;
|
||||
uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY = 10,ASSETCHAINS_FOUNDERS_REWARD;
|
||||
|
||||
uint32_t KOMODO_INITDONE;
|
||||
char KMDUSERPASS[8192+512+1],BTCUSERPASS[8192]; uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771;
|
||||
|
||||
@@ -1664,19 +1664,19 @@ uint64_t komodo_ac_block_subsidy(int nHeight)
|
||||
}
|
||||
|
||||
extern int64_t MAX_MONEY;
|
||||
void komodo_cbopretupdate(int32_t forceflag);
|
||||
void SplitStr(const std::string& strVal, std::vector<std::string> &outVals);
|
||||
|
||||
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=0,baseid,len,n,extralen = 0; uint64_t ccenables[256];
|
||||
std::string name,addn,hexstr,symbol; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[8192],disablebits[32],*extraptr=0; FILE *fp; uint64_t val; uint16_t port; int32_t i,nonz=0,baseid,len,n,extralen = 0; uint64_t ccenables[256];
|
||||
IS_KOMODO_NOTARY = GetBoolArg("-notary", false);
|
||||
IS_STAKED_NOTARY = GetArg("-stakednotary", -1);
|
||||
if ( IS_STAKED_NOTARY != -1 && IS_KOMODO_NOTARY == true ) {
|
||||
fprintf(stderr, "Cannot be STAKED and KMD notary at the same time!\n");
|
||||
exit(0);
|
||||
}
|
||||
MIN_RECV_SATS = GetArg("-mintxvalue",-1);
|
||||
WHITELIST_ADDRESS = GetArg("-whitelistaddress","");
|
||||
memset(ccenables,0,sizeof(ccenables));
|
||||
memset(disablebits,0,sizeof(disablebits));
|
||||
if ( GetBoolArg("-gen", false) != 0 )
|
||||
@@ -1733,7 +1733,7 @@ void komodo_args(char *argv0)
|
||||
{
|
||||
printf("KOMODO_REWIND %d\n",KOMODO_REWIND);
|
||||
}
|
||||
if ( name.c_str()[0] != 0 )
|
||||
if ( name.c_str()[0] != 0 )
|
||||
{
|
||||
std::string selectedAlgo = GetArg("-ac_algo", std::string(ASSETCHAINS_ALGORITHMS[0]));
|
||||
|
||||
@@ -1810,6 +1810,23 @@ void komodo_args(char *argv0)
|
||||
ASSETCHAINS_BEAMPORT = GetArg("-ac_beam",0);
|
||||
ASSETCHAINS_CODAPORT = GetArg("-ac_coda",0);
|
||||
ASSETCHAINS_MARMARA = GetArg("-ac_marmara",0);
|
||||
ASSETCHAINS_CBOPRET = GetArg("-ac_cbopret",0);
|
||||
if ( ASSETCHAINS_CBOPRET != 0 )
|
||||
{
|
||||
SplitStr(GetArg("-ac_prices",""), ASSETCHAINS_PRICES);
|
||||
for (i=0; i<ASSETCHAINS_PRICES.size(); i++)
|
||||
fprintf(stderr,"%s ",ASSETCHAINS_PRICES[i].c_str());
|
||||
fprintf(stderr,"%d -ac_prices\n",(int32_t)ASSETCHAINS_PRICES.size());
|
||||
}
|
||||
hexstr = GetArg("-ac_mineropret","");
|
||||
if ( hexstr.size() != 0 )
|
||||
{
|
||||
Mineropret.resize(hexstr.size()/2);
|
||||
decode_hex(Mineropret.data(),hexstr.size()/2,(char *)hexstr.c_str());
|
||||
for (i=0; i<Mineropret.size(); i++)
|
||||
fprintf(stderr,"%02x",Mineropret[i]);
|
||||
fprintf(stderr," Mineropret\n");
|
||||
}
|
||||
if ( ASSETCHAINS_COMMISSION != 0 && ASSETCHAINS_FOUNDERS_REWARD != 0 )
|
||||
{
|
||||
fprintf(stderr,"cannot use founders reward and commission on the same chain.\n");
|
||||
@@ -1948,7 +1965,7 @@ void komodo_args(char *argv0)
|
||||
fprintf(stderr,"-ac_script and -ac_marmara are mutually exclusive\n");
|
||||
exit(0);
|
||||
}
|
||||
if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1 || ASSETCHAINS_SELFIMPORT.size() > 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF|| ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LWMAPOS != 0 || ASSETCHAINS_LASTERA > 0 || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 || ASSETCHAINS_MARMARA != 0 || nonz > 0 || ASSETCHAINS_CCLIB.size() > 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 || ASSETCHAINS_NOTARY_PAY[0] != 0 || ASSETCHAINS_BLOCKTIME != 60 )
|
||||
if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1 || ASSETCHAINS_SELFIMPORT.size() > 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF|| ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LWMAPOS != 0 || ASSETCHAINS_LASTERA > 0 || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 || ASSETCHAINS_MARMARA != 0 || nonz > 0 || ASSETCHAINS_CCLIB.size() > 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 || ASSETCHAINS_NOTARY_PAY[0] != 0 || ASSETCHAINS_BLOCKTIME != 60 || ASSETCHAINS_CBOPRET != 0 || Mineropret.size() != 0 )
|
||||
{
|
||||
fprintf(stderr,"perc %.4f%% ac_pub=[%02x%02x%02x...] acsize.%d\n",dstr(ASSETCHAINS_COMMISSION)*100,ASSETCHAINS_OVERRIDE_PUBKEY33[0],ASSETCHAINS_OVERRIDE_PUBKEY33[1],ASSETCHAINS_OVERRIDE_PUBKEY33[2],(int32_t)ASSETCHAINS_SCRIPTPUB.size());
|
||||
extraptr = extrabuf;
|
||||
@@ -2048,6 +2065,26 @@ void komodo_args(char *argv0)
|
||||
}
|
||||
if ( ASSETCHAINS_BLOCKTIME != 60 )
|
||||
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_BLOCKTIME),(void *)&ASSETCHAINS_BLOCKTIME);
|
||||
if ( Mineropret.size() != 0 )
|
||||
{
|
||||
for (i=0; i<Mineropret.size(); i++)
|
||||
extraptr[extralen++] = Mineropret[i];
|
||||
}
|
||||
if ( ASSETCHAINS_CBOPRET != 0 )
|
||||
{
|
||||
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_CBOPRET),(void *)&ASSETCHAINS_CBOPRET);
|
||||
if ( ASSETCHAINS_PRICES.size() != 0 )
|
||||
{
|
||||
for (i=0; i<ASSETCHAINS_PRICES.size(); i++)
|
||||
{
|
||||
symbol = ASSETCHAINS_PRICES[i];
|
||||
memcpy(&extraptr[extralen],(char *)symbol.c_str(),symbol.size());
|
||||
extralen += symbol.size();
|
||||
}
|
||||
}
|
||||
komodo_cbopretupdate(1); // will set Mineropret
|
||||
fprintf(stderr,"This blockchain uses data produced from CoinDesk Bitcoin Price Index\n");
|
||||
}
|
||||
}
|
||||
|
||||
addn = GetArg("-seednode","");
|
||||
@@ -2079,7 +2116,7 @@ void komodo_args(char *argv0)
|
||||
|
||||
while ( (dirname= (char *)GetDataDir(false).string().c_str()) == 0 || dirname[0] == 0 )
|
||||
{
|
||||
fprintf(stderr,"waiting for datadir\n");
|
||||
fprintf(stderr,"waiting for datadir (%s)\n",dirname);
|
||||
#ifndef _WIN32
|
||||
sleep(3);
|
||||
#else
|
||||
|
||||
182
src/main.cpp
182
src/main.cpp
@@ -977,7 +977,7 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in
|
||||
* Ensure that a coinbase transaction is structured according to the consensus rules of the
|
||||
* chain
|
||||
*/
|
||||
bool ContextualCheckCoinbaseTransaction(const CTransaction& tx, const int nHeight)
|
||||
bool ContextualCheckCoinbaseTransaction(const CBlock *block,CBlockIndex * const previndex,const CTransaction& tx, const int nHeight)
|
||||
{
|
||||
// if time locks are on, ensure that this coin base is time locked exactly as it should be
|
||||
if (((uint64_t)(tx.GetValueOut()) >= ASSETCHAINS_TIMELOCKGTE) ||
|
||||
@@ -1014,6 +1014,15 @@ bool ContextualCheckCoinbaseTransaction(const CTransaction& tx, const int nHeigh
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
else if ( ASSETCHAINS_MARMARA != 0 && nHeight > 0 && (nHeight & 1) == 0 )
|
||||
{
|
||||
|
||||
}
|
||||
else if ( ASSETCHAINS_CBOPRET != 0 && nHeight > 0 && tx.vout.size() > 0 )
|
||||
{
|
||||
if ( komodo_opretvalidate(block,previndex,nHeight,tx.vout[tx.vout.size()-1].scriptPubKey) < 0 )
|
||||
return(false);
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
@@ -1026,7 +1035,7 @@ bool ContextualCheckCoinbaseTransaction(const CTransaction& tx, const int nHeigh
|
||||
* and ContextualCheckBlock (which calls this function).
|
||||
* 3. The isInitBlockDownload argument is only to assist with testing.
|
||||
*/
|
||||
bool ContextualCheckTransaction(
|
||||
bool ContextualCheckTransaction(const CBlock *block, CBlockIndex * const previndex,
|
||||
const CTransaction& tx,
|
||||
CValidationState &state,
|
||||
const int nHeight,
|
||||
@@ -1162,7 +1171,7 @@ bool ContextualCheckTransaction(
|
||||
|
||||
if (tx.IsCoinBase())
|
||||
{
|
||||
if (!ContextualCheckCoinbaseTransaction(tx, nHeight))
|
||||
if (!ContextualCheckCoinbaseTransaction(block,previndex,tx, nHeight))
|
||||
return state.DoS(100, error("CheckTransaction(): invalid script data for coinbase time lock"),
|
||||
REJECT_INVALID, "bad-txns-invalid-script-data-for-coinbase-time-lock");
|
||||
}
|
||||
@@ -1261,9 +1270,6 @@ bool CheckTransaction(uint32_t tiptime,const CTransaction& tx, CValidationState
|
||||
}
|
||||
}
|
||||
|
||||
extern char NOTARYADDRS[64][36];
|
||||
extern uint8_t NUM_NOTARIES;
|
||||
|
||||
int32_t komodo_isnotaryvout(char *coinaddr) // from ac_private chains only
|
||||
{
|
||||
static int32_t didinit; static char notaryaddrs[sizeof(Notaries_elected1)/sizeof(*Notaries_elected1) + 1][64];
|
||||
@@ -1383,7 +1389,7 @@ bool CheckTransactionWithoutProofVerification(uint32_t tiptime,const CTransactio
|
||||
}
|
||||
}
|
||||
if ( txout.scriptPubKey.size() > IGUANA_MAXSCRIPTSIZE )
|
||||
return state.DoS(100, error("CheckTransaction(): txout.scriptPubKey.size() too big"),REJECT_INVALID, "bad-txns-vout-negative");
|
||||
return state.DoS(100, error("CheckTransaction(): txout.scriptPubKey.size() too big"),REJECT_INVALID, "bad-txns-opret-too-big");
|
||||
nValueOut += txout.nValue;
|
||||
if (!MoneyRange(nValueOut))
|
||||
return state.DoS(100, error("CheckTransaction(): txout total out of range"),
|
||||
@@ -1670,7 +1676,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
||||
}
|
||||
// DoS level set to 10 to be more forgiving.
|
||||
// Check transaction contextually against the set of consensus rules which apply in the next block to be mined.
|
||||
if (!fSkipExpiry && !ContextualCheckTransaction(tx, state, nextBlockHeight, (dosLevel == -1) ? 10 : dosLevel))
|
||||
if (!fSkipExpiry && !ContextualCheckTransaction(0,0,tx, state, nextBlockHeight, (dosLevel == -1) ? 10 : dosLevel))
|
||||
{
|
||||
return error("AcceptToMemoryPool: ContextualCheckTransaction failed");
|
||||
}
|
||||
@@ -2958,6 +2964,33 @@ void DisconnectNotarisations(const CBlock &block)
|
||||
}
|
||||
}
|
||||
|
||||
int8_t GetAddressType(const CScript &scriptPubKey, CTxDestination &vDest, txnouttype &txType, vector<vector<unsigned char>> &vSols)
|
||||
{
|
||||
int8_t keyType = 0;
|
||||
// some non-standard types, like time lock coinbases, don't solve, but do extract
|
||||
if ( (Solver(scriptPubKey, txType, vSols) || ExtractDestination(scriptPubKey, vDest)) )
|
||||
{
|
||||
keyType = 1;
|
||||
if (vDest.which())
|
||||
{
|
||||
// if we failed to solve, and got a vDest, assume P2PKH or P2PK address returned
|
||||
CKeyID kid;
|
||||
if (CBitcoinAddress(vDest).GetKeyID(kid))
|
||||
{
|
||||
vSols.push_back(vector<unsigned char>(kid.begin(), kid.end()));
|
||||
}
|
||||
}
|
||||
else if (txType == TX_SCRIPTHASH)
|
||||
{
|
||||
keyType = 2;
|
||||
}
|
||||
else if (txType == TX_CRYPTOCONDITION )
|
||||
{
|
||||
keyType = 3;
|
||||
}
|
||||
}
|
||||
return keyType;
|
||||
}
|
||||
|
||||
bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool* pfClean)
|
||||
{
|
||||
@@ -2993,20 +3026,9 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
||||
vector<vector<unsigned char>> vSols;
|
||||
CTxDestination vDest;
|
||||
txnouttype txType = TX_PUBKEYHASH;
|
||||
int keyType = 1;
|
||||
if ((Solver(out.scriptPubKey, txType, vSols) || ExtractDestination(out.scriptPubKey, vDest)) && txType != TX_MULTISIG) {
|
||||
if (vDest.which())
|
||||
{
|
||||
CKeyID kid;
|
||||
if (CBitcoinAddress(vDest).GetKeyID(kid))
|
||||
{
|
||||
vSols.push_back(vector<unsigned char>(kid.begin(), kid.end()));
|
||||
}
|
||||
}
|
||||
else if (txType == TX_SCRIPTHASH)
|
||||
{
|
||||
keyType = 2;
|
||||
}
|
||||
int keyType = GetAddressType(out.scriptPubKey, vDest, txType, vSols);
|
||||
if ( keyType != 0 )
|
||||
{
|
||||
for (auto addr : vSols)
|
||||
{
|
||||
uint160 addrHash = addr.size() == 20 ? uint160(addr) : Hash160(addr);
|
||||
@@ -3063,23 +3085,9 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
||||
vector<vector<unsigned char>> vSols;
|
||||
CTxDestination vDest;
|
||||
txnouttype txType = TX_PUBKEYHASH;
|
||||
int keyType = 1;
|
||||
// some non-standard types, like time lock coinbases, don't solve, but do extract
|
||||
if ((Solver(prevout.scriptPubKey, txType, vSols) || ExtractDestination(prevout.scriptPubKey, vDest)))
|
||||
int keyType = GetAddressType(prevout.scriptPubKey, vDest, txType, vSols);
|
||||
if ( keyType != 0 )
|
||||
{
|
||||
// if we failed to solve, and got a vDest, assume P2PKH or P2PK address returned
|
||||
if (vDest.which())
|
||||
{
|
||||
CKeyID kid;
|
||||
if (CBitcoinAddress(vDest).GetKeyID(kid))
|
||||
{
|
||||
vSols.push_back(vector<unsigned char>(kid.begin(), kid.end()));
|
||||
}
|
||||
}
|
||||
else if (txType == TX_SCRIPTHASH)
|
||||
{
|
||||
keyType = 2;
|
||||
}
|
||||
for (auto addr : vSols)
|
||||
{
|
||||
uint160 addrHash = addr.size() == 20 ? uint160(addr) : Hash160(addr);
|
||||
@@ -3265,14 +3273,17 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||
//fprintf(stderr,"checkblock failure in connectblock futureblock.%d\n",futureblock);
|
||||
return false;
|
||||
}
|
||||
// check pindex->CONTEXT_VALIDATED flag
|
||||
if ( fCheckPOW != 0 && !ContextualCheckBlock(block, state, pindex->pprev) ) // Activate Jan 15th, 2019
|
||||
if ( fCheckPOW != 0 && (pindex->nStatus & BLOCK_VALID_CONTEXT) != BLOCK_VALID_CONTEXT ) // Activate Jan 15th, 2019
|
||||
{
|
||||
fprintf(stderr,"ContextualCheckBlock failed ht.%d\n",(int32_t)pindex->GetHeight());
|
||||
if ( pindex->nTime > 1547510400 )
|
||||
return false;
|
||||
fprintf(stderr,"grandfathered exception, until jan 15th 2019\n");
|
||||
if ( !ContextualCheckBlock(block, state, pindex->pprev) )
|
||||
{
|
||||
fprintf(stderr,"ContextualCheckBlock failed ht.%d\n",(int32_t)pindex->GetHeight());
|
||||
if ( pindex->nTime > 1547510400 )
|
||||
return false;
|
||||
fprintf(stderr,"grandfathered exception, until jan 15th 2019\n");
|
||||
} else pindex->nStatus |= BLOCK_VALID_CONTEXT;
|
||||
}
|
||||
|
||||
// Do this here before the block is moved to the main block files.
|
||||
if ( ASSETCHAINS_NOTARY_PAY[0] != 0 && pindex->GetHeight() > 10 )
|
||||
{
|
||||
@@ -3436,8 +3447,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||
|
||||
if (fAddressIndex || fSpentIndex)
|
||||
{
|
||||
for (size_t j = 0; j < tx.vin.size(); j++) {
|
||||
|
||||
for (size_t j = 0; j < tx.vin.size(); j++)
|
||||
{
|
||||
const CTxIn input = tx.vin[j];
|
||||
const CTxOut &prevout = view.GetOutputFor(tx.vin[j]);
|
||||
|
||||
@@ -3445,25 +3456,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||
CTxDestination vDest;
|
||||
txnouttype txType = TX_PUBKEYHASH;
|
||||
uint160 addrHash;
|
||||
int keyType = 0;
|
||||
// some non-standard types, like time lock coinbases, don't solve, but do extract
|
||||
if ((Solver(prevout.scriptPubKey, txType, vSols) || ExtractDestination(prevout.scriptPubKey, vDest)))
|
||||
int keyType = GetAddressType(prevout.scriptPubKey, vDest, txType, vSols);
|
||||
if ( keyType != 0 )
|
||||
{
|
||||
keyType = 1;
|
||||
|
||||
// if we failed to solve, and got a vDest, assume P2PKH or P2PK address returned
|
||||
if (vDest.which())
|
||||
{
|
||||
CKeyID kid;
|
||||
if (CBitcoinAddress(vDest).GetKeyID(kid))
|
||||
{
|
||||
vSols.push_back(vector<unsigned char>(kid.begin(), kid.end()));
|
||||
}
|
||||
}
|
||||
else if (txType == TX_SCRIPTHASH)
|
||||
{
|
||||
keyType = 2;
|
||||
}
|
||||
for (auto addr : vSols)
|
||||
{
|
||||
addrHash = addr.size() == 20 ? uint160(addr) : Hash160(addr);
|
||||
@@ -3473,12 +3468,12 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||
// remove address from unspent index
|
||||
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(keyType, addrHash, input.prevout.hash, input.prevout.n), CAddressUnspentValue()));
|
||||
}
|
||||
}
|
||||
|
||||
if (fSpentIndex) {
|
||||
// add the spent index to determine the txid and input that spent an output
|
||||
// and to find the amount and address from an input
|
||||
spentIndex.push_back(make_pair(CSpentIndexKey(input.prevout.hash, input.prevout.n), CSpentIndexValue(txhash, j, pindex->GetHeight(), prevout.nValue, keyType, addrHash)));
|
||||
if (fSpentIndex) {
|
||||
// add the spent index to determine the txid and input that spent an output
|
||||
// and to find the amount and address from an input
|
||||
spentIndex.push_back(make_pair(CSpentIndexKey(input.prevout.hash, input.prevout.n), CSpentIndexValue(txhash, j, pindex->GetHeight(), prevout.nValue, keyType, addrHash)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3529,23 +3524,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||
vector<vector<unsigned char>> vSols;
|
||||
CTxDestination vDest;
|
||||
txnouttype txType = TX_PUBKEYHASH;
|
||||
int keyType = 1;
|
||||
// some non-standard types, like time lock coinbases, don't solve, but do extract
|
||||
if ((Solver(out.scriptPubKey, txType, vSols) || ExtractDestination(out.scriptPubKey, vDest)) && txType != TX_MULTISIG)
|
||||
int keyType = GetAddressType(out.scriptPubKey, vDest, txType, vSols);
|
||||
if ( keyType != 0 )
|
||||
{
|
||||
// if we failed to solve, and got a vDest, assume P2PKH or P2PK address returned
|
||||
if (vDest.which())
|
||||
{
|
||||
CKeyID kid;
|
||||
if (CBitcoinAddress(vDest).GetKeyID(kid))
|
||||
{
|
||||
vSols.push_back(vector<unsigned char>(kid.begin(), kid.end()));
|
||||
}
|
||||
}
|
||||
else if (txType == TX_SCRIPTHASH)
|
||||
{
|
||||
keyType = 2;
|
||||
}
|
||||
for (auto addr : vSols)
|
||||
{
|
||||
addrHash = addr.size() == 20 ? uint160(addr) : Hash160(addr);
|
||||
@@ -4111,7 +4092,14 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
|
||||
GetMainSignals().BlockChecked(*pblock, state);
|
||||
if (!rv) {
|
||||
if (state.IsInvalid())
|
||||
{
|
||||
InvalidBlockFound(pindexNew, state);
|
||||
/*if ( ASSETCHAINS_CBOPRET != 0 )
|
||||
{
|
||||
pindexNew->nStatus &= ~BLOCK_FAILED_MASK;
|
||||
fprintf(stderr,"reconsiderblock %d\n",(int32_t)pindexNew->GetHeight());
|
||||
}*/
|
||||
}
|
||||
return error("ConnectTip(): ConnectBlock %s failed", pindexNew->GetBlockHash().ToString());
|
||||
}
|
||||
mapBlockSource.erase(pindexNew->GetBlockHash());
|
||||
@@ -5157,7 +5145,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
|
||||
const CTransaction& tx = block.vtx[i];
|
||||
|
||||
// Check transaction contextually against consensus rules at block height
|
||||
if (!ContextualCheckTransaction(tx, state, nHeight, 100)) {
|
||||
if (!ContextualCheckTransaction(&block,pindexPrev,tx, state, nHeight, 100)) {
|
||||
return false; // Failure reason has been set in validation state object
|
||||
}
|
||||
|
||||
@@ -5202,7 +5190,7 @@ bool AcceptBlockHeader(int32_t *futureblockp,const CBlockHeader& block, CValidat
|
||||
miSelf->second = pindex = AddToBlockIndex(block);
|
||||
if (ppindex)
|
||||
*ppindex = pindex;
|
||||
if ( pindex != 0 && pindex->nStatus & BLOCK_FAILED_MASK )
|
||||
if ( pindex != 0 && (pindex->nStatus & BLOCK_FAILED_MASK) != 0 )
|
||||
{
|
||||
if ( ASSETCHAINS_CC == 0 )//&& (ASSETCHAINS_PRIVATE == 0 || KOMODO_INSYNC >= Params().GetConsensus().vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight) )
|
||||
return state.Invalid(error("%s: block is marked invalid", __func__), 0, "duplicate");
|
||||
@@ -5324,7 +5312,8 @@ bool AcceptBlock(int32_t *futureblockp,CBlock& block, CValidationState& state, C
|
||||
|
||||
// See method docstring for why this is always disabled
|
||||
auto verifier = libzcash::ProofVerifier::Disabled();
|
||||
if ((!CheckBlock(futureblockp,pindex->GetHeight(),pindex,block, state, verifier,0)) || !ContextualCheckBlock(block, state, pindex->pprev))
|
||||
bool fContextualCheckBlock = ContextualCheckBlock(block, state, pindex->pprev);
|
||||
if ( (!CheckBlock(futureblockp,pindex->GetHeight(),pindex,block, state, verifier,0)) || !fContextualCheckBlock )
|
||||
{
|
||||
static int32_t saplinght = -1;
|
||||
CBlockIndex *tmpptr;
|
||||
@@ -5349,6 +5338,8 @@ bool AcceptBlock(int32_t *futureblockp,CBlock& block, CValidationState& state, C
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ( fContextualCheckBlock )
|
||||
pindex->nStatus |= BLOCK_VALID_CONTEXT;
|
||||
|
||||
int nHeight = pindex->GetHeight();
|
||||
// Temp File fix. LABS has been using this for ages with no bad effects.
|
||||
@@ -7035,8 +7026,19 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||
Misbehaving(pfrom->GetId(), 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
else if ( strCommand == "events" )
|
||||
{
|
||||
int32_t i;
|
||||
if ( ASSETCHAINS_CCLIB != "gamescc" )
|
||||
{
|
||||
Misbehaving(pfrom->GetId(), 1);
|
||||
return false;
|
||||
}
|
||||
std::vector<uint8_t> payload;
|
||||
vRecv >> payload;
|
||||
komodo_netevent(payload);
|
||||
return(true);
|
||||
}
|
||||
else if (strCommand == "verack")
|
||||
{
|
||||
pfrom->SetRecvVersion(min(pfrom->nVersion, PROTOCOL_VERSION));
|
||||
|
||||
@@ -706,7 +706,7 @@ bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, cons
|
||||
std::vector<CScriptCheck> *pvChecks = NULL);
|
||||
|
||||
/** Check a transaction contextually against a set of consensus rules */
|
||||
bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state, int nHeight, int dosLevel,
|
||||
bool ContextualCheckTransaction(const CBlock *block, CBlockIndex * const pindexPrev,const CTransaction& tx, CValidationState &state, int nHeight, int dosLevel,
|
||||
bool (*isInitBlockDownload)() = IsInitialBlockDownload);
|
||||
|
||||
/** Apply the effects of this transaction on the UTXO set represented by view */
|
||||
|
||||
@@ -155,6 +155,7 @@ CScript MarmaraCoinbaseOpret(uint8_t funcid,int32_t height,CPubKey pk);
|
||||
uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector<int8_t> &NotarisationNotaries, uint32_t timestamp, int32_t height, uint8_t *script, int32_t len);
|
||||
int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
|
||||
int32_t komodo_getnotarizedheight(uint32_t timestamp,int32_t height, uint8_t *script, int32_t len);
|
||||
CScript komodo_mineropret(int32_t nHeight);
|
||||
|
||||
CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32_t gpucount, bool isStake)
|
||||
{
|
||||
@@ -223,8 +224,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
|
||||
|
||||
CBlockIndex* pindexPrev = 0;
|
||||
{
|
||||
ENTER_CRITICAL_SECTION(cs_main);
|
||||
ENTER_CRITICAL_SECTION(mempool.cs);
|
||||
LOCK2(cs_main,mempool.cs);
|
||||
pindexPrev = chainActive.LastTip();
|
||||
const int nHeight = pindexPrev->GetHeight() + 1;
|
||||
const Consensus::Params &consensusParams = chainparams.GetConsensus();
|
||||
@@ -563,11 +563,10 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
|
||||
//LogPrintf("CreateNewBlock(): total size %u blocktime.%u nBits.%08x stake.%i\n", nBlockSize,blocktime,pblock->nBits,isStake);
|
||||
if ( ASSETCHAINS_SYMBOL[0] != 0 && isStake )
|
||||
{
|
||||
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[512],*ptr;
|
||||
CMutableTransaction txStaked = CreateNewContextualCMutableTransaction(Params().GetConsensus(), stakeHeight);
|
||||
|
||||
LEAVE_CRITICAL_SECTION(cs_main);
|
||||
LEAVE_CRITICAL_SECTION(mempool.cs);
|
||||
if (ASSETCHAINS_LWMAPOS != 0)
|
||||
{
|
||||
uint32_t nBitsPOS;
|
||||
@@ -592,7 +591,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
|
||||
{
|
||||
sleep(1);
|
||||
if ( (rand() % 100) < 1 )
|
||||
fprintf(stderr, "%u seconds until elegible, waiting.\n", blocktime-((uint32_t)GetAdjustedTime()+57));
|
||||
fprintf(stderr, "%u seconds until elegible, waiting...\n", blocktime-((uint32_t)GetAdjustedTime()+57));
|
||||
if ( chainActive.LastTip()->GetHeight() >= stakeHeight )
|
||||
{
|
||||
fprintf(stderr, "Block Arrived, reset staking loop.\n");
|
||||
@@ -602,7 +601,8 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
ENTER_CRITICAL_SECTION(cs_main);
|
||||
ENTER_CRITICAL_SECTION(mempool.cs);
|
||||
if ( siglen > 0 )
|
||||
{
|
||||
CAmount txfees;
|
||||
@@ -615,7 +615,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
|
||||
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)));
|
||||
} else return(0); //fprintf(stderr,"no utxos eligible for staking\n");
|
||||
} else return(0); //fprintf(stderr,"no utxos eligible for staking\n");
|
||||
}
|
||||
|
||||
// Create coinbase tx
|
||||
@@ -687,11 +687,6 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
|
||||
if (scriptPubKeyIn.IsPayToScriptHash() || scriptPubKeyIn.IsPayToCryptoCondition())
|
||||
{
|
||||
fprintf(stderr,"CreateNewBlock: attempt to add timelock to pay2sh or pay2cc\n");
|
||||
if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) )
|
||||
{
|
||||
LEAVE_CRITICAL_SECTION(cs_main);
|
||||
LEAVE_CRITICAL_SECTION(mempool.cs);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -713,17 +708,19 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
|
||||
if ( totalsats == 0 )
|
||||
{
|
||||
fprintf(stderr, "Could not create notary payment, trying again.\n");
|
||||
if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) )
|
||||
{
|
||||
LEAVE_CRITICAL_SECTION(cs_main);
|
||||
LEAVE_CRITICAL_SECTION(mempool.cs);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
fprintf(stderr, "Created notary payment coinbase totalsat.%lu\n",totalsats);
|
||||
} else fprintf(stderr, "vout 2 of notarisation is not OP_RETURN scriptlen.%i\n", scriptlen);
|
||||
}
|
||||
|
||||
if ( ASSETCHAINS_CBOPRET != 0 )
|
||||
{
|
||||
int32_t numv = (int32_t)txNew.vout.size();
|
||||
txNew.vout.resize(numv+1);
|
||||
txNew.vout[numv].nValue = 0;
|
||||
txNew.vout[numv].scriptPubKey = komodo_mineropret(nHeight);
|
||||
//printf("autocreate commision/cbopret.%lld vout[%d]\n",(long long)ASSETCHAINS_CBOPRET,(int32_t)txNew.vout.size());
|
||||
}
|
||||
pblock->vtx[0] = txNew;
|
||||
pblocktemplate->vTxFees[0] = -nFees;
|
||||
|
||||
@@ -781,11 +778,6 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"error adding notaryvin, need to create 0.0001 utxos\n");
|
||||
if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) )
|
||||
{
|
||||
LEAVE_CRITICAL_SECTION(cs_main);
|
||||
LEAVE_CRITICAL_SECTION(mempool.cs);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
@@ -800,11 +792,6 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
|
||||
//fprintf(stderr,"valid\n");
|
||||
}
|
||||
}
|
||||
if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) )
|
||||
{
|
||||
LEAVE_CRITICAL_SECTION(cs_main);
|
||||
LEAVE_CRITICAL_SECTION(mempool.cs);
|
||||
}
|
||||
//fprintf(stderr,"done new block\n");
|
||||
return pblocktemplate.release();
|
||||
}
|
||||
@@ -931,6 +918,24 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight,
|
||||
return CreateNewBlock(pubkey, scriptPubKey, gpucount, isStake);
|
||||
}
|
||||
|
||||
void komodo_sendmessage(int32_t minpeers,int32_t maxpeers,const char *message,std::vector<uint8_t> payload)
|
||||
{
|
||||
int32_t numsent = 0;
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
{
|
||||
if ( pnode->hSocket == INVALID_SOCKET )
|
||||
continue;
|
||||
if ( numsent < minpeers || (rand() % 10) == 0 )
|
||||
{
|
||||
//fprintf(stderr,"pushmessage\n");
|
||||
pnode->PushMessage(message,payload);
|
||||
if ( numsent++ > maxpeers )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void komodo_broadcast(CBlock *pblock,int32_t limit)
|
||||
{
|
||||
if (IsInitialBlockDownload())
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
#include "cc/CCinclude.h"
|
||||
#include <cstring>
|
||||
|
||||
extern char NOTARYADDRS[64][36];
|
||||
extern char NOTARYADDRS[64][64];
|
||||
extern std::string NOTARY_ADDRESS,NOTARY_PUBKEY;
|
||||
extern int32_t STAKED_ERA,IS_STAKED_NOTARY,IS_KOMODO_NOTARY;
|
||||
extern pthread_mutex_t staked_mutex;
|
||||
extern uint8_t NOTARY_PUBKEY33[33],NUM_NOTARIES;
|
||||
extern uint8_t NOTARY_PUBKEY33[33];
|
||||
|
||||
int8_t is_STAKED(const char *chain_name)
|
||||
{
|
||||
@@ -46,16 +46,6 @@ int32_t STAKED_era(int timestamp)
|
||||
return(0);
|
||||
};
|
||||
|
||||
int8_t updateStakedNotary() {
|
||||
std::string notaryname;
|
||||
char Raddress[18]; uint8_t pubkey33[33];
|
||||
decode_hex(pubkey33,33,(char *)NOTARY_PUBKEY.c_str());
|
||||
pubkey2addr((char *)Raddress,(uint8_t *)pubkey33);
|
||||
NOTARY_ADDRESS.clear();
|
||||
NOTARY_ADDRESS.assign(Raddress);
|
||||
return(StakedNotaryID(notaryname,Raddress));
|
||||
}
|
||||
|
||||
int8_t StakedNotaryID(std::string ¬aryname, char *Raddress) {
|
||||
if ( STAKED_ERA != 0 )
|
||||
{
|
||||
@@ -116,7 +106,6 @@ void UpdateNotaryAddrs(uint8_t pubkeys[64][33],int8_t numNotaries) {
|
||||
// null pubkeys, era 0.
|
||||
pthread_mutex_lock(&staked_mutex);
|
||||
memset(NOTARYADDRS,0,sizeof(NOTARYADDRS));
|
||||
NUM_NOTARIES = 0;
|
||||
pthread_mutex_unlock(&staked_mutex);
|
||||
}
|
||||
else
|
||||
@@ -125,7 +114,6 @@ void UpdateNotaryAddrs(uint8_t pubkeys[64][33],int8_t numNotaries) {
|
||||
pthread_mutex_lock(&staked_mutex);
|
||||
for (int i = 0; i<numNotaries; i++)
|
||||
pubkey2addr((char *)NOTARYADDRS[i],(uint8_t *)pubkeys[i]);
|
||||
NUM_NOTARIES = numNotaries;
|
||||
pthread_mutex_unlock(&staked_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +119,6 @@ static const char *notaries_STAKED[NUM_STAKED_ERAS][64][2] =
|
||||
|
||||
int8_t is_STAKED(const char *chain_name);
|
||||
int32_t STAKED_era(int timestamp);
|
||||
int8_t updateStakedNotary();
|
||||
int8_t numStakedNotaries(uint8_t pubkeys[64][33],int8_t era);
|
||||
int8_t StakedNotaryID(std::string ¬aryname, char *Raddress);
|
||||
void UpdateNotaryAddrs(uint8_t pubkeys[64][33],int8_t numNotaries);
|
||||
|
||||
98
src/notarystats.py
Executable file
98
src/notarystats.py
Executable file
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
sudo apt-get install python3-dev
|
||||
sudo apt-get install python3 libgnutls28-dev libssl-dev
|
||||
sudo apt-get install python3-pip
|
||||
pip3 install setuptools
|
||||
pip3 install wheel
|
||||
pip3 install base58 slick-bitcoinrpc
|
||||
./notarystats.py
|
||||
------------------------------------------------
|
||||
"""
|
||||
import platform
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
import pprint
|
||||
from slickrpc import Proxy
|
||||
|
||||
# fucntion to define rpc_connection
|
||||
def def_credentials(chain):
|
||||
rpcport = '';
|
||||
operating_system = platform.system()
|
||||
if operating_system == 'Darwin':
|
||||
ac_dir = os.environ['HOME'] + '/Library/Application Support/Komodo'
|
||||
elif operating_system == 'Linux':
|
||||
ac_dir = os.environ['HOME'] + '/.komodo'
|
||||
elif operating_system == 'Windows':
|
||||
ac_dir = '%s/komodo/' % os.environ['APPDATA']
|
||||
if chain == 'KMD':
|
||||
coin_config_file = str(ac_dir + '/komodo.conf')
|
||||
else:
|
||||
coin_config_file = str(ac_dir + '/' + chain + '/' + chain + '.conf')
|
||||
with open(coin_config_file, 'r') as f:
|
||||
for line in f:
|
||||
l = line.rstrip()
|
||||
if re.search('rpcuser', l):
|
||||
rpcuser = l.replace('rpcuser=', '')
|
||||
elif re.search('rpcpassword', l):
|
||||
rpcpassword = l.replace('rpcpassword=', '')
|
||||
elif re.search('rpcport', l):
|
||||
rpcport = l.replace('rpcport=', '')
|
||||
if len(rpcport) == 0:
|
||||
if chain == 'KMD':
|
||||
rpcport = 7771
|
||||
else:
|
||||
print("rpcport not in conf file, exiting")
|
||||
print("check " + coin_config_file)
|
||||
exit(1)
|
||||
return (Proxy("http://%s:%s@127.0.0.1:%d" % (rpcuser, rpcpassword, int(rpcport))))
|
||||
|
||||
|
||||
rpc = def_credentials('KMD')
|
||||
pp = pprint.PrettyPrinter(indent=2)
|
||||
|
||||
notarynames = [ "0dev1_jl777", "0dev2_kolo", "0dev3_kolo", "0dev4_decker_AR", "a-team_SH", "artik_AR", "artik_EU", "artik_NA", "artik_SH", "badass_EU", "badass_NA", "batman_AR", "batman_SH", "ca333", "chainmakers_EU", "chainmakers_NA", "chainstrike_SH", "cipi_AR", "cipi_NA", "crackers_EU", "crackers_NA", "dwy_EU", "emmanux_SH", "etszombi_EU", "fullmoon_AR", "fullmoon_NA", "fullmoon_SH", "goldenman_EU", "indenodes_AR", "indenodes_EU", "indenodes_NA", "indenodes_SH", "jackson_AR", "jeezy_EU", "karasugoi_NA", "komodoninja_EU", "komodoninja_SH", "komodopioneers_SH", "libscott_SH", "lukechilds_AR", "madmax_AR", "meshbits_AR", "meshbits_SH", "metaphilibert_AR", "metaphilibert_SH", "patchkez_SH", "pbca26_NA", "peer2cloud_AR", "peer2cloud_SH", "polycryptoblog_NA", "hyper_AR", "hyper_EU", "hyper_SH", "hyper_NA", "popcornbag_AR", "popcornbag_NA", "alien_AR", "alien_EU", "thegaltmines_NA", "titomane_AR", "titomane_EU", "titomane_SH", "webworker01_NA", "xrobesx_NA" ]
|
||||
notaries = 64 * [0]
|
||||
|
||||
startheight = 821657 #Second time filter for assetchains (block 821657) for KMD its 814000
|
||||
stopheight = 1307200
|
||||
for i in range(startheight,stopheight):
|
||||
ret = rpc.getNotarisationsForBlock(i)
|
||||
KMD = ret['KMD']
|
||||
if len(KMD) > 0:
|
||||
for obj in KMD:
|
||||
#for now skip KMD for this. As official stats are from BTC chain
|
||||
# this can be reversed to !== to count KMD numbers :)
|
||||
if obj['chain'] == 'KMD':
|
||||
continue;
|
||||
for notary in obj['notaries']:
|
||||
notaries[notary] = notaries[notary] + 1
|
||||
|
||||
i = 0
|
||||
SH = []
|
||||
AR = []
|
||||
EU = []
|
||||
NA = []
|
||||
for notary in notaries:
|
||||
tmpnotary = {}
|
||||
tmpnotary['node'] = notarynames[i]
|
||||
tmpnotary['ac_count'] = notary
|
||||
if notarynames[i].endswith('SH'):
|
||||
SH.append(tmpnotary)
|
||||
elif notarynames[i].endswith('AR'):
|
||||
AR.append(tmpnotary)
|
||||
elif notarynames[i].endswith('EU'):
|
||||
EU.append(tmpnotary)
|
||||
elif notarynames[i].endswith('NA'):
|
||||
NA.append(tmpnotary)
|
||||
i = i + 1
|
||||
|
||||
regions = {}
|
||||
regions['SH'] = sorted(SH, key=lambda k: k['ac_count'], reverse=True)
|
||||
regions['AR'] = sorted(AR, key=lambda k: k['ac_count'], reverse=True)
|
||||
regions['EU'] = sorted(EU, key=lambda k: k['ac_count'], reverse=True)
|
||||
regions["NA"] = sorted(NA, key=lambda k: k['ac_count'], reverse=True)
|
||||
|
||||
pp.pprint(regions)
|
||||
@@ -1174,38 +1174,161 @@ UniValue paxprice(const UniValue& params, bool fHelp)
|
||||
return ret;
|
||||
}
|
||||
|
||||
UniValue paxprices(const UniValue& params, bool fHelp)
|
||||
int32_t komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHeight);
|
||||
char *komodo_pricename(char *name,int32_t ind);
|
||||
int64_t komodo_pricesmoothed(int64_t *correlated,int32_t cskip,int64_t *correlated2,int32_t numprices);
|
||||
int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int32_t rawskip,uint32_t *nonzprices,int32_t smoothwidth);
|
||||
int32_t komodo_nextheight();
|
||||
uint32_t komodo_heightstamp(int32_t height);
|
||||
int64_t komodo_pricemult(int32_t ind);
|
||||
#define PRICES_SMOOTHWIDTH 1
|
||||
|
||||
int32_t prices_extract(int64_t *pricedata,int32_t firstheight,int32_t numblocks,int32_t ind)
|
||||
{
|
||||
if ( fHelp || params.size() != 3 )
|
||||
throw runtime_error("paxprices \"base\" \"rel\" maxsamples\n");
|
||||
int32_t height,i,n,width,numpricefeeds = -1; uint64_t seed,ignore,rngval; int64_t *correlated2; uint32_t rawprices[1440*6],*ptr;
|
||||
//daywindow = (3600*24/ASSETCHAINS_BLOCKTIME) + 1;
|
||||
//pricedata = (uint32_t *)calloc(sizeof(*prices)*3,numblocks + daywindow*2 + PRICES_SMOOTHWIDTH);
|
||||
width = numblocks+PRICES_DAYWINDOW*2+PRICES_SMOOTHWIDTH;
|
||||
komodo_heightpricebits(&seed,rawprices,firstheight + numblocks - 1);
|
||||
if ( firstheight < width )
|
||||
return(-1);
|
||||
for (i=0; i<width; i++)
|
||||
{
|
||||
if ( (n= komodo_heightpricebits(&ignore,rawprices,firstheight + numblocks - 1 - i)) < 0 )
|
||||
return(-1);
|
||||
if ( numpricefeeds < 0 )
|
||||
numpricefeeds = n;
|
||||
if ( n != numpricefeeds )
|
||||
return(-2);
|
||||
ptr = (uint32_t *)&pricedata[i*3];
|
||||
ptr[0] = rawprices[ind];
|
||||
ptr[1] = rawprices[0]; // timestamp
|
||||
}
|
||||
rngval = seed;
|
||||
correlated2 = (int64_t *)calloc(sizeof(*correlated2),width);
|
||||
for (i=0; i<numblocks+PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH; i++)
|
||||
{
|
||||
rngval = (rngval*11109 + 13849);
|
||||
ptr = (uint32_t *)&pricedata[i*3];
|
||||
correlated2[i] = ptr[0];
|
||||
if ( (pricedata[i*3+1]= komodo_pricecorrelated(rngval,ind,(uint32_t *)&pricedata[i*3],6,0,PRICES_SMOOTHWIDTH)) < 0 )
|
||||
{
|
||||
free(correlated2);
|
||||
return(-3);
|
||||
}
|
||||
}
|
||||
for (i=0; i<numblocks; i++)
|
||||
pricedata[i*3+2] = komodo_pricesmoothed(&pricedata[i*3+1],3,correlated2,numblocks+PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH);
|
||||
return(0);
|
||||
}
|
||||
|
||||
UniValue prices(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if ( fHelp || params.size() != 1 )
|
||||
throw runtime_error("prices maxsamples\n");
|
||||
LOCK(cs_main);
|
||||
UniValue ret(UniValue::VOBJ); uint64_t relvolume,prices[4096]; uint32_t i,n; int32_t heights[sizeof(prices)/sizeof(*prices)];
|
||||
std::string base = params[0].get_str();
|
||||
std::string rel = params[1].get_str();
|
||||
int32_t maxsamples = atoi(params[2].get_str().c_str());
|
||||
UniValue ret(UniValue::VOBJ); uint64_t seed,rngval; int64_t smoothed,*correlated,*correlated2; char name[64],*str; uint32_t rawprices[1440*6],*prices; uint32_t i,width,j,numpricefeeds=-1,n,numsamples,nextheight,offset,ht;
|
||||
if ( ASSETCHAINS_CBOPRET == 0 )
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices");
|
||||
|
||||
int32_t maxsamples = atoi(params[0].get_str().c_str());
|
||||
if ( maxsamples < 1 )
|
||||
maxsamples = 1;
|
||||
else if ( maxsamples > sizeof(heights)/sizeof(*heights) )
|
||||
maxsamples = sizeof(heights)/sizeof(*heights);
|
||||
ret.push_back(Pair("base", base));
|
||||
ret.push_back(Pair("rel", rel));
|
||||
n = komodo_paxprices(heights,prices,maxsamples,(char *)base.c_str(),(char *)rel.c_str());
|
||||
nextheight = komodo_nextheight();
|
||||
UniValue a(UniValue::VARR);
|
||||
for (i=0; i<n; i++)
|
||||
if ( PRICES_DAYWINDOW < 7 )
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "daywindow is too small");
|
||||
width = maxsamples+2*PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH;
|
||||
numpricefeeds = komodo_heightpricebits(&seed,rawprices,nextheight-1);
|
||||
if ( numpricefeeds <= 0 )
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "illegal numpricefeeds");
|
||||
prices = (uint32_t *)calloc(sizeof(*prices),width*numpricefeeds);
|
||||
correlated = (int64_t *)calloc(sizeof(*correlated),width);
|
||||
correlated2 = (int64_t *)calloc(sizeof(*correlated2),width);
|
||||
//prices2 = (uint32_t *)calloc(sizeof(*prices2),width);
|
||||
i = 0;
|
||||
for (ht=nextheight-1,i=0; i<width&&ht>2; i++,ht--)
|
||||
{
|
||||
UniValue item(UniValue::VOBJ);
|
||||
if ( heights[i] < 0 || heights[i] > chainActive.Height() )
|
||||
if ( ht < 0 || ht > chainActive.Height() )
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
|
||||
else
|
||||
{
|
||||
CBlockIndex *pblockindex = chainActive[heights[i]];
|
||||
|
||||
item.push_back(Pair("t", (int64_t)pblockindex->nTime));
|
||||
item.push_back(Pair("p", (double)prices[i] / COIN));
|
||||
a.push_back(item);
|
||||
if ( (n= komodo_heightpricebits(0,rawprices,ht)) > 0 )
|
||||
{
|
||||
if ( n != numpricefeeds )
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "numprices != first numprices");
|
||||
else
|
||||
{
|
||||
for (j=0; j<numpricefeeds; j++)
|
||||
prices[j*width + i] = rawprices[j];
|
||||
}
|
||||
} else throw JSONRPCError(RPC_INVALID_PARAMETER, "no komodo_rawprices found");
|
||||
}
|
||||
}
|
||||
ret.push_back(Pair("array", a));
|
||||
numsamples = i;
|
||||
ret.push_back(Pair("firstheight", (int64_t)nextheight-1-i));
|
||||
UniValue timestamps(UniValue::VARR);
|
||||
for (i=0; i<maxsamples; i++)
|
||||
timestamps.push_back((int64_t)prices[i]);
|
||||
ret.push_back(Pair("timestamps",timestamps));
|
||||
rngval = seed;
|
||||
//for (i=0; i<PRICES_DAYWINDOW; i++)
|
||||
// fprintf(stderr,"%.4f ",(double)prices[width+i]/10000);
|
||||
//fprintf(stderr," maxsamples.%d\n",maxsamples);
|
||||
for (j=1; j<numpricefeeds; j++)
|
||||
{
|
||||
UniValue item(UniValue::VOBJ),p(UniValue::VARR);
|
||||
if ( (str= komodo_pricename(name,j)) != 0 )
|
||||
{
|
||||
item.push_back(Pair("name",str));
|
||||
if ( numsamples >= width )
|
||||
{
|
||||
for (i=0; i<maxsamples+PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH&&i<numsamples; i++)
|
||||
{
|
||||
offset = j*width + i;
|
||||
rngval = (rngval*11109 + 13849);
|
||||
correlated2[i] = prices[offset];
|
||||
if ( (correlated[i]= komodo_pricecorrelated(rngval,j,&prices[offset],1,0,PRICES_SMOOTHWIDTH)) < 0 )
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "null correlated price");
|
||||
}
|
||||
for (i=0; i<maxsamples&&i<numsamples; i++)
|
||||
{
|
||||
offset = j*width + i;
|
||||
smoothed = komodo_pricesmoothed(&correlated[i],1,correlated2,maxsamples+PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH);
|
||||
UniValue parr(UniValue::VARR);
|
||||
parr.push_back(ValueFromAmount((int64_t)prices[offset] * komodo_pricemult(j)));
|
||||
parr.push_back(ValueFromAmount(correlated[i]));
|
||||
parr.push_back(ValueFromAmount(smoothed));
|
||||
// compare to alternate method
|
||||
p.push_back(parr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; i<maxsamples&&i<numsamples; i++)
|
||||
{
|
||||
offset = j*width + i;
|
||||
UniValue parr(UniValue::VARR);
|
||||
parr.push_back(ValueFromAmount((int64_t)prices[offset] * komodo_pricemult(j)));
|
||||
p.push_back(parr);
|
||||
}
|
||||
}
|
||||
item.push_back(Pair("prices",p));
|
||||
} else item.push_back(Pair("name","error"));
|
||||
a.push_back(item);
|
||||
}
|
||||
ret.push_back(Pair("pricefeeds",a));
|
||||
ret.push_back(Pair("result","success"));
|
||||
ret.push_back(Pair("seed",(int64_t)seed));
|
||||
ret.push_back(Pair("height",(int64_t)nextheight-1));
|
||||
ret.push_back(Pair("maxsamples",(int64_t)maxsamples));
|
||||
ret.push_back(Pair("width",(int64_t)width));
|
||||
ret.push_back(Pair("daywindow",(int64_t)PRICES_DAYWINDOW));
|
||||
ret.push_back(Pair("numpricefeeds",(int64_t)numpricefeeds));
|
||||
free(prices);
|
||||
//free(prices2);
|
||||
free(correlated);
|
||||
free(correlated2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -171,6 +171,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
||||
{ "assetchainproof", 1},
|
||||
{ "crosschainproof", 1},
|
||||
{ "getproofroot", 2},
|
||||
{ "getNotarisationsForBlock", 0},
|
||||
{ "height_MoM", 1},
|
||||
{ "calc_MoM", 2},
|
||||
};
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "consensus/validation.h"
|
||||
#include "cc/eval.h"
|
||||
#include "cc/utils.h"
|
||||
#include "cc/CCinclude.h"
|
||||
#include "main.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "rpc/server.h"
|
||||
@@ -33,8 +34,10 @@
|
||||
#include "script/script_error.h"
|
||||
#include "script/sign.h"
|
||||
#include "script/standard.h"
|
||||
#include "notaries_staked.h"
|
||||
|
||||
#include "key_io.h"
|
||||
#include "cc/CCImportGateway.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <univalue.h>
|
||||
@@ -42,19 +45,24 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define RETURN_IF_ERROR(CCerror) if ( CCerror != "" ) { ERR_RESULT(CCerror); return(result); }
|
||||
#define ERR_RESULT(x) result.push_back(Pair("result", "error")) , result.push_back(Pair("error", x));
|
||||
|
||||
extern std::string CCerror;
|
||||
extern std::string ASSETCHAINS_SELFIMPORT;
|
||||
extern uint16_t ASSETCHAINS_CODAPORT, ASSETCHAINS_BEAMPORT;
|
||||
int32_t ensure_CCrequirements(uint8_t evalcode);
|
||||
|
||||
int32_t komodo_MoM(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip);
|
||||
int32_t komodo_MoMoMdata(char *hexstr,int32_t hexsize,struct komodo_ccdataMoMoM *mdata,char *symbol,int32_t kmdheight,int32_t notarized_height);
|
||||
struct komodo_ccdata_entry *komodo_allMoMs(int32_t *nump,uint256 *MoMoMp,int32_t kmdstarti,int32_t kmdendi);
|
||||
uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth);
|
||||
int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
|
||||
extern std::string ASSETCHAINS_SELFIMPORT;
|
||||
uint256 Parseuint256(char *hexstr);
|
||||
|
||||
std::string MakeSelfImportSourceTx(CTxDestination &dest, int64_t amount, CMutableTransaction &mtx);
|
||||
int32_t GetSelfimportProof(std::string source, CMutableTransaction &mtx, CScript &scriptPubKey, TxProof &proof, std::string rawsourcetx, int32_t &ivout, uint256 sourcetxid, uint64_t burnAmount);
|
||||
std::string MakeGatewaysImportTx(uint64_t txfee, uint256 bindtxid, int32_t height, std::string refcoin, std::vector<uint8_t>proof, std::string rawburntx, int32_t ivout, uint256 burntxid);
|
||||
std::string MakeCodaImportTx(uint64_t txfee, std::string receipt, std::string srcaddr, std::vector<CTxOut> vouts);
|
||||
|
||||
UniValue assetchainproof(const UniValue& params, bool fHelp)
|
||||
{
|
||||
@@ -338,7 +346,6 @@ UniValue selfimport(const UniValue& params, bool fHelp)
|
||||
source = params[5].get_str();
|
||||
} */
|
||||
|
||||
|
||||
if (source == "BEAM")
|
||||
{
|
||||
if (ASSETCHAINS_BEAMPORT == 0)
|
||||
@@ -398,15 +405,406 @@ UniValue selfimport(const UniValue& params, bool fHelp)
|
||||
|
||||
// source is external coin is the assetchains symbol in the burnTx OP_RETURN
|
||||
// burnAmount, rawtx and rawproof should be enough for gatewaysdeposit equivalent
|
||||
std::string hextx = MakeGatewaysImportTx(0, bindtxid, height, source, rawproof, rawsourcetx, ivout, sourcetxid);
|
||||
//std::string hextx = MakeGatewaysImportTx(0, bindtxid, height, source, rawproof, rawsourcetx, ivout, "");
|
||||
|
||||
result.push_back(Pair("hex", hextx));
|
||||
result.push_back(Pair("UsedRawtxVout", ivout)); // notify user about the used vout of rawtx
|
||||
// result.push_back(Pair("hex", hextx));
|
||||
// result.push_back(Pair("UsedRawtxVout", ivout)); // notify user about the used vout of rawtx
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool GetNotarisationNotaries(uint8_t notarypubkeys[64][33], int8_t &numNN, const std::vector<CTxIn> &vin, std::vector<int8_t> &NotarisationNotaries);
|
||||
|
||||
|
||||
UniValue importdual(const UniValue& params, bool fHelp)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ);
|
||||
CMutableTransaction mtx;
|
||||
std::string hex,source,sourceaddr,destaddr,burntxid; uint64_t burnAmount;
|
||||
CPubKey destpub; std::vector<CTxOut> vouts;
|
||||
|
||||
if ( ASSETCHAINS_SELFIMPORT.size() == 0 )
|
||||
throw runtime_error("importdual only works on -ac_import chains");
|
||||
|
||||
if (fHelp || params.size() < 4)
|
||||
throw runtime_error("burntxid source_addr dest_pubkey amount\n");
|
||||
|
||||
CCerror = "";
|
||||
|
||||
burntxid = params[0].get_str();
|
||||
sourceaddr = params[1].get_str();
|
||||
destaddr = params[2].get_str();
|
||||
burnAmount = atof(params[3].get_str().c_str()) * COIN + 0.00000000499999;
|
||||
|
||||
source = ASSETCHAINS_SELFIMPORT; //defaults to -ac_import=... param
|
||||
|
||||
CTxDestination dest = DecodeDestination(destaddr.c_str());
|
||||
CScript scriptPubKey = GetScriptForDestination(dest);
|
||||
vouts.push_back(CTxOut(burnAmount,scriptPubKey));
|
||||
|
||||
if (source == "BEAM")
|
||||
{
|
||||
if (ASSETCHAINS_BEAMPORT == 0)
|
||||
return(-1);
|
||||
// confirm via ASSETCHAINS_BEAMPORT that burnTx/hash is a valid BEAM burn
|
||||
// return(0);
|
||||
return -1;
|
||||
}
|
||||
else if (source == "CODA")
|
||||
{
|
||||
if (ASSETCHAINS_CODAPORT == 0)
|
||||
return(-1);
|
||||
hex=MakeCodaImportTx(0,burntxid,sourceaddr,vouts);
|
||||
// confirm via ASSETCHAINS_CODAPORT that burnTx/hash is a valid CODA burn
|
||||
// return(0);
|
||||
}
|
||||
RETURN_IF_ERROR(CCerror);
|
||||
if ( hex.size() > 0 )
|
||||
{
|
||||
result.push_back(Pair("result", "success"));
|
||||
result.push_back(Pair("hex", hex));
|
||||
} else ERR_RESULT("couldnt importdual");
|
||||
return result;
|
||||
}
|
||||
|
||||
UniValue importgatewayinfo(const UniValue& params, bool fHelp)
|
||||
{
|
||||
uint256 txid;
|
||||
|
||||
if ( ASSETCHAINS_SELFIMPORT.size() == 0 )
|
||||
throw runtime_error("importgatewaybind only works on -ac_import chains");
|
||||
if ( fHelp || params.size() != 1 )
|
||||
throw runtime_error("importgatewayinfo bindtxid\n");
|
||||
txid = Parseuint256(params[0].get_str().c_str());
|
||||
return(ImportGatewayInfo(txid));
|
||||
}
|
||||
|
||||
UniValue importgatewaybind(const UniValue& params, bool fHelp)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ);
|
||||
CMutableTransaction mtx; std::vector<unsigned char> pubkey;
|
||||
std::string hex,coin; int32_t i,M,N; std::vector<CPubKey> pubkeys;
|
||||
uint256 oracletxid; uint8_t p1,p2,p3,p4;
|
||||
|
||||
if ( ASSETCHAINS_SELFIMPORT.size() == 0 )
|
||||
throw runtime_error("importgatewaybind only works on -ac_import chains");
|
||||
if ( fHelp || params.size() != 8)
|
||||
throw runtime_error("use \'importgatewaybind coin orcletxid M N pubkeys pubtype p2shtype wiftype [taddr]\' to bind an import gateway\n");
|
||||
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 0 )
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
CCerror = "";
|
||||
coin = params[0].get_str();
|
||||
oracletxid = Parseuint256(params[1].get_str().c_str());
|
||||
M = atoi(params[2].get_str().c_str());
|
||||
N = atoi(params[3].get_str().c_str());
|
||||
if ( M > N || N == 0 || N > 15 )
|
||||
throw runtime_error("illegal M or N > 15\n");
|
||||
if ( params.size() < 4+N+3 )
|
||||
throw runtime_error("not enough parameters for N pubkeys\n");
|
||||
for (i=0; i<N; i++)
|
||||
{
|
||||
pubkey = ParseHex(params[4+i].get_str().c_str());
|
||||
if (pubkey.size()!= 33)
|
||||
throw runtime_error("invalid destination pubkey");
|
||||
pubkeys.push_back(pubkey2pk(pubkey));
|
||||
}
|
||||
p1 = atoi((char *)params[4+N].get_str().c_str());
|
||||
p2 = atoi((char *)params[4+N+1].get_str().c_str());
|
||||
p3 = atoi((char *)params[4+N+2].get_str().c_str());
|
||||
if (params.size() == 7+N+1) p4 = atoi((char *)params[7+N].get_str().c_str());
|
||||
if (coin == "BEAM" || coin == "CODA")
|
||||
{
|
||||
ERR_RESULT("for BEAM and CODA import use importdual RPC");
|
||||
return result;
|
||||
}
|
||||
else if (coin != ASSETCHAINS_SELFIMPORT)
|
||||
{
|
||||
ERR_RESULT("source coin not equal to ac_import name");
|
||||
return result;
|
||||
}
|
||||
hex = ImportGatewayBind(0, coin, oracletxid, M, N, pubkeys, p1, p2, p3, p4);
|
||||
RETURN_IF_ERROR(CCerror);
|
||||
if ( hex.size() > 0 )
|
||||
{
|
||||
result.push_back(Pair("result", "success"));
|
||||
result.push_back(Pair("hex", hex));
|
||||
} else ERR_RESULT("couldnt importgatewaybind");
|
||||
return result;
|
||||
}
|
||||
|
||||
UniValue importgatewaydeposit(const UniValue& params, bool fHelp)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ);
|
||||
CMutableTransaction mtx; std::vector<uint8_t> rawproof;
|
||||
std::string hex,coin,rawburntx; int32_t height,burnvout;
|
||||
CPubKey destpub; std::vector<CTxOut> vouts; uint256 bindtxid,burntxid;
|
||||
|
||||
if ( ASSETCHAINS_SELFIMPORT.size() == 0 )
|
||||
throw runtime_error("importgatewaydeposit only works on -ac_import chains");
|
||||
if ( fHelp || params.size() != 8)
|
||||
throw runtime_error("use \'importgatewaydeposit bindtxid height coin burntxid nvout rawburntx rawproof destpub\' to import deposited coins\n");
|
||||
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 0 )
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
CCerror = "";
|
||||
bindtxid = Parseuint256(params[0].get_str().c_str());
|
||||
height = atoi(params[1].get_str().c_str());
|
||||
coin = params[2].get_str();
|
||||
burntxid = Parseuint256(params[3].get_str().c_str());
|
||||
burnvout = atoi(params[4].get_str().c_str());
|
||||
rawburntx = params[5].get_str();
|
||||
rawproof = ParseHex(params[6].get_str());
|
||||
destpub = ParseHex(params[7].get_str());
|
||||
if (coin == "BEAM" || coin == "CODA")
|
||||
{
|
||||
ERR_RESULT("for BEAM and CODA import use importdual RPC");
|
||||
return result;
|
||||
}
|
||||
else if (coin != ASSETCHAINS_SELFIMPORT)
|
||||
{
|
||||
ERR_RESULT("source coin not equal to ac_import name");
|
||||
return result;
|
||||
}
|
||||
hex = ImportGatewayDeposit(0, bindtxid, height, coin, burntxid, burnvout, rawburntx, rawproof, destpub);
|
||||
RETURN_IF_ERROR(CCerror);
|
||||
if ( hex.size() > 0 )
|
||||
{
|
||||
result.push_back(Pair("result", "success"));
|
||||
result.push_back(Pair("hex", hex));
|
||||
} else ERR_RESULT("couldnt importgatewaydeposit");
|
||||
return result;
|
||||
}
|
||||
|
||||
UniValue importgatewaywithdraw(const UniValue& params, bool fHelp)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ);
|
||||
CMutableTransaction mtx; std::vector<uint8_t> rawproof;
|
||||
std::string hex,coin,rawburntx; int64_t amount; int32_t height,burnvout;
|
||||
CPubKey destpub; std::vector<CTxOut> vouts; uint256 bindtxid,burntxid;
|
||||
|
||||
if ( ASSETCHAINS_SELFIMPORT.size() == 0 )
|
||||
throw runtime_error("importgatewaywithdraw only works on -ac_import chains");
|
||||
if ( fHelp || params.size() != 4)
|
||||
throw runtime_error("use \'importgatewaywithdraw bindtxid coin withdrawpub amount\' to burn imported coins and withdraw them on external chain\n");
|
||||
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 0 )
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
CCerror = "";
|
||||
bindtxid = Parseuint256(params[0].get_str().c_str());
|
||||
coin = params[1].get_str();
|
||||
destpub = ParseHex(params[2].get_str());
|
||||
amount = atof((char *)params[3].get_str().c_str()) * COIN + 0.00000000499999;
|
||||
if (coin == "BEAM" || coin == "CODA")
|
||||
{
|
||||
ERR_RESULT("for BEAM and CODA import use importdual RPC");
|
||||
return result;
|
||||
}
|
||||
else if (coin != ASSETCHAINS_SELFIMPORT)
|
||||
{
|
||||
ERR_RESULT("source coin not equal to ac_import name");
|
||||
return result;
|
||||
}
|
||||
hex = ImportGatewayWithdraw(0, bindtxid, coin, destpub, amount);
|
||||
RETURN_IF_ERROR(CCerror);
|
||||
if ( hex.size() > 0 )
|
||||
{
|
||||
result.push_back(Pair("result", "success"));
|
||||
result.push_back(Pair("hex", hex));
|
||||
} else ERR_RESULT("couldnt importgatewaywithdraw");
|
||||
return result;
|
||||
}
|
||||
|
||||
UniValue importgatewaypartialsign(const UniValue& params, bool fHelp)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ); std::string coin,parthex,hex; uint256 txid;
|
||||
|
||||
if ( ASSETCHAINS_SELFIMPORT.size() == 0 )
|
||||
throw runtime_error("importgatewayspartialsign only works on -ac_import chains");
|
||||
if ( fHelp || params.size() != 3 )
|
||||
throw runtime_error("importgatewayspartialsign txidaddr refcoin hex\n");
|
||||
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 0 )
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
txid = Parseuint256((char *)params[0].get_str().c_str());
|
||||
coin = params[1].get_str();
|
||||
parthex = params[2].get_str();
|
||||
hex = ImportGatewayPartialSign(0,txid,coin,parthex);
|
||||
if ( hex.size() > 0 )
|
||||
{
|
||||
result.push_back(Pair("result", "success"));
|
||||
result.push_back(Pair("hex",hex));
|
||||
} else ERR_RESULT("couldnt importgatewayspartialsign");
|
||||
return(result);
|
||||
}
|
||||
|
||||
UniValue importgatewaycompletesigning(const UniValue& params, bool fHelp)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ); uint256 withdrawtxid; std::string txhex,hex,coin;
|
||||
|
||||
if ( ASSETCHAINS_SELFIMPORT.size() == 0 )
|
||||
throw runtime_error("importgatewaycompletesigning only works on -ac_import chains");
|
||||
if ( fHelp || params.size() != 3 )
|
||||
throw runtime_error("importgatewaycompletesigning withdrawtxid coin hex\n");
|
||||
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 0 )
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
withdrawtxid = Parseuint256((char *)params[0].get_str().c_str());
|
||||
coin = params[1].get_str();
|
||||
txhex = params[2].get_str();
|
||||
hex = ImportGatewayCompleteSigning(0,withdrawtxid,coin,txhex);
|
||||
RETURN_IF_ERROR(CCerror);
|
||||
if ( hex.size() > 0 )
|
||||
{
|
||||
result.push_back(Pair("result", "success"));
|
||||
result.push_back(Pair("hex", hex));
|
||||
} else ERR_RESULT("couldnt importgatewaycompletesigning");
|
||||
return(result);
|
||||
}
|
||||
|
||||
UniValue importgatewaymarkdone(const UniValue& params, bool fHelp)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ); uint256 completetxid; std::string hex,coin;
|
||||
if ( fHelp || params.size() != 2 )
|
||||
throw runtime_error("importgatewaymarkdone completesigningtx coin\n");
|
||||
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 0 )
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
completetxid = Parseuint256((char *)params[0].get_str().c_str());
|
||||
coin = params[1].get_str();
|
||||
hex = ImportGatewayMarkDone(0,completetxid,coin);
|
||||
RETURN_IF_ERROR(CCerror);
|
||||
if ( hex.size() > 0 )
|
||||
{
|
||||
result.push_back(Pair("result", "success"));
|
||||
result.push_back(Pair("hex", hex));
|
||||
} else ERR_RESULT("couldnt importgatewaymarkdone");
|
||||
return(result);
|
||||
}
|
||||
|
||||
UniValue importgatewaypendingdeposits(const UniValue& params, bool fHelp)
|
||||
{
|
||||
uint256 bindtxid; std::string coin;
|
||||
if ( fHelp || params.size() != 2 )
|
||||
throw runtime_error("importgatewaypendingdeposits bindtxid coin\n");
|
||||
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 0 )
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
bindtxid = Parseuint256((char *)params[0].get_str().c_str());
|
||||
coin = params[1].get_str();
|
||||
return(ImportGatewayPendingDeposits(bindtxid,coin));
|
||||
}
|
||||
|
||||
UniValue importgatewaypendingwithdraws(const UniValue& params, bool fHelp)
|
||||
{
|
||||
uint256 bindtxid; std::string coin;
|
||||
if ( fHelp || params.size() != 2 )
|
||||
throw runtime_error("importgatewaypendingwithdraws bindtxid coin\n");
|
||||
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 0 )
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
bindtxid = Parseuint256((char *)params[0].get_str().c_str());
|
||||
coin = params[1].get_str();
|
||||
return(ImportGatewayPendingWithdraws(bindtxid,coin));
|
||||
}
|
||||
|
||||
UniValue importgatewayprocessed(const UniValue& params, bool fHelp)
|
||||
{
|
||||
uint256 bindtxid; std::string coin;
|
||||
if ( fHelp || params.size() != 2 )
|
||||
throw runtime_error("importgatewayprocessed bindtxid coin\n");
|
||||
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 0 )
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
bindtxid = Parseuint256((char *)params[0].get_str().c_str());
|
||||
coin = params[1].get_str();
|
||||
return(ImportGatewayProcessedWithdraws(bindtxid,coin));
|
||||
}
|
||||
|
||||
UniValue importgatewayexternaladdress(const UniValue& params, bool fHelp)
|
||||
{
|
||||
uint256 bindtxid; CPubKey pubkey;
|
||||
|
||||
if ( fHelp || params.size() != 2)
|
||||
throw runtime_error("importgatewayexternaladdress bindtxid pubkey\n");
|
||||
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 0 )
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
bindtxid = Parseuint256((char *)params[0].get_str().c_str());
|
||||
pubkey = ParseHex(params[1].get_str().c_str());
|
||||
return(ImportGatewayExternalAddress(bindtxid,pubkey));
|
||||
}
|
||||
|
||||
UniValue importgatewaydumpprivkey(const UniValue& params, bool fHelp)
|
||||
{
|
||||
uint256 bindtxid;
|
||||
|
||||
if ( fHelp || params.size() != 2)
|
||||
throw runtime_error("importgatewaydumpprivkey bindtxid address\n");
|
||||
if ( ensure_CCrequirements(EVAL_IMPORTGATEWAY) < 0 )
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
bindtxid = Parseuint256((char *)params[0].get_str().c_str());
|
||||
std::string strAddress = params[1].get_str();
|
||||
CTxDestination dest = DecodeDestination(strAddress);
|
||||
if (!IsValidDestination(dest)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid transparent address");
|
||||
}
|
||||
const CKeyID *keyID = boost::get<CKeyID>(&dest);
|
||||
if (!keyID) {
|
||||
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key");
|
||||
}
|
||||
CKey vchSecret;
|
||||
// if (!pwalletMain->GetKey(*keyID, vchSecret)) {
|
||||
// throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known");
|
||||
//}
|
||||
return(ImportGatewayDumpPrivKey(bindtxid,vchSecret));
|
||||
}
|
||||
|
||||
UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp)
|
||||
{
|
||||
// TODO take timestamp as param, and loop blockindex to get starting/finish height.
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error("getNotarisationsForBlock height\n\n"
|
||||
"Takes a block height and returns notarisation information "
|
||||
"within the block");
|
||||
|
||||
LOCK(cs_main);
|
||||
int32_t height = params[0].get_int();
|
||||
if ( height < 0 || height > chainActive.Height() )
|
||||
throw runtime_error("height out of range.\n");
|
||||
|
||||
uint256 blockHash = chainActive[height]->GetBlockHash();
|
||||
|
||||
NotarisationsInBlock nibs;
|
||||
GetBlockNotarisations(blockHash, nibs);
|
||||
UniValue out(UniValue::VOBJ);
|
||||
//out.push_back(make_pair("blocktime",(int)));
|
||||
UniValue labs(UniValue::VARR);
|
||||
UniValue kmd(UniValue::VARR);
|
||||
// Gets KMD notaries on KMD... but LABS notaries on labs chains needs to be fixed so LABS are identified on KMD.
|
||||
int8_t numNN = 0; uint8_t notarypubkeys[64][33] = {0};
|
||||
numNN = komodo_notaries(notarypubkeys, height, chainActive[height]->nTime);
|
||||
|
||||
BOOST_FOREACH(const Notarisation& n, nibs)
|
||||
{
|
||||
UniValue item(UniValue::VOBJ); UniValue notaryarr(UniValue::VARR); std::vector<int8_t> NotarisationNotaries;
|
||||
if ( is_STAKED(n.second.symbol) != 0 )
|
||||
continue; // for now just skip this... need to fetch diff pubkeys for these chains. labs.push_back(item);
|
||||
uint256 hash; CTransaction tx;
|
||||
if ( GetTransaction(n.first,tx,hash,false) )
|
||||
{
|
||||
if ( !GetNotarisationNotaries(notarypubkeys, numNN, tx.vin, NotarisationNotaries) )
|
||||
continue;
|
||||
if ( NotarisationNotaries.size() < numNN/5 )
|
||||
continue;
|
||||
}
|
||||
item.push_back(make_pair("txid", n.first.GetHex()));
|
||||
item.push_back(make_pair("chain", n.second.symbol));
|
||||
item.push_back(make_pair("height", (int)n.second.height));
|
||||
item.push_back(make_pair("blockhash", n.second.blockHash.GetHex()));
|
||||
item.push_back(make_pair("KMD_height", height)); // for when timstamp input is used.
|
||||
|
||||
for ( auto notary : NotarisationNotaries )
|
||||
notaryarr.push_back(notary);
|
||||
item.push_back(make_pair("notaries",notaryarr));
|
||||
kmd.push_back(item);
|
||||
}
|
||||
out.push_back(make_pair("KMD", kmd));
|
||||
//out.push_back(make_pair("LABS", labs));
|
||||
return out;
|
||||
}
|
||||
|
||||
/*UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error("getNotarisationsForBlock blockHash\n\n"
|
||||
@@ -426,7 +824,7 @@ UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp)
|
||||
out.push_back(item);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
UniValue scanNotarisationsDB(const UniValue& params, bool fHelp)
|
||||
@@ -536,9 +934,9 @@ UniValue getimports(const UniValue& params, bool fHelp)
|
||||
UniValue objTx(UniValue::VOBJ);
|
||||
objTx.push_back(Pair("txid",tx.GetHash().ToString()));
|
||||
TxProof proof; CTransaction burnTx; std::vector<CTxOut> payouts; CTxDestination importaddress;
|
||||
TotalImported += tx.vout[1].nValue;
|
||||
objTx.push_back(Pair("amount", ValueFromAmount(tx.vout[1].nValue)));
|
||||
if (ExtractDestination(tx.vout[1].scriptPubKey, importaddress))
|
||||
TotalImported += tx.vout[0].nValue;
|
||||
objTx.push_back(Pair("amount", ValueFromAmount(tx.vout[0].nValue)));
|
||||
if (ExtractDestination(tx.vout[0].scriptPubKey, importaddress))
|
||||
{
|
||||
objTx.push_back(Pair("address", CBitcoinAddress(importaddress).ToString()));
|
||||
}
|
||||
|
||||
@@ -853,8 +853,9 @@ bool getAddressFromIndex(const int &type, const uint160 &hash, std::string &addr
|
||||
address = CBitcoinAddress(CScriptID(hash)).ToString();
|
||||
} else if (type == 1) {
|
||||
address = CBitcoinAddress(CKeyID(hash)).ToString();
|
||||
}
|
||||
else {
|
||||
} else if (type == 3) {
|
||||
address = CBitcoinAddress(CKeyID(hash)).ToString();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -354,6 +354,21 @@ static const CRPCCommand vRPCCommands[] =
|
||||
{ "crosschain", "migrate_createimporttransaction", &migrate_createimporttransaction, true },
|
||||
{ "crosschain", "migrate_completeimporttransaction", &migrate_completeimporttransaction, true },
|
||||
{ "crosschain", "selfimport", &selfimport, true },
|
||||
{ "crosschain", "importdual", &importdual, true },
|
||||
//ImportGateway
|
||||
{ "crosschain", "importgatewayddress", &importgatewayaddress, true },
|
||||
{ "crosschain", "importgatewayinfo", &importgatewayinfo, true },
|
||||
{ "crosschain", "importgatewaybind", &importgatewaybind, true },
|
||||
{ "crosschain", "importgatewaydeposit", &importgatewaydeposit, true },
|
||||
{ "crosschain", "importgatewaywithdraw", &importgatewaywithdraw, true },
|
||||
{ "crosschain", "importgatewaypartialsign", &importgatewaypartialsign, true },
|
||||
{ "crosschain", "importgatewaycompletesigning", &importgatewaycompletesigning, true },
|
||||
{ "crosschain", "importgatewaymarkdone", &importgatewaymarkdone, true },
|
||||
{ "crosschain", "importgatewaypendingdeposits", &importgatewaypendingdeposits, true },
|
||||
{ "crosschain", "importgatewaypendingwithdraws", &importgatewaypendingwithdraws, true },
|
||||
{ "crosschain", "importgatewayprocessed", &importgatewayprocessed, true },
|
||||
|
||||
|
||||
|
||||
/* Mining */
|
||||
{ "mining", "getblocktemplate", &getblocktemplate, true },
|
||||
@@ -441,14 +456,10 @@ static const CRPCCommand vRPCCommands[] =
|
||||
{ "oracles", "oraclessamples", &oraclessamples, true },
|
||||
|
||||
// Prices
|
||||
{ "prices", "prices", &prices, true },
|
||||
{ "prices", "pricesaddress", &pricesaddress, true },
|
||||
{ "prices", "priceslist", &priceslist, true },
|
||||
{ "prices", "pricesinfo", &pricesinfo, true },
|
||||
{ "prices", "pricescreate", &pricescreate, true },
|
||||
{ "prices", "pricesaddfunding", &pricesaddfunding, true },
|
||||
{ "prices", "pricesbet", &pricesbet, true },
|
||||
{ "prices", "pricesstatus", &pricesstatus, true },
|
||||
{ "prices", "pricesfinish", &pricesfinish, true },
|
||||
|
||||
// Pegs
|
||||
{ "pegs", "pegsaddress", &pegsaddress, true },
|
||||
@@ -466,6 +477,12 @@ static const CRPCCommand vRPCCommands[] =
|
||||
|
||||
// Payments
|
||||
{ "payments", "paymentsaddress", &paymentsaddress, true },
|
||||
{ "payments", "paymentstxidopret", &payments_txidopret, true },
|
||||
{ "payments", "paymentscreate", &payments_create, true },
|
||||
{ "payments", "paymentslist", &payments_list, true },
|
||||
{ "payments", "paymentsinfo", &payments_info, true },
|
||||
{ "payments", "paymentsfund", &payments_fund, true },
|
||||
{ "payments", "paymentsrelease", &payments_release, true },
|
||||
|
||||
{ "CClib", "cclibaddress", &cclibaddress, true },
|
||||
{ "CClib", "cclibinfo", &cclibinfo, true },
|
||||
|
||||
@@ -272,11 +272,6 @@ extern UniValue oraclessamples(const UniValue& params, bool fHelp);
|
||||
extern UniValue pricesaddress(const UniValue& params, bool fHelp);
|
||||
extern UniValue priceslist(const UniValue& params, bool fHelp);
|
||||
extern UniValue pricesinfo(const UniValue& params, bool fHelp);
|
||||
extern UniValue pricescreate(const UniValue& params, bool fHelp);
|
||||
extern UniValue pricesaddfunding(const UniValue& params, bool fHelp);
|
||||
extern UniValue pricesbet(const UniValue& params, bool fHelp);
|
||||
extern UniValue pricesstatus(const UniValue& params, bool fHelp);
|
||||
extern UniValue pricesfinish(const UniValue& params, bool fHelp);
|
||||
extern UniValue pegsaddress(const UniValue& params, bool fHelp);
|
||||
extern UniValue marmaraaddress(const UniValue& params, bool fHelp);
|
||||
extern UniValue marmara_poolpayout(const UniValue& params, bool fHelp);
|
||||
@@ -288,6 +283,13 @@ 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 payments_release(const UniValue& params, bool fHelp);
|
||||
extern UniValue payments_fund(const UniValue& params, bool fHelp);
|
||||
extern UniValue payments_txidopret(const UniValue& params, bool fHelp);
|
||||
extern UniValue payments_create(const UniValue& params, bool fHelp);
|
||||
extern UniValue payments_info(const UniValue& params, bool fHelp);
|
||||
extern UniValue payments_list(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);
|
||||
@@ -312,7 +314,6 @@ extern UniValue channelsopen(const UniValue& params, bool fHelp);
|
||||
extern UniValue channelspayment(const UniValue& params, bool fHelp);
|
||||
extern UniValue channelsclose(const UniValue& params, bool fHelp);
|
||||
extern UniValue channelsrefund(const UniValue& params, bool fHelp);
|
||||
|
||||
//extern UniValue tokenswapask(const UniValue& params, bool fHelp);
|
||||
//extern UniValue tokenfillswap(const UniValue& params, bool fHelp);
|
||||
extern UniValue faucetfund(const UniValue& params, bool fHelp);
|
||||
@@ -433,6 +434,18 @@ extern UniValue invalidateblock(const UniValue& params, bool fHelp);
|
||||
extern UniValue reconsiderblock(const UniValue& params, bool fHelp);
|
||||
extern UniValue getspentinfo(const UniValue& params, bool fHelp);
|
||||
extern UniValue selfimport(const UniValue& params, bool fHelp);
|
||||
extern UniValue importdual(const UniValue& params, bool fHelp);
|
||||
extern UniValue importgatewayaddress(const UniValue& params, bool fHelp);
|
||||
extern UniValue importgatewayinfo(const UniValue& params, bool fHelp);
|
||||
extern UniValue importgatewaybind(const UniValue& params, bool fHelp);
|
||||
extern UniValue importgatewaydeposit(const UniValue& params, bool fHelp);
|
||||
extern UniValue importgatewaywithdraw(const UniValue& params, bool fHelp);
|
||||
extern UniValue importgatewaypartialsign(const UniValue& params, bool fHelp);
|
||||
extern UniValue importgatewaycompletesigning(const UniValue& params, bool fHelp);
|
||||
extern UniValue importgatewaymarkdone(const UniValue& params, bool fHelp);
|
||||
extern UniValue importgatewaypendingdeposits(const UniValue& params, bool fHelp);
|
||||
extern UniValue importgatewaypendingwithdraws(const UniValue& params, bool fHelp);
|
||||
extern UniValue importgatewayprocessed(const UniValue& params, bool fHelp);
|
||||
|
||||
extern UniValue getblocksubsidy(const UniValue& params, bool fHelp);
|
||||
|
||||
@@ -479,6 +492,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);
|
||||
|
||||
extern UniValue prices(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);
|
||||
|
||||
21
src/tui/LICENSE
Normal file
21
src/tui/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Anton Lysakov
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
58
src/tui/README.md
Normal file
58
src/tui/README.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Komodo Cryptoconditons Terminal User Interfaces (aka TUIs)
|
||||
|
||||
These tools creating for demonstration and partial automation of Komodo cryptoconditions modules testing. (RogueCC game, AssetsCC, OraclesCC, GatewaysCC, MarmaraCC, ...)
|
||||
|
||||
|
||||
Developer installation (on Ubuntu 18.04) :
|
||||
|
||||
Python3 required for execution:
|
||||
|
||||
* `sudo apt-get install python3.6 python3-pip libgnutls28-dev`
|
||||
|
||||
pip packages needed:
|
||||
|
||||
* `pip3 install setuptools wheel slick-bitcoinrpc`
|
||||
* or `pip3 install -r requirements.txt`
|
||||
|
||||
Starting:
|
||||
|
||||
# TUI for RogueCC
|
||||
|
||||
If you're looking for player 3 in 1 (daemon + game + TUI) multiOS bundle - please check `releases` of this repo.
|
||||
|
||||
`python3 rogue_tui.py`
|
||||
|
||||

|
||||
|
||||
# TUI for OraclesCC
|
||||
|
||||
Have files uploader/downloader functionality - also there is a AWS branch for AWS certificates uploading demonstration
|
||||
|
||||
`python3 oracles_cc_tui.py`
|
||||
|
||||

|
||||
|
||||
# TUI for GatewaysCC
|
||||
|
||||

|
||||
|
||||
`python3 gateways_creation_tui.py`
|
||||
|
||||
`python3 gateways_usage_tui.py`
|
||||
|
||||
At the moment raw version of manual gateway how-to guide can be found here: https://docs.komodoplatform.com/cc/contracts/gateways/scenarios/tutorial.html I advice to read it before you start use this tool to understand the flow.
|
||||
|
||||
# TUI for MarmaraCC
|
||||
|
||||
`python3 marmara_tui.py`
|
||||
|
||||

|
||||
|
||||
# TUI for AssetsCC (not much finished)
|
||||
|
||||
`python3 assets_cc_tui.py`
|
||||
|
||||
Before execution be sure than daemon for needed AC up.
|
||||
|
||||
|
||||
|
||||
39
src/tui/lib/logo.txt
Normal file
39
src/tui/lib/logo.txt
Normal file
@@ -0,0 +1,39 @@
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0xlc:ldOKNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0xo:,........';lxOXNMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMWNKkoc,..................':ox0XWMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMWNKkdc;............................,:ok0NWMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMWNKOdl;'.....................................,cdkKNWMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMW0c'..............................................';kNMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMK:......................';:c:'......................,kWMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMXl...................;cdkKNWWNXOdl;'..................;OWMMMMMMMMMMM
|
||||
MMMMMMMMMMMNo...............,cok0XWMMMMMMMMMMWNKkdc;'..............:KMMMMMMMMMMM
|
||||
MMMMMMMMMMWx'...........;ox0XWMMMMMMMMMMMMMMMMMMMMWNKko:............lXMMMMMMMMMM
|
||||
MMMMMMMMMWk,...........lXWMMMMMMMMMMMMWWWWMMMMMMMMMMMMMNx'...........oNMMMMMMMMM
|
||||
MMMMMMMMW0;...........cKMMMMMMMMMWNXOdl::cdkKNWMMMMMMMMMNo...........'xWMMMMMMMM
|
||||
MMMMMMMMKc...........;0WMMMMMWN0xl:,........';ldOXWMMMMMMXl...........,OWMMMMMMM
|
||||
MMMMMMMXl...........,kWMMMMMMKl..................;OWMMMMMMK:...........;0MMMMMMM
|
||||
MMMMMMNd...........'xNMMMMMMXl....................:0WMMMMMWO;...........cKMMMMMM
|
||||
MMMMMNx'...........oNMMMMMMNd......................cKMMMMMMWk'...........lXMMMMM
|
||||
MMMMWO,...........lXMMMMMMWx'.......................oXMMMMMMNd'...........dNMMMM
|
||||
MMMMXc...........,OWMMMMMMK:........................,kWMMMMMMKc...........;0MMMM
|
||||
MMMMWx'...........oXMMMMMMNd........................cKMMMMMMWk,...........lXMMMM
|
||||
MMMMMNd...........'dNMMMMMMXl......................:0MMMMMMWO;...........cKMMMMM
|
||||
MMMMMMXl...........,kWMMMMMMKc....................,OWMMMMMM0:...........;0MMMMMM
|
||||
MMMMMMMKc...........;OWMMMMMW0:..................,kWMMMMMMXc...........,OWMMMMMM
|
||||
MMMMMMMM0;...........:KMMMMMMWKko:,..........';lx0WMMMMMMNo...........'xWMMMMMMM
|
||||
MMMMMMMMWk,...........lXMMMMMMMMWWXOxl:,,;cdOKNWMMMMMMMMNx'...........dNMMMMMMMM
|
||||
MMMMMMMMMWx'...........dNMMMMMMMMMMMMWNXXNWMMMMMMMMMMMMWk,...........lXMMMMMMMMM
|
||||
MMMMMMMMMMNo............cx0XWMMMMMMMMMMMMMMMMMMMMMMWN0kl,...........cKMMMMMMMMMM
|
||||
MMMMMMMMMMMXl..............,:ok0XWMMMMMMMMMMMMWNKkdc;..............;0WMMMMMMMMMM
|
||||
MMMMMMMMMMMMK:..................,cokKNWMMWNKOdl;'.................,kWMMMMMMMMMMM
|
||||
MMMMMMMMMMMMWO;......................;cool;'.....................'xNMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMWk;................................................'dNMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMWXOxl;'.......................................,cdkKWMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMWNKOdc;..............................,cok0NWMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMWNKkoc,....................,:ox0XWMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0ko:,..........':lx0XWMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0xl:,,;ldOKNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNNXNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
129
src/tui/lib/rpclib.py
Normal file
129
src/tui/lib/rpclib.py
Normal file
@@ -0,0 +1,129 @@
|
||||
import http
|
||||
from slickrpc import Proxy
|
||||
|
||||
|
||||
# RPC connection
|
||||
def rpc_connect(rpc_user, rpc_password, port):
|
||||
try:
|
||||
rpc_connection = Proxy("http://%s:%s@127.0.0.1:%d"%(rpc_user, rpc_password, port))
|
||||
except Exception:
|
||||
raise Exception("Connection error! Probably no daemon on selected port.")
|
||||
return rpc_connection
|
||||
|
||||
|
||||
# Non CC calls
|
||||
def getinfo(rpc_connection):
|
||||
try:
|
||||
getinfo = rpc_connection.getinfo()
|
||||
except Exception:
|
||||
raise Exception("Connection error!")
|
||||
return getinfo
|
||||
|
||||
|
||||
def sendrawtransaction(rpc_connection, hex):
|
||||
tx_id = rpc_connection.sendrawtransaction(hex)
|
||||
return tx_id
|
||||
|
||||
|
||||
def gettransaction(rpc_connection, tx_id):
|
||||
transaction_info = rpc_connection.gettransaction(tx_id)
|
||||
return transaction_info
|
||||
|
||||
|
||||
def getrawtransaction(rpc_connection, tx_id):
|
||||
rawtransaction = rpc_connection.getrawtransaction(tx_id)
|
||||
return rawtransaction
|
||||
|
||||
|
||||
def getbalance(rpc_connection):
|
||||
balance = rpc_connection.getbalance()
|
||||
return balance
|
||||
|
||||
# Token CC calls
|
||||
def token_create(rpc_connection, name, supply, description):
|
||||
token_hex = rpc_connection.tokencreate(name, supply, description)
|
||||
return token_hex
|
||||
|
||||
|
||||
def token_info(rpc_connection, token_id):
|
||||
token_info = rpc_connection.tokeninfo(token_id)
|
||||
return token_info
|
||||
|
||||
|
||||
#TODO: have to add option with pubkey input
|
||||
def token_balance(rpc_connection, token_id):
|
||||
token_balance = rpc_connection.tokenbalance(token_id)
|
||||
return token_balance
|
||||
|
||||
def token_list(rpc_connection):
|
||||
token_list = rpc_connection.tokenlist()
|
||||
return token_list
|
||||
|
||||
|
||||
def token_convert(rpc_connection, evalcode, token_id, pubkey, supply):
|
||||
token_convert_hex = rpc_connection.tokenconvert(evalcode, token_id, pubkey, supply)
|
||||
return token_convert_hex
|
||||
|
||||
def get_rawmempool(rpc_connection):
|
||||
mempool = rpc_connection.getrawmempool()
|
||||
return mempool
|
||||
|
||||
# Oracle CC calls
|
||||
def oracles_create(rpc_connection, name, description, data_type):
|
||||
oracles_hex = rpc_connection.oraclescreate(name, description, data_type)
|
||||
return oracles_hex
|
||||
|
||||
|
||||
def oracles_register(rpc_connection, oracle_id, data_fee):
|
||||
oracles_register_hex = rpc_connection.oraclesregister(oracle_id, data_fee)
|
||||
return oracles_register_hex
|
||||
|
||||
|
||||
def oracles_subscribe(rpc_connection, oracle_id, publisher_id, data_fee):
|
||||
oracles_subscribe_hex = rpc_connection.oraclessubscribe(oracle_id, publisher_id, data_fee)
|
||||
return oracles_subscribe_hex
|
||||
|
||||
|
||||
def oracles_info(rpc_connection, oracle_id):
|
||||
oracles_info = rpc_connection.oraclesinfo(oracle_id)
|
||||
return oracles_info
|
||||
|
||||
|
||||
def oracles_data(rpc_connection, oracle_id, hex_string):
|
||||
oracles_data = rpc_connection.oraclesdata(oracle_id, hex_string)
|
||||
return oracles_data
|
||||
|
||||
|
||||
def oracles_list(rpc_connection):
|
||||
oracles_list = rpc_connection.oracleslist()
|
||||
return oracles_list
|
||||
|
||||
|
||||
def oracles_samples(rpc_connection, oracletxid, batonutxo, num):
|
||||
oracles_sample = rpc_connection.oraclessamples(oracletxid, batonutxo, num)
|
||||
return oracles_sample
|
||||
|
||||
|
||||
# Gateways CC calls
|
||||
# Arguments changing dynamically depends of M N, so supposed to wrap it this way
|
||||
# token_id, oracle_id, coin_name, token_supply, M, N + pubkeys for each N
|
||||
def gateways_bind(rpc_connection, *args):
|
||||
gateways_bind_hex = rpc_connection.gatewaysbind(*args)
|
||||
return gateways_bind_hex
|
||||
|
||||
|
||||
def gateways_deposit(rpc_connection, gateway_id, height, coin_name,\
|
||||
coin_txid, claim_vout, deposit_hex, proof, dest_pub, amount):
|
||||
gateways_deposit_hex = rpc_connection.gatewaysdeposit(gateway_id, height, coin_name,\
|
||||
coin_txid, claim_vout, deposit_hex, proof, dest_pub, amount)
|
||||
return gateways_deposit_hex
|
||||
|
||||
|
||||
def gateways_claim(rpc_connection, gateway_id, coin_name, deposit_txid, dest_pub, amount):
|
||||
gateways_claim_hex = rpc_connection.gatewaysclaim(gateway_id, coin_name, deposit_txid, dest_pub, amount)
|
||||
return gateways_claim_hex
|
||||
|
||||
|
||||
def gateways_withdraw(rpc_connection, gateway_id, coin_name, withdraw_pub, amount):
|
||||
gateways_withdraw_hex = rpc_connection.gatewayswithdraw(gateway_id, coin_name, withdraw_pub, amount)
|
||||
return gateways_withdraw_hex
|
||||
1974
src/tui/lib/tuilib.py
Executable file
1974
src/tui/lib/tuilib.py
Executable file
File diff suppressed because it is too large
Load Diff
8
src/tui/requirements.txt
Normal file
8
src/tui/requirements.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
configobj==5.0.6
|
||||
pip==9.0.1
|
||||
pycurl==7.43.0.2
|
||||
setuptools==39.0.1
|
||||
six==1.12.0
|
||||
slick-bitcoinrpc==0.1.4
|
||||
ujson==1.35
|
||||
wheel==0.32.3
|
||||
67
src/tui/tui_assets.py
Executable file
67
src/tui/tui_assets.py
Executable file
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from lib import rpclib, tuilib
|
||||
import os
|
||||
import time
|
||||
|
||||
|
||||
header = "\
|
||||
___ _ _____ \n\
|
||||
/ _ \ | | / __ \\\n\
|
||||
/ /_\ \ ___ ___ ___ | |_ ___ | / \/\n\
|
||||
| _ |/ __|/ __| / _ \| __|/ __|| | \n\
|
||||
| | | |\__ \\\__ \| __/| |_ \__ \| \__/\\\n\
|
||||
\_| |_/|___/|___/ \___| \__||___/ \____/\n"
|
||||
|
||||
|
||||
menuItems = [
|
||||
{"Check current connection": tuilib.getinfo_tui},
|
||||
{"Check mempool": tuilib.print_mempool},
|
||||
{"Print tokens list": tuilib.print_tokens_list},
|
||||
{"Check my tokens balances" : tuilib.print_tokens_balances},
|
||||
# transfer tokens (pre-print tokens balances)
|
||||
{"Create token": tuilib.token_create_tui},
|
||||
# trading zone - pre-print token orders - possible to open order or fill existing one
|
||||
{"Exit": exit}
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
while True:
|
||||
os.system('clear')
|
||||
print(tuilib.colorize(header, 'pink'))
|
||||
print(tuilib.colorize('CLI version 0.2 by Anton Lysakov\n', 'green'))
|
||||
for item in menuItems:
|
||||
print(tuilib.colorize("[" + str(menuItems.index(item)) + "] ", 'blue') + list(item.keys())[0])
|
||||
choice = input(">> ")
|
||||
try:
|
||||
if int(choice) < 0:
|
||||
raise ValueError
|
||||
# Call the matching function
|
||||
if list(menuItems[int(choice)].keys())[0] == "Exit":
|
||||
list(menuItems[int(choice)].values())[0]()
|
||||
else:
|
||||
list(menuItems[int(choice)].values())[0](rpc_connection)
|
||||
except (ValueError, IndexError):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
while True:
|
||||
try:
|
||||
print(tuilib.colorize("Welcome to the GatewaysCC TUI!\n"
|
||||
"Please provide asset chain RPC connection details for initialization", "blue"))
|
||||
rpc_connection = tuilib.rpc_connection_tui()
|
||||
rpclib.getinfo(rpc_connection)
|
||||
except Exception:
|
||||
print(tuilib.colorize("Cant connect to RPC! Please re-check credentials.", "pink"))
|
||||
else:
|
||||
print(tuilib.colorize("Succesfully connected!\n", "green"))
|
||||
with (open("lib/logo.txt", "r")) as logo:
|
||||
for line in logo:
|
||||
print(line, end='')
|
||||
time.sleep(0.04)
|
||||
print("\n")
|
||||
break
|
||||
main()
|
||||
|
||||
67
src/tui/tui_gateways_creation.py
Executable file
67
src/tui/tui_gateways_creation.py
Executable file
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from lib import rpclib, tuilib
|
||||
import os
|
||||
import time
|
||||
|
||||
header = "\
|
||||
_____ _ _____ _____ \n\
|
||||
| __ \ | | / __ \/ __ \\\n\
|
||||
| | \/ __ _| |_ _____ ____ _ _ _ ___| / \/| / \/\n\
|
||||
| | __ / _` | __/ _ \ \ /\ / / _` | | | / __| | | | \n\
|
||||
| |_\ \ (_| | || __/\ V V / (_| | |_| \__ \ \__/\| \__/\\\n\
|
||||
\____/\__,_|\__\___| \_/\_/ \__,_|\__, |___/\____/ \____/\n\
|
||||
__/ | \n\
|
||||
|___/ \n"
|
||||
|
||||
|
||||
menuItems = [
|
||||
{"Check current connection": tuilib.getinfo_tui},
|
||||
{"Check mempool": tuilib.print_mempool},
|
||||
{"Create token": tuilib.token_create_tui},
|
||||
{"Create oracle": tuilib.oracle_create_tui},
|
||||
{"Register as publisher for oracle": tuilib.oracle_register_tui},
|
||||
{"Subscribe on oracle (+UTXO generator)": tuilib.oracle_subscription_utxogen},
|
||||
{"Bind Gateway": tuilib.gateways_bind_tui},
|
||||
{"Exit": exit}
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
while True:
|
||||
os.system('clear')
|
||||
print(tuilib.colorize(header, 'pink'))
|
||||
print(tuilib.colorize('CLI version 0.2\n', 'green'))
|
||||
for item in menuItems:
|
||||
print(tuilib.colorize("[" + str(menuItems.index(item)) + "] ", 'blue') + list(item.keys())[0])
|
||||
choice = input(">> ")
|
||||
try:
|
||||
if int(choice) < 0:
|
||||
raise ValueError
|
||||
# Call the matching function
|
||||
if list(menuItems[int(choice)].keys())[0] == "Exit":
|
||||
list(menuItems[int(choice)].values())[0]()
|
||||
else:
|
||||
list(menuItems[int(choice)].values())[0](rpc_connection)
|
||||
except (ValueError, IndexError):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
while True:
|
||||
try:
|
||||
print(tuilib.colorize("Welcome to the GatewaysCC TUI!\n"
|
||||
"Please provide asset chain RPC connection details for initialization", "blue"))
|
||||
rpc_connection = tuilib.rpc_connection_tui()
|
||||
rpclib.getinfo(rpc_connection)
|
||||
except Exception:
|
||||
print(tuilib.colorize("Cant connect to RPC! Please re-check credentials.", "pink"))
|
||||
else:
|
||||
print(tuilib.colorize("Succesfully connected!\n", "green"))
|
||||
with (open("lib/logo.txt", "r")) as logo:
|
||||
for line in logo:
|
||||
print(line, end='')
|
||||
time.sleep(0.04)
|
||||
print("\n")
|
||||
break
|
||||
main()
|
||||
96
src/tui/tui_gateways_usage.py
Executable file
96
src/tui/tui_gateways_usage.py
Executable file
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from lib import rpclib, tuilib
|
||||
import os, time
|
||||
|
||||
header = "\
|
||||
_____ _ _____ _____ \n\
|
||||
| __ \ | | / __ \/ __ \\\n\
|
||||
| | \/ __ _| |_ _____ ____ _ _ _ ___| / \/| / \/\n\
|
||||
| | __ / _` | __/ _ \ \ /\ / / _` | | | / __| | | | \n\
|
||||
| |_\ \ (_| | || __/\ V V / (_| | |_| \__ \ \__/\| \__/\\\n\
|
||||
\____/\__,_|\__\___| \_/\_/ \__,_|\__, |___/\____/ \____/\n\
|
||||
__/ | \n\
|
||||
|___/ \n"
|
||||
|
||||
menuItems = [
|
||||
{"Check connection to assetchain": tuilib.getinfo_tui},
|
||||
{"Check assetchain mempool": tuilib.print_mempool},
|
||||
{"Check connection to KMD": tuilib.getinfo_tui},
|
||||
{"Connect to KMD daemon": tuilib.rpc_kmd_connection_tui},
|
||||
{"Send KMD gateway deposit transaction": tuilib.gateways_send_kmd},
|
||||
{"Execute gateways deposit": tuilib.gateways_deposit_tui},
|
||||
{"Execute gateways claim": tuilib.gateways_claim_tui},
|
||||
{"Execute gateways withdrawal": tuilib.gateways_withdrawal_tui},
|
||||
{"Exit": exit}
|
||||
]
|
||||
|
||||
def main():
|
||||
while True:
|
||||
os.system('clear')
|
||||
print(tuilib.colorize(header, 'pink'))
|
||||
print(tuilib.colorize('CLI version 0.2\n', 'green'))
|
||||
for item in menuItems:
|
||||
print(tuilib.colorize("[" + str(menuItems.index(item)) + "] ", 'blue') + list(item.keys())[0])
|
||||
choice = input(">> ")
|
||||
try:
|
||||
if int(choice) < 0:
|
||||
raise ValueError
|
||||
# Call the matching function
|
||||
if list(menuItems[int(choice)].keys())[0] == "Exit":
|
||||
list(menuItems[int(choice)].values())[0]()
|
||||
# We have to call KMD specific functions with connection to KMD daemon
|
||||
elif list(menuItems[int(choice)].keys())[0] == "Connect to KMD daemon":
|
||||
rpc_connection_kmd = list(menuItems[int(choice)].values())[0]()
|
||||
elif list(menuItems[int(choice)].keys())[0] == "Check connection to KMD":
|
||||
while True:
|
||||
try:
|
||||
list(menuItems[int(choice)].values())[0](rpc_connection_kmd)
|
||||
break
|
||||
except Exception as e:
|
||||
print("Please connect to KMD daemon first!")
|
||||
input("Press [Enter] to continue...")
|
||||
break
|
||||
elif list(menuItems[int(choice)].keys())[0] == "Send KMD gateway deposit transaction":
|
||||
while True:
|
||||
try:
|
||||
list(menuItems[int(choice)].values())[0](rpc_connection_kmd)
|
||||
break
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print("Please connect to KMD daemon first!")
|
||||
input("Press [Enter] to continue...")
|
||||
break
|
||||
elif list(menuItems[int(choice)].keys())[0] == "Execute gateways deposit":
|
||||
while True:
|
||||
try:
|
||||
list(menuItems[int(choice)].values())[0](rpc_connection, rpc_connection_kmd)
|
||||
break
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print("Please connect to KMD daemon first!")
|
||||
input("Press [Enter] to continue...")
|
||||
break
|
||||
else:
|
||||
list(menuItems[int(choice)].values())[0](rpc_connection)
|
||||
except (ValueError, IndexError):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
while True:
|
||||
try:
|
||||
print(tuilib.colorize("Welcome to the GatewaysCC TUI!\nPlease provide RPC connection details for initialization", "blue"))
|
||||
rpc_connection = tuilib.rpc_connection_tui()
|
||||
rpclib.getinfo(rpc_connection)
|
||||
except Exception:
|
||||
print(tuilib.colorize("Cant connect to RPC! Please re-check credentials.", "pink"))
|
||||
else:
|
||||
print(tuilib.colorize("Succesfully connected!\n", "green"))
|
||||
with (open("lib/logo.txt", "r")) as logo:
|
||||
for line in logo:
|
||||
print(line, end='')
|
||||
time.sleep(0.04)
|
||||
print("\n")
|
||||
break
|
||||
main()
|
||||
68
src/tui/tui_marmara.py
Executable file
68
src/tui/tui_marmara.py
Executable file
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from lib import rpclib, tuilib
|
||||
import os
|
||||
import time
|
||||
|
||||
|
||||
header = "\
|
||||
___ ___ _____ _ _ _____ \n\
|
||||
| \/ | |_ _| | | |_ _|\n\
|
||||
| . . | __ _ _ __ _ __ ___ __ _ _ __ __ _ | | | | | | | |\n\
|
||||
| |\/| |/ _` | '__| '_ ` _ \ / _` | '__/ _` | | | | | | | | |\n\
|
||||
| | | | (_| | | | | | | | | (_| | | | (_| | | | | |_| |_| |_\n\
|
||||
\_| |_/\__,_|_| |_| |_| |_|\__,_|_| \__,_| \_/ \___/ \___/\n"
|
||||
|
||||
|
||||
menuItems = [
|
||||
{"Check current connection": tuilib.getinfo_tui},
|
||||
{"Check mempool": tuilib.print_mempool},
|
||||
{"Check MARMARA info": tuilib.marmara_info_tui},
|
||||
{"Lock funds for MARMARA": tuilib.marmara_lock_tui},
|
||||
{"Request MARMARA cheque": tuilib.marmara_receive_tui},
|
||||
{"Issue MARMARA cheque": tuilib.marmara_issue_tui},
|
||||
{"Check credit loop status": tuilib.marmara_creditloop_tui},
|
||||
{"Settle MARMARA loop": tuilib.marmara_settlement_tui},
|
||||
{"Exit": exit}
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
while True:
|
||||
os.system('clear')
|
||||
print(tuilib.colorize(header, 'pink'))
|
||||
print(tuilib.colorize('CLI version 0.1\n', 'green'))
|
||||
for item in menuItems:
|
||||
print(tuilib.colorize("[" + str(menuItems.index(item)) + "] ", 'blue') + list(item.keys())[0])
|
||||
choice = input(">> ")
|
||||
try:
|
||||
if int(choice) < 0:
|
||||
raise ValueError
|
||||
# Call the matching function
|
||||
if list(menuItems[int(choice)].keys())[0] == "Exit":
|
||||
list(menuItems[int(choice)].values())[0]()
|
||||
else:
|
||||
list(menuItems[int(choice)].values())[0](rpc_connection)
|
||||
except (ValueError, IndexError):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
while True:
|
||||
chain = input("Input assetchain name (-ac_name= value) you want to work with: ")
|
||||
try:
|
||||
print(tuilib.colorize("Welcome to the MarmaraCC TUI!\n"
|
||||
"Please provide asset chain RPC connection details for initialization", "blue"))
|
||||
rpc_connection = tuilib.def_credentials(chain)
|
||||
rpclib.getinfo(rpc_connection)
|
||||
except Exception:
|
||||
print(tuilib.colorize("Cant connect to RPC! Please re-check credentials.", "pink"))
|
||||
else:
|
||||
print(tuilib.colorize("Succesfully connected!\n", "green"))
|
||||
with (open("lib/logo.txt", "r")) as logo:
|
||||
for line in logo:
|
||||
print(line, end='')
|
||||
time.sleep(0.04)
|
||||
print("\n")
|
||||
break
|
||||
main()
|
||||
67
src/tui/tui_oracles.py
Executable file
67
src/tui/tui_oracles.py
Executable file
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from lib import rpclib, tuilib
|
||||
import os
|
||||
import time
|
||||
|
||||
header = "\
|
||||
_____ _ _____ _____ \n\
|
||||
| _ | | | / __ \/ __ \\\n\
|
||||
| | | | _ __ __ _ ___ | | ___ ___ | / \/| / \/\n\
|
||||
| | | || '__| / _` | / __|| | / _ \/ __|| | | |\n\
|
||||
\ \_/ /| | | (_| || (__ | || __/\__ \| \__/\| \__/\\\n\
|
||||
\___/ |_| \__,_| \___||_| \___||___/ \____/ \____/\n"
|
||||
|
||||
menuItems = [
|
||||
# TODO: Have to implement here native oracle file uploader / reader, should be dope
|
||||
# TODO: data publisher / converter for different types
|
||||
{"Check current connection": tuilib.getinfo_tui},
|
||||
{"Check mempool": tuilib.print_mempool},
|
||||
{"Create oracle": tuilib.oracle_create_tui},
|
||||
{"Register as publisher for oracle": tuilib.oracle_register_tui},
|
||||
{"Subscribe on oracle (+UTXO generator)": tuilib.oracle_subscription_utxogen},
|
||||
{"Upload file to oracle": tuilib.convert_file_oracle_D},
|
||||
{"Display list of files uploaded to this AC": tuilib.display_files_list},
|
||||
{"Download files from oracle": tuilib.files_downloader},
|
||||
{"Exit": exit}
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
while True:
|
||||
os.system('clear')
|
||||
print(tuilib.colorize(header, 'pink'))
|
||||
print(tuilib.colorize('CLI version 0.2 by Anton Lysakov\n', 'green'))
|
||||
for item in menuItems:
|
||||
print(tuilib.colorize("[" + str(menuItems.index(item)) + "] ", 'blue') + list(item.keys())[0])
|
||||
choice = input(">> ")
|
||||
try:
|
||||
if int(choice) < 0:
|
||||
raise ValueError
|
||||
# Call the matching function
|
||||
if list(menuItems[int(choice)].keys())[0] == "Exit":
|
||||
list(menuItems[int(choice)].values())[0]()
|
||||
else:
|
||||
list(menuItems[int(choice)].values())[0](rpc_connection)
|
||||
except (ValueError, IndexError):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
while True:
|
||||
try:
|
||||
print(tuilib.colorize("Welcome to the GatewaysCC TUI!\n"
|
||||
"Please provide asset chain RPC connection details for initialization", "blue"))
|
||||
rpc_connection = tuilib.rpc_connection_tui()
|
||||
rpclib.getinfo(rpc_connection)
|
||||
except Exception:
|
||||
print(tuilib.colorize("Cant connect to RPC! Please re-check credentials.", "pink"))
|
||||
else:
|
||||
print(tuilib.colorize("Succesfully connected!\n", "green"))
|
||||
with (open("lib/logo.txt", "r")) as logo:
|
||||
for line in logo:
|
||||
print(line, end='')
|
||||
time.sleep(0.04)
|
||||
print("\n")
|
||||
break
|
||||
main()
|
||||
116
src/tui/tui_rogue.py
Executable file
116
src/tui/tui_rogue.py
Executable file
@@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from lib import rpclib, tuilib
|
||||
import os
|
||||
import time
|
||||
import sys
|
||||
import platform
|
||||
|
||||
header = "\
|
||||
______ _____ _____ \n\
|
||||
| ___ \ / __ \/ __ \\\n\
|
||||
| |_/ /___ __ _ _ _ ___| / \/| / \/\n\
|
||||
| // _ \ / _` | | | |/ _ \ | | |\n\
|
||||
| |\ \ (_) | (_| | |_| | __/ \__/\| \__/\\\n\
|
||||
\_| \_\___/ \__, |\__,_|\___|\____/ \____/\n\
|
||||
__/ |\n\
|
||||
|___/\n"
|
||||
|
||||
|
||||
menuItems = [
|
||||
{"Check current connection": tuilib.getinfo_tui},
|
||||
{"Check mempool": tuilib.print_mempool},
|
||||
{"Check my warriors list": tuilib.print_players_list},
|
||||
{"Transfer warrior to other pubkey": tuilib.warrior_trasnfer},
|
||||
{"TOP-20 ROGUE Warriors": tuilib.top_warriors_rating},
|
||||
{"Set warriors name": tuilib.set_warriors_name},
|
||||
{"Start singleplayer training game (creating, registering and starting game)": tuilib.rogue_newgame_singleplayer},
|
||||
{"Create multiplayer game": tuilib.rogue_newgame_multiplayer},
|
||||
{"Join (register) multiplayer game": tuilib.rogue_join_multiplayer_game},
|
||||
{"Check my multiplayer games status / start": tuilib.play_multiplayer_game},
|
||||
{"Check if somebody wants to buy your warrior (incoming bids)": tuilib.print_icoming_bids},
|
||||
{"Place order to sell warrior": tuilib.sell_warrior},
|
||||
{"Place order to buy someones warrior": tuilib.place_bid_on_warriror},
|
||||
{"Check if somebody selling warrior": tuilib.find_warriors_asks},
|
||||
{"Check / cancel my warriors trade orders": tuilib.warriors_orders_check},
|
||||
# {"Manually exit the game (bailout)": "test"},
|
||||
# {"Manually claim ROGUE coins for game (highlander)": "test"},
|
||||
{"Exit": tuilib.exit}
|
||||
]
|
||||
|
||||
def main():
|
||||
while True:
|
||||
operating_system = platform.system()
|
||||
if operating_system != 'Win64' and operating_system != 'Windows':
|
||||
os.system('clear')
|
||||
else:
|
||||
os.system('cls')
|
||||
print(tuilib.colorize(header, 'pink'))
|
||||
print(tuilib.colorize('TUI v0.0.3\n', 'green'))
|
||||
menu_items_counter = 0
|
||||
for item in menuItems:
|
||||
if menu_items_counter == 0:
|
||||
print("\nUtility:\n")
|
||||
menu_items_counter = menu_items_counter + 1
|
||||
print(tuilib.colorize("[" + str(menuItems.index(item)) + "] ", 'blue') + list(item.keys())[0])
|
||||
if menu_items_counter == 6:
|
||||
print("\nNew singleplayer game:\n")
|
||||
if menu_items_counter == 7:
|
||||
print("\nMultiplayer games:\n")
|
||||
if menu_items_counter == 10:
|
||||
print("\nDEX features:\n")
|
||||
choice = input(">> ")
|
||||
try:
|
||||
if int(choice) < 0:
|
||||
raise ValueError
|
||||
# Call the matching function
|
||||
if list(menuItems[int(choice)].keys())[0] == "Exit":
|
||||
list(menuItems[int(choice)].values())[0]()
|
||||
else:
|
||||
list(menuItems[int(choice)].values())[0](rpc_connection)
|
||||
except (ValueError, IndexError):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
while True:
|
||||
chain = "ROGUE"
|
||||
try:
|
||||
print(tuilib.colorize("Welcome to the RogueCC TUI!\n"
|
||||
"Please provide asset chain RPC connection details for initialization", "blue"))
|
||||
rpc_connection = tuilib.def_credentials(chain)
|
||||
rpclib.getinfo(rpc_connection)
|
||||
# waiting until chain is in sync
|
||||
while True:
|
||||
have_blocks = rpclib.getinfo(rpc_connection)["blocks"]
|
||||
longest_chain = rpclib.getinfo(rpc_connection)["longestchain"]
|
||||
if have_blocks != longest_chain:
|
||||
print(tuilib.colorize("ROGUE not synced yet.", "red"))
|
||||
print("Have " + str(have_blocks) + " from " + str(longest_chain) + " blocks")
|
||||
time.sleep(5)
|
||||
else:
|
||||
print(tuilib.colorize("Chain is synced!", "green"))
|
||||
break
|
||||
# checking if pubkey is set and set valid if not
|
||||
info = rpclib.getinfo(rpc_connection)
|
||||
if "pubkey" in info.keys():
|
||||
print("Pubkey is already set")
|
||||
else:
|
||||
valid_address = rpc_connection.getaccountaddress("")
|
||||
valid_pubkey = rpc_connection.validateaddress(valid_address)["pubkey"]
|
||||
rpc_connection.setpubkey(valid_pubkey)
|
||||
print(tuilib.colorize("Pubkey is succesfully set!", "green"))
|
||||
# copy ROGUE config to current daemon directory if it's not here
|
||||
tuilib.check_if_config_is_here(rpc_connection, "ROGUE")
|
||||
except Exception:
|
||||
print(tuilib.colorize("Cant connect to ROGUE daemon RPC! Please check if daemon is up.", "pink"))
|
||||
tuilib.exit()
|
||||
else:
|
||||
print(tuilib.colorize("Succesfully connected!\n", "green"))
|
||||
with (open("lib/logo.txt", "r")) as logo:
|
||||
for line in logo:
|
||||
print(line, end='')
|
||||
time.sleep(0.04)
|
||||
print("\n")
|
||||
break
|
||||
main()
|
||||
96
src/tui/tui_tetris.py
Executable file
96
src/tui/tui_tetris.py
Executable file
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from lib import rpclib, tuilib
|
||||
import os
|
||||
import time
|
||||
import sys
|
||||
import platform
|
||||
|
||||
header = "\
|
||||
_____ _ _ ______\n\
|
||||
|_ _| | | (_) | _ \n\
|
||||
| | ___| |_ _ __ _ ___| | | |__ _ _ __ _ __\n\
|
||||
| |/ _ \ __| '__| / __| | | / _` | '_ \| '_ \\\n\
|
||||
| | __/ |_| | | \__ \ |/ / (_| | |_) | |_) |\n\
|
||||
\_/\___|\__|_| |_|___/___/ \__,_| .__/| .__/\n\
|
||||
| | | |\n\
|
||||
|_| |_|"
|
||||
|
||||
|
||||
menuItems = [
|
||||
{"Check current connection": tuilib.getinfo_tui},
|
||||
{"Check mempool": tuilib.print_mempool},
|
||||
{"Start singleplayer tetris game (creating, registering and starting game)": tuilib.rogue_newgame_singleplayer},
|
||||
{"Exit": tuilib.exit}
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
while True:
|
||||
operating_system = platform.system()
|
||||
if operating_system != 'Win64' and operating_system != 'Windows':
|
||||
os.system('clear')
|
||||
else:
|
||||
os.system('cls')
|
||||
print(tuilib.colorize(header, 'pink'))
|
||||
print(tuilib.colorize('TUI v0.0.3\n', 'green'))
|
||||
menu_items_counter = 0
|
||||
for item in menuItems:
|
||||
print(tuilib.colorize("[" + str(menuItems.index(item)) + "] ", 'blue') + list(item.keys())[0])
|
||||
choice = input(">> ")
|
||||
try:
|
||||
if int(choice) < 0:
|
||||
raise ValueError
|
||||
# Call the matching function
|
||||
if list(menuItems[int(choice)].keys())[0] == "Exit":
|
||||
list(menuItems[int(choice)].values())[0]()
|
||||
elif list(menuItems[int(choice)].keys())[0] == "Start singleplayer tetris game (creating, registering and starting game)":
|
||||
list(menuItems[int(choice)].values())[0](rpc_connection, False)
|
||||
else:
|
||||
list(menuItems[int(choice)].values())[0](rpc_connection)
|
||||
except (ValueError, IndexError):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
while True:
|
||||
chain = "GTEST"
|
||||
try:
|
||||
print(tuilib.colorize("Welcome to the Tetris TUI!\n"
|
||||
"Please provide asset chain RPC connection details for initialization", "blue"))
|
||||
rpc_connection = tuilib.def_credentials(chain)
|
||||
rpclib.getinfo(rpc_connection)
|
||||
# waiting until chain is in sync
|
||||
while True:
|
||||
have_blocks = rpclib.getinfo(rpc_connection)["blocks"]
|
||||
longest_chain = rpclib.getinfo(rpc_connection)["longestchain"]
|
||||
if have_blocks != longest_chain:
|
||||
print(tuilib.colorize("GTEST not synced yet.", "red"))
|
||||
print("Have " + str(have_blocks) + " from " + str(longest_chain) + " blocks")
|
||||
time.sleep(5)
|
||||
else:
|
||||
print(tuilib.colorize("Chain is synced!", "green"))
|
||||
break
|
||||
# checking if pubkey is set and set valid if not
|
||||
info = rpclib.getinfo(rpc_connection)
|
||||
if "pubkey" in info.keys():
|
||||
print("Pubkey is already set")
|
||||
else:
|
||||
valid_address = rpc_connection.getaccountaddress("")
|
||||
valid_pubkey = rpc_connection.validateaddress(valid_address)["pubkey"]
|
||||
rpc_connection.setpubkey(valid_pubkey)
|
||||
print(tuilib.colorize("Pubkey is succesfully set!", "green"))
|
||||
# copy ROGUE config to current daemon directory if it's not here
|
||||
tuilib.check_if_config_is_here(rpc_connection, "GTEST")
|
||||
except Exception:
|
||||
print(tuilib.colorize("Cant connect to GTEST daemon RPC! Please check if daemon is up.", "pink"))
|
||||
tuilib.exit()
|
||||
else:
|
||||
print(tuilib.colorize("Succesfully connected!\n", "green"))
|
||||
with (open("lib/logo.txt", "r")) as logo:
|
||||
for line in logo:
|
||||
print(line, end='')
|
||||
time.sleep(0.04)
|
||||
print("\n")
|
||||
break
|
||||
main()
|
||||
209
src/txdb.cpp
209
src/txdb.cpp
@@ -438,38 +438,33 @@ bool CBlockTreeDB::ReadAddressIndex(uint160 addressHash, int type,
|
||||
bool getAddressFromIndex(const int &type, const uint160 &hash, std::string &address);
|
||||
uint32_t komodo_segid32(char *coinaddr);
|
||||
|
||||
UniValue CBlockTreeDB::Snapshot(int top)
|
||||
#define DECLARE_IGNORELIST std::map <std::string,int> ignoredMap = { \
|
||||
{"RReUxSs5hGE39ELU23DfydX8riUuzdrHAE", 1}, \
|
||||
{"RMUF3UDmzWFLSKV82iFbMaqzJpUnrWjcT4", 1}, \
|
||||
{"RA5imhVyJa7yHhggmBytWuDr923j2P1bxx", 1}, \
|
||||
{"RBM5LofZFodMeewUzoMWcxedm3L3hYRaWg", 1}, \
|
||||
{"RAdcko2d94TQUcJhtFHZZjMyWBKEVfgn4J", 1}, \
|
||||
{"RLzUaZ934k2EFCsAiVjrJqM8uU1vmMRFzk", 1}, \
|
||||
{"RMSZMWZXv4FhUgWhEo4R3AQXmRDJ6rsGyt", 1}, \
|
||||
{"RUDrX1v5toCsJMUgtvBmScKjwCB5NaR8py", 1}, \
|
||||
{"RMSZMWZXv4FhUgWhEo4R3AQXmRDJ6rsGyt", 1}, \
|
||||
{"RRvwmbkxR5YRzPGL5kMFHMe1AH33MeD8rN", 1}, \
|
||||
{"RQLQvSgpPAJNPgnpc8MrYsbBhep95nCS8L", 1}, \
|
||||
{"RK8JtBV78HdvEPvtV5ckeMPSTojZPzHUTe", 1}, \
|
||||
{"RHVs2KaCTGUMNv3cyWiG1jkEvZjigbCnD2", 1}, \
|
||||
{"RE3SVaDgdjkRPYA6TRobbthsfCmxQedVgF", 1}, \
|
||||
{"RW6S5Lw5ZCCvDyq4QV9vVy7jDHfnynr5mn", 1}, \
|
||||
{"RTkJwAYtdXXhVsS3JXBAJPnKaBfMDEswF8", 1}, \
|
||||
{"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY", 1} \
|
||||
};
|
||||
|
||||
int32_t CBlockTreeDB::Snapshot2(int64_t dustthreshold, int32_t top ,std::vector <std::pair<CAmount, std::string>> &vaddr, UniValue *ret)
|
||||
{
|
||||
int64_t total = 0; int64_t totalAddresses = 0; std::string address;
|
||||
int64_t utxos = 0; int64_t ignoredAddresses = 0;
|
||||
int64_t utxos = 0; int64_t ignoredAddresses = 0, cryptoConditionsUTXOs = 0, cryptoConditionsTotals = 0;
|
||||
DECLARE_IGNORELIST
|
||||
boost::scoped_ptr<CDBIterator> iter(NewIterator());
|
||||
std::map <std::string, CAmount> addressAmounts;
|
||||
std::vector <std::pair<CAmount, std::string>> vaddr;
|
||||
UniValue result(UniValue::VOBJ);
|
||||
result.push_back(Pair("start_time", (int) time(NULL)));
|
||||
|
||||
std::map <std::string,int> ignoredMap = {
|
||||
{"RReUxSs5hGE39ELU23DfydX8riUuzdrHAE", 1},
|
||||
{"RMUF3UDmzWFLSKV82iFbMaqzJpUnrWjcT4", 1},
|
||||
{"RA5imhVyJa7yHhggmBytWuDr923j2P1bxx", 1},
|
||||
{"RBM5LofZFodMeewUzoMWcxedm3L3hYRaWg", 1},
|
||||
{"RAdcko2d94TQUcJhtFHZZjMyWBKEVfgn4J", 1},
|
||||
{"RLzUaZ934k2EFCsAiVjrJqM8uU1vmMRFzk", 1},
|
||||
{"RMSZMWZXv4FhUgWhEo4R3AQXmRDJ6rsGyt", 1},
|
||||
{"RUDrX1v5toCsJMUgtvBmScKjwCB5NaR8py", 1},
|
||||
{"RMSZMWZXv4FhUgWhEo4R3AQXmRDJ6rsGyt", 1},
|
||||
{"RRvwmbkxR5YRzPGL5kMFHMe1AH33MeD8rN", 1},
|
||||
{"RQLQvSgpPAJNPgnpc8MrYsbBhep95nCS8L", 1},
|
||||
{"RK8JtBV78HdvEPvtV5ckeMPSTojZPzHUTe", 1},
|
||||
{"RHVs2KaCTGUMNv3cyWiG1jkEvZjigbCnD2", 1},
|
||||
{"RE3SVaDgdjkRPYA6TRobbthsfCmxQedVgF", 1},
|
||||
{"RW6S5Lw5ZCCvDyq4QV9vVy7jDHfnynr5mn", 1},
|
||||
{"RTkJwAYtdXXhVsS3JXBAJPnKaBfMDEswF8", 1},
|
||||
{"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY", 1} //Burnaddress for null privkey
|
||||
};
|
||||
|
||||
int64_t startingHeight = chainActive.Height();
|
||||
//fprintf(stderr, "Starting snapshot at height %lli\n", startingHeight);
|
||||
for (iter->SeekToLast(); iter->Valid(); iter->Prev())
|
||||
{
|
||||
boost::this_thread::interruption_point();
|
||||
@@ -478,103 +473,127 @@ UniValue CBlockTreeDB::Snapshot(int top)
|
||||
std::vector<unsigned char> slKey = std::vector<unsigned char>();
|
||||
pair<char, CAddressIndexIteratorKey> keyObj;
|
||||
iter->GetKey(keyObj);
|
||||
|
||||
char chType = keyObj.first;
|
||||
CAddressIndexIteratorKey indexKey = keyObj.second;
|
||||
|
||||
//fprintf(stderr, "chType=%d\n", chType);
|
||||
if (chType == DB_ADDRESSUNSPENTINDEX)
|
||||
{
|
||||
try {
|
||||
CAmount nValue;
|
||||
iter->GetValue(nValue);
|
||||
|
||||
getAddressFromIndex(indexKey.type, indexKey.hashBytes, address);
|
||||
|
||||
if (nValue > 0) {
|
||||
std::map <std::string, int>::iterator ignored = ignoredMap.find(address);
|
||||
if (ignored != ignoredMap.end()) {
|
||||
fprintf(stderr,"ignoring %s\n", address.c_str());
|
||||
ignoredAddresses++;
|
||||
if ( indexKey.type == 3 )
|
||||
{
|
||||
cryptoConditionsUTXOs++;
|
||||
cryptoConditionsTotals += nValue;
|
||||
continue;
|
||||
}
|
||||
if ( nValue > dustthreshold )
|
||||
{
|
||||
std::map <std::string, int>::iterator ignored = ignoredMap.find(address);
|
||||
if (ignored != ignoredMap.end())
|
||||
{
|
||||
fprintf(stderr,"ignoring %s\n", address.c_str());
|
||||
ignoredAddresses++;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::map <std::string, CAmount>::iterator pos = addressAmounts.find(address);
|
||||
if (pos == addressAmounts.end()) {
|
||||
// insert new address + utxo amount
|
||||
//fprintf(stderr, "inserting new address %s with amount %li\n", address.c_str(), nValue);
|
||||
addressAmounts[address] = nValue;
|
||||
totalAddresses++;
|
||||
} else {
|
||||
// update unspent tally for this address
|
||||
//fprintf(stderr, "updating address %s with new utxo amount %li\n", address.c_str(), nValue);
|
||||
addressAmounts[address] += nValue;
|
||||
if ( pos == addressAmounts.end() )
|
||||
{
|
||||
// insert new address + utxo amount
|
||||
//fprintf(stderr, "inserting new address %s with amount %li\n", address.c_str(), nValue);
|
||||
addressAmounts[address] = nValue;
|
||||
totalAddresses++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// update unspent tally for this address
|
||||
//fprintf(stderr, "updating address %s with new utxo amount %li\n", address.c_str(), nValue);
|
||||
addressAmounts[address] += nValue;
|
||||
}
|
||||
//fprintf(stderr,"{\"%s\", %.8f},\n",address.c_str(),(double)nValue/COIN);
|
||||
// total += nValue;
|
||||
utxos++;
|
||||
} else {
|
||||
fprintf(stderr,"ignoring amount=0 UTXO for %s\n", address.c_str());
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
} //else fprintf(stderr,"ignoring amount=0 UTXO for %s\n", address.c_str());
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
fprintf(stderr, "DONE %s: LevelDB addressindex exception! - %s\n", __func__, e.what());
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
fprintf(stderr, "DONE reading index entries\n");
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
fprintf(stderr, "DONE reading index entries\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UniValue addresses(UniValue::VARR);
|
||||
//fprintf(stderr, "total=%f, totalAddresses=%li, utxos=%li, ignored=%li\n", (double) total / COIN, totalAddresses, utxos, ignoredAddresses);
|
||||
|
||||
for (std::pair<std::string, CAmount> element : addressAmounts) {
|
||||
vaddr.push_back( make_pair(element.second, element.first) );
|
||||
}
|
||||
for (std::pair<std::string, CAmount> element : addressAmounts)
|
||||
vaddr.push_back( make_pair(element.second, element.first) );
|
||||
std::sort(vaddr.rbegin(), vaddr.rend());
|
||||
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
UniValue addressesSorted(UniValue::VARR);
|
||||
int topN = 0;
|
||||
for (std::vector<std::pair<CAmount, std::string>>::iterator it = vaddr.begin(); it!=vaddr.end(); ++it)
|
||||
{
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.push_back( make_pair("addr", it->second.c_str() ) );
|
||||
char amount[32];
|
||||
sprintf(amount, "%.8f", (double) it->first / COIN);
|
||||
obj.push_back( make_pair("amount", amount) );
|
||||
obj.push_back( make_pair("segid",(int32_t)komodo_segid32((char *)it->second.c_str()) & 0x3f) );
|
||||
total += it->first;
|
||||
addressesSorted.push_back(obj);
|
||||
topN++;
|
||||
// If requested, only show top N addresses in output JSON
|
||||
if (top == topN)
|
||||
break;
|
||||
total += it->first;
|
||||
topN++;
|
||||
// If requested, only show top N addresses in output JSON
|
||||
if ( top == topN )
|
||||
break;
|
||||
}
|
||||
// this is for the snapshot RPC, you can skip this by passing a 0 as the last argument.
|
||||
if (ret)
|
||||
{
|
||||
// Total amount in this snapshot, which is less than circulating supply if top parameter is used
|
||||
// Use the address_total for a total of all address included when using top parameter.
|
||||
ret->push_back(make_pair("total", (double) (total+cryptoConditionsTotals)/ COIN ));
|
||||
// Average amount in each address of this snapshot
|
||||
ret->push_back(make_pair("average",(double) (total/COIN) / totalAddresses ));
|
||||
// Total number of utxos processed in this snaphot
|
||||
ret->push_back(make_pair("utxos", utxos));
|
||||
// Total number of addresses in this snaphot
|
||||
ret->push_back(make_pair("total_addresses", top ? top : totalAddresses ));
|
||||
// Total number of ignored addresses in this snaphot
|
||||
ret->push_back(make_pair("ignored_addresses", ignoredAddresses));
|
||||
// Total number of crypto condition utxos we skipped
|
||||
ret->push_back(make_pair("skipped_cc_utxos", cryptoConditionsUTXOs));
|
||||
// Total value of skipped crypto condition utxos
|
||||
ret->push_back(make_pair("cc_utxo_value", (double) cryptoConditionsTotals / COIN));
|
||||
// total of all the address's, does not count coins in CC vouts.
|
||||
ret->push_back(make_pair("address_total", (double) total/ COIN ));
|
||||
// The snapshot finished at this block height
|
||||
ret->push_back(make_pair("ending_height", chainActive.Height()));
|
||||
}
|
||||
return(topN);
|
||||
}
|
||||
|
||||
if (top)
|
||||
totalAddresses = top;
|
||||
|
||||
if (totalAddresses > 0) {
|
||||
// Array of all addreses with balances
|
||||
UniValue CBlockTreeDB::Snapshot(int top)
|
||||
{
|
||||
int topN = 0;
|
||||
std::vector <std::pair<CAmount, std::string>> vaddr;
|
||||
UniValue result(UniValue::VOBJ);
|
||||
UniValue addressesSorted(UniValue::VARR);
|
||||
result.push_back(Pair("start_time", (int) time(NULL)));
|
||||
if ( Snapshot2(0,top,vaddr,&result) != 0 )
|
||||
{
|
||||
for (std::vector<std::pair<CAmount, std::string>>::iterator it = vaddr.begin(); it!=vaddr.end(); ++it)
|
||||
{
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.push_back( make_pair("addr", it->second.c_str() ) );
|
||||
char amount[32];
|
||||
sprintf(amount, "%.8f", (double) it->first / COIN);
|
||||
obj.push_back( make_pair("amount", amount) );
|
||||
obj.push_back( make_pair("segid",(int32_t)komodo_segid32((char *)it->second.c_str()) & 0x3f) );
|
||||
addressesSorted.push_back(obj);
|
||||
topN++;
|
||||
// If requested, only show top N addresses in output JSON
|
||||
if ( top == topN )
|
||||
break;
|
||||
}
|
||||
// Array of all addreses with balances
|
||||
result.push_back(make_pair("addresses", addressesSorted));
|
||||
// Total amount in this snapshot, which is less than circulating supply if top parameter is used
|
||||
result.push_back(make_pair("total", (double) total / COIN ));
|
||||
// Average amount in each address of this snapshot
|
||||
result.push_back(make_pair("average",(double) (total/COIN) / totalAddresses ));
|
||||
}
|
||||
// Total number of utxos processed in this snaphot
|
||||
result.push_back(make_pair("utxos", utxos));
|
||||
// Total number of addresses in this snaphot
|
||||
result.push_back(make_pair("total_addresses", totalAddresses));
|
||||
// Total number of ignored addresses in this snaphot
|
||||
result.push_back(make_pair("ignored_addresses", ignoredAddresses));
|
||||
// The snapshot began at this block height
|
||||
result.push_back(make_pair("start_height", startingHeight));
|
||||
// The snapshot finished at this block height
|
||||
result.push_back(make_pair("ending_height", chainActive.Height()));
|
||||
} else result.push_back(make_pair("error", "problem doing snapshot"));
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user