p
This commit is contained in:
blackjok3r
2018-12-11 07:29:41 +08:00
69 changed files with 2579 additions and 2459 deletions

188
README.md
View File

@@ -1,16 +1,13 @@
## VerusCoin version 0.4.0c
VerusCoin is a new, mineable and stakeable cryptocurrency. It is a live fork of Komodo that retains its Zcash lineage and improves it. VerusCoin will leverage the Komodo platform and dPoW notarization for enhanced security and cross-chain interoperability. We have added a variation of a zawy12, lwma difficulty algorithm, a new CPU-optimized hash algorithm and a new algorithm for fair proof of stake. We describe these changes and vision going forward in a [our Phase I white paper](http://185.25.51.16/papers/VerusPhaseI.pdf) and [our Vision](http://185.25.51.16/papers/VerusVision.pdf).
- [VerusCoin web site https://veruscoin.io/ Wallets and CLI tools](https://veruscoin.io/)
- [VerusCoin Explorer](https://explorer.veruscoin.io/)
[![Build Status](https://travis-ci.org/KomodoPlatform/komodo.svg?branch=dev)](https://travis-ci.org/KomodoPlatform/komodo)
---
![Komodo Logo](https://i.imgur.com/vIwVtqv.png "Komodo Logo")
## Komodo with Bitcore
This version of Komodo contains Bitcore support for komodo and all its assetchains.
## Komodo
## Komodod
This software is the VerusCoin enhanced Komodo client. Generally, you will use this if you want to mine VRSC or setup a full node. When you run the wallet it launches komodod automatically. On first launch it downloads Zcash parameters, roughly 1GB, which is mildly slow.
The wallet downloads and stores the block chain or asset chain of the coin you select. It downloads and stores the entire history of the coins transactions; depending on the speed of your computer and network connection, the synchronization process could take a day or more once the blockchain has reached a significant size.
This is the official Komodo sourcecode repository based on https://github.com/jl777/komodo.
## Development Resources
- Komodo Website: [https://komodoplatform.com](https://komodoplatform.com/)
- Komodo Blockexplorer: [https://kmdexplorer.io](https://kmdexplorer.io/)
@@ -26,23 +23,23 @@ The wallet downloads and stores the block chain or asset chain of the coin you s
## List of Komodo Platform Technologies
- Delayed Proof of Work (dPoW) - Additional security layer and Komodos own consensus algorithm.
- zk-SNARKs - Komodo Platform's privacy technology for shielded transactions
- Tokens/Assets Technology - create "colored coins" on the Komodo Platform and use them as a layer for securites
- Reward API - Komodo CC technology for securities
- CC - Crypto Conditions to realize "smart contract" logic on top of the Komodo Platform
- Jumblr - Decentralized tumbler for KMD and other cryptocurrencies
- Assetchains - Create your own Blockchain that inherits all Komodo Platform functionalities and blockchain interoperability
- Pegged Assets - Chains that maintain a peg to fiat currencies
- Peerchains - Scalability solution where sibling chains form a network of blockchains
- More in depth covered [here](https://docs.google.com/document/d/1AbhWrtagu4vYdkl-vsWz-HSNyNvK-W-ZasHCqe7CZy0)
- Also note you receive 5% APR on your holdings.
[See this article for more details](https://komodoplatform.atlassian.net/wiki/spaces/KPSD/pages/20480015/Claim+KMD+Interest+in+Agama)
- Delayed Proof of Work (dPoW) - Additional security layer and Komodos own consensus algorithm
- zk-SNARKs - Komodo Platform's privacy technology for shielded transactions
- Tokens/Assets Technology - create "colored coins" on the Komodo Platform and use them as a layer for securites
- Reward API - Komodo CC technology for securities
- CC - Crypto Conditions to realize "smart contract" logic on top of the Komodo Platform
- Jumblr - Decentralized tumbler for KMD and other cryptocurrencies
- Assetchains - Create your own Blockchain that inherits all Komodo Platform functionalities and blockchain interoperability
- Pegged Assets - Chains that maintain a peg to fiat currencies
- Peerchains - Scalability solution where sibling chains form a network of blockchains
- More in depth covered [here](https://docs.google.com/document/d/1AbhWrtagu4vYdkl-vsWz-HSNyNvK-W-ZasHCqe7CZy0)
- Also note you receive 5% Active User Reward on your balance.
[See this article for more details](https://support.komodoplatform.com/en/support/solutions/articles/29000024515-how-to-claim-the-kmd-active-user-reward-in-agama)
## Tech Specification
- Max Supply: 200 million KMD.
- Block Time: 1M 2s
- Block Reward: 3KMD
- Max Supply: 200 million KMD
- Block Time: 1m 2s
- Block Reward: 3 KMD
- Mining Algorithm: Equihash
## About this Project
@@ -57,86 +54,121 @@ Komodo is based on Zcash and has been extended by our innovative consensus algor
sudo apt-get install build-essential pkg-config libc6-dev m4 g++-multilib autoconf libtool ncurses-dev unzip git python python-zmq zlib1g-dev wget libcurl4-gnutls-dev bsdmainutils automake curl
```
### Build Komodo
Building
--------
This software is based on zcash and considered experimental and is continously undergoing heavy development.
First time you'll need to get assorted startup values downloaded. This takes a moderate amount of time once but then does not need to be repeated unless you bring a new system up. The command is:
```
./zcutil/fetch-params.sh
```
Building for Ubunutu/Mint:
```
./zcutil/build.sh
```
Building for Mac OS/X (see README-MAC.md):
```
./zcutil/build-mac.sh
```
Building for Windows:
```
./zcutil/build-win.sh
```
VerusCoin
------
We develop on dev and some other branches and produce releases of of the master branch, using pull requests to manage what goes into master. The dev branch is considered the bleeding edge codebase, and may even be oncompatible from time to time, while the master-branch is considered tested (unit tests, runtime tests, functionality). At no point of time do the Komodo Platform developers or Verus Developers take any responsbility for any damage out of the usage of this software.
Verus builds for all operating systems out of the same codebase. Follow the OS specific instructions from below.
The dev branch is considered the bleeding edge codebase while the master-branch is considered tested (unit tests, runtime tests, functionality). At no point of time do the Komodo Platform developers take any responsbility for any damage out of the usage of this software.
Komodo builds for all operating systems out of the same codebase. Follow the OS specific instructions from below.
#### Linux
```shell
git clone https://github.com/VerusCoin/VerusCoin
cd VerusCoin
#you might want to: git checkout <branch>; git pull
git clone https://github.com/komodoplatform/komodo --branch master --single-branch
cd komodo
./zcutil/fetch-params.sh
# -j8 = using 8 threads for the compilation - replace 8 with number of threads you want to use
./zcutil/build.sh -j8
#This can take some time.
```
**The VerusCoin enhanced komodo is experimental and a work-in-progress.** Use at your own risk.
#### OSX
Ensure you have [brew](https://brew.sh) and the command line tools installed (comes automatically with XCode) and run:
```shell
brew update && brew install gcc@6
git clone https://github.com/komodoplatform/komodo --branch master --single-branch
cd komodo
./zcutil/fetch-params.sh
# -j8 = using 8 threads for the compilation - replace 8 with number of threads you want to use
./zcutil/build-mac.sh -j8
#This can take some time.
```
#### Windows
Use a debian cross-compilation setup with mingw for windows and run:
```shell
sudo apt-get install build-essential pkg-config libc6-dev m4 g++-multilib autoconf libtool ncurses-dev unzip git python python-zmq zlib1g-dev wget libcurl4-gnutls-dev bsdmainutils automake curl cmake mingw-w64
curl https://sh.rustup.rs -sSf | sh
source $HOME/.cargo/env
rustup target add x86_64-pc-windows-gnu
git clone https://github.com/jl777/komodo --branch master --single-branch
cd komodo
./zcutil/fetch-params.sh
# -j8 = using 8 threads for the compilation - replace 8 with number of threads you want to use
./zcutil/build-win.sh -j8
#This can take some time.
```
**komodo is experimental and a work-in-progress.** Use at your own risk.
#To view komodod output:
tail -f ~/.komodo/debug.log
#To view VRSC output:
tail -f ~/.komodo/VRSC/debug.log
Note that this directory is correct for Linux, not Mac or Windows
#To view all command
./src/komodo-cli help
**Zcash is unfinished and highly experimental.** Use at your own risk.
To reset the Komodo blockchain change into the *~/.komodo* data directory and delete the corresponding files by running `rm -rf blocks chainstate debug.log komodostate db.log`
#### :ledger: Deprecation Policy
#### Create komodo.conf
This release is considered deprecated 16 weeks after the release day. There
is an automatic deprecation shutdown feature which will halt the node some
time after this 16 week time period. The automatic feature is based on block
height.
Create a komodo.conf file:
#Older Komodo Details
The remaining text is from the komodo source we forked when creating VerusCoin/Veruscoin.
```
mkdir ~/.komodo
cd ~/.komodo
touch komodo.conf
#Add the following lines to the komodo.conf file:
rpcuser=yourrpcusername
rpcpassword=yoursecurerpcpassword
rpcbind=127.0.0.1
txindex=1
addnode=5.9.102.210
addnode=78.47.196.146
addnode=178.63.69.164
addnode=88.198.65.74
addnode=5.9.122.241
addnode=144.76.94.38
addnode=89.248.166.91
```
### Create your own Blockchain based on Komodo
Komodo allows anyone to create a runtime fork which represents an independent Blockchain. Below are the detailed instructions:
Setup two independent servers with at least 1 server having a static IP and build komodod on those servers.
#### On server 1 (with static IP) run:
```shell
./komodod -ac_name=name_of_your_chain -ac_supply=100000 -bind=ip_of_server_1 &
```
#### On server 2 run:
```shell
./komodod -ac_name=name_of_your_chain -ac_supply=100000 -addnode=ip_of_server_1 -gen &
```
**Komodo is based on Zcash which is unfinished and highly experimental.** Use at your own risk.
License
-------
For license information see the file [COPYING](COPYING).
**NOTE TO EXCHANGES:**
https://bitcointalk.org/index.php?topic=1605144.msg17732151#msg17732151
There is a small chance that an outbound transaction will give an error due to mismatched values in wallet calculations. There is a -exchange option that you can run komodod with, but make sure to have the entire transaction history under the same -exchange mode. Otherwise you will get wallet conflicts.
**To change modes:**
a) backup all privkeys (launch komodod with `-exportdir=<path>` and `dumpwallet`)
b) start a totally new sync including `wallet.dat`, launch with same `exportdir`
c) stop it before it gets too far and import all the privkeys from a) using `komodo-cli importwallet filename`
d) resume sync till it gets to chaintip
a) backup all privkeys (launch komodod with `-exportdir=<path>` and `dumpwallet`)
b) start a totally new sync including `wallet.dat`, launch with same `exportdir`
c) stop it before it gets too far and import all the privkeys from a) using `komodo-cli importwallet filename`
d) resume sync till it gets to chaintip
For example:
```shell
./verusd -exportdir=/tmp &
./verus dumpwallet example
./verus stop
mv ~/.komodo/VRSC ~/.komodo/VRSC.old && mkdir ~/.komodo/VRSC && cp ~/.komodo/VRSC.old/VRSC.conf ~/.komodo/VRSC.old/peers.dat ~/.komodo/VRSC
./verusd -exchange -exportdir=/tmp &
./verus importwallet /tmp/example
./komodod -exportdir=/tmp &
./komodo-cli dumpwallet example
./komodo-cli stop
mv ~/.komodo ~/.komodo.old && mkdir ~/.komodo && cp ~/.komodo.old/komodo.conf ~/.komodo.old/peers.dat ~/.komodo
./komodod -exchange -exportdir=/tmp &
./komodo-cli importwallet /tmp/example
```
---
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 notices and this permission notice shall be included in all copies or substantial portions of the Software.
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.

View File

@@ -14,6 +14,11 @@ testScripts=(
'ac_private.py'
'verushash.py'
'cryptoconditions.py'
'cryptoconditions_dice.py'
'cryptoconditions_faucet.py'
'cryptoconditions_oracles.py'
'cryptoconditions_rewards.py'
'cryptoconditions_token.py'
'paymentdisclosure.py'
'prioritisetransaction.py'
'wallet_treestate.py'

View File

@@ -0,0 +1,259 @@
#!/usr/bin/env python2
# Copyright (c) 2018 SuperNET developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from test_framework.test_framework import BitcoinTestFramework
from test_framework.authproxy import JSONRPCException
from test_framework.util import assert_equal, assert_greater_than, \
initialize_chain_clean, initialize_chain, start_nodes, start_node, connect_nodes_bi, \
stop_nodes, sync_blocks, sync_mempools, wait_bitcoinds, rpc_port, assert_raises
from cryptoconditions import assert_success, assert_error, generate_random_string
class CryptoconditionsDiceTest(BitcoinTestFramework):
def setup_chain(self):
print("Initializing CC test directory "+self.options.tmpdir)
self.num_nodes = 2
initialize_chain_clean(self.options.tmpdir, self.num_nodes)
def setup_network(self, split = False):
print("Setting up network...")
self.addr = "RWPg8B91kfK5UtUN7z6s6TeV9cHSGtVY8D"
self.pubkey = "02676d00110c2cd14ae24f95969e8598f7ccfaa675498b82654a5b5bd57fc1d8cf"
self.privkey = "UqMgxk7ySPNQ4r9nKAFPjkXy6r5t898yhuNCjSZJLg3RAM4WW1m9"
self.addr1 = "RXEXoa1nRmKhMbuZovpcYwQMsicwzccZBp"
self.pubkey1 = "024026d4ad4ecfc1f705a9b42ca64af6d2ad947509c085534a30b8861d756c6ff0"
self.privkey1 = "UtdydP56pGTFmawHzHr1wDrc4oUwCNW1ttX8Pc3KrvH3MA8P49Wi"
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
extra_args=[[
# always give -ac_name as first extra_arg and port as third
'-ac_name=REGTEST',
'-conf='+self.options.tmpdir+'/node0/REGTEST.conf',
'-port=64367',
'-rpcport=64368',
'-regtest',
'-addressindex=1',
'-spentindex=1',
'-ac_supply=5555555',
'-ac_reward=10000000000000',
'-pubkey=' + self.pubkey,
'-ac_cc=2',
'-whitelist=127.0.0.1',
'-debug',
'--daemon',
'-rpcuser=rt',
'-rpcpassword=rt'
],
['-ac_name=REGTEST',
'-conf='+self.options.tmpdir+'/node1/REGTEST.conf',
'-port=64365',
'-rpcport=64366',
'-regtest',
'-addressindex=1',
'-spentindex=1',
'-ac_supply=5555555',
'-ac_reward=10000000000000',
'-pubkey=' + self.pubkey1,
'-ac_cc=2',
'-whitelist=127.0.0.1',
'-debug',
'-addnode=127.0.0.1:64367',
'--daemon',
'-rpcuser=rt',
'-rpcpassword=rt']]
)
self.is_network_split = split
self.rpc = self.nodes[0]
self.rpc1 = self.nodes[1]
self.sync_all()
print("Done setting up network")
def send_and_mine(self, xtn, rpc_connection):
txid = rpc_connection.sendrawtransaction(xtn)
assert txid, 'got txid'
# we need the tx above to be confirmed in the next block
rpc_connection.generate(1)
return txid
def run_dice_tests(self):
rpc = self.nodes[0]
rpc1 = self.nodes[1]
self.sync_all()
# have to generate few blocks on second node to be able to place bets
rpc1.generate(10)
result = rpc1.getbalance()
assert_greater_than(result, 100000)
dice = rpc.diceaddress()
assert_equal(dice['result'], 'success')
for x in ['myCCaddress', 'DiceCCaddress', 'Dicemarker', 'myaddress']:
assert_equal(dice[x][0], 'R')
dice = rpc.diceaddress(self.pubkey)
assert_equal(dice['result'], 'success')
for x in ['myCCaddress', 'DiceCCaddress', 'Dicemarker', 'myaddress', 'CCaddress']:
assert_equal(dice[x][0], 'R')
# no dice created yet
result = rpc.dicelist()
assert_equal(result, [])
# creating dice plan with too long name (>8 chars)
result = rpc.dicefund("THISISTOOLONG", "10000", "10", "10000", "10", "5")
assert_error(result)
# creating dice plan with < 100 funding
result = rpc.dicefund("LUCKY","10","1","10000","10","5")
assert_error(result)
# creating dice plan with 0 blocks timeout
result = rpc.dicefund("LUCKY","10","1","10000","10","0")
assert_error(result)
# creating dice plan
dicefundtx = rpc.dicefund("LUCKY","1000","1","800","10","5")
diceid = self.send_and_mine(dicefundtx['hex'], rpc)
# checking if it in plans list now
result = rpc.dicelist()
assert_equal(result[0], diceid)
# set dice name for futher usage
dicename = "LUCKY"
# adding zero funds to plan
result = rpc.diceaddfunds(dicename,diceid,"0")
assert_error(result)
# adding negative funds to plan
result = rpc.diceaddfunds(dicename,diceid,"-1")
assert_error(result)
# adding funds to plan
addfundstx = rpc.diceaddfunds(dicename,diceid,"1100")
result = self.send_and_mine(addfundstx['hex'], rpc)
# checking if funds added to plan
result = rpc.diceinfo(diceid)
assert_equal(result["funding"], "2100.00000000")
# not valid dice info checking
result = rpc.diceinfo("invalid")
assert_error(result)
# placing 0 amount bet
result = rpc1.dicebet(dicename,diceid,"0","2")
assert_error(result)
# placing negative amount bet
result = rpc1.dicebet(dicename,diceid,"-1","2")
assert_error(result)
# placing bet more than maxbet
result = rpc1.dicebet(dicename,diceid,"900","2")
assert_error(result)
# placing bet with amount more than funding
result = rpc1.dicebet(dicename,diceid,"3000","2")
assert_error(result)
# placing bet with potential won more than funding
result = rpc1.dicebet(dicename,diceid,"750","9")
assert_error(result)
# placing 0 odds bet
result = rpc1.dicebet(dicename,diceid,"1","0")
assert_error(result)
# placing negative odds bet
result = rpc1.dicebet(dicename,diceid,"1","-1")
assert_error(result)
# placing bet with odds more than allowed
result = rpc1.dicebet(dicename,diceid,"1","11")
assert_error(result)
# placing bet with not correct dice name
result = rpc1.dicebet("nope",diceid,"100","2")
assert_error(result)
# placing bet with not correct dice id
result = rpc1.dicebet(dicename,self.pubkey,"100","2")
assert_error(result)
# have to make some entropy for the next test
entropytx = 0
fundingsum = 1
while entropytx < 110:
fundingsuminput = str(fundingsum)
fundinghex = rpc.diceaddfunds(dicename,diceid,fundingsuminput)
result = self.send_and_mine(fundinghex['hex'], rpc)
entropytx = entropytx + 1
fundingsum = fundingsum + 1
rpc.generate(2)
self.sync_all()
# valid bet placing
placebet = rpc1.dicebet(dicename,diceid,"100","2")
betid = self.send_and_mine(placebet["hex"], rpc1)
assert result, "bet placed"
# check bet status
result = rpc1.dicestatus(dicename,diceid,betid)
assert_success(result)
# note initial dice funding state at this point.
# TODO: track player balance somehow (hard to do because of mining and fees)
diceinfo = rpc.diceinfo(diceid)
funding = float(diceinfo['funding'])
# # placing same amount bets with amount 1 and odds 1:3, checking if balance changed correct
# losscounter = 0
# wincounter = 0
# betcounter = 0
#
# while (betcounter < 10):
# placebet = rpc1.dicebet(dicename,diceid,"1","2")
# betid = self.send_and_mine(placebet["hex"], rpc1)
# time.sleep(3)
# self.sync_all()
# finish = rpc.dicefinish(dicename,diceid,betid)
# self.send_and_mine(finish["hex"], rpc1)
# self.sync_all()
# time.sleep(3)
# betresult = rpc1.dicestatus(dicename,diceid,betid)
# betcounter = betcounter + 1
# if betresult["status"] == "loss":
# losscounter = losscounter + 1
# elif betresult["status"] == "win":
# wincounter = wincounter + 1
# else:
# pass
#
# # funding balance should increase if player loss, decrease if player won
# fundbalanceguess = funding + losscounter - wincounter * 2
# fundinfoactual = rpc.diceinfo(diceid)
# assert_equal(round(fundbalanceguess),round(float(fundinfoactual['funding'])))
def run_test(self):
print("Mining blocks...")
rpc = self.nodes[0]
rpc1 = self.nodes[1]
# utxos from block 1 become mature in block 101
rpc.generate(101)
self.sync_all()
rpc.getinfo()
rpc1.getinfo()
# this corresponds to -pubkey above
print("Importing privkeys")
rpc.importprivkey(self.privkey)
rpc1.importprivkey(self.privkey1)
self.run_dice_tests()
if __name__ == '__main__':
CryptoconditionsDiceTest ().main()

View File

@@ -0,0 +1,173 @@
#!/usr/bin/env python2
# Copyright (c) 2018 SuperNET developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from test_framework.test_framework import BitcoinTestFramework
from test_framework.authproxy import JSONRPCException
from test_framework.util import assert_equal, assert_greater_than, \
initialize_chain_clean, initialize_chain, start_nodes, start_node, connect_nodes_bi, \
stop_nodes, sync_blocks, sync_mempools, wait_bitcoinds, rpc_port, assert_raises
from cryptoconditions import assert_success, assert_error, generate_random_string
class CryptoconditionsFaucetTest(BitcoinTestFramework):
def setup_chain(self):
print("Initializing CC test directory "+self.options.tmpdir)
self.num_nodes = 2
initialize_chain_clean(self.options.tmpdir, self.num_nodes)
def setup_network(self, split = False):
print("Setting up network...")
self.addr = "RWPg8B91kfK5UtUN7z6s6TeV9cHSGtVY8D"
self.pubkey = "02676d00110c2cd14ae24f95969e8598f7ccfaa675498b82654a5b5bd57fc1d8cf"
self.privkey = "UqMgxk7ySPNQ4r9nKAFPjkXy6r5t898yhuNCjSZJLg3RAM4WW1m9"
self.addr1 = "RXEXoa1nRmKhMbuZovpcYwQMsicwzccZBp"
self.pubkey1 = "024026d4ad4ecfc1f705a9b42ca64af6d2ad947509c085534a30b8861d756c6ff0"
self.privkey1 = "UtdydP56pGTFmawHzHr1wDrc4oUwCNW1ttX8Pc3KrvH3MA8P49Wi"
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
extra_args=[[
# always give -ac_name as first extra_arg and port as third
'-ac_name=REGTEST',
'-conf='+self.options.tmpdir+'/node0/REGTEST.conf',
'-port=64367',
'-rpcport=64368',
'-regtest',
'-addressindex=1',
'-spentindex=1',
'-ac_supply=5555555',
'-ac_reward=10000000000000',
'-pubkey=' + self.pubkey,
'-ac_cc=2',
'-whitelist=127.0.0.1',
'-debug',
'--daemon',
'-rpcuser=rt',
'-rpcpassword=rt'
],
['-ac_name=REGTEST',
'-conf='+self.options.tmpdir+'/node1/REGTEST.conf',
'-port=64365',
'-rpcport=64366',
'-regtest',
'-addressindex=1',
'-spentindex=1',
'-ac_supply=5555555',
'-ac_reward=10000000000000',
'-pubkey=' + self.pubkey1,
'-ac_cc=2',
'-whitelist=127.0.0.1',
'-debug',
'-addnode=127.0.0.1:64367',
'--daemon',
'-rpcuser=rt',
'-rpcpassword=rt']]
)
self.is_network_split = split
self.rpc = self.nodes[0]
self.rpc1 = self.nodes[1]
self.sync_all()
print("Done setting up network")
def send_and_mine(self, xtn, rpc_connection):
txid = rpc_connection.sendrawtransaction(xtn)
assert txid, 'got txid'
# we need the tx above to be confirmed in the next block
rpc_connection.generate(1)
return txid
def run_faucet_tests(self):
rpc = self.rpc
rpc1 = self.rpc1
# basic sanity tests
result = rpc.getwalletinfo()
assert_greater_than(result['txcount'], 100)
assert_greater_than(result['balance'], 0.0)
balance = result['balance']
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']:
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']:
assert_equal(result[x][0], 'R')
# no funds in the faucet yet
result = rpc.faucetget()
assert_error(result)
result = rpc.faucetinfo()
assert_success(result)
result = rpc.faucetfund("0")
assert_error(result)
result = rpc.faucetfund("-1")
assert_error(result)
# we need at least 1 + txfee to get
result = rpc.faucetfund("2")
assert_success(result)
assert result['hex'], "hex key found"
# broadcast the xtn
result = rpc.sendrawtransaction(result['hex'])
txid = result[0]
assert txid, "found txid"
# we need the tx above to be confirmed in the next block
rpc.generate(1)
self.sync_all()
result = rpc.getwalletinfo()
# minus one block reward
balance2 = result['balance'] - 100000
# make sure our balance is less now
assert_greater_than(balance, balance2)
result = rpc.faucetinfo()
assert_success(result)
assert_greater_than( result['funding'], 0 )
# claiming faucet on second node
faucetgethex = rpc1.faucetget()
assert_success(faucetgethex)
assert faucetgethex['hex'], "hex key found"
balance1 = rpc1.getwalletinfo()['balance']
# try to broadcast the faucetget transaction
result = self.send_and_mine(faucetgethex['hex'], rpc1)
assert txid, "transaction broadcasted"
balance2 = rpc1.getwalletinfo()['balance']
assert_greater_than(balance2, balance1)
self.sync_all()
def run_test(self):
print("Mining blocks...")
rpc = self.nodes[0]
rpc1 = self.nodes[1]
# utxos from block 1 become mature in block 101
rpc.generate(101)
self.sync_all()
rpc.getinfo()
rpc1.getinfo()
# this corresponds to -pubkey above
print("Importing privkeys")
rpc.importprivkey(self.privkey)
rpc1.importprivkey(self.privkey1)
self.run_faucet_tests()
if __name__ == '__main__':
CryptoconditionsFaucetTest ().main()

View File

@@ -0,0 +1,293 @@
#!/usr/bin/env python2
# Copyright (c) 2018 SuperNET developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from test_framework.test_framework import BitcoinTestFramework
from test_framework.authproxy import JSONRPCException
from test_framework.util import assert_equal, assert_greater_than, \
initialize_chain_clean, initialize_chain, start_nodes, start_node, connect_nodes_bi, \
stop_nodes, sync_blocks, sync_mempools, wait_bitcoinds, rpc_port, assert_raises
from cryptoconditions import assert_success, assert_error, generate_random_string
class CryptoconditionsOraclesTest(BitcoinTestFramework):
def setup_chain(self):
print("Initializing CC test directory "+self.options.tmpdir)
self.num_nodes = 2
initialize_chain_clean(self.options.tmpdir, self.num_nodes)
def setup_network(self, split = False):
print("Setting up network...")
self.addr = "RWPg8B91kfK5UtUN7z6s6TeV9cHSGtVY8D"
self.pubkey = "02676d00110c2cd14ae24f95969e8598f7ccfaa675498b82654a5b5bd57fc1d8cf"
self.privkey = "UqMgxk7ySPNQ4r9nKAFPjkXy6r5t898yhuNCjSZJLg3RAM4WW1m9"
self.addr1 = "RXEXoa1nRmKhMbuZovpcYwQMsicwzccZBp"
self.pubkey1 = "024026d4ad4ecfc1f705a9b42ca64af6d2ad947509c085534a30b8861d756c6ff0"
self.privkey1 = "UtdydP56pGTFmawHzHr1wDrc4oUwCNW1ttX8Pc3KrvH3MA8P49Wi"
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
extra_args=[[
# always give -ac_name as first extra_arg and port as third
'-ac_name=REGTEST',
'-conf='+self.options.tmpdir+'/node0/REGTEST.conf',
'-port=64367',
'-rpcport=64368',
'-regtest',
'-addressindex=1',
'-spentindex=1',
'-ac_supply=5555555',
'-ac_reward=10000000000000',
'-pubkey=' + self.pubkey,
'-ac_cc=2',
'-whitelist=127.0.0.1',
'-debug',
'--daemon',
'-rpcuser=rt',
'-rpcpassword=rt'
],
['-ac_name=REGTEST',
'-conf='+self.options.tmpdir+'/node1/REGTEST.conf',
'-port=64365',
'-rpcport=64366',
'-regtest',
'-addressindex=1',
'-spentindex=1',
'-ac_supply=5555555',
'-ac_reward=10000000000000',
'-pubkey=' + self.pubkey1,
'-ac_cc=2',
'-whitelist=127.0.0.1',
'-debug',
'-addnode=127.0.0.1:64367',
'--daemon',
'-rpcuser=rt',
'-rpcpassword=rt']]
)
self.is_network_split = split
self.rpc = self.nodes[0]
self.rpc1 = self.nodes[1]
self.sync_all()
print("Done setting up network")
def send_and_mine(self, xtn, rpc_connection):
txid = rpc_connection.sendrawtransaction(xtn)
assert txid, 'got txid'
# we need the tx above to be confirmed in the next block
rpc_connection.generate(1)
return txid
def run_oracles_tests(self):
rpc = self.nodes[0]
rpc1 = self.nodes[1]
result = rpc1.oraclesaddress()
result = rpc.oraclesaddress()
assert_success(result)
for x in ['OraclesCCaddress', 'Oraclesmarker', 'myCCaddress', 'myaddress']:
assert_equal(result[x][0], 'R')
result = rpc.oraclesaddress(self.pubkey)
assert_success(result)
for x in ['OraclesCCaddress', 'Oraclesmarker', 'myCCaddress', 'myaddress']:
assert_equal(result[x][0], 'R')
# there are no oracles created yet
result = rpc.oracleslist()
assert_equal(result, [])
# looking up non-existent oracle should return error.
result = rpc.oraclesinfo("none")
assert_error(result)
# attempt to create oracle with not valid data type should return error
result = rpc.oraclescreate("Test", "Test", "Test")
assert_error(result)
# attempt to create oracle with description > 32 symbols should return error
too_long_name = generate_random_string(33)
result = rpc.oraclescreate(too_long_name, "Test", "s")
# attempt to create oracle with description > 4096 symbols should return error
too_long_description = generate_random_string(4100)
result = rpc.oraclescreate("Test", too_long_description, "s")
assert_error(result)
# valid creating oracles of different types
# using such naming to re-use it for data publishing / reading (e.g. oracle_s for s type)
valid_formats = ["s", "S", "d", "D", "c", "C", "t", "T", "i", "I", "l", "L", "h", "Ihh"]
for f in valid_formats:
result = rpc.oraclescreate("Test", "Test", f)
assert_success(result)
globals()["oracle_{}".format(f)] = self.send_and_mine(result['hex'], rpc)
# trying to register with negative datafee
for f in valid_formats:
result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "-100")
assert_error(result)
# trying to register with zero datafee
for f in valid_formats:
result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "0")
assert_error(result)
# trying to register with datafee less than txfee
for f in valid_formats:
result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "500")
assert_error(result)
# trying to register valid
for f in valid_formats:
result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "10000")
assert_success(result)
register_txid = self.send_and_mine(result["hex"], rpc)
assert register_txid, "got txid"
# TODO: for most of the non valid oraclesregister and oraclessubscribe transactions generating and broadcasting now
# so trying only valid oraclessubscribe atm
for f in valid_formats:
result = rpc.oraclessubscribe(globals()["oracle_{}".format(f)], self.pubkey, "1")
assert_success(result)
subscribe_txid = self.send_and_mine(result["hex"], rpc)
assert register_txid, "got txid"
# now lets publish and read valid data for each oracle type
# s type
result = rpc.oraclesdata(globals()["oracle_{}".format("s")], "05416e746f6e")
assert_success(result)
# baton
oraclesdata_s = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("s")], oraclesdata_s, "1")
assert_equal("[u'Anton']", str(result["samples"][0]), "Data match")
# S type
result = rpc.oraclesdata(globals()["oracle_{}".format("S")], "000161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161")
assert_success(result)
# baton
oraclesdata_S = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("S")], oraclesdata_S, "1")
assert_equal("[u'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa']", str(result["samples"][0]), "Data match")
# d type
result = rpc.oraclesdata(globals()["oracle_{}".format("d")], "0101")
assert_success(result)
# baton
oraclesdata_d = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("d")], oraclesdata_d, "1")
# TODO: working not correct now!
#assert_equal("[u'01']", str(result["samples"][0]), "Data match")
# D type
result = rpc.oraclesdata(globals()["oracle_{}".format("D")], "0101")
assert_success(result)
# baton
oraclesdata_D = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("D")], oraclesdata_D, "1")
# TODO: working not correct now!
#assert_equal("[u'01']", str(result["samples"][0]), "Data match")
# c type
result = rpc.oraclesdata(globals()["oracle_{}".format("c")], "ff")
assert_success(result)
# baton
oraclesdata_c = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("c")], oraclesdata_c, "1")
assert_equal("[u'-1']", str(result["samples"][0]), "Data match")
# C type
result = rpc.oraclesdata(globals()["oracle_{}".format("C")], "ff")
assert_success(result)
# baton
oraclesdata_C = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("C")], oraclesdata_C, "1")
assert_equal("[u'255']", str(result["samples"][0]), "Data match")
# t type
result = rpc.oraclesdata(globals()["oracle_{}".format("t")], "ffff")
assert_success(result)
# baton
oraclesdata_t = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("t")], oraclesdata_t, "1")
assert_equal("[u'-1']", str(result["samples"][0]), "Data match")
# T type
result = rpc.oraclesdata(globals()["oracle_{}".format("T")], "ffff")
assert_success(result)
# baton
oraclesdata_T = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("T")], oraclesdata_T, "1")
assert_equal("[u'65535']", str(result["samples"][0]), "Data match")
# i type
result = rpc.oraclesdata(globals()["oracle_{}".format("i")], "ffffffff")
assert_success(result)
# baton
oraclesdata_i = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("i")], oraclesdata_i, "1")
assert_equal("[u'-1']", str(result["samples"][0]), "Data match")
# I type
result = rpc.oraclesdata(globals()["oracle_{}".format("I")], "ffffffff")
assert_success(result)
# baton
oraclesdata_I = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("I")], oraclesdata_I, "1")
assert_equal("[u'4294967295']", str(result["samples"][0]), "Data match")
# l type
result = rpc.oraclesdata(globals()["oracle_{}".format("l")], "00000000ffffffff")
assert_success(result)
# baton
oraclesdata_l = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("l")], oraclesdata_l, "1")
# TODO: working not correct now!
#assert_equal("[u'-4294967296']", str(result["samples"][0]), "Data match")
# L type
result = rpc.oraclesdata(globals()["oracle_{}".format("L")], "00000000ffffffff")
assert_success(result)
# baton
oraclesdata_L = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("L")], oraclesdata_L, "1")
assert_equal("[u'18446744069414584320']", str(result["samples"][0]), "Data match")
# h type
result = rpc.oraclesdata(globals()["oracle_{}".format("h")], "00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff")
assert_success(result)
# baton
oraclesdata_h = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("h")], oraclesdata_h, "1")
assert_equal("[u'ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000']", str(result["samples"][0]), "Data match")
# Ihh type
result = rpc.oraclesdata(globals()["oracle_{}".format("Ihh")], "00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff")
assert_success(result)
# baton
oraclesdata_Ihh = self.send_and_mine(result["hex"], rpc)
result = rpc.oraclessamples(globals()["oracle_{}".format("Ihh")], oraclesdata_Ihh, "1")
assert_equal("[u'0']", str(result["samples"][0]), "Data match")
assert_equal("[u'00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff']", str(result["samples"][1]), "Data match")
assert_equal("[u'00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff']", str(result["samples"][2]), "Data match")
def run_test(self):
print("Mining blocks...")
rpc = self.nodes[0]
rpc1 = self.nodes[1]
# utxos from block 1 become mature in block 101
rpc.generate(101)
self.sync_all()
rpc.getinfo()
rpc1.getinfo()
# this corresponds to -pubkey above
print("Importing privkeys")
rpc.importprivkey(self.privkey)
rpc1.importprivkey(self.privkey1)
self.run_oracles_tests()
if __name__ == '__main__':
CryptoconditionsOraclesTest().main()

View File

@@ -0,0 +1,208 @@
#!/usr/bin/env python2
# Copyright (c) 2018 SuperNET developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from test_framework.test_framework import BitcoinTestFramework
from test_framework.authproxy import JSONRPCException
from test_framework.util import assert_equal, assert_greater_than, \
initialize_chain_clean, initialize_chain, start_nodes, start_node, connect_nodes_bi, \
stop_nodes, sync_blocks, sync_mempools, wait_bitcoinds, rpc_port, assert_raises
from cryptoconditions import assert_success, assert_error, generate_random_string
class CryptoconditionsRewardsTest(BitcoinTestFramework):
def setup_chain(self):
print("Initializing CC test directory "+self.options.tmpdir)
self.num_nodes = 2
initialize_chain_clean(self.options.tmpdir, self.num_nodes)
def setup_network(self, split = False):
print("Setting up network...")
self.addr = "RWPg8B91kfK5UtUN7z6s6TeV9cHSGtVY8D"
self.pubkey = "02676d00110c2cd14ae24f95969e8598f7ccfaa675498b82654a5b5bd57fc1d8cf"
self.privkey = "UqMgxk7ySPNQ4r9nKAFPjkXy6r5t898yhuNCjSZJLg3RAM4WW1m9"
self.addr1 = "RXEXoa1nRmKhMbuZovpcYwQMsicwzccZBp"
self.pubkey1 = "024026d4ad4ecfc1f705a9b42ca64af6d2ad947509c085534a30b8861d756c6ff0"
self.privkey1 = "UtdydP56pGTFmawHzHr1wDrc4oUwCNW1ttX8Pc3KrvH3MA8P49Wi"
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
extra_args=[[
# always give -ac_name as first extra_arg and port as third
'-ac_name=REGTEST',
'-conf='+self.options.tmpdir+'/node0/REGTEST.conf',
'-port=64367',
'-rpcport=64368',
'-regtest',
'-addressindex=1',
'-spentindex=1',
'-ac_supply=5555555',
'-ac_reward=10000000000000',
'-pubkey=' + self.pubkey,
'-ac_cc=2',
'-whitelist=127.0.0.1',
'-debug',
'--daemon',
'-rpcuser=rt',
'-rpcpassword=rt'
],
['-ac_name=REGTEST',
'-conf='+self.options.tmpdir+'/node1/REGTEST.conf',
'-port=64365',
'-rpcport=64366',
'-regtest',
'-addressindex=1',
'-spentindex=1',
'-ac_supply=5555555',
'-ac_reward=10000000000000',
'-pubkey=' + self.pubkey1,
'-ac_cc=2',
'-whitelist=127.0.0.1',
'-debug',
'-addnode=127.0.0.1:64367',
'--daemon',
'-rpcuser=rt',
'-rpcpassword=rt']]
)
self.is_network_split = split
self.rpc = self.nodes[0]
self.rpc1 = self.nodes[1]
self.sync_all()
print("Done setting up network")
def send_and_mine(self, xtn, rpc_connection):
txid = rpc_connection.sendrawtransaction(xtn)
assert txid, 'got txid'
# we need the tx above to be confirmed in the next block
rpc_connection.generate(1)
return txid
def run_rewards_tests(self):
rpc = self.nodes[0]
result = rpc.rewardsaddress()
for x in ['RewardsCCaddress', 'myCCaddress', 'Rewardsmarker', 'myaddress']:
assert_equal(result[x][0], 'R')
result = rpc.rewardsaddress(self.pubkey)
for x in ['RewardsCCaddress', 'myCCaddress', 'Rewardsmarker', 'myaddress', 'CCaddress']:
assert_equal(result[x][0], 'R')
# no rewards yet
result = rpc.rewardslist()
assert_equal(result, [])
# looking up non-existent reward should return error
result = rpc.rewardsinfo("none")
assert_error(result)
# creating rewards plan with name > 8 chars, should return error
result = rpc.rewardscreatefunding("STUFFSTUFF", "7777", "25", "0", "10", "10")
assert_error(result)
# creating rewards plan with 0 funding
result = rpc.rewardscreatefunding("STUFF", "0", "25", "0", "10", "10")
assert_error(result)
# creating rewards plan with 0 maxdays
result = rpc.rewardscreatefunding("STUFF", "7777", "25", "0", "10", "0")
assert_error(result)
# creating rewards plan with > 25% APR
result = rpc.rewardscreatefunding("STUFF", "7777", "30", "0", "10", "10")
assert_error(result)
# creating valid rewards plan
result = rpc.rewardscreatefunding("STUFF", "7777", "25", "0", "10", "10")
assert result['hex'], 'got raw xtn'
fundingtxid = rpc.sendrawtransaction(result['hex'])
assert fundingtxid, 'got txid'
# confirm the above xtn
rpc.generate(1)
result = rpc.rewardsinfo(fundingtxid)
assert_success(result)
assert_equal(result['name'], 'STUFF')
assert_equal(result['APR'], "25.00000000")
assert_equal(result['minseconds'], 0)
assert_equal(result['maxseconds'], 864000)
assert_equal(result['funding'], "7777.00000000")
assert_equal(result['mindeposit'], "10.00000000")
assert_equal(result['fundingtxid'], fundingtxid)
# checking if new plan in rewardslist
result = rpc.rewardslist()
assert_equal(result[0], fundingtxid)
# creating reward plan with already existing name, should return error
result = rpc.rewardscreatefunding("STUFF", "7777", "25", "0", "10", "10")
assert_error(result)
# add funding amount must be positive
result = rpc.rewardsaddfunding("STUFF", fundingtxid, "-1")
assert_error(result)
# add funding amount must be positive
result = rpc.rewardsaddfunding("STUFF", fundingtxid, "0")
assert_error(result)
# adding valid funding
result = rpc.rewardsaddfunding("STUFF", fundingtxid, "555")
addfundingtxid = self.send_and_mine(result['hex'], rpc)
assert addfundingtxid, 'got funding txid'
# checking if funding added to rewardsplan
result = rpc.rewardsinfo(fundingtxid)
assert_equal(result['funding'], "8332.00000000")
# trying to lock funds, locking funds amount must be positive
result = rpc.rewardslock("STUFF", fundingtxid, "-5")
assert_error(result)
# trying to lock funds, locking funds amount must be positive
result = rpc.rewardslock("STUFF", fundingtxid, "0")
assert_error(result)
# trying to lock less than the min amount is an error
result = rpc.rewardslock("STUFF", fundingtxid, "7")
assert_error(result)
# locking funds in rewards plan
result = rpc.rewardslock("STUFF", fundingtxid, "10")
assert_success(result)
locktxid = result['hex']
assert locktxid, "got lock txid"
# locktxid has not been broadcast yet
result = rpc.rewardsunlock("STUFF", fundingtxid, locktxid)
assert_error(result)
# broadcast xtn
txid = rpc.sendrawtransaction(locktxid)
assert txid, 'got txid from sendrawtransaction'
# confirm the xtn above
rpc.generate(1)
# will not unlock since reward amount is less than tx fee
result = rpc.rewardsunlock("STUFF", fundingtxid, locktxid)
assert_error(result)
def run_test(self):
print("Mining blocks...")
rpc = self.nodes[0]
rpc1 = self.nodes[1]
# utxos from block 1 become mature in block 101
rpc.generate(101)
self.sync_all()
rpc.getinfo()
rpc1.getinfo()
# this corresponds to -pubkey above
print("Importing privkeys")
rpc.importprivkey(self.privkey)
rpc1.importprivkey(self.privkey1)
self.run_rewards_tests()
if __name__ == '__main__':
CryptoconditionsRewardsTest().main()

View File

@@ -0,0 +1,288 @@
#!/usr/bin/env python2
# Copyright (c) 2018 SuperNET developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from test_framework.test_framework import BitcoinTestFramework
from test_framework.authproxy import JSONRPCException
from test_framework.util import assert_equal, assert_greater_than, \
initialize_chain_clean, initialize_chain, start_nodes, start_node, connect_nodes_bi, \
stop_nodes, sync_blocks, sync_mempools, wait_bitcoinds, rpc_port, assert_raises
from cryptoconditions import assert_success, assert_error, generate_random_string
class CryptoconditionsTokenTest(BitcoinTestFramework):
def setup_chain(self):
print("Initializing CC test directory "+self.options.tmpdir)
self.num_nodes = 2
initialize_chain_clean(self.options.tmpdir, self.num_nodes)
def setup_network(self, split = False):
print("Setting up network...")
self.addr = "RWPg8B91kfK5UtUN7z6s6TeV9cHSGtVY8D"
self.pubkey = "02676d00110c2cd14ae24f95969e8598f7ccfaa675498b82654a5b5bd57fc1d8cf"
self.privkey = "UqMgxk7ySPNQ4r9nKAFPjkXy6r5t898yhuNCjSZJLg3RAM4WW1m9"
self.addr1 = "RXEXoa1nRmKhMbuZovpcYwQMsicwzccZBp"
self.pubkey1 = "024026d4ad4ecfc1f705a9b42ca64af6d2ad947509c085534a30b8861d756c6ff0"
self.privkey1 = "UtdydP56pGTFmawHzHr1wDrc4oUwCNW1ttX8Pc3KrvH3MA8P49Wi"
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
extra_args=[[
# always give -ac_name as first extra_arg and port as third
'-ac_name=REGTEST',
'-conf='+self.options.tmpdir+'/node0/REGTEST.conf',
'-port=64367',
'-rpcport=64368',
'-regtest',
'-addressindex=1',
'-spentindex=1',
'-ac_supply=5555555',
'-ac_reward=10000000000000',
'-pubkey=' + self.pubkey,
'-ac_cc=2',
'-whitelist=127.0.0.1',
'-debug',
'--daemon',
'-rpcuser=rt',
'-rpcpassword=rt'
],
['-ac_name=REGTEST',
'-conf='+self.options.tmpdir+'/node1/REGTEST.conf',
'-port=64365',
'-rpcport=64366',
'-regtest',
'-addressindex=1',
'-spentindex=1',
'-ac_supply=5555555',
'-ac_reward=10000000000000',
'-pubkey=' + self.pubkey1,
'-ac_cc=2',
'-whitelist=127.0.0.1',
'-debug',
'-addnode=127.0.0.1:64367',
'--daemon',
'-rpcuser=rt',
'-rpcpassword=rt']]
)
self.is_network_split = split
self.rpc = self.nodes[0]
self.rpc1 = self.nodes[1]
self.sync_all()
print("Done setting up network")
def send_and_mine(self, xtn, rpc_connection):
txid = rpc_connection.sendrawtransaction(xtn)
assert txid, 'got txid'
# we need the tx above to be confirmed in the next block
rpc_connection.generate(1)
return txid
def run_token_tests(self):
rpc = self.nodes[0]
result = rpc.tokenaddress()
assert_success(result)
for x in ['AssetsCCaddress', 'myCCaddress', 'Assetsmarker', 'myaddress']:
assert_equal(result[x][0], 'R')
result = rpc.tokenaddress(self.pubkey)
assert_success(result)
for x in ['AssetsCCaddress', 'myCCaddress', 'Assetsmarker', 'myaddress', 'CCaddress']:
assert_equal(result[x][0], 'R')
# there are no tokens created yet
result = rpc.tokenlist()
assert_equal(result, [])
# trying to create token with negaive supply
result = rpc.tokencreate("NUKE", "-1987420", "no bueno supply")
assert_error(result)
# creating token with name more than 32 chars
result = rpc.tokencreate("NUKE123456789012345678901234567890", "1987420", "name too long")
assert_error(result)
# creating valid token
result = rpc.tokencreate("DUKE", "1987.420", "Duke's custom token")
assert_success(result)
tokenid = self.send_and_mine(result['hex'], rpc)
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)
assert_equal(result['balance'], 198742000000)
assert_equal(result['tokenid'], tokenid)
# get token balance for token without pubkey
result = rpc.tokenbalance(tokenid)
assert_success(result)
assert_equal(result['balance'], 198742000000)
assert_equal(result['tokenid'], tokenid)
# this is not a valid assetid
result = rpc.tokeninfo(self.pubkey)
assert_error(result)
# check tokeninfo for valid token
result = rpc.tokeninfo(tokenid)
assert_success(result)
assert_equal(result['tokenid'], tokenid)
assert_equal(result['owner'], self.pubkey)
assert_equal(result['name'], "DUKE")
assert_equal(result['supply'], 198742000000)
assert_equal(result['description'], "Duke's custom token")
# invalid numtokens ask
result = rpc.tokenask("-1", tokenid, "1")
assert_error(result)
# invalid numtokens ask
result = rpc.tokenask("0", tokenid, "1")
assert_error(result)
# invalid price ask
result = rpc.tokenask("1", tokenid, "-1")
assert_error(result)
# invalid price ask
result = rpc.tokenask("1", tokenid, "0")
assert_error(result)
# invalid tokenid ask
result = rpc.tokenask("100", "deadbeef", "1")
assert_error(result)
# valid ask
tokenask = rpc.tokenask("100", tokenid, "7.77")
tokenaskhex = tokenask['hex']
tokenaskid = self.send_and_mine(tokenask['hex'], rpc)
result = rpc.tokenorders()
order = result[0]
assert order, "found order"
# invalid ask fillunits
result = rpc.tokenfillask(tokenid, tokenaskid, "0")
assert_error(result)
# invalid ask fillunits
result = rpc.tokenfillask(tokenid, tokenaskid, "-777")
assert_error(result)
# valid ask fillunits
fillask = rpc.tokenfillask(tokenid, tokenaskid, "777")
result = self.send_and_mine(fillask['hex'], rpc)
txid = result[0]
assert txid, "found txid"
# should be no token orders
result = rpc.tokenorders()
assert_equal(result, [])
# checking ask cancellation
testorder = rpc.tokenask("100", tokenid, "7.77")
testorderid = self.send_and_mine(testorder['hex'], rpc)
cancel = rpc.tokencancelask(tokenid, testorderid)
self.send_and_mine(cancel["hex"], rpc)
result = rpc.tokenorders()
assert_equal(result, [])
# invalid numtokens bid
result = rpc.tokenbid("-1", tokenid, "1")
assert_error(result)
# invalid numtokens bid
result = rpc.tokenbid("0", tokenid, "1")
assert_error(result)
# invalid price bid
result = rpc.tokenbid("1", tokenid, "-1")
assert_error(result)
# invalid price bid
result = rpc.tokenbid("1", tokenid, "0")
assert_error(result)
# invalid tokenid bid
result = rpc.tokenbid("100", "deadbeef", "1")
assert_error(result)
tokenbid = rpc.tokenbid("100", tokenid, "10")
tokenbidhex = tokenbid['hex']
tokenbidid = self.send_and_mine(tokenbid['hex'], rpc)
result = rpc.tokenorders()
order = result[0]
assert order, "found order"
# invalid bid fillunits
result = rpc.tokenfillbid(tokenid, tokenbidid, "0")
assert_error(result)
# invalid bid fillunits
result = rpc.tokenfillbid(tokenid, tokenbidid, "-777")
assert_error(result)
# valid bid fillunits
fillbid = rpc.tokenfillbid(tokenid, tokenbidid, "1000")
result = self.send_and_mine(fillbid['hex'], rpc)
txid = result[0]
assert txid, "found txid"
# should be no token orders
result = rpc.tokenorders()
assert_equal(result, [])
# checking bid cancellation
testorder = rpc.tokenbid("100", tokenid, "7.77")
testorderid = self.send_and_mine(testorder['hex'], rpc)
cancel = rpc.tokencancelbid(tokenid, testorderid)
self.send_and_mine(cancel["hex"], rpc)
result = rpc.tokenorders()
assert_equal(result, [])
# invalid token transfer amount (have to add status to CC code!)
randompubkey = "021a559101e355c907d9c553671044d619769a6e71d624f68bfec7d0afa6bd6a96"
result = rpc.tokentransfer(tokenid,randompubkey,"0")
assert_error(result)
# invalid token transfer amount (have to add status to CC code!)
result = rpc.tokentransfer(tokenid,randompubkey,"-1")
assert_error(result)
# valid token transfer
sendtokens = rpc.tokentransfer(tokenid,randompubkey,"1")
self.send_and_mine(sendtokens["hex"], rpc)
result = rpc.tokenbalance(tokenid,randompubkey)
assert_equal(result["balance"], 1)
def run_test(self):
print("Mining blocks...")
rpc = self.nodes[0]
rpc1 = self.nodes[1]
# utxos from block 1 become mature in block 101
rpc.generate(101)
self.sync_all()
rpc.getinfo()
rpc1.getinfo()
# this corresponds to -pubkey above
print("Importing privkeys")
rpc.importprivkey(self.privkey)
rpc1.importprivkey(self.privkey1)
self.run_token_tests()
if __name__ == '__main__':
CryptoconditionsTokenTest().main()

View File

@@ -28,7 +28,7 @@ class ListReceivedTest (BitcoinTestFramework):
self.sync_all()
assert_equal(new_height, self.nodes[0].getblockcount())
def run_test_release(self, release, expected_memo, height):
def run_test_release(self, release, height):
self.generate_and_sync(height+1)
taddr = self.nodes[1].getnewaddress()
zaddr1 = self.nodes[1].z_getnewaddress(release)
@@ -61,7 +61,7 @@ class ListReceivedTest (BitcoinTestFramework):
# Generate some change by sending part of zaddr1 to zaddr2
zaddr2 = self.nodes[1].z_getnewaddress(release)
opid = self.nodes[1].z_sendmany(zaddr1,
[{'address': zaddr2, 'amount': 0.6, 'memo': my_memo}])
[{'address': zaddr2, 'amount': 0.6}])
txid = wait_and_assert_operationid_status(self.nodes[1], opid)
self.sync_all()
self.generate_and_sync(height+4)
@@ -74,12 +74,12 @@ class ListReceivedTest (BitcoinTestFramework):
assert_equal(txid, r[0]['txid'])
assert_equal(Decimal('0.4')-fee, r[0]['amount'])
assert_true(r[0]['change'], "Note valued at (0.4-fee) should be change")
assert_equal(expected_memo, r[0]['memo'])
assert_equal(no_memo, r[0]['memo'])
# The old note still exists (it's immutable), even though it is spent
assert_equal(Decimal('1.0'), r[1]['amount'])
assert_false(r[1]['change'], "Note valued at 1.0 should not be change")
assert_equal(expected_memo, r[0]['memo'])
assert_equal(my_memo, r[1]['memo'])
# zaddr2 should not have change
r = self.nodes[1].z_listreceivedbyaddress(zaddr2, 0)
@@ -88,11 +88,11 @@ class ListReceivedTest (BitcoinTestFramework):
assert_equal(txid, r[0]['txid'])
assert_equal(Decimal('0.6'), r[0]['amount'])
assert_false(r[0]['change'], "Note valued at 0.6 should not be change")
assert_equal(my_memo, r[0]['memo'])
assert_equal(no_memo, r[0]['memo'])
def run_test(self):
self.run_test_release('sprout', no_memo, 200)
self.run_test_release('sapling', no_memo, 204)
self.run_test_release('sprout', 200)
self.run_test_release('sapling', 204)
if __name__ == '__main__':
ListReceivedTest().main()

View File

@@ -68,12 +68,22 @@ class WalletPersistenceTest (BitcoinTestFramework):
# Verify shielded balance
assert_equal(self.nodes[0].z_getbalance(sapling_addr), Decimal('20'))
# Verify size of shielded pools
pools = self.nodes[0].getblockchaininfo()['valuePools']
assert_equal(pools[0]['chainValue'], Decimal('0')) # Sprout
assert_equal(pools[1]['chainValue'], Decimal('20')) # Sapling
# Restart the nodes
stop_nodes(self.nodes)
wait_bitcoinds()
self.setup_network()
# Verify size of shielded pools
pools = self.nodes[0].getblockchaininfo()['valuePools']
assert_equal(pools[0]['chainValue'], Decimal('0')) # Sprout
assert_equal(pools[1]['chainValue'], Decimal('20')) # Sapling
# Node 0 sends some shielded funds to Node 1
dest_addr = self.nodes[1].z_getnewaddress('sapling')
recipients = []
@@ -128,4 +138,4 @@ class WalletPersistenceTest (BitcoinTestFramework):
assert_equal(self.nodes[1].z_getbalance(dest_addr), Decimal('16'))
if __name__ == '__main__':
WalletPersistenceTest().main()
WalletPersistenceTest().main()

View File

@@ -261,7 +261,6 @@ BITCOIN_CORE_H = \
wallet/wallet.h \
wallet/wallet_ismine.h \
wallet/walletdb.h \
veruslaunch.h \
zmq/zmqabstractnotifier.h \
zmq/zmqconfig.h\
zmq/zmqnotificationinterface.h \
@@ -483,7 +482,6 @@ libbitcoin_common_a_SOURCES = \
script/script_error.cpp \
script/sign.cpp \
script/standard.cpp \
veruslaunch.cpp \
transaction_builder.cpp \
$(BITCOIN_CORE_H) \
$(LIBZCASH_H)

View File

@@ -10,7 +10,6 @@ komodo_test_SOURCES = \
test-komodo/test_coinimport.cpp \
test-komodo/test_eval_bet.cpp \
test-komodo/test_eval_notarisation.cpp \
test-komodo/test_crosschain.cpp \
test-komodo/test_parse_notarisation.cpp
komodo_test_CPPFLAGS = $(komodod_CPPFLAGS)

View File

@@ -11,7 +11,7 @@ if [ -z "$delay" ]; then delay=20; fi
./listassetchainparams | while read args; do
gen=""
if [ $[RANDOM % 10] == 1 ]; then
gen=" -gen"
gen=" -gen -genproclimit=1"
fi
./komodod $gen $args $overide_args -pubkey=$pubkey -addnode=$seed_ip &

View File

@@ -94,7 +94,8 @@
},
{
"ac_name": "OOT",
"ac_supply": "216000000"
"ac_supply": "216000000",
"ac_sapling": "5000000"
},
{
"ac_name": "BNTN",
@@ -177,18 +178,6 @@
"190.114.254.104"
]
},
{
"ac_name": "KMDICE",
"ac_supply": "10500000",
"ac_reward": "2500000000",
"ac_halving": "210000",
"ac_cc": "2",
"addressindex": "1",
"spentindex": "1",
"addnode": [
"144.76.217.232"
]
},
{
"ac_name": "DION",
"ac_supply": "3900000000",

View File

@@ -27,7 +27,7 @@ echo $pubkey
./komodod -pubkey=$pubkey -ac_name=BEER -ac_supply=100000000 -addnode=78.47.196.146 &
./komodod -pubkey=$pubkey -ac_name=PIZZA -ac_supply=100000000 -addnode=78.47.196.146 &
./komodod -pubkey=$pubkey -ac_name=NINJA -ac_supply=100000000 -addnode=78.47.196.146 &
./komodod -pubkey=$pubkey -ac_name=OOT -ac_supply=216000000 -addnode=174.138.107.226 &
./komodod -pubkey=$pubkey -ac_name=OOT -ac_supply=216000000 -ac_saplinig=5000000 -addnode=174.138.107.226 &
./komodod -pubkey=$pubkey -ac_name=BNTN -ac_supply=500000000 -addnode=94.130.169.205 &
./komodod -pubkey=$pubkey -ac_name=CHAIN -ac_supply=999999 -addnode=78.47.146.222 &
./komodod -pubkey=$pubkey -ac_name=PRLPAY -ac_supply=500000000 -addnode=13.250.226.125 &

View File

@@ -16,6 +16,8 @@
#include <event2/buffer.h>
#include <event2/keyvalq_struct.h>
#include "support/events.h"
uint16_t BITCOIND_RPCPORT = 7771;
char ASSETCHAINS_SYMBOL[65];
#include <univalue.h>
@@ -64,27 +66,6 @@ public:
};
#define FROM_CLI
#include "uint256.h"
#include "arith_uint256.h"
#include "komodo_structs.h"
#include "komodo_globals.h"
#include "komodo_utils.h"
#include "komodo_cJSON.c"
#include "komodo_notary.h"
void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth)
{
}
uint32_t komodo_heightstamp(int32_t height)
{
return(0);
}
//
// This function returns either one of EXIT_ codes when it's expected to stop the process or
// CONTINUE_EXECUTION when it's expected to continue further.
@@ -99,7 +80,11 @@ static int AppInitRPC(int argc, char* argv[])
// Parameters
//
ParseParameters(argc, argv);
komodo_args(argv[0]);
std:string name;
name = GetArg("-ac_name","");
if ( !name.empty() )
strncpy(ASSETCHAINS_SYMBOL,name.c_str(),sizeof(ASSETCHAINS_SYMBOL)-1);
if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help") || mapArgs.count("-version")) {
std::string strUsage = _("Komodo RPC client version") + " " + FormatFullVersion() + "\n" + PrivacyInfo();
if (!mapArgs.count("-version")) {

View File

@@ -35,7 +35,7 @@ CScript EncodeAssetOpRet(uint8_t funcid,uint256 assetid,uint256 assetid2,int64_t
bool DecodeAssetCreateOpRet(const CScript &scriptPubKey,std::vector<uint8_t> &origpubkey,std::string &name,std::string &description);
uint8_t DecodeAssetOpRet(const CScript &scriptPubKey,uint256 &assetid,uint256 &assetid2,int64_t &price,std::vector<uint8_t> &origpubkey);
bool SetAssetOrigpubkey(std::vector<uint8_t> &origpubkey,int64_t &price,const CTransaction &tx);
int64_t IsAssetvout(int64_t &price,std::vector<uint8_t> &origpubkey,const CTransaction& tx,int32_t v,uint256 refassetid);
int64_t IsAssetvout(int32_t maxAssetExactAmountDepth, struct CCcontract_info *cp, Eval* eval, int64_t &price,std::vector<uint8_t> &origpubkey,const CTransaction& tx,int32_t v,uint256 refassetid);
bool ValidateBidRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice);
bool ValidateAskRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice);
bool ValidateSwapRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice);
@@ -44,7 +44,8 @@ bool SetAskFillamounts(int64_t &paid,int64_t &remaining_price,int64_t orig_nValu
bool SetSwapFillamounts(int64_t &paid,int64_t &remaining_price,int64_t orig_nValue,int64_t &received,int64_t totalprice);
int64_t AssetValidateBuyvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpprice,std::vector<uint8_t> &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 refassetid);
int64_t AssetValidateSellvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpprice,std::vector<uint8_t> &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 assetid);
bool AssetExactAmounts(struct CCcontract_info *cp,int64_t &inputs,int32_t starti,int64_t &outputs,Eval* eval,const CTransaction &tx,uint256 assetid);
bool AssetExactAmounts(int32_t maxDepth, struct CCcontract_info *cp,int64_t &inputs,int32_t starti,int64_t &outputs,Eval* eval,const CTransaction &tx,uint256 assetid);
//bool AssetExactAmounts(bool doValidateTx, struct CCcontract_info *cp, int64_t &inputs, int32_t starti, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 assetid, std::vector<CTransaction> &ccVinsTxs);
// CCassetstx
int64_t GetAssetBalance(CPubKey pk,uint256 tokenid);

View File

@@ -342,25 +342,54 @@ bool GetAssetorigaddrs(struct CCcontract_info *cp,char *CCaddr,char *destaddr,co
else return(false);
}
int64_t IsAssetvout(int64_t &price,std::vector<uint8_t> &origpubkey,const CTransaction& tx,int32_t v,uint256 refassetid)
// Checks if the vout is a really Asset CC vout
// if maxAssetExactAmountDepth > 0, it also validates the vin transaction itself:
// it should be either sum(cc vins) == sum(cc vouts) or the transaction is the 'tokenbase' ('c') tx
int64_t IsAssetvout(int32_t maxAssetExactAmountDepth, struct CCcontract_info *cp, Eval* eval, int64_t &price,std::vector<uint8_t> &origpubkey,const CTransaction& tx,int32_t v,uint256 refassetid)
{
uint256 assetid,assetid2; int64_t nValue=0; int32_t n; uint8_t funcid;
if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) // maybe check address too?
{
n = tx.vout.size();
if (maxAssetExactAmountDepth > 0) {
//validate all tx
int64_t myCCVinsAmount = 0, myCCVoutsAmount = 0;
std::vector<CTransaction> ccVinsTxs;
//std::cerr << "IsAssetvout() validate=yes" << std::endl;
const bool validateVinTxs = false;
bool isEqualAmounts = AssetExactAmounts(maxAssetExactAmountDepth, cp, myCCVinsAmount, 0, myCCVoutsAmount, eval, tx, refassetid);
// if ccInputs != ccOutputs and it is not the tokenbase tx means it is possibly fake tx (dimxy):
if (!isEqualAmounts && refassetid != tx.GetHash()) { // checking that this is the true tokenbase tx, by verifying that funcid=c, is done further in this function (dimxy)
std::cerr << "IsAssetvout() detected bad tx=" << tx.GetHash().GetHex() << ": cc inputs != cc outputs and not the 'tokenbase' tx" << std::endl;
return 0;
}
}
n = tx.vout.size();
if (v >= n - 1) { // just moved this up (dimxy)
std::cerr << "isAssetVout() internal err: (v >= n - 1), returning 0" << std::endl;
return(0);
}
nValue = tx.vout[v].nValue;
//fprintf(stderr,"CC vout v.%d of n.%d %.8f\n",v,n,(double)nValue/COIN);
if ( v >= n-1 )
return(0);
// fprintf(stderr,"IsAssetvout() CC vout v.%d of n=%d amount=%.8f\n",v,n,(double)nValue/COIN);
if ( (funcid= DecodeAssetOpRet(tx.vout[n-1].scriptPubKey,assetid,assetid2,price,origpubkey)) == 0 )
{
fprintf(stderr,"null decodeopret v.%d\n",v);
fprintf(stderr,"IsAssetvout() null decodeopret v.%d\n",v);
return(0);
}
else if ( funcid == 'c' )
{
if ( refassetid == tx.GetHash() && v == 0 )
return(nValue);
if (refassetid == tx.GetHash() && v == 0) {
std::cerr << "isAssetVout() this is the tokenbase 'c' tx, txid=" << tx.GetHash().GetHex() << " returning nValue=" << nValue << std::endl;
return(nValue);
}
}
else if ( (funcid == 'b' || funcid == 'B') && v == 0 ) // critical! 'b'/'B' vout0 is NOT asset
return(0);
@@ -368,7 +397,7 @@ int64_t IsAssetvout(int64_t &price,std::vector<uint8_t> &origpubkey,const CTrans
{
if ( assetid == refassetid )
{
//fprintf(stderr,"returning %.8f\n",(double)nValue/COIN);
fprintf(stderr,"IsAssetvout() returning %.8f\n",(double)nValue/COIN);
return(nValue);
}
}
@@ -443,29 +472,37 @@ int64_t AssetValidateSellvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpp
fprintf(stderr,"AssetValidateSellvin\n");
if ( (nValue= AssetValidateCCvin(cp,eval,CCaddr,origaddr,tx,1,vinTx)) == 0 )
return(0);
if ( (assetoshis= IsAssetvout(tmpprice,tmporigpubkey,vinTx,0,assetid)) == 0 )
if ( (assetoshis= IsAssetvout(1, cp, NULL, tmpprice,tmporigpubkey,vinTx,0,assetid)) == 0 )
return eval->Invalid("invalid missing CC vout0 for sellvin");
else return(assetoshis);
}
bool AssetExactAmounts(struct CCcontract_info *cp,int64_t &inputs,int32_t starti,int64_t &outputs,Eval* eval,const CTransaction &tx,uint256 assetid)
// overload with additional params for deep tx validation (dimxy)
bool AssetExactAmounts(int maxDepth, struct CCcontract_info *cp, int64_t &inputs, int32_t starti, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 assetid)
{
CTransaction vinTx; uint256 hashBlock,id,id2; int32_t i,flag,numvins,numvouts; int64_t assetoshis; std::vector<uint8_t> tmporigpubkey; int64_t tmpprice;
numvins = tx.vin.size();
numvouts = tx.vout.size();
inputs = outputs = 0;
maxDepth--;
for (i=starti; i<numvins; i++)
{
if ( (*cp->ismyvin)(tx.vin[i].scriptSig) != 0 )
{
if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 )
{
//std::cerr << "AssetExactAmounts() eval is true=" << (eval != NULL) << " ismyvin=ok for_i=" << i << std::endl;
// we are really not inside validation! -- dimxy
if ( (eval && eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0) || (!eval && !myGetTransaction(tx.vin[i].prevout.hash, vinTx, hashBlock)) )
{
fprintf(stderr,"i.%d starti.%d numvins.%d\n",i,starti,numvins);
return eval->Invalid("always should find vin, but didnt");
}
else if ( (assetoshis= IsAssetvout(tmpprice,tmporigpubkey,vinTx,tx.vin[i].prevout.n,assetid)) != 0 )
fprintf(stderr,"AssetExactAmounts() cannot read vintx i.%d starti.%d numvins.%d\n", i,starti,numvins);
return (!eval) ? false : eval->Invalid("always should find vin, but didnt");
} // false means 'don't go deeper' -- dimxy
else if ( (assetoshis= IsAssetvout( maxDepth, cp, eval, tmpprice,tmporigpubkey,vinTx,tx.vin[i].prevout.n,assetid)) != 0 )
{
fprintf(stderr,"vin%d %llu, ",i,(long long)assetoshis);
fprintf(stderr,"AssetExactAmounts() vin%d %llu, ",i,(long long)assetoshis);
inputs += assetoshis;
}
else
@@ -473,33 +510,47 @@ bool AssetExactAmounts(struct CCcontract_info *cp,int64_t &inputs,int32_t starti
if ( vinTx.vout[i].scriptPubKey.IsPayToCryptoCondition() != 0 && DecodeAssetOpRet(vinTx.vout[vinTx.vout.size()-1].scriptPubKey,id,id2,tmpprice,tmporigpubkey) == 't' && id == assetid )
{
assetoshis = vinTx.vout[i].nValue;
fprintf(stderr,"vin%d %llu special case, ",i,(long long)assetoshis);
fprintf(stderr,"AssetExactAmounts() vin%d assetoshis=%llu special case, ",i,(long long)assetoshis);
inputs += assetoshis;
}
}
}
}
if ( DecodeAssetOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,id,id2,tmpprice,tmporigpubkey) == 't' && id == assetid )
flag = 1;
else flag = 0;
for (i=0; i<numvouts; i++)
{
if ( (assetoshis= IsAssetvout(tmpprice,tmporigpubkey,tx,i,assetid)) != 0 )
{ // 'false' means 'dont go deep' -- dimxy
if ( (assetoshis= IsAssetvout(maxDepth, cp, eval, tmpprice,tmporigpubkey,tx,i,assetid)) != 0 )
{
fprintf(stderr,"vout%d %llu, ",i,(long long)assetoshis);
fprintf(stderr,"AssetExactAmounts() vout%d assetoshis=%llu, ",i,(long long)assetoshis);
outputs += assetoshis;
}
// Note: account it only if this is 'transfer' tx -- dimxy
else if ( flag != 0 && tx.vout[i].scriptPubKey.IsPayToCryptoCondition() != 0 )
{
assetoshis = tx.vout[i].nValue;
fprintf(stderr,"vout%d %llu special case, ",i,(long long)assetoshis);
fprintf(stderr,"AssetExactAmounts() vout%d assetoshis=%llu special case, ",i,(long long)assetoshis);
outputs += assetoshis;
}
}
//std::cerr << "AssetExactAmounts() inputs=" << inputs << " outputs=" << outputs << " for txid=" << tx.GetHash().GetHex() << std::endl;
if ( inputs != outputs )
{
fprintf(stderr,"inputs %.8f vs %.8f outputs\n",(double)inputs/COIN,(double)outputs/COIN);
std::cerr << "AssetExactAmounts() incorrect inputs=" << (double)inputs / COIN << " vs outputs=" << (double)outputs/COIN << " for txid=" << tx.GetHash().GetHex() << std::endl;
return(false);
}
else return(true);
}
// overload for existing calls of this function (dimxy)
/*bool AssetExactAmounts(struct CCcontract_info *cp, int64_t &inputs, int32_t starti, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 assetid) {
std::vector<CTransaction> ccVinsTxs;
return AssetExactAmounts(true, cp, inputs, starti, outputs, eval, tx, assetid);
}*/

View File

@@ -38,25 +38,29 @@ int64_t AddAssetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubK
Getscriptaddress(destaddr,vintx.vout[vout].scriptPubKey);
if ( strcmp(destaddr,coinaddr) != 0 && strcmp(destaddr,cp->unspendableCCaddr) != 0 && strcmp(destaddr,cp->unspendableaddr2) != 0 )
continue;
fprintf(stderr,"check %s %.8f\n",destaddr,(double)vintx.vout[vout].nValue/COIN);
if ( (nValue= IsAssetvout(price,origpubkey,vintx,vout,assetid)) > 0 && myIsutxo_spentinmempool(txid,vout) == 0 )
fprintf(stderr,"AddAssetInputs() check destaddress=%s vout amount=%.8f\n",destaddr,(double)vintx.vout[vout].nValue/COIN);
if ( (nValue= IsAssetvout(1, cp, NULL, price,origpubkey,vintx,vout,assetid)) > 0 && myIsutxo_spentinmempool(txid,vout) == 0 )
{
if ( total != 0 && maxinputs != 0 )
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
nValue = it->second.satoshis;
totalinputs += nValue;
//std::cerr << "AddAssetInputs() adding input nValue=" << nValue << std::endl;
n++;
if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) )
break;
}
}
}
//std::cerr << "AddAssetInputs() found totalinputs=" << totalinputs << std::endl;
return(totalinputs);
}
int64_t GetAssetBalance(CPubKey pk,uint256 tokenid)
{
CMutableTransaction mtx; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_ASSETS);
return(AddAssetInputs(cp,mtx,pk,tokenid,0,0));
}
@@ -186,7 +190,8 @@ UniValue AssetOrders(uint256 refassetid)
std::string CreateAsset(int64_t txfee,int64_t assetsupply,std::string name,std::string description)
{
CMutableTransaction mtx; CPubKey mypk; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk; struct CCcontract_info *cp,C;
if ( assetsupply < 0 )
{
fprintf(stderr,"negative assetsupply %lld\n",(long long)assetsupply);
@@ -212,7 +217,8 @@ std::string CreateAsset(int64_t txfee,int64_t assetsupply,std::string name,std::
std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector<uint8_t> destpubkey,int64_t total)
{
CMutableTransaction mtx; CPubKey mypk; uint64_t mask; int64_t CCchange=0,inputs=0; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk; uint64_t mask; int64_t CCchange=0,inputs=0; struct CCcontract_info *cp,C;
if ( total < 0 )
{
fprintf(stderr,"negative total %lld\n",(long long)total);
@@ -232,6 +238,11 @@ std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector<uint8_t> des
mask = ~((1LL << mtx.vin.size()) - 1);
if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,total,60)) > 0 )
{
if (inputs < total) { //added dimxy
std::cerr << "AssetTransfer(): insufficient funds" << std::endl;
return ("");
}
if ( inputs > total )
CCchange = (inputs - total);
//for (i=0; i<n; i++)
@@ -247,7 +258,8 @@ std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector<uint8_t> des
std::string AssetConvert(int64_t txfee,uint256 assetid,std::vector<uint8_t> destpubkey,int64_t total,int32_t evalcode)
{
CMutableTransaction mtx; CPubKey mypk; int64_t CCchange=0,inputs=0; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk; int64_t CCchange=0,inputs=0; struct CCcontract_info *cp,C;
if ( total < 0 )
{
fprintf(stderr,"negative total %lld\n",(long long)total);
@@ -273,7 +285,8 @@ std::string AssetConvert(int64_t txfee,uint256 assetid,std::vector<uint8_t> dest
std::string CreateBuyOffer(int64_t txfee,int64_t bidamount,uint256 assetid,int64_t pricetotal)
{
CMutableTransaction mtx; CPubKey mypk; struct CCcontract_info *cp,C; uint256 hashBlock; CTransaction vintx; std::vector<uint8_t> origpubkey; std::string name,description;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk; struct CCcontract_info *cp,C; uint256 hashBlock; CTransaction vintx; std::vector<uint8_t> origpubkey; std::string name,description;
if ( bidamount < 0 || pricetotal < 0 )
{
fprintf(stderr,"negative bidamount %lld, pricetotal %lld\n",(long long)bidamount,(long long)pricetotal);
@@ -303,7 +316,11 @@ std::string CreateBuyOffer(int64_t txfee,int64_t bidamount,uint256 assetid,int64
std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t pricetotal)
{
CMutableTransaction mtx; CPubKey mypk; uint64_t mask; int64_t inputs,CCchange; CScript opret; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk; uint64_t mask; int64_t inputs,CCchange; CScript opret; struct CCcontract_info *cp,C;
//std::cerr << "CreateSell() askamount=" << askamount << " pricetotal=" << pricetotal << std::endl;
if ( askamount < 0 || pricetotal < 0 )
{
fprintf(stderr,"negative askamount %lld, askamount %lld\n",(long long)pricetotal,(long long)askamount);
@@ -318,8 +335,12 @@ std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t p
mask = ~((1LL << mtx.vin.size()) - 1);
if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,askamount,60)) > 0 )
{
if ( inputs < askamount )
askamount = inputs;
if (inputs < askamount) {
//askamount = inputs;
std::cerr << "CreateSell(): insufficient tokens for ask" << std::endl;
return ("");
}
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,askamount,GetUnspendable(cp,0)));
if ( inputs > askamount )
CCchange = (inputs - askamount);
@@ -327,15 +348,21 @@ std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t p
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk));
opret = EncodeAssetOpRet('s',assetid,zeroid,pricetotal,Mypubkey());
return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,opret));
} else fprintf(stderr,"need some assets to place ask\n");
}
else {
fprintf(stderr, "need some assets to place ask\n");
}
}
fprintf(stderr,"need some native coins to place ask\n");
else { // dimxy added 'else', because it was misleading message before
fprintf(stderr, "need some native coins to place ask\n");
}
return("");
}
std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 assetid2,int64_t pricetotal)
{
CMutableTransaction mtx; CPubKey mypk; uint64_t mask; int64_t inputs,CCchange; CScript opret; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk; uint64_t mask; int64_t inputs,CCchange; CScript opret; struct CCcontract_info *cp,C;
fprintf(stderr,"asset swaps disabled\n");
return("");
if ( askamount < 0 || pricetotal < 0 )
@@ -366,15 +393,22 @@ std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 a
opret = EncodeAssetOpRet('e',assetid,assetid2,pricetotal,Mypubkey());
}
return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,opret));
} else fprintf(stderr,"need some assets to place ask\n");
}
else {
fprintf(stderr, "need some assets to place ask\n");
}
}
fprintf(stderr,"need some native coins to place ask\n");
else { // dimxy added 'else', because it was misleading message before
fprintf(stderr,"need some native coins to place ask\n");
}
return("");
}
std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid)
{
CMutableTransaction mtx; CTransaction vintx; uint64_t mask; uint256 hashBlock; int64_t bidamount; CPubKey mypk; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction vintx; uint64_t mask; uint256 hashBlock; int64_t bidamount; CPubKey mypk; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_ASSETS);
if ( txfee == 0 )
txfee = 10000;
@@ -395,7 +429,8 @@ std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid)
std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid)
{
CMutableTransaction mtx; CTransaction vintx; uint64_t mask; uint256 hashBlock; int64_t askamount; CPubKey mypk; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction vintx; uint64_t mask; uint256 hashBlock; int64_t askamount; CPubKey mypk; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_ASSETS);
if ( txfee == 0 )
txfee = 10000;
@@ -416,7 +451,8 @@ std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid)
std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t fillamount)
{
CTransaction vintx; uint256 hashBlock; CMutableTransaction mtx; CPubKey mypk; std::vector<uint8_t> origpubkey; int32_t bidvout=0; uint64_t mask; int64_t origprice,bidamount,paid_amount,remaining_required,inputs,CCchange=0; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction vintx; uint256 hashBlock; CPubKey mypk; std::vector<uint8_t> origpubkey; int32_t bidvout=0; uint64_t mask; int64_t origprice,bidamount,paid_amount,remaining_required,inputs,CCchange=0; struct CCcontract_info *cp,C;
if ( fillamount < 0 )
{
fprintf(stderr,"negative fillamount %lld\n",(long long)fillamount);
@@ -456,7 +492,8 @@ std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t f
std::string FillSell(int64_t txfee,uint256 assetid,uint256 assetid2,uint256 asktxid,int64_t fillunits)
{
CTransaction vintx,filltx; uint256 hashBlock; CMutableTransaction mtx; CPubKey mypk; std::vector<uint8_t> origpubkey; double dprice; uint64_t mask; int32_t askvout=0; int64_t received_assetoshis,total_nValue,orig_assetoshis,paid_nValue,remaining_nValue,inputs,CCchange=0; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction vintx,filltx; uint256 hashBlock; CPubKey mypk; std::vector<uint8_t> origpubkey; double dprice; uint64_t mask; int32_t askvout=0; int64_t received_assetoshis,total_nValue,orig_assetoshis,paid_nValue,remaining_nValue,inputs,CCchange=0; struct CCcontract_info *cp,C;
if ( fillunits < 0 )
{
CCerror = strprintf("negative fillunits %lld\n",(long long)fillunits);

View File

@@ -105,6 +105,7 @@ extern CWallet* pwalletMain;
#endif
bool GetAddressUnspent(uint160 addressHash, int type,std::vector<std::pair<CAddressUnspentKey,CAddressUnspentValue> > &unspentOutputs);
CBlockIndex *komodo_getblockindex(uint256 hash);
int32_t komodo_nextheight();
static const uint256 zeroid;
bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock);
@@ -177,6 +178,7 @@ std::string FinalizeCCTx(uint64_t skipmask,struct CCcontract_info *cp,CMutableTr
void SetCCunspents(std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs,char *coinaddr);
void SetCCtxids(std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex,char *coinaddr);
int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs);
int64_t AddNormalinputs2(CMutableTransaction &mtx,int64_t total,int32_t maxinputs);
int64_t CCutxovalue(char *coinaddr,uint256 utxotxid,int32_t utxovout);
// curve25519 and sha256

View File

@@ -62,8 +62,26 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
GetCCaddress(cp,myaddr,mypk);
mycond = MakeCCcond1(cp->evalcode,mypk);
GetCCaddress(cp,unspendable,unspendablepk);
othercond = MakeCCcond1(cp->evalcode,unspendablepk);
//fprintf(stderr,"myCCaddr.(%s) %p vs unspendable.(%s) %p\n",myaddr,mycond,unspendable,othercond);
othercond = MakeCCcond1(cp->evalcode,unspendablepk);
//Reorder vins so that for multiple normal vins all other except vin0 goes to the end
//This is a must to avoid hardfork change of validation in every CC, because there could be maximum one normal vin at the begining with current validation.
for (i=0; i<n; i++)
{
if ( GetTransaction(mtx.vin[i].prevout.hash,vintx,hashBlock,false) != 0 )
{
if ( vintx.vout[mtx.vin[i].prevout.n].scriptPubKey.IsPayToCryptoCondition() == 0 && ccvins==0)
normalvins++;
else ccvins++;
}
}
if (normalvins>1 && ccvins)
{
for(i=1;i<normalvins;i++)
{
mtx.vin.push_back(mtx.vin[1]);
mtx.vin.erase(mtx.vin.begin() + 1);
}
}
memset(utxovalues,0,sizeof(utxovalues));
for (i=0; i<n; i++)
{
@@ -74,14 +92,12 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
totalinputs += utxovalues[i];
if ( vintx.vout[utxovout].scriptPubKey.IsPayToCryptoCondition() == 0 )
{
//fprintf(stderr,"vin.%d is normal %.8f\n",i,(double)utxovalues[i]/COIN);
if (ccvins==0) normalvins++;
//fprintf(stderr,"vin.%d is normal %.8f\n",i,(double)utxovalues[i]/COIN);
normalinputs += utxovalues[i];
vinimask |= (1LL << i);
}
else
{
ccvins++;
{
mask |= (1LL << i);
}
} else fprintf(stderr,"FinalizeCCTx couldnt find %s\n",mtx.vin[i].prevout.hash.ToString().c_str());
@@ -98,16 +114,6 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
mtx.vout.push_back(CTxOut(0,opret));
PrecomputedTransactionData txdata(mtx);
n = mtx.vin.size();
//Reorder vins so that for multiple normal vins all other except vin0 goes to the end
//This is a must to avoid hardfork change of validation in every CC, because there could be maximum one normal vin at the begining with current validation.
if (normalvins>1)
{
for(i=1;i<normalvins;i++)
{
mtx.vin.push_back(mtx.vin[1]);
mtx.vin.erase(mtx.vin.begin() + 1);
}
}
for (i=0; i<n; i++)
{
if ( GetTransaction(mtx.vin[i].prevout.hash,vintx,hashBlock,false) != 0 )
@@ -431,3 +437,92 @@ int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int3
#endif
return(0);
}
int64_t AddNormalinputs2(CMutableTransaction &mtx,int64_t total,int32_t maxinputs)
{
int32_t abovei,belowi,ind,vout,i,n = 0,maxutxos=64; 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;
sum = 0;
Getscriptaddress(coinaddr,CScript() << Mypubkey() << OP_CHECKSIG);
SetCCunspents(unspentOutputs,coinaddr);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
txid = it->first.txhash;
vout = (int32_t)it->first.index;
if ( it->second.satoshis < threshold )
continue;
if ( myGetTransaction(txid,tx,hashBlock) != 0 && tx.vout.size() > 0 && vout < tx.vout.size() && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() == 0 )
{
//fprintf(stderr,"check %.8f to vins array.%d of %d %s/v%d\n",(double)out.tx->vout[out.i].nValue/COIN,n,maxutxos,txid.GetHex().c_str(),(int32_t)vout);
if ( mtx.vin.size() > 0 )
{
for (i=0; i<mtx.vin.size(); i++)
if ( txid == mtx.vin[i].prevout.hash && vout == mtx.vin[i].prevout.n )
break;
if ( i != mtx.vin.size() )
continue;
}
if ( n > 0 )
{
for (i=0; i<n; i++)
if ( txid == utxos[i].txid && vout == utxos[i].vout )
break;
if ( i != n )
continue;
}
if ( myIsutxo_spentinmempool(txid,vout) == 0 )
{
up = &utxos[n++];
up->txid = txid;
up->nValue = it->second.satoshis;
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 )
break;
}
}
}
remains = total;
for (i=0; i<maxinputs && n>0; i++)
{
below = above = 0;
abovei = belowi = -1;
if ( CC_vinselect(&abovei,&above,&belowi,&below,utxos,n,remains) < 0 )
{
printf("error finding unspent i.%d of %d, %.8f vs %.8f\n",i,n,(double)remains/COIN,(double)total/COIN);
free(utxos);
return(0);
}
if ( belowi < 0 || abovei >= 0 )
ind = abovei;
else ind = belowi;
if ( ind < 0 )
{
printf("error finding unspent i.%d of %d, %.8f vs %.8f, abovei.%d belowi.%d ind.%d\n",i,n,(double)remains/COIN,(double)total/COIN,abovei,belowi,ind);
free(utxos);
return(0);
}
up = &utxos[ind];
mtx.vin.push_back(CTxIn(up->txid,up->vout,CScript()));
totalinputs += up->nValue;
remains -= up->nValue;
utxos[ind] = utxos[--n];
memset(&utxos[n],0,sizeof(utxos[n]));
//fprintf(stderr,"totalinputs %.8f vs total %.8f i.%d vs max.%d\n",(double)totalinputs/COIN,(double)total/COIN,i,maxinputs);
if ( totalinputs >= total || (i+1) >= maxinputs )
break;
}
free(utxos);
if ( totalinputs >= total )
{
//fprintf(stderr,"return totalinputs %.8f\n",(double)totalinputs/COIN);
return(totalinputs);
}
return(0);
}

View File

@@ -129,6 +129,10 @@
vout.n-1: opreturn [EVAL_ASSETS] ['E'] [assetid vin0+1] [assetid vin2] [remaining asset2 required] [origpubkey]
*/
// tx validation
bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
{
static uint256 zero;
@@ -155,9 +159,11 @@ bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx
else starti = 1;
if ( assetid == zero )
return eval->Invalid("illegal assetid");
else if ( AssetExactAmounts(cp,inputs,starti,outputs,eval,tx,assetid) == false )
else if ( AssetExactAmounts(2, cp,inputs,starti,outputs,eval,tx,assetid) == false )
return eval->Invalid("asset inputs != outputs");
}
switch ( funcid )
{
case 'c': // create wont be called to be verified as it has no CC inputs
@@ -321,7 +327,7 @@ bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx
}
fprintf(stderr,"fill validated\n");
break;
case 'E': // fillexchange
case 'E': // fillexchange
return eval->Invalid("unexpected assets fillexchange funcid");
break; // disable asset swaps
//vin.0: normal input
@@ -333,7 +339,7 @@ bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx
//vout.3: CC output for asset2 change (if any)
//vout.3/4: normal output for change (if any)
//vout.n-1: opreturn [EVAL_ASSETS] ['E'] [assetid vin0+1] [assetid vin2] [remaining asset2 required] [origpubkey]
if ( AssetExactAmounts(cp,inputs,1,outputs,eval,tx,assetid2) == false )
if ( AssetExactAmounts(1, cp,inputs,1,outputs,eval,tx,assetid2) == false )
eval->Invalid("asset2 inputs != outputs");
if ( (assetoshis= AssetValidateSellvin(cp,eval,totalunits,tmporigpubkey,CCaddr,origaddr,tx,assetid)) == 0 )
return(false);

View File

@@ -150,7 +150,8 @@ int64_t AddAuctionInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPu
std::string AuctionBid(uint64_t txfee,uint256 itemhash,int64_t amount)
{
CMutableTransaction mtx; CPubKey mypk,Auctionpk; CScript opret; int64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,Auctionpk; CScript opret; int64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_AUCTION);
if ( txfee == 0 )
txfee = 10000;
@@ -170,7 +171,8 @@ std::string AuctionBid(uint64_t txfee,uint256 itemhash,int64_t amount)
std::string AuctionDeliver(uint64_t txfee,uint256 itemhash,uint256 bidtxid)
{
CMutableTransaction mtx; CPubKey mypk,Auctionpk; CScript opret; int64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,Auctionpk; CScript opret; int64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_AUCTION);
if ( txfee == 0 )
txfee = 10000;
@@ -190,7 +192,8 @@ std::string AuctionDeliver(uint64_t txfee,uint256 itemhash,uint256 bidtxid)
std::string AuctionPost(uint64_t txfee,uint256 itemhash,int64_t minbid,char *title,char *description)
{
CMutableTransaction mtx; CPubKey mypk,Auctionpk; int64_t funds = 0; CScript opret; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,Auctionpk; int64_t funds = 0; CScript opret; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_AUCTION);
if ( txfee == 0 )
txfee = 10000;

View File

@@ -25,6 +25,7 @@
#include "cc/utils.h"
#include "primitives/transaction.h"
int32_t komodo_nextheight();
std::vector<CC*> BetProtocol::PlayerConditions()
{
@@ -53,7 +54,7 @@ CC* BetProtocol::MakeDisputeCond()
*/
CMutableTransaction BetProtocol::MakeSessionTx(CAmount spendFee)
{
CMutableTransaction mtx;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CC *disputeCond = MakeDisputeCond();
mtx.vout.push_back(CTxOut(spendFee, CCPubKey(disputeCond)));
@@ -70,7 +71,7 @@ CMutableTransaction BetProtocol::MakeSessionTx(CAmount spendFee)
CMutableTransaction BetProtocol::MakeDisputeTx(uint256 signedSessionTxHash, uint256 vmResultHash)
{
CMutableTransaction mtx;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CC *disputeCond = MakeDisputeCond();
mtx.vin.push_back(CTxIn(signedSessionTxHash, 0, CScript()));
@@ -84,7 +85,7 @@ CMutableTransaction BetProtocol::MakeDisputeTx(uint256 signedSessionTxHash, uint
CMutableTransaction BetProtocol::MakePostEvidenceTx(uint256 signedSessionTxHash,
int playerIdx, std::vector<unsigned char> state)
{
CMutableTransaction mtx;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
mtx.vin.push_back(CTxIn(signedSessionTxHash, playerIdx+1, CScript()));
mtx.vout.push_back(CTxOut(0, CScript() << OP_RETURN << state));
@@ -115,7 +116,7 @@ CC* BetProtocol::MakePayoutCond(uint256 signedSessionTxHash)
CMutableTransaction BetProtocol::MakeStakeTx(CAmount totalPayout, uint256 signedSessionTxHash)
{
CMutableTransaction mtx;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CC *payoutCond = MakePayoutCond(signedSessionTxHash);
mtx.vout.push_back(CTxOut(totalPayout, CCPubKey(payoutCond)));
@@ -128,7 +129,7 @@ CMutableTransaction BetProtocol::MakeStakeTx(CAmount totalPayout, uint256 signed
CMutableTransaction BetProtocol::MakeAgreePayoutTx(std::vector<CTxOut> payouts,
uint256 signedStakeTxHash)
{
CMutableTransaction mtx;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
mtx.vin.push_back(CTxIn(signedStakeTxHash, 0, CScript()));
mtx.vout = payouts;
return mtx;
@@ -138,7 +139,7 @@ CMutableTransaction BetProtocol::MakeAgreePayoutTx(std::vector<CTxOut> payouts,
CMutableTransaction BetProtocol::MakeImportPayoutTx(std::vector<CTxOut> payouts,
CTransaction signedDisputeTx, uint256 signedStakeTxHash, MoMProof momProof)
{
CMutableTransaction mtx;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
mtx.vin.push_back(CTxIn(signedStakeTxHash, 0, CScript()));
mtx.vout = payouts;
CScript proofData;

View File

@@ -430,7 +430,8 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C
std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment)
{
CMutableTransaction mtx; uint8_t hash[32],hashdest[32]; uint64_t funds; int32_t i; uint256 hashchain,entropy,hentropy;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
uint8_t hash[32],hashdest[32]; uint64_t funds; int32_t i; uint256 hashchain,entropy,hentropy;
CPubKey mypk; struct CCcontract_info *cp,C;
if ( numpayments <= 0 || payment <= 0 || numpayments > CHANNELS_MAXPAYMENTS )
@@ -464,7 +465,8 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64
std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint256 secret)
{
CMutableTransaction mtx; CPubKey mypk,srcpub,destpub; uint256 txid,hashchain,gensecret,hashblock,entropy,hentropy,prevtxid,param3;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,srcpub,destpub; uint256 txid,hashchain,gensecret,hashblock,entropy,hentropy,prevtxid,param3;
struct CCcontract_info *cp,C; int32_t i,funcid,prevdepth,numvouts,numpayments,totalnumpayments;
int64_t payment,change,funds,param2;
uint8_t hash[32],hashdest[32];
@@ -569,7 +571,8 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2
std::string ChannelClose(uint64_t txfee,uint256 opentxid)
{
CMutableTransaction mtx; CPubKey mypk,srcpub,destpub; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,srcpub,destpub; struct CCcontract_info *cp,C;
CTransaction channelOpenTx;
uint256 hashblock,tmp_txid,prevtxid,hashchain;
int32_t numvouts,numpayments;
@@ -616,7 +619,8 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid)
std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid)
{
CMutableTransaction mtx; CPubKey mypk; struct CCcontract_info *cp,C; int64_t funds,payment,param2;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk; struct CCcontract_info *cp,C; int64_t funds,payment,param2;
int32_t i,numpayments,numvouts,param1;
uint256 hashchain,hashblock,txid,prevtxid,param3,entropy,hentropy,secret;
CTransaction channelOpenTx,channelCloseTx,prevTx;

View File

@@ -98,7 +98,7 @@ What is needed is for the dealer node to track the entropy tx that was already b
#include "../compat/endian.h"
#define MAX_ENTROPYUSED 8192
#define DICE_MINUTXOS 10000
#define DICE_MINUTXOS 15000
extern int32_t KOMODO_INSYNC;
pthread_mutex_t DICE_MUTEX,DICEREVEALED_MUTEX;
@@ -245,9 +245,12 @@ bool mySenddicetransaction(std::string res,uint256 entropyused,int32_t entropyvo
{
RelayTransaction(tx);
fprintf(stderr,"rebroadcast.%c and clear [%d] and broadcast entropyused.%s bettxid.%s -> %s\n",funcid,i,entropyused.GetHex().c_str(),bettxid.GetHex().c_str(),tx.GetHash().GetHex().c_str());
if ( ptr->rawtx.empty() == 0 )
ptr->rawtx.clear();
ptr->txid = zeroid;
if ( ptr != 0 )
{
if ( ptr->rawtx.empty() == 0 )
ptr->rawtx.clear();
ptr->txid = zeroid;
}
//fprintf(stderr,"error adding funcid.%c E.%s bet.%s -> %s to mempool, probably Disable replacement feature size.%d\n",funcid,entropyused.GetHex().c_str(),bettxid.GetHex().c_str(),tx.GetHash().GetHex().c_str(),(int32_t)ptr->rawtx.size());
}
} else fprintf(stderr,"error duplicate entropyused different bettxid\n");
@@ -1332,7 +1335,8 @@ UniValue DiceList()
std::string DiceCreateFunding(uint64_t txfee,char *planstr,int64_t funds,int64_t minbet,int64_t maxbet,int64_t maxodds,int64_t timeoutblocks)
{
CMutableTransaction mtx; uint256 zero; CScript fundingPubKey; CPubKey mypk,dicepk; int64_t a,b,c,d; uint64_t sbits; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
uint256 zero; CScript fundingPubKey; CPubKey mypk,dicepk; int64_t a,b,c,d; uint64_t sbits; struct CCcontract_info *cp,C;
if ( funds < 0 || minbet < 0 || maxbet < 0 || maxodds < 1 || maxodds > 9999 || timeoutblocks < 0 || timeoutblocks > 1440 )
{
CCerror = "invalid parameter error";
@@ -1366,7 +1370,8 @@ std::string DiceCreateFunding(uint64_t txfee,char *planstr,int64_t funds,int64_t
std::string DiceAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t amount)
{
CMutableTransaction mtx; CScript fundingPubKey,scriptPubKey; uint256 entropy,hentropy; CPubKey mypk,dicepk; uint64_t sbits; struct CCcontract_info *cp,C; int64_t minbet,maxbet,maxodds,timeoutblocks;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CScript fundingPubKey,scriptPubKey; uint256 entropy,hentropy; CPubKey mypk,dicepk; uint64_t sbits; struct CCcontract_info *cp,C; int64_t minbet,maxbet,maxodds,timeoutblocks;
if ( amount < 0 )
{
CCerror = "amount must be positive";
@@ -1390,7 +1395,7 @@ std::string DiceAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,int6
}
if ( scriptPubKey == fundingPubKey )
{
if ( AddNormalinputs(mtx,mypk,amount+2*txfee,1) > 0 )
if ( AddNormalinputs2(mtx,amount+2*txfee,60) > 0 )
{
hentropy = DiceHashEntropy(entropy,mtx.vin[0].prevout.hash,mtx.vin[0].prevout.n,1);
mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,dicepk));
@@ -1409,7 +1414,8 @@ std::string DiceAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,int6
std::string DiceBet(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t bet,int32_t odds)
{
CMutableTransaction mtx; CScript fundingPubKey; CPubKey mypk,dicepk; uint64_t sbits,entropyval,entropyval2; int64_t funding,minbet,maxbet,maxodds,timeoutblocks; uint256 entropytxid,entropytxid2,entropy,hentropy; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CScript fundingPubKey; CPubKey mypk,dicepk; uint64_t sbits,entropyval,entropyval2; int64_t funding,minbet,maxbet,maxodds,timeoutblocks; uint256 entropytxid,entropytxid2,entropy,hentropy; struct CCcontract_info *cp,C;
if ( bet < 0 )
{
CCerror = "bet must be positive";
@@ -1467,7 +1473,8 @@ std::string DiceBet(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t bet
std::string DiceBetFinish(uint8_t &funcid,uint256 &entropyused,int32_t &entropyvout,int32_t *resultp,uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettxid,int32_t winlosetimeout,uint256 vin0txid,int32_t vin0vout)
{
CMutableTransaction mtx,savemtx; CScript scriptPubKey,fundingPubKey; CTransaction oldbetTx,betTx,entropyTx; uint256 hentropyproof,entropytxid,hashBlock,bettorentropy,entropy,hentropy,oldbettxid; CPubKey mypk,dicepk,fundingpk; struct CCcontract_info *cp,C; int64_t inputs=0,CCchange=0,odds,fundsneeded,minbet,maxbet,maxodds,timeoutblocks; int32_t oldentropyvout,retval=0,iswin=0; uint64_t entropyval,sbits;
CMutableTransaction savemtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CScript scriptPubKey,fundingPubKey; CTransaction oldbetTx,betTx,entropyTx; uint256 hentropyproof,entropytxid,hashBlock,bettorentropy,entropy,hentropy,oldbettxid; CPubKey mypk,dicepk,fundingpk; struct CCcontract_info *cp,C; int64_t inputs=0,CCchange=0,odds,fundsneeded,minbet,maxbet,maxodds,timeoutblocks; int32_t oldentropyvout,retval=0,iswin=0; uint64_t entropyval,sbits;
entropyused = zeroid;
*resultp = 0;
funcid = 0;
@@ -1501,7 +1508,7 @@ std::string DiceBetFinish(uint8_t &funcid,uint256 &entropyused,int32_t &entropyv
{
if ( vin0txid == zeroid || vin0vout < 0 )
{
if ( AddNormalinputs(mtx,mypk,2*txfee,3) == 0 ) // must be a single vin!!
if ( AddNormalinputs2(mtx,2*txfee,3) == 0 ) // must be a single vin!!
{
CCerror = "no txfee inputs for win/lose";
fprintf(stderr,"%s\n", CCerror.c_str() );
@@ -1648,22 +1655,32 @@ static uint256 dealer0_fundingtxid;
void *dealer0_loop(void *_arg)
{
char *planstr = (char *)_arg;
CTransaction tx; CPubKey mypk,dicepk; uint64_t entropyval; uint256 entropytxid; int32_t entropytxs,i,n,num; CScript fundingPubKey; struct CCcontract_info *cp,C; char coinaddr[64]; std::string res; int64_t minbet,maxbet,maxodds,timeoutblocks; uint64_t refsbits,txfee = 10000;
CTransaction tx,*entropytxs,entropytx; CPubKey mypk,dicepk; uint64_t entropyval; uint256 hashBlock,entropytxid,txid; int32_t height,lastht,numentropytxs,i,n,m,num; CScript fundingPubKey; struct CCcontract_info *cp,C; char coinaddr[64]; std::string res; int64_t minbet,maxbet,maxodds,timeoutblocks; uint64_t refsbits,txfee = 10000;
if ( (cp= Diceinit(fundingPubKey,dealer0_fundingtxid,&C,planstr,txfee,mypk,dicepk,refsbits,minbet,maxbet,maxodds,timeoutblocks)) == 0 )
{
fprintf(stderr,"error initializing dealer0_loop\n");
exit(-1);
}
fprintf(stderr,"dealer0 node running\n");
height = lastht = 0;
entropytxs = (CTransaction *)calloc(sizeof(*entropytxs),DICE_MINUTXOS);
while ( 1 )
{
DicePlanFunds(entropyval,entropytxid,refsbits,cp,dicepk,dealer0_fundingtxid,entropytxs,false);
if ( entropytxs < DICE_MINUTXOS )
while ( KOMODO_INSYNC == 0 || (height= KOMODO_INSYNC) == lastht )
{
n = sqrt(DICE_MINUTXOS - entropytxs) + 10;
for (i=0; i<DICE_MINUTXOS - entropytxs && i<n; i++)
sleep(3);
}
lastht = height;
fprintf(stderr,"New height.%d\n",height);
DicePlanFunds(entropyval,entropytxid,refsbits,cp,dicepk,dealer0_fundingtxid,numentropytxs,false);
if ( numentropytxs < DICE_MINUTXOS )
{
n = sqrt(DICE_MINUTXOS - numentropytxs);
//if ( n > 10 )
// n = 10;
for (i=m=0; i<DICE_MINUTXOS - numentropytxs && i<n; i++)
{
res = DiceAddfunding(txfee,planstr,dealer0_fundingtxid,COIN/100);
res = DiceAddfunding(txfee,planstr,dealer0_fundingtxid,COIN);
if ( res.empty() == 0 && res.size() > 64 && is_hexstr((char *)res.c_str(),0) > 64 )
{
if ( DecodeHexTx(tx,res) != 0 )
@@ -1671,12 +1688,37 @@ void *dealer0_loop(void *_arg)
LOCK(cs_main);
if ( myAddtomempool(tx) != 0 )
{
fprintf(stderr,"ENTROPY %s: %d of %d, %d\n",tx.GetHash().GetHex().c_str(),i,n,DICE_MINUTXOS - entropytxs);
fprintf(stderr,"ENTROPY %s: %d of %d, %d\n",tx.GetHash().GetHex().c_str(),i,n,DICE_MINUTXOS - numentropytxs);
RelayTransaction(tx);
entropytxs[m++] = tx;
} else break;
} else break;
} else break;
}
for (i=0; i<m; i++)
{
tx = entropytxs[i];
txid = tx.GetHash();
fprintf(stderr,"check %d of %d: %s\n",i,m,txid.GetHex().c_str());
while ( 1 )
{
if ( myGetTransaction(txid,entropytx,hashBlock) == 0 || hashBlock == zeroid )
{
LOCK(cs_main);
if ( myAddtomempool(tx) != 0 )
{
fprintf(stderr,"resend ENTROPY %s: %d of %d\n",txid.GetHex().c_str(),i,m);
RelayTransaction(tx);
}
}
else
{
fprintf(stderr,"found %s in %s\n",txid.GetHex().c_str(),hashBlock.GetHex().c_str());
break;
}
sleep(10);
}
}
}
pubkey2addr(coinaddr,Mypubkey().data());
dicefinish_utxosget(num,0,0,coinaddr);

View File

@@ -74,11 +74,11 @@ bool Eval::Dispatch(const CC *cond, const CTransaction &txTo, unsigned int nIn)
switch ( ecode )
{
case EVAL_IMPORTPAYOUT:
//return ImportPayout(vparams, txTo, nIn);
return ImportPayout(vparams, txTo, nIn);
break;
case EVAL_IMPORTCOIN:
//return ImportCoin(vparams, txTo, nIn);
return ImportCoin(vparams, txTo, nIn);
break;
default:
@@ -192,17 +192,6 @@ bool Eval::GetNotarisationData(const uint256 notaryHash, NotarisationData &data)
return true;
}
/*
* Get MoMoM corresponding to a notarisation tx hash (on assetchain)
*/
bool Eval::GetProofRoot(uint256 kmdNotarisationHash, uint256 &momom) const
{
std::pair<uint256,NotarisationData> out;
if (!GetNextBacknotarisation(kmdNotarisationHash, out)) return false;
momom = out.second.MoMoM;
return true;
}
uint32_t Eval::GetAssetchainsCC() const
{

View File

@@ -104,7 +104,6 @@ public:
virtual bool GetBlock(uint256 hash, CBlockIndex& blockIdx) const;
virtual int32_t GetNotaries(uint8_t pubkeys[64][33], int32_t height, uint32_t timestamp) const;
virtual bool GetNotarisationData(uint256 notarisationHash, NotarisationData &data) const;
virtual bool GetProofRoot(uint256 kmdNotarisationHash, uint256 &momom) const;
virtual bool CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t timestamp) const;
virtual uint32_t GetAssetchainsCC() const;
virtual std::string GetAssetchainsSymbol() const;

View File

@@ -174,7 +174,8 @@ int64_t AddFaucetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPub
std::string FaucetGet(uint64_t txfee)
{
CMutableTransaction mtx,tmpmtx; CPubKey mypk,faucetpk; int64_t inputs,CCchange=0,nValue=FAUCETSIZE; struct CCcontract_info *cp,C; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash;
CMutableTransaction tmpmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,faucetpk; int64_t inputs,CCchange=0,nValue=FAUCETSIZE; struct CCcontract_info *cp,C; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash;
cp = CCinit(&C,EVAL_FAUCET);
if ( txfee == 0 )
txfee = 10000;
@@ -214,7 +215,8 @@ std::string FaucetGet(uint64_t txfee)
std::string FaucetFund(uint64_t txfee,int64_t funds)
{
CMutableTransaction mtx; CPubKey mypk,faucetpk; CScript opret; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,faucetpk; CScript opret; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_FAUCET);
if ( txfee == 0 )
txfee = 10000;
@@ -231,7 +233,8 @@ std::string FaucetFund(uint64_t txfee,int64_t funds)
UniValue FaucetInfo()
{
UniValue result(UniValue::VOBJ); char numstr[64];
CMutableTransaction mtx; CPubKey faucetpk; struct CCcontract_info *cp,C; int64_t funding;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey faucetpk; struct CCcontract_info *cp,C; int64_t funding;
result.push_back(Pair("result","success"));
result.push_back(Pair("name","Faucet"));
cp = CCinit(&C,EVAL_FAUCET);

View File

@@ -157,7 +157,8 @@ std::string FSMList()
std::string FSMCreate(uint64_t txfee,std::string name,std::string states)
{
CMutableTransaction mtx; CPubKey mypk,fsmpk; CScript opret; int64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,fsmpk; CScript opret; int64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_FSM);
if ( txfee == 0 )
txfee = 10000;
@@ -177,7 +178,8 @@ std::string FSMCreate(uint64_t txfee,std::string name,std::string states)
std::string FSMInfo(uint256 fsmtxid)
{
CMutableTransaction mtx; CPubKey mypk,fsmpk; int64_t funds = 0; CScript opret; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,fsmpk; int64_t funds = 0; CScript opret; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_FSM);
mypk = pubkey2pk(Mypubkey());
fsmpk = GetUnspendable(cp,0);

View File

@@ -748,7 +748,8 @@ int32_t GatewaysBindExists(struct CCcontract_info *cp,CPubKey gatewayspk,uint256
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)
{
CMutableTransaction mtx; CTransaction oracletx; uint8_t taddr,prefix,prefix2; CPubKey mypk,gatewayspk; CScript opret; uint256 hashBlock; struct CCcontract_info *cp,C; std::string name,description,format; int32_t i,numvouts; int64_t fullsupply; char destaddr[64],coinaddr[64],str[65],*fstr;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction oracletx; uint8_t taddr,prefix,prefix2; CPubKey mypk,gatewayspk; CScript opret; uint256 hashBlock; struct CCcontract_info *cp,C; std::string name,description,format; int32_t i,numvouts; int64_t fullsupply; char destaddr[64],coinaddr[64],str[65],*fstr;
cp = CCinit(&C,EVAL_GATEWAYS);
if ( strcmp((char *)"KMD",coin.c_str()) == 0 )
{
@@ -833,7 +834,8 @@ std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t
std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 cointxid,int32_t claimvout,std::string deposithex,std::vector<uint8_t>proof,CPubKey destpub,int64_t amount)
{
CMutableTransaction mtx; CTransaction bindtx; CPubKey mypk,gatewayspk; uint256 oracletxid,merkleroot,mhash,hashBlock,tokenid,txid;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction 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 str[67],depositaddr[64],txidaddr[64];
@@ -899,7 +901,8 @@ std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::
std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,uint256 deposittxid,CPubKey destpub,int64_t amount)
{
CMutableTransaction mtx; CTransaction tx; CPubKey mypk,gatewayspk,tmpdestpub; struct CCcontract_info *cp,C; uint8_t M,N,taddr,prefix,prefix2;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction tx; CPubKey mypk,gatewayspk,tmpdestpub; struct CCcontract_info *cp,C; uint8_t M,N,taddr,prefix,prefix2;
std::string coin, deposithex; std::vector<CPubKey> msigpubkeys,publishers; int64_t totalsupply,depositamount,tmpamount,inputs,CCchange=0;
int32_t numvouts,claimvout,height; std::vector<uint8_t> proof;
uint256 hashBlock,assetid,oracletxid,tmptxid,cointxid; char str[65],depositaddr[64],coinaddr[64],destaddr[64]; std::vector<uint256> txids;
@@ -962,7 +965,8 @@ std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,ui
std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,CPubKey withdrawpub,int64_t amount)
{
CMutableTransaction mtx; CTransaction tx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction tx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C;
uint256 assetid,hashBlock,oracletxid; int32_t numvouts; int64_t totalsupply,inputs,CCchange=0; uint8_t M,N,taddr,prefix,prefix2; std::string coin;
std::vector<CPubKey> msigpubkeys; char depositaddr[64],str[65],coinaddr[64];
cp = CCinit(&C,EVAL_GATEWAYS);
@@ -1001,7 +1005,8 @@ std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin
std::string GatewaysPartialSign(uint64_t txfee,uint256 txid,std::string refcoin, std::string hex)
{
CMutableTransaction mtx; CPubKey mypk,txidaddrpk,signerpk; struct CCcontract_info *cp,C; CTransaction tx;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,txidaddrpk,signerpk; struct CCcontract_info *cp,C; CTransaction tx;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; char txidaddr[65];
int32_t maxK,K=0; uint256 tmptxid,parttxid,hashBlock;
cp = CCinit(&C,EVAL_GATEWAYS);
@@ -1040,7 +1045,8 @@ std::string GatewaysPartialSign(uint64_t txfee,uint256 txid,std::string refcoin,
std::string GatewaysCompleteSigning(uint64_t txfee,uint256 withdrawtxid,std::string refcoin,std::string hex)
{
CMutableTransaction mtx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C; char txidaddr[65];
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C; char txidaddr[65];
cp = CCinit(&C,EVAL_GATEWAYS);
mypk = pubkey2pk(Mypubkey());
gatewayspk = GetUnspendable(cp,0);
@@ -1054,7 +1060,8 @@ std::string GatewaysCompleteSigning(uint64_t txfee,uint256 withdrawtxid,std::str
std::string GatewaysMarkDone(uint64_t txfee,uint256 completetxid,std::string refcoin)
{
CMutableTransaction mtx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C; char txidaddr[65];
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C; char txidaddr[65];
cp = CCinit(&C,EVAL_GATEWAYS);
mypk = pubkey2pk(Mypubkey());
if ( txfee == 0 )
@@ -1247,7 +1254,8 @@ UniValue GatewaysList()
UniValue GatewaysInfo(uint256 bindtxid)
{
UniValue result(UniValue::VOBJ),a(UniValue::VARR); std::string coin; char str[67],numstr[65],depositaddr[64],gatewaysassets[64]; uint8_t M,N; std::vector<CPubKey> pubkeys; uint8_t taddr,prefix,prefix2; uint256 tokenid,oracletxid,hashBlock; CTransaction tx; CMutableTransaction mtx; CPubKey Gatewayspk; struct CCcontract_info *cp,C; int32_t i; int64_t totalsupply,remaining;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
UniValue result(UniValue::VOBJ),a(UniValue::VARR); std::string coin; char str[67],numstr[65],depositaddr[64],gatewaysassets[64]; uint8_t M,N; std::vector<CPubKey> pubkeys; uint8_t taddr,prefix,prefix2; uint256 tokenid,oracletxid,hashBlock; CTransaction tx; CPubKey Gatewayspk; struct CCcontract_info *cp,C; int32_t i; int64_t totalsupply,remaining;
result.push_back(Pair("result","success"));
result.push_back(Pair("name","Gateways"));
cp = CCinit(&C,EVAL_GATEWAYS);

View File

@@ -143,7 +143,8 @@ int64_t AddHeirInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKe
std::string HeirGet(uint64_t txfee,int64_t nValue)
{
CMutableTransaction mtx,tmpmtx; CPubKey mypk,Heirpk; int64_t inputs,CCchange=0; struct CCcontract_info *cp,C; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash;
CMutableTransaction tmpmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,Heirpk; int64_t inputs,CCchange=0; struct CCcontract_info *cp,C; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash;
cp = CCinit(&C,EVAL_HEIR);
if ( txfee == 0 )
txfee = 10000;
@@ -183,7 +184,8 @@ std::string HeirGet(uint64_t txfee,int64_t nValue)
std::string HeirFund(uint64_t txfee,int64_t funds)
{
CMutableTransaction mtx; CPubKey mypk,Heirpk; CScript opret; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,Heirpk; CScript opret; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_HEIR);
if ( txfee == 0 )
txfee = 10000;
@@ -199,8 +201,9 @@ std::string HeirFund(uint64_t txfee,int64_t funds)
UniValue HeirInfo()
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
UniValue result(UniValue::VOBJ); char numstr[64];
CMutableTransaction mtx; CPubKey Heirpk; struct CCcontract_info *cp,C; int64_t funding;
CPubKey Heirpk; struct CCcontract_info *cp,C; int64_t funding;
result.push_back(Pair("result","success"));
result.push_back(Pair("name","Heir"));
cp = CCinit(&C,EVAL_HEIR);

View File

@@ -16,6 +16,7 @@
#include "cc/eval.h"
#include "cc/utils.h"
#include "importcoin.h"
#include "crosschain.h"
#include "primitives/transaction.h"
@@ -75,12 +76,8 @@ bool Eval::ImportCoin(const std::vector<uint8_t> params, const CTransaction &imp
// Check proof confirms existance of burnTx
{
uint256 momom, target;
if (!GetProofRoot(proof.first, momom))
return Invalid("coudnt-load-momom");
target = proof.second.Exec(burnTx.GetHash());
if (momom != proof.second.Exec(burnTx.GetHash()))
uint256 target = proof.second.Exec(burnTx.GetHash());
if (!CheckMoMoM(proof.first, target))
return Invalid("momom-check-fail");
}

View File

@@ -283,7 +283,8 @@ UniValue LottoList()
std::string LottoCreate(uint64_t txfee,char *planstr,int64_t funding,int32_t ticketsize,int32_t odds,int32_t firstheight,int32_t period)
{
CMutableTransaction mtx; uint256 entropy,hentropy; CPubKey mypk,lottopk; uint64_t sbits; int64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
uint256 entropy,hentropy; CPubKey mypk,lottopk; uint64_t sbits; int64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_LOTTO);
if ( txfee == 0 )
txfee = 10000;
@@ -301,7 +302,8 @@ std::string LottoCreate(uint64_t txfee,char *planstr,int64_t funding,int32_t tic
std::string LottoTicket(uint64_t txfee,uint256 lottoid,int64_t numtickets)
{
CMutableTransaction mtx; CPubKey mypk,lottopk; CScript opret; int64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,lottopk; CScript opret; int64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_LOTTO);
if ( txfee == 0 )
txfee = 10000;
@@ -321,7 +323,8 @@ std::string LottoTicket(uint64_t txfee,uint256 lottoid,int64_t numtickets)
std::string LottoWinner(uint64_t txfee)
{
CMutableTransaction mtx; CPubKey mypk,lottopk; int64_t winnings = 0; CScript opret; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,lottopk; int64_t winnings = 0; CScript opret; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_LOTTO);
if ( txfee == 0 )
txfee = 10000;

View File

@@ -728,7 +728,8 @@ int64_t LifetimeOraclesFunds(struct CCcontract_info *cp,uint256 oracletxid,CPubK
std::string OracleCreate(int64_t txfee,std::string name,std::string description,std::string format)
{
CMutableTransaction mtx; CPubKey mypk,Oraclespk; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,Oraclespk; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_ORACLES);
if ( name.size() > 32 || description.size() > 4096 || format.size() > 4096 )
{
@@ -749,7 +750,8 @@ std::string OracleCreate(int64_t txfee,std::string name,std::string description,
std::string OracleRegister(int64_t txfee,uint256 oracletxid,int64_t datafee)
{
CMutableTransaction mtx; CPubKey mypk,markerpubkey,batonpk; struct CCcontract_info *cp,C; char markeraddr[64],batonaddr[64];
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,markerpubkey,batonpk; struct CCcontract_info *cp,C; char markeraddr[64],batonaddr[64];
cp = CCinit(&C,EVAL_ORACLES);
if ( txfee == 0 )
txfee = 10000;
@@ -772,7 +774,8 @@ std::string OracleRegister(int64_t txfee,uint256 oracletxid,int64_t datafee)
std::string OracleSubscribe(int64_t txfee,uint256 oracletxid,CPubKey publisher,int64_t amount)
{
CMutableTransaction mtx; CPubKey mypk,markerpubkey; struct CCcontract_info *cp,C; char markeraddr[64];
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,markerpubkey; struct CCcontract_info *cp,C; char markeraddr[64];
cp = CCinit(&C,EVAL_ORACLES);
if ( txfee == 0 )
txfee = 10000;
@@ -789,7 +792,8 @@ std::string OracleSubscribe(int64_t txfee,uint256 oracletxid,CPubKey publisher,i
std::string OracleData(int64_t txfee,uint256 oracletxid,std::vector <uint8_t> data)
{
CMutableTransaction mtx; CScript pubKey; CPubKey mypk,batonpk; int64_t datafee,inputs,CCchange = 0; struct CCcontract_info *cp,C; uint256 batontxid; char coinaddr[64],batonaddr[64]; std::vector <uint8_t> prevdata;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CScript pubKey; CPubKey mypk,batonpk; int64_t datafee,inputs,CCchange = 0; struct CCcontract_info *cp,C; uint256 batontxid; char coinaddr[64],batonaddr[64]; std::vector <uint8_t> prevdata;
cp = CCinit(&C,EVAL_ORACLES);
mypk = pubkey2pk(Mypubkey());
if ( data.size() > 8192 )
@@ -879,7 +883,8 @@ UniValue OracleInfo(uint256 origtxid)
{
UniValue result(UniValue::VOBJ),a(UniValue::VARR);
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
CMutableTransaction mtx; 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;
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;
cp = CCinit(&C,EVAL_ORACLES);
CCtxidaddr(markeraddr,origtxid);
if ( GetTransaction(origtxid,tx,hashBlock,false) == 0 )

View File

@@ -144,7 +144,8 @@ int64_t AddPaymentsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CP
std::string PaymentsGet(uint64_t txfee,int64_t nValue)
{
CMutableTransaction mtx,tmpmtx; CPubKey mypk,Paymentspk; int64_t inputs,CCchange=0; struct CCcontract_info *cp,C; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash;
CMutableTransaction tmpmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,Paymentspk; int64_t inputs,CCchange=0; struct CCcontract_info *cp,C; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash;
cp = CCinit(&C,EVAL_PAYMENTS);
if ( txfee == 0 )
txfee = 10000;
@@ -184,7 +185,8 @@ std::string PaymentsGet(uint64_t txfee,int64_t nValue)
std::string PaymentsFund(uint64_t txfee,int64_t funds)
{
CMutableTransaction mtx; CPubKey mypk,Paymentspk; CScript opret; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,Paymentspk; CScript opret; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_PAYMENTS);
if ( txfee == 0 )
txfee = 10000;
@@ -201,7 +203,8 @@ std::string PaymentsFund(uint64_t txfee,int64_t funds)
UniValue PaymentsInfo()
{
UniValue result(UniValue::VOBJ); char numstr[64];
CMutableTransaction mtx; CPubKey Paymentspk; struct CCcontract_info *cp,C; int64_t funding;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey Paymentspk; struct CCcontract_info *cp,C; int64_t funding;
result.push_back(Pair("result","success"));
result.push_back(Pair("name","Payments"));
cp = CCinit(&C,EVAL_PAYMENTS);

View File

@@ -151,7 +151,8 @@ int64_t AddPegsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKe
std::string PegsGet(uint64_t txfee,int64_t nValue)
{
CMutableTransaction mtx,tmpmtx; CPubKey mypk,Pegspk; int64_t inputs,CCchange=0; struct CCcontract_info *cp,C; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash;
CMutableTransaction tmpmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,Pegspk; int64_t inputs,CCchange=0; struct CCcontract_info *cp,C; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash;
cp = CCinit(&C,EVAL_PEGS);
if ( txfee == 0 )
txfee = 10000;
@@ -191,7 +192,8 @@ std::string PegsGet(uint64_t txfee,int64_t nValue)
std::string PegsFund(uint64_t txfee,int64_t funds)
{
CMutableTransaction mtx; CPubKey mypk,Pegspk; CScript opret; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,Pegspk; CScript opret; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_PEGS);
if ( txfee == 0 )
txfee = 10000;
@@ -208,7 +210,8 @@ std::string PegsFund(uint64_t txfee,int64_t funds)
UniValue PegsInfo()
{
UniValue result(UniValue::VOBJ); char numstr[64];
CMutableTransaction mtx; CPubKey Pegspk; struct CCcontract_info *cp,C; int64_t funding;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey Pegspk; struct CCcontract_info *cp,C; int64_t funding;
result.push_back(Pair("result","success"));
result.push_back(Pair("name","Pegs"));
cp = CCinit(&C,EVAL_PEGS);

View File

@@ -182,7 +182,8 @@ UniValue PricesList()
// bettoken
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)
{
CMutableTransaction mtx; CTransaction oracletx; int64_t fullsupply,inputs,CCchange=0; uint256 hashBlock; char str[65],coinaddr[64],houseaddr[64]; CPubKey mypk,pricespk; int32_t i,N,numvouts; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction oracletx; int64_t fullsupply,inputs,CCchange=0; uint256 hashBlock; char str[65],coinaddr[64],houseaddr[64]; CPubKey mypk,pricespk; int32_t i,N,numvouts; struct CCcontract_info *cp,C;
if ( funding < 100*COIN || maxleverage <= 0 || maxleverage > 10000 )
{
CCerror = "invalid parameter error";
@@ -293,7 +294,8 @@ UniValue PricesInfo(uint256 fundingtxid)
std::string PricesAddFunding(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,int64_t amount)
{
CMutableTransaction mtx; struct CCcontract_info *cp,C; CPubKey pricespk,planpk,mypk; uint256 hashBlock,oracletxid,longtoken,shorttoken,bettoken; CTransaction tx; int64_t balance,supply,exposure,inputs,CCchange = 0; uint64_t funding,mode; int32_t margin,maxleverage; char houseaddr[64],myaddr[64]; std::vector<CPubKey>pubkeys;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
struct CCcontract_info *cp,C; CPubKey pricespk,planpk,mypk; uint256 hashBlock,oracletxid,longtoken,shorttoken,bettoken; CTransaction tx; int64_t balance,supply,exposure,inputs,CCchange = 0; uint64_t funding,mode; int32_t margin,maxleverage; char houseaddr[64],myaddr[64]; std::vector<CPubKey>pubkeys;
if ( amount < 10000 )
{
CCerror = "amount must be positive";
@@ -343,7 +345,8 @@ std::string PricesAddFunding(uint64_t txfee,uint256 refbettoken,uint256 fundingt
std::string PricesBet(uint64_t txfee,uint256 refbettoken,uint256 fundingtxid,int64_t amount,int32_t leverage)
{
CMutableTransaction mtx; struct CCcontract_info *cp,C; CPubKey pricespk,planpk,mypk; uint256 hashBlock,oracletxid,longtoken,shorttoken,tokenid,bettoken; CTransaction tx; int64_t balance,supply,exposure,inputs,inputs2,longexposure,netexposure,shortexposure,CCchange = 0,CCchange2 = 0; uint64_t funding,mode; int32_t dir,margin,maxleverage; char houseaddr[64],myaddr[64],exposureaddr[64]; std::vector<CPubKey>pubkeys;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
struct CCcontract_info *cp,C; CPubKey pricespk,planpk,mypk; uint256 hashBlock,oracletxid,longtoken,shorttoken,tokenid,bettoken; CTransaction tx; int64_t balance,supply,exposure,inputs,inputs2,longexposure,netexposure,shortexposure,CCchange = 0,CCchange2 = 0; uint64_t funding,mode; int32_t dir,margin,maxleverage; char houseaddr[64],myaddr[64],exposureaddr[64]; std::vector<CPubKey>pubkeys;
if ( amount < 0 )
{
amount = -amount;

View File

@@ -500,7 +500,8 @@ UniValue RewardsList()
std::string RewardsCreateFunding(uint64_t txfee,char *planstr,int64_t funds,int64_t APR,int64_t minseconds,int64_t maxseconds,int64_t mindeposit)
{
CMutableTransaction mtx; CPubKey mypk,rewardspk; CScript opret; uint64_t sbits,a,b,c,d; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,rewardspk; CScript opret; uint64_t sbits,a,b,c,d; struct CCcontract_info *cp,C;
if ( funds < COIN || mindeposit < 0 || minseconds < 0 || maxseconds < 0 )
{
fprintf(stderr,"negative parameter error\n");
@@ -534,7 +535,8 @@ std::string RewardsCreateFunding(uint64_t txfee,char *planstr,int64_t funds,int6
std::string RewardsAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t amount)
{
CMutableTransaction mtx; CPubKey mypk,rewardspk; CScript opret; uint64_t sbits,a,b,c,d; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,rewardspk; CScript opret; uint64_t sbits,a,b,c,d; struct CCcontract_info *cp,C;
if ( amount < 0 )
{
fprintf(stderr,"negative parameter error\n");
@@ -568,7 +570,8 @@ std::string RewardsAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,i
std::string RewardsLock(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t deposit)
{
CMutableTransaction mtx; CPubKey mypk,rewardspk; CScript opret; uint64_t lockedfunds,sbits,funding,APR,minseconds,maxseconds,mindeposit; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,rewardspk; CScript opret; uint64_t lockedfunds,sbits,funding,APR,minseconds,maxseconds,mindeposit; struct CCcontract_info *cp,C;
if ( deposit < txfee )
{
CCerror = "deposit amount less than txfee";
@@ -611,7 +614,8 @@ std::string RewardsLock(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t
std::string RewardsUnlock(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 locktxid)
{
CMutableTransaction mtx,firstmtx; CTransaction tx; char coinaddr[64]; CPubKey mypk,rewardspk; CScript scriptPubKey,ignore; uint256 hashBlock; uint64_t sbits,APR,minseconds,maxseconds,mindeposit; int64_t funding,reward=0,amount=0,inputs,CCchange=0; struct CCcontract_info *cp,C;
CMutableTransaction firstmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction tx; char coinaddr[64]; CPubKey mypk,rewardspk; CScript scriptPubKey,ignore; uint256 hashBlock; uint64_t sbits,APR,minseconds,maxseconds,mindeposit; int64_t funding,reward=0,amount=0,inputs,CCchange=0; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_REWARDS);
if ( txfee == 0 )
txfee = 10000;

View File

@@ -143,7 +143,8 @@ int64_t AddTriggersInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CP
std::string TriggersGet(uint64_t txfee,int64_t nValue)
{
CMutableTransaction mtx,tmpmtx; CPubKey mypk,Triggerspk; int64_t inputs,CCchange=0; struct CCcontract_info *cp,C; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash;
CMutableTransaction tmpmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,Triggerspk; int64_t inputs,CCchange=0; struct CCcontract_info *cp,C; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash;
cp = CCinit(&C,EVAL_TRIGGERS);
if ( txfee == 0 )
txfee = 10000;
@@ -183,7 +184,8 @@ std::string TriggersGet(uint64_t txfee,int64_t nValue)
std::string TriggersFund(uint64_t txfee,int64_t funds)
{
CMutableTransaction mtx; CPubKey mypk,Triggerspk; CScript opret; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,Triggerspk; CScript opret; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_TRIGGERS);
if ( txfee == 0 )
txfee = 10000;
@@ -200,7 +202,8 @@ std::string TriggersFund(uint64_t txfee,int64_t funds)
UniValue TriggersInfo()
{
UniValue result(UniValue::VOBJ); char numstr[64];
CMutableTransaction mtx; CPubKey Triggerspk; struct CCcontract_info *cp,C; int64_t funding;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey Triggerspk; struct CCcontract_info *cp,C; int64_t funding;
result.push_back(Pair("result","success"));
result.push_back(Pair("name","Triggers"));
cp = CCinit(&C,EVAL_TRIGGERS);

View File

@@ -557,7 +557,7 @@ extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
const CScript &CCoinsViewCache::GetSpendFor(const CCoins *coins, const CTxIn& input)
{
assert(coins);
if (coins->nHeight < 6400 && !strcmp(ASSETCHAINS_SYMBOL, "VRSC"))
/*if (coins->nHeight < 6400 && !strcmp(ASSETCHAINS_SYMBOL, "VRSC"))
{
std::string hc = input.prevout.hash.ToString();
if (LaunchMap().lmap.count(hc))
@@ -568,7 +568,7 @@ const CScript &CCoinsViewCache::GetSpendFor(const CCoins *coins, const CTxIn& in
return txData.scriptPubKey;
}
}
}
}*/
return coins->vout[input.prevout.n].scriptPubKey;
}

View File

@@ -24,7 +24,7 @@
#include <boost/foreach.hpp>
#include <boost/unordered_map.hpp>
#include "zcash/IncrementalMerkleTree.hpp"
#include "veruslaunch.h"
//#include "veruslaunch.h"
/**
* Pruned version of CTransaction: only retains metadata and unspent transaction outputs
@@ -456,7 +456,7 @@ class CTransactionExceptionData
CTransactionExceptionData() : scriptPubKey(), voutMask() {}
};
class CLaunchMap
/*class CLaunchMap
{
public:
std::unordered_map<std::string, CTransactionExceptionData> lmap;
@@ -477,7 +477,7 @@ class CLaunchMap
}
}
};
static CLaunchMap launchMap = CLaunchMap();
static CLaunchMap launchMap = CLaunchMap();*/
/** CCoinsView that adds a memory cache for transactions to another CCoinsView */
class CCoinsViewCache : public CCoinsViewBacked
@@ -507,7 +507,7 @@ public:
~CCoinsViewCache();
// Standard CCoinsView methods
static CLaunchMap &LaunchMap() { return launchMap; }
//static CLaunchMap &LaunchMap() { return launchMap; }
bool GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const;
bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const;
bool GetNullifier(const uint256 &nullifier, ShieldedType type) const;

View File

@@ -69,7 +69,7 @@ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeigh
destNotarisationTxid = nota.first;
else if (seenOwnNotarisations == 2)
goto end;
break;
//break;
}
}
@@ -96,8 +96,9 @@ template <typename IsTarget>
int ScanNotarisationsFromHeight(int nHeight, const IsTarget f, Notarisation &found)
{
int limit = std::min(nHeight + NOTARISATION_SCAN_LIMIT_BLOCKS, chainActive.Height());
for (int h=nHeight; h<limit; h++) {
int start = std::max(nHeight, 1);
for (int h=start; h<limit; h++) {
NotarisationsInBlock notarisations;
if (!GetBlockNotarisations(*chainActive[h]->phashBlock, notarisations))
@@ -125,7 +126,7 @@ TxProof GetCrossChainProof(const uint256 txid, const char* targetSymbol, uint32_
*/
EvalRef eval;
uint256 MoM = assetChainProof.second.Exec(txid);
// Get a kmd height for given notarisation Txid
int kmdHeight;
{
@@ -157,7 +158,7 @@ TxProof GetCrossChainProof(const uint256 txid, const char* targetSymbol, uint32_
uint256 MoMoM = CalculateProofRoot(targetSymbol, targetCCid, kmdHeight, moms, targetChainNotarisationTxid);
if (MoMoM.IsNull())
throw std::runtime_error("No MoMs found");
// Find index of source MoM in MoMoM
int nIndex;
for (nIndex=0; nIndex<moms.size(); nIndex++) {
@@ -246,6 +247,38 @@ bool GetNextBacknotarisation(uint256 kmdNotarisationTxid, Notarisation &out)
}
bool CheckMoMoM(uint256 kmdNotarisationHash, uint256 momom)
{
/*
* Given a notarisation hash and an MoMoM. Backnotarisations may arrive out of order
* or multiple in the same block. So dereference the notarisation hash to the corresponding
* backnotarisation and scan around the kmdheight to see if the MoMoM is a match.
* This is a sledgehammer approach...
*/
Notarisation bn;
if (!GetBackNotarisation(kmdNotarisationHash, bn))
return false;
// Need to get block height of that backnotarisation
EvalRef eval;
CBlockIndex block;
CTransaction tx;
if (!eval->GetTxConfirmed(bn.first, tx, block)){
fprintf(stderr, "Can't get height of backnotarisation, this should not happen\n");
return false;
}
Notarisation nota;
auto checkMoMoM = [&](Notarisation &nota) {
return nota.second.MoMoM == momom;
};
return (bool) ScanNotarisationsFromHeight(block.GetHeight()-100, checkMoMoM, nota);
}
/*
* On assetchain
* in: txid
@@ -278,7 +311,7 @@ TxProof GetAssetchainProof(uint256 hash)
};
if (!ScanNotarisationsFromHeight(blockIndex->GetHeight(), isTarget, nota))
throw std::runtime_error("backnotarisation not yet confirmed");
// index of block in MoM leaves
nIndex = nota.second.height - blockIndex->GetHeight();
}
@@ -292,7 +325,7 @@ TxProof GetAssetchainProof(uint256 hash)
}
bool fMutated;
BuildMerkleTree(&fMutated, leaves, tree);
branch = GetMerkleBranch(nIndex, leaves.size(), tree);
branch = GetMerkleBranch(nIndex, leaves.size(), tree);
// Check branch
uint256 ourResult = SafeCheckMerkleBranch(blockIndex->hashMerkleRoot, branch, nIndex);
@@ -331,7 +364,7 @@ TxProof GetAssetchainProof(uint256 hash)
}
// Check the proof
if (nota.second.MoM != CBlock::CheckMerkleBranch(hash, branch, nIndex))
if (nota.second.MoM != CBlock::CheckMerkleBranch(hash, branch, nIndex))
throw std::runtime_error("Failed validating MoM");
// All done!

View File

@@ -15,7 +15,7 @@ TxProof GetCrossChainProof(const uint256 txid, const char* targetSymbol, uint32_
void CompleteImportTransaction(CTransaction &importTx);
/* On assetchain */
bool GetNextBacknotarisation(uint256 txid, std::pair<uint256,NotarisationData> &bn);
bool CheckMoMoM(uint256 kmdNotarisationHash, uint256 momom);
#endif /* CROSSCHAIN_H */

View File

@@ -1,9 +1,9 @@
#! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.
scriptversion=2012-10-14.11; # UTC
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
# Copyright (C) 1999-2018 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
@@ -17,7 +17,7 @@ scriptversion=2012-10-14.11; # UTC
# 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/>.
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@@ -255,7 +255,8 @@ EOF
echo "compile $scriptversion"
exit $?
;;
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
func_cl_wrapper "$@" # Doesn't return...
;;
esac
@@ -339,9 +340,9 @@ exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

View File

@@ -291,7 +291,7 @@ TEST_F(ContextualCheckBlockTest, BlockOverwinterRulesRejectOtherTx) {
{
SCOPED_TRACE("BlockOverwinterRulesRejectSaplingTx");
ExpectInvalidBlockFromTx(CTransaction(mtx), 100, "bad-overwinter-tx-version-group-id");
ExpectInvalidBlockFromTx(CTransaction(mtx), 0, "bad-overwinter-tx-version-group-id");
}
}
@@ -319,6 +319,6 @@ TEST_F(ContextualCheckBlockTest, BlockSaplingRulesRejectOtherTx) {
{
SCOPED_TRACE("BlockSaplingRulesRejectOverwinterTx");
ExpectInvalidBlockFromTx(CTransaction(mtx), 100, "bad-sapling-tx-version-group-id");
ExpectInvalidBlockFromTx(CTransaction(mtx), 0, "bad-sapling-tx-version-group-id");
}
}

View File

@@ -844,7 +844,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
const CChainParams& chainparams = Params();
// Set this early so that experimental features are correctly enabled/disabled
fExperimentalMode = GetBoolArg("-experimentalfeatures", false);
fExperimentalMode = GetBoolArg("-experimentalfeatures", true);
// Fail early if user has set experimental options without the global flag
if (!fExperimentalMode) {
@@ -1486,7 +1486,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex, dbCompression, dbMaxOpenFiles);
fAddressIndex = GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX);
pblocktree->ReadFlag("addressindex", checkval);
if ( checkval != fAddressIndex )
if ( checkval != fAddressIndex && fAddressIndex != 0 )
{
pblocktree->WriteFlag("addressindex", fAddressIndex);
fprintf(stderr,"set addressindex, will reindex. could take a while.\n");
@@ -1494,7 +1494,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
}
fSpentIndex = GetBoolArg("-spentindex", DEFAULT_SPENTINDEX);
pblocktree->ReadFlag("spentindex", checkval);
if ( checkval != fSpentIndex )
if ( checkval != fSpentIndex && fSpentIndex != 0 )
{
pblocktree->WriteFlag("spentindex", fSpentIndex);
fprintf(stderr,"set spentindex, will reindex. could take a while.\n");

View File

@@ -1062,6 +1062,14 @@ uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256
return(0);
}
int32_t komodo_nextheight()
{
CBlockIndex *pindex; int32_t ht,longest = komodo_longestchain();
if ( (pindex= chainActive.LastTip()) != 0 && (ht= pindex->GetHeight()) >= longest )
return(ht+1);
else return(longest + 1);
}
int32_t komodo_isrealtime(int32_t *kmdheightp)
{
struct komodo_state *sp; CBlockIndex *pindex;
@@ -1763,12 +1771,12 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
{
if ( (is_PoSblock= komodo_is_PoSblock(slowflag,height,pblock,bnTarget,bhash)) == 0 )
{
if ( slowflag == 0 ) // need all past 100 blocks to calculate PoW target
return(0);
if ( ASSETCHAINS_STAKED == 100 && height > 100 ) // only PoS allowed! POSTEST64
return(-1);
else
{
if ( slowflag == 0 ) // need all past 100 blocks to calculate PoW target
return(0);
if ( slowflag != 0 )
bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED);
if ( bhash > bnTarget )
@@ -1788,6 +1796,8 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
fprintf(stderr,"unexpected negative is_PoSblock.%d\n",is_PoSblock);
return(-1);
}
else if ( ASSETCHAINS_STAKED != 0 )
failed = 0;
}
if ( failed == 0 && ASSETCHAINS_COMMISSION != 0 ) //ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 )
{
@@ -1816,12 +1826,28 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
return(-1);
}
}
//fprintf(stderr,"komodo_checkPOW possible.%d slowflag.%d ht.%d notaryid.%d failed.%d\n",possible,slowflag,height,notaryid,failed);
//fprintf(stderr,"komodo_checkPOW possible.%d slowflag.%d ht.%d notaryid.%d failed.%d\n",possible,slowflag,height,notaryid,failed);
if ( failed != 0 && possible == 0 && notaryid < 0 )
return(-1);
else return(0);
}
int32_t komodo_acpublic(uint32_t tiptime)
{
int32_t acpublic = ASSETCHAINS_PUBLIC; CBlockIndex *pindex;
if ( acpublic == 0 )
{
if ( tiptime == 0 )
{
if ( (pindex= chainActive.LastTip()) != 0 )
tiptime = pindex->nTime;
}
if ( (ASSETCHAINS_SYMBOL[0] == 0 || strcmp(ASSETCHAINS_SYMBOL,"ZEX") == 0) && tiptime >= KOMODO_SAPLING_DEADLINE )
acpublic = 1;
}
return(acpublic);
}
int64_t komodo_newcoins(int64_t *zfundsp,int32_t nHeight,CBlock *pblock)
{
CTxDestination address; int32_t i,j,m,n,vout; uint8_t *script; uint256 txid,hashBlock; int64_t zfunds=0,vinsum=0,voutsum=0;

View File

@@ -13,7 +13,7 @@
#define KOMODO_FIRSTFUNGIBLEID 100
#define KOMODO_SAPLING_ACTIVATION 1544832000 // Dec 15th, 2018
#define KOMODO_SAPLING_DEADLINE 1550188800 // Feb 15th, 2019
extern uint8_t ASSETCHAINS_TXPOW,ASSETCHAINS_PUBLIC;
int32_t MAX_BLOCK_SIZE(int32_t height);

View File

@@ -77,7 +77,7 @@ static int64_t nTimeBestReceived = 0;
CWaitableCriticalSection csBestBlock;
CConditionVariable cvBlockChange;
int nScriptCheckThreads = 0;
bool fExperimentalMode = false;
bool fExperimentalMode = true;
bool fImporting = false;
bool fReindex = false;
bool fTxIndex = false;
@@ -1034,9 +1034,12 @@ bool ContextualCheckTransaction(
}
// Reject transactions with non-Sapling version group ID
if (tx.fOverwintered && tx.nVersionGroupId != SAPLING_VERSION_GROUP_ID) {
return state.DoS(dosLevel, error("CheckTransaction(): invalid Sapling tx version"),
REJECT_INVALID, "bad-sapling-tx-version-group-id");
if (tx.fOverwintered && tx.nVersionGroupId != SAPLING_VERSION_GROUP_ID)
{
//return state.DoS(dosLevel, error("CheckTransaction(): invalid Sapling tx version"),REJECT_INVALID, "bad-sapling-tx-version-group-id");
return state.DoS(isInitBlockDownload() ? 0 : dosLevel,
error("CheckTransaction(): invalid Sapling tx version"),
REJECT_INVALID, "bad-sapling-tx-version-group-id");
}
// Reject transactions with invalid version
@@ -1058,9 +1061,12 @@ bool ContextualCheckTransaction(
}
// Reject transactions with non-Overwinter version group ID
if (tx.fOverwintered && tx.nVersionGroupId != OVERWINTER_VERSION_GROUP_ID) {
return state.DoS(dosLevel, error("CheckTransaction(): invalid Overwinter tx version"),
REJECT_INVALID, "bad-overwinter-tx-version-group-id");
if (tx.fOverwintered && tx.nVersionGroupId != OVERWINTER_VERSION_GROUP_ID)
{
//return state.DoS(dosLevel, error("CheckTransaction(): invalid Overwinter tx version"),REJECT_INVALID, "bad-overwinter-tx-version-group-id");
return state.DoS(isInitBlockDownload() ? 0 : dosLevel,
error("CheckTransaction(): invalid Overwinter tx version"),
REJECT_INVALID, "bad-overwinter-tx-version-group-id");
}
// Reject transactions with invalid version
@@ -1253,10 +1259,12 @@ int32_t komodo_isnotaryvout(char *coinaddr) // from ac_private chains only
return(0);
}
int32_t komodo_acpublic(uint32_t tiptime);
bool CheckTransactionWithoutProofVerification(uint32_t tiptime,const CTransaction& tx, CValidationState &state)
{
// Basic checks that don't depend on any context
int32_t invalid_private_taddr=0,z_z=0,z_t=0,t_z=0,acpublic = ASSETCHAINS_PUBLIC;
int32_t invalid_private_taddr=0,z_z=0,z_t=0,t_z=0,acpublic = komodo_acpublic(tiptime);
/**
* Previously:
* 1. The consensus rule below was:
@@ -1359,8 +1367,6 @@ bool CheckTransactionWithoutProofVerification(uint32_t tiptime,const CTransactio
return state.DoS(100, error("CheckTransaction(): tx.valueBalance has no sources or sinks"),
REJECT_INVALID, "bad-txns-valuebalance-nonzero");
}
if ( (ASSETCHAINS_SYMBOL[0] == 0 || strcmp(ASSETCHAINS_SYMBOL,"ZEX") == 0) && tiptime >= KOMODO_SAPLING_DEADLINE )
acpublic = 1;
if ( acpublic != 0 && (tx.vShieldedSpend.empty() == 0 || tx.vShieldedOutput.empty() == 0) )
{
return state.DoS(100, error("CheckTransaction(): this is a public chain, no sapling allowed"),
@@ -1725,7 +1731,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
if (pfMissingInputs)
*pfMissingInputs = true;
//fprintf(stderr,"missing inputs\n");
return state.DoS(0, error("AcceptToMemoryPool: tx inputs not found"),REJECT_INVALID, "bad-txns-inputs-missing");
//return state.DoS(0, error("AcceptToMemoryPool: tx inputs not found"),REJECT_INVALID, "bad-txns-inputs-missing");
return(false);
}
}
@@ -1973,12 +1980,13 @@ bool myAddtomempool(CTransaction &tx, CValidationState *pstate)
pstate = &state;
CTransaction Ltx; bool fMissingInputs,fOverrideFees = false;
if ( mempool.lookup(tx.GetHash(),Ltx) == 0 )
return(AcceptToMemoryPool(mempool, *pstate, tx, false, &fMissingInputs, !fOverrideFees));
return(AcceptToMemoryPool(mempool, *pstate, tx, true, &fMissingInputs, !fOverrideFees));
else return(true);
}
bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock)
{
memset(&hashBlock,0,sizeof(hashBlock));
// need a GetTransaction without lock so the validation code for assets can run without deadlock
{
//fprintf(stderr,"check mempool\n");
@@ -2022,6 +2030,7 @@ bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlo
bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow)
{
CBlockIndex *pindexSlow = NULL;
memset(&hashBlock,0,sizeof(hashBlock));
LOCK(cs_main);
@@ -4678,7 +4687,7 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C
const uint256 &hash = tx.GetHash();
if ( tx.vjoinsplit.size() == 0 ) {
transactionsToRemove.push_back(tx);
tmpmempool.addUnchecked(hash,e,!IsInitialBlockDownload());
tmpmempool.addUnchecked(hash,e,true);
}
}
BOOST_FOREACH(const CTransaction& tx, transactionsToRemove) {
@@ -4756,6 +4765,7 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C
// here we add back all txs from the temp mempool to the main mempool.
// which removes any tx locally that were invalid after the block arrives.
int invalidtxs = 0;
LOCK(mempool.cs);
BOOST_FOREACH(const CTxMemPoolEntry& e, tmpmempool.mapTx) {
CTransaction tx = e.GetTx();
CValidationState state; bool fMissingInputs,fOverrideFees = false;
@@ -5201,11 +5211,11 @@ bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNo
CheckBlockIndex();
if (!ret && futureblock == 0)
{
if ( ASSETCHAINS_SYMBOL[0] == 0 )
/*if ( ASSETCHAINS_SYMBOL[0] == 0 )
{
//fprintf(stderr,"request headers from failed process block peer\n");
pfrom->PushMessage("getheaders", chainActive.GetLocator(chainActive.LastTip()), uint256());
}
}*/
komodo_longestchain();
return error("%s: AcceptBlock FAILED", __func__);
}
@@ -5623,8 +5633,11 @@ bool static LoadBlockIndexDB()
CBlockIndex *pindex;
if ( (pindex= chainActive.LastTip()) != 0 )
{
fprintf(stderr,"set sapling height, if possible from ht.%d %u\n",(int32_t)pindex->GetHeight(),(uint32_t)pindex->nTime);
komodo_activate_sapling(pindex);
if ( ASSETCHAINS_SAPLING <= 0 )
{
fprintf(stderr,"set sapling height, if possible from ht.%d %u\n",(int32_t)pindex->GetHeight(),(uint32_t)pindex->nTime);
komodo_activate_sapling(pindex);
}
}
return true;
}

View File

@@ -463,8 +463,6 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount,
uint64_t txfees,utxovalue; uint32_t txtime; uint256 utxotxid; int32_t i,siglen,numsigs,utxovout; uint8_t utxosig[128],*ptr;
CMutableTransaction txStaked = CreateNewContextualCMutableTransaction(Params().GetConsensus(), stakeHeight);
//if ( blocktime > pindexPrev->GetMedianTimePast()+60 )
// blocktime = pindexPrev->GetMedianTimePast() + 60;
if (ASSETCHAINS_LWMAPOS != 0)
{
uint32_t nBitsPOS;
@@ -479,6 +477,9 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount,
}
else
{
blocktime = GetAdjustedTime();
//if ( blocktime > pindexPrev->GetMedianTimePast()+60 )
// blocktime = pindexPrev->GetMedianTimePast() + 60;
siglen = komodo_staked(txStaked, pblock->nBits, &blocktime, &txtime, &utxotxid, &utxovout, &utxovalue, utxosig);
}
@@ -736,7 +737,7 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight,
}
else
{
if (!isStake)
//if ( !isStake || ASSETCHAINS_STAKED != 0 )
{
if (!reservekey.GetReservedKey(pubkey))
{

View File

@@ -136,7 +136,6 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "z_shieldcoinbase", 3},
{ "z_getoperationstatus", 0},
{ "z_getoperationresult", 0},
{ "z_importkey", 1 },
{ "paxprice", 4 },
{ "paxprices", 3 },
{ "paxpending", 0 },

View File

@@ -606,9 +606,10 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
return BIP22ValidationResult(state);
}
}
if (strMode != "template")
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
else
{
strMode = "template";
}
bool fvNodesEmpty;
{

View File

@@ -56,7 +56,7 @@ extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
uint32_t komodo_segid32(char *coinaddr);
int64_t komodo_coinsupply(int64_t *zfundsp,int32_t height);
int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp);
#define KOMODO_VERSION "0.3.1"
#define KOMODO_VERSION "0.3.0"
#define VERUS_VERSION "0.4.0g"
extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT;
extern uint32_t ASSETCHAINS_CC;

View File

@@ -1274,7 +1274,7 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp)
// push to local node and sync with wallets
CValidationState state;
bool fMissingInputs;
if (!AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, !fOverrideFees)) {
if (!AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs, !fOverrideFees)) {
if (state.IsInvalid()) {
throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
} else {

View File

@@ -33,7 +33,10 @@ extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue&
void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
int32_t komodo_longestchain();
int32_t komodo_dpowconfs(int32_t height,int32_t numconfs);
<<<<<<< HEAD:src/rpcblockchain.old
extern int32_t KOMODO_LONGESTCHAIN;
=======
>>>>>>> master:src/rpcblockchain.cpp
double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty)
{

View File

@@ -1,213 +0,0 @@
#include <zmq.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <cryptoconditions.h>
#include <gtest/gtest.h>
#include "cc/eval.h"
#include "importcoin.h"
#include "base58.h"
#include "core_io.h"
#include "crosschain.h"
#include "key.h"
#include "komodo_structs.h"
#include "main.h"
#include "notarisationdb.h"
#include "primitives/block.h"
#include "primitives/transaction.h"
#include "script/cc.h"
#include "script/interpreter.h"
#include "script/serverchecker.h"
#include "txmempool.h"
#include "crosschain.h"
#include "testutils.h"
extern uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth);
extern bool KOMODO_TEST_ASSETCHAIN_SKIP_POW;
/*
* Tests for the whole process of creating and validating notary proofs
* using proof roots (MoMoMs). This is to support coin imports.
*/
namespace TestCrossChainProof {
class TestCrossChain : public ::testing::Test, public Eval {
public:
bool CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t timestamp) const
{
NotarisationData data(2);
return ParseNotarisationOpReturn(tx, data); // If it parses it's valid
}
protected:
static void SetUpTestCase() { }
virtual void SetUp() {
KOMODO_TEST_ASSETCHAIN_SKIP_POW = 1;
ASSETCHAINS_CC = 1;
EVAL_TEST = this;
}
};
uint256 endianHash(uint256 h)
{
uint256 out;
for (int i=0; i<32; i++) {
out.begin()[31-i] = h.begin()[i];
}
return out;
}
TEST_F(TestCrossChain, testCreateAndValidateImportProof)
{
/*
* This tests the full process of creation of a cross chain proof.
* For the purposes of the test we will use one assetchain and a KMD chain.
*
* In order to do this test, we need 2 blockchains, so we'll fork and make a socket
* for IPC.
*/
int childPid = fork();
void *ctx = zmq_ctx_new();
void *socket = zmq_socket(ctx, ZMQ_PAIR);
if (!childPid)
strcpy(ASSETCHAINS_SYMBOL, "PIZZA");
setupChain();
std::vector<CBlock> blocks;
blocks.resize(1000);
NotarisationData a2kmd(0), kmd2a(1);
int numTestNotarisations = 10;
auto SendIPC = [&] (std::vector<uint8_t> v) {
assert(v.size() == zmq_send(socket, v.data(), v.size(), 0));
};
auto RecvIPC = [&] () {
std::vector<uint8_t> out;
out.resize(100000);
int len = zmq_recv(socket, out.data(), out.size(), 0);
assert(len != -1);
out.resize(len);
return out;
};
auto RecordNotarisation = [&] (CTransaction inputTx, NotarisationData data) {
CMutableTransaction mtx = spendTx(inputTx);
mtx.vout.resize(2);
mtx.vout[0].scriptPubKey << VCH(notaryKey.GetPubKey().begin(), 33) << OP_CHECKSIG;
mtx.vout[1].scriptPubKey << OP_RETURN << E_MARSHAL(ss << data);
mtx.vout[1].nValue = 0;
mtx.vin[0].scriptSig << getSig(mtx, inputTx.vout[0].scriptPubKey);
acceptTxFail(CTransaction(mtx));
return mtx.GetHash();
};
auto RunTestAssetchain = [&] ()
{
NotarisationData n(0), back(1);
strcpy(n.symbol, "PIZZA");
n.ccId = 2;
int height = 0;
/*
* Send notarisations and write backnotarisations
*/
for (int ni=0; ni<numTestNotarisations; ni++)
{
generateBlock(&blocks[++height]);
generateBlock(&blocks[++height]);
n.blockHash = blocks[height].GetHash();
n.MoM = endianHash(komodo_calcMoM(n.height=height, n.MoMDepth=2));
SendIPC(E_MARSHAL(ss << n));
assert(E_UNMARSHAL(RecvIPC(), ss >> back));
RecordNotarisation(blocks[height].vtx[0], back);
}
/*
* Test a proof
*/
uint256 txid = blocks[7].vtx[0].GetHash();
TxProof proof = GetAssetchainProof(txid);
SendIPC(E_MARSHAL(ss << txid; ss << proof));
E_UNMARSHAL(RecvIPC(), ss >> proof);
std::pair<uint256,NotarisationData> bn;
if (!GetNextBacknotarisation(proof.first, bn)) {
printf("GetNextBackNotarisation failed\n");
return 1;
}
if (proof.second.Exec(txid) != bn.second.MoMoM) {
printf("MoMom incorrect\n");
return 1;
}
return 0;
};
auto RunTestKmd = [&] ()
{
NotarisationData n(0);
int height = 0;
/*
* Write notarisations and send backnotarisations
*/
for (int ni=0; ni<numTestNotarisations; ni++)
{
n.IsBackNotarisation = 0;
E_UNMARSHAL(RecvIPC(), ss >> n);
// Grab a coinbase input to fund notarisation
generateBlock(&blocks[++height]);
n.txHash = RecordNotarisation(blocks[height].vtx[0], n);
{
std::vector<uint256> moms;
uint256 destNotarisationTxid;
n.MoMoM = CalculateProofRoot(n.symbol, 2, height, moms, destNotarisationTxid);
}
n.IsBackNotarisation = 1;
SendIPC(E_MARSHAL(ss << n));
}
/*
* Extend proof
*/
TxProof proof;
uint256 txid;
// Extend proof to MoMoM
assert(E_UNMARSHAL(RecvIPC(), ss >> txid; ss >> proof));
proof = GetCrossChainProof(txid, (char*)"PIZZA", 2, proof);
SendIPC(E_MARSHAL(ss << proof));
};
const char endpoint[] = "ipc://tmpKomodoTestCrossChainSock";
if (!childPid) {
assert(0 == zmq_connect(socket, endpoint));
usleep(20000);
int out = RunTestAssetchain();
if (!out) printf("Assetchain success\n");
exit(out);
}
else {
assert(0 == zmq_bind(socket, endpoint));
RunTestKmd();
int returnStatus;
waitpid(childPid, &returnStatus, 0);
unlink("tmpKomodoTestCrossChainSock");
ASSERT_EQ(0, returnStatus);
}
}
} /* namespace TestCrossChainProof */

View File

@@ -670,7 +670,8 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
pindexNew->nCachedBranchId = diskindex.nCachedBranchId;
pindexNew->nTx = diskindex.nTx;
pindexNew->nSproutValue = diskindex.nSproutValue;
pindexNew->nSaplingValue = diskindex.nSaplingValue;
// Consistency checks
auto header = pindexNew->GetBlockHeader();
if (header.GetHash() != pindexNew->GetBlockHash())

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +0,0 @@
// Copyright (c) 2018 The Verus developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef VERUS_LAUNCH_H
#define VERUS_LAUNCH_H
#include <string>
#define WHITELIST_COUNT 704
extern const char *whitelist_ids[WHITELIST_COUNT];
extern const char *whitelist_address;
extern uint64_t whitelist_masks[WHITELIST_COUNT];
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -9,6 +9,7 @@
#include "asyncrpcoperation.h"
#include "paymentdisclosure.h"
#include "primitives/transaction.h"
#include "transaction_builder.h"
#include "wallet.h"
#include "zcash/Address.hpp"
#include "zcash/JoinSplit.hpp"
@@ -24,11 +25,13 @@
using namespace libzcash;
// Input UTXO is a tuple of txid, vout, amount
typedef std::tuple<COutPoint, CAmount> MergeToAddressInputUTXO;
// Input UTXO is a tuple of txid, vout, amount, script
typedef std::tuple<COutPoint, CAmount, CScript> MergeToAddressInputUTXO;
// Input JSOP is a tuple of JSOutpoint, note, amount, spending key
typedef std::tuple<JSOutPoint, SproutNote, CAmount, SpendingKey> MergeToAddressInputNote;
typedef std::tuple<JSOutPoint, SproutNote, CAmount, SproutSpendingKey> MergeToAddressInputSproutNote;
typedef std::tuple<SaplingOutPoint, SaplingNote, CAmount, SaplingExpandedSpendingKey> MergeToAddressInputSaplingNote;
// A recipient is a tuple of address, memo (optional if zaddr)
typedef std::tuple<std::string, std::string> MergeToAddressRecipient;
@@ -53,33 +56,36 @@ class AsyncRPCOperation_mergetoaddress : public AsyncRPCOperation
{
public:
AsyncRPCOperation_mergetoaddress(
CMutableTransaction contextualTx,
std::vector<MergeToAddressInputUTXO> utxoInputs,
std::vector<MergeToAddressInputNote> noteInputs,
MergeToAddressRecipient recipient,
CAmount fee = MERGE_TO_ADDRESS_OPERATION_DEFAULT_MINERS_FEE,
UniValue contextInfo = NullUniValue);
boost::optional<TransactionBuilder> builder,
CMutableTransaction contextualTx,
std::vector<MergeToAddressInputUTXO> utxoInputs,
std::vector<MergeToAddressInputSproutNote> sproutNoteInputs,
std::vector<MergeToAddressInputSaplingNote> saplingNoteInputs,
MergeToAddressRecipient recipient,
CAmount fee = MERGE_TO_ADDRESS_OPERATION_DEFAULT_MINERS_FEE,
UniValue contextInfo = NullUniValue);
virtual ~AsyncRPCOperation_mergetoaddress();
// We don't want to be copied or moved around
AsyncRPCOperation_mergetoaddress(AsyncRPCOperation_mergetoaddress const&) = delete; // Copy construct
AsyncRPCOperation_mergetoaddress(AsyncRPCOperation_mergetoaddress&&) = delete; // Move construct
AsyncRPCOperation_mergetoaddress& operator=(AsyncRPCOperation_mergetoaddress const&) = delete; // Copy assign
AsyncRPCOperation_mergetoaddress& operator=(AsyncRPCOperation_mergetoaddress&&) = delete; // Move assign
virtual void main();
virtual UniValue getStatus() const;
bool testmode = false; // Set to true to disable sending txs and generating proofs
bool paymentDisclosureMode = false; // Set to true to save esk for encrypted notes in payment disclosure database.
bool paymentDisclosureMode = true; // Set to true to save esk for encrypted notes in payment disclosure database.
private:
friend class TEST_FRIEND_AsyncRPCOperation_mergetoaddress; // class for unit testing
UniValue contextinfo_; // optional data to include in return value from getStatus()
bool isUsingBuilder_; // Indicates that no Sprout addresses are involved
uint32_t consensusBranchId_;
CAmount fee_;
int mindepth_;
@@ -88,43 +94,45 @@ private:
bool isToZaddr_;
CTxDestination toTaddr_;
PaymentAddress toPaymentAddress_;
uint256 joinSplitPubKey_;
unsigned char joinSplitPrivKey_[crypto_sign_SECRETKEYBYTES];
// The key is the result string from calling JSOutPoint::ToString()
std::unordered_map<std::string, MergeToAddressWitnessAnchorData> jsopWitnessAnchorMap;
std::vector<MergeToAddressInputUTXO> utxoInputs_;
std::vector<MergeToAddressInputNote> noteInputs_;
std::vector<MergeToAddressInputSproutNote> sproutNoteInputs_;
std::vector<MergeToAddressInputSaplingNote> saplingNoteInputs_;
TransactionBuilder builder_;
CTransaction tx_;
std::array<unsigned char, ZC_MEMO_SIZE> get_memo_from_hex_string(std::string s);
bool main_impl();
// JoinSplit without any input notes to spend
UniValue perform_joinsplit(MergeToAddressJSInfo&);
// JoinSplit with input notes to spend (JSOutPoints))
UniValue perform_joinsplit(MergeToAddressJSInfo&, std::vector<JSOutPoint>&);
// JoinSplit where you have the witnesses and anchor
UniValue perform_joinsplit(
MergeToAddressJSInfo& info,
std::vector<boost::optional<SproutWitness>> witnesses,
uint256 anchor);
MergeToAddressJSInfo& info,
std::vector<boost::optional<SproutWitness>> witnesses,
uint256 anchor);
void sign_send_raw_transaction(UniValue obj); // throws exception if there was an error
void lock_utxos();
void unlock_utxos();
void lock_notes();
void unlock_notes();
// payment disclosure!
std::vector<PaymentDisclosureKeyInfo> paymentDisclosureData_;
};
@@ -135,54 +143,54 @@ class TEST_FRIEND_AsyncRPCOperation_mergetoaddress
{
public:
std::shared_ptr<AsyncRPCOperation_mergetoaddress> delegate;
TEST_FRIEND_AsyncRPCOperation_mergetoaddress(std::shared_ptr<AsyncRPCOperation_mergetoaddress> ptr) : delegate(ptr) {}
CTransaction getTx()
{
return delegate->tx_;
}
void setTx(CTransaction tx)
{
delegate->tx_ = tx;
}
// Delegated methods
std::array<unsigned char, ZC_MEMO_SIZE> get_memo_from_hex_string(std::string s)
{
return delegate->get_memo_from_hex_string(s);
}
bool main_impl()
{
return delegate->main_impl();
}
UniValue perform_joinsplit(MergeToAddressJSInfo& info)
{
return delegate->perform_joinsplit(info);
}
UniValue perform_joinsplit(MergeToAddressJSInfo& info, std::vector<JSOutPoint>& v)
{
return delegate->perform_joinsplit(info, v);
}
UniValue perform_joinsplit(
MergeToAddressJSInfo& info,
std::vector<boost::optional<SproutWitness>> witnesses,
uint256 anchor)
MergeToAddressJSInfo& info,
std::vector<boost::optional<SproutWitness>> witnesses,
uint256 anchor)
{
return delegate->perform_joinsplit(info, witnesses, anchor);
}
void sign_send_raw_transaction(UniValue obj)
{
delegate->sign_send_raw_transaction(obj);
}
void set_state(OperationStatus state)
{
delegate->state_.store(state);

View File

@@ -123,7 +123,7 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
// Enable payment disclosure if requested
paymentDisclosureMode = fExperimentalMode && GetBoolArg("-paymentdisclosure", false);
paymentDisclosureMode = fExperimentalMode && GetBoolArg("-paymentdisclosure", true);
}
AsyncRPCOperation_sendmany::~AsyncRPCOperation_sendmany() {
@@ -1366,7 +1366,8 @@ void AsyncRPCOperation_sendmany::add_taddr_change_output_to_tx(CBitcoinAddress *
}
std::array<unsigned char, ZC_MEMO_SIZE> AsyncRPCOperation_sendmany::get_memo_from_hex_string(std::string s) {
std::array<unsigned char, ZC_MEMO_SIZE> memo = {{0x00}};
// initialize to default memo (no_memo), see section 5.5 of the protocol spec
std::array<unsigned char, ZC_MEMO_SIZE> memo = {{0xF6}};
std::vector<unsigned char> rawMemo = ParseHex(s.c_str());

View File

@@ -75,7 +75,7 @@ public:
bool testmode = false; // Set to true to disable sending txs and generating proofs
bool paymentDisclosureMode = false; // Set to true to save esk for encrypted notes in payment disclosure database.
bool paymentDisclosureMode = true; // Set to true to save esk for encrypted notes in payment disclosure database.
private:
friend class TEST_FRIEND_AsyncRPCOperation_sendmany; // class for unit testing

View File

@@ -93,7 +93,7 @@ AsyncRPCOperation_shieldcoinbase::AsyncRPCOperation_shieldcoinbase(
lock_utxos();
// Enable payment disclosure if requested
paymentDisclosureMode = fExperimentalMode && GetBoolArg("-paymentdisclosure", false);
paymentDisclosureMode = fExperimentalMode && GetBoolArg("-paymentdisclosure", true);
}
AsyncRPCOperation_shieldcoinbase::~AsyncRPCOperation_shieldcoinbase() {

View File

@@ -65,7 +65,7 @@ public:
bool testmode = false; // Set to true to disable sending txs and generating proofs
bool cheatSpend = false; // set when this is shielding a cheating coinbase
bool paymentDisclosureMode = false; // Set to true to save esk for encrypted notes in payment disclosure database.
bool paymentDisclosureMode = true; // Set to true to save esk for encrypted notes in payment disclosure database.
private:
friend class ShieldToAddress;

View File

@@ -42,7 +42,7 @@ UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp)
return NullUniValue;
string enableArg = "paymentdisclosure";
auto fEnablePaymentDisclosure = fExperimentalMode && GetBoolArg("-" + enableArg, false);
auto fEnablePaymentDisclosure = fExperimentalMode && GetBoolArg("-" + enableArg, true);
string strPaymentDisclosureDisabledMsg = "";
if (!fEnablePaymentDisclosure) {
strPaymentDisclosureDisabledMsg = experimentalDisabledHelpMsg("z_getpaymentdisclosure", enableArg);
@@ -149,7 +149,7 @@ UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp)
return NullUniValue;
string enableArg = "paymentdisclosure";
auto fEnablePaymentDisclosure = fExperimentalMode && GetBoolArg("-" + enableArg, false);
auto fEnablePaymentDisclosure = fExperimentalMode && GetBoolArg("-" + enableArg, true);
string strPaymentDisclosureDisabledMsg = "";
if (!fEnablePaymentDisclosure) {
strPaymentDisclosureDisabledMsg = experimentalDisabledHelpMsg("z_validatepaymentdisclosure", enableArg);

View File

@@ -111,7 +111,6 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime()));
entry.push_back(Pair("expiryheight", (int64_t)wtx.nExpiryHeight));
} else entry.push_back(Pair("confirmations", confirms));
uint256 hash = wtx.GetHash();
entry.push_back(Pair("txid", hash.GetHex()));
UniValue conflicts(UniValue::VARR);
@@ -1421,9 +1420,9 @@ UniValue sendmany(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Zcash address: ") + name_);
}
if (destinations.count(dest)) {
/*if (destinations.count(dest)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
}
}*/
destinations.insert(dest);
CScript scriptPubKey = GetScriptForDestination(dest);
@@ -2444,6 +2443,7 @@ UniValue walletlock(const UniValue& params, bool fHelp)
return NullUniValue;
}
int32_t komodo_acpublic(uint32_t tiptime);
UniValue encryptwallet(const UniValue& params, bool fHelp)
{
@@ -2451,7 +2451,8 @@ UniValue encryptwallet(const UniValue& params, bool fHelp)
return NullUniValue;
string enableArg = "developerencryptwallet";
auto fEnableWalletEncryption = fExperimentalMode && GetBoolArg("-" + enableArg, false);
int32_t flag = (komodo_acpublic(0) || ASSETCHAINS_SYMBOL[0] == 0);
auto fEnableWalletEncryption = fExperimentalMode && GetBoolArg("-" + enableArg, flag);
std::string strWalletEncryptionDisabledMsg = "";
if (!fEnableWalletEncryption) {
@@ -2951,8 +2952,8 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
"\nExamples\n"
+ HelpExampleCli("z_listunspent", "")
+ HelpExampleCli("z_listunspent", "6 9999999 false \"[\\\"ztbx5DLDxa5ZLFTchHhoPNkKs57QzSyib6UqXpEdy76T1aUdFxJt1w9318Z8DJ73XzbnWHKEZP9Yjg712N5kMmP4QzS9iC9\\\",\\\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\\\"]\"")
+ HelpExampleRpc("z_listunspent", "6 9999999 false \"[\\\"ztbx5DLDxa5ZLFTchHhoPNkKs57QzSyib6UqXpEdy76T1aUdFxJt1w9318Z8DJ73XzbnWHKEZP9Yjg712N5kMmP4QzS9iC9\\\",\\\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\\\"]\"")
+ HelpExampleCli("z_listunspent", "6 9999999 false \"[\\\"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\\\",\\\"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\\\"]\"")
+ HelpExampleRpc("z_listunspent", "6 9999999 false \"[\\\"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\\\",\\\"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\\\"]\"")
);
RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)(UniValue::VNUM)(UniValue::VBOOL)(UniValue::VARR));
@@ -3788,8 +3789,8 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
" \"change\": true|false, (boolean) true if the address that received the note is also one of the sending addresses\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("z_listreceivedbyaddress", "\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
+ HelpExampleRpc("z_listreceivedbyaddress", "\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
+ HelpExampleCli("z_listreceivedbyaddress", "\"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\"")
+ HelpExampleRpc("z_listreceivedbyaddress", "\"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\"")
);
LOCK2(cs_main, pwalletMain->cs_wallet);
@@ -4121,8 +4122,8 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
"\nResult:\n"
"\"operationid\" (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
"\nExamples:\n"
+ HelpExampleCli("z_sendmany", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" '[{\"address\": \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\" ,\"amount\": 5.0}]'")
+ HelpExampleRpc("z_sendmany", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", [{\"address\": \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\" ,\"amount\": 5.0}]")
+ HelpExampleCli("z_sendmany", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" '[{\"address\": \"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\" ,\"amount\": 5.0}]'")
+ HelpExampleRpc("z_sendmany", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", [{\"address\": \"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\" ,\"amount\": 5.0}]")
);
LOCK2(cs_main, pwalletMain->cs_wallet);
@@ -4212,15 +4213,10 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
}
// If we are sending from a shielded address, all recipient
// shielded addresses must be of the same type.
if (fromSprout && toSapling) {
if ((fromSprout && toSapling) || (fromSapling && toSprout)) {
throw JSONRPCError(
RPC_INVALID_PARAMETER,
"Cannot send from a Sprout address to a Sapling address using z_sendmany");
}
if (fromSapling && toSprout) {
throw JSONRPCError(
RPC_INVALID_PARAMETER,
"Cannot send from a Sapling address to a Sprout address using z_sendmany");
"Cannot send between Sprout and Sapling addresses using z_sendmany");
}
} else {
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ")+address );
@@ -4432,8 +4428,8 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
" \"opid\": xxx (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("z_shieldcoinbase", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
+ HelpExampleRpc("z_shieldcoinbase", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
+ HelpExampleCli("z_shieldcoinbase", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" \"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\"")
+ HelpExampleRpc("z_shieldcoinbase", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", \"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\"")
);
LOCK2(cs_main, pwalletMain->cs_wallet);
@@ -4621,160 +4617,159 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
return o;
}
#define MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT 50
#define MERGE_TO_ADDRESS_DEFAULT_SHIELDED_LIMIT 10
#define MERGE_TO_ADDRESS_DEFAULT_SPROUT_LIMIT 10
#define MERGE_TO_ADDRESS_DEFAULT_SAPLING_LIMIT 90
#define JOINSPLIT_SIZE GetSerializeSize(JSDescription(), SER_NETWORK, PROTOCOL_VERSION)
#define OUTPUTDESCRIPTION_SIZE GetSerializeSize(OutputDescription(), SER_NETWORK, PROTOCOL_VERSION)
#define SPENDDESCRIPTION_SIZE GetSerializeSize(SpendDescription(), SER_NETWORK, PROTOCOL_VERSION)
UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return NullUniValue;
string enableArg = "zmergetoaddress";
auto fEnableMergeToAddress = fExperimentalMode && GetBoolArg("-" + enableArg, false);
auto fEnableMergeToAddress = fExperimentalMode && GetBoolArg("-" + enableArg, true);
std::string strDisabledMsg = "";
if (!fEnableMergeToAddress) {
strDisabledMsg = experimentalDisabledHelpMsg("z_mergetoaddress", enableArg);
}
if (fHelp || params.size() < 2 || params.size() > 6)
throw runtime_error(
"z_mergetoaddress [\"fromaddress\", ... ] \"toaddress\" ( fee ) ( transparent_limit ) ( shielded_limit ) ( memo )\n"
+ strDisabledMsg +
"\nMerge multiple UTXOs and notes into a single UTXO or note. Coinbase UTXOs are ignored; use `z_shieldcoinbase`"
"\nto combine those into a single note."
"\n\nThis is an asynchronous operation, and UTXOs selected for merging will be locked. If there is an error, they"
"\nare unlocked. The RPC call `listlockunspent` can be used to return a list of locked UTXOs."
"\n\nThe number of UTXOs and notes selected for merging can be limited by the caller. If the transparent limit"
"\nparameter is set to zero, and Overwinter is not yet active, the -mempooltxinputlimit option will determine the"
"\nnumber of UTXOs. Any limit is constrained by the consensus rule defining a maximum transaction size of"
+ strprintf("\n%d bytes before Sapling, and %d bytes once Sapling activates.", MAX_TX_SIZE_BEFORE_SAPLING, MAX_TX_SIZE_AFTER_SAPLING)
+ HelpRequiringPassphrase() + "\n"
"\nArguments:\n"
"1. fromaddresses (string, required) A JSON array with addresses.\n"
" The following special strings are accepted inside the array:\n"
" - \"*\": Merge both UTXOs and notes from all addresses belonging to the wallet.\n"
" - \"ANY_TADDR\": Merge UTXOs from all t-addrs belonging to the wallet.\n"
" - \"ANY_ZADDR\": Merge notes from all z-addrs belonging to the wallet.\n"
" If a special string is given, any given addresses of that type will be ignored.\n"
" [\n"
" \"address\" (string) Can be a t-addr or a z-addr\n"
" ,...\n"
" ]\n"
"2. \"toaddress\" (string, required) The t-addr or z-addr to send the funds to.\n"
"3. fee (numeric, optional, default="
+ strprintf("%s", FormatMoney(MERGE_TO_ADDRESS_OPERATION_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
"4. transparent_limit (numeric, optional, default="
+ strprintf("%d", MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT) + ") Limit on the maximum number of UTXOs to merge. Set to 0 to use node option -mempooltxinputlimit (before Overwinter), or as many as will fit in the transaction (after Overwinter).\n"
"4. shielded_limit (numeric, optional, default="
+ strprintf("%d", MERGE_TO_ADDRESS_DEFAULT_SHIELDED_LIMIT) + ") Limit on the maximum number of notes to merge. Set to 0 to merge as many as will fit in the transaction.\n"
"5. \"memo\" (string, optional) Encoded as hex. When toaddress is a z-addr, this will be stored in the memo field of the new note.\n"
"\nResult:\n"
"{\n"
" \"remainingUTXOs\": xxx (numeric) Number of UTXOs still available for merging.\n"
" \"remainingTransparentValue\": xxx (numeric) Value of UTXOs still available for merging.\n"
" \"remainingNotes\": xxx (numeric) Number of notes still available for merging.\n"
" \"remainingShieldedValue\": xxx (numeric) Value of notes still available for merging.\n"
" \"mergingUTXOs\": xxx (numeric) Number of UTXOs being merged.\n"
" \"mergingTransparentValue\": xxx (numeric) Value of UTXOs being merged.\n"
" \"mergingNotes\": xxx (numeric) Number of notes being merged.\n"
" \"mergingShieldedValue\": xxx (numeric) Value of notes being merged.\n"
" \"opid\": xxx (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("z_mergetoaddress", "'[\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"]' ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf")
+ HelpExampleRpc("z_mergetoaddress", "[\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"], \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
);
"z_mergetoaddress [\"fromaddress\", ... ] \"toaddress\" ( fee ) ( transparent_limit ) ( shielded_limit ) ( memo )\n"
+ strDisabledMsg +
"\nMerge multiple UTXOs and notes into a single UTXO or note. Coinbase UTXOs are ignored; use `z_shieldcoinbase`"
"\nto combine those into a single note."
"\n\nThis is an asynchronous operation, and UTXOs selected for merging will be locked. If there is an error, they"
"\nare unlocked. The RPC call `listlockunspent` can be used to return a list of locked UTXOs."
"\n\nThe number of UTXOs and notes selected for merging can be limited by the caller. If the transparent limit"
"\nparameter is set to zero, and Overwinter is not yet active, the -mempooltxinputlimit option will determine the"
"\nnumber of UTXOs. Any limit is constrained by the consensus rule defining a maximum transaction size of"
+ strprintf("\n%d bytes before Sapling, and %d bytes once Sapling activates.", MAX_TX_SIZE_BEFORE_SAPLING, MAX_TX_SIZE_AFTER_SAPLING)
+ HelpRequiringPassphrase() + "\n"
"\nArguments:\n"
"1. fromaddresses (string, required) A JSON array with addresses.\n"
" The following special strings are accepted inside the array:\n"
" - \"ANY_TADDR\": Merge UTXOs from any t-addrs belonging to the wallet.\n"
" - \"ANY_SPROUT\": Merge notes from any Sprout z-addrs belonging to the wallet.\n"
" - \"ANY_SAPLING\": Merge notes from any Sapling z-addrs belonging to the wallet.\n"
" If a special string is given, any given addresses of that type will be ignored.\n"
" [\n"
" \"address\" (string) Can be a t-addr or a z-addr\n"
" ,...\n"
" ]\n"
"2. \"toaddress\" (string, required) The t-addr or z-addr to send the funds to.\n"
"3. fee (numeric, optional, default="
+ strprintf("%s", FormatMoney(MERGE_TO_ADDRESS_OPERATION_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
"4. transparent_limit (numeric, optional, default="
+ strprintf("%d", MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT) + ") Limit on the maximum number of UTXOs to merge. Set to 0 to use node option -mempooltxinputlimit (before Overwinter), or as many as will fit in the transaction (after Overwinter).\n"
"4. shielded_limit (numeric, optional, default="
+ strprintf("%d Sprout or %d Sapling Notes", MERGE_TO_ADDRESS_DEFAULT_SPROUT_LIMIT, MERGE_TO_ADDRESS_DEFAULT_SAPLING_LIMIT) + ") Limit on the maximum number of notes to merge. Set to 0 to merge as many as will fit in the transaction.\n"
"5. \"memo\" (string, optional) Encoded as hex. When toaddress is a z-addr, this will be stored in the memo field of the new note.\n"
"\nResult:\n"
"{\n"
" \"remainingUTXOs\": xxx (numeric) Number of UTXOs still available for merging.\n"
" \"remainingTransparentValue\": xxx (numeric) Value of UTXOs still available for merging.\n"
" \"remainingNotes\": xxx (numeric) Number of notes still available for merging.\n"
" \"remainingShieldedValue\": xxx (numeric) Value of notes still available for merging.\n"
" \"mergingUTXOs\": xxx (numeric) Number of UTXOs being merged.\n"
" \"mergingTransparentValue\": xxx (numeric) Value of UTXOs being merged.\n"
" \"mergingNotes\": xxx (numeric) Number of notes being merged.\n"
" \"mergingShieldedValue\": xxx (numeric) Value of notes being merged.\n"
" \"opid\": xxx (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("z_mergetoaddress", "'[\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"]' ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf")
+ HelpExampleRpc("z_mergetoaddress", "[\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"], \"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\"")
);
if (!fEnableMergeToAddress) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error: z_mergetoaddress is disabled.");
}
LOCK2(cs_main, pwalletMain->cs_wallet);
bool useAny = false;
bool useAnyUTXO = false;
bool useAnyNote = false;
bool useAnySprout = false;
bool useAnySapling = false;
std::set<CTxDestination> taddrs = {};
std::set<libzcash::PaymentAddress> zaddrs = {};
uint32_t branchId = CurrentEpochBranchId(chainActive.Height(), Params().GetConsensus());
UniValue addresses = params[0].get_array();
if (addresses.size()==0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, fromaddresses array is empty.");
// Keep track of addresses to spot duplicates
std::set<std::string> setAddress;
// Sources
bool containsSaplingZaddrSource = false;
for (const UniValue& o : addresses.getValues()) {
if (!o.isStr())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected string");
std::string address = o.get_str();
if (address == "*") {
useAny = true;
} else if (address == "ANY_TADDR") {
if (address == "ANY_TADDR") {
useAnyUTXO = true;
} else if (address == "ANY_ZADDR") {
useAnyNote = true;
} else if (address == "ANY_SPROUT") {
useAnySprout = true;
} else if (address == "ANY_SAPLING") {
useAnySapling = true;
} else {
CTxDestination taddr = DecodeDestination(address);
if (IsValidDestination(taddr)) {
// Ignore any listed t-addrs if we are using all of them
if (!(useAny || useAnyUTXO)) {
taddrs.insert(taddr);
}
taddrs.insert(taddr);
} else {
auto zaddr = DecodePaymentAddress(address);
if (IsValidPaymentAddress(zaddr, branchId)) {
// Ignore listed z-addrs if we are using all of them
if (!(useAny || useAnyNote)) {
zaddrs.insert(zaddr);
}
// Check if z-addr is Sapling
bool isSapling = boost::get<libzcash::SaplingPaymentAddress>(&zaddr) != nullptr;
containsSaplingZaddrSource |= isSapling;
if (IsValidPaymentAddress(zaddr)) {
zaddrs.insert(zaddr);
} else {
throw JSONRPCError(
RPC_INVALID_PARAMETER,
string("Invalid parameter, unknown address format: ") + address);
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Unknown address format: ") + address);
}
}
}
if (setAddress.count(address))
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ") + address);
setAddress.insert(address);
}
if (useAnyUTXO && taddrs.size() > 0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify specific t-addrs when using \"ANY_TADDR\"");
}
if ((useAnySprout || useAnySapling) && zaddrs.size() > 0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify specific z-addrs when using \"ANY_SPROUT\" or \"ANY_SAPLING\"");
}
const int nextBlockHeight = chainActive.Height() + 1;
const bool overwinterActive = NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER);
const bool saplingActive = NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING);
// Validate the destination address
auto destaddress = params[1].get_str();
bool isToZaddr = false;
bool isToSproutZaddr = false;
bool isToSaplingZaddr = false;
CTxDestination taddr = DecodeDestination(destaddress);
if (!IsValidDestination(taddr)) {
if (IsValidPaymentAddressString(destaddress, branchId)) {
isToZaddr = true;
// Is this a Sapling address?
auto res = DecodePaymentAddress(destaddress);
if (IsValidPaymentAddress(res)) {
isToSaplingZaddr = boost::get<libzcash::SaplingPaymentAddress>(&res) != nullptr;
auto decodeAddr = DecodePaymentAddress(destaddress);
if (IsValidPaymentAddress(decodeAddr)) {
if (boost::get<libzcash::SaplingPaymentAddress>(&decodeAddr) != nullptr) {
isToSaplingZaddr = true;
// If Sapling is not active, do not allow sending to a sapling addresses.
if (!saplingActive) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated");
}
} else {
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
isToSproutZaddr = true;
}
} else {
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
}
}
else if ( ASSETCHAINS_PRIVATE != 0 )
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain");
// Convert fee from currency format to zatoshis
CAmount nFee = SHIELD_COINBASE_DEFAULT_MINERS_FEE;
if (params.size() > 2) {
@@ -4784,7 +4779,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
nFee = AmountFromValue( params[2] );
}
}
int nUTXOLimit = MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT;
if (params.size() > 3) {
nUTXOLimit = params[3].get_int();
@@ -4792,19 +4787,22 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of UTXOs cannot be negative");
}
}
int nNoteLimit = MERGE_TO_ADDRESS_DEFAULT_SHIELDED_LIMIT;
int sproutNoteLimit = MERGE_TO_ADDRESS_DEFAULT_SPROUT_LIMIT;
int saplingNoteLimit = MERGE_TO_ADDRESS_DEFAULT_SAPLING_LIMIT;
if (params.size() > 4) {
nNoteLimit = params[4].get_int();
int nNoteLimit = params[4].get_int();
if (nNoteLimit < 0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of notes cannot be negative");
}
sproutNoteLimit = nNoteLimit;
saplingNoteLimit = nNoteLimit;
}
std::string memo;
if (params.size() > 5) {
memo = params[5].get_str();
if (!isToZaddr) {
if (!(isToSproutZaddr || isToSaplingZaddr)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Memo can not be used with a taddr. It can only be used with a zaddr.");
} else if (!IsHex(memo)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected memo data in hexadecimal format.");
@@ -4813,75 +4811,56 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, size of memo is larger than maximum allowed %d", ZC_MEMO_SIZE ));
}
}
MergeToAddressRecipient recipient(destaddress, memo);
int nextBlockHeight = chainActive.Height() + 1;
bool overwinterActive = NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER);
unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING;
if (!NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) {
max_tx_size = MAX_TX_SIZE_BEFORE_SAPLING;
}
// This RPC does not support Sapling yet.
if (isToSaplingZaddr || containsSaplingZaddrSource) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling is not supported yet by z_mergetoadress");
}
// If this RPC does support Sapling...
// If Sapling is not active, do not allow sending from or sending to Sapling addresses.
if (!NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) {
if (isToSaplingZaddr || containsSaplingZaddrSource) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated");
}
}
// Prepare to get UTXOs and notes
std::vector<MergeToAddressInputUTXO> utxoInputs;
std::vector<MergeToAddressInputNote> noteInputs;
std::vector<MergeToAddressInputSproutNote> sproutNoteInputs;
std::vector<MergeToAddressInputSaplingNote> saplingNoteInputs;
CAmount mergedUTXOValue = 0;
CAmount mergedNoteValue = 0;
CAmount remainingUTXOValue = 0;
CAmount remainingNoteValue = 0;
#ifdef __LP64__
uint64_t utxoCounter = 0;
uint64_t noteCounter = 0;
#else
size_t utxoCounter = 0;
size_t noteCounter = 0;
#endif
bool maxedOutUTXOsFlag = false;
bool maxedOutNotesFlag = false;
size_t mempoolLimit = (nUTXOLimit != 0) ? nUTXOLimit : (overwinterActive ? 0 : (size_t)GetArg("-mempooltxinputlimit", 0));
unsigned int max_tx_size = saplingActive ? MAX_TX_SIZE_AFTER_SAPLING : MAX_TX_SIZE_BEFORE_SAPLING;
size_t estimatedTxSize = 200; // tx overhead + wiggle room
if (isToZaddr) {
if (isToSproutZaddr) {
estimatedTxSize += JOINSPLIT_SIZE;
} else if (isToSaplingZaddr) {
estimatedTxSize += OUTPUTDESCRIPTION_SIZE;
}
if (useAny || useAnyUTXO || taddrs.size() > 0) {
if (useAnyUTXO || taddrs.size() > 0) {
// Get available utxos
vector<COutput> vecOutputs;
pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, false);
// Find unspent utxos and update estimated size
for (const COutput& out : vecOutputs) {
if (!out.fSpendable) {
continue;
}
CScript scriptPubKey = out.tx->vout[out.i].scriptPubKey;
CTxDestination address;
if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
if (!ExtractDestination(scriptPubKey, address)) {
continue;
}
// If taddr is not wildcard "*", filter utxos
if (taddrs.size() > 0 && !taddrs.count(address)) {
continue;
}
utxoCounter++;
CAmount nValue = out.tx->vout[out.i].nValue;
if (!maxedOutUTXOsFlag) {
size_t increase = (boost::get<CScriptID>(&address) != nullptr) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE;
if (estimatedTxSize + increase >= max_tx_size ||
@@ -4891,34 +4870,51 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
} else {
estimatedTxSize += increase;
COutPoint utxo(out.tx->GetHash(), out.i);
utxoInputs.emplace_back(utxo, nValue);
utxoInputs.emplace_back(utxo, nValue, scriptPubKey);
mergedUTXOValue += nValue;
}
}
if (maxedOutUTXOsFlag) {
remainingUTXOValue += nValue;
}
}
}
if (useAny || useAnyNote || zaddrs.size() > 0) {
if (useAnySprout || useAnySapling || zaddrs.size() > 0) {
// Get available notes
std::vector<CSproutNotePlaintextEntry> sproutEntries;
std::vector<SaplingNoteEntry> saplingEntries;
pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs);
// If Sapling is not active, do not allow sending from a sapling addresses.
if (!saplingActive && saplingEntries.size() > 0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated");
}
// Sending from both Sprout and Sapling is currently unsupported using z_mergetoaddress
if (sproutEntries.size() > 0 && saplingEntries.size() > 0) {
throw JSONRPCError(
RPC_INVALID_PARAMETER,
"Cannot send from both Sprout and Sapling addresses using z_mergetoaddress");
}
// If sending between shielded addresses, they must be the same type
if ((saplingEntries.size() > 0 && isToSproutZaddr) || (sproutEntries.size() > 0 && isToSaplingZaddr)) {
throw JSONRPCError(
RPC_INVALID_PARAMETER,
"Cannot send between Sprout and Sapling addresses using z_mergetoaddress");
}
// Find unspent notes and update estimated size
for (CSproutNotePlaintextEntry& entry : sproutEntries) {
for (const CSproutNotePlaintextEntry& entry : sproutEntries) {
noteCounter++;
CAmount nValue = entry.plaintext.value();
if (!maxedOutNotesFlag) {
// If we haven't added any notes yet and the merge is to a
// z-address, we have already accounted for the first JoinSplit.
size_t increase = (noteInputs.empty() && !isToZaddr) || (noteInputs.size() % 2 == 0) ? JOINSPLIT_SIZE : 0;
size_t increase = (sproutNoteInputs.empty() && !isToSproutZaddr) || (sproutNoteInputs.size() % 2 == 0) ? JOINSPLIT_SIZE : 0;
if (estimatedTxSize + increase >= max_tx_size ||
(nNoteLimit > 0 && noteCounter > nNoteLimit))
(sproutNoteLimit > 0 && noteCounter > sproutNoteLimit))
{
maxedOutNotesFlag = true;
} else {
@@ -4926,31 +4922,49 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
auto zaddr = entry.address;
SproutSpendingKey zkey;
pwalletMain->GetSproutSpendingKey(zaddr, zkey);
noteInputs.emplace_back(entry.jsop, entry.plaintext.note(zaddr), nValue, zkey);
sproutNoteInputs.emplace_back(entry.jsop, entry.plaintext.note(zaddr), nValue, zkey);
mergedNoteValue += nValue;
}
}
if (maxedOutNotesFlag) {
remainingNoteValue += nValue;
}
}
for (const SaplingNoteEntry& entry : saplingEntries) {
noteCounter++;
CAmount nValue = entry.note.value();
if (!maxedOutNotesFlag) {
size_t increase = SPENDDESCRIPTION_SIZE;
if (estimatedTxSize + increase >= max_tx_size ||
(saplingNoteLimit > 0 && noteCounter > saplingNoteLimit))
{
maxedOutNotesFlag = true;
} else {
estimatedTxSize += increase;
libzcash::SaplingExtendedSpendingKey extsk;
if (!pwalletMain->GetSaplingExtendedSpendingKey(entry.address, extsk)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Could not find spending key for payment address.");
}
saplingNoteInputs.emplace_back(entry.op, entry.note, nValue, extsk.expsk);
mergedNoteValue += nValue;
}
}
if (maxedOutNotesFlag) {
remainingNoteValue += nValue;
}
}
// TODO: Add Sapling support
}
#ifdef __LP64__
uint64_t numUtxos = utxoInputs.size(); //ca333
uint64_t numNotes = noteInputs.size();
#else
size_t numUtxos = utxoInputs.size();
size_t numNotes = noteInputs.size();
#endif
size_t numNotes = sproutNoteInputs.size() + saplingNoteInputs.size();
if (numUtxos == 0 && numNotes == 0) {
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Could not find any funds to merge.");
}
// Sanity check: Don't do anything if:
// - We only have one from address
// - It's equal to toaddress
@@ -4958,42 +4972,47 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
if (setAddress.size() == 1 && setAddress.count(destaddress) && (numUtxos + numNotes) == 1) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Destination address is also the only source address, and all its funds are already merged.");
}
CAmount mergedValue = mergedUTXOValue + mergedNoteValue;
if (mergedValue < nFee) {
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS,
strprintf("Insufficient funds, have %s, which is less than miners fee %s",
FormatMoney(mergedValue), FormatMoney(nFee)));
strprintf("Insufficient funds, have %s, which is less than miners fee %s",
FormatMoney(mergedValue), FormatMoney(nFee)));
}
// Check that the user specified fee is sane (if too high, it can result in error -25 absurd fee)
CAmount netAmount = mergedValue - nFee;
if (nFee > netAmount) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the net amount to be shielded %s", FormatMoney(nFee), FormatMoney(netAmount)));
}
// Keep record of parameters in context object
UniValue contextInfo(UniValue::VOBJ);
contextInfo.push_back(Pair("fromaddresses", params[0]));
contextInfo.push_back(Pair("toaddress", params[1]));
contextInfo.push_back(Pair("fee", ValueFromAmount(nFee)));
// Contextual transaction we will build on
CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(
Params().GetConsensus(),
nextBlockHeight);
bool isShielded = numNotes > 0 || isToZaddr;
if (contextualTx.nVersion == 1 && isShielded) {
Params().GetConsensus(),
nextBlockHeight);
bool isSproutShielded = sproutNoteInputs.size() > 0 || isToSproutZaddr;
if (contextualTx.nVersion == 1 && isSproutShielded) {
contextualTx.nVersion = 2; // Tx format should support vjoinsplit
}
// Builder (used if Sapling addresses are involved)
boost::optional<TransactionBuilder> builder;
if (isToSaplingZaddr || saplingNoteInputs.size() > 0) {
builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, pwalletMain);
}
// Create operation and add to global queue
std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
std::shared_ptr<AsyncRPCOperation> operation(
new AsyncRPCOperation_mergetoaddress(contextualTx, utxoInputs, noteInputs, recipient, nFee, contextInfo) );
new AsyncRPCOperation_mergetoaddress(builder, contextualTx, utxoInputs, sproutNoteInputs, saplingNoteInputs, recipient, nFee, contextInfo) );
q->addOperation(operation);
AsyncRPCOperationId operationId = operation->getId();
// Return continuation information
UniValue o(UniValue::VOBJ);
o.push_back(Pair("remainingUTXOs", static_cast<uint64_t>(utxoCounter - numUtxos)));
@@ -5161,8 +5180,10 @@ struct komodo_staking *komodo_addutxo(struct komodo_staking *array,int32_t *numk
{
*maxkp += 1000;
array = (struct komodo_staking *)realloc(array,sizeof(*array) * (*maxkp));
//fprintf(stderr,"realloc max.%d array.%p\n",*maxkp,array);
}
kp = &array[(*numkp)++];
//fprintf(stderr,"kp.%p num.%d\n",kp,*numkp);
memset(kp,0,sizeof(*kp));
strcpy(kp->address,address);
kp->txid = txid;
@@ -5185,15 +5206,11 @@ arith_uint256 _komodo_eligible(struct komodo_staking *kp,arith_uint256 ratio,uin
diff = 3600*24*30;
if ( iter > 0 )
diff += segid*2;
coinage = ((uint64_t)kp->nValue/COIN * diff);
coinage = ((uint64_t)kp->nValue * diff);
if ( blocktime+iter+segid*2 > prevtime+480 )
coinage *= ((blocktime+iter+segid*2) - (prevtime+400));
//if ( nHeight >= 2500 && blocktime+iter+segid*2 > prevtime+180 )
// coinage *= ((blocktime+iter+segid*2) - (prevtime+60));
coinage256 = arith_uint256(coinage+1);
hashval = ratio * (kp->hashval / coinage256);
//if ( nHeight >= 900 && nHeight < 916 )
// hashval = (hashval / coinage256);
return(hashval);
}
@@ -5223,7 +5240,7 @@ uint32_t komodo_eligible(arith_uint256 bnTarget,arith_uint256 ratio,struct komod
return(blocktime);
}
}
}
} else fprintf(stderr,"maxiters is not good enough\n");
return(0);
}
@@ -5250,10 +5267,10 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
if ( (minage= nHeight*3) > 6000 ) // about 100 blocks
minage = 6000;
komodo_segids(hashbuf,nHeight-101,100);
if ( *blocktimep > tipindex->nTime+60 )
if ( *blocktimep < tipindex->nTime+60 )
*blocktimep = tipindex->nTime+60;
//fprintf(stderr,"Start scan of utxo for staking %u ht.%d\n",(uint32_t)time(NULL),nHeight);
if ( time(NULL) > lasttime+600 )
if ( time(NULL) > lasttime+600 || array == 0 )
{
if ( array != 0 )
{
@@ -5272,7 +5289,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
counter++;
if ( out.nDepth < nMinDepth || out.nDepth > nMaxDepth )
{
//fprintf(stderr,"komodo_staked invalid depth %d\n",(int32_t)out.nDepth);
fprintf(stderr,"komodo_staked invalid depth %d\n",(int32_t)out.nDepth);
continue;
}
CAmount nValue = out.tx->vout[out.i].nValue;
@@ -5286,12 +5303,14 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
if ( GetTransaction(out.tx->GetHash(),tx,hashBlock,true) != 0 && (pindex= komodo_getblockindex(hashBlock)) != 0 )
{
array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,out.tx->GetHash(),out.i,(char *)CBitcoinAddress(address).ToString().c_str(),hashbuf,(CScript)pk);
//fprintf(stderr,"addutxo numkp.%d vs max.%d\n",numkp,maxkp);
}
}
}
lasttime = (uint32_t)time(NULL);
//fprintf(stderr,"finished kp data of utxo for staking %u ht.%d numkp.%d maxkp.%d\n",(uint32_t)time(NULL),nHeight,numkp,maxkp);
//fprintf(stderr,"finished kp data of utxo for staking %u ht.%d numkp.%d maxkp.%d\n",(uint32_t)time(NULL),nHeight,numkp,maxkp);
}
//fprintf(stderr,"numkp.%d blocktime.%u\n",numkp,*blocktimep);
block_from_future_rejecttime = (uint32_t)GetAdjustedTime() + 57;
for (i=winners=0; i<numkp; i++)
{
@@ -5304,7 +5323,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
if ( (eligible2= komodo_eligible(bnTarget,ratio,kp,nHeight,*blocktimep,(uint32_t)tipindex->nTime+27,minage,hashbuf)) == 0 )
continue;
eligible = komodo_stake(0,bnTarget,nHeight,kp->txid,kp->vout,0,(uint32_t)tipindex->nTime+27,kp->address);
//fprintf(stderr,"i.%d %u vs %u\n",i,eligible2,eligible);
//fprintf(stderr,"i.%d %u vs %u\n",i,eligible2,eligible);
if ( eligible > 0 )
{
besttime = m = 0;
@@ -5317,7 +5336,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
if ( eligible < block_from_future_rejecttime ) // nothing gained by going earlier
break;
m++;
//fprintf(stderr,"m.%d ht.%d validated winning blocktime %u -> %.8f eligible.%u test prior\n",m,nHeight,*blocktimep,(double)kp->nValue/COIN,eligible);
//fprintf(stderr,"m.%d ht.%d validated winning blocktime %u -> %.8f eligible.%u test prior\n",m,nHeight,*blocktimep,(double)kp->nValue/COIN,eligible);
}
}
else
@@ -5327,7 +5346,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
}
eligible = besttime;
winners++;
//fprintf(stderr,"ht.%d validated winning [%d] -> %.8f eligible.%u test prior\n",nHeight,(int32_t)(eligible - tipindex->nTime),(double)kp->nValue/COIN,eligible);
//fprintf(stderr,"ht.%d validated winning [%d] -> %.8f eligible.%u test prior\n",nHeight,(int32_t)(eligible - tipindex->nTime),(double)kp->nValue/COIN,eligible);
if ( earliest == 0 || eligible < earliest || (eligible == earliest && (*utxovaluep == 0 || kp->nValue < *utxovaluep)) )
{
earliest = eligible;
@@ -5340,7 +5359,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
fprintf(stderr,"ht.%d earliest.%u [%d].%d (%s) nValue %.8f locktime.%u counter.%d winners.%d\n",nHeight,earliest,(int32_t)(earliest - tipindex->nTime),m,kp->address,(double)kp->nValue/COIN,*txtimep,counter,winners);
}
} //else fprintf(stderr,"utxo not eligible\n");
} //else fprintf(stderr,"no tipindex\n");
}
if ( numkp < 10000 && array != 0 )
{
free(array);
@@ -5375,7 +5394,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
for (i=0; i<siglen; i++)
utxosig[i] = ptr[i];//, fprintf(stderr,"%02x",ptr[i]);
//fprintf(stderr," siglen.%d\n",siglen);
//fprintf(stderr,"best %u from %u, gap %d lag.%d\n",earliest,*blocktimep,(int32_t)(earliest - *blocktimep),(int32_t)(time(NULL) - *blocktimep));
//fprintf(stderr,"best %u from %u, gap %d lag.%d\n",earliest,*blocktimep,(int32_t)(earliest - *blocktimep),(int32_t)(time(NULL) - *blocktimep));
*blocktimep = earliest;
}
} //else fprintf(stderr,"no earliest utxo for staking\n");
@@ -5412,6 +5431,7 @@ int32_t ensure_CCrequirements()
#include "../cc/CCOracles.h"
#include "../cc/CCGateways.h"
#include "../cc/CCPrices.h"
#include "../cc/CCHeir.h"
UniValue CCaddress(struct CCcontract_info *cp,char *name,std::vector<unsigned char> &pubkey)
{
@@ -5633,15 +5653,25 @@ UniValue gatewaysaddress(const UniValue& params, bool fHelp)
UniValue heiraddress(const UniValue& params, bool fHelp)
{
struct CCcontract_info *cp,C; std::vector<unsigned char> pubkey;
struct CCcontract_info *cp,C; std::vector<unsigned char> destPubkey;
cp = CCinit(&C,EVAL_HEIR);
if ( fHelp || params.size() > 1 )
throw runtime_error("heiraddress [pubkey]\n");
if ( fHelp || (params.size() != 4 && params.size() != 3))
throw runtime_error("heiraddress func txid amount [destpubkey]\n");
if ( ensure_CCrequirements() < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
if ( params.size() == 1 )
pubkey = ParseHex(params[0].get_str().c_str());
return(CCaddress(cp,(char *)"Heir",pubkey));
//if ( params.size() == 1 )
// pubkey = ParseHex(params[0].get_str().c_str());
char funcid = ((char *)params[0].get_str().c_str())[0];
uint256 assetid = Parseuint256((char *)params[1].get_str().c_str());
int64_t funds = atof(params[2].get_str().c_str()) * COIN ;
if(params.size() == 4)
destPubkey = ParseHex(params[3].get_str().c_str());
//return HeirFundBad(funcid, assetid, funds, destPubkey);
return(CCaddress(cp,(char *)"Heir",destPubkey));
}
UniValue lottoaddress(const UniValue& params, bool fHelp)
@@ -6939,7 +6969,7 @@ UniValue tokencreate(const UniValue& params, bool fHelp)
const CKeyStore& keystore = *pwalletMain;
LOCK2(cs_main, pwalletMain->cs_wallet);
name = params[0].get_str();
supply = atof(params[1].get_str().c_str()) * COIN + 0.00000000499999;
supply = atof(params[1].get_str().c_str()) * COIN + 0.00000000499999; // what for is this '+0.00000000499999'? it will be lost while converting double to int64_t (dimxy)
if ( name.size() == 0 || name.size() > 32)
{
ERR_RESULT("Token name must not be empty and up to 32 characters");
@@ -6979,7 +7009,8 @@ UniValue tokentransfer(const UniValue& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
tokenid = Parseuint256((char *)params[0].get_str().c_str());
std::vector<unsigned char> pubkey(ParseHex(params[1].get_str().c_str()));
amount = atol(params[2].get_str().c_str());
//amount = atol(params[2].get_str().c_str());
amount = atoll(params[2].get_str().c_str()); // dimxy changed to prevent loss of significance
if ( tokenid == zeroid )
{
ERR_RESULT("invalid tokenid");
@@ -7015,7 +7046,8 @@ UniValue tokenconvert(const UniValue& params, bool fHelp)
evalcode = atoi(params[0].get_str().c_str());
tokenid = Parseuint256((char *)params[1].get_str().c_str());
std::vector<unsigned char> pubkey(ParseHex(params[2].get_str().c_str()));
amount = atol(params[3].get_str().c_str());
//amount = atol(params[3].get_str().c_str());
amount = atoll(params[3].get_str().c_str()); // dimxy changed to prevent loss of significance
if ( tokenid == zeroid )
{
ERR_RESULT("invalid tokenid");
@@ -7048,7 +7080,8 @@ UniValue tokenbid(const UniValue& params, bool fHelp)
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
const CKeyStore& keystore = *pwalletMain;
LOCK2(cs_main, pwalletMain->cs_wallet);
numtokens = atoi(params[0].get_str().c_str());
//numtokens = atoi(params[0].get_str().c_str());
numtokens = atoll(params[0].get_str().c_str()); // dimxy changed to prevent loss of significance
tokenid = Parseuint256((char *)params[1].get_str().c_str());
price = atof(params[2].get_str().c_str());
bidamount = (price * numtokens) * COIN + 0.0000000049999;
@@ -7116,7 +7149,8 @@ UniValue tokenfillbid(const UniValue& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
tokenid = Parseuint256((char *)params[0].get_str().c_str());
bidtxid = Parseuint256((char *)params[1].get_str().c_str());
fillamount = atol(params[2].get_str().c_str());
// fillamount = atol(params[2].get_str().c_str());
fillamount = atoll(params[2].get_str().c_str()); // dimxy changed to prevent loss of significance
if ( fillamount <= 0 )
{
ERR_RESULT("fillamount must be positive");
@@ -7145,10 +7179,12 @@ UniValue tokenask(const UniValue& params, bool fHelp)
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
const CKeyStore& keystore = *pwalletMain;
LOCK2(cs_main, pwalletMain->cs_wallet);
numtokens = atoi(params[0].get_str().c_str());
//numtokens = atoi(params[0].get_str().c_str());
numtokens = atoll(params[0].get_str().c_str()); // dimxy changed to prevent loss of significance
tokenid = Parseuint256((char *)params[1].get_str().c_str());
price = atof(params[2].get_str().c_str());
askamount = (price * numtokens) * COIN + 0.0000000049999;
//std::cerr << std::boolalpha << "tokenask(): (tokenid == zeroid) is " << (tokenid == zeroid) << " (numtokens <= 0) is " << (numtokens <= 0) << " (price <= 0) is " << (price <= 0) << " (askamount <= 0) is " << (askamount <= 0) << std::endl;
if ( tokenid == zeroid || numtokens <= 0 || price <= 0 || askamount <= 0 )
{
ERR_RESULT("invalid parameter");
@@ -7177,7 +7213,8 @@ UniValue tokenswapask(const UniValue& params, bool fHelp)
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
const CKeyStore& keystore = *pwalletMain;
LOCK2(cs_main, pwalletMain->cs_wallet);
numtokens = atoi(params[0].get_str().c_str());
//numtokens = atoi(params[0].get_str().c_str());
numtokens = atoll(params[0].get_str().c_str()); // dimxy changed to prevent loss of significance
tokenid = Parseuint256((char *)params[1].get_str().c_str());
otherid = Parseuint256((char *)params[2].get_str().c_str());
price = atof(params[3].get_str().c_str());
@@ -7231,7 +7268,8 @@ UniValue tokenfillask(const UniValue& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
tokenid = Parseuint256((char *)params[0].get_str().c_str());
asktxid = Parseuint256((char *)params[1].get_str().c_str());
fillunits = atol(params[2].get_str().c_str());
//fillunits = atol(params[2].get_str().c_str());
fillunits = atoll(params[2].get_str().c_str()); // dimxy changed to prevent loss of significance
if ( fillunits <= 0 )
{
ERR_RESULT("fillunits must be positive");
@@ -7271,7 +7309,8 @@ UniValue tokenfillswap(const UniValue& params, bool fHelp)
tokenid = Parseuint256((char *)params[0].get_str().c_str());
otherid = Parseuint256((char *)params[1].get_str().c_str());
asktxid = Parseuint256((char *)params[2].get_str().c_str());
fillunits = atol(params[3].get_str().c_str());
//fillunits = atol(params[3].get_str().c_str());
fillunits = atoll(params[3].get_str().c_str()); // dimxy changed to prevent loss of significance
hex = FillSell(0,tokenid,otherid,asktxid,fillunits);
if (fillunits > 0) {
if ( hex.size() > 0 ) {

View File

@@ -3615,7 +3615,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
if (!NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) {
max_tx_size = MAX_TX_SIZE_BEFORE_SAPLING;
}
/*
// Discourage fee sniping.
//
// However because of a off-by-one-error in previous versions we need to
@@ -3636,7 +3636,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
txNew.nLockTime = std::max(0, (int)txNew.nLockTime - GetRandInt(100));
assert(txNew.nLockTime <= (unsigned int)chainActive.Height());
assert(txNew.nLockTime < LOCKTIME_THRESHOLD);
assert(txNew.nLockTime < LOCKTIME_THRESHOLD);*/
{
LOCK2(cs_main, cs_wallet);
@@ -4960,10 +4960,10 @@ void CWallet::GetFilteredNotes(
}
// skip locked notes
// TODO: Add locking for Sapling notes
// if (ignoreLocked && IsLockedNote(op)) {
// continue;
// }
// TODO: Add locking for Sapling notes -> done
if (ignoreLocked && IsLockedNote(op)) {
continue;
}
auto note = notePt.note(nd.ivk).get();
saplingEntries.push_back(SaplingNoteEntry {

View File

@@ -46,7 +46,7 @@ extern bool fSendFreeTransactions;
extern bool fPayAtLeastCustomFee;
//! -paytxfee default
static const CAmount DEFAULT_TRANSACTION_FEE = 0;
static const CAmount DEFAULT_TRANSACTION_FEE = 10000;
//! -paytxfee will warn if called with a higher fee than this amount (in satoshis) per KB
static const CAmount nHighTransactionFeeWarning = 0.01 * COIN;
//! -maxtxfee default