diff --git a/.gitignore b/.gitignore index bebcef932..3916d4e87 100644 --- a/.gitignore +++ b/.gitignore @@ -120,3 +120,4 @@ src/komodo-cli src/komodod src/komodo-tx src/komodo-test +src/wallet-utility diff --git a/Makefile.am b/Makefile.am index d0c289ee1..d3171b206 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,7 +15,7 @@ endif BITCOIND_BIN=$(top_builddir)/src/zcashd$(EXEEXT) BITCOIN_CLI_BIN=$(top_builddir)/src/zcash-cli$(EXEEXT) -WALLET_UTILITY_BIN=$(top_builddir)/src/wallet-utility$(EXEEXT) +#WALLET_UTILITY_BIN=$(top_builddir)/src/wallet-utility$(EXEEXT) BITCOIN_WIN_INSTALLER=$(PACKAGE)-$(PACKAGE_VERSION)-win$(WINDOWS_BITS)-setup$(EXEEXT) if TARGET_DARWIN @@ -156,8 +156,8 @@ $(BITCOIND_BIN): FORCE $(BITCOIN_CLI_BIN): FORCE $(MAKE) -C src $(@F) -$(WALLET_UTILITY_BIN): FORCE - $(MAKE) -C src $(@F) +#$(WALLET_UTILITY_BIN): FORCE +# $(MAKE) -C src $(@F) if USE_LCOV diff --git a/README-mac.md b/README-mac.md index c085cb617..f3dd5e281 100644 --- a/README-mac.md +++ b/README-mac.md @@ -1,4 +1,6 @@ -First off you need Apple's Xcode (at least version 7, preferably 8.x) and the Xcode Command Line Tools: +## Install for Mac OS X + +First off you need Apple's Xcode (at least version 7, preferably 8.x or later) and the Xcode Command Line Tools: https://itunes.apple.com/us/app/xcode/id497799835?mt=12 @@ -11,25 +13,51 @@ And this is the list of brew packages you'll need installed: ```shell brew tap discoteq/discoteq; brew install flock brew install autoconf autogen automake -brew tap homebrew/versions; brew install homebrew/versions/gcc5 +brew install gcc@6 brew install binutils brew install protobuf brew install coreutils brew install wget ``` +or + +```shell +brew tap discoteq/discoteq; brew install flock autoconf autogen automake gcc@6 binutils protobuf coreutils wget +``` + Get all that installed, then run: ```shell -git clone https://github.com/j-cimb-barker/komodo.git +git clone https://github.com/jl777/komodo.git cd komodo -git checkout dev ./zcutil/build-mac.sh +./zcutil/fetch-params.sh ``` To build a distributable version of komodo then run the makeDistrib.sh script after building. -When you are done building, you need to do a few things in the [Configuration](https://github.com/zcash/zcash/wiki/1.0-User-Guide#configuration) section of the Zcash User Guide differently because we are on the Mac. All instances of `~/.zcash` need to be replaced by `~/Library/Application\ Support/Zcash` -The fetch-params.sh script, however, has already been altered to fetch the proving keys into the correct directory to conform to Mac specific naming conventions. +When you are done building, you need to create `Komodo.conf` the Mac way. + +```shell +mkdir ~/Library/Application\ Support/Komodo +touch ~/Library/Application\ Support/Komodo/Komodo.conf +nano ~/Library/Application\ Support/Komodo/Komodo.conf +``` + +Add the following lines to the Komodo.conf file: + +```shell +rpcuser=dontuseweakusernameoryougetrobbed +rpcpassword=dontuseweakpasswordoryougetrobbed +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 +``` Happy Building diff --git a/README.md b/README.md index e766870a5..5d85d013d 100644 --- a/README.md +++ b/README.md @@ -1,38 +1,46 @@ ## Komodo with Bitcore This version of Komodo contains Bitcore support for komodo and all its assetchains. + ## Komodod This software is Komodo client, generally you will use this if you want to mine KMD or setup a full node. It downloads and stores the entire history of Komodo 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. + ## Development Resources - Komodo Web: [https://komodoplatform.com/](https://komodoplatform.com/) -- Organization web: [https://www.supernet.org](https://www.supernet.org) -- Forum: [https://forum.supernet.org/](https://forum.supernet.org/) -- Mail: [info@supernet.org](mailto:info@supernet.org) -- Support & Guides: [https://support.supernet.org/support/home](https://support.supernet.org/support/home) +- Organization web: [https://komodoplatform.com/](https://komodoplatform.com/) +- Forum: [https://forum.komodoplatform.com/](https://forum.komodoplatform.com/) +- Mail: [info@komodoplatform.com](mailto:info@komodoplatform.com) +- Support: [https://support.komodoplatform.com/support/home](https://support.komodoplatform.com/support/home) +- Knowledgebase & How-to: [https://komodoplatform.atlassian.net/wiki/spaces/KPSD/pages](https://komodoplatform.atlassian.net/wiki/spaces/KPSD/pages) - API references: [http://docs.supernet.org/](http://docs.supernet.org/) #Not up to date. +- Whitepaper: [Komodo Whitepaper](https://komodoplatform.com/wp-content/uploads/2018/03/2018-03-12-Komodo-White-Paper-Full.pdf) - Komodo Platform public material: [Komodo Platform public material](https://docs.google.com/document/d/1AbhWrtagu4vYdkl-vsWz-HSNyNvK-W-ZasHCqe7CZy0) + ## List of Komodo Platform Technologies -Delayed Proof of Work (dPoW) - Additional security layer. -zk-SNARKs - Komodo Platform's privacy technology -Jumblr - Decentralized tumbler for KMD and other cryptocurrencies -Assetchains - Easy way to fork Komodo coin -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://supernet.org/en/resources/articles/receive-free-coins-quaranteed-kmd-interest) +- Delayed Proof of Work (dPoW) - Additional security layer. +- zk-SNARKs - Komodo Platform's privacy technology +- Jumblr - Decentralized tumbler for KMD and other cryptocurrencies +- Assetchains - Easy way to fork Komodo coin +- 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) + ## Tech Specification -Max Supply: 200 million KMD. -Block Time: 1M 2s -Block Reward: 3KMD -Mining Algorithm: Equihash +- Max Supply: 200 million KMD. +- Block Time: 1M 2s +- Block Reward: 3KMD +- Mining Algorithm: Equihash + ## About this Project Komodo is based on Zcash and has been by our innovative consensus algorithm called dPoW which utilizes Bitcoin's hashrate to store Komodo blockchain information into the Bitcoin blockchain. Other new and native Komodo features are the privacy technology called JUMBLR or our assetchain capabilities (one click plug and play blockchain solutions). More details are available under https://komodoplatform.com/. + ## Getting started Dependencies ------------ -``` +```shell #The following packages are needed: 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-openssl-dev bsdmainutils automake curl ``` @@ -54,7 +62,7 @@ dPoW branch: autobuild into GUI installers, unix, osx, windows beta branch: notary nodes, command line unix dev branch: bleeding edge, possibly wont even compile, multiple updates per hour -``` +```shell git clone https://github.com/jl777/komodo cd komodo #you might want to: git checkout ; git pull @@ -64,7 +72,6 @@ cd komodo #This can take some time. ``` - **komodo is experimental and a work-in-progress.** Use at your own risk. Deprecation Policy @@ -76,11 +83,14 @@ time after this one year period. The automatic feature is based on block height and can be explicitly disabled. -# to update an existing version, git checkout dPoW if not on that branch already +# to update an existing version, `git checkout dPoW` if not on that branch already +```shell git pull ./zcutil/fetch-params.sh ./zcutil/build.sh -j8 -To reset the blockchain, from ~/.komodo rm -rf blocks chainstate debug.log komodostate db.log +``` +To reset the blockchain, from *~/.komodo* `rm -rf blocks chainstate debug.log komodostate db.log` + Create komodo.conf ------------------ @@ -105,7 +115,7 @@ addnode=89.248.166.91 Start mining ------------ -``` +```shell #iguana documentation shows how to get the btcpubkey and wifstrs that need to be used #bitcoin also need to be installed with txindex=1 and with rpc enabled cd ~ @@ -136,59 +146,89 @@ Both komodod and komodo-cli recognize -ac_name=option so you can create fork fro ``` ======= **Zcash is unfinished and highly experimental.** Use at your own risk. + Where do I begin? ----------------- We have a guide for joining the main Zcash network: https://github.com/zcash/zcash/wiki/1.0-User-Guide + ### Need Help? * See the documentation at the [Zcash Wiki](https://github.com/zcash/zcash/wiki) for help and more information. * Ask for help on the [Zcash](https://forum.z.cash/) forum. Participation in the Zcash project is subject to a [Code of Conduct](code_of_conduct.md). + Building -------- Build Zcash along with most dependencies from source by running -./zcutil/build.sh. Currently only Linux is officially supported. +`./zcutil/build.sh`. Currently only Linux is officially supported. + License ------- For license information see the file [COPYING](COPYING). -NOTE TO EXCHANGES: + +**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= 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 + +**To change modes:** + +a) backup all privkeys (launch komodod with `-exportdir=` 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 ./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 -############## JUMBLR -komodod now has jumblr_deposit and jumblr_secret RPC calls. +``` + +## JUMBLR +komodod now has `jumblr_deposit` and `jumblr_secret` RPC calls. + Jumblr works like described previously where all the nodes with jumblr active synchronize their tx activity during the same block to maximize the mixing effect. However, unlike all other mixers/tumblers, you never give up control of your coins to anybody else. JUMBLR uses a one to many allocation of funds, ie. one deposit address and many secret addresses. You can always run multiple komodod daemons to get multiple active deposit addresses. + JUMBLR implements t -> z, z -> z and z -> t transactions to maximize privacy of the destination t (transparent) address. So while it is transparent, its first activity is funds coming from an untracable z address. + Which of the three stages is done is randomly selected at each turn. Also when there is more than one possible transaction at the selected stage, a random one is selected. This randomization prevents analyzing incoming z ->t transactions by its size to correlate it to the originating address. -jumblr_deposit designates the deposit address as the jumblr deposit address for that session. You can select an address that already has funds in it and it will immediately start jumblr process. If there are no funds, it will wait until you send funds to it. -There are three sizes of a jumblr transaction: 10 KMD, 100 KMD and 1000 KMD. There is also a fixed interval of blocks where all jumblr nodes are active. Currently it is set to be 10, but this is subject to change. Only during every 10*10 blocks are the largest 1000 KMD transactions processed, so this concentrates all the large transactions every N*N blocks. -jumblr_secret notifies JUMBLR where to send the final z -> t transactions. In order to allow larger accounts to obtain privacy, up to 777 secret addresses are supported. Whenever a z -> t stage is activated, a random secret address from the list of the then active secret addresses is selected. -Practical Advice: + +`jumblr_deposit ` designates the deposit address as the jumblr deposit address for that session. You can select an address that already has funds in it and it will immediately start jumblr process. If there are no funds, it will wait until you send funds to it. + +There are three sizes of a jumblr transaction: 10 KMD, 100 KMD and 1000 KMD. There is also a fixed interval of blocks where all jumblr nodes are active. Currently it is set to be 10, but this is subject to change. Only during every 10*10 blocks are the largest 1000 KMD transactions processed, so this concentrates all the large transactions every N*N blocks. + +`jumblr_secret ` notifies JUMBLR where to send the final z -> t transactions. In order to allow larger accounts to obtain privacy, up to 777 secret addresses are supported. Whenever a z -> t stage is activated, a random secret address from the list of the then active secret addresses is selected. + +#### Practical Advice: Obtaining privacy used to be very difficult. JUMBLR makes it as simple as issuing two command line calls. Higher level layers can be added to help manage the addresses, ie. linking them at the passphrase level. Such matters are left to each implementation. + Once obtained, it is very easy to lose all the privacy. With a single errant transaction that combines some previously used address and the secretaddress, well, the secretaddress is no longer so private. + The advice is to setup a totally separate node! + This might seem a bit drastic, but if you want to maintain privacy, it is best to make it look like all the transactions are coming from a different node. The easiest way for most people to do this is to actually have a different node. -It can be a dedicated laptop (recommended) or a VPS (for smaller amounts) with a totally fresh komodod wallet. Generate an address on this wallet and use that as the jumblr_secret address on your main node. As the JUMBLR operates funds will teleport into your secret node's address. If you are careful and never use the same IP address for both your nodes, you will be able to maintain very good privacy. + +It can be a dedicated laptop (recommended) or a VPS (for smaller amounts) with a totally fresh komodod wallet. Generate an address on this wallet and use that as the jumblr_secret address on your main node. As the JUMBLR operates funds will teleport into your secret node's address. If you are careful and never use the same IP address for both your nodes, you will be able to maintain very good privacy. + Of course, don't send emails that link the two accounts together! Dont use secret address funds for home delivery purchases! Etc. There are many ways to lose the privacy, just think about what linkages can be dont at the IP and blockchain level and that should be a useful preparation. + What if you have 100,000 KMD and you dont want others to know you are such a whale? Instead of generating 1 secret address, generate 100 and make a script file with: +```shell ./komodo-cli jumblr_secret ./komodo-cli jumblr_secret ... ./komodo-cli jumblr_secret +``` And make sure to delete all traces of this when the JUMBLR is finished. You will end up with 100 addresses that have an average of 1000 KMD each. So as long as you are careful and dont do a 10,000 KMD transaction (that will link 10 of your secret addresses together), you can appear as 100 different people each with 1000 KMD. + diff --git a/darwin.host.mk.patch b/darwin.host.mk.patch index 426702563..deeb7a810 100644 --- a/darwin.host.mk.patch +++ b/darwin.host.mk.patch @@ -5,8 +5,8 @@ OSX_SDK_VERSION=10.9 OSX_SDK=$(SDK_PATH)/MacOSX$(OSX_SDK_VERSION).sdk LD64_VERSION=241.9 -! darwin_CC=gcc-5 -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) -! darwin_CXX=g++-5 -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) +! darwin_CC=gcc-6 -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) +! darwin_CXX=g++-6 -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) darwin_CFLAGS=-pipe darwin_CXXFLAGS=$(darwin_CFLAGS) diff --git a/darwin.mk.patch b/darwin.mk.patch index 80bc5b2d9..fdfd7bc38 100644 --- a/darwin.mk.patch +++ b/darwin.mk.patch @@ -2,8 +2,8 @@ --- ../../komodo-jl777/depends/builders/darwin.mk 2017-01-03 09:48:21.646034937 +0000 *************** *** 1,5 **** -! build_darwin_CC = gcc-5 -! build_darwin_CXX = g++-5 +! build_darwin_CC = gcc-6 +! build_darwin_CXX = g++-6 build_darwin_AR: = $(shell xcrun -f ar) build_darwin_RANLIB: = $(shell xcrun -f ranlib) build_darwin_STRIP: = $(shell xcrun -f strip) @@ -21,8 +21,8 @@ ! build_darwin_DOWNLOAD = wget --timeout=$(DOWNLOAD_CONNECT_TIMEOUT) --tries=$(DOWNLOAD_RETRIES) -nv -O #darwin host on darwin builder. overrides darwin host preferences. -! darwin_CC= gcc-5 -! darwin_CXX= g++-5 +! darwin_CC= gcc-6 +! darwin_CXX= g++-6 darwin_AR:=$(shell xcrun -f ar) darwin_RANLIB:=$(shell xcrun -f ranlib) darwin_STRIP:=$(shell xcrun -f strip) diff --git a/depends/builders/darwin.mk b/depends/builders/darwin.mk index b986aecec..f9b066fcf 100644 --- a/depends/builders/darwin.mk +++ b/depends/builders/darwin.mk @@ -1,5 +1,5 @@ -build_darwin_CC = gcc-5 -build_darwin_CXX = g++-5 +build_darwin_CC = gcc-6 +build_darwin_CXX = g++-6 build_darwin_AR: = $(shell xcrun -f ar) build_darwin_RANLIB: = $(shell xcrun -f ranlib) build_darwin_STRIP: = $(shell xcrun -f strip) @@ -7,19 +7,11 @@ build_darwin_OTOOL: = $(shell xcrun -f otool) build_darwin_NM: = $(shell xcrun -f nm) build_darwin_INSTALL_NAME_TOOL:=$(shell xcrun -f install_name_tool) build_darwin_SHA256SUM = shasum -a 256 -#<<<<<<< HEAD -##build_darwin_DOWNLOAD = curl --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -L -f -o +build_darwin_DOWNLOAD = curl --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -L -f -o #darwin host on darwin builder. overrides darwin host preferences. -#darwin_CC= gcc-5 -#darwin_CXX= g++-5 -#======= -build_darwin_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -o - -#darwin host on darwin builder. overrides darwin host preferences. -darwin_CC=$(shell xcrun -f clang) -mmacosx-version-min=$(OSX_MIN_VERSION) -darwin_CXX:=$(shell xcrun -f clang++) -mmacosx-version-min=$(OSX_MIN_VERSION) -stdlib=libc++ -#>>>>>>> zcash/master +darwin_CC= gcc-6 +darwin_CXX= g++-6 darwin_AR:=$(shell xcrun -f ar) darwin_RANLIB:=$(shell xcrun -f ranlib) darwin_STRIP:=$(shell xcrun -f strip) diff --git a/depends/hosts/darwin.mk b/depends/hosts/darwin.mk index 4f1748657..5eaeddc26 100644 --- a/depends/hosts/darwin.mk +++ b/depends/hosts/darwin.mk @@ -1,15 +1,9 @@ OSX_MIN_VERSION=10.8 OSX_SDK_VERSION=10.11 OSX_SDK=$(SDK_PATH)/MacOSX$(OSX_SDK_VERSION).sdk -#<<<<<<< HEAD -#LD64_VERSION=241.9 -#darwin_CC=gcc-5 -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) -#darwin_CXX=g++-5 -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) -#======= LD64_VERSION=253.9 -darwin_CC=clang -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) -darwin_CXX=clang++ -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) -stdlib=libc++ -#>>>>>>> zcash/master +darwin_CC=gcc-6 -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) +darwin_CXX=g++-6 -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) darwin_CFLAGS=-pipe darwin_CXXFLAGS=$(darwin_CFLAGS) diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index 099993a62..8f3fd1b1c 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -1,17 +1,17 @@ + package=boost -$(package)_version=1_62_0 -$(package)_download_path=http://sourceforge.net/projects/boost/files/boost/1.62.0 +$(package)_version=1_66_0 +$(package)_download_path=https://dl.bintray.com/boostorg/release/1.66.0/source $(package)_file_name=$(package)_$($(package)_version).tar.bz2 -$(package)_sha256_hash=36c96b0f6155c98404091d8ceb48319a28279ca0333fba1ad8611eb90afb2ca0 -$(package)_patches=deprecated_auto_ptr.patch include_poll.patch +$(package)_sha256_hash=5721818253e6a0989583192f96782c4a98eb6204965316df9f5ad75819225ca9 define $(package)_set_vars $(package)_config_opts_release=variant=release $(package)_config_opts_debug=variant=debug -$(package)_config_opts=--layout=tagged --build-type=complete --user-config=user-config.jam -$(package)_config_opts+=link=static -sNO_BZIP2=1 -sNO_ZLIB=1 +$(package)_config_opts=--layout=system --user-config=user-config.jam +$(package)_config_opts+=threading=multi link=static -sNO_BZIP2=1 -sNO_ZLIB=1 $(package)_config_opts_linux=threadapi=pthread runtime-link=shared -$(package)_config_opts_darwin=--toolset=gcc threadapi=pthread runtime-link=shared +$(package)_config_opts_darwin=--toolset=gcc runtime-link=shared threadapi=pthread $(package)_config_opts_mingw32=binary-format=pe target-os=windows threadapi=win32 runtime-link=static $(package)_config_opts_x86_64_mingw32=address-model=64 $(package)_config_opts_i686_mingw32=address-model=32 @@ -25,10 +25,9 @@ $(package)_cxxflags=-std=c++11 -fvisibility=hidden $(package)_cxxflags_linux=-fPIC endef + define $(package)_preprocess_cmds - echo "using $(boost_toolset_$(host_os)) : : $($(package)_cxx) : \"$($(package)_cxxflags) $($(package)_cppflags)\" \"$($(package)_ldflags)\" \"$(boost_archiver_$(host_os))\" \"$(host_STRIP)\" \"$(host_RANLIB)\" \"$(host_WINDRES)\" : ;" > user-config.jam && \ - patch -p1 < $($(package)_patch_dir)/deprecated_auto_ptr.patch && \ - patch -p1 < $($(package)_patch_dir)/include_poll.patch + echo "using $(boost_toolset_$(host_os)) : : $($(package)_cxx) : \"$($(package)_cxxflags) $($(package)_cppflags)\" \"$($(package)_ldflags)\" \"$(boost_archiver_$(host_os))\" \"$(host_STRIP)\" \"$(host_RANLIB)\" \"$(host_WINDRES)\" : ;" > user-config.jam endef define $(package)_config_cmds diff --git a/depends/packages/googletest.mk b/depends/packages/googletest.mk index b9fa3e7e8..1275593f5 100644 --- a/depends/packages/googletest.mk +++ b/depends/packages/googletest.mk @@ -14,7 +14,8 @@ endif ifeq ($(build_os),darwin) $(package)_install=ginstall define $(package)_build_cmds - $(MAKE) -C make gtest.a + $(MAKE) -C googlemock/make gmock.a && \ + $(MAKE) -C googletest/make gtest.a endef else $(package)_install=install diff --git a/depends/packages/libgmp.mk b/depends/packages/libgmp.mk index f06e4a6c4..d8e41573a 100644 --- a/depends/packages/libgmp.mk +++ b/depends/packages/libgmp.mk @@ -18,7 +18,7 @@ $(package)_dependencies= $(package)_config_opts=--enable-cxx --disable-shared else $(package)_version=6.1.1 -$(package)_download_path=https://gmplib.org/download/gmp/ +$(package)_download_path=https://supernetorg.bintray.com/misc $(package)_file_name=gmp-$($(package)_version).tar.bz2 $(package)_sha256_hash=a8109865f2893f1373b0a8ed5ff7429de8db696fc451b1036bd7bdf95bbeffd6 $(package)_dependencies= diff --git a/depends/packages/librustzcash.mk b/depends/packages/librustzcash.mk index bfd8fef1e..20126776a 100644 --- a/depends/packages/librustzcash.mk +++ b/depends/packages/librustzcash.mk @@ -7,7 +7,6 @@ $(package)_sha256_hash=a5760a90d4a1045c8944204f29fa2a3cf2f800afee400f88bf89bbfe2 $(package)_git_commit=91348647a86201a9482ad4ad68398152dc3d635e $(package)_dependencies=rust - ifeq ($(host_os),mingw32) define $(package)_build_cmds ~/.cargo/bin/cargo build --release --target=x86_64-pc-windows-gnu --verbose diff --git a/depends/packages/libsodium.mk b/depends/packages/libsodium.mk index 91e6f27b7..efa5d90de 100644 --- a/depends/packages/libsodium.mk +++ b/depends/packages/libsodium.mk @@ -1,17 +1,20 @@ +ifeq ($(build_os),darwin) +package=libsodium +$(package)_version=1.0.11 +$(package)_download_path=https://supernetorg.bintray.com/misc +$(package)_file_name=libsodium-1.0.11.tar.gz +$(package)_sha256_hash=a14549db3c49f6ae2170cbbf4664bd48ace50681045e8dbea7c8d9fb96f9c765 +$(package)_dependencies= +$(package)_config_opts= +else package=libsodium -#<<<<<<< HEAD -#$(package)_version=1.0.11 -#$(package)_download_path=https://supernetorg.bintray.com/misc -#$(package)_file_name=libsodium-1.0.11.tar.gz -#$(package)_sha256_hash=a14549db3c49f6ae2170cbbf4664bd48ace50681045e8dbea7c8d9fb96f9c765 -#======= $(package)_version=1.0.15 $(package)_download_path=https://download.libsodium.org/libsodium/releases/ $(package)_file_name=$(package)-$($(package)_version).tar.gz $(package)_sha256_hash=fb6a9e879a2f674592e4328c5d9f79f082405ee4bb05cb6e679b90afe9e178f4 -#>>>>>>> zcash/master $(package)_dependencies= $(package)_config_opts= +endif define $(package)_preprocess_cmds cd $($(package)_build_subdir); ./autogen.sh diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 3c78e29c3..9174db320 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -1,7 +1,12 @@ rust_packages := rust librustzcash -proton_packages := proton -zcash_packages := libgmp libsodium +ifeq ($(build_os),darwin) + zcash_packages := libsnark libgmp libsodium +else + proton_packages := proton + zcash_packages := libgmp libsodium +endif + ifeq ($(host_os),linux) packages := boost openssl libevent zeromq $(zcash_packages) googletest #googlemock else diff --git a/depends/packages/proton.mk b/depends/packages/proton.mk index aa49f380f..39428f54b 100644 --- a/depends/packages/proton.mk +++ b/depends/packages/proton.mk @@ -1,6 +1,6 @@ package=proton $(package)_version=0.17.0 -$(package)_download_path=http://apache.cs.utah.edu/qpid/proton/$($(package)_version) +$(package)_download_path=https://archive.apache.org/dist/qpid/proton/$($(package)_version) $(package)_file_name=qpid-proton-$($(package)_version).tar.gz $(package)_sha256_hash=6ffd26d3d0e495bfdb5d9fefc5349954e6105ea18cc4bb191161d27742c5a01a $(package)_patches=minimal-build.patch @@ -21,4 +21,3 @@ endef define $(package)_stage_cmds cd build; $(MAKE) VERBOSE=1 DESTDIR=$($(package)_staging_prefix_dir) install endef - diff --git a/depends/packages/rust.mk b/depends/packages/rust.mk index eb28c76d1..2e3f0b204 100644 --- a/depends/packages/rust.mk +++ b/depends/packages/rust.mk @@ -1,23 +1,16 @@ package=rust $(package)_version=1.16.0 $(package)_download_path=https://static.rust-lang.org/dist -#<<<<<<< HEAD -#ifeq ($(build_os),darwin) -#$(package)_file_name=rust-$($(package)_version)-x86_64-apple-darwin.tar.gz -#$(package)_sha256_hash=2d08259ee038d3a2c77a93f1a31fc59e7a1d6d1bbfcba3dba3c8213b2e5d1926 -#else ifeq ($(host_os),mingw32) -#$(package)_file_name=rust-$($(package)_version)-i686-unknown-linux-gnu.tar.gz -#$(package)_sha256_hash=b5859161ebb182d3b75fa14a5741e5de87b088146fb0ef4a30f3b2439c6179c5 -#else -#$(package)_file_name=rust-$($(package)_version)-x86_64-unknown-linux-gnu.tar.gz -#$(package)_sha256_hash=48621912c242753ba37cad5145df375eeba41c81079df46f93ffb4896542e8fd -#endif -#======= -$(package)_file_name_linux=rust-$($(package)_version)-x86_64-unknown-linux-gnu.tar.gz -$(package)_sha256_hash_linux=48621912c242753ba37cad5145df375eeba41c81079df46f93ffb4896542e8fd -$(package)_file_name_darwin=rust-$($(package)_version)-x86_64-apple-darwin.tar.gz -$(package)_sha256_hash_darwin=2d08259ee038d3a2c77a93f1a31fc59e7a1d6d1bbfcba3dba3c8213b2e5d1926 -#>>>>>>> zcash/master +ifeq ($(build_os),darwin) +$(package)_file_name=rust-$($(package)_version)-x86_64-apple-darwin.tar.gz +$(package)_sha256_hash=2d08259ee038d3a2c77a93f1a31fc59e7a1d6d1bbfcba3dba3c8213b2e5d1926 +else ifeq ($(host_os),mingw32) +$(package)_file_name=rust-$($(package)_version)-i686-unknown-linux-gnu.tar.gz +$(package)_sha256_hash=b5859161ebb182d3b75fa14a5741e5de87b088146fb0ef4a30f3b2439c6179c5 +else +$(package)_file_name=rust-$($(package)_version)-x86_64-unknown-linux-gnu.tar.gz +$(package)_sha256_hash=48621912c242753ba37cad5145df375eeba41c81079df46f93ffb4896542e8fd +endif define $(package)_stage_cmds ./install.sh --destdir=$($(package)_staging_dir) --prefix=$(host_prefix)/native --disable-ldconfig diff --git a/libsnark.mk.patch b/libsnark.mk.patch index f43ea2188..28a60c8b6 100644 --- a/libsnark.mk.patch +++ b/libsnark.mk.patch @@ -14,7 +14,7 @@ - ifeq ($(build_os),darwin) - define $(package)_build_cmds -- CC=gcc-5 CXX=g++-5 CXXFLAGS="-arch x86_64 -DBINARY_OUTPUT -DNO_PT_COMPRESSION=1" $(MAKE) lib DEPINST=$(host_prefix) CURVE=ALT_BN128 MULTICORE=0 NO_PROCPS=1 NO_GTEST=1 NO_DOCS=1 STATIC=1 NO_SUPERCOP=1 FEATUREFLAGS=-DMONTGOMERY_OUTPUT +- CC=gcc-6 CXX=g++-6 CXXFLAGS="-arch x86_64 -DBINARY_OUTPUT -DNO_PT_COMPRESSION=1" $(MAKE) lib DEPINST=$(host_prefix) CURVE=ALT_BN128 MULTICORE=0 NO_PROCPS=1 NO_GTEST=1 NO_DOCS=1 STATIC=1 NO_SUPERCOP=1 FEATUREFLAGS=-DMONTGOMERY_OUTPUT - endef - else define $(package)_build_cmds diff --git a/migratecoin.md b/migratecoin.md new file mode 100644 index 000000000..7859bdff2 --- /dev/null +++ b/migratecoin.md @@ -0,0 +1,61 @@ +# MigrateCoin protocol + + + +## ExportCoins tx: + + + +``` + +vin: + + [ any ] + +vout: + + - amount: {burnAmount} + + script: OP_RETURN "send to ledger {id} {voutsHash}" + +``` + + + +* ExportCoin is a standard tx which burns coins in an OP_RETURN + + + +## ImportCoins tx: + + + +``` + +vin: + + - txid: 0000000000000000000000000000000000000000000000000000000000000000 + + idx: 0 + + script: CC_EVAL(EVAL_IMPORTCOINS, {momoProof},{exportCoin}) OP_CHECKCRYPTOCONDITION_UNILATERAL + +vout: + + - [ vouts matching voutsHash in exportCoin ] + +``` + + + +* ImportCoin transaction has no signature + +* ImportCoin is non malleable + +* ImportCoin satisfies tx.IsCoinBase() + +* ImportCoin uses a new opcode which allows a one sided check (no scriptPubKey) + +* ImportCoin must contain CC opcode EVAL_IMPORTCOINS + +* ImportCoin fees are equal to the difference between burnAmount in exportCoins and the sum of outputs. diff --git a/src/Makefile.am b/src/Makefile.am index 5166a6103..f9b19978b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -100,9 +100,9 @@ bin_PROGRAMS = noinst_PROGRAMS = TESTS = -if BUILD_BITCOIND +#if BUILD_BITCOIND bin_PROGRAMS += komodod -endif +#endif if BUILD_BITCOIN_UTILS bin_PROGRAMS += komodo-cli komodo-tx @@ -111,6 +111,7 @@ if ENABLE_WALLET bin_PROGRAMS += wallet-utility endif + LIBZCASH_H = \ zcash/IncrementalMerkleTree.hpp \ zcash/NoteEncryption.hpp \ @@ -255,11 +256,11 @@ libbitcoin_server_a_SOURCES = \ asyncrpcqueue.cpp \ bloom.cpp \ cc/eval.cpp \ - cc/importpayout.cpp \ - cc/disputepayout.cpp \ + cc/import.cpp \ cc/betprotocol.cpp \ chain.cpp \ checkpoints.cpp \ + crosschain.cpp \ deprecation.cpp \ httprpc.cpp \ httpserver.cpp \ @@ -271,12 +272,14 @@ libbitcoin_server_a_SOURCES = \ miner.cpp \ net.cpp \ noui.cpp \ + notarisationdb.cpp \ paymentdisclosure.cpp \ paymentdisclosuredb.cpp \ policy/fees.cpp \ pow.cpp \ rest.cpp \ rpcblockchain.cpp \ + rpccrosschain.cpp \ rpcmining.cpp \ rpcmisc.cpp \ rpcnet.cpp \ @@ -384,6 +387,7 @@ libbitcoin_common_a_SOURCES = \ core_read.cpp \ core_write.cpp \ hash.cpp \ + importcoin.cpp \ key.cpp \ keystore.cpp \ netbase.cpp \ @@ -528,7 +532,7 @@ wallet_utility_LDADD = \ $(LIBZCASH) \ $(LIBSNARK) \ $(LIBZCASH_LIBS)\ - $(LIBCRYPTOCONDITIONS) + $(LIBCRYPTOCONDITIONS) endif # zcash-tx binary # @@ -604,7 +608,7 @@ endif libzcashconsensus_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined $(RELDFLAGS) libzcashconsensus_la_LIBADD = $(LIBSECP256K1) -libzcashconsensus_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(builddir)/obj -I$(srcdir)/secp256k1/include -DBUILD_BITCOIN_INTERNAL +libzcashconsensus_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(builddir)/obj -I$(srcdir)/secp256k1/include -I$(srcdir)/cryptoconditions/include -DBUILD_BITCOIN_INTERNAL libzcashconsensus_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) endif diff --git a/src/Makefile.ktest.include b/src/Makefile.ktest.include index 06aab54dc..07c64caa0 100644 --- a/src/Makefile.ktest.include +++ b/src/Makefile.ktest.include @@ -5,9 +5,13 @@ bin_PROGRAMS += komodo-test # tool for generating our public parameters komodo_test_SOURCES = \ test-komodo/main.cpp \ + test-komodo/testutils.cpp \ test-komodo/test_cryptoconditions.cpp \ + test-komodo/test_coinimport.cpp \ test-komodo/test_eval_bet.cpp \ - test-komodo/test_eval_notarisation.cpp + test-komodo/test_eval_notarisation.cpp \ + test-komodo/test_crosschain.cpp \ + test-komodo/test_parse_notarisation.cpp komodo_test_CPPFLAGS = $(komodod_CPPFLAGS) diff --git a/src/ac/axo b/src/ac/axo new file mode 100755 index 000000000..18d38cac0 --- /dev/null +++ b/src/ac/axo @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=AXO $1 $2 $3 $4 $5 $6 diff --git a/src/ac/beer b/src/ac/beer new file mode 100755 index 000000000..34317bb93 --- /dev/null +++ b/src/ac/beer @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=BEER $1 $2 $3 $4 $5 $6 diff --git a/src/ac/bet b/src/ac/bet new file mode 100755 index 000000000..ed99ce59f --- /dev/null +++ b/src/ac/bet @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=BET $1 $2 $3 $4 $5 $6 diff --git a/src/ac/bntn b/src/ac/bntn new file mode 100755 index 000000000..7ae6f4e8d --- /dev/null +++ b/src/ac/bntn @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=BNTN $1 $2 $3 $4 $5 $6 diff --git a/src/ac/bots b/src/ac/bots new file mode 100755 index 000000000..15c0fc288 --- /dev/null +++ b/src/ac/bots @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=BOTS $1 $2 $3 $4 $5 $6 diff --git a/src/ac/btch b/src/ac/btch new file mode 100755 index 000000000..6a57ea8d1 --- /dev/null +++ b/src/ac/btch @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=BTCH $1 $2 $3 $4 $5 $6 diff --git a/src/ac/ceal b/src/ac/ceal new file mode 100755 index 000000000..0cbeba67b --- /dev/null +++ b/src/ac/ceal @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=CEAL $1 $2 $3 $4 $5 $6 diff --git a/src/ac/chain b/src/ac/chain new file mode 100755 index 000000000..c55d30fbd --- /dev/null +++ b/src/ac/chain @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=CHAIN $1 $2 $3 $4 $5 $6 diff --git a/src/ac/coqui b/src/ac/coqui new file mode 100755 index 000000000..d4fcb63d5 --- /dev/null +++ b/src/ac/coqui @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=COQUI $1 $2 $3 $4 $5 $6 diff --git a/src/ac/crypto b/src/ac/crypto new file mode 100755 index 000000000..5a3d46188 --- /dev/null +++ b/src/ac/crypto @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=CRYPTO $1 $2 $3 $4 $5 $6 diff --git a/src/ac/dex b/src/ac/dex new file mode 100755 index 000000000..67331201a --- /dev/null +++ b/src/ac/dex @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=DEX $1 $2 $3 $4 $5 $6 diff --git a/src/ac/dsec b/src/ac/dsec new file mode 100755 index 000000000..a050ca94f --- /dev/null +++ b/src/ac/dsec @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=DSEC $1 $2 $3 $4 $5 $6 diff --git a/src/ac/eql b/src/ac/eql new file mode 100755 index 000000000..99cfa9a09 --- /dev/null +++ b/src/ac/eql @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=EQL $1 $2 $3 $4 $5 $6 diff --git a/src/ac/etomic b/src/ac/etomic new file mode 100755 index 000000000..76eb0191c --- /dev/null +++ b/src/ac/etomic @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=ETOMIC $1 $2 $3 $4 $5 $6 diff --git a/src/ac/glxt b/src/ac/glxt new file mode 100755 index 000000000..6cedfbf87 --- /dev/null +++ b/src/ac/glxt @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=GLXT $1 $2 $3 $4 $5 $6 diff --git a/src/ac/hodl b/src/ac/hodl new file mode 100755 index 000000000..a5430db59 --- /dev/null +++ b/src/ac/hodl @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=HODL $1 $2 $3 $4 $5 $6 diff --git a/src/ac/jumblr b/src/ac/jumblr new file mode 100755 index 000000000..2969c5009 --- /dev/null +++ b/src/ac/jumblr @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=JUMBLR $1 $2 $3 $4 $5 $6 diff --git a/src/ac/kv b/src/ac/kv new file mode 100755 index 000000000..997fccb33 --- /dev/null +++ b/src/ac/kv @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=KV $1 $2 $3 $4 $5 $6 diff --git a/src/ac/mesh b/src/ac/mesh new file mode 100755 index 000000000..19b359509 --- /dev/null +++ b/src/ac/mesh @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=MESH $1 $2 $3 $4 $5 $6 diff --git a/src/ac/mgw b/src/ac/mgw new file mode 100755 index 000000000..9afa86b7a --- /dev/null +++ b/src/ac/mgw @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=MGW $1 $2 $3 $4 $5 $6 diff --git a/src/ac/mnz b/src/ac/mnz new file mode 100755 index 000000000..f4e1f3501 --- /dev/null +++ b/src/ac/mnz @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=MNZ $1 $2 $3 $4 $5 $6 diff --git a/src/ac/mshark b/src/ac/mshark new file mode 100755 index 000000000..1f0c950c6 --- /dev/null +++ b/src/ac/mshark @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=MSHARK $1 $2 $3 $4 $5 $6 diff --git a/src/ac/ninja b/src/ac/ninja new file mode 100755 index 000000000..f7722abb0 --- /dev/null +++ b/src/ac/ninja @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=NINJA $1 $2 $3 $4 $5 $6 diff --git a/src/ac/oot b/src/ac/oot new file mode 100755 index 000000000..4c7c6b683 --- /dev/null +++ b/src/ac/oot @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=OOT $1 $2 $3 $4 $5 $6 diff --git a/src/ac/pangea b/src/ac/pangea new file mode 100755 index 000000000..9920189ea --- /dev/null +++ b/src/ac/pangea @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=PANGEA $1 $2 $3 $4 $5 $6 diff --git a/src/ac/pizza b/src/ac/pizza new file mode 100755 index 000000000..d8400d9d3 --- /dev/null +++ b/src/ac/pizza @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=PIZZA $1 $2 $3 $4 $5 $6 diff --git a/src/ac/prlpay b/src/ac/prlpay new file mode 100755 index 000000000..3d1063d13 --- /dev/null +++ b/src/ac/prlpay @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=PRLPAY $1 $2 $3 $4 $5 $6 diff --git a/src/ac/revs b/src/ac/revs new file mode 100755 index 000000000..b898eb5dc --- /dev/null +++ b/src/ac/revs @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=REVS $1 $2 $3 $4 $5 $6 diff --git a/src/ac/supernet b/src/ac/supernet new file mode 100755 index 000000000..d841ffa0e --- /dev/null +++ b/src/ac/supernet @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=SUPERNET $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/vote2018 b/src/ac/vote2018 similarity index 100% rename from src/fiat/vote2018 rename to src/ac/vote2018 diff --git a/src/ac/wlc b/src/ac/wlc new file mode 100755 index 000000000..ef7c47b90 --- /dev/null +++ b/src/ac/wlc @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=WLC $1 $2 $3 $4 $5 $6 diff --git a/src/amount.cpp b/src/amount.cpp index f658c4a28..4e32ff45b 100644 --- a/src/amount.cpp +++ b/src/amount.cpp @@ -7,7 +7,7 @@ #include "tinyformat.h" -const std::string CURRENCY_UNIT = "ZEC"; +const std::string CURRENCY_UNIT = "KMD"; CFeeRate::CFeeRate(const CAmount& nFeePaid, size_t nSize) { diff --git a/src/assetchains b/src/assetchains index 517687097..4029dc039 100755 --- a/src/assetchains +++ b/src/assetchains @@ -1,9 +1,13 @@ #!/bin/bash + source pubkey.txt +# You can now add delay line to pubkey.txt file + args=("$@") seed_ip=`getent hosts zero.kolo.supernet.org | awk '{ print $1 }'` komodo_binary='./komodod' -delay=20 + +if [ -z "$delay" ]; then delay=20; fi function komodo_asset () { @@ -21,7 +25,14 @@ function komodo_asset () supply=" " fi - $komodo_binary -pubkey=$pubkey -ac_name=$1 $supply -addnode=$seed_ip $gen $args & + if [ -n "$3" ] + then + reward=" -ac_reward=$3" + else + reward=" " + fi + + $komodo_binary -ac_name=$1 $gen $supply $reward $args -pubkey=$pubkey -addnode=$seed_ip & sleep $delay } @@ -47,7 +58,6 @@ komodo_asset MNZ 257142858 komodo_asset AXO 200000000 komodo_asset ETOMIC 100000000 komodo_asset BTCH 20998641 -komodo_asset VOTE2018 600000000 komodo_asset PIZZA 100000000 komodo_asset BEER 100000000 komodo_asset NINJA 100000000 @@ -55,3 +65,8 @@ komodo_asset OOT 216000000 komodo_asset BNTN 500000000 komodo_asset CHAIN 999999 komodo_asset PRLPAY 500000000 +komodo_asset DSEC 7000000 +komodo_asset GLXT 100000000 +komodo_asset EQL 500000000 +komodo_asset ZILLA 11000000 +komodo_asset RFOX 1000000000 100000000 diff --git a/src/assetchains.old b/src/assetchains.old index c025e0430..b8658ab24 100755 --- a/src/assetchains.old +++ b/src/assetchains.old @@ -24,7 +24,6 @@ echo $pubkey ./komodod -pubkey=$pubkey -ac_name=AXO -ac_supply=200000000 -addnode=78.47.196.146 & ./komodod -pubkey=$pubkey -ac_name=ETOMIC -ac_supply=100000000 -addnode=78.47.196.146 & ./komodod -pubkey=$pubkey -ac_name=BTCH -ac_supply=20998641 -addnode=78.47.196.146 & -./komodod -pubkey=$pubkey -ac_name=VOTE2018 -ac_supply=600000000 -addnode=78.47.196.146 & ./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 & @@ -32,68 +31,10 @@ echo $pubkey ./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 & -#sleep $delay +./komodod -pubkey=$pubkey -ac_name=DSEC -ac_supply=7000000 -addnode=185.148.147.30 & +./komodod -pubkey=$pubkey -ac_name=GLXT -ac_supply=100000000 -addnode=13.230.224.15 & +./komodod -pubkey=$pubkey -ac_name=EQL -ac_supply=500000000 -addnode=46.101.124.153 & +./komodod -pubkey=$pubkey -ac_name=ZILLA -ac_supply=11000000 -addnode=54.39.23.248 & +./komodod -pubkey=$pubkey -ac_name=RFOX -ac_supply=1000000000 -ac_reward=100000000 -addnode=78.47.196.146 & +~/VerusCoin/src/komodod -pubkey=$pubkey -ac_name=VRSC -ac_algo=verushash -ac_cc=1 -ac_veruspos=50 -ac_supply=0 -ac_eras=3 -ac_reward=0,38400000000,2400000000 -ac_halving=1,43200,1051920 -ac_decay=100000000,0,0 -ac_end=10080,226080,0 -ac_timelockgte=19200000000 -ac_timeunlockfrom=129600 -ac_timeunlockto=1180800 -addnode=185.25.48.236 -addnode=185.64.105.111 & -#./komodod -pubkey=$pubkey -ac_name=USD -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=EUR -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=JPY -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=GBP -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=AUD -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=CAD -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=CHF -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=NZD -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=CNY -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=RUB -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=MXN -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=BRL -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=INR -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=HKD -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=TRY -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=ZAR -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=PLN -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=NOK -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=SEK -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=DKK -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=CZK -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=HUF -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=ILS -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=KRW -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=MYR -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=PHP -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=RON -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=SGD -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=THB -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=BGN -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=IDR -addnode=78.47.196.146 $1 & -#sleep $delay -#./komodod -pubkey=$pubkey -ac_name=HRK -addnode=78.47.196.146 $1 & diff --git a/src/assetchains_stop b/src/assetchains_stop new file mode 100755 index 000000000..e55231b1a --- /dev/null +++ b/src/assetchains_stop @@ -0,0 +1,40 @@ +#!/bin/bash +args=("$@") +komodo_cli='./komodo-cli' +delay=20 + +function komodo_stop () +{ + $komodo_cli --ac_name=$1 stop +} + +#set -x + +komodo_stop REVS +komodo_stop SUPERNET +komodo_stop DEX +komodo_stop PANGEA +komodo_stop JUMBLR +komodo_stop BET +komodo_stop CRYPTO +komodo_stop HODL +komodo_stop MSHARK +komodo_stop BOTS +komodo_stop MGW +komodo_stop COQUI +komodo_stop WLC +komodo_stop KV +komodo_stop CEAL +komodo_stop MESH +komodo_stop MNZ +komodo_stop AXO +komodo_stop ETOMIC +komodo_stop BTCH +komodo_stop PIZZA +komodo_stop BEER +komodo_stop NINJA +komodo_stop OOT +komodo_stop BNTN +komodo_stop CHAIN +komodo_stop PRLPAY +komodo_stop DSEC diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 178f0baed..bf189e483 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -202,7 +202,7 @@ UniValue CallRPC(const string& strMethod, const UniValue& params) { std::string host = GetArg("-rpcconnect", "127.0.0.1"); int port = GetArg("-rpcport", BaseParams().RPCPort()); - BITCOIND_PORT = port; + BITCOIND_RPCPORT = port; // Obtain event base raii_event_base base = obtain_event_base(); diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index bf4934da4..5c12cfa2f 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -45,6 +45,8 @@ static bool fDaemon; #define KOMODO_ASSETCHAIN_MAXLEN 65 extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; void komodo_passport_iteration(); +uint64_t komodo_interestsum(); +int32_t komodo_longestchain(); void WaitForShutdown(boost::thread_group* threadGroup) { @@ -56,8 +58,14 @@ void WaitForShutdown(boost::thread_group* threadGroup) if ( ASSETCHAINS_SYMBOL[0] == 0 ) { komodo_passport_iteration(); - MilliSleep(1000); - } else MilliSleep(1000); + MilliSleep(10000); + } + else + { + komodo_interestsum(); + komodo_longestchain(); + MilliSleep(20000); + } fShutdown = ShutdownRequested(); } if (threadGroup) @@ -125,7 +133,7 @@ bool AppInit(int argc, char* argv[]) sleep(1); #endif } - printf("initialized %s\n",ASSETCHAINS_SYMBOL); + printf("initialized %s at %u\n",ASSETCHAINS_SYMBOL,(uint32_t)time(NULL)); if (!boost::filesystem::is_directory(GetDataDir(false))) { fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str()); diff --git a/src/cc/betprotocol.cpp b/src/cc/betprotocol.cpp index 53b79176c..9fe9a567d 100644 --- a/src/cc/betprotocol.cpp +++ b/src/cc/betprotocol.cpp @@ -1,9 +1,13 @@ #include +#include "hash.h" +#include "main.h" +#include "chain.h" #include "streams.h" #include "script/cc.h" -#include "cc/eval.h" #include "cc/betprotocol.h" +#include "cc/eval.h" +#include "cc/utils.h" #include "primitives/transaction.h" @@ -137,3 +141,146 @@ bool GetOpReturnHash(CScript script, uint256 &hash) hash = uint256(vHash); return true; } + + +/* + * Crypto-Condition EVAL method that verifies a payout against a transaction + * notarised on another chain. + * + * IN: params - condition params + * IN: importTx - Payout transaction on value chain (KMD) + * IN: nIn - index of input of stake + * + * importTx: Spends stakeTx with payouts from asset chain + * + * in 0: Spends Stake TX and contains ImportPayout CC + * out 0: OP_RETURN MomProof, disputeTx + * out 1-: arbitrary payouts + * + * disputeTx: Spends sessionTx.0 (opener on asset chain) + * + * in 0: spends sessionTx.0 + * in 1-: anything + * out 0: OP_RETURN hash of payouts + * out 1-: anything + */ +bool Eval::ImportPayout(const std::vector params, const CTransaction &importTx, unsigned int nIn) +{ + if (importTx.vout.size() == 0) return Invalid("no-vouts"); + + // load data from vout[0] + MoMProof proof; + CTransaction disputeTx; + { + std::vector vopret; + GetOpReturnData(importTx.vout[0].scriptPubKey, vopret); + if (!E_UNMARSHAL(vopret, ss >> proof; ss >> disputeTx)) + return Invalid("invalid-payload"); + } + + // Check disputeTx.0 shows correct payouts + { + uint256 givenPayoutsHash; + GetOpReturnHash(disputeTx.vout[0].scriptPubKey, givenPayoutsHash); + std::vector payouts(importTx.vout.begin() + 1, importTx.vout.end()); + if (givenPayoutsHash != SerializeHash(payouts)) + return Invalid("wrong-payouts"); + } + + // Check disputeTx spends sessionTx.0 + // condition ImportPayout params is session ID from other chain + { + uint256 sessionHash; + if (!E_UNMARSHAL(params, ss >> sessionHash)) + return Invalid("malformed-params"); + if (disputeTx.vin[0].prevout != COutPoint(sessionHash, 0)) + return Invalid("wrong-session"); + } + + // Check disputeTx solves momproof from vout[0] + { + NotarisationData data(0); + if (!GetNotarisationData(proof.notarisationHash, data)) + return Invalid("coudnt-load-mom"); + + if (data.MoM != proof.branch.Exec(disputeTx.GetHash())) + return Invalid("mom-check-fail"); + } + + return Valid(); +} + + +/* + * Crypto-Condition EVAL method that resolves a dispute of a session + * + * IN: vm - AppVM virtual machine to verify states + * IN: params - condition params + * IN: disputeTx - transaction attempting to resolve dispute + * IN: nIn - index of input of dispute tx + * + * disputeTx: attempt to resolve a dispute + * + * in 0: Spends Session TX first output, reveals DisputeHeader + * out 0: OP_RETURN hash of payouts + */ +bool Eval::DisputePayout(AppVM &vm, std::vector params, const CTransaction &disputeTx, unsigned int nIn) +{ + if (disputeTx.vout.size() == 0) return Invalid("no-vouts"); + + // get payouts hash + uint256 payoutHash; + if (!GetOpReturnHash(disputeTx.vout[0].scriptPubKey, payoutHash)) + return Invalid("invalid-payout-hash"); + + // load params + uint16_t waitBlocks; + std::vector vmParams; + if (!E_UNMARSHAL(params, ss >> VARINT(waitBlocks); ss >> vmParams)) + return Invalid("malformed-params"); + + // ensure that enough time has passed + { + CTransaction sessionTx; + CBlockIndex sessionBlock; + + // if unconformed its too soon + if (!GetTxConfirmed(disputeTx.vin[0].prevout.hash, sessionTx, sessionBlock)) + return Error("couldnt-get-parent"); + + if (GetCurrentHeight() < sessionBlock.nHeight + waitBlocks) + return Invalid("dispute-too-soon"); // Not yet + } + + // get spends + std::vector spends; + if (!GetSpendsConfirmed(disputeTx.vin[0].prevout.hash, spends)) + return Error("couldnt-get-spends"); + + // verify result from VM + int maxLength = -1; + uint256 bestPayout; + for (int i=1; i vmState; + if (spends[i].vout.size() == 0) continue; + if (!GetOpReturnData(spends[i].vout[0].scriptPubKey, vmState)) continue; + auto out = vm.evaluate(vmParams, vmState); + uint256 resultHash = SerializeHash(out.second); + if (out.first > maxLength) { + maxLength = out.first; + bestPayout = resultHash; + } + // The below means that if for any reason there is a draw, the first dispute wins + else if (out.first == maxLength) { + if (bestPayout != payoutHash) { + fprintf(stderr, "WARNING: VM has multiple solutions of same length\n"); + bestPayout = resultHash; + } + } + } + + if (maxLength == -1) return Invalid("no-evidence"); + + return bestPayout == payoutHash ? Valid() : Invalid("wrong-payout"); +} diff --git a/src/cc/betprotocol.h b/src/cc/betprotocol.h index b08783b85..fad33f7ed 100644 --- a/src/cc/betprotocol.h +++ b/src/cc/betprotocol.h @@ -3,7 +3,6 @@ #include "cc/eval.h" #include "pubkey.h" -#include "primitives/block.h" #include "primitives/transaction.h" #include "cryptoconditions/include/cryptoconditions.h" @@ -11,25 +10,18 @@ class MoMProof { public: - int nIndex; - std::vector branch; + MerkleBranch branch; uint256 notarisationHash; - - MoMProof() {} - MoMProof(int i, std::vector b, uint256 n) : notarisationHash(n), nIndex(i), branch(b) {} - uint256 Exec(uint256 hash) const { return CBlock::CheckMerkleBranch(hash, branch, nIndex); } - ADD_SERIALIZE_METHODS; - template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(VARINT(nIndex)); READWRITE(branch); READWRITE(notarisationHash); } }; + class BetProtocol { protected: diff --git a/src/cc/disputepayout.cpp b/src/cc/disputepayout.cpp deleted file mode 100644 index 610342274..000000000 --- a/src/cc/disputepayout.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include - -#include "hash.h" -#include "chain.h" -#include "version.h" -#include "script/cc.h" -#include "cc/eval.h" -#include "cc/betprotocol.h" -#include "primitives/transaction.h" - - -/* - * Crypto-Condition EVAL method that resolves a dispute of a session - * - * IN: vm - AppVM virtual machine to verify states - * IN: params - condition params - * IN: disputeTx - transaction attempting to resolve dispute - * IN: nIn - index of input of dispute tx - * - * disputeTx: attempt to resolve a dispute - * - * in 0: Spends Session TX first output, reveals DisputeHeader - * out 0: OP_RETURN hash of payouts - */ -bool Eval::DisputePayout(AppVM &vm, std::vector params, const CTransaction &disputeTx, unsigned int nIn) -{ - if (disputeTx.vout.size() == 0) return Invalid("no-vouts"); - - // get payouts hash - uint256 payoutHash; - if (!GetOpReturnHash(disputeTx.vout[0].scriptPubKey, payoutHash)) - return Invalid("invalid-payout-hash"); - - // load params - uint16_t waitBlocks; - std::vector vmParams; - if (!E_UNMARSHAL(params, ss >> VARINT(waitBlocks); ss >> vmParams)) - return Invalid("malformed-params"); - - // ensure that enough time has passed - { - CTransaction sessionTx; - CBlockIndex sessionBlock; - - // if unconformed its too soon - if (!GetTxConfirmed(disputeTx.vin[0].prevout.hash, sessionTx, sessionBlock)) - return Error("couldnt-get-parent"); - - if (GetCurrentHeight() < sessionBlock.nHeight + waitBlocks) - return Invalid("dispute-too-soon"); // Not yet - } - - // get spends - std::vector spends; - if (!GetSpendsConfirmed(disputeTx.vin[0].prevout.hash, spends)) - return Error("couldnt-get-spends"); - - // verify result from VM - int maxLength = -1; - uint256 bestPayout; - for (int i=1; i vmState; - if (spends[i].vout.size() == 0) continue; - if (!GetOpReturnData(spends[i].vout[0].scriptPubKey, vmState)) continue; - auto out = vm.evaluate(vmParams, vmState); - uint256 resultHash = SerializeHash(out.second); - if (out.first > maxLength) { - maxLength = out.first; - bestPayout = resultHash; - } - // The below means that if for any reason there is a draw, the first dispute wins - else if (out.first == maxLength) { - if (bestPayout != payoutHash) { - fprintf(stderr, "WARNING: VM has multiple solutions of same length\n"); - bestPayout = resultHash; - } - } - } - - if (maxLength == -1) return Invalid("no-evidence"); - - return bestPayout == payoutHash ? Valid() : Invalid("wrong-payout"); -} diff --git a/src/cc/eval.cpp b/src/cc/eval.cpp index 3c53f9866..25550d1e2 100644 --- a/src/cc/eval.cpp +++ b/src/cc/eval.cpp @@ -1,12 +1,15 @@ #include #include +#include "primitives/block.h" #include "primitives/transaction.h" #include "script/cc.h" #include "cc/eval.h" +#include "cc/utils.h" #include "main.h" #include "chain.h" #include "core_io.h" +#include "crosschain.h" Eval* EVAL_TEST = 0; @@ -14,9 +17,7 @@ Eval* EVAL_TEST = 0; bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn) { - Eval eval_; - Eval *eval = EVAL_TEST; - if (!eval) eval = &eval_; + EvalRef eval; bool out = eval->Dispatch(cond, tx, nIn); assert(eval->state.IsValid() == out); @@ -49,6 +50,10 @@ bool Eval::Dispatch(const CC *cond, const CTransaction &txTo, unsigned int nIn) return ImportPayout(vparams, txTo, nIn); } + if (ecode == EVAL_IMPORTCOIN) { + return ImportCoin(vparams, txTo, nIn); + } + return Invalid("invalid-code"); } @@ -144,7 +149,7 @@ bool Eval::CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t t /* - * Get MoM from a notarisation tx hash + * Get MoM from a notarisation tx hash (on KMD) */ bool Eval::GetNotarisationData(const uint256 notaryHash, NotarisationData &data) const { @@ -152,54 +157,84 @@ bool Eval::GetNotarisationData(const uint256 notaryHash, NotarisationData &data) CBlockIndex block; if (!GetTxConfirmed(notaryHash, notarisationTx, block)) return false; if (!CheckNotaryInputs(notarisationTx, block.nHeight, block.nTime)) return false; - if (notarisationTx.vout.size() < 2) return false; - if (!data.Parse(notarisationTx.vout[1].scriptPubKey)) return false; + if (!ParseNotarisationOpReturn(notarisationTx, data)) return false; return true; } +/* + * Get MoMoM corresponding to a notarisation tx hash (on assetchain) + */ +bool Eval::GetProofRoot(uint256 kmdNotarisationHash, uint256 &momom) const +{ + std::pair out; + if (!GetNextBacknotarisation(kmdNotarisationHash, out)) return false; + momom = out.second.MoMoM; + return true; +} + + +uint32_t Eval::GetAssetchainsCC() const +{ + return ASSETCHAINS_CC; +} + + +std::string Eval::GetAssetchainsSymbol() const +{ + return std::string(ASSETCHAINS_SYMBOL); +} + /* * Notarisation data, ie, OP_RETURN payload in notarisation transactions */ -extern char ASSETCHAINS_SYMBOL[16]; - -bool NotarisationData::Parse(const CScript scriptPK) +bool ParseNotarisationOpReturn(const CTransaction &tx, NotarisationData &data) { - *this = NotarisationData(); - + if (tx.vout.size() < 2) return false; std::vector vdata; - if (!GetOpReturnData(scriptPK, vdata)) return false; - - CDataStream ss(vdata, SER_NETWORK, PROTOCOL_VERSION); - - try { - ss >> blockHash; - ss >> height; - if (ASSETCHAINS_SYMBOL[0]) - ss >> txHash; - - char *nullPos = (char*) memchr(&ss[0], 0, ss.size()); - if (!nullPos) return false; - ss.read(symbol, nullPos-&ss[0]+1); - - if (ss.size() < 36) return false; - ss >> MoM; - ss >> MoMDepth; - } catch (...) { - return false; - } - return true; + if (!GetOpReturnData(tx.vout[1].scriptPubKey, vdata)) return false; + bool out = E_UNMARSHAL(vdata, ss >> data); + return out; } /* * Misc */ - std::string EvalToStr(EvalCode c) { FOREACH_EVAL(EVAL_GENERATE_STRING); char s[10]; sprintf(s, "0x%x", c); return std::string(s); + +} + + +uint256 SafeCheckMerkleBranch(uint256 hash, const std::vector& vMerkleBranch, int nIndex) +{ + if (nIndex == -1) + return uint256(); + for (auto it(vMerkleBranch.begin()); it != vMerkleBranch.end(); ++it) + { + if (nIndex & 1) { + if (*it == hash) { + // non canonical. hash may be equal to node but never on the right. + return uint256(); + } + hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash)); + } + else + hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it)); + nIndex >>= 1; + } + return hash; +} + + +uint256 GetMerkleRoot(const std::vector& vLeaves) +{ + bool fMutated; + std::vector vMerkleTree; + return BuildMerkleTree(&fMutated, vLeaves, vMerkleTree); } diff --git a/src/cc/eval.h b/src/cc/eval.h index f998c9f3d..0eef563a3 100644 --- a/src/cc/eval.h +++ b/src/cc/eval.h @@ -3,6 +3,7 @@ #include +#include "cc/utils.h" #include "chain.h" #include "streams.h" #include "version.h" @@ -20,8 +21,10 @@ * a possible code is EVAL_BITCOIN_SCRIPT, where the entire binary * after the code is interpreted as a bitcoin script. */ -#define FOREACH_EVAL(EVAL) \ - EVAL(EVAL_IMPORTPAYOUT, 0xe1) +#define FOREACH_EVAL(EVAL) \ + EVAL(EVAL_IMPORTPAYOUT, 0xe1) \ + EVAL(EVAL_IMPORTCOIN, 0xe2) + typedef uint8_t EvalCode; @@ -54,6 +57,11 @@ public: */ bool ImportPayout(std::vector params, const CTransaction &importTx, unsigned int nIn); + /* + * Import coin from another chain with same symbol + */ + bool ImportCoin(std::vector params, const CTransaction &importTx, unsigned int nIn); + /* * IO functions */ @@ -64,10 +72,30 @@ 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; }; +extern Eval* EVAL_TEST; + + +/* + * Get a pointer to an Eval to use + */ +typedef std::unique_ptr EvalRef_; +class EvalRef : public EvalRef_ +{ +public: + EvalRef() : EvalRef_( + EVAL_TEST ? EVAL_TEST : new Eval(), + [](Eval* e){if (e!=EVAL_TEST) delete e;}) { } +}; + + + bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn); @@ -88,22 +116,92 @@ public: }; -/* - * Data from notarisation OP_RETURN - */ -class NotarisationData { -public: - uint256 blockHash; - uint32_t height; - uint256 txHash; // Only get this guy in asset chains not in KMD - char symbol[64]; - uint256 MoM; - uint32_t MoMDepth; +extern char ASSETCHAINS_SYMBOL[65]; - bool Parse(CScript scriptPubKey); + +/* + * Data from notarisation OP_RETURN from chain being notarised + */ +class NotarisationData +{ +public: + int IsBackNotarisation = 0; + uint256 blockHash = uint256(); + uint32_t height = 0; + uint256 txHash = uint256(); + char symbol[64]; + uint256 MoM = uint256(); + uint16_t MoMDepth = 0; + uint16_t ccId = 0; + uint256 MoMoM = uint256(); + uint32_t MoMoMDepth = 0; + + NotarisationData(int IsBack=2) : IsBackNotarisation(IsBack) { + symbol[0] = '\0'; + } + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + + bool IsBack = IsBackNotarisation; + if (2 == IsBackNotarisation) IsBack = DetectBackNotarisation(s, ser_action); + + READWRITE(blockHash); + READWRITE(height); + if (IsBack) + READWRITE(txHash); + SerSymbol(s, ser_action); + if (s.size() == 0) return; + READWRITE(MoM); + READWRITE(MoMDepth); + READWRITE(ccId); + if (s.size() == 0) return; + if (IsBack) { + READWRITE(MoMoM); + READWRITE(MoMoMDepth); + } + } + + template + void SerSymbol(Stream& s, CSerActionSerialize act) + { + s.write(symbol, strlen(symbol)+1); + } + + template + void SerSymbol(Stream& s, CSerActionUnserialize act) + { + size_t readlen = std::min(sizeof(symbol), s.size()); + char *nullPos = (char*) memchr(&s[0], 0, readlen); + if (!nullPos) + throw std::ios_base::failure("couldn't parse symbol"); + s.read(symbol, nullPos-&s[0]+1); + } + + template + bool DetectBackNotarisation(Stream& s, CSerActionUnserialize act) + { + if (ASSETCHAINS_SYMBOL[0]) return 1; + if (s.size() >= 72) { + if (strcmp("BTC", &s[68]) == 0) return 1; + if (strcmp("KMD", &s[68]) == 0) return 1; + } + return 0; + } + + template + bool DetectBackNotarisation(Stream& s, CSerActionSerialize act) + { + return !txHash.IsNull(); + } }; +bool ParseNotarisationOpReturn(const CTransaction &tx, NotarisationData &data); + + /* * Eval code utilities. */ @@ -116,28 +214,42 @@ std::string EvalToStr(EvalCode c); /* - * Serialisation boilerplate + * Merkle stuff */ -#define E_MARSHAL(body) SerializeF([&] (CDataStream &ss) {body;}) -template -std::vector SerializeF(const T f) -{ - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - f(ss); - return std::vector(ss.begin(), ss.end()); -} +uint256 SafeCheckMerkleBranch(uint256 hash, const std::vector& vMerkleBranch, int nIndex); -#define E_UNMARSHAL(params, body) DeserializeF(params, [&] (CDataStream &ss) {body;}) -template -bool DeserializeF(const std::vector vIn, T f) + +class MerkleBranch { - CDataStream ss(vIn, SER_NETWORK, PROTOCOL_VERSION); - try { - f(ss); - if (ss.eof()) return true; - } catch(...) {} - return false; -} +public: + int nIndex; + std::vector branch; + + MerkleBranch() {} + MerkleBranch(int i, std::vector b) : nIndex(i), branch(b) {} + uint256 Exec(uint256 hash) const { return SafeCheckMerkleBranch(hash, branch, nIndex); } + + MerkleBranch& operator<<(MerkleBranch append) + { + nIndex += append.nIndex << branch.size(); + branch.insert(branch.end(), append.branch.begin(), append.branch.end()); + return *this; + } + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(VARINT(nIndex)); + READWRITE(branch); + } +}; + + +typedef std::pair TxProof; + + +uint256 GetMerkleRoot(const std::vector& vLeaves); #endif /* CC_EVAL_H */ diff --git a/src/cc/import.cpp b/src/cc/import.cpp new file mode 100644 index 000000000..5f0b804e8 --- /dev/null +++ b/src/cc/import.cpp @@ -0,0 +1,72 @@ +#include "cc/eval.h" +#include "cc/utils.h" +#include "importcoin.h" +#include "primitives/transaction.h" + + +/* + * CC Eval method for import coin. + * + * This method should control every parameter of the ImportCoin transaction, since it has no signature + * to protect it from malleability. + */ +bool Eval::ImportCoin(const std::vector params, const CTransaction &importTx, unsigned int nIn) +{ + if (importTx.vout.size() < 2) + return Invalid("too-few-vouts"); + + // params + TxProof proof; + CTransaction burnTx; + std::vector payouts; + + if (!UnmarshalImportTx(importTx, proof, burnTx, payouts)) + return Invalid("invalid-params"); + + // Control all aspects of this transaction + // It should not be at all malleable + if (MakeImportCoinTransaction(proof, burnTx, payouts).GetHash() != importTx.GetHash()) + return Invalid("non-canonical"); + + // burn params + uint32_t targetCcid; + std::string targetSymbol; + uint256 payoutsHash; + + if (!UnmarshalBurnTx(burnTx, targetSymbol, &targetCcid, payoutsHash)) + return Invalid("invalid-burn-tx"); + + if (targetCcid != GetAssetchainsCC() || targetSymbol != GetAssetchainsSymbol()) + return Invalid("importcoin-wrong-chain"); + + // check burn amount + { + uint64_t burnAmount = burnTx.vout[0].nValue; + if (burnAmount == 0) + return Invalid("invalid-burn-amount"); + uint64_t totalOut = 0; + for (int i=0; i burnAmount) + return Invalid("payout-too-high"); + } + + // Check burntx shows correct outputs hash + if (payoutsHash != SerializeHash(payouts)) + return Invalid("wrong-payouts"); + + // 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())) + return Invalid("momom-check-fail"); + } + + return Valid(); +} + + diff --git a/src/cc/importpayout.cpp b/src/cc/importpayout.cpp deleted file mode 100644 index 1363eb924..000000000 --- a/src/cc/importpayout.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include - -#include "main.h" -#include "chain.h" -#include "streams.h" -#include "cc/eval.h" -#include "cc/betprotocol.h" -#include "primitives/transaction.h" - - -/* - * Crypto-Condition EVAL method that verifies a payout against a transaction - * notarised on another chain. - * - * IN: params - condition params - * IN: importTx - Payout transaction on value chain (KMD) - * IN: nIn - index of input of stake - * - * importTx: Spends stakeTx with payouts from asset chain - * - * in 0: Spends Stake TX and contains ImportPayout CC - * out 0: OP_RETURN MomProof, disputeTx - * out 1-: arbitrary payouts - * - * disputeTx: Spends sessionTx.0 (opener on asset chain) - * - * in 0: spends sessionTx.0 - * in 1-: anything - * out 0: OP_RETURN hash of payouts - * out 1-: anything - */ -bool Eval::ImportPayout(const std::vector params, const CTransaction &importTx, unsigned int nIn) -{ - if (importTx.vout.size() == 0) return Invalid("no-vouts"); - - // load data from vout[0] - MoMProof proof; - CTransaction disputeTx; - { - std::vector vopret; - GetOpReturnData(importTx.vout[0].scriptPubKey, vopret); - if (!E_UNMARSHAL(vopret, ss >> proof; ss >> disputeTx)) - return Invalid("invalid-payload"); - } - - // Check disputeTx.0 shows correct payouts - { - uint256 givenPayoutsHash; - GetOpReturnHash(disputeTx.vout[0].scriptPubKey, givenPayoutsHash); - std::vector payouts(importTx.vout.begin() + 1, importTx.vout.end()); - if (givenPayoutsHash != SerializeHash(payouts)) - return Invalid("wrong-payouts"); - } - - // Check disputeTx spends sessionTx.0 - // condition ImportPayout params is session ID from other chain - { - uint256 sessionHash; - if (!E_UNMARSHAL(params, ss >> sessionHash)) - return Invalid("malformed-params"); - if (disputeTx.vin[0].prevout != COutPoint(sessionHash, 0)) - return Invalid("wrong-session"); - } - - // Check disputeTx solves momproof from vout[0] - { - NotarisationData data; - if (!GetNotarisationData(proof.notarisationHash, data)) - return Invalid("coudnt-load-mom"); - - if (data.MoM != proof.Exec(disputeTx.GetHash())) - return Invalid("mom-check-fail"); - } - - return Valid(); -} diff --git a/src/cc/utils.cpp b/src/cc/utils.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cc/utils.h b/src/cc/utils.h new file mode 100644 index 000000000..5704016e4 --- /dev/null +++ b/src/cc/utils.h @@ -0,0 +1,34 @@ +#ifndef CC_UTILS_H +#define CC_UTILS_H + +#include "streams.h" +#include "version.h" + + +/* + * Serialisation boilerplate + */ + +template +std::vector SerializeF(const T f) +{ + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + f(ss); + return std::vector(ss.begin(), ss.end()); +} + +template +bool DeserializeF(const std::vector vIn, T f) +{ + CDataStream ss(vIn, SER_NETWORK, PROTOCOL_VERSION); + try { + f(ss); + if (ss.eof()) return true; + } catch(...) {} + return false; +} + +#define E_MARSHAL(body) SerializeF([&] (CDataStream &ss) {body;}) +#define E_UNMARSHAL(params, body) DeserializeF(params, [&] (CDataStream &ss) {body;}) + +#endif /* CC_UTILS_H */ diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 49c4a2244..d48d32c93 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -79,7 +79,7 @@ void *chainparams_commandline(void *ptr); #include "komodo_defs.h" extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -extern uint16_t ASSETCHAINS_PORT; +extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; extern uint32_t ASSETCHAIN_INIT; extern uint32_t ASSETCHAINS_MAGIC; extern uint64_t ASSETCHAINS_SUPPLY; @@ -173,6 +173,8 @@ public: base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x88)(0xAD)(0xE4).convert_to_container >(); // guarantees the first two characters, when base58 encoded, are "zc" base58Prefixes[ZCPAYMENT_ADDRRESS] = {22,154}; + // guarantees the first 4 characters, when base58 encoded, are "ZiVK" + base58Prefixes[ZCVIEWING_KEY] = {0xA8,0xAB,0xD3}; // guarantees the first two characters, when base58 encoded, are "SK" base58Prefixes[ZCSPENDING_KEY] = {171,54}; @@ -209,7 +211,7 @@ void CChainParams::SetCheckpointData(CChainParams::CCheckpointData checkpointDat void *chainparams_commandline(void *ptr) { CChainParams::CCheckpointData checkpointData; - while ( ASSETCHAINS_PORT == 0 ) + while ( ASSETCHAINS_P2PPORT == 0 ) { #ifdef _WIN32 boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); @@ -217,15 +219,17 @@ void *chainparams_commandline(void *ptr) sleep(1); #endif } - //fprintf(stderr,">>>>>>>> port.%u\n",ASSETCHAINS_PORT); + //fprintf(stderr,">>>>>>>> port.%u\n",ASSETCHAINS_P2PPORT); if ( ASSETCHAINS_SYMBOL[0] != 0 ) { - mainParams.SetDefaultPort(ASSETCHAINS_PORT); + mainParams.SetDefaultPort(ASSETCHAINS_P2PPORT); + if ( ASSETCHAINS_RPCPORT == 0 ) + ASSETCHAINS_RPCPORT = ASSETCHAINS_P2PPORT + 1; mainParams.pchMessageStart[0] = ASSETCHAINS_MAGIC & 0xff; mainParams.pchMessageStart[1] = (ASSETCHAINS_MAGIC >> 8) & 0xff; mainParams.pchMessageStart[2] = (ASSETCHAINS_MAGIC >> 16) & 0xff; mainParams.pchMessageStart[3] = (ASSETCHAINS_MAGIC >> 24) & 0xff; - fprintf(stderr,">>>>>>>>>> %s: port.%u/%u magic.%08x %u %u coins\n",ASSETCHAINS_SYMBOL,ASSETCHAINS_PORT,ASSETCHAINS_PORT+1,ASSETCHAINS_MAGIC,ASSETCHAINS_MAGIC,(uint32_t)ASSETCHAINS_SUPPLY); + fprintf(stderr,">>>>>>>>>> %s: p2p.%u rpc.%u magic.%08x %u %u coins\n",ASSETCHAINS_SYMBOL,ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,ASSETCHAINS_MAGIC,ASSETCHAINS_MAGIC,(uint32_t)ASSETCHAINS_SUPPLY); checkpointData = //(Checkpoints::CCheckpointData) { @@ -465,6 +469,8 @@ public: base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container >(); base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container >(); base58Prefixes[ZCPAYMENT_ADDRRESS] = {20,81}; + // guarantees the first 4 characters, when base58 encoded, are "ZiVt" + base58Prefixes[ZCVIEWING_KEY] = {0xA8,0xAC,0x0C}; base58Prefixes[ZCSPENDING_KEY] = {177,235}; vFixedSeeds = std::vector(pnSeed6_test, pnSeed6_test + ARRAYLEN(pnSeed6_test)); @@ -530,11 +536,18 @@ public: BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K)); nEquihashN = N; nEquihashK = K; - genesis.nTime = 1296688602; - genesis.nBits = KOMODO_MINDIFF_NBITS; - genesis.nNonce = uint256S("0x0000000000000000000000000000000000000000000000000000000000000021"); - genesis.nSolution = ParseHex("0f2a976db4c4263da10fd5d38eb1790469cf19bdb4bf93450e09a72fdff17a3454326399"); + + genesis = CreateGenesisBlock( + 1296688602, + uint256S("0x0000000000000000000000000000000000000000000000000000000000000009"), + ParseHex("01936b7db1eb4ac39f151b8704642d0a8bda13ec547d54cd5e43ba142fc6d8877cab07b3"), + + + KOMODO_MINDIFF_NBITS, 4, 0); consensus.hashGenesisBlock = genesis.GetHash(); + assert(consensus.hashGenesisBlock == uint256S("0x029f11d80ef9765602235e1bc9727e3eb6ba20839319f761fee920d63401e327")); + assert(genesis.hashMerkleRoot == uint256S("0xc4eaa58879081de3c24a7b117ed2b28300e7ec4c4c1dff1d3f1268b7857a4ddb")); + nDefaultPort = 17779; nPruneAfterHeight = 1000; diff --git a/src/coins.cpp b/src/coins.cpp index bb40af9cc..b2d838506 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -9,6 +9,7 @@ #include "version.h" #include "policy/fees.h" #include "komodo_defs.h" +#include "importcoin.h" #include @@ -392,11 +393,13 @@ extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t *interestp,const CTransaction& tx,uint32_t tiptime) const { + CAmount value,nResult = 0; if ( interestp != 0 ) *interestp = 0; + if ( tx.IsCoinImport() ) + return GetCoinImportValue(tx); if ( tx.IsCoinBase() != 0 ) return 0; - CAmount value,nResult = 0; for (unsigned int i = 0; i < tx.vin.size(); i++) { value = GetOutputFor(tx.vin[i]).nValue; @@ -421,6 +424,7 @@ CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t *interestp,const CTr return nResult; } + bool CCoinsViewCache::HaveJoinSplitRequirements(const CTransaction& tx) const { boost::unordered_map intermediates; @@ -457,11 +461,12 @@ bool CCoinsViewCache::HaveJoinSplitRequirements(const CTransaction& tx) const bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const { - if (!tx.IsCoinBase()) { + if (!tx.IsMint()) { for (unsigned int i = 0; i < tx.vin.size(); i++) { const COutPoint &prevout = tx.vin[i].prevout; const CCoins* coins = AccessCoins(prevout.hash); if (!coins || !coins->IsAvailable(prevout.n)) { + fprintf(stderr,"HaveInputs missing input %s/v%d\n",prevout.hash.ToString().c_str(),prevout.n); return false; } } @@ -482,6 +487,9 @@ double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight) const if (tx.vjoinsplit.size() > 0) { return MAX_PRIORITY; } + if (tx.IsCoinImport()) { + return MAX_PRIORITY; + } double dResult = 0.0; BOOST_FOREACH(const CTxIn& txin, tx.vin) diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index d2e7dec3f..c2972e598 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -17,7 +17,7 @@ static const int32_t OVERWINTER_MAX_TX_VERSION = 3; /** The maximum allowed size for a serialized block, in bytes (network rule) */ static const unsigned int MAX_BLOCK_SIZE = 2000000; /** The maximum allowed number of signature check operations in a block (network rule) */ -static const unsigned int MAX_BLOCK_SIGOPS = 20000; +extern unsigned int MAX_BLOCK_SIGOPS; /** The maximum size of a transaction (network rule) */ static const unsigned int MAX_TX_SIZE = 100000; /** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */ diff --git a/src/crosschain.cpp b/src/crosschain.cpp new file mode 100644 index 000000000..ca7223abb --- /dev/null +++ b/src/crosschain.cpp @@ -0,0 +1,336 @@ +#include "cc/eval.h" +#include "crosschain.h" +#include "importcoin.h" +#include "main.h" +#include "notarisationdb.h" + +/* + * The crosschain workflow. + * + * 3 chains, A, B, and KMD. We would like to prove TX on B. + * There is a notarisation, nA0, which will include TX via an MoM. + * The notarisation nA0 must fall between 2 notarisations of B, + * ie, nB0 and nB1. An MoMoM including this range is propagated to + * B in notarisation receipt (backnotarisation) bnB2. + * + * A: TX bnA0 + * \ / + * KMD: nB0 nA0 nB1 nB2 + * \ \ \ + * B: bnB0 bnB1 bnB2 + */ + +// XXX: There are potential crashes wherever we access chainActive without a lock, +// because it might be disconnecting blocks at the same time. + + +int NOTARISATION_SCAN_LIMIT_BLOCKS = 1440; + + +/* On KMD */ +uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeight, + std::vector &moms, uint256 &destNotarisationTxid) +{ + /* + * Notaries don't wait for confirmation on KMD before performing a backnotarisation, + * but we need a determinable range that will encompass all merkle roots. Include MoMs + * including the block height of the last notarisation until the height before the + * previous notarisation. + * + * kmdHeight notarisations-0 notarisations-1 + * *********************| + * > scan backwards > + */ + + if (targetCCid <= 1) + return uint256(); + + if (kmdHeight < 0 || kmdHeight > chainActive.Height()) + return uint256(); + + int seenOwnNotarisations = 0; + + for (int i=0; i kmdHeight) break; + NotarisationsInBlock notarisations; + uint256 blockHash = *chainActive[kmdHeight-i]->phashBlock; + if (!GetBlockNotarisations(blockHash, notarisations)) + continue; + + // See if we have an own notarisation in this block + BOOST_FOREACH(Notarisation& nota, notarisations) { + if (strcmp(nota.second.symbol, symbol) == 0) + { + seenOwnNotarisations++; + if (seenOwnNotarisations == 1) + destNotarisationTxid = nota.first; + else if (seenOwnNotarisations == 2) + goto end; + break; + } + } + + if (seenOwnNotarisations == 1) { + BOOST_FOREACH(Notarisation& nota, notarisations) { + if (nota.second.ccId == targetCCid) + moms.push_back(nota.second.MoM); + } + } + } + +end: + return GetMerkleRoot(moms); +} + + +/* + * Get a notarisation from a given height + * + * Will scan notarisations leveldb up to a limit + */ +template +int ScanNotarisationsFromHeight(int nHeight, const IsTarget f, Notarisation &found) +{ + int limit = std::min(nHeight + NOTARISATION_SCAN_LIMIT_BLOCKS, chainActive.Height()); + + for (int h=nHeight; hphashBlock, notarisations)) + continue; + + BOOST_FOREACH(found, notarisations) { + if (f(found)) { + return h; + } + } + } + return 0; +} + + +/* On KMD */ +TxProof GetCrossChainProof(const uint256 txid, const char* targetSymbol, uint32_t targetCCid, + const TxProof assetChainProof) +{ + /* + * Here we are given a proof generated by an assetchain A which goes from given txid to + * an assetchain MoM. We need to go from the notarisationTxid for A to the MoMoM range of the + * backnotarisation for B (given by kmdheight of notarisation), find the MoM within the MoMs for + * that range, and finally extend the proof to lead to the MoMoM (proof root). + */ + EvalRef eval; + uint256 MoM = assetChainProof.second.Exec(txid); + + // Get a kmd height for given notarisation Txid + int kmdHeight; + { + CTransaction sourceNotarisation; + uint256 hashBlock; + CBlockIndex blockIdx; + if (!eval->GetTxConfirmed(assetChainProof.first, sourceNotarisation, blockIdx)) + throw std::runtime_error("Notarisation not found"); + kmdHeight = blockIdx.nHeight; + } + + // We now have a kmdHeight of the notarisation from chain A. So we know that a MoM exists + // at that height. + // If we call CalculateProofRoot with that height, it'll scan backwards, until it finds + // a notarisation from B, and it might not include our notarisation from A + // at all. So, the thing we need to do is scan forwards to find the notarisation for B, + // that is inclusive of A. + Notarisation nota; + auto isTarget = [&](Notarisation ¬a) { + return strcmp(nota.second.symbol, targetSymbol) == 0; + }; + kmdHeight = ScanNotarisationsFromHeight(kmdHeight, isTarget, nota); + if (!kmdHeight) + throw std::runtime_error("Cannot find notarisation for target inclusive of source"); + + // Get MoMs for kmd height and symbol + std::vector moms; + uint256 targetChainNotarisationTxid; + 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 vBranch; + { + CBlock fakeBlock; + for (int i=0; i payouts; + if (!UnmarshalImportTx(importTx, proof, burnTx, payouts)) + throw std::runtime_error("Couldn't parse importTx"); + + std::string targetSymbol; + uint32_t targetCCid; + uint256 payoutsHash; + if (!UnmarshalBurnTx(burnTx, targetSymbol, &targetCCid, payoutsHash)) + throw std::runtime_error("Couldn't parse burnTx"); + + proof = GetCrossChainProof(burnTx.GetHash(), targetSymbol.data(), targetCCid, proof); + + importTx = MakeImportCoinTransaction(proof, burnTx, payouts); +} + + +bool IsSameAssetChain(const Notarisation ¬a) { + return strcmp(nota.second.symbol, ASSETCHAINS_SYMBOL) == 0; +}; + + +/* On assetchain */ +bool GetNextBacknotarisation(uint256 kmdNotarisationTxid, Notarisation &out) +{ + /* + * Here we are given a txid, and a proof. + * We go from the KMD notarisation txid to the backnotarisation, + * then jump to the next backnotarisation, which contains the corresponding MoMoM. + */ + Notarisation bn; + if (!GetBackNotarisation(kmdNotarisationTxid, 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; + } + + return (bool) ScanNotarisationsFromHeight(block.nHeight+1, &IsSameAssetChain, out); +} + + +/* + * On assetchain + * in: txid + * out: pair + */ +TxProof GetAssetchainProof(uint256 hash) +{ + int nIndex; + CBlockIndex* blockIndex; + Notarisation nota; + std::vector branch; + + { + uint256 blockHash; + CTransaction tx; + if (!GetTransaction(hash, tx, blockHash, true)) + throw std::runtime_error("cannot find transaction"); + + if (blockHash.IsNull()) + throw std::runtime_error("tx still in mempool"); + + blockIndex = mapBlockIndex[blockHash]; + int h = blockIndex->nHeight; + // The assumption here is that the first notarisation for a height GTE than + // the transaction block height will contain the corresponding MoM. If there + // are sequence issues with the notarisations this may fail. + auto isTarget = [&](Notarisation ¬a) { + if (!IsSameAssetChain(nota)) return false; + return nota.second.height >= blockIndex->nHeight; + }; + if (!ScanNotarisationsFromHeight(blockIndex->nHeight, isTarget, nota)) + throw std::runtime_error("backnotarisation not yet confirmed"); + + // index of block in MoM leaves + nIndex = nota.second.height - blockIndex->nHeight; + } + + // build merkle chain from blocks to MoM + { + std::vector leaves, tree; + for (int i=0; ihashMerkleRoot; + leaves.push_back(mRoot); + } + bool fMutated; + BuildMerkleTree(&fMutated, leaves, tree); + branch = GetMerkleBranch(nIndex, leaves.size(), tree); + + // Check branch + uint256 ourResult = SafeCheckMerkleBranch(blockIndex->hashMerkleRoot, branch, nIndex); + if (nota.second.MoM != ourResult) + throw std::runtime_error("Failed merkle block->MoM"); + } + + // Now get the tx merkle branch + { + CBlock block; + + if (fHavePruned && !(blockIndex->nStatus & BLOCK_HAVE_DATA) && blockIndex->nTx > 0) + throw std::runtime_error("Block not available (pruned data)"); + + if(!ReadBlockFromDisk(block, blockIndex,1)) + throw std::runtime_error("Can't read block from disk"); + + // Locate the transaction in the block + int nTxIndex; + for (nTxIndex = 0; nTxIndex < (int)block.vtx.size(); nTxIndex++) + if (block.vtx[nTxIndex].GetHash() == hash) + break; + + if (nTxIndex == (int)block.vtx.size()) + throw std::runtime_error("Error locating tx in block"); + + std::vector txBranch = block.GetMerkleBranch(nTxIndex); + + // Check branch + if (block.hashMerkleRoot != CBlock::CheckMerkleBranch(hash, txBranch, nTxIndex)) + throw std::runtime_error("Failed merkle tx->block"); + + // concatenate branches + nIndex = (nIndex << txBranch.size()) + nTxIndex; + branch.insert(branch.begin(), txBranch.begin(), txBranch.end()); + } + + // Check the proof + if (nota.second.MoM != CBlock::CheckMerkleBranch(hash, branch, nIndex)) + throw std::runtime_error("Failed validating MoM"); + + // All done! + CDataStream ssProof(SER_NETWORK, PROTOCOL_VERSION); + return std::make_pair(nota.second.txHash, MerkleBranch(nIndex, branch)); +} diff --git a/src/crosschain.h b/src/crosschain.h new file mode 100644 index 000000000..15452ac63 --- /dev/null +++ b/src/crosschain.h @@ -0,0 +1,21 @@ +#ifndef CROSSCHAIN_H +#define CROSSCHAIN_H + +#include "cc/eval.h" + + +/* On assetchain */ +TxProof GetAssetchainProof(uint256 hash); + +/* On KMD */ +uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeight, + std::vector &moms, uint256 &destNotarisationTxid); +TxProof GetCrossChainProof(const uint256 txid, const char* targetSymbol, uint32_t targetCCid, + const TxProof assetChainProof); +void CompleteImportTransaction(CTransaction &importTx); + +/* On assetchain */ +bool GetNextBacknotarisation(uint256 txid, std::pair &bn); + + +#endif /* CROSSCHAIN_H */ diff --git a/src/cryptoconditions/src/cryptoconditions.c b/src/cryptoconditions/src/cryptoconditions.c index 2f136917e..6fd54f245 100644 --- a/src/cryptoconditions/src/cryptoconditions.c +++ b/src/cryptoconditions/src/cryptoconditions.c @@ -13,7 +13,12 @@ #include "src/eval.c" #include "src/json_rpc.c" #include -#include + +#ifdef __LP64__ +#include +#else +#include // Index into CTransaction.vjoinsplit +#endif struct CCType *CCTypeRegistry[] = { diff --git a/src/cryptoconditions/src/json_rpc.c b/src/cryptoconditions/src/json_rpc.c index 42c13612c..13cffec1d 100644 --- a/src/cryptoconditions/src/json_rpc.c +++ b/src/cryptoconditions/src/json_rpc.c @@ -1,8 +1,12 @@ #include "cryptoconditions.h" #include "internal.h" #include -#include +#ifdef __LP64__ +#include +#else +#include // Index into CTransaction.vjoinsplit +#endif static cJSON *jsonCondition(CC *cond) { cJSON *root = cJSON_CreateObject(); diff --git a/src/cryptoconditions/src/secp256k1.c b/src/cryptoconditions/src/secp256k1.c index 73f7a9164..78b9c4e9e 100644 --- a/src/cryptoconditions/src/secp256k1.c +++ b/src/cryptoconditions/src/secp256k1.c @@ -1,6 +1,11 @@ #define _GNU_SOURCE 1 +#if __linux #include +#elif defined(_WIN32) || defined(_WIN64) +#include +#endif + #include #include diff --git a/src/deprecation.cpp b/src/deprecation.cpp index 9f394e720..73ff8046d 100644 --- a/src/deprecation.cpp +++ b/src/deprecation.cpp @@ -11,12 +11,13 @@ #include "chainparams.h" static const std::string CLIENT_VERSION_STR = FormatVersion(CLIENT_VERSION); +extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; void EnforceNodeDeprecation(int nHeight, bool forceLogging) { // Do not enforce deprecation in regtest or on testnet std::string networkID = Params().NetworkIDString(); - if (networkID != "main") return; + if (networkID != "main" || ASSETCHAINS_SYMBOL[0] != 0 ) return; int blocksToDeprecation = DEPRECATION_HEIGHT - nHeight; bool disableDeprecation = (GetArg("-disabledeprecation", "") == CLIENT_VERSION_STR); @@ -58,4 +59,4 @@ void EnforceNodeDeprecation(int nHeight, bool forceLogging) { LogPrintf("*** %s\n", msg); uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_WARNING); } -} \ No newline at end of file +} diff --git a/src/dpowassets b/src/dpowassets index 14bb39912..f9d86dd57 100755 --- a/src/dpowassets +++ b/src/dpowassets @@ -2,9 +2,9 @@ set -x source pubkey.txt echo $pubkey +sleep 3 - -curl --url "http://127.0.0.1:7776" --data "{\"timeout\":60000,\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"REVS\",\"pubkey\":\"$pubkey\"}" +curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"REVS\",\"pubkey\":\"$pubkey\"}" curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"SUPERNET\",\"pubkey\":\"$pubkey\"}" curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"DEX\",\"pubkey\":\"$pubkey\"}" @@ -22,14 +22,19 @@ curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dp curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"CEAL\",\"pubkey\":\"$pubkey\"}" curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"MESH\",\"pubkey\":\"$pubkey\"}" curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"MNZ\",\"pubkey\":\"$pubkey\"}" -curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"CHIPS\",\"pubkey\":\"$pubkey\"}" curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"AXO\",\"pubkey\":\"$pubkey\"}" curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"ETOMIC\",\"pubkey\":\"$pubkey\"}" curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"BTCH\",\"pubkey\":\"$pubkey\"}" curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"CHAIN\",\"pubkey\":\"$pubkey\"}" -curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"VOTE2018\",\"pubkey\":\"$pubkey\"}" curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"NINJA\",\"pubkey\":\"$pubkey\"}" curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"OOT\",\"pubkey\":\"$pubkey\"}" curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"BNTN\",\"pubkey\":\"$pubkey\"}" curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"PRLPAY\",\"pubkey\":\"$pubkey\"}" - +curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"DSEC\",\"pubkey\":\"$pubkey\"}" +curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"GLXT\",\"pubkey\":\"$pubkey\"}" +curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"EQL\",\"pubkey\":\"$pubkey\"}" +curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"ZILLA\",\"pubkey\":\"$pubkey\"}" +curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"CHIPS\",\"pubkey\":\"$pubkey\"}" +curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"GAME\",\"freq\":5,\"pubkey\":\"$pubkey\"}" +curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"RFOX\",\"freq\":10,\"pubkey\":\"$pubkey\"}" +curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"VRSC\",\"freq\":10,\"pubkey\":\"$pubkey\"}" diff --git a/src/fiat-cli b/src/fiat-cli index ce2e7a51d..2838575f9 100755 --- a/src/fiat-cli +++ b/src/fiat-cli @@ -22,9 +22,14 @@ echo etomic; fiat/etomic $1 $2 $3 $4 echo btch; fiat/btch $1 $2 $3 $4 echo pizza; fiat/pizza $1 $2 $3 $4 echo beer; fiat/beer $1 $2 $3 $4 -echo vote2018; fiat/vote2018 $1 $2 $3 $4 echo ninja; fiat/ninja $1 $2 $3 $4 echo oot; fiat/oot $1 $2 $3 $4 echo bntn; fiat/bntn $1 $2 $3 $4 echo chain; fiat/chain $1 $2 $3 $4 echo prlpay; fiat/prlpay $1 $2 $3 $4 +echo dsec; fiat/dsec $1 $2 $3 $4 +echo glxt; fiat/glxt $1 $2 $3 $4 +echo eql; fiat/eql $1 $2 $3 $4 +echo zilla; fiat/zilla $1 $2 $3 $4 +echo vrsc; fiat/vrsc $1 $2 $3 $4 +echo rfox; fiat/rfox $1 $2 $3 $4 diff --git a/src/fiat/dsec b/src/fiat/dsec new file mode 100755 index 000000000..a050ca94f --- /dev/null +++ b/src/fiat/dsec @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=DSEC $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/eql b/src/fiat/eql new file mode 100755 index 000000000..99cfa9a09 --- /dev/null +++ b/src/fiat/eql @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=EQL $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/glxt b/src/fiat/glxt new file mode 100755 index 000000000..6cedfbf87 --- /dev/null +++ b/src/fiat/glxt @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=GLXT $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/rfox b/src/fiat/rfox new file mode 100755 index 000000000..e082505d0 --- /dev/null +++ b/src/fiat/rfox @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=RFOX $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/vrsc b/src/fiat/vrsc new file mode 100755 index 000000000..6cd4dd1fb --- /dev/null +++ b/src/fiat/vrsc @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=VRSC $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/zilla b/src/fiat/zilla new file mode 100755 index 000000000..d8c713369 --- /dev/null +++ b/src/fiat/zilla @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=ZILLA $1 $2 $3 $4 $5 $6 diff --git a/src/gtest/test_checkblock.cpp b/src/gtest/test_checkblock.cpp index e098cfdae..284cff134 100644 --- a/src/gtest/test_checkblock.cpp +++ b/src/gtest/test_checkblock.cpp @@ -22,6 +22,7 @@ public: MOCK_CONST_METHOD0(GetRejectReason, std::string()); }; +int32_t futureblock; TEST(CheckBlock, VersionTooLow) { auto verifier = libzcash::ProofVerifier::Strict(); @@ -30,7 +31,7 @@ TEST(CheckBlock, VersionTooLow) { MockCValidationState state; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "version-too-low", false)).Times(1); - EXPECT_FALSE(CheckBlock(0,0,block, state, verifier, false, false)); + EXPECT_FALSE(CheckBlock(&futureblock,0,0,block, state, verifier, false, false)); } @@ -230,4 +231,4 @@ TEST(ContextualCheckBlock, BlockOverwinterRulesRejectSproutTx) { // Revert to default UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); -} \ No newline at end of file +} diff --git a/src/importcoin.cpp b/src/importcoin.cpp new file mode 100644 index 000000000..8b87cb535 --- /dev/null +++ b/src/importcoin.cpp @@ -0,0 +1,121 @@ +#include "crosschain.h" +#include "importcoin.h" +#include "cc/utils.h" +#include "coins.h" +#include "hash.h" +#include "script/cc.h" +#include "primitives/transaction.h" + + +CTransaction MakeImportCoinTransaction(const TxProof proof, const CTransaction burnTx, const std::vector payouts) +{ + std::vector payload = E_MARSHAL(ss << EVAL_IMPORTCOIN); + CMutableTransaction mtx; + mtx.vin.push_back(CTxIn(COutPoint(burnTx.GetHash(), 10e8), CScript() << payload)); + mtx.vout = payouts; + auto importData = E_MARSHAL(ss << proof; ss << burnTx); + mtx.vout.insert(mtx.vout.begin(), CTxOut(0, CScript() << OP_RETURN << importData)); + return CTransaction(mtx); +} + + +CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector payouts) +{ + std::vector opret = E_MARSHAL(ss << VARINT(targetCCid); + ss << targetSymbol; + ss << SerializeHash(payouts)); + return CTxOut(value, CScript() << OP_RETURN << opret); +} + + +bool UnmarshalImportTx(const CTransaction &importTx, TxProof &proof, CTransaction &burnTx, + std::vector &payouts) +{ + std::vector vData; + GetOpReturnData(importTx.vout[0].scriptPubKey, vData); + if (importTx.vout.size() < 1) return false; + payouts = std::vector(importTx.vout.begin()+1, importTx.vout.end()); + return importTx.vin.size() == 1 && + importTx.vin[0].scriptSig == (CScript() << E_MARSHAL(ss << EVAL_IMPORTCOIN)) && + E_UNMARSHAL(vData, ss >> proof; ss >> burnTx); +} + + +bool UnmarshalBurnTx(const CTransaction &burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash) +{ + std::vector burnOpret; + if (burnTx.vout.size() == 0) return false; + GetOpReturnData(burnTx.vout[0].scriptPubKey, burnOpret); + return E_UNMARSHAL(burnOpret, ss >> VARINT(*targetCCid); + ss >> targetSymbol; + ss >> payoutsHash); +} + + +/* + * Required by main + */ +CAmount GetCoinImportValue(const CTransaction &tx) +{ + TxProof proof; + CTransaction burnTx; + std::vector payouts; + if (UnmarshalImportTx(tx, proof, burnTx, payouts)) { + return burnTx.vout.size() ? burnTx.vout[0].nValue : 0; + } + return 0; +} + + +/* + * CoinImport is different enough from normal script execution that it's not worth + * making all the mods neccesary in the interpreter to do the dispatch correctly. + */ +bool VerifyCoinImport(const CScript& scriptSig, TransactionSignatureChecker& checker, CValidationState &state) +{ + auto pc = scriptSig.begin(); + opcodetype opcode; + std::vector evalScript; + + auto f = [&] () { + if (!scriptSig.GetOp(pc, opcode, evalScript)) + return false; + if (pc != scriptSig.end()) + return false; + if (evalScript.size() == 0) + return false; + if (evalScript.begin()[0] != EVAL_IMPORTCOIN) + return false; + // Ok, all looks good so far... + CC *cond = CCNewEval(evalScript); + bool out = checker.CheckEvalCondition(cond); + cc_free(cond); + return out; + }; + + return f() ? true : state.Invalid(false, 0, "invalid-coin-import"); +} + + +void AddImportTombstone(const CTransaction &importTx, CCoinsViewCache &inputs, int nHeight) +{ + uint256 burnHash = importTx.vin[0].prevout.hash; + CCoinsModifier modifier = inputs.ModifyCoins(burnHash); + modifier->nHeight = nHeight; + modifier->nVersion = 1; + modifier->vout.push_back(CTxOut(0, CScript() << OP_0)); +} + + +void RemoveImportTombstone(const CTransaction &importTx, CCoinsViewCache &inputs) +{ + uint256 burnHash = importTx.vin[0].prevout.hash; + inputs.ModifyCoins(burnHash)->Clear(); +} + + +int ExistsImportTombstone(const CTransaction &importTx, const CCoinsViewCache &inputs) +{ + uint256 burnHash = importTx.vin[0].prevout.hash; + return inputs.HaveCoins(burnHash); +} diff --git a/src/importcoin.h b/src/importcoin.h new file mode 100644 index 000000000..f62bb45a1 --- /dev/null +++ b/src/importcoin.h @@ -0,0 +1,28 @@ +#ifndef IMPORTCOIN_H +#define IMPORTCOIN_H + +#include "cc/eval.h" +#include "coins.h" +#include "primitives/transaction.h" +#include "script/interpreter.h" +#include + + +CAmount GetCoinImportValue(const CTransaction &tx); + +CTransaction MakeImportCoinTransaction(const TxProof proof, + const CTransaction burnTx, const std::vector payouts); + +CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector payouts); + +bool UnmarshalBurnTx(const CTransaction &burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash); +bool UnmarshalImportTx(const CTransaction &importTx, TxProof &proof, CTransaction &burnTx, + std::vector &payouts); + +bool VerifyCoinImport(const CScript& scriptSig, TransactionSignatureChecker& checker, CValidationState &state); + +void AddImportTombstone(const CTransaction &importTx, CCoinsViewCache &inputs, int nHeight); +void RemoveImportTombstone(const CTransaction &importTx, CCoinsViewCache &inputs); +int ExistsImportTombstone(const CTransaction &importTx, const CCoinsViewCache &inputs); + +#endif /* IMPORTCOIN_H */ diff --git a/src/init.cpp b/src/init.cpp index 7027ede54..52c919421 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -21,6 +21,7 @@ #include "httpserver.h" #include "httprpc.h" #include "key.h" +#include "notarisationdb.h" #include "main.h" #include "metrics.h" #include "miner.h" @@ -1413,11 +1414,14 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) delete pcoinsdbview; delete pcoinscatcher; delete pblocktree; + delete pnotarisations; pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex, dbCompression, dbMaxOpenFiles); pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex); pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview); pcoinsTip = new CCoinsViewCache(pcoinscatcher); + pnotarisations = new NotarisationDB(100*1024*1024, false, fReindex); + if (fReindex) { pblocktree->WriteReindexing(true); @@ -1442,7 +1446,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) break; } KOMODO_LOADINGBLOCKS = 0; - // Check for changed -txindex state if (fTxIndex != GetBoolArg("-txindex", true)) { strLoadError = _("You need to rebuild the database using -reindex to change -txindex"); diff --git a/src/komodo.h b/src/komodo.h index 829d64ec2..ae0898ed3 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2017 The SuperNET Developers. * + * Copyright © 2014-2018 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -54,6 +54,7 @@ int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char #include "komodo_jumblr.h" #include "komodo_gateway.h" #include "komodo_events.h" +#include "komodo_ccdata.h" void komodo_currentheight_set(int32_t height) { @@ -112,7 +113,7 @@ int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char if ( fread(&MoMdepth,1,sizeof(MoMdepth),fp) != sizeof(MoMdepth) ) errs++; if ( 1 && ASSETCHAINS_SYMBOL[0] != 0 && sp != 0 ) - printf("%s load[%s.%d -> %s] NOTARIZED %d %s MoM.%s %d\n",ASSETCHAINS_SYMBOL,symbol,sp->NUM_NPOINTS,dest,notarized_height,notarized_hash.ToString().c_str(),MoM.ToString().c_str(),MoMdepth); + printf("%s load[%s.%d -> %s] NOTARIZED %d %s MoM.%s %d CCid.%u\n",ASSETCHAINS_SYMBOL,symbol,sp->NUM_NPOINTS,dest,notarized_height,notarized_hash.ToString().c_str(),MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff); } else { @@ -200,8 +201,7 @@ int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char komodo_eventadd_pricefeed(sp,symbol,ht,pvals,numpvals); //printf("load pvals ht.%d numpvals.%d\n",ht,numpvals); } else printf("error loading pvals[%d]\n",numpvals); - } - else printf("[%s] %s illegal func.(%d %c)\n",ASSETCHAINS_SYMBOL,symbol,func,func); + } // else printf("[%s] %s illegal func.(%d %c)\n",ASSETCHAINS_SYMBOL,symbol,func,func); return(func); } else return(-1); } @@ -258,7 +258,7 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long if ( memread(&MoMdepth,sizeof(MoMdepth),filedata,&fpos,datalen) != sizeof(MoMdepth) ) errs++; if ( 1 && ASSETCHAINS_SYMBOL[0] != 0 && sp != 0 ) - printf("%s load[%s.%d -> %s] NOTARIZED %d %s MoM.%s %d\n",ASSETCHAINS_SYMBOL,symbol,sp->NUM_NPOINTS,dest,notarized_height,notarized_hash.ToString().c_str(),MoM.ToString().c_str(),MoMdepth); + printf("%s load[%s.%d -> %s] NOTARIZED %d %s MoM.%s %d CCid.%u\n",ASSETCHAINS_SYMBOL,symbol,sp->NUM_NPOINTS,dest,notarized_height,notarized_hash.ToString().c_str(),MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff); } else { @@ -311,7 +311,7 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long { if ( memread(opret,olen,filedata,&fpos,datalen) != olen ) errs++; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && matched != 0 ) + if ( 1 && ASSETCHAINS_SYMBOL[0] != 0 && matched != 0 ) { int32_t i; for (i=0; iMoMdepth > 0 && sp->MoM != zero ) + if ( sp->MoMdepth != 0 && sp->MoM != zero ) fputc('M',fp); else fputc('N',fp); if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) @@ -491,7 +491,7 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar errs++; if ( fwrite(&sp->NOTARIZED_DESTTXID,1,sizeof(sp->NOTARIZED_DESTTXID),fp) != sizeof(sp->NOTARIZED_DESTTXID) ) errs++; - if ( sp->MoMdepth > 0 && sp->MoM != zero ) + if ( sp->MoMdepth != 0 && sp->MoM != zero ) { if ( fwrite(&sp->MoM,1,sizeof(sp->MoM),fp) != sizeof(sp->MoM) ) errs++; @@ -505,15 +505,40 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar } } +int32_t komodo_validate_chain(uint256 srchash,int32_t notarized_height) +{ + static int32_t last_rewind; int32_t rewindtarget; CBlockIndex *pindex; struct komodo_state *sp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; + if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) + return(0); + if ( IsInitialBlockDownload() == 0 && ((pindex= mapBlockIndex[srchash]) == 0 || pindex->nHeight != notarized_height) ) + { + if ( sp->NOTARIZED_HEIGHT > 0 && sp->NOTARIZED_HEIGHT < notarized_height ) + rewindtarget = sp->NOTARIZED_HEIGHT - 1; + else if ( notarized_height > 101 ) + rewindtarget = notarized_height - 101; + else rewindtarget = 0; + if ( rewindtarget != 0 && rewindtarget > KOMODO_REWIND && rewindtarget > last_rewind ) + { + if ( last_rewind != 0 ) + { + //KOMODO_REWIND = rewindtarget; + fprintf(stderr,"%s FORK detected. notarized.%d %s not in this chain! last notarization %d -> rewindtarget.%d\n",ASSETCHAINS_SYMBOL,notarized_height,srchash.ToString().c_str(),sp->NOTARIZED_HEIGHT,rewindtarget); + } + last_rewind = rewindtarget; + } + return(0); + } else return(1); +} + int32_t komodo_voutupdate(int32_t *isratificationp,int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i,int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp,uint64_t value,int32_t notarized,uint64_t signedmask,uint32_t timestamp) { static uint256 zero; static FILE *signedfp; - int32_t opretlen,nid,k,len = 0; uint256 srchash,desttxid; uint8_t crypto777[33]; struct komodo_state *sp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; + int32_t opretlen,nid,offset,k,MoMdepth,matched,len = 0; uint256 MoM,srchash,desttxid; uint8_t crypto777[33]; struct komodo_state *sp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) return(-1); if ( scriptlen == 35 && scriptbuf[0] == 33 && scriptbuf[34] == 0xac ) { - if ( i == 0 && j == 0 && memcmp(NOTARY_PUBKEY33,scriptbuf+1,33) == 0 && NOTARY_PUBKEY33[0] != 0 ) + if ( i == 0 && j == 0 && memcmp(NOTARY_PUBKEY33,scriptbuf+1,33) == 0 && IS_KOMODO_NOTARY != 0 ) { printf("%s KOMODO_LASTMINED.%d -> %d\n",ASSETCHAINS_SYMBOL,KOMODO_LASTMINED,height); prevKOMODO_LASTMINED = KOMODO_LASTMINED; @@ -555,6 +580,8 @@ int32_t komodo_voutupdate(int32_t *isratificationp,int32_t notaryid,uint8_t *scr } if ( scriptbuf[len++] == 0x6a ) { + struct komodo_ccdata ccdata; struct komodo_ccdataMoMoM MoMoMdata; + int32_t validated = 0,nameoffset,opoffset = 0; if ( (opretlen= scriptbuf[len++]) == 0x4c ) opretlen = scriptbuf[len++]; else if ( opretlen == 0x4d ) @@ -562,96 +589,158 @@ int32_t komodo_voutupdate(int32_t *isratificationp,int32_t notaryid,uint8_t *scr opretlen = scriptbuf[len++]; opretlen += (scriptbuf[len++] << 8); } - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - printf("[%s] notarized.%d notarizedht.%d sp.Nht %d sp.ht %d opretlen.%d (%c %c %c)\n",ASSETCHAINS_SYMBOL,notarized,*notarizedheightp,sp->NOTARIZED_HEIGHT,sp->CURRENT_HEIGHT,opretlen,scriptbuf[len+32*2+4],scriptbuf[len+32*2+4+1],scriptbuf[len+32*2+4+2]); - if ( j == 1 && opretlen >= 32*2+4 && strcmp(ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,(char *)&scriptbuf[len+32*2+4]) == 0 ) + opoffset = len; + matched = 0; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) { + if ( strcmp("KMD",(char *)&scriptbuf[len+32 * 2 + 4]) == 0 ) + matched = 1; + } + else + { + if ( scriptbuf[len] == 'K' ) + { + fprintf(stderr,"i.%d j.%d KV OPRET len.%d %.8f\n",i,j,opretlen,dstr(value)); + komodo_stateupdate(height,0,0,0,txhash,0,0,0,0,0,0,value,&scriptbuf[len],opretlen,j,zero,0); + return(-1); + } + if ( strcmp(ASSETCHAINS_SYMBOL,(char *)&scriptbuf[len+32*2+4]) == 0 ) + matched = 1; + } + offset = 32 * (1 + matched) + 4; + nameoffset = (int32_t)strlen((char *)&scriptbuf[len+offset]); + nameoffset++; + memset(&ccdata,0,sizeof(ccdata)); + strncpy(ccdata.symbol,(char *)&scriptbuf[len+offset],sizeof(ccdata.symbol)); + if ( j == 1 && opretlen >= len+offset-opoffset ) + { + memset(&MoMoMdata,0,sizeof(MoMoMdata)); + if ( matched == 0 && bitweight(signedmask) >= KOMODO_MINRATIFY ) + notarized = 1; + if ( strcmp("PIZZA",ccdata.symbol) == 0 || strncmp("TXSCL",ccdata.symbol,5) == 0 ) + notarized = 1; + if ( 0 && opretlen != 149 ) + printf("[%s].%d (%s) matched.%d i.%d j.%d notarized.%d %llx opretlen.%d len.%d offset.%d opoffset.%d\n",ASSETCHAINS_SYMBOL,height,ccdata.symbol,matched,i,j,notarized,(long long)signedmask,opretlen,len,offset,opoffset); len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&srchash); len += iguana_rwnum(0,&scriptbuf[len],sizeof(*notarizedheightp),(uint8_t *)notarizedheightp); - len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&desttxid); - if ( strcmp("PIZZA",ASSETCHAINS_SYMBOL) == 0 && opretlen == 110 ) + if ( matched != 0 ) + len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&desttxid); + if ( matched != 0 ) + validated = komodo_validate_chain(srchash,*notarizedheightp); + else validated = 1; + if ( notarized != 0 && validated != 0 ) { - notarized = 1; - } - static int32_t last_rewind; - int32_t rewindtarget,validated = 0; - CBlockIndex *pindex;// - if ( IsInitialBlockDownload() == 0 && ((pindex= mapBlockIndex[srchash]) == 0 || pindex->nHeight != *notarizedheightp) ) - { - if ( sp->NOTARIZED_HEIGHT > 0 && sp->NOTARIZED_HEIGHT < *notarizedheightp ) - rewindtarget = sp->NOTARIZED_HEIGHT - 1; - else if ( *notarizedheightp > 101 ) - rewindtarget = *notarizedheightp - 101; - else rewindtarget = 0; - if ( rewindtarget != 0 && rewindtarget > KOMODO_REWIND && rewindtarget > last_rewind ) + //sp->NOTARIZED_HEIGHT = *notarizedheightp; + //sp->NOTARIZED_HASH = srchash; + //sp->NOTARIZED_DESTTXID = desttxid; + memset(&MoM,0,sizeof(MoM)); + MoMdepth = 0; + len += nameoffset; + ccdata.MoMdata.notarized_height = *notarizedheightp; + ccdata.MoMdata.height = height; + ccdata.MoMdata.txi = i; + //printf("nameoffset.%d len.%d + 36 %d opoffset.%d vs opretlen.%d\n",nameoffset,len,len+36,opoffset,opretlen); + if ( len+36-opoffset <= opretlen ) { - if ( last_rewind != 0 ) + len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&MoM); + len += iguana_rwnum(0,&scriptbuf[len],sizeof(MoMdepth),(uint8_t *)&MoMdepth); + ccdata.MoMdata.MoM = MoM; + ccdata.MoMdata.MoMdepth = MoMdepth & 0xffff; + if ( len+sizeof(ccdata.CCid)-opoffset <= opretlen ) { - //KOMODO_REWIND = rewindtarget; - fprintf(stderr,"%s FORK detected. notarized.%d %s not in this chain! last notarization %d -> rewindtarget.%d\n",ASSETCHAINS_SYMBOL,*notarizedheightp,srchash.ToString().c_str(),sp->NOTARIZED_HEIGHT,rewindtarget); + len += iguana_rwnum(0,&scriptbuf[len],sizeof(ccdata.CCid),(uint8_t *)&ccdata.CCid); + //if ( ((MoMdepth>>16) & 0xffff) != (ccdata.CCid & 0xffff) ) + // fprintf(stderr,"%s CCid mismatch %u != %u\n",ASSETCHAINS_SYMBOL,((MoMdepth>>16) & 0xffff),(ccdata.CCid & 0xffff)); + ccdata.len = sizeof(ccdata.CCid); + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + { + // MoMoM, depth, numpairs, (notarization ht, MoMoM offset) + if ( len+48-opoffset <= opretlen && strcmp(ccdata.symbol,ASSETCHAINS_SYMBOL) == 0 ) + { + len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.kmdstarti); + len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.kmdendi); + len += iguana_rwbignum(0,&scriptbuf[len],sizeof(MoMoMdata.MoMoM),(uint8_t *)&MoMoMdata.MoMoM); + len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.MoMoMdepth); + len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.numpairs); + MoMoMdata.len += sizeof(MoMoMdata.MoMoM) + sizeof(uint32_t)*4; + if ( len+MoMoMdata.numpairs*8-opoffset == opretlen ) + { + MoMoMdata.pairs = (struct komodo_ccdatapair *)calloc(MoMoMdata.numpairs,sizeof(*MoMoMdata.pairs)); + for (k=0; k sp->NOTARIZED_HEIGHT && *notarizedheightp < height && validated != 0 ) - { - int32_t nameoffset = (int32_t)strlen(ASSETCHAINS_SYMBOL) + 1; - sp->NOTARIZED_HEIGHT = *notarizedheightp; - sp->NOTARIZED_HASH = srchash; - sp->NOTARIZED_DESTTXID = desttxid; - memset(&sp->MoM,0,sizeof(sp->MoM)); - sp->MoMdepth = 0; - if ( len+36 <= opretlen ) - { - len += iguana_rwbignum(0,&scriptbuf[len+nameoffset],32,(uint8_t *)&sp->MoM); - len += iguana_rwnum(0,&scriptbuf[len+nameoffset],sizeof(sp->MoMdepth),(uint8_t *)&sp->MoMdepth); - if ( sp->MoM == zero || sp->MoMdepth > 1440 || sp->MoMdepth < 0 ) + if ( MoM == zero || (MoMdepth&0xffff) > *notarizedheightp || (MoMdepth&0xffff) < 0 ) { - memset(&sp->MoM,0,sizeof(sp->MoM)); - sp->MoMdepth = 0; + memset(&MoM,0,sizeof(MoM)); + MoMdepth = 0; } else { - //printf("VALID %s MoM.%s [%d]\n",ASSETCHAINS_SYMBOL,sp->MoM.ToString().c_str(),sp->MoMdepth); + komodo_rwccdata(ASSETCHAINS_SYMBOL,1,&ccdata,&MoMoMdata); + if ( matched != 0 ) + printf("[%s] matched.%d VALID (%s) MoM.%s [%d] CCid.%u\n",ASSETCHAINS_SYMBOL,matched,ccdata.symbol,MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff); } + if ( MoMoMdata.pairs != 0 ) + free(MoMoMdata.pairs); + memset(&ccdata,0,sizeof(ccdata)); + memset(&MoMoMdata,0,sizeof(MoMoMdata)); } - komodo_stateupdate(height,0,0,0,zero,0,0,0,0,0,0,0,0,0,0,sp->MoM,sp->MoMdepth); - len += nameoffset; - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - printf("[%s] ht.%d NOTARIZED.%d %s.%s %sTXID.%s lens.(%d %d) MoM.%s %d\n",ASSETCHAINS_SYMBOL,height,*notarizedheightp,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),ASSETCHAINS_SYMBOL[0]==0?"BTC":"KMD",desttxid.ToString().c_str(),opretlen,len,sp->MoM.ToString().c_str(),sp->MoMdepth); - if ( ASSETCHAINS_SYMBOL[0] == 0 ) + else if ( ASSETCHAINS_SYMBOL[0] == 0 && matched != 0 && notarized != 0 && validated != 0 ) + komodo_rwccdata((char *)"KMD",1,&ccdata,0); + if ( matched != 0 && *notarizedheightp > sp->NOTARIZED_HEIGHT && *notarizedheightp < height ) { - if ( signedfp == 0 ) + sp->NOTARIZED_HEIGHT = *notarizedheightp; + sp->NOTARIZED_HASH = srchash; + sp->NOTARIZED_DESTTXID = desttxid; + if ( MoM != zero && (MoMdepth&0xffff) > 0 ) { - char fname[512]; - komodo_statefname(fname,ASSETCHAINS_SYMBOL,(char *)"signedmasks"); - if ( (signedfp= fopen(fname,"rb+")) == 0 ) - signedfp = fopen(fname,"wb"); - else fseek(signedfp,0,SEEK_END); + sp->MoM = MoM; + sp->MoMdepth = MoMdepth; } - if ( signedfp != 0 ) + komodo_stateupdate(height,0,0,0,zero,0,0,0,0,0,0,0,0,0,0,sp->MoM,sp->MoMdepth); + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + printf("[%s] ht.%d NOTARIZED.%d %s.%s %sTXID.%s lens.(%d %d) MoM.%s %d\n",ASSETCHAINS_SYMBOL,height,*notarizedheightp,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),ASSETCHAINS_SYMBOL[0]==0?"BTC":"KMD",desttxid.ToString().c_str(),opretlen,len,sp->MoM.ToString().c_str(),sp->MoMdepth); + if ( ASSETCHAINS_SYMBOL[0] == 0 ) { - fwrite(&height,1,sizeof(height),signedfp); - fwrite(&signedmask,1,sizeof(signedmask),signedfp); - fflush(signedfp); - } - if ( opretlen > len && scriptbuf[len] == 'A' ) - { - //for (i=0; i len && scriptbuf[len] == 'A' ) + { + //for (i=0; iNOTARIZED_HEIGHT ) - printf("validated.%d notarized.%d %llx reject ht.%d NOTARIZED.%d prev.%d %s.%s DESTTXID.%s (%s) len.%d opretlen.%d\n",validated,notarized,(long long)signedmask,height,*notarizedheightp,sp->NOTARIZED_HEIGHT,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),desttxid.ToString().c_str(),(char *)&scriptbuf[len],len,opretlen); + } else if ( opretlen != 149 && height > 600000 && matched != 0 ) + printf("%s validated.%d notarized.%d %llx reject ht.%d NOTARIZED.%d prev.%d %s.%s DESTTXID.%s len.%d opretlen.%d\n",ccdata.symbol,validated,notarized,(long long)signedmask,height,*notarizedheightp,sp->NOTARIZED_HEIGHT,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),desttxid.ToString().c_str(),len,opretlen); } - else if ( i == 0 && j == 1 && opretlen == 149 ) + else if ( matched != 0 && i == 0 && j == 1 && opretlen == 149 ) { if ( notaryid >= 0 && notaryid < 64 ) komodo_paxpricefeed(height,&scriptbuf[len],opretlen); } - else + else if ( matched != 0 ) { //int32_t k; for (k=0; knHeight != hwmheight ) + { printf("%s hwmheight.%d vs pindex->nHeight.%d t.%u reorg.%d\n",ASSETCHAINS_SYMBOL,hwmheight,pindex->nHeight,(uint32_t)pindex->nTime,hwmheight-pindex->nHeight); + komodo_purge_ccdata((int32_t)pindex->nHeight); + hwmheight = pindex->nHeight; + } komodo_event_rewind(sp,symbol,pindex->nHeight); komodo_stateupdate(pindex->nHeight,0,0,0,zero,0,0,0,0,-pindex->nHeight,pindex->nTime,0,0,0,0,zero,0); } @@ -786,7 +879,7 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block) } notarized = 1; } - if ( NOTARY_PUBKEY33[0] != 0 && ASSETCHAINS_SYMBOL[0] == 0 ) + if ( IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 ) printf("(tx.%d: ",i); for (j=0; j= sizeof(uint32_t) && len <= sizeof(scriptbuf) ) @@ -823,7 +916,7 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block) } } } - if ( NOTARY_PUBKEY33[0] != 0 && ASSETCHAINS_SYMBOL[0] == 0 ) + if ( IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 ) printf(") "); if ( 0 && ASSETCHAINS_SYMBOL[0] == 0 ) printf("[%s] ht.%d txi.%d signedmask.%llx numvins.%d numvouts.%d notarized.%d special.%d isratification.%d\n",ASSETCHAINS_SYMBOL,height,i,(long long)signedmask,numvins,numvouts,notarized,specialtx,isratification); @@ -866,7 +959,7 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block) } } } - if ( NOTARY_PUBKEY33[0] != 0 && ASSETCHAINS_SYMBOL[0] == 0 ) + if ( IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 ) printf("%s ht.%d\n",ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL,height); if ( pindex->nHeight == hwmheight ) komodo_stateupdate(height,0,0,0,zero,0,0,0,0,height,(uint32_t)pindex->nTime,0,0,0,0,zero,0); diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index e9a379abc..0e8d8ddfd 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -411,7 +411,7 @@ int32_t komodo_verifynotarizedscript(int32_t height,uint8_t *script,int32_t len, for (i=0; i<32; i++) ((uint8_t *)&hash)[i] = script[2+i]; if ( hash == NOTARIZED_HASH ) - return(0); + return(1); for (i=0; i<32; i++) printf("%02x",((uint8_t *)&NOTARIZED_HASH)[i]); printf(" notarized, "); @@ -504,7 +504,7 @@ int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t uint256 hash; char params[128],*hexstr,*jsonstr; cJSON *result; int32_t i; uint8_t revbuf[32]; memset(&hash,0,sizeof(hash)); sprintf(params,"[%d]",height); - if ( (jsonstr= komodo_issuemethod(KMDUSERPASS,(char *)"getblockhash",params,BITCOIND_PORT)) != 0 ) + if ( (jsonstr= komodo_issuemethod(KMDUSERPASS,(char *)"getblockhash",params,BITCOIND_RPCPORT)) != 0 ) { if ( (result= cJSON_Parse(jsonstr)) != 0 ) { @@ -592,7 +592,6 @@ void komodo_disconnect(CBlockIndex *pindex,CBlock& block) } else printf("komodo_disconnect: ht.%d cant get komodo_state.(%s)\n",pindex->nHeight,ASSETCHAINS_SYMBOL); } - int32_t komodo_is_notarytx(const CTransaction& tx) { uint8_t *ptr; static uint8_t crypto777[33]; @@ -659,7 +658,7 @@ int32_t komodo_block2height(CBlock *block) return(height); } -void komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block) +int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block) { int32_t n; if ( KOMODO_LOADINGBLOCKS == 0 ) @@ -675,8 +674,12 @@ void komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block) //komodo_init(0); n = block->vtx[0].vout[0].scriptPubKey.size(); if ( n == 35 ) + { memcpy(pubkey33,ptr+1,33); + return(1); + } } + return(0); } int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex) @@ -725,45 +728,45 @@ uint32_t komodo_heightstamp(int32_t height) } /*void komodo_pindex_init(CBlockIndex *pindex,int32_t height) gets data corrupted - { - int32_t i,num; uint8_t pubkeys[64][33]; CBlock block; - if ( pindex->didinit != 0 ) - return; - //printf("pindex.%d komodo_pindex_init notary.%d from height.%d\n",pindex->nHeight,pindex->notaryid,height); - if ( pindex->didinit == 0 ) - { - pindex->notaryid = -1; - if ( KOMODO_LOADINGBLOCKS == 0 ) - memset(pindex->pubkey33,0xff,33); - else memset(pindex->pubkey33,0,33); - if ( komodo_blockload(block,pindex) == 0 ) - { - komodo_block2pubkey33(pindex->pubkey33,&block); - //for (i=0; i<33; i++) - // fprintf(stderr,"%02x",pindex->pubkey33[i]); - //fprintf(stderr," set pubkey at height %d/%d\n",pindex->nHeight,height); - //if ( pindex->pubkey33[0] == 2 || pindex->pubkey33[0] == 3 ) - // pindex->didinit = (KOMODO_LOADINGBLOCKS == 0); - } // else fprintf(stderr,"error loading block at %d/%d",pindex->nHeight,height); - } - if ( pindex->didinit != 0 && pindex->nHeight >= 0 && (num= komodo_notaries(pubkeys,(int32_t)pindex->nHeight,(uint32_t)pindex->nTime)) > 0 ) - { - for (i=0; ipubkey33,33) == 0 ) - { - pindex->notaryid = i; - break; - } - } - if ( 0 && i == num ) - { - for (i=0; i<33; i++) - fprintf(stderr,"%02x",pindex->pubkey33[i]); - fprintf(stderr," unmatched pubkey at height %d/%d\n",pindex->nHeight,height); - } - } - }*/ +{ + int32_t i,num; uint8_t pubkeys[64][33]; CBlock block; + if ( pindex->didinit != 0 ) + return; + //printf("pindex.%d komodo_pindex_init notary.%d from height.%d\n",pindex->nHeight,pindex->notaryid,height); + if ( pindex->didinit == 0 ) + { + pindex->notaryid = -1; + if ( KOMODO_LOADINGBLOCKS == 0 ) + memset(pindex->pubkey33,0xff,33); + else memset(pindex->pubkey33,0,33); + if ( komodo_blockload(block,pindex) == 0 ) + { + komodo_block2pubkey33(pindex->pubkey33,&block); + //for (i=0; i<33; i++) + // fprintf(stderr,"%02x",pindex->pubkey33[i]); + //fprintf(stderr," set pubkey at height %d/%d\n",pindex->nHeight,height); + //if ( pindex->pubkey33[0] == 2 || pindex->pubkey33[0] == 3 ) + // pindex->didinit = (KOMODO_LOADINGBLOCKS == 0); + } // else fprintf(stderr,"error loading block at %d/%d",pindex->nHeight,height); + } + if ( pindex->didinit != 0 && pindex->nHeight >= 0 && (num= komodo_notaries(pubkeys,(int32_t)pindex->nHeight,(uint32_t)pindex->nTime)) > 0 ) + { + for (i=0; ipubkey33,33) == 0 ) + { + pindex->notaryid = i; + break; + } + } + if ( 0 && i == num ) + { + for (i=0; i<33; i++) + fprintf(stderr,"%02x",pindex->pubkey33[i]); + fprintf(stderr," unmatched pubkey at height %d/%d\n",pindex->nHeight,height); + } + } +}*/ void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height) { @@ -777,34 +780,34 @@ void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height) } /*int8_t komodo_minerid(int32_t height,uint8_t *destpubkey33) - { - int32_t num,i,numnotaries; CBlockIndex *pindex; uint32_t timestamp=0; uint8_t pubkey33[33],pubkeys[64][33]; - if ( (pindex= chainActive[height]) != 0 ) - { - if ( pindex->didinit != 0 ) - { - if ( destpubkey33 != 0 ) - memcpy(destpubkey33,pindex->pubkey33,33); - return(pindex->notaryid); - } - komodo_index2pubkey33(pubkey33,pindex,height); - if ( destpubkey33 != 0 ) - memcpy(destpubkey33,pindex->pubkey33,33); - if ( pindex->didinit != 0 ) - return(pindex->notaryid); - timestamp = pindex->GetBlockTime(); - if ( (num= komodo_notaries(pubkeys,height,timestamp)) > 0 ) - { - for (i=0; ididinit != 0 ) + { + if ( destpubkey33 != 0 ) + memcpy(destpubkey33,pindex->pubkey33,33); + return(pindex->notaryid); + } + komodo_index2pubkey33(pubkey33,pindex,height); + if ( destpubkey33 != 0 ) + memcpy(destpubkey33,pindex->pubkey33,33); + if ( pindex->didinit != 0 ) + return(pindex->notaryid); + timestamp = pindex->GetBlockTime(); + if ( (num= komodo_notaries(pubkeys,height,timestamp)) > 0 ) + { + for (i=0; inTime; if ( komodo_blockload(block,pindex) == 0 ) { komodo_block2pubkey33(pubkeys[i],&block); @@ -835,24 +839,39 @@ int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,int32_t *non else return(0); } -int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width) // deprecate +int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width) { - /*int32_t i,n=0; - for (i=0; i= 82000 ) { if ( notaryid >= 0 ) @@ -861,14 +880,20 @@ int32_t komodo_is_special(uint8_t pubkeys[66][33],int32_t mids[66],int32_t heigh { if ( mids[i] == notaryid ) { - //for (j=0; j<66; j++) - // fprintf(stderr,"%d ",mids[j]); - //fprintf(stderr,"ht.%d repeat notaryid.%d in mids[%d]\n",height,notaryid,i); if ( height > 792000 ) + { + for (j=0; j<66; j++) + fprintf(stderr,"%d ",mids[j]); + fprintf(stderr,"ht.%d repeat notaryid.%d in mids[%d]\n",height,notaryid,i); return(-1); - else break; + } else break; } } + if ( blocktime != 0 && blocktimes[1] != 0 && blocktime < blocktimes[1]+57 ) + { + if ( height > 807000 ) + return(-2); + } return(1); } else return(0); } @@ -883,7 +908,7 @@ int32_t komodo_is_special(uint8_t pubkeys[66][33],int32_t mids[66],int32_t heigh else limit = 66; for (i=1; i 0 && notarized_ht > 0 && nHeight > notarized_ht-depth && nHeight <= notarized_ht ) + if ( depth != 0 && notarized_ht > 0 && nHeight > notarized_ht-depth && nHeight <= notarized_ht ) { *MoMp = MoM; *notarized_heightp = notarized_ht; @@ -938,7 +963,7 @@ int32_t komodo_checkpoint(int32_t *notarized_heightp,int32_t nHeight,uint256 has fprintf(stderr,"[%s] nHeight.%d == NOTARIZED_HEIGHT.%d, diff hash\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height); return(-1); } - } else fprintf(stderr,"[%s] unexpected error notary_hash %s ht.%d at ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,notary->nHeight); + } //else fprintf(stderr,"[%s] unexpected error notary_hash %s ht.%d at ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,notary->nHeight); } //else if ( notarized_height > 0 && notarized_height != 73880 && notarized_height >= 170000 ) // fprintf(stderr,"[%s] couldnt find notarized.(%s %d) ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,pindex->nHeight); @@ -999,27 +1024,371 @@ int32_t komodo_isrealtime(int32_t *kmdheightp) else return(0); } -int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag) +int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t cmptime,int32_t dispflag) { - uint32_t cmptime = nTime; if ( KOMODO_REWIND == 0 && ASSETCHAINS_SYMBOL[0] == 0 && (int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD ) //1473793441 ) { if ( txheight > 246748 ) { if ( txheight < 247205 ) cmptime -= 16000; - if ( (int64_t)tx.nLockTime < cmptime-3600 ) + if ( (int64_t)tx.nLockTime < cmptime-KOMODO_MAXMEMPOOLTIME ) { - if ( tx.nLockTime != 1477258935 || dispflag != 0 ) + if ( tx.nLockTime != 1477258935 && dispflag != 0 ) { - fprintf(stderr,"komodo_validate_interest.%d reject.%d [%d] locktime %u cmp2.%u\n",dispflag,txheight,(int32_t)(tx.nLockTime - (cmptime-3600)),(uint32_t)tx.nLockTime,cmptime); + fprintf(stderr,"komodo_validate_interest.%d reject.%d [%d] locktime %u cmp2.%u\n",dispflag,txheight,(int32_t)(tx.nLockTime - (cmptime-KOMODO_MAXMEMPOOLTIME)),(uint32_t)tx.nLockTime,cmptime); } return(-1); } if ( 0 && dispflag != 0 ) - fprintf(stderr,"validateinterest.%d accept.%d [%d] locktime %u cmp2.%u\n",dispflag,(int32_t)txheight,(int32_t)(tx.nLockTime - (cmptime-3600)),(int32_t)tx.nLockTime,cmptime); + fprintf(stderr,"validateinterest.%d accept.%d [%d] locktime %u cmp2.%u\n",dispflag,(int32_t)txheight,(int32_t)(tx.nLockTime - (cmptime-KOMODO_MAXMEMPOOLTIME)),(int32_t)tx.nLockTime,cmptime); } } return(0); } +/* + komodo_checkPOW (fast) is called early in the process and should only refer to data immediately available. it is a filter to prevent bad blocks from going into the local DB. The more blocks we can filter out at this stage, the less junk in the local DB that will just get purged later on. + + komodo_checkPOW (slow) is called right before connecting blocks so all prior blocks can be assumed to be there and all checks must pass + + commission must be in coinbase.vout[1] and must be >= 10000 sats + PoS stake must be without txfee and in the last tx in the block at vout[0] + PoW mining on PoS chain must solve a harder diff that adjusts, but never less than KOMODO_POWMINMULT + */ +#define KOMODO_POWMINMULT 16 + +uint64_t komodo_commission(const CBlock *pblock) +{ + int32_t i,j,n=0,txn_count; uint64_t commission,total = 0; + txn_count = pblock->vtx.size(); + for (i=0; ivtx[i].vout.size(); + for (j=0; jvtx[i].vout[j].nValue; + } + } + //fprintf(stderr,"txn.%d n.%d commission total %.8f -> %.8f\n",txn_count,n,dstr(total),dstr((total * ASSETCHAINS_COMMISSION) / COIN)); + commission = ((total * ASSETCHAINS_COMMISSION) / COIN); + if ( commission < 10000 ) + commission = 0; + return(commission); +} + +uint32_t komodo_segid32(char *coinaddr) +{ + bits256 addrhash; + vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)coinaddr,(int32_t)strlen(coinaddr)); + return(addrhash.uints[0]); +} + +uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeight,uint256 txid,int32_t vout,uint32_t blocktime,uint32_t prevtime,char *destaddr) +{ + CBlockIndex *pindex; bool fNegative,fOverflow; uint8_t hashbuf[128]; char address[64]; bits256 addrhash; arith_uint256 hashval; uint256 hash,pasthash; int64_t diff=0; int32_t segid,minage,i,iter=0; uint32_t txtime,winner = 0; arith_uint256 bnMaxPoSdiff; uint64_t value,coinage,supply = ASSETCHAINS_SUPPLY + nHeight*ASSETCHAINS_REWARD/SATOSHIDEN; + txtime = komodo_txtime(&value,txid,vout,address); + if ( blocktime < prevtime+57 ) + blocktime = prevtime+57; + if ( value == 0 || txtime == 0 || blocktime == 0 || prevtime == 0 ) + { + fprintf(stderr,"komodo_stake null %.8f %u %u %u\n",dstr(value),txtime,blocktime,prevtime); + return(0); + } + bnMaxPoSdiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); + bnMaxPoSdiff = (bnMaxPoSdiff / arith_uint256(4)); + if ( bnTarget < bnMaxPoSdiff ) + bnTarget = bnMaxPoSdiff; + if ( (minage= nHeight*3) > 6000 ) // about 100 blocks + minage = 6000; + pindex = 0; + if ( (pindex= komodo_chainactive(nHeight>50?nHeight-50:1)) != 0 ) + { + vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)address,(int32_t)strlen(address)); + segid = ((nHeight + addrhash.uints[0]) & 0x3f); + pasthash = pindex->GetBlockHash(); + memcpy(hashbuf,&pasthash,sizeof(pasthash)); + memcpy(&hashbuf[sizeof(pasthash)],&addrhash,sizeof(addrhash)); + vcalc_sha256(0,(uint8_t *)&hash,hashbuf,(int32_t)sizeof(uint256)*2); + //fprintf(stderr,"(%s) vs. (%s) %s %.8f txtime.%u\n",address,destaddr,hash.ToString().c_str(),dstr(value),txtime); + for (iter=0; iter<3600; iter++) + { + diff = (iter + blocktime - txtime - minage); + if ( iter > 0 ) + diff += iter + segid*2; + //if ( diff > 3600*24 ) + // break; + if ( blocktime+iter+segid*2 < txtime+minage ) + continue; + coinage = (value * diff) * ((diff >> 16) + 1); + hashval = arith_uint256(supply * 64) * (UintToArith256(hash) / arith_uint256(coinage+1)); + if ( hashval <= bnTarget ) + { + winner = 1; + if ( validateflag == 0 ) + { + blocktime += iter; + blocktime += segid * 2; + } + break; + } + if ( validateflag != 0 ) + { + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]); + fprintf(stderr," vs target "); + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); + fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d gap.%d %.8f diff.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,(int32_t)(blocktime - prevtime),dstr(value),(int32_t)diff); + break; + } + } + //fprintf(stderr,"iterated until i.%d winner.%d\n",i,winner); + if ( 0 ) + { + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]); + fprintf(stderr," vs "); + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); + fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d t.%u %.8f diff.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,dstr(value),(int32_t)diff); + } + } //else fprintf(stderr,"skip PoS scan: diff %d blocktime %u > %u txtime+minage %u pindex.%p\n",(int32_t)(blocktime - (txtime+minage)),blocktime,txtime,minage,pindex); + if ( nHeight < 10 ) + return(blocktime); + return(blocktime * winner); +} + +arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc) +{ + CBlockIndex *pindex; arith_uint256 bnTarget,hashval,sum,ave; bool fNegative,fOverflow; int32_t i,n,ht,percPoS,diff,val; + *percPoSp = percPoS = 0; + if ( height <= 10 ) + return(target); + sum = arith_uint256(0); + ave = sum; + for (i=n=0; i<100; i++) + { + ht = height - 100 + i; + if ( ht <= 1 ) + continue; + if ( (pindex= komodo_chainactive(ht)) != 0 ) + { + bnTarget.SetCompact(pindex->nBits,&fNegative,&fOverflow); + bnTarget = (bnTarget / arith_uint256(KOMODO_POWMINMULT)); + hashval = UintToArith256(pindex->GetBlockHash()); + if ( hashval <= bnTarget ) // PoW is never as easy as PoS/16, some PoS will be counted as PoW + { + fprintf(stderr,"1"); + sum += hashval; + n++; + } + else + { + percPoS++; + fprintf(stderr,"0"); + } + if ( (i % 10) == 9 ) + fprintf(stderr," %d, ",percPoS); + } + } + if ( n < 100 ) + percPoS = ((percPoS * n) + (goalperc * (100-n))) / 100; + fprintf(stderr," -> %d%% percPoS vs goalperc.%d ht.%d\n",percPoS,goalperc,height); + *percPoSp = percPoS; + target = (target / arith_uint256(KOMODO_POWMINMULT)); + if ( n > 0 ) + { + ave = (sum / arith_uint256(n)); + if ( ave > target ) + ave = target; + } else return(target); + if ( percPoS < goalperc ) // increase PoW diff -> lower bnTarget + { + bnTarget = (ave * arith_uint256(percPoS * percPoS)) / arith_uint256(goalperc * goalperc * goalperc); + if ( 1 ) + { + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&ave)[i]); + fprintf(stderr," increase diff -> "); + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); + fprintf(stderr," floor diff "); + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&target)[i]); + fprintf(stderr," ht.%d percPoS.%d vs goal.%d -> diff %d\n",height,percPoS,goalperc,goalperc - percPoS); + } + } + else if ( percPoS > goalperc ) // decrease PoW diff -> raise bnTarget + { + bnTarget = ((ave * arith_uint256(goalperc)) + (target * arith_uint256(percPoS))) / arith_uint256(percPoS + goalperc); + if ( 1 ) + { + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&ave)[i]); + fprintf(stderr," decrease diff -> "); + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); + fprintf(stderr," floor diff "); + for (i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&target)[i]); + fprintf(stderr," ht.%d percPoS.%d vs goal.%d -> diff %d\n",height,percPoS,goalperc,goalperc - percPoS); + } + } + else bnTarget = ave; // recent ave is perfect + return(bnTarget); +} + +int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_uint256 bnTarget) +{ + CBlockIndex *previndex; char voutaddr[64],destaddr[64]; uint256 txid; uint32_t txtime,prevtime=0; int32_t vout,txn_count,eligible,isPoS = 0; uint64_t value; CTxDestination voutaddress; + txn_count = pblock->vtx.size(); + if ( txn_count > 1 ) + { + if ( prevtime == 0 ) + { + if ( (previndex= mapBlockIndex[pblock->hashPrevBlock]) != 0 ) + prevtime = (uint32_t)previndex->nTime; + } + txid = pblock->vtx[txn_count-1].vin[0].prevout.hash; + vout = pblock->vtx[txn_count-1].vin[0].prevout.n; + if ( prevtime != 0 ) + { + eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime,(char *)""); + if ( eligible == 0 || eligible > pblock->nTime ) + { + fprintf(stderr,"komodo_is_PoSblock PoS failure ht.%d eligible.%u vs blocktime.%u, lag.%d -> check to see if it is PoW block\n",height,eligible,(uint32_t)pblock->nTime,(int32_t)(eligible - pblock->nTime)); + } else isPoS = 1; + } + else if ( slowflag == 0 ) // maybe previous block is not seen yet, do the best approx + { + txtime = komodo_txtime(&value,txid,vout,destaddr); + if ( ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) ) + { + strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); + if ( strcmp(destaddr,voutaddr) == 0 && pblock->vtx[txn_count-1].vout[0].nValue == value ) + isPoS = 1; // close enough for a pre-filter + else fprintf(stderr,"komodo_is_PoSblock ht.%d (%s) != (%s) or %.8f != %.8f\n",height,destaddr,voutaddr,dstr(value),dstr(pblock->vtx[txn_count-1].vout[0].nValue)); + } else fprintf(stderr,"komodo_is_PoSblock ht.%d couldnt extract voutaddress\n",height); + } else return(-1); + } + return(isPoS); +} + +int64_t komodo_checkcommission(CBlock *pblock,int32_t height) +{ + int64_t checktoshis=0; uint8_t *script; + if ( ASSETCHAINS_COMMISSION != 0 ) + { + checktoshis = komodo_commission(pblock); + if ( checktoshis > 10000 && pblock->vtx[0].vout.size() != 2 ) + return(-1); + else if ( checktoshis != 0 ) + { + script = (uint8_t *)pblock->vtx[0].vout[1].scriptPubKey.data(); + if ( script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 ) + return(-1); + if ( pblock->vtx[0].vout[1].nValue != checktoshis ) + { + fprintf(stderr,"ht.%d checktoshis %.8f vs actual vout[1] %.8f\n",height,dstr(checktoshis),dstr(pblock->vtx[0].vout[1].nValue)); + return(-1); + } + } + } + return(checktoshis); +} + +bool KOMODO_TEST_ASSETCHAIN_SKIP_POW = 0; + +int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height) +{ + uint256 hash; arith_uint256 bnTarget,bhash; bool fNegative,fOverflow; uint8_t *script,pubkey33[33],pubkeys[64][33]; int32_t i,possible,PoSperc,is_PoSblock=0,n,failed = 0,notaryid = -1; int64_t checktoshis,value; CBlockIndex *pprev; + if ( !CheckEquihashSolution(pblock, Params()) ) + { + fprintf(stderr,"komodo_checkPOW slowflag.%d ht.%d CheckEquihashSolution failed\n",slowflag,height); + return(-1); + } + hash = pblock->GetHash(); + bnTarget.SetCompact(pblock->nBits,&fNegative,&fOverflow); + bhash = UintToArith256(hash); + possible = komodo_block2pubkey33(pubkey33,pblock); + //fprintf(stderr,"height.%d slowflag.%d possible.%d cmp.%d\n",height,slowflag,possible,bhash > bnTarget); + if ( height == 0 ) + { + if ( slowflag != 0 ) + return(0); + if ( (pprev= mapBlockIndex[pblock->hashPrevBlock]) != 0 ) + height = pprev->nHeight + 1; + if ( height == 0 ) + return(0); + } + if ( (ASSETCHAINS_SYMBOL[0] != 0 || height > 792000) && bhash > bnTarget ) + { + failed = 1; + if ( height > 0 && ASSETCHAINS_SYMBOL[0] == 0 ) // for the fast case + { + if ( (n= komodo_notaries(pubkeys,height,pblock->nTime)) > 0 ) + { + for (i=0; i= 2 ) // must PoS or have at least 16x better PoW + { + if ( (is_PoSblock= komodo_is_PoSblock(slowflag,height,pblock,bnTarget)) == 0 ) + { + if ( ASSETCHAINS_STAKED == 100 && height > 100 ) // only PoS allowed! + return(-1); + else + { + if ( slowflag != 0 ) + bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED); + else if ( height > 100 ) + bnTarget = (bnTarget / arith_uint256(KOMODO_POWMINMULT)); // lower bound + if ( bhash > bnTarget ) + { + for (i=31; i>=16; i--) + fprintf(stderr,"%02x",((uint8_t *)&bhash)[i]); + fprintf(stderr," > "); + for (i=31; i>=16; i--) + fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); + fprintf(stderr," ht.%d PoW diff violation PoSperc.%d vs goalperc.%d\n",height,PoSperc,(int32_t)ASSETCHAINS_STAKED); + return(-1); + } + } + } else if ( is_PoSblock < 0 ) + return(-1); + } + if ( failed == 0 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 ) + { + if ( height == 1 ) + { + script = (uint8_t *)pblock->vtx[0].vout[0].scriptPubKey.data(); + if ( script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 ) + return(-1); + } + else + { + if ( komodo_checkcommission(pblock,height) < 0 ) + return(-1); + } + } + //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); +} + diff --git a/src/komodo_cJSON.c b/src/komodo_cJSON.c index ca2c6517c..8569b7802 100755 --- a/src/komodo_cJSON.c +++ b/src/komodo_cJSON.c @@ -56,7 +56,7 @@ static int32_t cJSON_strcasecmp(const char *s1,const char *s2) // the following written by jl777 /****************************************************************************** - * Copyright © 2014-2017 The SuperNET Developers. * + * Copyright © 2014-2018 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/komodo_ccdata.h b/src/komodo_ccdata.h new file mode 100644 index 000000000..012183fc7 --- /dev/null +++ b/src/komodo_ccdata.h @@ -0,0 +1,269 @@ +/****************************************************************************** + * Copyright © 2014-2018 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + +#ifndef H_KOMODOCCDATA_H +#define H_KOMODOCCDATA_H + +struct komodo_ccdata *CC_data; +int32_t CC_firstheight; + +uint256 BuildMerkleTree(bool* fMutated, const std::vector leaves, std::vector &vMerkleTree); + +uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth) +{ + static uint256 zero; CBlockIndex *pindex; int32_t i; std::vector tree, leaves; + bool fMutated; + MoMdepth &= 0xffff; // In case it includes the ccid + if ( MoMdepth >= height ) + return(zero); + for (i=0; ihashMerkleRoot); + else + return(zero); + } + return BuildMerkleTree(&fMutated, leaves, tree); +} + +struct komodo_ccdata_entry *komodo_allMoMs(int32_t *nump,uint256 *MoMoMp,int32_t kmdstarti,int32_t kmdendi) +{ + struct komodo_ccdata_entry *allMoMs=0; struct komodo_ccdata *ccdata,*tmpptr; int32_t i,num,max; + bool fMutated; std::vector tree, leaves; + num = max = 0; + portable_mutex_lock(&KOMODO_CC_mutex); + DL_FOREACH_SAFE(CC_data,ccdata,tmpptr) + { + if ( ccdata->MoMdata.height <= kmdendi && ccdata->MoMdata.height >= kmdstarti ) + { + if ( num >= max ) + { + max += 100; + allMoMs = (struct komodo_ccdata_entry *)realloc(allMoMs,max * sizeof(*allMoMs)); + } + allMoMs[num].MoM = ccdata->MoMdata.MoM; + allMoMs[num].notarized_height = ccdata->MoMdata.notarized_height; + allMoMs[num].kmdheight = ccdata->MoMdata.height; + allMoMs[num].txi = ccdata->MoMdata.txi; + strcpy(allMoMs[num].symbol,ccdata->symbol); + num++; + } + if ( ccdata->MoMdata.height < kmdstarti ) + break; + } + portable_mutex_unlock(&KOMODO_CC_mutex); + if ( (*nump= num) > 0 ) + { + for (i=0; i= 0) { + if ( mdata->numpairs >= maxpairs ) + { + maxpairs += 100; + mdata->pairs = (struct komodo_ccdatapair *)realloc(mdata->pairs,sizeof(*mdata->pairs)*maxpairs); + //fprintf(stderr,"pairs reallocated to %p num.%d\n",mdata->pairs,mdata->numpairs); + } + } else { + fprintf(stderr,"komodo_addpair.maxpairs %d must be >= 0\n",(int32_t)maxpairs); + return(-1); + } + mdata->pairs[mdata->numpairs].notarized_height = notarized_height; + mdata->pairs[mdata->numpairs].MoMoMoffset = offset; + mdata->numpairs++; + return(maxpairs); +} + +int32_t komodo_MoMoMdata(char *hexstr,int32_t hexsize,struct komodo_ccdataMoMoM *mdata,char *symbol,int32_t kmdheight,int32_t notarized_height) +{ + uint8_t hexdata[8192]; struct komodo_ccdata *ccdata,*tmpptr; int32_t len,maxpairs,i,retval=-1,depth,starti,endi,CCid=0; struct komodo_ccdata_entry *allMoMs; + starti = endi = depth = len = maxpairs = 0; + hexstr[0] = 0; + if ( sizeof(hexdata)*2+1 > hexsize ) + { + fprintf(stderr,"hexsize.%d too small for %d\n",hexsize,(int32_t)sizeof(hexdata)); + return(-1); + } + memset(mdata,0,sizeof(*mdata)); + portable_mutex_lock(&KOMODO_CC_mutex); + DL_FOREACH_SAFE(CC_data,ccdata,tmpptr) + { + if ( ccdata->MoMdata.height < kmdheight ) + { + //fprintf(stderr,"%s notarized.%d kmd.%d\n",ccdata->symbol,ccdata->MoMdata.notarized_height,ccdata->MoMdata.height); + if ( strcmp(ccdata->symbol,symbol) == 0 ) + { + if ( endi == 0 ) + { + endi = ccdata->MoMdata.height; + CCid = ccdata->CCid; + } + if ( (mdata->numpairs == 1 && notarized_height == 0) || ccdata->MoMdata.notarized_height <= notarized_height ) + { + starti = ccdata->MoMdata.height + 1; + if ( notarized_height == 0 ) + notarized_height = ccdata->MoMdata.notarized_height; + break; + } + } + starti = ccdata->MoMdata.height; + } + } + portable_mutex_unlock(&KOMODO_CC_mutex); + mdata->kmdstarti = starti; + mdata->kmdendi = endi; + if ( starti != 0 && endi != 0 && endi >= starti ) + { + if ( (allMoMs= komodo_allMoMs(&depth,&mdata->MoMoM,starti,endi)) != 0 ) + { + mdata->MoMoMdepth = depth; + for (i=0; inumpairs > 0 ) + { + len += iguana_rwnum(1,&hexdata[len],sizeof(CCid),(uint8_t *)&CCid); + len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->kmdstarti); + len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->kmdendi); + len += iguana_rwbignum(1,&hexdata[len],sizeof(mdata->MoMoM),(uint8_t *)&mdata->MoMoM); + len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->MoMoMdepth); + len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->numpairs); + for (i=0; inumpairs; i++) + { + if ( len + sizeof(uint32_t)*2 > sizeof(hexdata) ) + { + fprintf(stderr,"%s %d %d i.%d of %d exceeds hexdata.%d\n",symbol,kmdheight,notarized_height,i,mdata->numpairs,(int32_t)sizeof(hexdata)); + break; + } + len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->pairs[i].notarized_height); + len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->pairs[i].MoMoMoffset); + } + if ( i == mdata->numpairs && len*2+1 < hexsize ) + { + init_hexbytes_noT(hexstr,hexdata,len); + //fprintf(stderr,"hexstr.(%s)\n",hexstr); + retval = 0; + } else fprintf(stderr,"%s %d %d too much hexdata[%d] for hexstr[%d]\n",symbol,kmdheight,notarized_height,len,hexsize); + } + free(allMoMs); + } + } + return(retval); +} + +void komodo_purge_ccdata(int32_t height) +{ + struct komodo_ccdata *ccdata,*tmpptr; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + { + portable_mutex_lock(&KOMODO_CC_mutex); + DL_FOREACH_SAFE(CC_data,ccdata,tmpptr) + { + if ( ccdata->MoMdata.height >= height ) + { + printf("PURGE %s notarized.%d\n",ccdata->symbol,ccdata->MoMdata.notarized_height); + DL_DELETE(CC_data,ccdata); + free(ccdata); + } else break; + } + portable_mutex_unlock(&KOMODO_CC_mutex); + } + else + { + // purge notarized data + } +} + +// this is just a demo of ccdata processing to create example data for the MoMoM and allMoMs calls +int32_t komodo_rwccdata(char *thischain,int32_t rwflag,struct komodo_ccdata *ccdata,struct komodo_ccdataMoMoM *MoMoMdata) +{ + uint256 hash,zero; bits256 tmp; int32_t i,nonz; struct komodo_ccdata *ptr; struct notarized_checkpoint *np; + return(0); // disable this path as libscott method is much better + if ( rwflag == 0 ) + { + // load from disk + } + else + { + // write to disk + } + if ( ccdata->MoMdata.height > 0 && (CC_firstheight == 0 || ccdata->MoMdata.height < CC_firstheight) ) + CC_firstheight = ccdata->MoMdata.height; + for (nonz=i=0; i<32; i++) + { + if ( (tmp.bytes[i]= ((uint8_t *)&ccdata->MoMdata.MoM)[31-i]) != 0 ) + nonz++; + } + if ( nonz == 0 ) + return(0); + memcpy(&hash,&tmp,sizeof(hash)); + //fprintf(stderr,"[%s] ccdata.%s id.%d notarized_ht.%d MoM.%s height.%d/t%d\n",ASSETCHAINS_SYMBOL,ccdata->symbol,ccdata->CCid,ccdata->MoMdata.notarized_height,hash.ToString().c_str(),ccdata->MoMdata.height,ccdata->MoMdata.txi); + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + { + if ( CC_data != 0 && (CC_data->MoMdata.height > ccdata->MoMdata.height || (CC_data->MoMdata.height == ccdata->MoMdata.height && CC_data->MoMdata.txi >= ccdata->MoMdata.txi)) ) + { + printf("out of order detected? SKIP CC_data ht.%d/txi.%d vs ht.%d/txi.%d\n",CC_data->MoMdata.height,CC_data->MoMdata.txi,ccdata->MoMdata.height,ccdata->MoMdata.txi); + } + else + { + ptr = (struct komodo_ccdata *)calloc(1,sizeof(*ptr)); + *ptr = *ccdata; + portable_mutex_lock(&KOMODO_CC_mutex); + DL_PREPEND(CC_data,ptr); + portable_mutex_unlock(&KOMODO_CC_mutex); + } + } + else + { + if ( MoMoMdata != 0 && MoMoMdata->pairs != 0 ) + { + for (i=0; inumpairs; i++) + { + if ( (np= komodo_npptr(MoMoMdata->pairs[i].notarized_height)) != 0 ) + { + memset(&zero,0,sizeof(zero)); + if ( memcmp(&np->MoMoM,&zero,sizeof(np->MoMoM)) == 0 ) + { + np->MoMoM = MoMoMdata->MoMoM; + np->MoMoMdepth = MoMoMdata->MoMoMdepth; + np->MoMoMoffset = MoMoMdata->MoMoMoffset; + np->kmdstarti = MoMoMdata->kmdstarti; + np->kmdendi = MoMoMdata->kmdendi; + } + else if ( memcmp(&np->MoMoM,&MoMoMdata->MoMoM,sizeof(np->MoMoM)) != 0 || np->MoMoMdepth != MoMoMdata->MoMoMdepth || np->MoMoMoffset != MoMoMdata->MoMoMoffset || np->kmdstarti != MoMoMdata->kmdstarti || np->kmdendi != MoMoMdata->kmdendi ) + { + fprintf(stderr,"preexisting MoMoM mismatch: %s (%d %d %d %d) vs %s (%d %d %d %d)\n",np->MoMoM.ToString().c_str(),np->MoMoMdepth,np->MoMoMoffset,np->kmdstarti,np->kmdendi,MoMoMdata->MoMoM.ToString().c_str(),MoMoMdata->MoMoMdepth,MoMoMdata->MoMoMoffset,MoMoMdata->kmdstarti,MoMoMdata->kmdendi); + } + } + } + } + } + return(1); +} + +#endif diff --git a/src/komodo_curve25519.h b/src/komodo_curve25519.h index a7283e265..90d9a7e00 100644 --- a/src/komodo_curve25519.h +++ b/src/komodo_curve25519.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2017 The SuperNET Developers. * + * Copyright © 2014-2018 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/komodo_defs.h b/src/komodo_defs.h index db792c44e..1d7351638 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -5,5 +5,8 @@ #define KOMODO_ELECTION_GAP 2000 #define ROUNDROBIN_DELAY 61 #define KOMODO_ASSETCHAIN_MAXLEN 65 +#define KOMODO_LIMITED_NETWORKSIZE 4 +#define KOMODO_MAXMEMPOOLTIME 3600 // affects consensus +#define CRYPTO777_PUBSECPSTR "020e46e79a2a8d12b9b5d12c7a91adb4e454edfae43c0a0cb805427d2ac7613fd9" #endif diff --git a/src/komodo_events.h b/src/komodo_events.h index c64ccbaa2..d4ea17ce5 100644 --- a/src/komodo_events.h +++ b/src/komodo_events.h @@ -39,16 +39,17 @@ struct komodo_event *komodo_eventadd(struct komodo_state *sp,int32_t height,char void komodo_eventadd_notarized(struct komodo_state *sp,char *symbol,int32_t height,char *dest,uint256 notarized_hash,uint256 notarized_desttxid,int32_t notarizedheight,uint256 MoM,int32_t MoMdepth) { - struct komodo_event_notarized N; - if ( NOTARY_PUBKEY33[0] != 0 && komodo_verifynotarization(symbol,dest,height,notarizedheight,notarized_hash,notarized_desttxid) != 0 ) + static uint32_t counter; int32_t verified=0; char *coin; struct komodo_event_notarized N; + coin = (ASSETCHAINS_SYMBOL[0] == 0) ? (char *)"KMD" : ASSETCHAINS_SYMBOL; + if ( IS_KOMODO_NOTARY != 0 && (verified= komodo_verifynotarization(symbol,dest,height,notarizedheight,notarized_hash,notarized_desttxid)) < 0 ) { - if ( height > 50000 || ASSETCHAINS_SYMBOL[0] != 0 ) + if ( counter++ < 100 ) printf("[%s] error validating notarization ht.%d notarized_height.%d, if on a pruned %s node this can be ignored\n",ASSETCHAINS_SYMBOL,height,notarizedheight,dest); } - else + else if ( strcmp(symbol,coin) == 0 ) { - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - fprintf(stderr,"validated [%s] ht.%d notarized %d\n",ASSETCHAINS_SYMBOL,height,notarizedheight); + if ( 0 && IS_KOMODO_NOTARY != 0 && verified != 0 ) + fprintf(stderr,"validated [%s] ht.%d notarized %d\n",coin,height,notarizedheight); memset(&N,0,sizeof(N)); N.blockhash = notarized_hash; N.desttxid = notarized_desttxid; diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 72f36a21c..9de6b4fc9 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2017 The SuperNET Developers. * + * Copyright © 2014-2018 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -650,157 +650,10 @@ int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max) void komodo_passport_iteration(); -uint64_t komodo_commission(const CBlock &block) -{ - int32_t i,j,n=0,txn_count; uint64_t total = 0; - txn_count = block.vtx.size(); - for (i=0; i %.8f\n",txn_count,n,dstr(total),dstr((total * ASSETCHAINS_COMMISSION) / COIN)); - return((total * ASSETCHAINS_COMMISSION) / COIN); -} - -uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeight,uint256 txid,int32_t vout,uint32_t blocktime,uint32_t prevtime,char *destaddr) -{ - CBlockIndex *pindex; uint8_t hashbuf[128]; char address[64]; bits256 addrhash; arith_uint256 hashval; uint256 hash,pasthash; int64_t diff=0; int32_t segid,minage,i,iter=0; uint32_t txtime,winner = 0; uint64_t value,coinage,supply = ASSETCHAINS_SUPPLY + nHeight*ASSETCHAINS_REWARD/SATOSHIDEN; - txtime = komodo_txtime(&value,txid,vout,address); - if ( value == 0 || txtime == 0 ) - return(0); - if ( (minage= nHeight*3) > 6000 ) - minage = 6000; - if ( blocktime > txtime+minage && (pindex= komodo_chainactive(nHeight>200?nHeight-200:1)) != 0 ) - { - vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)address,(int32_t)strlen(address)); - segid = ((nHeight + addrhash.uints[0]) & 0x3f); - pasthash = pindex->GetBlockHash(); - memcpy(hashbuf,&pasthash,sizeof(pasthash)); - memcpy(&hashbuf[sizeof(pasthash)],&addrhash,sizeof(addrhash)); - vcalc_sha256(0,(uint8_t *)&hash,hashbuf,(int32_t)sizeof(uint256)*2); - //fprintf(stderr,"(%s) vs. (%s) %s %.8f txtime.%u\n",address,destaddr,hash.ToString().c_str(),dstr(value),txtime); - for (iter=0; iter<3600; iter++) - { - diff = (iter + blocktime - txtime - minage); - if ( diff > 3600*24 ) - break; - coinage = (value * diff) * ((diff >> 16) + 1); - hashval = arith_uint256(supply * 64) * (UintToArith256(hash) / arith_uint256(coinage+1)); - if ( hashval <= bnTarget ) - { - winner = 1; - if ( validateflag == 0 ) - { - blocktime += iter; - blocktime += segid * 2; - } - break; - } - if ( validateflag != 0 ) - { - for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]); - fprintf(stderr," vs target "); - for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); - fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d gap.%d %.8f diff.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,(int32_t)(blocktime - prevtime),dstr(value),(int32_t)diff); - break; - } - } - //fprintf(stderr,"iterated until i.%d winner.%d\n",i,winner); - if ( 0 ) - { - for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]); - fprintf(stderr," vs "); - for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); - fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d t.%u %.8f diff.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,dstr(value),(int32_t)diff); - } - } - if ( nHeight < 2 ) - return(blocktime); - return(blocktime * winner); -} - -#define KOMODO_POWMINMULT 16 -arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc) -{ - CBlockIndex *pindex; arith_uint256 bnTarget,hashval,sum,ave; bool fNegative,fOverflow; int32_t i,n,ht,percPoS,diff; - *percPoSp = percPoS = 0; - sum = arith_uint256(0); - ave = sum; - for (i=n=0; i<100; i++) - { - ht = height - 100 + i; - if ( (pindex= komodo_chainactive(ht)) != 0 ) - { - bnTarget.SetCompact(pindex->nBits,&fNegative,&fOverflow); - bnTarget = (bnTarget / arith_uint256(KOMODO_POWMINMULT)); - hashval = UintToArith256(pindex->GetBlockHash()); - if ( hashval <= bnTarget ) // PoW is never as easy as PoS/64, some PoS will be counted as PoW - { - sum += hashval; - n++; - } else percPoS++; - } - } - *percPoSp = percPoS; - target = (target / arith_uint256(KOMODO_POWMINMULT)); - if ( n > 0 ) - { - ave = (sum / arith_uint256(n)); - if ( ave > target ) - ave = target; - } else return(target); - if ( percPoS < goalperc ) // increase PoW diff -> lower bnTarget - { - bnTarget = (ave * arith_uint256(goalperc)) / arith_uint256(percPoS + goalperc); - if ( 1 ) - { - for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&ave)[i]); - fprintf(stderr," increase diff -> "); - for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); - fprintf(stderr," floor diff "); - for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&target)[i]); - fprintf(stderr," ht.%d percPoS.%d vs goal.%d -> diff %d\n",height,percPoS,goalperc,goalperc - percPoS); - } - } - else if ( percPoS > goalperc ) // decrease PoW diff -> raise bnTarget - { - bnTarget = ((ave * arith_uint256(goalperc)) + (target * arith_uint256(percPoS))) / arith_uint256(percPoS + goalperc); - if ( 1 ) - { - for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&ave)[i]); - fprintf(stderr," decrease diff -> "); - for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); - fprintf(stderr," floor diff "); - for (i=31; i>=24; i--) - fprintf(stderr,"%02x",((uint8_t *)&target)[i]); - fprintf(stderr," ht.%d percPoS.%d vs goal.%d -> diff %d\n",height,percPoS,goalperc,goalperc - percPoS); - } - } - else bnTarget = ave; // recent ave is perfect - return(bnTarget); -} - int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtime) // verify above block is valid pax pricing { static uint256 array[64]; static int32_t numbanned,indallvouts; - int32_t i,j,k,n,ht,baseid,txn_count,activation,num,opretlen,offset=1,errs=0,matched=0,kmdheights[256],otherheights[256]; uint256 hash,txids[256]; char symbol[KOMODO_ASSETCHAIN_MAXLEN],base[KOMODO_ASSETCHAIN_MAXLEN]; uint16_t vouts[256]; int8_t baseids[256]; uint8_t *script,opcode,rmd160s[256*20]; uint64_t total,subsidy,available,deposited,issued,withdrawn,approved,redeemed,checktoshis,seed; int64_t values[256],srcvalues[256]; struct pax_transaction *pax; struct komodo_state *sp; + int32_t i,j,k,n,ht,baseid,txn_count,activation,num,opretlen,offset=1,errs=0,notmatched=0,matched=0,kmdheights[256],otherheights[256]; uint256 hash,txids[256]; char symbol[KOMODO_ASSETCHAIN_MAXLEN],base[KOMODO_ASSETCHAIN_MAXLEN]; uint16_t vouts[256]; int8_t baseids[256]; uint8_t *script,opcode,rmd160s[256*20]; uint64_t total,subsidy,available,deposited,issued,withdrawn,approved,redeemed,seed; int64_t checktoshis,values[256],srcvalues[256]; struct pax_transaction *pax; struct komodo_state *sp; CTransaction tx; activation = 235300; if ( *(int32_t *)&array[0] == 0 ) numbanned = komodo_bannedset(&indallvouts,array,(int32_t)(sizeof(array)/sizeof(*array))); @@ -815,6 +668,11 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim { for (i=0; i 1 && block.vtx[txn_count-1].vout.size() > 0 && block.vtx[txn_count-1].vout[0].nValue == 5000 ) + { + if ( block.vtx[txn_count-1].vin.size() == 1 && GetTransaction(block.vtx[txn_count-1].vin[0].prevout.hash,tx,hash,false) && block.vtx[0].vout[0].scriptPubKey == tx.vout[block.vtx[txn_count-1].vin[0].prevout.n].scriptPubKey ) + notmatched = 1; + } n = block.vtx[i].vin.size(); for (j=0; j= MAX_MONEY ) { overflow = 1; break; } + if ( i > 1 && script[0] != 0x6a && val < 5000 ) + strangeout++; total += val; if ( total < prevtotal || (val != 0 && total == prevtotal) ) { @@ -854,9 +715,12 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim { if ( overflow != 0 || total > COIN/10 ) { - //fprintf(stderr,">>>>>>>> <<<<<<<<<< ht.%d illegal nonz output %.8f n.%d\n",height,dstr(block.vtx[0].vout[1].nValue),n); if ( height >= activation ) + { + if ( height > 800000 ) + fprintf(stderr,">>>>>>>> <<<<<<<<<< ht.%d illegal nonz output %.8f n.%d\n",height,dstr(block.vtx[0].vout[1].nValue),n); return(-1); + } } else if ( block.nBits == KOMODO_MINDIFF_NBITS && total > 0 ) // to deal with fee stealing { @@ -864,375 +728,44 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim if ( height > KOMODO_NOTARIES_HEIGHT1 ) return(-1); } + if ( strangeout != 0 || notmatched != 0 ) + { + if ( 0 && strcmp(NOTARY_PUBKEY.c_str(),"03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828") == 0 ) + fprintf(stderr,">>>>>>>>>>>>> DUST ht.%d strangout.%d notmatched.%d <<<<<<<<<\n",height,strangeout,notmatched); + if ( height > 1000000 && strangeout != 0 ) + return(-1); + } + else if ( height > 814000 ) + { + script = (uint8_t *)block.vtx[0].vout[0].scriptPubKey.data(); + return(-1 * (komodo_electednotary(&num,script+1,height,0) >= 0) * (height > 1000000)); + } } else { - if ( ASSETCHAINS_STAKED != 0 && height >= 2 ) + checktoshis = 0; + if ( ASSETCHAINS_COMMISSION != 0 && height > 1 ) { - arith_uint256 bnTarget,hashval; int32_t PoSperc; bool fNegative,fOverflow; CBlockIndex *previndex; uint32_t eligible,isPoS = 0; - bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow); - if ( txn_count > 1 ) + if ( (checktoshis= komodo_checkcommission((CBlock *)&block,height)) < 0 ) { - if ( prevtime == 0 ) - { - if ( (previndex= mapBlockIndex[block.hashPrevBlock]) != 0 ) - prevtime = (uint32_t)previndex->nTime; - } - eligible = komodo_stake(1,bnTarget,height,block.vtx[txn_count-1].vin[0].prevout.hash,block.vtx[txn_count-1].vin[0].prevout.n,block.nTime,prevtime,(char *)""); - if ( eligible == 0 || eligible > block.nTime ) - { - fprintf(stderr,"PoS failure ht.%d eligible.%u vs blocktime.%u, lag.%d -> check to see if it is PoW block\n",height,eligible,(uint32_t)block.nTime,(int32_t)(eligible - block.nTime)); - } else isPoS = 1; - } - if ( isPoS == 0 && height > 100 ) - { - if ( ASSETCHAINS_STAKED == 100 ) - { - fprintf(stderr,"ht.%d 100%% PoS after height 100 rule violated for -ac_staking=100\n",height); - return(-1); - } - // check PoW - bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED); - hashval = UintToArith256(block.GetHash()); - if ( hashval > bnTarget ) - { - /*for (i=31; i>=0; i--) - fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]); - fprintf(stderr," > "); - for (i=31; i>=0; i--) - fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); - fprintf(stderr," ht.%d PoW diff violation PoSperc.%d vs goalperc.%d\n",height,PoSperc,(int32_t)ASSETCHAINS_STAKED);*/ - return(-1); - } - } - } - if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && ASSETCHAINS_COMMISSION != 0 && block.vtx[0].vout.size() > 1 ) - { - script = (uint8_t *)block.vtx[0].vout[1].scriptPubKey.data(); - if ( script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 ) + fprintf(stderr,"ht.%d checktoshis %.8f overflow.%d total %.8f strangeout.%d\n",height,dstr(checktoshis),overflow,dstr(total),strangeout); return(-1); - if ( (checktoshis = komodo_commission(block)) != 0 ) - { - if ( block.vtx[0].vout[1].nValue != checktoshis ) - { - fprintf(stderr,"checktoshis %.8f vs actual vout[1] %.8f\n",dstr(checktoshis),dstr(block.vtx[0].vout[1].nValue)); - return(-1); - } else return(0); } } - if ( overflow != 0 || total > 0 ) + if ( height > 1 && checktoshis == 0 ) + { + checktoshis = ((uint64_t)GetBlockSubsidy(height, Params().GetConsensus()) - block.vtx[0].vout[0].nValue); + } + if ( height >= 2 && (overflow != 0 || total > checktoshis || strangeout != 0) ) + { + fprintf(stderr,"checkdeposit: ht.%d checktoshis %.8f overflow.%d total %.8f strangeout.%d\n",height,dstr(checktoshis),overflow,dstr(total),strangeout); + if ( strangeout != 0 ) + fprintf(stderr,">>>>>>>>>>>>> %s DUST ht.%d strangout.%d notmatched.%d <<<<<<<<<\n",ASSETCHAINS_SYMBOL,height,strangeout,notmatched); return(-1); + } } return(0); } -/* - //fprintf(stderr,"ht.%d n.%d nValue %.8f (%d %d %d)\n",height,n,dstr(block.vtx[0].vout[1].nValue),KOMODO_PAX,komodo_isrealtime(&ht),KOMODO_PASSPORT_INITDONE); - offset += komodo_scriptitemlen(&opretlen,&script[offset]); - //printf("offset.%d opretlen.%d [%02x %02x %02x %02x]\n",offset,opretlen,script[0],script[1],script[2],script[3]); - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - { - opcode = 'X'; - if ( height >= 235300 ) - return(-1); - strcpy(symbol,(char *)"KMD"); - if ( komodo_isrealtime(&ht) == 0 || KOMODO_PASSPORT_INITDONE == 0 ) // init time already in DB - return(0); - } - else - { - strcpy(symbol,ASSETCHAINS_SYMBOL); - opcode = 'I'; - if ( (baseid= komodo_baseid(symbol)) < 0 ) - { - if ( block.vtx[0].vout.size() != 1 ) - { - printf("%s has more than one coinbase?\n",symbol); - return(-1); - } - return(0); - } - while ( KOMODO_PASSPORT_INITDONE == 0 ) - komodo_passport_iteration(); - komodo_passport_iteration(); - // grandfathering preexisting - if ( height < 777 ) - return(0); - if ( baseid == USD ) // 6820 in balance calcs - { - if ( height <= 6821 || height <= 2000 || height == 2968 || height == 2960 || height == 2649 || height == 3275 || height == 3282 || height == 3328 || height == 3468 ) - return(0); - } - else if ( baseid == EUR ) - { - if ( height < 1200 || height == 1408 || height == 1111 || height == 1094 || height == 1092 || height == 1080 || height == 1053 || height == 1005 || height == 822 || height == 821 || height == 810 || height == 797 || height == 790 || height == 787 || height == 785 || height == 1313 || height == 1288 || height == 1263 || height == 1262 || height <= 211 || height == 210 || height == 188 || height == 185 || height == 182 || height == 181 || height == 171 || height == 170 || height == 169 || height == 168 || height == 167 || height == 166 || height == 165 || height == 164 || height == 163 || height == 162 ) - return(0); - } - else if ( baseid == JPY ) - { - if ( height == 1038 || height == 1039 || height == 1040 || height == 1041 || height == 1014 || height == 998 || height == 973 || height == 139 || height == 971 || height == 141 || height == 816 || height == 814 || height == 803 || height == 142 || height == 782 || height == 145 || height == 181 || height == 186 || height == 192 || height == 190 || height == 189 || height == 255 || height == 218 || height == 233 || height == 259 || height == 278 || height == 361 || height == 367 || height == 733 || height == 688 || height == 468 ) - return(0); - } - else if ( baseid == GBP ) - { - if ( height == 1025 || height == 1026 || height == 1027 || height == 1028 || height == 997 || height == 970 || height == 953 || height == 951 || height == 803 || height == 800 || height == 786 || height == 123 || height == 771 || height == 137 || height == 139 || height == 140 || height == 146 || height == 194 || height == 200 || height == 202 || height == 203 || height == 205 || height == 210 || height == 216 || height == 271 || height == 233 || height == 294 ) - return(0); - } - else if ( baseid == AUD ) - { - if ( height == 1012 || height == 1013 || height == 1014 || height == 985 || height == 958 || height == 936 || height == 933 || height == 790 || height == 788 || height == 778 || height == 124 || height == 777 || height == 122 || height == 140 || height == 142 || height == 143 || height == 186 || height == 196 || height == 198 || height == 201 || height == 210 || height == 192 ) - return(0); - } - else if ( baseid == CAD ) - { - if ( height < 1000 || height == 836 || height == 781 || height == 779 || height == 798 || height == 794 || height == 1181 || height == 1179 || height == 1159 || height == 1134 || height == 1132 || height == 121 || height == 970 || height == 119 || height == 299 || height == 302 || height == 303 || height == 306 || height == 308 || height == 355 || height == 362 || height == 367 || height == 363 || height == 364 || height == 380 || height == 373 || height == 390 || height == 437 || height == 777 ) - return(0); - } - else if ( baseid == CHF ) - { - if ( height == 987 || height == 988 || height == 989 || height == 960 || height == 931 || height == 914 || height == 122 || height == 912 || height == 141 || height == 780 || height == 145 || height == 777 || height == 151 || height == 775 || height == 765 || height == 195 || height == 764 || height == 737 || height == 194 || height == 193 || height == 198 || height == 207 || height == 216 || height == 227 || height == 256 || height == 260 || height == 276 || height == 289 || height == 292 || height == 349 ) - return(0); - } - else if ( baseid == NZD ) - { - if ( height < 1000 || height == 787 || height == 786 || height == 784 || height == 785 || height == 777 || height == 1113 || height == 1083 || height == 1067 || height == 265 || height == 1064 || height == 920 || height == 913 || height == 124 || height == 911 || height == 903 || height == 900 || height == 879 || height == 122 || height == 266 || height == 269 || height == 270 || height == 278 || height == 307 || height == 318 || height == 322 || height == 335 || height == 395 || height == 406 || height == 314 ) - return(0); - } - else if ( baseid == CNY ) - { - if ( height == 987 || height == 988 || height == 989 || height == 982 || height == 957 || height == 931 || height == 119 || height == 929 || height == 134 || height == 782 || height == 137 || height == 775 || height == 143 || height == 772 || height == 186 || height == 763 || height == 761 || height == 734 || height == 183 || height == 190 || height == 192 || height == 211 || height == 203 || height == 226 || height == 263 || height == 264 || height == 277 || height == 342 || height == 613 || height == 525 ) - return(0); - } - else if ( baseid == RUB ) - { - if ( height == 819 || height == 812 || height == 810 || height == 802 || height == 801 || height == 1074 || height == 1040 || height == 1014 || height == 163 || height == 1013 || height == 877 || height == 867 || height == 863 || height == 834 || height == 158 || height == 126 || height == 106 || height == 105 || height == 174 || height == 175 || height == 176 || height == 177 || height == 181 || height == 183 || height == 184 || height == 187 ) - return(0); - } - else if ( baseid == MXN ) - { - if ( height == 1079 || height == 1080 || height == 1081 || height == 1069 || height == 1048 || height == 1028 || height == 121 || height == 1027 || height == 146 || height == 894 || height == 891 || height == 148 || height == 882 || height == 879 || height == 151 || height == 856 || height == 158 || height == 822 || height == 197 || height == 203 || height == 207 || height == 209 || height == 213 || height == 217 || height == 218 || height == 226 || height == 283 || height == 302 || height == 319 || height == 318 || height == 569 ) - return(0); - } - else if ( baseid == BRL ) - { - if ( height == 1003 || height == 1004 || height == 1005 || height == 972 || height == 943 || height == 922 || height == 118 || height == 920 || height == 145 || height == 787 || height == 783 || height == 147 || height == 781 || height == 774 || height == 148 || height == 771 || height == 154 || height == 751 || height == 156 || height == 188 || height == 193 || height == 195 || height == 199 || height == 203 || height == 225 || height == 230 || height == 262 || height == 266 || height == 284 || height == 300 || height == 640 ) - return(0); - } - else if ( baseid == INR ) - { - if ( height == 998 || height == 999 || height == 1000 || height == 788 || height == 786 || height == 775 || height == 753 || height == 125 || height == 153 || height == 155 || height == 159 || height == 204 || height == 206 || height == 211 || height == 217 || height == 220 || height == 229 || height == 265 || height == 292 || height == 300 ) - return(0); - } - else if ( baseid == PLN ) - { - if ( height == 1029 || height == 1030 || height == 1031 || height == 1009 || height == 984 || height == 960 || height == 959 || height == 798 || height == 794 || height == 792 || height == 782 || height == 775 || height == 755 || height == 122 || height == 120 || height == 158 || height == 160 || height == 163 || height == 225 || height == 217 || height == 219 || height == 229 || height == 234 || height == 286 || height == 231 || height == 292 ) - return(0); - } - else if ( baseid == HKD ) - { - if ( height == 1013 || height == 1014 || height == 1015 || height == 1002 || height == 979 || height == 947 || height == 123 || height == 946 || height == 153 || height == 811 || height == 808 || height == 806 || height == 155 || height == 795 || height == 157 || height == 773 || height == 205 || height == 208 || height == 210 || height == 211 || height == 215 || height == 221 || height == 231 || height == 255 || height == 273 || height == 293 || height == 310 || height == 654 ) - return(0); - } - else if ( baseid == TRY ) - { - if ( height == 1022 || height == 1023 || height == 1051 || height == 991 || height == 974 || height == 949 || height == 141 || height == 948 || height == 783 || height == 153 || height == 781 || height == 779 || height == 776 || height == 768 || height == 765 || height == 121 || height == 142 || height == 144 || height == 143 || height == 149 || height == 204 || height == 210 || height == 216 || height == 229 || height == 280 || height == 145 ) - return(0); - } - else if ( baseid == NOK ) - { - if ( height == 987 || height == 988 || height == 989 || height == 962 || height == 911 || height == 907 || height == 125 || height == 765 || height == 150 || height == 762 || height == 760 || height == 753 || height == 152 || height == 751 || height == 151 || height == 154 || height == 160 || height == 195 || height == 203 || height == 207 || height == 211 || height == 220 || height == 236 || height == 253 || height == 278 || height == 283 ) - return(0); - } - else if ( baseid == ZAR ) - { - if ( height == 979 || height == 980 || height == 981 || height == 956 || height == 937 || height == 906 || height == 905 || height == 122 || height == 756 || height == 754 || height == 752 || height == 749 || height == 742 || height == 739 || height == 120 || height == 151 || height == 153 || height == 157 || height == 159 || height == 206 || height == 213 || height == 216 || height == 222 || height == 277 || height == 287 || height == 215 ) - return(0); - } - else if ( baseid == SEK ) - { - if ( height == 960 || height == 961 || height == 962 || height == 943 || height == 925 || height == 896 || height == 147 || height == 894 || height == 759 || height == 751 || height == 749 || height == 742 || height == 740 || height == 716 || height == 123 || height == 148 || height == 150 || height == 151 || height == 157 || height == 199 || height == 200 || height == 201 || height == 206 || height == 256 || height == 257 || height == 268 ) - return(0); - } - else if ( baseid == CZK ) - { - if ( height < 1000 || height == 1084 || height == 1085 || height == 1086 || height == 778 || height == 1079 || height == 1054 || height == 1032 || height == 121 || height == 1030 || height == 182 || height == 876 || height == 873 || height == 871 || height == 184 || height == 862 || height == 185 || height == 861 || height == 186 || height == 838 || height == 238 || height == 242 || height == 246 || height == 248 || height == 250 || height == 251 || height == 256 || height == 282 || height == 322 || height == 343 || height == 433 || height == 323 || height == 276 ) - return(0); - } - else if ( baseid == HUF ) - { - if ( height < 2200 || height == 1531 || height == 1528 || height == 1530 || height == 1451 || height == 1448 || height == 1442 || height == 1418 || height == 1407 || height == 1406 || height == 1392 || height == 1391 || height == 1387 || height == 1383 || height == 1335 || height == 1337 || height == 1338 || height == 1649 || height == 2378 || height == 2376 || height == 2371 || height == 1330 || height == 2326 || height == 1344 || height == 2305 || height == 2304 || height == 2171 || height == 2168 || height == 2166 || height == 2156 || height == 2135 || height == 1343 || height == 1342 || height == 1341 || height == 1340 || height == 1339 || height == 1336 || height == 1334 || height == 1333 || height == 1346 || height == 1400 || height == 1525 || height == 1509 ) - return(0); - } - else if ( baseid == DKK ) - { - if ( height == 1241 || height == 945 || height == 898 || height == 894 || height == 892 || height == 866 || height == 857 || height == 853 || height == 834 || height == 812 || height == 792 || height == 784 || height == 778 || height == 783 || height == 1214 || height == 1186 || height == 1158 || height == 126 || height == 1156 || height == 329 || height == 1021 || height == 1016 || height == 1014 || height == 333 || height == 1003 || height == 1002 || height == 978 || height == 332 || height == 337 || height == 381 || height == 390 || height == 386 || height == 401 || height == 389 || height == 396 || height == 428 || height == 473 || height == 490 || height == 493 ) - return(0); - } - else if ( baseid == ILS ) - { - if ( height == 1017 || height == 1018 || height == 1019 || height == 1010 || height == 985 || height == 954 || height == 120 || height == 952 || height == 143 || height == 819 || height == 817 || height == 808 || height == 145 || height == 786 || height == 155 || height == 753 || height == 151 || height == 149 || height == 199 || height == 193 || height == 201 || height == 209 || height == 284 || height == 305 || height == 676 || height == 702 || height == 406 ) - return(0); - } - else if ( baseid == MYR ) - { - if ( height == 1020 || height == 1021 || height == 1022 || height == 1015 || height == 984 || height == 950 || height == 949 || height == 823 || height == 820 || height == 818 || height == 812 || height == 809 || height == 126 || height == 789 || height == 144 || height == 746 || height == 146 || height == 147 || height == 148 || height == 150 || height == 205 || height == 210 || height == 215 || height == 219 || height == 222 || height == 290 || height == 242 || height == 312 ) - return(0); - } - else if ( baseid == PHP ) - { - if ( height == 859 || height == 817 || height == 812 || height == 811 || height == 792 || height == 779 || height == 778 || height == 781 || height == 1154 || height == 1114 || height == 1077 || height == 1076 || height == 931 || height == 927 || height == 925 || height == 918 || height == 891 || height == 127 || height == 125 || height == 272 || height == 275 || height == 276 || height == 278 || height == 328 || height == 330 || height == 335 || height == 344 || height == 315 ) - return(0); - } - else if ( baseid == KRW ) - { - if ( height == 1021 || height == 1022 || height == 1023 || height == 1010 || height == 950 || height == 916 || height == 138 || height == 914 || height == 140 || height == 785 || height == 782 || height == 781 || height == 142 || height == 775 || height == 148 || height == 772 || height == 751 || height == 147 || height == 146 || height == 159 || height == 175 || height == 181 || height == 184 || height == 186 || height == 188 || height == 196 || height == 209 || height == 238 ) - return(0); - } - else if ( baseid == RON ) - { - if ( height == 1008 || height == 1009 || height == 1010 || height == 1003 || height == 973 || height == 940 || height == 939 || height == 806 || height == 802 || height == 800 || height == 793 || height == 789 || height == 768 || height == 123 || height == 141 || height == 143 || height == 144 || height == 150 || height == 197 || height == 200 || height == 202 || height == 217 || height == 240 || height == 276 ) - return(0); - } - else if ( baseid == SGD ) - { - if ( height == 1016 || height == 1017 || height == 1018 || height == 1010 || height == 984 || height == 951 || height == 950 || height == 801 || height == 798 || height == 792 || height == 788 || height == 122 || height == 769 || height == 120 || height == 158 || height == 160 || height == 164 || height == 169 || height == 229 || height == 234 || height == 246 || height == 297 || height == 299 || height == 316 || height == 233 ) - return(0); - } - else if ( baseid == THB ) - { - if ( height == 977 || height == 978 || height == 968 || height == 933 || height == 898 || height == 897 || height == 788 || height == 786 || height == 779 || height == 777 || height == 757 || height == 119 || height == 140 || height == 142 || height == 146 || height == 152 || height == 196 || height == 200 || height == 214 || height == 260 || height == 263 ) - return(0); - } - else if ( baseid == BGN ) - { - if ( height == 1044 || height == 1045 || height == 1046 || height == 1030 || height == 995 || height == 960 || height == 959 || height == 830 || height == 822 || height == 819 || height == 810 || height == 809 || height == 781 || height == 124 || height == 122 || height == 189 || height == 193 || height == 200 || height == 194 || height == 250 || height == 256 || height == 260 || height == 280 ) - return(0); - } - else if ( baseid == HRK ) - { - if ( height == 1027 || height == 1028 || height == 1029 || height == 1022 || height == 999 || height == 969 || height == 967 || height == 832 || height == 829 || height == 827 || height == 817 || height == 792 || height == 754 || height == 125 || height == 123 || height == 184 || height == 186 || height == 187 || height == 227 || height == 230 || height == 235 || height == 240 || height == 242 || height == 261 || height == 336 ) - return(0); - } - else if ( baseid == IDR ) - { - if ( height == 836 || height == 1036 || height == 837 || height == 720 || height == 715 || height == 714 || height == 696 || height == 695 || height == 694 || height == 693 || height == 119 || height == 689 || height == 120 || height == 669 || height == 123 || height == 662 || height == 122 || height == 634 || height == 121 || height == 609 || height == 124 || height == 174 || height == 603 || height == 595 || height == 166 || height == 176 || height == 589 || height == 172 || height == 587 || height == 179 || height == 239 || height == 175 || height == 245 || height == 260 ) - return(0); - } - } - if ( script[offset] == opcode && opretlen < block.vtx[0].vout[n-1].scriptPubKey.size() ) - { - if ( (num= komodo_issued_opreturn(base,txids,vouts,values,srcvalues,kmdheights,otherheights,baseids,rmd160s,&script[offset],opretlen,opcode == 'X')) > 0 ) - { - for (i=1; iRTmask & (1LL << 32)) == 0 ) - { - if ( rtflag == 0 ) - printf("[%s] skip checkdeposit.%s not RT %llx\n",ASSETCHAINS_SYMBOL,CURRENCIES[baseids[i-1]],(long long)sp->RTmask); - sleep(60); - rtflag = 1; - //matched++; - //continue; - } - if ( rtflag != 0 ) - printf("[%s] %s reached RT\n",ASSETCHAINS_SYMBOL,CURRENCIES[baseids[i-1]]); - } - if ( (pax= komodo_paxfinds(txids[i-1],vouts[i-1])) != 0 ) // finds... make sure right one - { - pax->type = opcode; - if ( opcode == 'I' && (pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,symbol) != 0 || available < pax->fiatoshis) ) - { - printf("checkdeposit.[%s.%d]: skip %s %.8f when avail %.8f deposited %.8f, issued %.8f withdrawn %.8f approved %.8f redeemed %.8f\n",ASSETCHAINS_SYMBOL,height,symbol,dstr(pax->fiatoshis),dstr(available),dstr(deposited),dstr(issued),dstr(withdrawn),dstr(approved),dstr(redeemed)); - return(-1); - } - if ( pax->fiatoshis == block.vtx[0].vout[i].nValue ) - { - matched++; - if ( pax->marked != 0 && height >= 80820 ) - { - printf(">>>>>>>>>>> %c errs.%d i.%d match %.8f vs %.8f paxmarked.%d kht.%d ht.%d [%s].%d\n",opcode,errs,i,dstr(opcode == 'I' ? pax->fiatoshis : pax->komodoshis),dstr(block.vtx[0].vout[i].nValue),pax->marked,pax->height,pax->otherheight,ASSETCHAINS_SYMBOL,height); - } - else - { - } - if ( strcmp(ASSETCHAINS_SYMBOL,CURRENCIES[baseids[i-1]]) == 0 ) - { - //check deposit validates AUD.1047 [3] 0.14585530 -> 0.01000000 (0.14585530 0.01000000 0.01000000) - char destaddr[64],coinaddr[64]; uint8_t pubkey33[33]; - checktoshis = PAX_fiatdest(&seed,0,destaddr,pubkey33,coinaddr,pax->height,CURRENCIES[baseids[i-1]],pax->fiatoshis); - //checktoshis = komodo_paxprice(&seed,pax->height,CURRENCIES[baseids[i-1]],(char *)"KMD",(uint64_t)pax->komodoshis); - if ( komodo_paxcmp(CURRENCIES[baseids[i-1]],pax->height,pax->komodoshis,checktoshis,seed) < 0 ) - { - printf("paxcmp FAIL when check deposit validates %s.%d [%d] %.8f -> %.8f (%.8f %.8f %.8f)\n",CURRENCIES[baseids[i-1]],height,i,dstr(srcvalues[i-1]),dstr(values[i-1]),dstr(pax->komodoshis),dstr(pax->fiatoshis),dstr(block.vtx[0].vout[i].nValue)); - return(-1); - } //else printf("check deposit validates %s.%d [%d] %.8f -> %.8f (%.8f %.8f %.8f)\n",CURRENCIES[baseids[i-1]],height,i,dstr(srcvalues[i-1]),dstr(values[i-1]),dstr(pax->komodoshis),dstr(pax->fiatoshis),dstr(block.vtx[0].vout[i].nValue)); - } - } - else if ( strcmp(ASSETCHAINS_SYMBOL,CURRENCIES[baseids[i-1]]) == 0 ) - { - for (j=0; j<32; j++) - printf("%02x",((uint8_t *)&txids[i-1])[j]); - printf(" cant paxfind %c txid [%d]\n",opcode,height); - printf(">>>>>>>>>>> %c errs.%d i.%d match %.8f vs %.8f pax.%p [%s] ht.%d\n",opcode,errs,i,dstr(opcode == 'I' ? pax->fiatoshis : pax->komodoshis),dstr(block.vtx[0].vout[i].nValue),pax,ASSETCHAINS_SYMBOL,height); - return(-1); - } - } - else //if ( kmdheights[i-1] > 0 && otherheights[i-1] > 0 ) - { - hash = block.GetHash(); - for (j=0; j= activation ) - return(-1); - } - } - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - { - //if ( height > 0 && (height < chainActive.Tip()->nHeight || (height >= chainActive.Tip()->nHeight && komodo_isrealtime(&ht) != 0)) && matched != num ) - //{ - // printf("WOULD REJECT %s: ht.%d (%c) matched.%d vs num.%d tip.%d isRT.%d\n",symbol,height,opcode,matched,num,(int32_t)chainActive.Tip()->nHeight,komodo_isrealtime(&ht)); - // can easily happen depending on order of loading - //if ( height > 200000 ) - //{ - // printf("REJECT: ht.%d (%c) matched.%d vs num.%d\n",height,opcode,matched,num); - // return(-1); - //} - //} // disabled 'X' path - } - else - { - if ( height > 0 && (height < chainActive.Tip()->nHeight || (height >= chainActive.Tip()->nHeight && komodo_isrealtime(&ht) != 0)) && matched != num ) - { - printf("REJECT %s: ht.%d (%c) matched.%d vs num.%d tip.%d isRT.%d\n",symbol,height,opcode,matched,num,(int32_t)chainActive.Tip()->nHeight,komodo_isrealtime(&ht)); - return(-1); - } - } - } - else - { - for (i=0; i= activation ) - return(-1); - } - //printf("opretlen.%d num.%d\n",opretlen,num); - } - else - { - for (i=0; i lastinterest ) + { + komodo_interestsum(); + komodo_longestchain(); + lastinterest = komodo_chainactive_timestamp(); + } refsp = komodo_stateptr(symbol,dest); if ( ASSETCHAINS_SYMBOL[0] == 0 ) { @@ -1967,12 +1508,12 @@ void komodo_passport_iteration() if ( sp != 0 && isrealtime == 0 ) refsp->RTbufs[0][2] = 0; } - komodo_paxtotal(); + //komodo_paxtotal(); // calls komodo_isrealtime(), which calls komodo_longestchain() refsp->RTmask |= RTmask; if ( expired == 0 && KOMODO_PASSPORT_INITDONE == 0 ) { KOMODO_PASSPORT_INITDONE = 1; - printf("done PASSPORT %s refid.%d\n",ASSETCHAINS_SYMBOL,refid); + printf("READY for %s RPC calls at %u! done PASSPORT %s refid.%d\n",ASSETCHAINS_SYMBOL,(uint32_t)time(NULL),ASSETCHAINS_SYMBOL,refid); } } diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 31ba6c32c..b4f886e4b 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2017 The SuperNET Developers. * + * Copyright © 2014-2018 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -15,6 +15,7 @@ #include "komodo_defs.h" +void komodo_prefetch(FILE *fp); uint32_t komodo_heightstamp(int32_t height); 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 kheight,uint32_t ktime,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth); void komodo_init(int32_t height); @@ -22,7 +23,6 @@ int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,in int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp); char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port); void komodo_init(int32_t height); -void komodo_assetchain_pubkeys(char *jsonstr); int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); int32_t komodo_isrealtime(int32_t *kmdheightp); uint64_t komodo_paxtotal(); @@ -46,19 +46,22 @@ struct komodo_state KOMODO_STATES[34]; int COINBASE_MATURITY = _COINBASE_MATURITY;//100; int32_t IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE,KOMODO_PAX,KOMODO_EXCHANGEWALLET,KOMODO_REWIND; -int32_t KOMODO_LASTMINED,prevKOMODO_LASTMINED,JUMBLR_PAUSE; -std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY; -uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33]; +int32_t KOMODO_LASTMINED,prevKOMODO_LASTMINED,JUMBLR_PAUSE = 1; +std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY; +uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_PUBLIC; char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],ASSETCHAINS_USERPASS[4096]; -uint16_t ASSETCHAINS_PORT; +uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; uint32_t ASSETCHAIN_INIT,ASSETCHAINS_CC; uint32_t ASSETCHAINS_MAGIC = 2387029918; +uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; uint64_t ASSETCHAINS_ENDSUBSIDY,ASSETCHAINS_REWARD,ASSETCHAINS_HALVING,ASSETCHAINS_DECAY,ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED,ASSETCHAINS_SUPPLY = 10; uint32_t KOMODO_INITDONE; -char KMDUSERPASS[4096],BTCUSERPASS[4096]; uint16_t KMD_PORT = 7771,BITCOIND_PORT = 7771; +char KMDUSERPASS[8192],BTCUSERPASS[8192]; uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771; uint64_t PENDING_KOMODO_TX; +extern int32_t KOMODO_LOADINGBLOCKS; +unsigned int MAX_BLOCK_SIGOPS = 20000; struct komodo_kv *KOMODO_KV; -pthread_mutex_t KOMODO_KV_mutex; +pthread_mutex_t KOMODO_KV_mutex,KOMODO_CC_mutex; diff --git a/src/komodo_interest.h b/src/komodo_interest.h index 07b12cfe1..3141532fa 100644 --- a/src/komodo_interest.h +++ b/src/komodo_interest.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2017 The SuperNET Developers. * + * Copyright © 2014-2018 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -80,14 +80,16 @@ uint64_t komodo_moneysupply(int32_t height) } #endif -uint64_t _komodo_interestnew(uint64_t nValue,uint32_t nLockTime,uint32_t tiptime) +uint64_t _komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime) { int32_t minutes; uint64_t interest = 0; - if ( nLockTime >= LOCKTIME_THRESHOLD && tiptime > nLockTime && (minutes= (tiptime - nLockTime) / 60) >= 60 ) + if ( nLockTime >= LOCKTIME_THRESHOLD && tiptime > nLockTime && (minutes= (tiptime - nLockTime) / 60) >= (KOMODO_MAXMEMPOOLTIME/60) ) { if ( minutes > 365 * 24 * 60 ) minutes = 365 * 24 * 60; - minutes -= 59; + if ( txheight >= 1000000 && minutes > 31 * 24 * 60 ) + minutes = 31 * 24 * 60; + minutes -= ((KOMODO_MAXMEMPOOLTIME/60) - 1); interest = ((nValue / 10512000) * minutes); } return(interest); @@ -97,7 +99,7 @@ uint64_t komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime, { uint64_t interest = 0; if ( txheight < KOMODO_ENDOFERA && nLockTime >= LOCKTIME_THRESHOLD && tiptime != 0 && nLockTime < tiptime && nValue >= 10*COIN ) //komodo_moneysupply(txheight) < MAX_MONEY && - interest = _komodo_interestnew(nValue,nLockTime,tiptime); + interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); return(interest); } @@ -151,21 +153,21 @@ uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uin else if ( txheight < 1000000 ) { interest = (numerator * minutes) / ((uint64_t)365 * 24 * 60); - interestnew = _komodo_interestnew(nValue,nLockTime,tiptime); + interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); if ( interest < interestnew ) printf("pathA current interest %.8f vs new %.8f for ht.%d %.8f locktime.%u tiptime.%u\n",dstr(interest),dstr(interestnew),txheight,dstr(nValue),nLockTime,tiptime); } - else interest = _komodo_interestnew(nValue,nLockTime,tiptime); + else interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); } else if ( txheight < 1000000 ) { numerator = (nValue * KOMODO_INTEREST); interest = (numerator / denominator) / COIN; - interestnew = _komodo_interestnew(nValue,nLockTime,tiptime); + interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); if ( interest < interestnew ) printf("pathB current interest %.8f vs new %.8f for ht.%d %.8f locktime.%u tiptime.%u\n",dstr(interest),dstr(interestnew),txheight,dstr(nValue),nLockTime,tiptime); } - else interest = _komodo_interestnew(nValue,nLockTime,tiptime); + else interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); } else { @@ -187,11 +189,11 @@ uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uin numerator = (nValue / 20); // assumes 5%! interest = ((numerator * minutes) / ((uint64_t)365 * 24 * 60)); //fprintf(stderr,"interest %llu %.8f <- numerator.%llu minutes.%d\n",(long long)interest,(double)interest/COIN,(long long)numerator,(int32_t)minutes); - interestnew = _komodo_interestnew(nValue,nLockTime,tiptime); + interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); if ( interest < interestnew ) fprintf(stderr,"pathC current interest %.8f vs new %.8f for ht.%d %.8f locktime.%u tiptime.%u\n",dstr(interest),dstr(interestnew),txheight,dstr(nValue),nLockTime,tiptime); } - else interest = _komodo_interestnew(nValue,nLockTime,tiptime); + else interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); } if ( 0 && numerator == (nValue * KOMODO_INTEREST) ) fprintf(stderr,"komodo_interest.%d %lld %.8f nLockTime.%u tiptime.%u minutes.%d interest %lld %.8f (%llu / %llu) prod.%llu\n",txheight,(long long)nValue,(double)nValue/COIN,nLockTime,tiptime,minutes,(long long)interest,(double)interest/COIN,(long long)numerator,(long long)denominator,(long long)(numerator * minutes)); diff --git a/src/komodo_jumblr.h b/src/komodo_jumblr.h index 951ed9de0..f36bb441a 100755 --- a/src/komodo_jumblr.h +++ b/src/komodo_jumblr.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2017 The SuperNET Developers. * + * Copyright © 2014-2018 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -83,7 +83,7 @@ char *jumblr_importaddress(char *address) { char params[1024]; sprintf(params,"[\"%s\", \"%s\", false]",address,address); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"importaddress",params,BITCOIND_PORT)); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"importaddress",params,BITCOIND_RPCPORT)); } char *jumblr_validateaddress(char *addr) @@ -91,7 +91,7 @@ char *jumblr_validateaddress(char *addr) char params[1024]; sprintf(params,"[\"%s\"]",addr); printf("validateaddress.%s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"validateaddress",params,BITCOIND_PORT)); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"validateaddress",params,BITCOIND_RPCPORT)); } int32_t Jumblr_secretaddrfind(char *searchaddr) @@ -222,28 +222,28 @@ char *jumblr_zgetnewaddress() { char params[1024]; sprintf(params,"[]"); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getnewaddress",params,BITCOIND_PORT)); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getnewaddress",params,BITCOIND_RPCPORT)); } char *jumblr_zlistoperationids() { char params[1024]; sprintf(params,"[]"); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listoperationids",params,BITCOIND_PORT)); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listoperationids",params,BITCOIND_RPCPORT)); } char *jumblr_zgetoperationresult(char *opid) { char params[1024]; sprintf(params,"[[\"%s\"]]",opid); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getoperationresult",params,BITCOIND_PORT)); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getoperationresult",params,BITCOIND_RPCPORT)); } char *jumblr_zgetoperationstatus(char *opid) { char params[1024]; sprintf(params,"[[\"%s\"]]",opid); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getoperationstatus",params,BITCOIND_PORT)); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getoperationstatus",params,BITCOIND_RPCPORT)); } char *jumblr_sendt_to_z(char *taddr,char *zaddr,double amount) @@ -253,7 +253,7 @@ char *jumblr_sendt_to_z(char *taddr,char *zaddr,double amount) return(clonestr((char *)"{\"error\":\"illegal address in t to z\"}")); sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",taddr,zaddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); printf("t -> z: %s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_PORT)); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); } char *jumblr_sendz_to_z(char *zaddrS,char *zaddrD,double amount) @@ -264,7 +264,7 @@ char *jumblr_sendz_to_z(char *zaddrS,char *zaddrD,double amount) //sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_TXFEE); printf("z -> z: %s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_PORT)); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); } char *jumblr_sendz_to_t(char *zaddr,char *taddr,double amount) @@ -274,56 +274,56 @@ char *jumblr_sendz_to_t(char *zaddr,char *taddr,double amount) return(clonestr((char *)"{\"error\":\"illegal address in z to t\"}")); sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddr,taddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); printf("z -> t: %s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_PORT)); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); } char *jumblr_zlistaddresses() { char params[1024]; sprintf(params,"[]"); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listaddresses",params,BITCOIND_PORT)); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listaddresses",params,BITCOIND_RPCPORT)); } char *jumblr_zlistreceivedbyaddress(char *addr) { char params[1024]; sprintf(params,"[\"%s\", 1]",addr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listreceivedbyaddress",params,BITCOIND_PORT)); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listreceivedbyaddress",params,BITCOIND_RPCPORT)); } char *jumblr_getreceivedbyaddress(char *addr) { char params[1024]; sprintf(params,"[\"%s\", 1]",addr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"getreceivedbyaddress",params,BITCOIND_PORT)); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"getreceivedbyaddress",params,BITCOIND_RPCPORT)); } char *jumblr_importprivkey(char *wifstr) { char params[1024]; sprintf(params,"[\"%s\", \"\", false]",wifstr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"importprivkey",params,BITCOIND_PORT)); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"importprivkey",params,BITCOIND_RPCPORT)); } char *jumblr_zgetbalance(char *addr) { char params[1024]; sprintf(params,"[\"%s\", 1]",addr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getbalance",params,BITCOIND_PORT)); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getbalance",params,BITCOIND_RPCPORT)); } char *jumblr_listunspent(char *coinaddr) { char params[1024]; sprintf(params,"[1, 99999999, [\"%s\"]]",coinaddr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"listunspent",params,BITCOIND_PORT)); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"listunspent",params,BITCOIND_RPCPORT)); } char *jumblr_gettransaction(char *txidstr) { char params[1024]; sprintf(params,"[\"%s\", 1]",txidstr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,BITCOIND_PORT)); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,BITCOIND_RPCPORT)); } int32_t jumblr_numvins(bits256 txid) diff --git a/src/komodo_kv.h b/src/komodo_kv.h index 7c20becb1..ee0496aae 100644 --- a/src/komodo_kv.h +++ b/src/komodo_kv.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2017 The SuperNET Developers. * + * Copyright © 2014-2018 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -64,7 +64,7 @@ int32_t komodo_kvsearch(uint256 *pubkeyp,int32_t current_height,uint32_t *flagsp if ( ptr != 0 ) { duration = komodo_kvduration(ptr->flags); - //printf("duration.%d flags.%d current.%d ht.%d keylen.%d valuesize.%d\n",duration,ptr->flags,current_height,ptr->height,ptr->keylen,ptr->valuesize); + fprintf(stderr,"duration.%d flags.%d current.%d ht.%d keylen.%d valuesize.%d\n",duration,ptr->flags,current_height,ptr->height,ptr->keylen,ptr->valuesize); if ( current_height > (ptr->height + duration) ) { HASH_DELETE(hh,KOMODO_KV,ptr); @@ -88,7 +88,7 @@ int32_t komodo_kvsearch(uint256 *pubkeyp,int32_t current_height,uint32_t *flagsp if ( (retval= ptr->valuesize) > 0 ) memcpy(value,ptr->value,retval); } - } + } else fprintf(stderr,"couldnt find (%s)\n",(char *)key); portable_mutex_unlock(&KOMODO_KV_mutex); if ( retval < 0 ) { @@ -112,12 +112,12 @@ void komodo_kvupdate(uint8_t *opretbuf,int32_t opretlen,uint64_t value) { static uint32_t counter; if ( ++counter < 1 ) - printf("komodo_kvupdate: keylen.%d + 13 > opretlen.%d, this can be ignored\n",keylen,opretlen); + fprintf(stderr,"komodo_kvupdate: keylen.%d + 13 > opretlen.%d, this can be ignored\n",keylen,opretlen); return; } valueptr = &key[keylen]; fee = komodo_kvfee(flags,opretlen,keylen); - //printf("fee %.8f vs %.8f flags.%d keylen.%d valuesize.%d height.%d (%02x %02x %02x) (%02x %02x %02x)\n",(double)fee/COIN,(double)value/COIN,flags,keylen,valuesize,height,key[0],key[1],key[2],valueptr[0],valueptr[1],valueptr[2]); + printf("fee %.8f vs %.8f flags.%d keylen.%d valuesize.%d height.%d (%02x %02x %02x) (%02x %02x %02x)\n",(double)fee/COIN,(double)value/COIN,flags,keylen,valuesize,height,key[0],key[1],key[2],valueptr[0],valueptr[1],valueptr[2]); if ( value >= fee ) { coresize = (int32_t)(sizeof(flags)+sizeof(height)+sizeof(keylen)+sizeof(valuesize)+keylen+valuesize+1); @@ -142,7 +142,7 @@ void komodo_kvupdate(uint8_t *opretbuf,int32_t opretlen,uint64_t value) { if ( komodo_kvsigverify(keyvalue,keylen+refvaluesize,refpubkey,sig) < 0 ) { - printf("komodo_kvsigverify error [%d]\n",coresize-13); + fprintf(stderr,"komodo_kvsigverify error [%d]\n",coresize-13); return; } } @@ -151,6 +151,7 @@ void komodo_kvupdate(uint8_t *opretbuf,int32_t opretlen,uint64_t value) HASH_FIND(hh,KOMODO_KV,key,keylen,ptr); if ( ptr != 0 ) { + fprintf(stderr,"(%s) already there\n",(char *)key); //if ( (ptr->flags & KOMODO_KVPROTECTED) != 0 ) { tstr = (char *)"transfer:"; @@ -171,7 +172,7 @@ void komodo_kvupdate(uint8_t *opretbuf,int32_t opretlen,uint64_t value) memcpy(ptr->key,key,keylen); newflag = 1; HASH_ADD_KEYPTR(hh,KOMODO_KV,ptr->key,ptr->keylen,ptr); - //printf("KV add.(%s) (%s)\n",ptr->key,valueptr); + fprintf(stderr,"KV add.(%s) (%s)\n",ptr->key,valueptr); } if ( newflag != 0 || (ptr->flags & KOMODO_KVPROTECTED) == 0 ) { @@ -193,7 +194,7 @@ void komodo_kvupdate(uint8_t *opretbuf,int32_t opretlen,uint64_t value) ptr->height = height; ptr->flags = flags; // jl777 used to or in KVPROTECTED portable_mutex_unlock(&KOMODO_KV_mutex); - } else fprintf(stderr,"size mismatch %d vs %d\n",opretlen,coresize); + } else fprintf(stderr,"KV update size mismatch %d vs %d\n",opretlen,coresize); } else fprintf(stderr,"not enough fee\n"); } diff --git a/src/komodo_notary.h b/src/komodo_notary.h index ca56ecb61..4711a9afc 100644 --- a/src/komodo_notary.h +++ b/src/komodo_notary.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2017 The SuperNET Developers. * + * Copyright © 2014-2018 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -13,6 +13,7 @@ * * ******************************************************************************/ + #include "komodo_defs.h" #include "komodo_cJSON.h" @@ -127,7 +128,7 @@ const char *Notaries_elected0[][2] = }; #define KOMODO_NOTARIES_TIMESTAMP1 1525132800 // May 1st 2018 1530921600 // 7/7/2017 -#define KOMODO_NOTARIES_HEIGHT1 ((820000 / KOMODO_ELECTION_GAP) * KOMODO_ELECTION_GAP) +#define KOMODO_NOTARIES_HEIGHT1 ((814000 / KOMODO_ELECTION_GAP) * KOMODO_ELECTION_GAP) const char *Notaries_elected1[][2] = { @@ -141,7 +142,7 @@ const char *Notaries_elected1[][2] = {"artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, {"artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, {"badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, - {"badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, + {"badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, // 10 {"batman_AR", "033ecb640ec5852f42be24c3bf33ca123fb32ced134bed6aa2ba249cf31b0f2563" }, {"batman_SH", "02ca5898931181d0b8aafc75ef56fce9c43656c0b6c9f64306e7c8542f6207018c" }, {"ca333_EU", "03fc87b8c804f12a6bd18efd43b0ba2828e4e38834f6b44c0bfee19f966a12ba99" }, @@ -151,7 +152,7 @@ const char *Notaries_elected1[][2] = {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, {"crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, - {"crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, + {"crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, // 20 {"dwy_EU", "0259c646288580221fdf0e92dbeecaee214504fdc8bbdf4a3019d6ec18b7540424" }, {"emmanux_SH", "033f316114d950497fc1d9348f03770cd420f14f662ab2db6172df44c389a2667a" }, {"etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, @@ -161,7 +162,7 @@ const char *Notaries_elected1[][2] = {"goldenman_EU", "02d6f13a8f745921cdb811e32237bb98950af1a5952be7b3d429abd9152f8e388d" }, {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, + {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, // 30 {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, {"jackson_AR", "038ff7cfe34cb13b524e0941d5cf710beca2ffb7e05ddf15ced7d4f14fbb0a6f69" }, {"jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, @@ -171,7 +172,7 @@ const char *Notaries_elected1[][2] = {"komodopioneers_SH", "033ace50aedf8df70035b962a805431363a61cc4e69d99d90726a2d48fb195f68c" }, {"libscott_SH", "03301a8248d41bc5dc926088a8cf31b65e2daf49eed7eb26af4fb03aae19682b95" }, {"lukechilds_AR", "031aa66313ee024bbee8c17915cf7d105656d0ace5b4a43a3ab5eae1e14ec02696" }, - {"madmax_AR", "03891555b4a4393d655bf76f0ad0fb74e5159a615b6925907678edc2aac5e06a75" }, + {"madmax_AR", "03891555b4a4393d655bf76f0ad0fb74e5159a615b6925907678edc2aac5e06a75" }, // 40 {"meshbits_AR", "02957fd48ae6cb361b8a28cdb1b8ccf5067ff68eb1f90cba7df5f7934ed8eb4b2c" }, {"meshbits_SH", "025c6e94877515dfd7b05682b9cc2fe4a49e076efe291e54fcec3add78183c1edb" }, {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, @@ -181,7 +182,7 @@ const char *Notaries_elected1[][2] = {"peer2cloud_AR", "034e5563cb885999ae1530bd66fab728e580016629e8377579493b386bf6cebb15" }, {"peer2cloud_SH", "03396ac453b3f23e20f30d4793c5b8ab6ded6993242df4f09fd91eb9a4f8aede84" }, {"polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, - {"hyper_AR", "020f2f984d522051bd5247b61b080b4374a7ab389d959408313e8062acad3266b4" }, + {"hyper_AR", "020f2f984d522051bd5247b61b080b4374a7ab389d959408313e8062acad3266b4" }, // 50 {"hyper_EU", "03d00cf9ceace209c59fb013e112a786ad583d7de5ca45b1e0df3b4023bb14bf51" }, {"hyper_SH", "0383d0b37f59f4ee5e3e98a47e461c861d49d0d90c80e9e16f7e63686a2dc071f3" }, {"hyper_NA", "03d91c43230336c0d4b769c9c940145a8c53168bf62e34d1bccd7f6cfc7e5592de" }, @@ -191,7 +192,7 @@ const char *Notaries_elected1[][2] = {"alien_EU", "020aab8308d4df375a846a9e3b1c7e99597b90497efa021d50bcf1bbba23246527" }, {"thegaltmines_NA", "031bea28bec98b6380958a493a703ddc3353d7b05eb452109a773eefd15a32e421" }, {"titomane_AR", "029d19215440d8cb9cc6c6b7a4744ae7fb9fb18d986e371b06aeb34b64845f9325" }, - {"titomane_EU", "0360b4805d885ff596f94312eed3e4e17cb56aa8077c6dd78d905f8de89da9499f" }, + {"titomane_EU", "0360b4805d885ff596f94312eed3e4e17cb56aa8077c6dd78d905f8de89da9499f" }, // 60 {"titomane_SH", "03573713c5b20c1e682a2e8c0f8437625b3530f278e705af9b6614de29277a435b" }, {"webworker01_NA", "03bb7d005e052779b1586f071834c5facbb83470094cff5112f0072b64989f97d7" }, {"xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, @@ -382,39 +383,74 @@ int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33, } //struct komodo_state *komodo_stateptr(char *symbol,char *dest); -int32_t komodo_notarized_height(uint256 *hashp,uint256 *txidp) -{ - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - { - *hashp = sp->NOTARIZED_HASH; - *txidp = sp->NOTARIZED_DESTTXID; - return(sp->NOTARIZED_HEIGHT); - } - else - { - memset(hashp,0,sizeof(*hashp)); - memset(txidp,0,sizeof(*txidp)); - return(0); - } -} - -struct notarized_checkpoint *komodo_npptr(int32_t height) +struct notarized_checkpoint *komodo_npptr_for_height(int32_t height, int *idx) { char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; int32_t i; struct komodo_state *sp; struct notarized_checkpoint *np = 0; if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) { for (i=sp->NUM_NPOINTS-1; i>=0; i--) { + *idx = i; np = &sp->NPOINTS[i]; - if ( np->MoMdepth > 0 && height > np->notarized_height-np->MoMdepth && height <= np->notarized_height ) + if ( np->MoMdepth != 0 && height > np->notarized_height-(np->MoMdepth&0xffff) && height <= np->notarized_height ) return(np); } } + *idx = -1; return(0); } +struct notarized_checkpoint *komodo_npptr(int32_t height) +{ + int idx; + return komodo_npptr_for_height(height, &idx); +} + +struct notarized_checkpoint *komodo_npptr_at(int idx) +{ + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) + if (idx < sp->NUM_NPOINTS) + return &sp->NPOINTS[idx]; + return(0); +} + +int32_t komodo_prevMoMheight() +{ + static uint256 zero; + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; int32_t i; struct komodo_state *sp; struct notarized_checkpoint *np = 0; + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) + { + for (i=sp->NUM_NPOINTS-1; i>=0; i--) + { + np = &sp->NPOINTS[i]; + if ( np->MoM != zero ) + return(np->notarized_height); + } + } + return(0); +} + +int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp) +{ + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) + { + *hashp = sp->NOTARIZED_HASH; + *txidp = sp->NOTARIZED_DESTTXID; + *prevMoMheightp = komodo_prevMoMheight(); + return(sp->NOTARIZED_HEIGHT); + } + else + { + *prevMoMheightp = 0; + memset(hashp,0,sizeof(*hashp)); + memset(txidp,0,sizeof(*txidp)); + return(0); + } +} + int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t height,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip) { struct notarized_checkpoint *np = 0; @@ -428,7 +464,7 @@ int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,in *MoMoMdepthp = np->MoMoMdepth; *kmdstartip = np->kmdstarti; *kmdendip = np->kmdendi; - return(np->MoMdepth); + return(np->MoMdepth & 0xffff); } *notarized_htp = *MoMoMoffsetp = *MoMoMdepthp = *kmdstartip = *kmdendip = 0; memset(MoMp,0,sizeof(*MoMp)); @@ -437,7 +473,6 @@ int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,in return(0); } - int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp) { struct notarized_checkpoint *np = 0; int32_t i=0,flag = 0; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; @@ -543,50 +578,4 @@ void komodo_init(int32_t height) didinit = 1; komodo_stateupdate(0,0,0,0,zero,0,0,0,0,0,0,0,0,0,0,zero,0); } - /*else if ( 0 && height == KOMODO_MAINNET_START ) - { - n = (int32_t)(sizeof(Notaries_elected)/sizeof(*Notaries_elected)); - for (k=0; k 0 ) - { - for (i=0; i offset + 6 ) decay = (long long)atof(argv[offset + 6]); - rpcport = 1 + komodo_calcport(argv[offset + 1],supply,endsubsidy,reward,halving,decay); - printf("./komodod -ac_name=%s -ac_supply=%llu -ac_end=%llu -ac_reward=%llu -ac_halving=%llu -ac_decay=%llu & # rpcport %u\n",argv[offset + 1],(long long)supply,(long long)endsubsidy,(long long)reward,(long long)halving,(long long)decay,rpcport); + rpcport = 1 + komodo_calcport(argv[offset + 1],supply,endsubsidy,reward,halving,decay,commission,staked,cc); + printf("./komodod -ac_name=%s -ac_cc=%u -ac_supply=%llu -ac_end=%llu -ac_reward=%llu -ac_halving=%llu -ac_decay=%llu & # rpcport %u\n[",argv[offset + 1],cc,(long long)supply,(long long)endsubsidy,(long long)reward,(long long)halving,(long long)decay,rpcport); if ( allocated != 0 ) { char name[64],newname[64]; @@ -859,14 +863,21 @@ int main(int argc, char * argv[]) allocated[rpcport-1] = 1; for (i=0; i [%s] statename.(%s) %s\n",test,ASSETCHAINS_SYMBOL,symbol,fname); } -void komodo_configfile(char *symbol,uint16_t port) +void komodo_configfile(char *symbol,uint16_t rpcport) { static char myusername[512],mypassword[8192]; FILE *fp; uint16_t kmdport; uint8_t buf2[33]; char fname[512],buf[128],username[512],password[8192]; uint32_t crc,r,r2,i; - if ( symbol != 0 && port != 0 ) + if ( symbol != 0 && rpcport != 0 ) { r = (uint32_t)time(NULL); r2 = OS_milliseconds(); @@ -1354,7 +1354,7 @@ void komodo_configfile(char *symbol,uint16_t port) sprintf(&password[i*2],"%02x",buf2[i]); password[i*2] = 0; sprintf(buf,"%s.conf",symbol); - BITCOIND_PORT = port; + BITCOIND_RPCPORT = rpcport; #ifdef _WIN32 sprintf(fname,"%s\\%s",GetDataDir(false).string().c_str(),buf); #else @@ -1365,7 +1365,7 @@ void komodo_configfile(char *symbol,uint16_t port) #ifndef FROM_CLI if ( (fp= fopen(fname,"wb")) != 0 ) { - fprintf(fp,"rpcuser=user%u\nrpcpassword=pass%s\nrpcport=%u\nserver=1\ntxindex=1\nrpcworkqueue=64\nrpcallowip=127.0.0.1\n",crc,password,port); + fprintf(fp,"rpcuser=user%u\nrpcpassword=pass%s\nrpcport=%u\nserver=1\ntxindex=1\nrpcworkqueue=256\nrpcallowip=127.0.0.1\n",crc,password,rpcport); fclose(fp); printf("Created (%s)\n",fname); } else printf("Couldnt create (%s)\n",fname); @@ -1373,7 +1373,7 @@ void komodo_configfile(char *symbol,uint16_t port) } else { - komodo_userpass(myusername,mypassword,fp); + _komodo_userpass(myusername,mypassword,fp); mapArgs["-rpcpassword"] = mypassword; mapArgs["-rpcusername"] = myusername; //fprintf(stderr,"myusername.(%s)\n",myusername); @@ -1396,7 +1396,7 @@ void komodo_configfile(char *symbol,uint16_t port) #endif if ( (fp= fopen(fname,"rb")) != 0 ) { - if ( (kmdport= komodo_userpass(username,password,fp)) != 0 ) + if ( (kmdport= _komodo_userpass(username,password,fp)) != 0 ) KMD_PORT = kmdport; sprintf(KMDUSERPASS,"%s:%s",username,password); fclose(fp); @@ -1420,12 +1420,11 @@ uint16_t komodo_userpass(char *userpass,char *symbol) komodo_statefname(fname,symbol,confname); if ( (fp= fopen(fname,"rb")) != 0 ) { - port = komodo_userpass(username,password,fp); + port = _komodo_userpass(username,password,fp); sprintf(userpass,"%s:%s",username,password); if ( strcmp(symbol,ASSETCHAINS_SYMBOL) == 0 ) strcpy(ASSETCHAINS_USERPASS,userpass); fclose(fp); - return((int32_t)strlen(userpass)); } return(port); } @@ -1477,7 +1476,7 @@ uint16_t komodo_port(char *symbol,uint64_t supply,uint32_t *magicp,uint8_t *extr printf("ports\n"); }*/ -char *iguanafmtstr = (char *)"curl --url \"http://127.0.0.1:7778\" --data \"{\\\"conf\\\":\\\"%s.conf\\\",\\\"path\\\":\\\"${HOME#\"/\"}/.komodo/%s\\\",\\\"unitval\\\":\\\"20\\\",\\\"zcash\\\":1,\\\"RELAY\\\":1,\\\"VALIDATE\\\":1,\\\"prefetchlag\\\":-1,\\\"poll\\\":100,\\\"active\\\":1,\\\"agent\\\":\\\"iguana\\\",\\\"method\\\":\\\"addcoin\\\",\\\"startpend\\\":4,\\\"endpend\\\":4,\\\"services\\\":129,\\\"maxpeers\\\":8,\\\"newcoin\\\":\\\"%s\\\",\\\"name\\\":\\\"%s\\\",\\\"hasheaders\\\":1,\\\"useaddmultisig\\\":0,\\\"netmagic\\\":\\\"%s\\\",\\\"p2p\\\":%u,\\\"rpc\\\":%u,\\\"pubval\\\":60,\\\"p2shval\\\":85,\\\"wifval\\\":188,\\\"txfee_satoshis\\\":\\\"10000\\\",\\\"isPoS\\\":0,\\\"minoutput\\\":10000,\\\"minconfirms\\\":2,\\\"genesishash\\\":\\\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\\\",\\\"protover\\\":170002,\\\"genesisblock\\\":\\\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\\\",\\\"debug\\\":0,\\\"seedipaddr\\\":\\\"%s\\\"}\""; +char *iguanafmtstr = (char *)"curl --url \"http://127.0.0.1:7776\" --data \"{\\\"conf\\\":\\\"%s.conf\\\",\\\"path\\\":\\\"${HOME#\"/\"}/.komodo/%s\\\",\\\"unitval\\\":\\\"20\\\",\\\"zcash\\\":1,\\\"RELAY\\\":-1,\\\"VALIDATE\\\":0,\\\"prefetchlag\\\":-1,\\\"poll\\\":100,\\\"active\\\":1,\\\"agent\\\":\\\"iguana\\\",\\\"method\\\":\\\"addcoin\\\",\\\"startpend\\\":4,\\\"endpend\\\":4,\\\"services\\\":129,\\\"maxpeers\\\":8,\\\"newcoin\\\":\\\"%s\\\",\\\"name\\\":\\\"%s\\\",\\\"hasheaders\\\":1,\\\"useaddmultisig\\\":0,\\\"netmagic\\\":\\\"%s\\\",\\\"p2p\\\":%u,\\\"rpc\\\":%u,\\\"pubval\\\":60,\\\"p2shval\\\":85,\\\"wifval\\\":188,\\\"txfee_satoshis\\\":\\\"10000\\\",\\\"isPoS\\\":0,\\\"minoutput\\\":10000,\\\"minconfirms\\\":2,\\\"genesishash\\\":\\\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\\\",\\\"protover\\\":170002,\\\"genesisblock\\\":\\\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\\\",\\\"debug\\\":0,\\\"seedipaddr\\\":\\\"%s\\\"}\""; int32_t komodo_whoami(char *pubkeystr,int32_t height,uint32_t timestamp) @@ -1503,14 +1502,26 @@ char *argv0names[] = void komodo_args(char *argv0) { extern int64_t MAX_MONEY; - std::string name,addn; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[256],*extraptr=0; FILE *fp; uint64_t val; int32_t i,baseid,len,n,extralen = 0; + extern const char *Notaries_elected1[][2]; + std::string name,addn; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[256],*extraptr=0; FILE *fp; uint64_t val; uint16_t port; int32_t i,baseid,len,n,extralen = 0; IS_KOMODO_NOTARY = GetBoolArg("-notary", false); if ( (KOMODO_EXCHANGEWALLET= GetBoolArg("-exchange", false)) != 0 ) fprintf(stderr,"KOMODO_EXCHANGEWALLET mode active\n"); + DONATION_PUBKEY = GetArg("-donation", ""); NOTARY_PUBKEY = GetArg("-pubkey", ""); if ( strlen(NOTARY_PUBKEY.c_str()) == 66 ) { USE_EXTERNAL_PUBKEY = 1; + if ( IS_KOMODO_NOTARY == 0 ) + { + for (i=0; i<64; i++) + if ( strcmp(NOTARY_PUBKEY.c_str(),Notaries_elected1[i][1]) == 0 ) + { + IS_KOMODO_NOTARY = 1; + fprintf(stderr,"running as notary.%d %s\n",i,Notaries_elected1[i][0]); + break; + } + } //KOMODO_PAX = 1; } //else KOMODO_PAX = GetArg("-pax",0); name = GetArg("-ac_name",""); @@ -1528,13 +1539,15 @@ void komodo_args(char *argv0) } } } - ASSETCHAINS_CC = GetArg("-ac_cc",0); // keep it outside the assetchains hashing so KMD can do it and we dont have two identical chains other than -ac_cc + ASSETCHAINS_CC = GetArg("-ac_cc",0); + ASSETCHAINS_PUBLIC = GetArg("-ac_public",0); if ( (KOMODO_REWIND= GetArg("-rewind",0)) != 0 ) { printf("KOMODO_REWIND %d\n",KOMODO_REWIND); } if ( name.c_str()[0] != 0 ) { + MAX_BLOCK_SIGOPS = 60000; ASSETCHAINS_SUPPLY = GetArg("-ac_supply",10); ASSETCHAINS_ENDSUBSIDY = GetArg("-ac_end",0); ASSETCHAINS_REWARD = GetArg("-ac_reward",0); @@ -1559,14 +1572,14 @@ void komodo_args(char *argv0) ASSETCHAINS_DECAY = 0; printf("ASSETCHAINS_DECAY cant be more than 100000000\n"); } - if ( strlen(ASSETCHAINS_OVERRIDE_PUBKEY.c_str()) == 66 && ASSETCHAINS_COMMISSION > 0 && ASSETCHAINS_COMMISSION <= 100000000 ) + if ( strlen(ASSETCHAINS_OVERRIDE_PUBKEY.c_str()) == 66 ) decode_hex(ASSETCHAINS_OVERRIDE_PUBKEY33,33,(char *)ASSETCHAINS_OVERRIDE_PUBKEY.c_str()); else if ( ASSETCHAINS_COMMISSION != 0 ) { ASSETCHAINS_COMMISSION = 0; printf("ASSETCHAINS_COMMISSION needs an ASETCHAINS_OVERRIDE_PUBKEY and cant be more than 100000000 (100%%)\n"); } - if ( ASSETCHAINS_ENDSUBSIDY != 0 || ASSETCHAINS_REWARD != 0 || ASSETCHAINS_HALVING != 0 || ASSETCHAINS_DECAY != 0 || ASSETCHAINS_COMMISSION != 0 ) + if ( ASSETCHAINS_ENDSUBSIDY != 0 || ASSETCHAINS_REWARD != 0 || ASSETCHAINS_HALVING != 0 || ASSETCHAINS_DECAY != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 ) { fprintf(stderr,"end.%llu blocks, reward %.8f halving.%llu blocks, decay.%llu perc %.4f%% ac_pub=[%02x...]\n",(long long)ASSETCHAINS_ENDSUBSIDY,dstr(ASSETCHAINS_REWARD),(long long)ASSETCHAINS_HALVING,(long long)ASSETCHAINS_DECAY,dstr(ASSETCHAINS_COMMISSION)*100,ASSETCHAINS_OVERRIDE_PUBKEY33[0]); extraptr = extrabuf; @@ -1575,13 +1588,13 @@ void komodo_args(char *argv0) extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_REWARD),(void *)&ASSETCHAINS_REWARD); extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_HALVING),(void *)&ASSETCHAINS_HALVING); extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_DECAY),(void *)&ASSETCHAINS_DECAY); - val = ASSETCHAINS_COMMISSION | ((ASSETCHAINS_STAKED & 0xff) << 32); + val = ASSETCHAINS_COMMISSION | (((uint64_t)ASSETCHAINS_STAKED & 0xff) << 32) | (((uint64_t)ASSETCHAINS_CC & 0xffff) << 40) | (ASSETCHAINS_PUBLIC & 0xff); extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(val),(void *)&val); } addn = GetArg("-seednode",""); if ( strlen(addn.c_str()) > 0 ) ASSETCHAINS_SEED = 1; - strncpy(ASSETCHAINS_SYMBOL,name.c_str(),sizeof(ASSETCHAINS_SYMBOL)-1); + strncpy(ASSETCHAINS_SYMBOL,name.c_str(),64); if ( (baseid= komodo_baseid(ASSETCHAINS_SYMBOL)) >= 0 && baseid < 32 ) MAX_MONEY = komodo_maxallowed(baseid); else if ( ASSETCHAINS_REWARD == 0 ) @@ -1589,7 +1602,7 @@ void komodo_args(char *argv0) else MAX_MONEY = (ASSETCHAINS_SUPPLY+1) * SATOSHIDEN + ASSETCHAINS_REWARD * (ASSETCHAINS_ENDSUBSIDY==0 ? 10000000 : ASSETCHAINS_ENDSUBSIDY); MAX_MONEY += (MAX_MONEY * ASSETCHAINS_COMMISSION) / SATOSHIDEN; //printf("baseid.%d MAX_MONEY.%s %.8f\n",baseid,ASSETCHAINS_SYMBOL,(double)MAX_MONEY/SATOSHIDEN); - ASSETCHAINS_PORT = komodo_port(ASSETCHAINS_SYMBOL,ASSETCHAINS_SUPPLY,&ASSETCHAINS_MAGIC,extraptr,extralen); + ASSETCHAINS_P2PPORT = komodo_port(ASSETCHAINS_SYMBOL,ASSETCHAINS_SUPPLY,&ASSETCHAINS_MAGIC,extraptr,extralen); while ( (dirname= (char *)GetDataDir(false).string().c_str()) == 0 || dirname[0] == 0 ) { fprintf(stderr,"waiting for datadir\n"); @@ -1604,11 +1617,14 @@ void komodo_args(char *argv0) { int32_t komodo_baseid(char *origbase); extern int COINBASE_MATURITY; - komodo_configfile(ASSETCHAINS_SYMBOL,ASSETCHAINS_PORT + 1); - komodo_userpass(ASSETCHAINS_USERPASS,ASSETCHAINS_SYMBOL); + if ( (port= komodo_userpass(ASSETCHAINS_USERPASS,ASSETCHAINS_SYMBOL)) != 0 ) + ASSETCHAINS_RPCPORT = port; + else komodo_configfile(ASSETCHAINS_SYMBOL,ASSETCHAINS_P2PPORT + 1); COINBASE_MATURITY = 1; - //fprintf(stderr,"ASSETCHAINS_PORT %s %u (%s)\n",ASSETCHAINS_SYMBOL,ASSETCHAINS_PORT,ASSETCHAINS_USERPASS); + //fprintf(stderr,"ASSETCHAINS_RPCPORT (%s) %u\n",ASSETCHAINS_SYMBOL,ASSETCHAINS_RPCPORT); } + if ( ASSETCHAINS_RPCPORT == 0 ) + ASSETCHAINS_RPCPORT = ASSETCHAINS_P2PPORT + 1; //ASSETCHAINS_NOTARIES = GetArg("-ac_notaries",""); //komodo_assetchain_pubkeys((char *)ASSETCHAINS_NOTARIES.c_str()); iguana_rwnum(1,magic,sizeof(ASSETCHAINS_MAGIC),(void *)&ASSETCHAINS_MAGIC); @@ -1616,10 +1632,10 @@ void komodo_args(char *argv0) sprintf(&magicstr[i<<1],"%02x",magic[i]); magicstr[8] = 0; #ifndef FROM_CLI - sprintf(fname,"gen%s",ASSETCHAINS_SYMBOL); + sprintf(fname,"%s_7776",ASSETCHAINS_SYMBOL); if ( (fp= fopen(fname,"wb")) != 0 ) { - fprintf(fp,iguanafmtstr,name.c_str(),name.c_str(),name.c_str(),name.c_str(),magicstr,ASSETCHAINS_PORT,ASSETCHAINS_PORT+1,"78.47.196.146"); + fprintf(fp,iguanafmtstr,name.c_str(),name.c_str(),name.c_str(),name.c_str(),magicstr,ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,"78.47.196.146"); fclose(fp); //printf("created (%s)\n",fname); } else printf("error creating (%s)\n",fname); @@ -1628,7 +1644,8 @@ void komodo_args(char *argv0) else { char fname[512],username[512],password[4096]; int32_t iter; FILE *fp; - ASSETCHAINS_PORT = 8777; + ASSETCHAINS_P2PPORT = 7770; + ASSETCHAINS_RPCPORT = 7771; for (iter=0; iter<2; iter++) { strcpy(fname,GetDataDir().string().c_str()); @@ -1653,7 +1670,7 @@ void komodo_args(char *argv0) #endif if ( (fp= fopen(fname,"rb")) != 0 ) { - komodo_userpass(username,password,fp); + _komodo_userpass(username,password,fp); sprintf(iter == 0 ? KMDUSERPASS : BTCUSERPASS,"%s:%s",username,password); fclose(fp); //printf("KOMODO.(%s) -> userpass.(%s)\n",fname,KMDUSERPASS); @@ -1662,8 +1679,11 @@ void komodo_args(char *argv0) break; } } - BITCOIND_PORT = GetArg("-rpcport", BaseParams().RPCPort()); - //fprintf(stderr,"%s chain params initialized\n",ASSETCHAINS_SYMBOL); + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + { + BITCOIND_RPCPORT = GetArg("-rpcport", ASSETCHAINS_RPCPORT); + //fprintf(stderr,"(%s) port.%u chain params initialized\n",ASSETCHAINS_SYMBOL,BITCOIND_RPCPORT); + } else BITCOIND_RPCPORT = GetArg("-rpcport", BaseParams().RPCPort()); } void komodo_nameset(char *symbol,char *dest,char *source) @@ -1696,3 +1716,24 @@ struct komodo_state *komodo_stateptr(char *symbol,char *dest) komodo_nameset(symbol,dest,ASSETCHAINS_SYMBOL); return(komodo_stateptrget(symbol)); } + +void komodo_prefetch(FILE *fp) +{ + long fsize,fpos; int32_t incr = 16*1024*1024; + fpos = ftell(fp); + fseek(fp,0,SEEK_END); + fsize = ftell(fp); + if ( fsize > incr ) + { + char *ignore = (char *)malloc(incr); + if ( ignore != 0 ) + { + rewind(fp); + while ( fread(ignore,1,incr,fp) == incr ) // prefetch + fprintf(stderr,"."); + free(ignore); + } + } + fseek(fp,fpos,SEEK_SET); +} + diff --git a/src/main.cpp b/src/main.cpp index 1d21289f2..a7565e0ab 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,6 +10,7 @@ #include "addrman.h" #include "alert.h" #include "arith_uint256.h" +#include "importcoin.h" #include "chainparams.h" #include "checkpoints.h" #include "checkqueue.h" @@ -19,8 +20,10 @@ #include "init.h" #include "merkleblock.h" #include "metrics.h" +#include "notarisationdb.h" #include "net.h" #include "pow.h" +#include "script/interpreter.h" #include "txdb.h" #include "txmempool.h" #include "ui_interface.h" @@ -55,7 +58,8 @@ CCriticalSection cs_main; extern uint8_t NOTARY_PUBKEY33[33]; extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN; int32_t KOMODO_NEWBLOCKS; -void komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); +int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); +void komodo_broadcast(CBlock *pblock,int32_t limit); BlockMap mapBlockIndex; CChain chainActive; @@ -584,6 +588,15 @@ CBlockTreeDB *pblocktree = NULL; #define KOMODO_ZCASH #include "komodo.h" +int64_t komodo_snapshot() +{ + int64_t total = -1; + if ( pblocktree != 0 ) + total = pblocktree->Snapshot(); + else fprintf(stderr,"null pblocktree start with -addressindex=true\n"); + return(total); +} + ////////////////////////////////////////////////////////////////////////////// // // mapOrphanTransactions @@ -816,7 +829,10 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs, { if (tx.IsCoinBase()) return true; // Coinbases don't use vin normally - + + if (tx.IsCoinImport()) + return tx.vin[0].scriptSig.IsCoinImport(); + for (unsigned int i = 0; i < tx.vin.size(); i++) { const CTxOut& prev = mapInputs.GetOutputFor(tx.vin[i]); @@ -887,7 +903,7 @@ unsigned int GetLegacySigOpCount(const CTransaction& tx) unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs) { - if (tx.IsCoinBase()) + if (tx.IsCoinBase() || tx.IsCoinImport()) return 0; unsigned int nSigOps = 0; @@ -944,8 +960,8 @@ bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state, return state.DoS(dosLevel, error("ContextualCheckTransaction(): transaction is expired"), REJECT_INVALID, "tx-overwinter-expired"); } } - - if (!(tx.IsCoinBase() || tx.vjoinsplit.empty())) { + + if (!(tx.IsMint() || tx.vjoinsplit.empty())) { auto consensusBranchId = CurrentEpochBranchId(nHeight, Params().GetConsensus()); // Empty output script. CScript scriptCode; @@ -1000,7 +1016,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state, if (!CheckTransactionWithoutProofVerification(tx, state)) { return false; } else { - // Ensure that zk-SNARKs verify + // Ensure that zk-SNARKs v|| y BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { if (!joinsplit.Verify(*pzcashParams, verifier, tx.joinSplitPubKey)) { return state.DoS(100, error("CheckTransaction(): joinsplit does not verify"), @@ -1058,6 +1074,7 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio // Transactions can contain empty `vin` and `vout` so long as // `vjoinsplit` is non-empty. + // Migrations may also have empty `vin` if (tx.vin.empty() && tx.vjoinsplit.empty()) return state.DoS(10, error("CheckTransaction(): vin empty"), REJECT_INVALID, "bad-txns-vin-empty"); @@ -1092,6 +1109,11 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio // Ensure that joinsplit values are well-formed BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit) { + if ( ASSETCHAINS_PUBLIC != 0 ) + { + return state.DoS(100, error("CheckTransaction(): this is a public chain, no privacy allowed"), + REJECT_INVALID, "bad-txns-acprivacy-chain"); + } if (joinsplit.vpub_old < 0) { return state.DoS(100, error("CheckTransaction(): joinsplit.vpub_old negative"), REJECT_INVALID, "bad-txns-vpub_old-negative"); @@ -1166,7 +1188,7 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio } } - if (tx.IsCoinBase()) + if (tx.IsMint()) { // There should be no joinsplits in a coinbase transaction if (tx.vjoinsplit.size() > 0) @@ -1283,7 +1305,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (pool.exists(hash)) { fprintf(stderr,"already in mempool\n"); - return false; + return state.Invalid(false, REJECT_DUPLICATE, "already in mempool"); } // Check for conflicts with in-memory transactions @@ -1294,10 +1316,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa COutPoint outpoint = tx.vin[i].prevout; if (pool.mapNextTx.count(outpoint)) { - static uint32_t counter; + //static uint32_t counter; // Disable replacement feature for now //if ( counter++ < 100 ) - fprintf(stderr,"Disable replacement feature for now\n"); + //fprintf(stderr,"Disable replacement feature for now\n"); return false; } } @@ -1328,28 +1350,37 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (view.HaveCoins(hash)) { fprintf(stderr,"view.HaveCoins(hash) error\n"); - return false; + return state.Invalid(false, REJECT_DUPLICATE, "already have coins"); } - // do all inputs exist? - // Note that this does not check for the presence of actual outputs (see the next check for that), - // and only helps with filling in pfMissingInputs (to determine missing vs spent). - BOOST_FOREACH(const CTxIn txin, tx.vin) + if (tx.IsCoinImport()) { - if (!view.HaveCoins(txin.prevout.hash)) + // Inverse of normal case; if input exists, it's been spent + if (ExistsImportTombstone(tx, view)) + return state.Invalid(false, REJECT_DUPLICATE, "import tombstone exists"); + } + else + { + // do all inputs exist? + // Note that this does not check for the presence of actual outputs (see the next check for that), + // and only helps with filling in pfMissingInputs (to determine missing vs spent). + BOOST_FOREACH(const CTxIn txin, tx.vin) { - if (pfMissingInputs) - *pfMissingInputs = true; - //fprintf(stderr,"missing inputs\n"); - return false; + if (!view.HaveCoins(txin.prevout.hash)) + { + if (pfMissingInputs) + *pfMissingInputs = true; + //fprintf(stderr,"missing inputs\n"); + return false; + } + } + + // are the actual inputs available? + if (!view.HaveInputs(tx)) + { + //fprintf(stderr,"accept failure.1\n"); + return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),REJECT_DUPLICATE, "bad-txns-inputs-spent"); } - } - - // are the actual inputs available? - if (!view.HaveInputs(tx)) - { - //fprintf(stderr,"accept failure.1\n"); - return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),REJECT_DUPLICATE, "bad-txns-inputs-spent"); } // are the joinsplit's requirements met? if (!view.HaveJoinSplitRequirements(tx)) @@ -1392,11 +1423,13 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Keep track of transactions that spend a coinbase, which we re-scan // during reorgs to ensure COINBASE_MATURITY is still met. bool fSpendsCoinbase = false; - BOOST_FOREACH(const CTxIn &txin, tx.vin) { - const CCoins *coins = view.AccessCoins(txin.prevout.hash); - if (coins->IsCoinBase()) { - fSpendsCoinbase = true; - break; + if (!tx.IsCoinImport()) { + BOOST_FOREACH(const CTxIn &txin, tx.vin) { + const CCoins *coins = view.AccessCoins(txin.prevout.hash); + if (coins->IsCoinBase()) { + fSpendsCoinbase = true; + break; + } } } @@ -1477,6 +1510,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // There is a similar check in CreateNewBlock() to prevent creating // invalid blocks, however allowing such transactions into the mempool // can be exploited as a DoS attack. + // XXX: is this neccesary for CryptoConditions? if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId)) { fprintf(stderr,"accept failure.10\n"); @@ -1600,7 +1634,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock if (pindexSlow) { CBlock block; - if (ReadBlockFromDisk(block, pindexSlow)) { + if (ReadBlockFromDisk(block, pindexSlow,1)) { BOOST_FOREACH(const CTransaction &tx, block.vtx) { if (tx.GetHash() == hash) { txOut = tx; @@ -1655,7 +1689,7 @@ bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos, const CMessageHeader::M return true; } -bool ReadBlockFromDisk(int32_t height,CBlock& block, const CDiskBlockPos& pos) +bool ReadBlockFromDisk(int32_t height,CBlock& block, const CDiskBlockPos& pos,bool checkPOW) { uint8_t pubkey33[33]; block.SetNull(); @@ -1665,7 +1699,7 @@ bool ReadBlockFromDisk(int32_t height,CBlock& block, const CDiskBlockPos& pos) if (filein.IsNull()) { //fprintf(stderr,"readblockfromdisk err A\n"); - return false;//error("ReadBlockFromDisk: OpenBlockFile failed for %s", pos.ToString()); + return error("ReadBlockFromDisk: OpenBlockFile failed for %s", pos.ToString()); } // Read block @@ -1677,23 +1711,26 @@ bool ReadBlockFromDisk(int32_t height,CBlock& block, const CDiskBlockPos& pos) return error("%s: Deserialize or I/O error - %s at %s", __func__, e.what(), pos.ToString()); } // Check the header - komodo_block2pubkey33(pubkey33,(CBlock *)&block); - if (!(CheckEquihashSolution(&block, Params()) && CheckProofOfWork(height,pubkey33,block.GetHash(), block.nBits, Params().GetConsensus()))) + if ( 0 && checkPOW != 0 ) { - int32_t i; for (i=0; i<33; i++) - fprintf(stderr,"%02x",pubkey33[i]); - fprintf(stderr," warning unexpected diff at ht.%d\n",height); - - return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString()); + komodo_block2pubkey33(pubkey33,(CBlock *)&block); + if (!(CheckEquihashSolution(&block, Params()) && CheckProofOfWork(height,pubkey33,block.GetHash(), block.nBits, Params().GetConsensus(),block.nTime))) + { + int32_t i; for (i=0; i<33; i++) + fprintf(stderr,"%02x",pubkey33[i]); + fprintf(stderr," warning unexpected diff at ht.%d\n",height); + + return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString()); + } } return true; } -bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex) +bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex,bool checkPOW) { if ( pindex == 0 ) return false; - if (!ReadBlockFromDisk(pindex->nHeight,block, pindex->GetBlockPos())) + if (!ReadBlockFromDisk(pindex->nHeight,block, pindex->GetBlockPos(),checkPOW)) return false; if (block.GetHash() != pindex->GetBlockHash()) return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s", @@ -1705,6 +1742,7 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex) extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; extern uint32_t ASSETCHAINS_MAGIC; extern uint64_t ASSETCHAINS_STAKED,ASSETCHAINS_ENDSUBSIDY,ASSETCHAINS_REWARD,ASSETCHAINS_HALVING,ASSETCHAINS_LINEAR,ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY; +extern uint8_t ASSETCHAINS_PUBLIC; CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) { @@ -1721,7 +1759,11 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) else { if ( nHeight == 1 ) - return(ASSETCHAINS_SUPPLY * COIN + (ASSETCHAINS_MAGIC & 0xffffff)); + { + if ( ASSETCHAINS_STAKED == 0 || strcmp("VRSC",ASSETCHAINS_SYMBOL) == 0 ) + return(ASSETCHAINS_SUPPLY * COIN + (ASSETCHAINS_MAGIC & 0xffffff)); + else return(ASSETCHAINS_SUPPLY * COIN + ASSETCHAINS_MAGIC); + } else if ( ASSETCHAINS_ENDSUBSIDY == 0 || nHeight < ASSETCHAINS_ENDSUBSIDY ) { if ( ASSETCHAINS_REWARD == 0 ) @@ -1963,7 +2005,7 @@ void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txundo, int nHeight) { - if (!tx.IsCoinBase()) // mark inputs spent + if (!tx.IsMint()) // mark inputs spent { txundo.vprevout.reserve(tx.vin.size()); BOOST_FOREACH(const CTxIn &txin, tx.vin) { @@ -1989,6 +2031,13 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txund } } inputs.ModifyCoins(tx.GetHash())->FromTx(tx, nHeight); // add outputs + + // Unorthodox state + if (tx.IsCoinImport()) { + // add a tombstone for the burnTx + AddImportTombstone(tx, inputs, nHeight); + } + } void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight) @@ -1999,7 +2048,8 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight) bool CScriptCheck::operator()() { const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; - if (!VerifyScript(scriptSig, scriptPubKey, nFlags, ServerTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *txdata), consensusBranchId, &error)) { + ServerTransactionSignatureChecker checker(ptxTo, nIn, amount, cacheStore, *txdata); + if (!VerifyScript(scriptSig, scriptPubKey, nFlags, checker, consensusBranchId, &error)) { return ::error("CScriptCheck(): %s:%d VerifySignature failed: %s", ptxTo->GetHash().ToString(), nIn, ScriptErrorString(error)); } return true; @@ -2109,7 +2159,7 @@ bool ContextualCheckInputs( uint32_t consensusBranchId, std::vector *pvChecks) { - if (!tx.IsCoinBase()) + if (!tx.IsMint()) { if (!Consensus::CheckTxInputs(tx, state, inputs, GetSpendHeight(inputs), consensusParams)) { return false; @@ -2161,7 +2211,13 @@ bool ContextualCheckInputs( } } } - + + if (tx.IsCoinImport()) + { + ServerTransactionSignatureChecker checker(&tx, 0, 0, false, txdata); + return VerifyCoinImport(tx.vin[0].scriptSig, checker, state); + } + return true; } @@ -2249,7 +2305,6 @@ namespace { catch (const std::exception& e) { return error("%s: Deserialize or I/O error - %s", __func__, e.what()); } - // Verify checksum CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION); hasher << hashBlock; @@ -2313,6 +2368,37 @@ static bool ApplyTxInUndo(const CTxInUndo& undo, CCoinsViewCache& view, const CO return fClean; } + +void ConnectNotarisations(const CBlock &block, int height) +{ + // Record Notarisations + NotarisationsInBlock notarisations = ScanBlockNotarisations(block, height); + if (notarisations.size() > 0) { + CLevelDBBatch batch; + batch.Write(block.GetHash(), notarisations); + WriteBackNotarisations(notarisations, batch); + pnotarisations->WriteBatch(batch, true); + LogPrintf("ConnectBlock: wrote %i block notarisations in block: %s\n", + notarisations.size(), block.GetHash().GetHex().data()); + } +} + + +void DisconnectNotarisations(const CBlock &block) +{ + // Delete from notarisations cache + NotarisationsInBlock nibs; + if (GetBlockNotarisations(block.GetHash(), nibs)) { + CLevelDBBatch batch; + batch.Erase(block.GetHash()); + EraseBackNotarisations(nibs, batch); + pnotarisations->WriteBatch(batch, true); + LogPrintf("DisconnectTip: deleted %i block notarisations in block: %s\n", + nibs.size(), block.GetHash().GetHex().data()); + } +} + + bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool* pfClean) { assert(pindex->GetBlockHash() == view.GetBestBlock()); @@ -2331,7 +2417,6 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex if (blockUndo.vtxundo.size() + 1 != block.vtx.size()) return error("DisconnectBlock(): block and undo data inconsistent"); - std::vector > addressIndex; std::vector > addressUnspentIndex; std::vector > spentIndex; @@ -2340,7 +2425,6 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex for (int i = block.vtx.size() - 1; i >= 0; i--) { const CTransaction &tx = block.vtx[i]; uint256 hash = tx.GetHash(); - if (fAddressIndex) { for (unsigned int k = tx.vout.size(); k-- > 0;) { @@ -2355,7 +2439,8 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex // undo unspent index addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), hash, k), CAddressUnspentValue())); - } else if (out.scriptPubKey.IsPayToPublicKeyHash()) { + } + else if (out.scriptPubKey.IsPayToPublicKeyHash()) { vector hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23); // undo receiving activity @@ -2364,7 +2449,18 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex // undo unspent index addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), hash, k), CAddressUnspentValue())); - } else { + } + else if (out.scriptPubKey.IsPayToPublicKey()) { + vector hashBytes(out.scriptPubKey.begin()+1, out.scriptPubKey.begin()+34); + + // undo receiving activity + addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->nHeight, i, hash, k, false), out.nValue)); + + // undo unspent index + addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), hash, k), CAddressUnspentValue())); + + } + else { continue; } @@ -2399,7 +2495,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex } // restore inputs - if (i > 0) { // not coinbases + if (!tx.IsMint()) { const CTxUndo &txundo = blockUndo.vtxundo[i-1]; if (txundo.vprevout.size() != tx.vin.size()) return error("DisconnectBlock(): transaction and undo data inconsistent"); @@ -2428,7 +2524,8 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight))); - } else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) { + } + else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) { vector hashBytes(prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23); // undo spending activity @@ -2437,14 +2534,29 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex // restore unspent index addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight))); - } else { + } + else if (prevout.scriptPubKey.IsPayToPublicKey()) { + vector hashBytes(prevout.scriptPubKey.begin()+1, prevout.scriptPubKey.begin()+34); + + // undo spending activity + addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->nHeight, i, hash, j, true), prevout.nValue * -1)); + + // restore unspent index + addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight))); + + } + else { continue; } } } } + else if (tx.IsCoinImport()) + { + RemoveImportTombstone(tx, view); + } } - + // set the old best anchor back view.PopAnchor(blockUndo.old_tree_root); @@ -2464,6 +2576,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex return AbortNode(state, "Failed to write address unspent index"); } } + return fClean; } @@ -2561,6 +2674,7 @@ void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const } } + static int64_t nTimeVerify = 0; static int64_t nTimeConnect = 0; static int64_t nTimeIndex = 0; @@ -2583,13 +2697,22 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } auto verifier = libzcash::ProofVerifier::Strict(); auto disabledVerifier = libzcash::ProofVerifier::Disabled(); - + int32_t futureblock; // Check it again to verify JoinSplit proofs, and in case a previous version let a bad block in - if (!CheckBlock(pindex->nHeight,pindex,block, state, fExpensiveChecks ? verifier : disabledVerifier, fCheckPOW, !fJustCheck)) //!fJustCheck, !fJustCheck)) + if (!CheckBlock(&futureblock,pindex->nHeight,pindex,block, state, fExpensiveChecks ? verifier : disabledVerifier, fCheckPOW, !fJustCheck) || futureblock != 0 ) + { + //fprintf(stderr,"checkblock failure in connectblock futureblock.%d\n",futureblock); return false; + } // verify that the view's current state corresponds to the previous block uint256 hashPrevBlock = pindex->pprev == NULL ? uint256() : pindex->pprev->GetBlockHash(); + if ( hashPrevBlock != view.GetBestBlock() ) + { + fprintf(stderr,"ConnectBlock(): hashPrevBlock != view.GetBestBlock()\n"); + return state.DoS(1, error("ConnectBlock(): hashPrevBlock != view.GetBestBlock()"), + REJECT_INVALID, "hashPrevBlock-not-bestblock"); + } assert(hashPrevBlock == view.GetBestBlock()); // Special case for the genesis block, skipping connection of its transactions @@ -2671,17 +2794,17 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, error("ConnectBlock(): too many sigops"), REJECT_INVALID, "bad-blk-sigops"); //fprintf(stderr,"ht.%d vout0 t%u\n",pindex->nHeight,tx.nLockTime); - if (!tx.IsCoinBase()) + if (!tx.IsMint()) { if (!view.HaveInputs(tx)) + { return state.DoS(100, error("ConnectBlock(): inputs missing/spent"), REJECT_INVALID, "bad-txns-inputs-missingorspent"); - + } // are the JoinSplit's requirements met? if (!view.HaveJoinSplitRequirements(tx)) return state.DoS(100, error("ConnectBlock(): JoinSplit requirements not met"), REJECT_INVALID, "bad-txns-joinsplit-requirements-not-met"); - if (fAddressIndex || fSpentIndex) { for (size_t j = 0; j < tx.vin.size(); j++) { @@ -2694,10 +2817,16 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (prevout.scriptPubKey.IsPayToScriptHash()) { hashBytes = uint160(vector (prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22)); addressType = 2; - } else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) { + } + else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) { hashBytes = uint160(vector (prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23)); addressType = 1; - } else { + } + else if (prevout.scriptPubKey.IsPayToPublicKey()) { + hashBytes = Hash160(vector (prevout.scriptPubKey.begin()+1, prevout.scriptPubKey.begin()+34)); + addressType = 1; + } + else { hashBytes.SetNull(); addressType = 0; } @@ -2718,7 +2847,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } } - // Add in sigops done by pay-to-script-hash inputs; // this is to prevent a "rogue miner" from creating // an incredibly-expensive-to-validate block. @@ -2744,7 +2872,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (fAddressIndex) { for (unsigned int k = 0; k < tx.vout.size(); k++) { const CTxOut &out = tx.vout[k]; - +//fprintf(stderr,"add %d vouts\n",(int32_t)tx.vout.size()); if (out.scriptPubKey.IsPayToScriptHash()) { vector hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22); @@ -2754,7 +2882,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // record unspent output addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight))); - } else if (out.scriptPubKey.IsPayToPublicKeyHash()) { + } + else if (out.scriptPubKey.IsPayToPublicKeyHash()) { vector hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23); // record receiving activity @@ -2763,7 +2892,18 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // record unspent output addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight))); - } else { + } + else if (out.scriptPubKey.IsPayToPublicKey()) { + vector hashBytes(out.scriptPubKey.begin()+1, out.scriptPubKey.begin()+34); + + // record receiving activity + addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue)); + + // record unspent output + addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight))); + + } + else { continue; } @@ -2789,7 +2929,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin vPos.push_back(std::make_pair(tx.GetHash(), pos)); pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); } - + view.PushAnchor(tree); if (!fJustCheck) { pindex->hashAnchorEnd = tree.root(); @@ -2800,14 +2940,14 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime1 - nTimeStart), 0.001 * (nTime1 - nTimeStart) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime1 - nTimeStart) / (nInputs-1), nTimeConnect * 0.000001); CAmount blockReward = nFees + GetBlockSubsidy(pindex->nHeight, chainparams.GetConsensus()) + sum; - if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && ASSETCHAINS_COMMISSION != 0 && block.vtx[0].vout.size() > 1 ) + if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && ASSETCHAINS_COMMISSION != 0 ) { uint64_t checktoshis; - if ( (checktoshis = komodo_commission(block)) != 0 ) + if ( (checktoshis= komodo_commission((CBlock *)&block)) != 0 ) { if ( block.vtx[0].vout.size() == 2 && block.vtx[0].vout[1].nValue == checktoshis ) blockReward += checktoshis; - else fprintf(stderr,"checktoshis %.8f vs actual vout[1] %.8f\n",dstr(checktoshis),dstr(block.vtx[0].vout[1].nValue)); + else fprintf(stderr,"checktoshis %.8f numvouts %d\n",dstr(checktoshis),(int32_t)block.vtx[0].vout.size()); } } if ( block.vtx[0].GetValueOut() > blockReward+1 ) @@ -2818,7 +2958,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)", block.vtx[0].GetValueOut(), blockReward), REJECT_INVALID, "bad-cb-amount"); - } else if ( NOTARY_PUBKEY33[0] != 0 ) + } else if ( IS_KOMODO_NOTARY != 0 ) fprintf(stderr,"allow nHeight.%d coinbase %.8f vs %.8f interest %.8f\n",(int32_t)pindex->nHeight,dstr(block.vtx[0].GetValueOut()),dstr(blockReward),dstr(sum)); } if (!control.Wait()) @@ -2858,11 +2998,12 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin pindex->RaiseValidity(BLOCK_VALID_SCRIPTS); setDirtyBlockIndex.insert(pindex); } + + ConnectNotarisations(block, pindex->nHeight); if (fTxIndex) if (!pblocktree->WriteTxIndex(vPos)) return AbortNode(state, "Failed to write transaction index"); - if (fAddressIndex) { if (!pblocktree->WriteAddressIndex(addressIndex)) { return AbortNode(state, "Failed to write address index"); @@ -3086,7 +3227,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { assert(pindexDelete); // Read block from disk. CBlock block; - if (!ReadBlockFromDisk(block, pindexDelete)) + if (!ReadBlockFromDisk(block, pindexDelete,1)) return AbortNode(state, "Failed to read block"); // Apply the block atomically to the chain state. uint256 anchorBeforeDisconnect = pcoinsTip->GetBestAnchor(); @@ -3096,6 +3237,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { if (!DisconnectBlock(block, state, pindexDelete, view)) return error("DisconnectTip(): DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString()); assert(view.Flush()); + DisconnectNotarisations(block); } LogPrint("bench", "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001); uint256 anchorAfterDisconnect = pcoinsTip->GetBestAnchor(); @@ -3153,7 +3295,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * int64_t nTime1 = GetTimeMicros(); CBlock block; if (!pblock) { - if (!ReadBlockFromDisk(block, pindexNew)) + if (!ReadBlockFromDisk(block, pindexNew,1)) return AbortNode(state, "Failed to read block"); pblock = █ } @@ -3212,6 +3354,8 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1; LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001); LogPrint("bench", "- Connect block: %.2fms [%.2fs]\n", (nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001); + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + komodo_broadcast(pblock,8); return true; } @@ -3311,8 +3455,8 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo pindexOldTip->phashBlock->GetHex(), pindexOldTip->nHeight, pindexOldTip->nChainWork.GetHex()) + "\n" + "- " + strprintf(_("New tip: %s, height %d, work %s"), pindexMostWork->phashBlock->GetHex(), pindexMostWork->nHeight, pindexMostWork->nChainWork.GetHex()) + "\n" + - "- " + strprintf(_("Fork point: %s, height %d"), - pindexFork->phashBlock->GetHex(), pindexFork->nHeight) + "\n\n" + + "- " + strprintf(_("Fork point: %s %s, height %d"), + ASSETCHAINS_SYMBOL,pindexFork->phashBlock->GetHex(), pindexFork->nHeight) + "\n\n" + _("Please help, human!"); LogPrintf("*** %s\n", msg); uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_ERROR); @@ -3541,9 +3685,21 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block) // Check for duplicate uint256 hash = block.GetHash(); BlockMap::iterator it = mapBlockIndex.find(hash); + BlockMap::iterator miPrev = mapBlockIndex.find(block.hashPrevBlock); if (it != mapBlockIndex.end()) - return it->second; - + { + if ( it->second != 0 ) // vNodes.size() >= KOMODO_LIMITED_NETWORKSIZE, change behavior to allow komodo_ensure to work + { + // this is the strange case where somehow the hash is in the mapBlockIndex via as yet undetermined process, but the pindex for the hash is not there. Theoretically it is due to processing the block headers, but I have seen it get this case without having received it from the block headers or anywhere else... jl777 + //fprintf(stderr,"addtoblockindex already there %p\n",it->second); + return it->second; + } + if ( miPrev != mapBlockIndex.end() && (*miPrev).second == 0 ) + { + //fprintf(stderr,"edge case of both block and prevblock in the strange state\n"); + return(0); // return here to avoid the state of pindex->nHeight not set and pprev NULL + } + } // Construct new block index object CBlockIndex* pindexNew = new CBlockIndex(block); assert(pindexNew); @@ -3553,11 +3709,11 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block) pindexNew->nSequenceId = 0; BlockMap::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first; pindexNew->phashBlock = &((*mi).first); - BlockMap::iterator miPrev = mapBlockIndex.find(block.hashPrevBlock); if (miPrev != mapBlockIndex.end()) { - pindexNew->pprev = (*miPrev).second; - pindexNew->nHeight = pindexNew->pprev->nHeight + 1; + if ( (pindexNew->pprev= (*miPrev).second) != 0 ) + pindexNew->nHeight = pindexNew->pprev->nHeight + 1; + else fprintf(stderr,"unexpected null pprev %s\n",hash.ToString().c_str()); pindexNew->BuildSkip(); } pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + GetBlockProof(*pindexNew); @@ -3566,7 +3722,8 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block) pindexBestHeader = pindexNew; setDirtyBlockIndex.insert(pindexNew); - + //fprintf(stderr,"added to block index %s %p\n",hash.ToString().c_str(),pindexNew); + mi->second = pindexNew; return pindexNew; } @@ -3722,7 +3879,7 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne return true; } -bool CheckBlockHeader(int32_t height,CBlockIndex *pindex, const CBlockHeader& blockhdr, CValidationState& state, bool fCheckPOW) +bool CheckBlockHeader(int32_t *futureblockp,int32_t height,CBlockIndex *pindex, const CBlockHeader& blockhdr, CValidationState& state, bool fCheckPOW) { // Check timestamp if ( 0 ) @@ -3740,96 +3897,90 @@ bool CheckBlockHeader(int32_t height,CBlockIndex *pindex, const CBlockHeader& bl fprintf(stderr," <- chainTip\n"); } } + *futureblockp = 0; if (blockhdr.GetBlockTime() > GetAdjustedTime() + 60) - return state.Invalid(error("CheckBlockHeader(): block timestamp too far in the future"),REJECT_INVALID, "time-too-new"); - else if ( ASSETCHAINS_STAKED != 0 && pindex != 0 && pindex->pprev != 0 && pindex->nTime <= pindex->pprev->nTime ) { - fprintf(stderr,"ht.%d %u vs ht.%d %u, is not monotonic\n",pindex->nHeight,pindex->nTime,pindex->pprev->nHeight,pindex->pprev->nTime); - return state.Invalid(error("CheckBlockHeader(): block timestamp needs to always increase"),REJECT_INVALID, "time-too-new"); + CBlockIndex *tipindex; + //fprintf(stderr,"ht.%d future block %u vs time.%u + 60\n",height,(uint32_t)blockhdr.GetBlockTime(),(uint32_t)GetAdjustedTime()); + if ( (tipindex= chainActive.Tip()) != 0 && tipindex->GetBlockHash() == blockhdr.hashPrevBlock && blockhdr.GetBlockTime() < GetAdjustedTime() + 60 + 5 ) + { + //fprintf(stderr,"it is the next block, let's wait for %d seconds\n",GetAdjustedTime() + 60 - blockhdr.GetBlockTime()); + while ( blockhdr.GetBlockTime() > GetAdjustedTime() + 60 ) + sleep(1); + //fprintf(stderr,"now its valid\n"); + } + else + { + if (blockhdr.GetBlockTime() < GetAdjustedTime() + 600) + *futureblockp = 1; + //LogPrintf("CheckBlockHeader block from future %d error",blockhdr.GetBlockTime() - GetAdjustedTime()); + return false; //state.Invalid(error("CheckBlockHeader(): block timestamp too far in the future"),REJECT_INVALID, "time-too-new"); + } } // Check block version - //if (block.nVersion < MIN_BLOCK_VERSION) - // return state.DoS(100, error("CheckBlockHeader(): block version too low"),REJECT_INVALID, "version-too-low"); + if (height > 0 && blockhdr.nVersion < MIN_BLOCK_VERSION) + return state.DoS(100, error("CheckBlockHeader(): block version too low"),REJECT_INVALID, "version-too-low"); // Check Equihash solution is valid - if ( fCheckPOW && !CheckEquihashSolution(&blockhdr, Params()) ) - return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"),REJECT_INVALID, "invalid-solution"); - + if ( fCheckPOW ) + { + if ( !CheckEquihashSolution(&blockhdr, Params()) ) + return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"),REJECT_INVALID, "invalid-solution"); + } // Check proof of work matches claimed amount /*komodo_index2pubkey33(pubkey33,pindex,height); - if ( fCheckPOW && !CheckProofOfWork(height,pubkey33,blockhdr.GetHash(), blockhdr.nBits, Params().GetConsensus()) ) + if ( fCheckPOW && !CheckProofOfWork(height,pubkey33,blockhdr.GetHash(), blockhdr.nBits, Params().GetConsensus(),blockhdr.nTime) ) return state.DoS(50, error("CheckBlockHeader(): proof of work failed"),REJECT_INVALID, "high-hash");*/ return true; } int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtime); +int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height); -int32_t komodo_reverify_blockcheck(CValidationState& state,int32_t height,CBlockIndex *pindex) -{ - static int32_t oneshot; - CBlockIndex *tipindex; int32_t rewindtarget; - if ( KOMODO_REWIND != 0 ) - oneshot = KOMODO_REWIND; - if ( oneshot == 0 && IsInitialBlockDownload() == 0 && (tipindex= chainActive.Tip()) != 0 ) - { - // if 200 blocks behind longestchain and no blocks for 2 hours - if ( KOMODO_LONGESTCHAIN > height+200 && KOMODO_NEWBLOCKS == 0 ) - { - if ( GetAdjustedTime() > tipindex->nTime+3600*2 ) - { - fprintf(stderr,"possible fork: tip.%d longest.%d newblock.%d lag.%d blocktime.%u\n",tipindex->nHeight,KOMODO_LONGESTCHAIN,height,(int32_t)(GetAdjustedTime() - tipindex->nTime),tipindex->nTime); - /*KOMODO_REWIND = tipindex->nHeight - 11; - rewindtarget = tipindex->nHeight - 11; - fprintf(stderr,"rewindtarget <- %d\n",rewindtarget); - oneshot = 1; - while ( rewindtarget > 0 && (tipindex= chainActive.Tip()) != 0 && tipindex->nHeight > rewindtarget ) - { - fprintf(stderr,"%d ",(int32_t)tipindex->nHeight); - InvalidateBlock(state,tipindex); - if ( !DisconnectTip(state) ) - break; - } - tipindex = chainActive.Tip(); - fprintf(stderr,"rewind done to %d\n",tipindex!=0?tipindex->nHeight:-1);*/ - } - } - } - return(0); -} - -bool CheckBlock(int32_t height,CBlockIndex *pindex,const CBlock& block, CValidationState& state, +bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const CBlock& block, CValidationState& state, libzcash::ProofVerifier& verifier, bool fCheckPOW, bool fCheckMerkleRoot) { - uint8_t pubkey33[33]; + uint8_t pubkey33[33]; uint256 hash; // These are checks that are independent of context. - - // Check that the header is valid (particularly PoW). This is mostly - // redundant with the call in AcceptBlockHeader. - if (!CheckBlockHeader(height,pindex,block,state,fCheckPOW)) + hash = block.GetHash(); + // Check that the header is valid (particularly PoW). This is mostly redundant with the call in AcceptBlockHeader. + if (!CheckBlockHeader(futureblockp,height,pindex,block,state,fCheckPOW)) { - fprintf(stderr,"checkblockheader error PoW.%d\n",fCheckPOW); - return false; + if ( *futureblockp == 0 ) + { + LogPrintf("CheckBlock header error"); + return false; + } } - komodo_block2pubkey33(pubkey33,(CBlock *)&block); - if ( fCheckPOW && !CheckProofOfWork(height,pubkey33,block.GetHash(), block.nBits, Params().GetConsensus()) ) + if ( fCheckPOW ) { - //komodo_reverify_blockcheck(state,height,pindex); - return state.DoS(1, error("CheckBlock(): proof of work failed"),REJECT_INVALID, "high-hash"); + //if ( !CheckEquihashSolution(&block, Params()) ) + // return state.DoS(100, error("CheckBlock: Equihash solution invalid"),REJECT_INVALID, "invalid-solution"); + komodo_block2pubkey33(pubkey33,(CBlock *)&block); + if ( !CheckProofOfWork(height,pubkey33,hash,block.nBits,Params().GetConsensus(),block.nTime) ) + { + int32_t z; for (z=31; z>=0; z--) + fprintf(stderr,"%02x",((uint8_t *)&hash)[z]); + fprintf(stderr," failed hash ht.%d\n",height); + return state.DoS(50, error("CheckBlock: proof of work failed"),REJECT_INVALID, "high-hash"); + } + if ( komodo_checkPOW(1,(CBlock *)&block,height) < 0 ) // checks Equihash + return state.DoS(100, error("CheckBlock: failed slow_checkPOW"),REJECT_INVALID, "failed-slow_checkPOW"); } // Check the merkle root. if (fCheckMerkleRoot) { bool mutated; uint256 hashMerkleRoot2 = block.BuildMerkleTree(&mutated); if (block.hashMerkleRoot != hashMerkleRoot2) - return state.DoS(100, error("CheckBlock(): hashMerkleRoot mismatch"), + return state.DoS(100, error("CheckBlock: hashMerkleRoot mismatch"), REJECT_INVALID, "bad-txnmrklroot", true); // Check for merkle tree malleability (CVE-2012-2459): repeating sequences // of transactions in a block without affecting the merkle root of a block, // while still invalidating it. if (mutated) - return state.DoS(100, error("CheckBlock(): duplicate transaction"), + return state.DoS(100, error("CheckBlock: duplicate transaction"), REJECT_INVALID, "bad-txns-duplicate", true); } @@ -3839,25 +3990,25 @@ bool CheckBlock(int32_t height,CBlockIndex *pindex,const CBlock& block, CValidat // Size limits if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE) - return state.DoS(100, error("CheckBlock(): size limits failed"), + return state.DoS(100, error("CheckBlock: size limits failed"), REJECT_INVALID, "bad-blk-length"); // First transaction must be coinbase, the rest must not be if (block.vtx.empty() || !block.vtx[0].IsCoinBase()) - return state.DoS(100, error("CheckBlock(): first tx is not coinbase"), + return state.DoS(100, error("CheckBlock: first tx is not coinbase"), REJECT_INVALID, "bad-cb-missing"); for (unsigned int i = 1; i < block.vtx.size(); i++) if (block.vtx[i].IsCoinBase()) - return state.DoS(100, error("CheckBlock(): more than one coinbase"), + return state.DoS(100, error("CheckBlock: more than one coinbase"), REJECT_INVALID, "bad-cb-multiple"); // Check transactions BOOST_FOREACH(const CTransaction& tx, block.vtx) { - if ( komodo_validate_interest(tx,height == 0 ? komodo_block2height((CBlock *)&block) : height,block.nTime,1) < 0 ) + if ( komodo_validate_interest(tx,height == 0 ? komodo_block2height((CBlock *)&block) : height,block.nTime,0) < 0 ) return error("CheckBlock: komodo_validate_interest failed"); if (!CheckTransaction(tx, state, verifier)) - return error("CheckBlock(): CheckTransaction failed"); + return error("CheckBlock: CheckTransaction failed"); } unsigned int nSigOps = 0; BOOST_FOREACH(const CTransaction& tx, block.vtx) @@ -3865,14 +4016,14 @@ bool CheckBlock(int32_t height,CBlockIndex *pindex,const CBlock& block, CValidat nSigOps += GetLegacySigOpCount(tx); } if (nSigOps > MAX_BLOCK_SIGOPS) - return state.DoS(100, error("CheckBlock(): out-of-bounds SigOpCount"), + return state.DoS(100, error("CheckBlock: out-of-bounds SigOpCount"), REJECT_INVALID, "bad-blk-sigops", true); if ( komodo_check_deposit(height,block,(pindex==0||pindex->pprev==0)?0:pindex->pprev->nTime) < 0 ) - //if ( komodo_check_deposit(ASSETCHAINS_SYMBOL[0] == 0 ? height : pindex != 0 ? (int32_t)pindex->nHeight : chainActive.Tip()->nHeight+1,block,pindex==0||pindex->pprev==0?0:pindex->pprev->nTime) < 0 ) { - static uint32_t counter; + //static uint32_t counter; //if ( counter++ < 100 && ASSETCHAINS_STAKED == 0 ) - fprintf(stderr,"check deposit rejection\n"); + // fprintf(stderr,"check deposit rejection\n"); + LogPrintf("CheckBlockHeader komodo_check_deposit error"); return(false); } return true; @@ -3891,7 +4042,7 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta int nHeight = pindexPrev->nHeight+1; // Check proof of work - if ( (nHeight < 235300 || nHeight > 236000) && block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams)) + if ( (ASSETCHAINS_SYMBOL[0] != 0 || nHeight < 235300 || nHeight > 236000) && block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams)) { cout << block.nBits << " block.nBits vs. calc " << GetNextWorkRequired(pindexPrev, &block, consensusParams) << endl; return state.DoS(100, error("%s: incorrect proof of work", __func__), @@ -3909,26 +4060,31 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta if (!Checkpoints::CheckBlock(chainParams.Checkpoints(), nHeight, hash)) { /*CBlockIndex *heightblock = chainActive[nHeight]; - if ( heightblock != 0 && heightblock->GetBlockHash() == hash ) - { - //fprintf(stderr,"got a pre notarization block that matches height.%d\n",(int32_t)nHeight); - return true; - }*/ + if ( heightblock != 0 && heightblock->GetBlockHash() == hash ) + { + //fprintf(stderr,"got a pre notarization block that matches height.%d\n",(int32_t)nHeight); + return true; + }*/ return state.DoS(100, error("%s: rejected by checkpoint lock-in at %d", __func__, nHeight),REJECT_CHECKPOINT, "checkpoint mismatch"); } // Don't accept any forks from the main chain prior to last checkpoint CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(chainParams.Checkpoints()); int32_t notarized_height; - if (pcheckpoint && nHeight > 1 && nHeight < pcheckpoint->nHeight ) - return state.DoS(1, error("%s: forked chain older than last checkpoint (height %d) vs %d", __func__, nHeight,pcheckpoint->nHeight)); - else if ( komodo_checkpoint(¬arized_height,nHeight,hash) < 0 ) + if ( nHeight == 1 && chainActive.Tip() != 0 && chainActive.Tip()->nHeight > 1 ) + return(false); + if ( nHeight != 0 ) { - CBlockIndex *heightblock = chainActive[nHeight]; - if ( heightblock != 0 && heightblock->GetBlockHash() == hash ) + if ( pcheckpoint != 0 && nHeight < pcheckpoint->nHeight ) + return state.DoS(1, error("%s: forked chain older than last checkpoint (height %d) vs %d", __func__, nHeight,pcheckpoint->nHeight)); + if ( komodo_checkpoint(¬arized_height,nHeight,hash) < 0 ) { - //fprintf(stderr,"got a pre notarization block that matches height.%d\n",(int32_t)nHeight); - return true; - } else return state.DoS(1, error("%s: forked chain %d older than last notarized (height %d) vs %d", __func__,nHeight, notarized_height)); + CBlockIndex *heightblock = chainActive[nHeight]; + if ( heightblock != 0 && heightblock->GetBlockHash() == hash ) + { + //fprintf(stderr,"got a pre notarization block that matches height.%d\n",(int32_t)nHeight); + return true; + } else return state.DoS(1, error("%s: forked chain %d older than last notarized (height %d) vs %d", __func__,nHeight, notarized_height)); + } } } // Reject block.nVersion < 4 blocks @@ -3977,108 +4133,108 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn return true; } -bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex** ppindex) +bool AcceptBlockHeader(int32_t *futureblockp,const CBlockHeader& block, CValidationState& state, CBlockIndex** ppindex) { + static uint256 zero; const CChainParams& chainparams = Params(); AssertLockHeld(cs_main); - // Check for duplicate + + // Check for duplicate uint256 hash = block.GetHash(); BlockMap::iterator miSelf = mapBlockIndex.find(hash); CBlockIndex *pindex = NULL; - if (miSelf != mapBlockIndex.end()) { + if (miSelf != mapBlockIndex.end()) + { // Block header is already known. - pindex = miSelf->second; + if ( (pindex= miSelf->second) == 0 ) + miSelf->second = pindex = AddToBlockIndex(block); if (ppindex) *ppindex = pindex; if ( pindex != 0 && pindex->nStatus & BLOCK_FAILED_MASK ) return state.Invalid(error("%s: block is marked invalid", __func__), 0, "duplicate"); -#ifdef DEXcode - if ( pindex != 0 && IsInitialBlockDownload() == 0 ) // jl777 debug test + /*if ( pindex != 0 && hash == komodo_requestedhash ) { - if (!CheckBlockHeader(pindex->nHeight,pindex, block, state,0)) - { - pindex->nStatus |= BLOCK_FAILED_MASK; - fprintf(stderr,"known block failing CheckBlockHeader %d\n",(int32_t)pindex->nHeight); - return false; - } - CBlockIndex* pindexPrev = NULL; - if (hash != chainparams.GetConsensus().hashGenesisBlock) - { - BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock); - if (mi == mapBlockIndex.end()) - { - pindex->nStatus |= BLOCK_FAILED_MASK; - fprintf(stderr,"known block.%d failing to find prevblock\n",(int32_t)pindex->nHeight); - return state.DoS(10, error("%s: prev block not found", __func__), 0, "bad-prevblk"); - } - pindexPrev = (*mi).second; - if (pindexPrev == 0 || (pindexPrev->nStatus & BLOCK_FAILED_MASK) ) - { - pindex->nStatus |= BLOCK_FAILED_MASK; - fprintf(stderr,"known block.%d found invalid prevblock\n",(int32_t)pindex->nHeight); - return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk"); - } - } - if (!ContextualCheckBlockHeader(block, state, pindexPrev)) - { - pindex->nStatus |= BLOCK_FAILED_MASK; - //fprintf(stderr,"known block.%d failing ContextualCheckBlockHeader\n",(int32_t)pindex->nHeight); - return false; - } - } - if ( *ppindex == 0 ) - fprintf(stderr,"unexpected null *ppindex\n"); -#endif - if ( pindex != 0 ) - return true; + fprintf(stderr,"AddToBlockIndex A komodo_requestedhash %s\n",komodo_requestedhash.ToString().c_str()); + memset(&komodo_requestedhash,0,sizeof(komodo_requestedhash)); + komodo_requestedcount = 0; + }*/ + + //if ( pindex == 0 ) + // fprintf(stderr,"accepthdr %s already known but no pindex\n",hash.ToString().c_str()); + return true; } - - if (!CheckBlockHeader(*ppindex!=0?(*ppindex)->nHeight:0,*ppindex, block, state,0)) + if (!CheckBlockHeader(futureblockp,*ppindex!=0?(*ppindex)->nHeight:0,*ppindex, block, state,0)) { - fprintf(stderr,"CheckBlockHeader failed\n"); - return false; + if ( *futureblockp == 0 ) + { + LogPrintf("AcceptBlockHeader CheckBlockHeader error\n"); + return false; + } } // Get prev block index CBlockIndex* pindexPrev = NULL; - if (hash != chainparams.GetConsensus().hashGenesisBlock) { + if (hash != chainparams.GetConsensus().hashGenesisBlock) + { BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock); if (mi == mapBlockIndex.end()) { - return state.DoS(10, error("%s: prev block not found", __func__), 0, "bad-prevblk"); + LogPrintf("AcceptBlockHeader hashPrevBlock %s not found\n",block.hashPrevBlock.ToString().c_str()); + return(false); + //return state.DoS(10, error("%s: prev block not found", __func__), 0, "bad-prevblk"); } pindexPrev = (*mi).second; - if (pindexPrev == 0 || (pindexPrev->nStatus & BLOCK_FAILED_MASK) ) + if (pindexPrev == 0 ) + { + LogPrintf("AcceptBlockHeader hashPrevBlock %s no pindexPrev\n",block.hashPrevBlock.ToString().c_str()); + return(false); + } + if ( (pindexPrev->nStatus & BLOCK_FAILED_MASK) ) return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk"); } if (!ContextualCheckBlockHeader(block, state, pindexPrev)) { - //fprintf(stderr,"ContextualCheckBlockHeader failed\n"); + //fprintf(stderr,"AcceptBlockHeader ContextualCheckBlockHeader failed\n"); + LogPrintf("AcceptBlockHeader ContextualCheckBlockHeader failed\n"); return false; } if (pindex == NULL) { - if ( (pindex= AddToBlockIndex(block)) == 0 ) - fprintf(stderr,"couldnt add to block index\n"); + if ( (pindex= AddToBlockIndex(block)) != 0 ) + { + miSelf = mapBlockIndex.find(hash); + if (miSelf != mapBlockIndex.end()) + miSelf->second = pindex; + //fprintf(stderr,"AcceptBlockHeader couldnt add to block index\n"); + } } if (ppindex) *ppindex = pindex; + /*if ( pindex != 0 && hash == komodo_requestedhash ) + { + fprintf(stderr,"AddToBlockIndex komodo_requestedhash %s\n",komodo_requestedhash.ToString().c_str()); + memset(&komodo_requestedhash,0,sizeof(komodo_requestedhash)); + komodo_requestedcount = 0; + }*/ return true; } -bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, bool fRequested, CDiskBlockPos* dbp) +bool AcceptBlock(int32_t *futureblockp,CBlock& block, CValidationState& state, CBlockIndex** ppindex, bool fRequested, CDiskBlockPos* dbp) { const CChainParams& chainparams = Params(); AssertLockHeld(cs_main); CBlockIndex *&pindex = *ppindex; - if (!AcceptBlockHeader(block, state, &pindex)) + if (!AcceptBlockHeader(futureblockp,block, state, &pindex)) { - fprintf(stderr,"AcceptBlockHeader rejected\n"); - return false; + if ( *futureblockp == 0 ) + { + LogPrintf("AcceptBlock AcceptBlockHeader error\n"); + return false; + } } if ( pindex == 0 ) { - fprintf(stderr,"unexpected AcceptBlock error null pindex\n"); + LogPrintf("AcceptBlock null pindex error\n"); return false; } //fprintf(stderr,"acceptblockheader passed\n"); @@ -4092,10 +4248,11 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, // blocks which are too close in height to the tip. Apply this test // regardless of whether pruning is enabled; it should generally be safe to // not process unrequested blocks. - bool fTooFarAhead = (pindex->nHeight > int(chainActive.Height() + MIN_BLOCKS_TO_KEEP)); + bool fTooFarAhead = (pindex->nHeight > int(chainActive.Height() + BLOCK_DOWNLOAD_WINDOW)); //MIN_BLOCKS_TO_KEEP)); // TODO: deal better with return value and error conditions for duplicate // and unrequested blocks. + //fprintf(stderr,"Accept %s flags already.%d requested.%d morework.%d farahead.%d\n",pindex->GetBlockHash().ToString().c_str(),fAlreadyHave,fRequested,fHasMoreWork,fTooFarAhead); if (fAlreadyHave) return true; if (!fRequested) { // If we didn't ask for it: if (pindex->nTx != 0) return true; // This is a previously-processed block that was pruned @@ -4105,18 +4262,20 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, // See method docstring for why this is always disabled auto verifier = libzcash::ProofVerifier::Disabled(); - if ((!CheckBlock(pindex->nHeight,pindex,block, state, verifier,0)) || !ContextualCheckBlock(block, state, pindex->pprev)) + if ((!CheckBlock(futureblockp,pindex->nHeight,pindex,block, state, verifier,0)) || !ContextualCheckBlock(block, state, pindex->pprev)) { - if (state.IsInvalid() && !state.CorruptionPossible()) { - pindex->nStatus |= BLOCK_FAILED_VALID; - setDirtyBlockIndex.insert(pindex); + if ( *futureblockp == 0 ) + { + if (state.IsInvalid() && !state.CorruptionPossible()) { + pindex->nStatus |= BLOCK_FAILED_VALID; + setDirtyBlockIndex.insert(pindex); + } + LogPrintf("AcceptBlock CheckBlock or ContextualCheckBlock error\n"); + return false; } - fprintf(stderr,"CheckBlock or ContextualCheckBlock failed\n"); - return false; } int nHeight = pindex->nHeight; - // Write block to history file try { unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); @@ -4136,8 +4295,10 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, if (fCheckForPruning) FlushStateToDisk(state, FLUSH_STATE_NONE); // we just allocated more disk space for block files - - return true; + if ( *futureblockp == 0 ) + return true; + LogPrintf("AcceptBlock block from future error\n"); + return false; } static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned nRequired, const Consensus::Params& consensusParams) @@ -4154,21 +4315,106 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned void komodo_currentheight_set(int32_t height); -bool ProcessNewBlock(int32_t height,CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp) +CBlockIndex *komodo_ensure(CBlock *pblock,uint256 hash) +{ + CBlockIndex *pindex = 0; + BlockMap::iterator miSelf = mapBlockIndex.find(hash); + if ( miSelf != mapBlockIndex.end() ) + { + if ( (pindex= miSelf->second) == 0 ) // create pindex so first Accept block doesnt fail + { + miSelf->second = AddToBlockIndex(*pblock); + //fprintf(stderr,"Block header %s is already known, but without pindex -> ensured %p\n",hash.ToString().c_str(),miSelf->second); + } + /*if ( hash != Params().GetConsensus().hashGenesisBlock ) + { + miSelf = mapBlockIndex.find(pblock->hashPrevBlock); + if ( miSelf != mapBlockIndex.end() ) + { + if ( miSelf->second == 0 ) + { + miSelf->second = InsertBlockIndex(pblock->hashPrevBlock); + fprintf(stderr,"autocreate previndex %s\n",pblock->hashPrevBlock.ToString().c_str()); + } + } + }*/ + } + return(pindex); +} + +CBlockIndex *oldkomodo_ensure(CBlock *pblock,uint256 hash) +{ + CBlockIndex *pindex=0,*previndex=0; + if ( (pindex= mapBlockIndex[hash]) == 0 ) + { + pindex = new CBlockIndex(); + if (!pindex) + throw runtime_error("komodo_ensure: new CBlockIndex failed"); + BlockMap::iterator mi = mapBlockIndex.insert(make_pair(hash, pindex)).first; + pindex->phashBlock = &((*mi).first); + } + BlockMap::iterator miSelf = mapBlockIndex.find(hash); + if ( miSelf == mapBlockIndex.end() ) + { + LogPrintf("komodo_ensure unexpected missing hash %s\n",hash.ToString().c_str()); + return(0); + } + if ( miSelf->second == 0 ) // create pindex so first Accept block doesnt fail + { + if ( pindex == 0 ) + { + pindex = AddToBlockIndex(*pblock); + fprintf(stderr,"ensure call addtoblockindex, got %p\n",pindex); + } + if ( pindex != 0 ) + { + miSelf->second = pindex; + LogPrintf("Block header %s is already known, but without pindex -> ensured %p\n",hash.ToString().c_str(),miSelf->second); + } else LogPrintf("komodo_ensure unexpected null pindex\n"); + } + /*if ( hash != Params().GetConsensus().hashGenesisBlock ) + { + miSelf = mapBlockIndex.find(pblock->hashPrevBlock); + if ( miSelf == mapBlockIndex.end() ) + previndex = InsertBlockIndex(pblock->hashPrevBlock); + if ( (miSelf= mapBlockIndex.find(pblock->hashPrevBlock)) != mapBlockIndex.end() ) + { + if ( miSelf->second == 0 ) // create pindex so first Accept block doesnt fail + { + if ( previndex == 0 ) + previndex = InsertBlockIndex(pblock->hashPrevBlock); + if ( previndex != 0 ) + { + miSelf->second = previndex; + LogPrintf("autocreate previndex %s\n",pblock->hashPrevBlock.ToString().c_str()); + } else LogPrintf("komodo_ensure unexpected null previndex\n"); + } + } else LogPrintf("komodo_ensure unexpected null miprev\n"); + } + }*/ + return(pindex); +} + +bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp) { // Preliminary checks - bool checked; + bool checked; uint256 hash; int32_t futureblock=0; auto verifier = libzcash::ProofVerifier::Disabled(); - if ( chainActive.Tip() != 0 ) + hash = pblock->GetHash(); + + if ( chainActive.Tip() != 0 ) komodo_currentheight_set(chainActive.Tip()->nHeight); - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - checked = CheckBlock(height!=0?height:komodo_block2height(pblock),0,*pblock, state, verifier,0); - else checked = CheckBlock(height!=0?height:komodo_block2height(pblock),0,*pblock, state, verifier,0); + checked = CheckBlock(&futureblock,height!=0?height:komodo_block2height(pblock),0,*pblock, state, verifier,0); { LOCK(cs_main); - bool fRequested = MarkBlockAsReceived(pblock->GetHash()); + bool fRequested = MarkBlockAsReceived(hash); fRequested |= fForceProcessing; - if (!checked) + if ( checked != 0 && komodo_checkPOW(from_miner && ASSETCHAINS_STAKED == 0,pblock,height) < 0 ) + { + checked = 0; + //fprintf(stderr,"passed checkblock but failed checkPOW.%d\n",from_miner && ASSETCHAINS_STAKED == 0); + } + if (!checked && futureblock == 0) { if ( pfrom != 0 ) { @@ -4176,19 +4422,24 @@ bool ProcessNewBlock(int32_t height,CValidationState &state, CNode* pfrom, CBloc } return error("%s: CheckBlock FAILED", __func__); } - // Store to disk CBlockIndex *pindex = NULL; - bool ret = AcceptBlock(*pblock, state, &pindex, fRequested, dbp); + if ( 1 ) + { + // without the komodo_ensure call, it is quite possible to get a non-error but null pindex returned from AcceptBlockHeader. In a 2 node network, it will be a long time before that block is reprocessed. Even though restarting makes it rescan, it seems much better to keep the nodes in sync + komodo_ensure(pblock,hash); + } + bool ret = AcceptBlock(&futureblock,*pblock, state, &pindex, fRequested, dbp); if (pindex && pfrom) { mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId(); } CheckBlockIndex(); - if (!ret) + if (!ret && futureblock == 0) return error("%s: AcceptBlock FAILED", __func__); + //else fprintf(stderr,"added block %s %p\n",pindex->GetBlockHash().ToString().c_str(),pindex->pprev); } - if (!ActivateBestChain(state, pblock)) + if (futureblock == 0 && !ActivateBestChain(state, pblock)) return error("%s: ActivateBestChain failed", __func__); return true; @@ -4205,30 +4456,31 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex indexDummy.nHeight = pindexPrev->nHeight + 1; // JoinSplit proofs are verified in ConnectBlock auto verifier = libzcash::ProofVerifier::Disabled(); - // NOTE: CheckBlockHeader is called by CheckBlock if (!ContextualCheckBlockHeader(block, state, pindexPrev)) { - fprintf(stderr,"TestBlockValidity failure A\n"); + //fprintf(stderr,"TestBlockValidity failure A checkPOW.%d\n",fCheckPOW); return false; } - if (!CheckBlock(indexDummy.nHeight,0,block, state, verifier, fCheckPOW, fCheckMerkleRoot)) + int32_t futureblock; + if (!CheckBlock(&futureblock,indexDummy.nHeight,0,block, state, verifier, fCheckPOW, fCheckMerkleRoot)) { - fprintf(stderr,"TestBlockValidity failure B\n"); + //fprintf(stderr,"TestBlockValidity failure B checkPOW.%d\n",fCheckPOW); return false; } if (!ContextualCheckBlock(block, state, pindexPrev)) { - fprintf(stderr,"TestBlockValidity failure C\n"); + //fprintf(stderr,"TestBlockValidity failure C checkPOW.%d\n",fCheckPOW); return false; } if (!ConnectBlock(block, state, &indexDummy, viewNew, true,fCheckPOW)) { - fprintf(stderr,"TestBlockValidity failure D\n"); + //fprintf(stderr,"TestBlockValidity failure D checkPOW.%d\n",fCheckPOW); return false; } assert(state.IsValid()); - + if ( futureblock != 0 ) + return(false); return true; } @@ -4299,7 +4551,6 @@ void FindFilesToPrune(std::set& setFilesToPrune) if (chainActive.Tip()->nHeight <= Params().PruneAfterHeight()) { return; } - unsigned int nLastBlockWeCanPrune = chainActive.Tip()->nHeight - MIN_BLOCKS_TO_KEEP; uint64_t nCurrentUsage = CalculateCurrentUsage(); // We don't check to prune until after we've allocated new space for files @@ -4348,10 +4599,9 @@ bool CheckDiskSpace(uint64_t nAdditionalBytes) return true; } - FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly) { - static int32_t didinit[1000]; long fsize,fpos; int32_t incr = 16*1024*1024; + static int32_t didinit[64]; if (pos.IsNull()) return NULL; boost::filesystem::path path = GetBlockPosFilename(pos, prefix); @@ -4365,22 +4615,7 @@ FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly) } if ( pos.nFile < sizeof(didinit)/sizeof(*didinit) && didinit[pos.nFile] == 0 && strcmp(prefix,(char *)"blk") == 0 ) { - fpos = ftell(file); - fseek(file,0,SEEK_END); - fsize = ftell(file); - if ( fsize > incr ) - { - char *ignore = (char *)malloc(incr); - if ( ignore != 0 ) - { - rewind(file); - while ( fread(ignore,1,incr,file) == incr ) - fprintf(stderr,"."); - free(ignore); - fprintf(stderr,"blk.%d loaded %ld bytes set fpos.%ld loading.%d\n",(int)pos.nFile,(long)ftell(file),(long)fpos,KOMODO_LOADINGBLOCKS); - } - } - fseek(file,fpos,SEEK_SET); + komodo_prefetch(file); didinit[pos.nFile] = 1; } if (pos.nPos) { @@ -4422,7 +4657,8 @@ CBlockIndex * InsertBlockIndex(uint256 hash) throw runtime_error("LoadBlockIndex(): new CBlockIndex failed"); mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first; pindexNew->phashBlock = &((*mi).first); - + //fprintf(stderr,"inserted to block index %s\n",hash.ToString().c_str()); + return pindexNew; } @@ -4431,9 +4667,10 @@ CBlockIndex * InsertBlockIndex(uint256 hash) bool static LoadBlockIndexDB() { const CChainParams& chainparams = Params(); + LogPrintf("%s: start loading guts\n", __func__); if (!pblocktree->LoadBlockIndexGuts()) return false; - + LogPrintf("%s: loaded guts\n", __func__); boost::this_thread::interruption_point(); // Calculate nChainWork @@ -4445,7 +4682,9 @@ bool static LoadBlockIndexDB() vSortedByHeight.push_back(make_pair(pindex->nHeight, pindex)); //komodo_pindex_init(pindex,(int32_t)pindex->nHeight); } + //fprintf(stderr,"load blockindexDB paired %u\n",(uint32_t)time(NULL)); sort(vSortedByHeight.begin(), vSortedByHeight.end()); + //fprintf(stderr,"load blockindexDB sorted %u\n",(uint32_t)time(NULL)); BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight) { CBlockIndex* pindex = item.second; @@ -4494,7 +4733,8 @@ bool static LoadBlockIndexDB() pindexBestHeader = pindex; //komodo_pindex_init(pindex,(int32_t)pindex->nHeight); } - + //fprintf(stderr,"load blockindexDB chained %u\n",(uint32_t)time(NULL)); + // Load block file info pblocktree->ReadLastBlockFile(nLastBlockFile); vinfoBlockFile.resize(nLastBlockFile + 1); @@ -4523,6 +4763,7 @@ bool static LoadBlockIndexDB() } //komodo_pindex_init(pindex,(int32_t)pindex->nHeight); } + //fprintf(stderr,"load blockindexDB %u\n",(uint32_t)time(NULL)); for (std::set::iterator it = setBlkDataFiles.begin(); it != setBlkDataFiles.end(); it++) { CDiskBlockPos pos(*it, 0); @@ -4544,7 +4785,6 @@ bool static LoadBlockIndexDB() // Check whether we have a transaction index pblocktree->ReadFlag("txindex", fTxIndex); LogPrintf("%s: transaction index %s\n", __func__, fTxIndex ? "enabled" : "disabled"); - // Check whether we have an address index pblocktree->ReadFlag("addressindex", fAddressIndex); LogPrintf("%s: address index %s\n", __func__, fAddressIndex ? "enabled" : "disabled"); @@ -4622,6 +4862,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth CValidationState state; // No need to verify JoinSplits twice auto verifier = libzcash::ProofVerifier::Disabled(); + //fprintf(stderr,"start VerifyDB %u\n",(uint32_t)time(NULL)); for (CBlockIndex* pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) { boost::this_thread::interruption_point(); @@ -4630,10 +4871,11 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth break; CBlock block; // check level 0: read from disk - if (!ReadBlockFromDisk(block, pindex)) + if (!ReadBlockFromDisk(block, pindex,0)) return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); // check level 1: verify block validity - if (nCheckLevel >= 1 && !CheckBlock(pindex->nHeight,pindex,block, state, verifier,0)) + int32_t futureblock; + if (nCheckLevel >= 1 && !CheckBlock(&futureblock,pindex->nHeight,pindex,block, state, verifier,0) ) return error("VerifyDB(): *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); // check level 2: verify undo validity if (nCheckLevel >= 2 && pindex) { @@ -4659,6 +4901,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth if (ShutdownRequested()) return true; } + //fprintf(stderr,"end VerifyDB %u\n",(uint32_t)time(NULL)); if (pindexFailure) return error("VerifyDB(): *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", chainActive.Height() - pindexFailure->nHeight + 1, nGoodTransactions); @@ -4670,7 +4913,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, 100 - (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * 50)))); pindex = chainActive.Next(pindex); CBlock block; - if (!ReadBlockFromDisk(block, pindex)) + if (!ReadBlockFromDisk(block, pindex,0)) return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); if (!ConnectBlock(block, state, pindex, coins,false, true)) return error("VerifyDB(): *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); @@ -4876,7 +5119,6 @@ bool InitBlockIndex() { // Use the provided setting for -txindex in the new database fTxIndex = GetBoolArg("-txindex", true); pblocktree->WriteFlag("txindex", fTxIndex); - // Use the provided setting for -addressindex in the new database fAddressIndex = GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX); pblocktree->WriteFlag("addressindex", fAddressIndex); @@ -4887,7 +5129,6 @@ bool InitBlockIndex() { fSpentIndex = GetBoolArg("-spentindex", DEFAULT_SPENTINDEX); pblocktree->WriteFlag("spentindex", fSpentIndex); - LogPrintf("Initializing databases...\n"); // Only add the genesis block if not reindexing (in which case we reuse the one already on disk) @@ -4931,7 +5172,8 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) int nLoaded = 0; try { // This takes over fileIn and calls fclose() on it in the CBufferedFile destructor - CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SIZE, MAX_BLOCK_SIZE+8, SER_DISK, CLIENT_VERSION); + //CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SIZE, MAX_BLOCK_SIZE+8, SER_DISK, CLIENT_VERSION); + CBufferedFile blkdat(fileIn, 32*MAX_BLOCK_SIZE, MAX_BLOCK_SIZE+8, SER_DISK, CLIENT_VERSION); uint64_t nRewind = blkdat.GetPos(); while (!blkdat.eof()) { boost::this_thread::interruption_point(); @@ -4980,7 +5222,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) // process in case the block isn't known yet if (mapBlockIndex.count(hash) == 0 || (mapBlockIndex[hash]->nStatus & BLOCK_HAVE_DATA) == 0) { CValidationState state; - if (ProcessNewBlock(0,state, NULL, &block, true, dbp)) + if (ProcessNewBlock(0,0,state, NULL, &block, true, dbp)) nLoaded++; if (state.IsError()) break; @@ -4997,12 +5239,12 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) std::pair::iterator, std::multimap::iterator> range = mapBlocksUnknownParent.equal_range(head); while (range.first != range.second) { std::multimap::iterator it = range.first; - if (ReadBlockFromDisk(mapBlockIndex[hash]!=0?mapBlockIndex[hash]->nHeight:0,block, it->second)) + if (ReadBlockFromDisk(mapBlockIndex[hash]!=0?mapBlockIndex[hash]->nHeight:0,block, it->second,1)) { LogPrintf("%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(), head.ToString()); CValidationState dummy; - if (ProcessNewBlock(0,dummy, NULL, &block, true, &it->second)) + if (ProcessNewBlock(0,0,dummy, NULL, &block, true, &it->second)) { nLoaded++; queue.push_back(block.GetHash()); @@ -5044,10 +5286,11 @@ void static CheckBlockIndex() // Build forward-pointing map of the entire block tree. std::multimap forward; for (BlockMap::iterator it = mapBlockIndex.begin(); it != mapBlockIndex.end(); it++) { - forward.insert(std::make_pair(it->second->pprev, it->second)); + if ( it->second != 0 ) + forward.insert(std::make_pair(it->second->pprev, it->second)); } - - assert(forward.size() == mapBlockIndex.size()); + if ( Params().NetworkIDString() != "regtest" ) + assert(forward.size() == mapBlockIndex.size()); std::pair::iterator,std::multimap::iterator> rangeGenesis = forward.equal_range(NULL); CBlockIndex *pindex = rangeGenesis.first->second; @@ -5356,7 +5599,7 @@ void static ProcessGetData(CNode* pfrom) { // Send block from disk CBlock block; - if (!ReadBlockFromDisk(block, (*mi).second)) + if (!ReadBlockFromDisk(block, (*mi).second,1)) { assert(!"cannot load block from disk"); } @@ -5862,7 +6105,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, vector vHeaders; int nLimit = MAX_HEADERS_RESULTS; LogPrint("net", "getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString(), pfrom->id); - if ( pfrom->lasthdrsreq >= chainActive.Height()-MAX_HEADERS_RESULTS || pfrom->lasthdrsreq != (int32_t)(pindex ? pindex->nHeight : -1) ) + //if ( pfrom->lasthdrsreq >= chainActive.Height()-MAX_HEADERS_RESULTS || pfrom->lasthdrsreq != (int32_t)(pindex ? pindex->nHeight : -1) )// no need to ever suppress this { pfrom->lasthdrsreq = (int32_t)(pindex ? pindex->nHeight : -1); for (; pindex; pindex = chainActive.Next(pindex)) @@ -5873,12 +6116,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } pfrom->PushMessage("headers", vHeaders); } - else if ( NOTARY_PUBKEY33[0] != 0 ) + /*else if ( IS_KOMODO_NOTARY != 0 ) { static uint32_t counter; if ( counter++ < 3 ) fprintf(stderr,"you can ignore redundant getheaders from peer.%d %d prev.%d\n",(int32_t)pfrom->id,(int32_t)(pindex ? pindex->nHeight : -1),pfrom->lasthdrsreq); - } + }*/ } @@ -6042,11 +6285,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, Misbehaving(pfrom->GetId(), 20); return error("non-continuous headers sequence"); } - if (!AcceptBlockHeader(header, state, &pindexLast)) { + int32_t futureblock; + if (!AcceptBlockHeader(&futureblock,header, state, &pindexLast)) { int nDoS; - if (state.IsInvalid(nDoS)) + if (state.IsInvalid(nDoS) && futureblock == 0) { - if (nDoS > 0) + if (nDoS > 0 && futureblock == 0) Misbehaving(pfrom->GetId(), nDoS/nDoS); return error("invalid header received"); } @@ -6087,7 +6331,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Such an unrequested block may still be processed, subject to the // conditions in AcceptBlock(). bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload(); - ProcessNewBlock(0,state, pfrom, &block, forceProcessing, NULL); + ProcessNewBlock(0,0,state, pfrom, &block, forceProcessing, NULL); int nDoS; if (state.IsInvalid(nDoS)) { pfrom->PushMessage("reject", strCommand, state.GetRejectCode(), @@ -6677,6 +6921,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) // // Message: getdata (blocks) // + static uint256 zero; vector vGetData; if (!pto->fDisconnect && !pto->fClient && (fFetch || !IsInitialBlockDownload()) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { vector vToDownload; @@ -6695,7 +6940,21 @@ bool SendMessages(CNode* pto, bool fSendTrickle) } } } - + /*CBlockIndex *pindex; + if ( komodo_requestedhash != zero && komodo_requestedcount < 16 && (pindex= mapBlockIndex[komodo_requestedhash]) != 0 ) + { + LogPrint("net","komodo_requestedhash.%d request %s to nodeid.%d\n",komodo_requestedcount,komodo_requestedhash.ToString().c_str(),pto->GetId()); + fprintf(stderr,"komodo_requestedhash.%d request %s to nodeid.%d\n",komodo_requestedcount,komodo_requestedhash.ToString().c_str(),pto->GetId()); + vGetData.push_back(CInv(MSG_BLOCK, komodo_requestedhash)); + MarkBlockAsInFlight(pto->GetId(), komodo_requestedhash, consensusParams, pindex); + komodo_requestedcount++; + if ( komodo_requestedcount > 16 ) + { + memset(&komodo_requestedhash,0,sizeof(komodo_requestedhash)); + komodo_requestedcount = 0; + } + }*/ + // // Message: getdata (non-blocks) // diff --git a/src/main.h b/src/main.h index 9ae87710a..ef46cd83d 100644 --- a/src/main.h +++ b/src/main.h @@ -190,7 +190,7 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals); * @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location. * @return True if state.IsValid() */ -bool ProcessNewBlock(int32_t height,CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp); +bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp); /** Check whether enough disk space is available for an incoming block */ bool CheckDiskSpace(uint64_t nAdditionalBytes = 0); /** Open a block file (blk?????.dat) */ @@ -780,8 +780,8 @@ bool GetAddressUnspent(uint160 addressHash, int type, /** Functions for disk access for blocks */ bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart); -bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos); -bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex); +bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos,bool checkPOW); +bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex,bool checkPOW); /** Functions for validating blocks and updating the block tree */ @@ -796,8 +796,8 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false,bool fCheckPOW = false); /** Context-independent validity checks */ -bool CheckBlockHeader(int32_t height,CBlockIndex *pindex,const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true); -bool CheckBlock(int32_t height,CBlockIndex *pindex,const CBlock& block, CValidationState& state, +bool CheckBlockHeader(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true); +bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const CBlock& block, CValidationState& state, libzcash::ProofVerifier& verifier, bool fCheckPOW = true, bool fCheckMerkleRoot = true); @@ -815,8 +815,8 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex * - The only caller of AcceptBlock verifies JoinSplit proofs elsewhere. * If dbp is non-NULL, the file is known to already reside on disk */ -bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex **pindex, bool fRequested, CDiskBlockPos* dbp); -bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL); +bool AcceptBlock(int32_t *futureblockp,CBlock& block, CValidationState& state, CBlockIndex **pindex, bool fRequested, CDiskBlockPos* dbp); +bool AcceptBlockHeader(int32_t *futureblockp,const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL); diff --git a/src/miner.cpp b/src/miner.cpp index 176fb83a7..4b7d09252 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -11,6 +11,7 @@ #include "amount.h" #include "base58.h" #include "chainparams.h" +#include "importcoin.h" #include "consensus/consensus.h" #include "consensus/upgrades.h" #include "consensus/validation.h" @@ -63,7 +64,7 @@ public: set setDependsOn; CFeeRate feeRate; double dPriority; - + COrphan(const CTransaction* ptxIn) : ptx(ptxIn), feeRate(0), dPriority(0) { } @@ -77,10 +78,10 @@ typedef boost::tuple TxPriority; class TxPriorityCompare { bool byFee; - + public: TxPriorityCompare(bool _byFee) : byFee(_byFee) { } - + bool operator()(const TxPriority& a, const TxPriority& b) { if (byFee) @@ -108,24 +109,30 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, extern int32_t ASSETCHAINS_SEED,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAIN_INIT,KOMODO_INITDONE,KOMODO_ON_DEMAND,KOMODO_INITDONE,KOMODO_PASSPORT_INITDONE; extern uint64_t ASSETCHAINS_REWARD,ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED; extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -extern std::string NOTARY_PUBKEY; +extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY; +void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len); + extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33]; uint32_t Mining_start,Mining_height; +int32_t My_notaryid = -1; int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); int32_t komodo_pax_opreturn(int32_t height,uint8_t *opret,int32_t maxsize); -uint64_t komodo_paxtotal(); +//uint64_t komodo_paxtotal(); int32_t komodo_baseid(char *origbase); -int32_t komodo_is_issuer(); -int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *symbol,int32_t tokomodo); -int32_t komodo_isrealtime(int32_t *kmdheightp); +//int32_t komodo_is_issuer(); +//int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *symbol,int32_t tokomodo); +//int32_t komodo_isrealtime(int32_t *kmdheightp); int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag); -uint64_t komodo_commission(const CBlock &block); +uint64_t komodo_commission(const CBlock *block); int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig); +int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33); -CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) +CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) { uint64_t deposits; int32_t isrealtime,kmdheight; uint32_t blocktime; const CChainParams& chainparams = Params(); // Create new block + if ( gpucount < 0 ) + gpucount = KOMODO_MAXGPUCOUNT; std::unique_ptr pblocktemplate(new CBlockTemplate()); if(!pblocktemplate.get()) { @@ -133,7 +140,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) return NULL; } CBlock *pblock = &pblocktemplate->block; // pointer for convenience - if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) >= 0 && chainActive.Tip()->nHeight >= ASSETCHAINS_MINHEIGHT ) + /*if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) >= 0 && chainActive.Tip()->nHeight >= ASSETCHAINS_MINHEIGHT ) { isrealtime = komodo_isrealtime(&kmdheight); deposits = komodo_paxtotal(); @@ -154,35 +161,35 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) KOMODO_ON_DEMAND = 0; if ( 0 && deposits != 0 ) printf("miner KOMODO_DEPOSIT %llu pblock->nHeight %d mempool.GetTotalTxSize(%d)\n",(long long)komodo_paxtotal(),(int32_t)chainActive.Tip()->nHeight,(int32_t)mempool.GetTotalTxSize()); - } + }*/ // -regtest only: allow overriding block.nVersion with // -blockversion=N to test forking scenarios if (Params().MineBlocksOnDemand()) pblock->nVersion = GetArg("-blockversion", pblock->nVersion); - + // Add dummy coinbase tx as first transaction pblock->vtx.push_back(CTransaction()); pblocktemplate->vTxFees.push_back(-1); // updated at end pblocktemplate->vTxSigOps.push_back(-1); // updated at end - + // Largest block you're willing to create: unsigned int nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE); // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity: nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize)); - + // How much of the block should be dedicated to high-priority transactions, // included regardless of the fees they pay unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE); nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize); - + // Minimum block size you want to create; block will be filled with free transactions // until there are no more or the block reaches this size: unsigned int nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE); nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize); - + // Collect memory pool transactions into the block CAmount nFees = 0; - + { LOCK2(cs_main, mempool.cs); CBlockIndex* pindexPrev = chainActive.Tip(); @@ -197,7 +204,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) list vOrphan; // list memory doesn't move map > mapDependers; bool fPrintPriority = GetBoolArg("-printpriority", false); - + // This vector will be sorted into a priority queue: vector vecPriority; vecPriority.reserve(mempool.mapTx.size()); @@ -205,75 +212,85 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) mi != mempool.mapTx.end(); ++mi) { const CTransaction& tx = mi->GetTx(); - + int64_t nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST) - ? nMedianTimePast - : pblock->GetBlockTime(); - + ? nMedianTimePast + : pblock->GetBlockTime(); + if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, nLockTimeCutoff) || IsExpiredTx(tx, nHeight)) - continue; - if ( komodo_validate_interest(tx,nHeight,(uint32_t)pblock->nTime,2) < 0 ) { - fprintf(stderr,"CreateNewBlock: komodo_validate_interest failure\n"); + //fprintf(stderr,"coinbase.%d finaltx.%d expired.%d\n",tx.IsCoinBase(),IsFinalTx(tx, nHeight, nLockTimeCutoff),IsExpiredTx(tx, nHeight)); + continue; + } + if ( ASSETCHAINS_SYMBOL[0] == 0 && komodo_validate_interest(tx,nHeight,(uint32_t)pblock->nTime,0) < 0 ) + { + //fprintf(stderr,"CreateNewBlock: komodo_validate_interest failure nHeight.%d nTime.%u vs locktime.%u\n",nHeight,(uint32_t)pblock->nTime,(uint32_t)tx.nLockTime); continue; } COrphan* porphan = NULL; double dPriority = 0; CAmount nTotalIn = 0; bool fMissingInputs = false; - BOOST_FOREACH(const CTxIn& txin, tx.vin) + if (tx.IsCoinImport()) { - // Read prev transaction - if (!view.HaveCoins(txin.prevout.hash)) - { - // This should never happen; all transactions in the memory - // pool should connect to either transactions in the chain - // or other transactions in the memory pool. - if (!mempool.mapTx.count(txin.prevout.hash)) - { - LogPrintf("ERROR: mempool transaction missing input\n"); - if (fDebug) assert("mempool transaction missing input" == 0); - fMissingInputs = true; - if (porphan) - vOrphan.pop_back(); - break; - } - - // Has to wait for dependencies - if (!porphan) - { - // Use list for automatic deletion - vOrphan.push_back(COrphan(&tx)); - porphan = &vOrphan.back(); - } - mapDependers[txin.prevout.hash].push_back(porphan); - porphan->setDependsOn.insert(txin.prevout.hash); - nTotalIn += mempool.mapTx.find(txin.prevout.hash)->GetTx().vout[txin.prevout.n].nValue; - continue; - } - const CCoins* coins = view.AccessCoins(txin.prevout.hash); - assert(coins); - - CAmount nValueIn = coins->vout[txin.prevout.n].nValue; + CAmount nValueIn = GetCoinImportValue(tx); nTotalIn += nValueIn; + dPriority += (double)nValueIn * 1000; // flat multiplier + } else { + BOOST_FOREACH(const CTxIn& txin, tx.vin) + { + // Read prev transaction + if (!view.HaveCoins(txin.prevout.hash)) + { + // This should never happen; all transactions in the memory + // pool should connect to either transactions in the chain + // or other transactions in the memory pool. + if (!mempool.mapTx.count(txin.prevout.hash)) + { + LogPrintf("ERROR: mempool transaction missing input\n"); + if (fDebug) assert("mempool transaction missing input" == 0); + fMissingInputs = true; + if (porphan) + vOrphan.pop_back(); + break; + } - int nConf = nHeight - coins->nHeight; + // Has to wait for dependencies + if (!porphan) + { + // Use list for automatic deletion + vOrphan.push_back(COrphan(&tx)); + porphan = &vOrphan.back(); + } + mapDependers[txin.prevout.hash].push_back(porphan); + porphan->setDependsOn.insert(txin.prevout.hash); + nTotalIn += mempool.mapTx.find(txin.prevout.hash)->GetTx().vout[txin.prevout.n].nValue; + continue; + } + const CCoins* coins = view.AccessCoins(txin.prevout.hash); + assert(coins); - dPriority += (double)nValueIn * nConf; + CAmount nValueIn = coins->vout[txin.prevout.n].nValue; + nTotalIn += nValueIn; + + int nConf = nHeight - coins->nHeight; + + dPriority += (double)nValueIn * nConf; + } + nTotalIn += tx.GetJoinSplitValueIn(); } - nTotalIn += tx.GetJoinSplitValueIn(); if (fMissingInputs) continue; - + // Priority is sum(valuein * age) / modified_txsize unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); dPriority = tx.ComputePriority(dPriority, nTxSize); - + uint256 hash = tx.GetHash(); mempool.ApplyDeltas(hash, dPriority, nTotalIn); - + CFeeRate feeRate(nTotalIn-tx.GetValueOut(), nTxSize); - + if (porphan) { porphan->dPriority = dPriority; @@ -282,45 +299,52 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) else vecPriority.push_back(TxPriority(dPriority, feeRate, &(mi->GetTx()))); } - + // Collect transactions into block uint64_t nBlockSize = 1000; uint64_t nBlockTx = 0; int64_t interest; int nBlockSigOps = 100; bool fSortedByFee = (nBlockPrioritySize <= 0); - + TxPriorityCompare comparer(fSortedByFee); std::make_heap(vecPriority.begin(), vecPriority.end(), comparer); - + while (!vecPriority.empty()) { // Take highest priority transaction off the priority queue: double dPriority = vecPriority.front().get<0>(); CFeeRate feeRate = vecPriority.front().get<1>(); const CTransaction& tx = *(vecPriority.front().get<2>()); - + std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer); vecPriority.pop_back(); - + // Size limits unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); - if (nBlockSize + nTxSize >= nBlockMaxSize) + if (nBlockSize + nTxSize >= nBlockMaxSize-512) // room for extra autotx + { + //fprintf(stderr,"nBlockSize %d + %d nTxSize >= %d nBlockMaxSize\n",(int32_t)nBlockSize,(int32_t)nTxSize,(int32_t)nBlockMaxSize); continue; - + } + // Legacy limits on sigOps: unsigned int nTxSigOps = GetLegacySigOpCount(tx); if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1) + { + //fprintf(stderr,"A nBlockSigOps %d + %d nTxSigOps >= %d MAX_BLOCK_SIGOPS-1\n",(int32_t)nBlockSigOps,(int32_t)nTxSigOps,(int32_t)MAX_BLOCK_SIGOPS); continue; - + } // Skip free transactions if we're past the minimum block size: const uint256& hash = tx.GetHash(); double dPriorityDelta = 0; CAmount nFeeDelta = 0; mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta); if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < ::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize)) + { + //fprintf(stderr,"fee rate skip\n"); continue; - + } // Prioritise by fee once past the priority size or we run out of high-priority // transactions: if (!fSortedByFee && @@ -330,26 +354,32 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) comparer = TxPriorityCompare(fSortedByFee); std::make_heap(vecPriority.begin(), vecPriority.end(), comparer); } - + if (!view.HaveInputs(tx)) + { + //fprintf(stderr,"dont have inputs\n"); continue; - + } CAmount nTxFees = view.GetValueIn(chainActive.Tip()->nHeight,&interest,tx,chainActive.Tip()->nTime)-tx.GetValueOut(); - + nTxSigOps += GetP2SHSigOpCount(tx, view); if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1) + { + //fprintf(stderr,"B nBlockSigOps %d + %d nTxSigOps >= %d MAX_BLOCK_SIGOPS-1\n",(int32_t)nBlockSigOps,(int32_t)nTxSigOps,(int32_t)MAX_BLOCK_SIGOPS); continue; - + } // Note that flags: we don't want to set mempool/IsStandard() // policy here, but we still have to ensure that the block we // create only contains transactions that are valid in new blocks. CValidationState state; PrecomputedTransactionData txdata(tx); if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId)) + { + //fprintf(stderr,"context failure\n"); continue; - + } UpdateCoins(tx, view, nHeight); - + // Added pblock->vtx.push_back(tx); pblocktemplate->vTxFees.push_back(nTxFees); @@ -358,12 +388,12 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) ++nBlockTx; nBlockSigOps += nTxSigOps; nFees += nTxFees; - + if (fPrintPriority) { LogPrintf("priority %.1f fee %s txid %s\n",dPriority, feeRate.ToString(), tx.GetHash().ToString()); } - + // Add transactions that depend on this one to the priority queue if (mapDependers.count(hash)) { @@ -381,41 +411,31 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) } } } - + nLastBlockTx = nBlockTx; nLastBlockSize = nBlockSize; - blocktime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); + blocktime = 1 + std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); //pblock->nTime = blocktime + 1; pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus()); //LogPrintf("CreateNewBlock(): total size %u blocktime.%u nBits.%08x\n", nBlockSize,blocktime,pblock->nBits); - if ( ASSETCHAINS_SYMBOL[0] != 0 && ASSETCHAINS_STAKED != 0 && NOTARY_PUBKEY33[0] != 0 ) + if ( ASSETCHAINS_SYMBOL[0] != 0 && ASSETCHAINS_STAKED != 0 && GetArg("-genproclimit", 0) == 0 ) { uint64_t txfees,utxovalue; uint32_t txtime; uint256 utxotxid,revtxid; int32_t i,siglen,numsigs,utxovout; uint8_t utxosig[128],*ptr; CMutableTransaction txStaked = CreateNewContextualCMutableTransaction(Params().GetConsensus(), chainActive.Height() + 1); - blocktime += 2; if ( (siglen= komodo_staked(txStaked,pblock->nBits,&blocktime,&txtime,&utxotxid,&utxovout,&utxovalue,utxosig)) > 0 ) { CAmount txfees = 0; + if ( (int32_t)chainActive.Tip()->nHeight+1 > 100 && GetAdjustedTime() < blocktime-13 ) + return(0); pblock->vtx.push_back(txStaked); pblocktemplate->vTxFees.push_back(txfees); pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txStaked)); nFees += txfees; pblock->nTime = blocktime; - if ( GetAdjustedTime()+30 < pblock->nTime ) - { - //printf("need to wait %d seconds to submit: ",(int32_t)(pblock->nTime - GetAdjustedTime())); - /*while ( GetAdjustedTime()+30 < pblock->nTime ) - { - sleep(30); - fprintf(stderr,"%d ",(int32_t)(pblock->nTime - GetAdjustedTime())); - }*/ - //fprintf(stderr,"finished waiting\n"); - sleep(30); - } - - } else fprintf(stderr,"no utxos eligible for staking\n"); + printf("staking PoS ht.%d t%u lag.%u\n",(int32_t)chainActive.Tip()->nHeight+1,blocktime,(uint32_t)(GetAdjustedTime() - (blocktime-13))); + } else return(0); //fprintf(stderr,"no utxos eligible for staking\n"); } - + // Create coinbase tx CMutableTransaction txNew = CreateNewContextualCMutableTransaction(chainparams.GetConsensus(), nHeight); txNew.vin.resize(1); @@ -423,38 +443,16 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) txNew.vout.resize(1); txNew.vout[0].scriptPubKey = scriptPubKeyIn; txNew.vout[0].nValue = GetBlockSubsidy(nHeight,chainparams.GetConsensus()); + if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY != 0 && My_notaryid >= 0 ) + txNew.vout[0].nValue += 5000; txNew.nLockTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); txNew.nExpiryHeight = 0; // Add fees txNew.vout[0].nValue += nFees; txNew.vin[0].scriptSig = CScript() << nHeight << OP_0; - - /*if ( ASSETCHAINS_SYMBOL[0] == 0 ) - { - int32_t i,opretlen; uint8_t opret[256],*ptr; - if ( (nHeight % 60) == 0 || komodo_gateway_deposits(&txNew,(char *)"KMD",1) == 0 ) - { - if ( (opretlen= komodo_pax_opreturn((int32_t)nHeight,opret,sizeof(opret))) > 0 ) // have pricefeed - { - txNew.vout.resize(2); - txNew.vout[1].scriptPubKey.resize(opretlen); - ptr = (uint8_t *)txNew.vout[1].scriptPubKey.data(); - for (i=0; i 1 ) - fprintf(stderr,"%s txNew numvouts.%d\n",ASSETCHAINS_SYMBOL,(int32_t)txNew.vout.size()); - }*/ - + pblock->vtx[0] = txNew; - if ( ASSETCHAINS_SYMBOL[0] != 0 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && ASSETCHAINS_COMMISSION != 0 && (commission= komodo_commission(pblocktemplate->block)) != 0 ) + if ( nHeight > 1 && ASSETCHAINS_SYMBOL[0] != 0 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && ASSETCHAINS_COMMISSION != 0 && (commission= komodo_commission((CBlock*)&pblocktemplate->block)) != 0 ) { int32_t i; uint8_t *ptr; txNew.vout.resize(2); @@ -475,73 +473,108 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) nonce <<= 32; nonce >>= 16; pblock->nNonce = ArithToUint256(nonce); - + // Fill in header pblock->hashPrevBlock = pindexPrev->GetBlockHash(); pblock->hashReserved = uint256(); - if ( ASSETCHAINS_SYMBOL[0] == 0 || ASSETCHAINS_STAKED == 0 || NOTARY_PUBKEY33[0] == 0 ) + if ( ASSETCHAINS_SYMBOL[0] == 0 || ASSETCHAINS_STAKED == 0 || GetArg("-genproclimit", 0) > 0 ) { UpdateTime(pblock, Params().GetConsensus(), pindexPrev); pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus()); } pblock->nSolution.clear(); pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]); - - CValidationState state; - if ( !TestBlockValidity(state, *pblock, pindexPrev, false, false)) + if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY != 0 && My_notaryid >= 0 ) { - static uint32_t counter; - //if ( counter++ < 100 && ASSETCHAINS_STAKED == 0 ) - fprintf(stderr,"warning: miner testblockvalidity failed\n"); - return(0); + uint32_t r; + CMutableTransaction txNotary = CreateNewContextualCMutableTransaction(Params().GetConsensus(), chainActive.Height() + 1); + if ( pblock->nTime < pindexPrev->nTime+60 ) + pblock->nTime = pindexPrev->nTime + 60; + if ( gpucount < 33 ) + { + uint8_t tmpbuffer[40]; uint32_t r; int32_t n=0; uint256 randvals; + memcpy(&tmpbuffer[n],&My_notaryid,sizeof(My_notaryid)), n += sizeof(My_notaryid); + memcpy(&tmpbuffer[n],&Mining_height,sizeof(Mining_height)), n += sizeof(Mining_height); + memcpy(&tmpbuffer[n],&pblock->hashPrevBlock,sizeof(pblock->hashPrevBlock)), n += sizeof(pblock->hashPrevBlock); + vcalc_sha256(0,(uint8_t *)&randvals,tmpbuffer,n); + memcpy(&r,&randvals,sizeof(r)); + pblock->nTime += (r % (33 - gpucount)*(33 - gpucount)); + } + if ( komodo_notaryvin(txNotary,NOTARY_PUBKEY33) > 0 ) + { + CAmount txfees = 5000; + pblock->vtx.push_back(txNotary); + pblocktemplate->vTxFees.push_back(txfees); + pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txNotary)); + nFees += txfees; + pblocktemplate->vTxFees[0] = -nFees; + //*(uint64_t *)(&pblock->vtx[0].vout[0].nValue) += txfees; + //fprintf(stderr,"added notaryvin\n"); + } + else + { + fprintf(stderr,"error adding notaryvin, need to create 0.0001 utxos\n"); + return(0); + } + } + else + { + CValidationState state; + if ( !TestBlockValidity(state, *pblock, pindexPrev, false, false)) + { + //static uint32_t counter; + //if ( counter++ < 100 && ASSETCHAINS_STAKED == 0 ) + // fprintf(stderr,"warning: miner testblockvalidity failed\n"); + return(0); + } } } - + return pblocktemplate.release(); } - + /* -#ifdef ENABLE_WALLET -boost::optional GetMinerScriptPubKey(CReserveKey& reservekey) -#else -boost::optional GetMinerScriptPubKey() -#endif -{ - CKeyID keyID; - CBitcoinAddress addr; - if (addr.SetString(GetArg("-mineraddress", ""))) { - addr.GetKeyID(keyID); - } else { -#ifdef ENABLE_WALLET - CPubKey pubkey; - if (!reservekey.GetReservedKey(pubkey)) { - return boost::optional(); - } - keyID = pubkey.GetID(); -#else - return boost::optional(); -#endif - } - - CScript scriptPubKey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG; - return scriptPubKey; -} - -#ifdef ENABLE_WALLET -CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey) -{ - boost::optional scriptPubKey = GetMinerScriptPubKey(reservekey); -#else -CBlockTemplate* CreateNewBlockWithKey() -{ - boost::optional scriptPubKey = GetMinerScriptPubKey(); -#endif - - if (!scriptPubKey) { - return NULL; - } - return CreateNewBlock(*scriptPubKey); -}*/ + #ifdef ENABLE_WALLET + boost::optional GetMinerScriptPubKey(CReserveKey& reservekey) + #else + boost::optional GetMinerScriptPubKey() + #endif + { + CKeyID keyID; + CBitcoinAddress addr; + if (addr.SetString(GetArg("-mineraddress", ""))) { + addr.GetKeyID(keyID); + } else { + #ifdef ENABLE_WALLET + CPubKey pubkey; + if (!reservekey.GetReservedKey(pubkey)) { + return boost::optional(); + } + keyID = pubkey.GetID(); + #else + return boost::optional(); + #endif + } + + CScript scriptPubKey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG; + return scriptPubKey; + } + + #ifdef ENABLE_WALLET + CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey) + { + boost::optional scriptPubKey = GetMinerScriptPubKey(reservekey); + #else + CBlockTemplate* CreateNewBlockWithKey() + { + boost::optional scriptPubKey = GetMinerScriptPubKey(); + #endif + + if (!scriptPubKey) { + return NULL; + } + return CreateNewBlock(*scriptPubKey); + }*/ ////////////////////////////////////////////////////////////////////////////// // @@ -564,7 +597,7 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& CMutableTransaction txCoinbase(pblock->vtx[0]); txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS; assert(txCoinbase.vin[0].scriptSig.size() <= 100); - + pblock->vtx[0] = txCoinbase; pblock->hashMerkleRoot = pblock->BuildMerkleTree(); } @@ -575,10 +608,14 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& // Internal miner // -CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey) +CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey,int32_t nHeight,int32_t gpucount) { CPubKey pubkey; CScript scriptPubKey; uint8_t *script,*ptr; int32_t i; - if ( USE_EXTERNAL_PUBKEY != 0 ) + if ( nHeight == 1 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 ) + { + scriptPubKey = CScript() << ParseHex(ASSETCHAINS_OVERRIDE_PUBKEY) << OP_CHECKSIG; + } + else if ( USE_EXTERNAL_PUBKEY != 0 ) { //fprintf(stderr,"use notary pubkey\n"); scriptPubKey = CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG; @@ -598,9 +635,29 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey) script[34] = OP_CHECKSIG; //scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; } - return CreateNewBlock(scriptPubKey); + return CreateNewBlock(scriptPubKey,gpucount); } +void komodo_broadcast(CBlock *pblock,int32_t limit) +{ + int32_t n = 1; + //fprintf(stderr,"broadcast new block t.%u\n",(uint32_t)time(NULL)); + { + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + { + if ( pnode->hSocket == INVALID_SOCKET ) + continue; + if ( (rand() % n) == 0 ) + { + pnode->PushMessage("block", *pblock); + if ( n++ > limit ) + break; + } + } + } + //fprintf(stderr,"finished broadcast new block t.%u\n",(uint32_t)time(NULL)); +} static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) #else @@ -609,7 +666,7 @@ static bool ProcessBlockFound(CBlock* pblock) { LogPrintf("%s\n", pblock->ToString()); LogPrintf("generated %s height.%d\n", FormatMoney(pblock->vtx[0].vout[0].nValue),chainActive.Tip()->nHeight+1); - + // Found a solution { LOCK(cs_main); @@ -624,11 +681,11 @@ static bool ProcessBlockFound(CBlock* pblock) for (i=31; i>=0; i--) fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); fprintf(stderr," <- chainTip (stale)\n"); - + return error("KomodoMiner: generated block is stale"); } } - + #ifdef ENABLE_WALLET // Remove key from key pool if ( IS_KOMODO_NOTARY == 0 ) @@ -645,24 +702,24 @@ static bool ProcessBlockFound(CBlock* pblock) wallet.mapRequestCount[pblock->GetHash()] = 0; } #endif - + // Process this block the same as if we had received it from another node CValidationState state; - if (!ProcessNewBlock(chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL)) + if (!ProcessNewBlock(1,chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL)) return error("KomodoMiner: ProcessNewBlock, block not accepted"); - + TrackMinedBlock(pblock->GetHash()); - + komodo_broadcast(pblock,16); return true; } int32_t komodo_baseid(char *origbase); -int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,int32_t *nonzpkeysp,int32_t height); +int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t *blocktimes,int32_t *nonzpkeysp,int32_t height); arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc); int32_t FOUND_BLOCK,KOMODO_MAYBEMINED; extern int32_t KOMODO_LASTMINED; int32_t roundrobin_delay; -arith_uint256 HASHTarget; +arith_uint256 HASHTarget,HASHTarget_POW; #ifdef ENABLE_WALLET void static BitcoinMiner(CWallet *pwallet) @@ -674,30 +731,30 @@ void static BitcoinMiner() SetThreadPriority(THREAD_PRIORITY_LOWEST); RenameThread("komodo-miner"); const CChainParams& chainparams = Params(); - + #ifdef ENABLE_WALLET // Each thread has its own key CReserveKey reservekey(pwallet); #endif - + // Each thread has its own counter unsigned int nExtraNonce = 0; - + unsigned int n = chainparams.EquihashN(); unsigned int k = chainparams.EquihashK(); - uint8_t *script; uint64_t total,checktoshis; int32_t i,j,notaryid = -1; + uint8_t *script; uint64_t total,checktoshis; int32_t i,j,gpucount=KOMODO_MAXGPUCOUNT,notaryid = -1; while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) ) //chainActive.Tip()->nHeight != 235300 && { sleep(1); if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 ) break; } - //sleep(60); komodo_chosennotary(¬aryid,chainActive.Tip()->nHeight,NOTARY_PUBKEY33,(uint32_t)chainActive.Tip()->GetBlockTime()); - + if ( notaryid != My_notaryid ) + My_notaryid = notaryid; std::string solver; //if ( notaryid >= 0 || ASSETCHAINS_SYMBOL[0] != 0 ) - solver = "tromp"; + solver = "tromp"; //else solver = "default"; assert(solver == "tromp" || solver == "default"); LogPrint("pow", "Using Equihash solver \"%s\" with n = %u, k = %u\n", solver, n, k); @@ -706,13 +763,13 @@ void static BitcoinMiner() std::mutex m_cs; bool cancelSolver = false; boost::signals2::connection c = uiInterface.NotifyBlockTip.connect( - [&m_cs, &cancelSolver](const uint256& hashNewTip) mutable { - std::lock_guard lock{m_cs}; - cancelSolver = true; - } - ); + [&m_cs, &cancelSolver](const uint256& hashNewTip) mutable { + std::lock_guard lock{m_cs}; + cancelSolver = true; + } + ); miningTimer.start(); - + try { if ( ASSETCHAINS_SYMBOL[0] != 0 ) fprintf(stderr,"try %s Mining with %s\n",ASSETCHAINS_SYMBOL,solver.c_str()); @@ -728,23 +785,18 @@ void static BitcoinMiner() do { bool fvNodesEmpty; { - LOCK(cs_vNodes); + //LOCK(cs_vNodes); fvNodesEmpty = vNodes.empty(); } if (!fvNodesEmpty )//&& !IsInitialBlockDownload()) break; MilliSleep(5000); //fprintf(stderr,"fvNodesEmpty %d IsInitialBlockDownload(%s) %d\n",(int32_t)fvNodesEmpty,ASSETCHAINS_SYMBOL,(int32_t)IsInitialBlockDownload()); - + } while (true); //fprintf(stderr,"%s Found peers\n",ASSETCHAINS_SYMBOL); miningTimer.start(); } - /*while ( ASSETCHAINS_SYMBOL[0] != 0 && chainActive.Tip()->nHeight < ASSETCHAINS_MINHEIGHT ) - { - fprintf(stderr,"%s waiting for block 100, ht.%d\n",ASSETCHAINS_SYMBOL,chainActive.Tip()->nHeight); - sleep(3); - }*/ // // Create new block // @@ -761,7 +813,7 @@ void static BitcoinMiner() sleep(3); } #ifdef ENABLE_WALLET - CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey); + CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey,pindexPrev->nHeight+1,gpucount); #else CBlockTemplate *ptr = CreateNewBlockWithKey(); #endif @@ -770,6 +822,7 @@ void static BitcoinMiner() static uint32_t counter; if ( counter++ < 100 && ASSETCHAINS_STAKED == 0 ) fprintf(stderr,"created illegal block, retry\n"); + sleep(1); continue; } unique_ptr pblocktemplate(ptr); @@ -803,16 +856,19 @@ void static BitcoinMiner() // // Search // - uint8_t pubkeys[66][33]; int mids[256],gpucount,nonzpkeys,i,j,externalflag; uint32_t savebits; int64_t nStart = GetTime(); + uint8_t pubkeys[66][33]; uint32_t blocktimes[66]; int mids[256],nonzpkeys,i,j,externalflag; uint32_t savebits; int64_t nStart = GetTime(); savebits = pblock->nBits; HASHTarget = arith_uint256().SetCompact(pblock->nBits); roundrobin_delay = ROUNDROBIN_DELAY; if ( ASSETCHAINS_SYMBOL[0] == 0 && notaryid >= 0 ) { j = 65; - if ( (Mining_height >= 235300 && Mining_height < 236000) || (Mining_height % KOMODO_ELECTION_GAP) > 64 || (Mining_height % KOMODO_ELECTION_GAP) == 0 ) + if ( (Mining_height >= 235300 && Mining_height < 236000) || (Mining_height % KOMODO_ELECTION_GAP) > 64 || (Mining_height % KOMODO_ELECTION_GAP) == 0 || Mining_height > 1000000 ) { - komodo_eligiblenotary(pubkeys,mids,&nonzpkeys,pindexPrev->nHeight); + int32_t dispflag = 0; + if ( notaryid <= 3 || notaryid == 32 || (notaryid >= 43 && notaryid <= 45) ||notaryid == 51 || notaryid == 52 || notaryid == 56 || notaryid == 57 || notaryid == 62 ) + dispflag = 1; + komodo_eligiblenotary(pubkeys,mids,blocktimes,&nonzpkeys,pindexPrev->nHeight); if ( nonzpkeys > 0 ) { for (i=0; i<33; i++) @@ -821,32 +877,26 @@ void static BitcoinMiner() if ( i == 33 ) externalflag = 1; else externalflag = 0; - if ( NOTARY_PUBKEY33[0] != 0 && (notaryid < 3 || notaryid == 34 || notaryid == 51 || notaryid == 52) ) + if ( IS_KOMODO_NOTARY != 0 ) { for (i=1; i<66; i++) if ( memcmp(pubkeys[i],pubkeys[0],33) == 0 ) break; - if ( externalflag == 0 && i != 66 ) - printf("VIOLATION at %d\n",i); + if ( externalflag == 0 && i != 66 && mids[i] >= 0 ) + printf("VIOLATION at %d, notaryid.%d\n",i,mids[i]); for (j=gpucount=0; j<65; j++) { - if ( mids[j] >= 0 || notaryid == 34 ) - fprintf(stderr,"%d ",mids[j]); - else fprintf(stderr,"GPU "); + if ( dispflag != 0 ) + { + if ( mids[j] >= 0 ) + fprintf(stderr,"%d ",mids[j]); + else fprintf(stderr,"GPU "); + } if ( mids[j] == -1 ) gpucount++; } - if ( gpucount > j/2 ) - { - double delta; - if ( notaryid < 0 ) - i = (rand() % 64); - else i = ((Mining_height + notaryid) % 64); - delta = sqrt((double)gpucount - j/2) / 2.; - roundrobin_delay += ((delta * i) / 64) - delta; - //fprintf(stderr,"delta.%f %f %f\n",delta,(double)(gpucount - j/3) / 2,(delta * i) / 64); - } - fprintf(stderr," <- prev minerids from ht.%d notary.%d gpucount.%d %.2f%% t.%u %d\n",pindexPrev->nHeight,notaryid,gpucount,100.*(double)gpucount/j,(uint32_t)time(NULL),roundrobin_delay); + if ( dispflag != 0 ) + fprintf(stderr," <- prev minerids from ht.%d notary.%d gpucount.%d %.2f%% t.%u\n",pindexPrev->nHeight,notaryid,gpucount,100.*(double)gpucount/j,(uint32_t)time(NULL)); } for (j=0; j<65; j++) if ( mids[j] == notaryid ) @@ -861,27 +911,27 @@ void static BitcoinMiner() } //else fprintf(stderr,"duplicate at j.%d\n",j); } else Mining_start = 0; } else Mining_start = 0; - if ( ASSETCHAINS_STAKED != 0 && NOTARY_PUBKEY33[0] == 0 ) + if ( ASSETCHAINS_STAKED != 0 && GetArg("-genproclimit", 0) == 0 ) { int32_t percPoS,z; - if ( Mining_height <= 100 ) + /*if ( Mining_height <= 100 ) { sleep(60); continue; - } - HASHTarget = komodo_PoWtarget(&percPoS,HASHTarget,Mining_height,ASSETCHAINS_STAKED); + }*/ + HASHTarget_POW = komodo_PoWtarget(&percPoS,HASHTarget,Mining_height,ASSETCHAINS_STAKED); for (z=31; z>=0; z--) - fprintf(stderr,"%02x",((uint8_t *)&HASHTarget)[z]); - fprintf(stderr," PoW for staked coin\n"); + fprintf(stderr,"%02x",((uint8_t *)&HASHTarget_POW)[z]); + fprintf(stderr," PoW for staked coin PoS %d%% vs target %d%%\n",percPoS,(int32_t)ASSETCHAINS_STAKED); } while (true) { /*if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && pblock->vtx[0].vout.size() == 1 && Mining_height > ASSETCHAINS_MINHEIGHT ) // skips when it shouldnt - { - fprintf(stderr,"skip generating %s on-demand block, no tx avail\n",ASSETCHAINS_SYMBOL); - sleep(10); - break; - }*/ + { + fprintf(stderr,"skip generating %s on-demand block, no tx avail\n",ASSETCHAINS_SYMBOL); + sleep(10); + break; + }*/ // Hash state KOMODO_CHOSEN_ONE = 0; crypto_generichash_blake2b_state state; @@ -898,242 +948,257 @@ void static BitcoinMiner() crypto_generichash_blake2b_update(&curr_state,pblock->nNonce.begin(),pblock->nNonce.size()); // (x_1, x_2, ...) = A(I, V, n, k) LogPrint("pow", "Running Equihash solver \"%s\" with nNonce = %s\n",solver, pblock->nNonce.ToString()); - arith_uint256 hashTarget = HASHTarget; - //fprintf(stderr,"running solver\n"); + arith_uint256 hashTarget; + if ( GetArg("-genproclimit", 0) > 0 && ASSETCHAINS_STAKED > 0 && ASSETCHAINS_STAKED < 100 && Mining_height > 10 ) + hashTarget = HASHTarget_POW; + else hashTarget = HASHTarget; std::function)> validBlock = #ifdef ENABLE_WALLET - [&pblock, &hashTarget, &pwallet, &reservekey, &m_cs, &cancelSolver, &chainparams] + [&pblock, &hashTarget, &pwallet, &reservekey, &m_cs, &cancelSolver, &chainparams] #else - [&pblock, &hashTarget, &m_cs, &cancelSolver, &chainparams] + [&pblock, &hashTarget, &m_cs, &cancelSolver, &chainparams] #endif - (std::vector soln) { + (std::vector soln) { + int32_t z; arith_uint256 h; CBlock B; // Write the solution to the hash and compute the result. LogPrint("pow", "- Checking solution against target\n"); pblock->nSolution = soln; solutionTargetChecks.increment(); - if ( UintToArith256(pblock->GetHash()) > HASHTarget ) - { - //if ( ASSETCHAINS_SYMBOL[0] != 0 ) - // fprintf(stderr," missed target\n"); + B = *pblock; + h = UintToArith256(B.GetHash()); + /*for (z=31; z>=16; z--) + fprintf(stderr,"%02x",((uint8_t *)&h)[z]); + fprintf(stderr," mined "); + for (z=31; z>=16; z--) + fprintf(stderr,"%02x",((uint8_t *)&HASHTarget)[z]); + fprintf(stderr," hashTarget "); + for (z=31; z>=16; z--) + fprintf(stderr,"%02x",((uint8_t *)&HASHTarget_POW)[z]); + fprintf(stderr," POW\n");*/ + if ( h > hashTarget ) return false; - } - CValidationState state; - if ( !TestBlockValidity(state, *pblock, chainActive.Tip(), true, false)) + if ( B.nTime > GetAdjustedTime() ) { - fprintf(stderr,"Invalid block mined, try again\n"); - return(false); + fprintf(stderr,"need to wait %d seconds to submit block\n",(int32_t)(B.nTime - GetAdjustedTime())); + while ( GetAdjustedTime() < B.nTime-2 ) + { + sleep(1); + if ( chainActive.Tip()->nHeight >= Mining_height ) + { + fprintf(stderr,"new block arrived\n"); + return(false); + } + } } if ( ASSETCHAINS_STAKED == 0 ) { - if ( Mining_start != 0 && time(NULL) < Mining_start+roundrobin_delay ) + if ( IS_KOMODO_NOTARY != 0 ) { - //printf("Round robin diff sleep %d\n",(int32_t)(Mining_start+roundrobin_delay-time(NULL))); - int32_t nseconds = Mining_start+roundrobin_delay-time(NULL); - if ( nseconds > 0 ) - sleep(nseconds); - MilliSleep((rand() % 1700) + 1); - } - else if ( ASSETCHAINS_SYMBOL[0] != 0 ) - { - sleep(rand() % 30); + int32_t r; + if ( (r= ((Mining_height + NOTARY_PUBKEY33[16]) % 64) / 8) > 0 ) + MilliSleep((rand() % (r * 1000)) + 1000); } } else { - if ( NOTARY_PUBKEY33[0] != 0 ) - { - printf("need to wait %d seconds to submit\n",(int32_t)(pblock->nTime - GetAdjustedTime())); - while ( GetAdjustedTime() < pblock->nTime ) - sleep(1); - } - else - { - uint256 tmp = pblock->GetHash(); - int32_t z; for (z=31; z>=0; z--) - fprintf(stderr,"%02x",((uint8_t *)&tmp)[z]); - fprintf(stderr," mined block!\n"); - } + while ( GetAdjustedTime() < B.nTime ) + sleep(1); + uint256 tmp = B.GetHash(); + int32_t z; for (z=31; z>=0; z--) + fprintf(stderr,"%02x",((uint8_t *)&tmp)[z]); + fprintf(stderr," mined block!\n"); + } + CValidationState state; + if ( !TestBlockValidity(state,B, chainActive.Tip(), true, false)) + { + h = UintToArith256(B.GetHash()); + for (z=31; z>=0; z--) + fprintf(stderr,"%02x",((uint8_t *)&h)[z]); + fprintf(stderr," Invalid block mined, try again\n"); + return(false); } KOMODO_CHOSEN_ONE = 1; // Found a solution SetThreadPriority(THREAD_PRIORITY_NORMAL); LogPrintf("KomodoMiner:\n"); - LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), HASHTarget.GetHex()); + LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", B.GetHash().GetHex(), HASHTarget.GetHex()); #ifdef ENABLE_WALLET - if (ProcessBlockFound(pblock, *pwallet, reservekey)) { + if (ProcessBlockFound(&B, *pwallet, reservekey)) { #else - if (ProcessBlockFound(pblock)) { + if (ProcessBlockFound(&B)) { #endif - // Ignore chain updates caused by us + // Ignore chain updates caused by us + std::lock_guard lock{m_cs}; + cancelSolver = false; + } + KOMODO_CHOSEN_ONE = 0; + SetThreadPriority(THREAD_PRIORITY_LOWEST); + // In regression test mode, stop mining after a block is found. + if (chainparams.MineBlocksOnDemand()) { + // Increment here because throwing skips the call below + ehSolverRuns.increment(); + throw boost::thread_interrupted(); + } + return true; + }; + std::function cancelled = [&m_cs, &cancelSolver](EhSolverCancelCheck pos) { std::lock_guard lock{m_cs}; - cancelSolver = false; - } - KOMODO_CHOSEN_ONE = 0; - SetThreadPriority(THREAD_PRIORITY_LOWEST); - // In regression test mode, stop mining after a block is found. - if (chainparams.MineBlocksOnDemand()) { - // Increment here because throwing skips the call below - ehSolverRuns.increment(); - throw boost::thread_interrupted(); - } - //if ( ASSETCHAINS_SYMBOL[0] == 0 && NOTARY_PUBKEY33[0] != 0 ) - // sleep(1800); - return true; - }; - std::function cancelled = [&m_cs, &cancelSolver](EhSolverCancelCheck pos) { - std::lock_guard lock{m_cs}; - return cancelSolver; - }; - - // TODO: factor this out into a function with the same API for each solver. - if (solver == "tromp" ) { //&& notaryid >= 0 ) { - // Create solver and initialize it. - equi eq(1); - eq.setstate(&curr_state); - - // Initialization done, start algo driver. - eq.digit0(0); - eq.xfull = eq.bfull = eq.hfull = 0; - eq.showbsizes(0); - for (u32 r = 1; r < WK; r++) { - (r&1) ? eq.digitodd(r, 0) : eq.digiteven(r, 0); + return cancelSolver; + }; + + // TODO: factor this out into a function with the same API for each solver. + if (solver == "tromp" ) { //&& notaryid >= 0 ) { + // Create solver and initialize it. + equi eq(1); + eq.setstate(&curr_state); + + // Initialization done, start algo driver. + eq.digit0(0); eq.xfull = eq.bfull = eq.hfull = 0; - eq.showbsizes(r); - } - eq.digitK(0); - ehSolverRuns.increment(); - - // Convert solution indices to byte array (decompress) and pass it to validBlock method. - for (size_t s = 0; s < eq.nsols; s++) { - LogPrint("pow", "Checking solution %d\n", s+1); - std::vector index_vector(PROOFSIZE); - for (size_t i = 0; i < PROOFSIZE; i++) { - index_vector[i] = eq.sols[s][i]; + eq.showbsizes(0); + for (u32 r = 1; r < WK; r++) { + (r&1) ? eq.digitodd(r, 0) : eq.digiteven(r, 0); + eq.xfull = eq.bfull = eq.hfull = 0; + eq.showbsizes(r); } - std::vector sol_char = GetMinimalFromIndices(index_vector, DIGITBITS); - - if (validBlock(sol_char)) { - // If we find a POW solution, do not try other solutions - // because they become invalid as we created a new block in blockchain. - break; - } - } - } else { - try { - // If we find a valid block, we rebuild - bool found = EhOptimisedSolve(n, k, curr_state, validBlock, cancelled); + eq.digitK(0); ehSolverRuns.increment(); - if (found) { - int32_t i; uint256 hash = pblock->GetHash(); - for (i=0; i<32; i++) - fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); - fprintf(stderr," <- %s Block found %d\n",ASSETCHAINS_SYMBOL,Mining_height); - FOUND_BLOCK = 1; - KOMODO_MAYBEMINED = Mining_height; + + // Convert solution indices to byte array (decompress) and pass it to validBlock method. + for (size_t s = 0; s < eq.nsols; s++) { + LogPrint("pow", "Checking solution %d\n", s+1); + std::vector index_vector(PROOFSIZE); + for (size_t i = 0; i < PROOFSIZE; i++) { + index_vector[i] = eq.sols[s][i]; + } + std::vector sol_char = GetMinimalFromIndices(index_vector, DIGITBITS); + + if (validBlock(sol_char)) { + // If we find a POW solution, do not try other solutions + // because they become invalid as we created a new block in blockchain. + break; + } + } + } else { + try { + // If we find a valid block, we rebuild + bool found = EhOptimisedSolve(n, k, curr_state, validBlock, cancelled); + ehSolverRuns.increment(); + if (found) { + int32_t i; uint256 hash = pblock->GetHash(); + for (i=0; i<32; i++) + fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); + fprintf(stderr," <- %s Block found %d\n",ASSETCHAINS_SYMBOL,Mining_height); + FOUND_BLOCK = 1; + KOMODO_MAYBEMINED = Mining_height; + break; + } + } catch (EhSolverCancelledException&) { + LogPrint("pow", "Equihash solver cancelled\n"); + std::lock_guard lock{m_cs}; + cancelSolver = false; + } + } + + // Check for stop or if block needs to be rebuilt + boost::this_thread::interruption_point(); + // Regtest mode doesn't require peers + if ( FOUND_BLOCK != 0 ) + { + FOUND_BLOCK = 0; + fprintf(stderr,"FOUND_BLOCK!\n"); + //sleep(2000); + } + if (vNodes.empty() && chainparams.MiningRequiresPeers()) + { + if ( ASSETCHAINS_SYMBOL[0] == 0 || Mining_height > ASSETCHAINS_MINHEIGHT ) + { + fprintf(stderr,"no nodes, break\n"); break; } - } catch (EhSolverCancelledException&) { - LogPrint("pow", "Equihash solver cancelled\n"); - std::lock_guard lock{m_cs}; - cancelSolver = false; } - } - - // Check for stop or if block needs to be rebuilt - boost::this_thread::interruption_point(); - // Regtest mode doesn't require peers - if ( FOUND_BLOCK != 0 ) - { - FOUND_BLOCK = 0; - fprintf(stderr,"FOUND_BLOCK!\n"); - //sleep(2000); - } - if (vNodes.empty() && chainparams.MiningRequiresPeers()) - { - if ( ASSETCHAINS_SYMBOL[0] == 0 || Mining_height > ASSETCHAINS_MINHEIGHT ) + if ((UintToArith256(pblock->nNonce) & 0xffff) == 0xffff) { - fprintf(stderr,"no nodes, break\n"); + //if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) + fprintf(stderr,"0xffff, break\n"); break; } - } - if ((UintToArith256(pblock->nNonce) & 0xffff) == 0xffff) - { - //if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - fprintf(stderr,"0xffff, break\n"); - break; - } - if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60) - { - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - fprintf(stderr,"timeout, break\n"); - break; - } - if ( pindexPrev != chainActive.Tip() ) - { - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - fprintf(stderr,"Tip advanced, break\n"); - break; - } - // Update nNonce and nTime - pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1); - pblock->nBits = savebits; - if ( ASSETCHAINS_STAKED == 0 || NOTARY_PUBKEY33[0] == 0 ) - UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); - if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks) - { - // Changing pblock->nTime can change work required on testnet: - HASHTarget.SetCompact(pblock->nBits); + if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60) + { + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) + fprintf(stderr,"timeout, break\n"); + break; + } + if ( pindexPrev != chainActive.Tip() ) + { + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) + fprintf(stderr,"Tip advanced, break\n"); + break; + } + // Update nNonce and nTime + pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1); + pblock->nBits = savebits; + /*if ( NOTARY_PUBKEY33[0] == 0 ) + { + int32_t percPoS; + UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); + if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks) + { + // Changing pblock->nTime can change work required on testnet: + HASHTarget.SetCompact(pblock->nBits); + HASHTarget_POW = komodo_PoWtarget(&percPoS,HASHTarget,Mining_height,ASSETCHAINS_STAKED); + } + }*/ } } } - } - catch (const boost::thread_interrupted&) - { + catch (const boost::thread_interrupted&) + { + miningTimer.stop(); + c.disconnect(); + LogPrintf("KomodoMiner terminated\n"); + throw; + } + catch (const std::runtime_error &e) + { + miningTimer.stop(); + c.disconnect(); + LogPrintf("KomodoMiner runtime error: %s\n", e.what()); + return; + } miningTimer.stop(); c.disconnect(); - LogPrintf("KomodoMiner terminated\n"); - throw; } - catch (const std::runtime_error &e) - { - miningTimer.stop(); - c.disconnect(); - LogPrintf("KomodoMiner runtime error: %s\n", e.what()); - return; - } - miningTimer.stop(); - c.disconnect(); -} - + #ifdef ENABLE_WALLET -void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads) + void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads) #else -void GenerateBitcoins(bool fGenerate, int nThreads) + void GenerateBitcoins(bool fGenerate, int nThreads) #endif -{ - static boost::thread_group* minerThreads = NULL; - - if (nThreads < 0) - nThreads = GetNumCores(); - - if (minerThreads != NULL) { - minerThreads->interrupt_all(); - delete minerThreads; - minerThreads = NULL; - } - - if (nThreads == 0 || !fGenerate) - return; - - minerThreads = new boost::thread_group(); - for (int i = 0; i < nThreads; i++) { + static boost::thread_group* minerThreads = NULL; + + if (nThreads < 0) + nThreads = GetNumCores(); + + if (minerThreads != NULL) + { + minerThreads->interrupt_all(); + delete minerThreads; + minerThreads = NULL; + } + + if (nThreads == 0 || !fGenerate) + return; + + minerThreads = new boost::thread_group(); + for (int i = 0; i < nThreads; i++) { #ifdef ENABLE_WALLET - minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet)); + minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet)); #else - minerThreads->create_thread(&BitcoinMiner); + minerThreads->create_thread(&BitcoinMiner); #endif + } } -} - + #endif // ENABLE_MINING diff --git a/src/miner.h b/src/miner.h index bf1a088f0..5486f2d5e 100644 --- a/src/miner.h +++ b/src/miner.h @@ -25,12 +25,13 @@ struct CBlockTemplate std::vector vTxFees; std::vector vTxSigOps; }; +#define KOMODO_MAXGPUCOUNT 65 /** Generate a new block, without valid proof-of-work */ -CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn); +CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount); #ifdef ENABLE_WALLET boost::optional GetMinerScriptPubKey(CReserveKey& reservekey); -CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey); +CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey,int32_t nHeight,int32_t gpucount); #else boost::optional GetMinerScriptPubKey(); CBlockTemplate* CreateNewBlockWithKey(); diff --git a/src/notarisationdb.cpp b/src/notarisationdb.cpp new file mode 100644 index 000000000..6210d88dd --- /dev/null +++ b/src/notarisationdb.cpp @@ -0,0 +1,84 @@ +#include "leveldbwrapper.h" +#include "notarisationdb.h" +#include "uint256.h" +#include "cc/eval.h" + +#include + + +NotarisationDB *pnotarisations; + + +NotarisationDB::NotarisationDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDBWrapper(GetDataDir() / "notarisations", nCacheSize, fMemory, fWipe, false, 64) { } + + +NotarisationsInBlock ScanBlockNotarisations(const CBlock &block, int nHeight) +{ + EvalRef eval; + NotarisationsInBlock vNotarisations; + + for (unsigned int i = 0; i < block.vtx.size(); i++) { + CTransaction tx = block.vtx[i]; + + // Special case for TXSCL. Should prob be removed at some point. + bool isTxscl = 0; + { + NotarisationData data; + if (ParseNotarisationOpReturn(tx, data)) + if (strlen(data.symbol) >= 5 && strncmp(data.symbol, "TXSCL", 5) == 0) + isTxscl = 1; + } + + if (isTxscl || eval->CheckNotaryInputs(tx, nHeight, block.nTime)) { + NotarisationData data; + if (ParseNotarisationOpReturn(tx, data)) { + vNotarisations.push_back(std::make_pair(tx.GetHash(), data)); + //printf("Parsed a notarisation for: %s, txid:%s, ccid:%i, momdepth:%i\n", + // data.symbol, tx.GetHash().GetHex().data(), data.ccId, data.MoMDepth); + //if (!data.MoMoM.IsNull()) printf("MoMoM:%s\n", data.MoMoM.GetHex().data()); + } + else + LogPrintf("WARNING: Couldn't parse notarisation for tx: %s at height %i\n", + tx.GetHash().GetHex().data(), nHeight); + } + } + return vNotarisations; +} + + +bool GetBlockNotarisations(uint256 blockHash, NotarisationsInBlock &nibs) +{ + return pnotarisations->Read(blockHash, nibs); +} + + +bool GetBackNotarisation(uint256 notarisationHash, Notarisation &n) +{ + return pnotarisations->Read(notarisationHash, n); +} + + +/* + * Write an index of KMD notarisation id -> backnotarisation + */ +void WriteBackNotarisations(const NotarisationsInBlock notarisations, CLevelDBBatch &batch) +{ + int wrote = 0; + BOOST_FOREACH(const Notarisation &n, notarisations) + { + if (!n.second.txHash.IsNull()) { + batch.Write(n.second.txHash, n); + wrote++; + } + } +} + + +void EraseBackNotarisations(const NotarisationsInBlock notarisations, CLevelDBBatch &batch) +{ + BOOST_FOREACH(const Notarisation &n, notarisations) + { + if (!n.second.txHash.IsNull()) + batch.Erase(n.second.txHash); + } +} diff --git a/src/notarisationdb.h b/src/notarisationdb.h new file mode 100644 index 000000000..ce5360e7d --- /dev/null +++ b/src/notarisationdb.h @@ -0,0 +1,27 @@ +#ifndef NOTARISATIONDB_H +#define NOTARISATIONDB_H + +#include "uint256.h" +#include "leveldbwrapper.h" +#include "cc/eval.h" + + +class NotarisationDB : public CLevelDBWrapper +{ +public: + NotarisationDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false); +}; + + +extern NotarisationDB *pnotarisations; + +typedef std::pair Notarisation; +typedef std::vector NotarisationsInBlock; + +NotarisationsInBlock ScanBlockNotarisations(const CBlock &block, int nHeight); +bool GetBlockNotarisations(uint256 blockHash, NotarisationsInBlock &nibs); +bool GetBackNotarisation(uint256 notarisationHash, Notarisation &n); +void WriteBackNotarisations(const NotarisationsInBlock notarisations, CLevelDBBatch &batch); +void EraseBackNotarisations(const NotarisationsInBlock notarisations, CLevelDBBatch &batch); + +#endif /* NOTARISATIONDB_H */ diff --git a/src/paymentdisclosure.h b/src/paymentdisclosure.h index e6a995ab4..fddb25bbe 100644 --- a/src/paymentdisclosure.h +++ b/src/paymentdisclosure.h @@ -73,7 +73,11 @@ struct PaymentDisclosurePayload { uint8_t version; // 0 = experimental, 1 = first production version, etc. uint256 esk; // zcash/NoteEncryption.cpp uint256 txid; // primitives/transaction.h + #ifdef __LP64__ + uint64_t js; + #else size_t js; // Index into CTransaction.vjoinsplit + #endif uint8_t n; // Index into JSDescription fields of length ZC_NUM_JS_OUTPUTS libzcash::PaymentAddress zaddr; // zcash/Address.hpp std::string message; // parameter to RPC call diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index e1fb1c3c6..e4ff99246 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -53,13 +53,13 @@ void TxConfirmStats::ClearCurrent(unsigned int nBlockHeight) unsigned int TxConfirmStats::FindBucketIndex(double val) { - extern char ASSETCHAINS_SYMBOL[]; + extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; auto it = bucketMap.lower_bound(val); if ( it != bucketMap.end() ) { - static uint32_t counter; - if ( counter++ < 1 ) - fprintf(stderr,"%s FindBucketIndex violation: from val %f\n",ASSETCHAINS_SYMBOL,val); + //static uint32_t counter; + //if ( counter++ < 1 ) + // fprintf(stderr,"%s FindBucketIndex violation: from val %f\n",ASSETCHAINS_SYMBOL,val); } return it->second; } diff --git a/src/pow.cpp b/src/pow.cpp index b7b945353..2e525e8cb 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -86,6 +86,8 @@ bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams& param unsigned int n = params.EquihashN(); unsigned int k = params.EquihashK(); + if ( Params().NetworkIDString() == "regtest" ) + return(true); // Hash state crypto_generichash_blake2b_state state; EhInitialiseState(n, k, state); @@ -117,27 +119,31 @@ bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams& param } int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); -int32_t komodo_is_special(uint8_t pubkeys[66][33],int32_t mids[66],int32_t height,uint8_t pubkey33[33],uint32_t timestamp); +int32_t komodo_is_special(uint8_t pubkeys[66][33],int32_t mids[66],uint32_t blocktimes[66],int32_t height,uint8_t pubkey33[33],uint32_t blocktime); int32_t komodo_currentheight(); CBlockIndex *komodo_chainactive(int32_t height); void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height); extern int32_t KOMODO_CHOSEN_ONE; extern uint64_t ASSETCHAINS_STAKED; -extern char ASSETCHAINS_SYMBOL[]; +extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; #define KOMODO_ELECTION_GAP 2000 -int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,int32_t *nonzpkeysp,int32_t height); +int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t blocktimes[66],int32_t *nonzpkeysp,int32_t height); int32_t KOMODO_LOADINGBLOCKS = 1; extern std::string NOTARY_PUBKEY; -bool CheckProofOfWork(int32_t height,uint8_t *pubkey33,uint256 hash, unsigned int nBits, const Consensus::Params& params) +bool CheckProofOfWork(int32_t height,uint8_t *pubkey33,uint256 hash,unsigned int nBits,const Consensus::Params& params,uint32_t blocktime) { extern int32_t KOMODO_REWIND; - bool fNegative,fOverflow; uint8_t origpubkey33[33]; int32_t i,nonzpkeys=0,nonz=0,special=0,special2=0,notaryid=-1,flag = 0, mids[66]; uint32_t timestamp = 0; CBlockIndex *pindex=0; + bool fNegative,fOverflow; uint8_t origpubkey33[33]; int32_t i,nonzpkeys=0,nonz=0,special=0,special2=0,notaryid=-1,flag = 0, mids[66]; uint32_t tiptime,blocktimes[66]; arith_uint256 bnTarget; uint8_t pubkeys[66][33]; + //for (i=31; i>=0; i--) + // fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); + //fprintf(stderr," checkpow\n"); memcpy(origpubkey33,pubkey33,33); - timestamp = komodo_chainactive_timestamp(); + memset(blocktimes,0,sizeof(blocktimes)); + tiptime = komodo_chainactive_timestamp(); bnTarget.SetCompact(nBits, &fNegative, &fOverflow); if ( height == 0 ) { @@ -146,7 +152,7 @@ bool CheckProofOfWork(int32_t height,uint8_t *pubkey33,uint256 hash, unsigned in } if ( height > 34000 && ASSETCHAINS_SYMBOL[0] == 0 ) // 0 -> non-special notary { - special = komodo_chosennotary(¬aryid,height,pubkey33,timestamp); + special = komodo_chosennotary(¬aryid,height,pubkey33,tiptime); for (i=0; i<33; i++) { if ( pubkey33[i] != 0 ) @@ -157,8 +163,8 @@ bool CheckProofOfWork(int32_t height,uint8_t *pubkey33,uint256 hash, unsigned in //fprintf(stderr,"ht.%d null pubkey checkproof return\n",height); return(true); // will come back via different path with pubkey set } - flag = komodo_eligiblenotary(pubkeys,mids,&nonzpkeys,height); - special2 = komodo_is_special(pubkeys,mids,height,pubkey33,timestamp); + flag = komodo_eligiblenotary(pubkeys,mids,blocktimes,&nonzpkeys,height); + special2 = komodo_is_special(pubkeys,mids,blocktimes,height,pubkey33,blocktime); if ( notaryid >= 0 ) { if ( height > 10000 && height < 80000 && (special != 0 || special2 > 0) ) @@ -166,7 +172,7 @@ bool CheckProofOfWork(int32_t height,uint8_t *pubkey33,uint256 hash, unsigned in else if ( height >= 80000 && height < 108000 && special2 > 0 ) flag = 1; else if ( height >= 108000 && special2 > 0 ) - flag = ((height % KOMODO_ELECTION_GAP) > 64 || (height % KOMODO_ELECTION_GAP) == 0); + flag = (height > 1000000 || (height % KOMODO_ELECTION_GAP) > 64 || (height % KOMODO_ELECTION_GAP) == 0); else if ( height == 790833 ) flag = 1; else if ( special2 < 0 ) @@ -175,7 +181,7 @@ bool CheckProofOfWork(int32_t height,uint8_t *pubkey33,uint256 hash, unsigned in flag = 0; else fprintf(stderr,"ht.%d notaryid.%d special.%d flag.%d special2.%d\n",height,notaryid,special,flag,special2); } - if ( flag != 0 || special2 > 0 ) + if ( (flag != 0 || special2 > 0) && special2 != -2 ) { //fprintf(stderr,"EASY MINING ht.%d\n",height); bnTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); @@ -190,11 +196,35 @@ bool CheckProofOfWork(int32_t height,uint8_t *pubkey33,uint256 hash, unsigned in if ( KOMODO_LOADINGBLOCKS != 0 ) return true; if ( ASSETCHAINS_SYMBOL[0] != 0 || height > 792000 ) + { + //if ( 0 && height > 792000 ) + { + for (i=31; i>=0; i--) + fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); + fprintf(stderr," hash vs "); + for (i=31; i>=0; i--) + fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); + fprintf(stderr," ht.%d special.%d special2.%d flag.%d notaryid.%d mod.%d error\n",height,special,special2,flag,notaryid,(height % 35)); + for (i=0; i<33; i++) + fprintf(stderr,"%02x",pubkey33[i]); + fprintf(stderr," <- pubkey\n"); + for (i=0; i<33; i++) + fprintf(stderr,"%02x",origpubkey33[i]); + fprintf(stderr," <- origpubkey\n"); + } return false; + } } + /*for (i=31; i>=0; i--) + fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); + fprintf(stderr," hash vs "); + for (i=31; i>=0; i--) + fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); + fprintf(stderr," height.%d notaryid.%d PoW valid\n",height,notaryid);*/ return true; } + arith_uint256 GetBlockProof(const CBlockIndex& block) { arith_uint256 bnTarget; diff --git a/src/pow.h b/src/pow.h index 3edec74ac..213fe228d 100644 --- a/src/pow.h +++ b/src/pow.h @@ -25,7 +25,7 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams&); /** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */ -bool CheckProofOfWork(int32_t height,uint8_t *pubkey33,uint256 hash, unsigned int nBits, const Consensus::Params&); +bool CheckProofOfWork(int32_t height,uint8_t *pubkey33,uint256 hash, unsigned int nBits, const Consensus::Params&,uint32_t blocktime); arith_uint256 GetBlockProof(const CBlockIndex& block); /** Return the time it would take to redo the work difference between from and to, assuming the current hashrate corresponds to the difficulty at tip, in seconds. */ diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index c2300c82a..8543a601e 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -15,7 +15,9 @@ uint256 CBlockHeader::GetHash() const return SerializeHash(*this); } -uint256 CBlock::BuildMerkleTree(bool* fMutated) const + +uint256 BuildMerkleTree(bool* fMutated, const std::vector leaves, + std::vector &vMerkleTree) { /* WARNING! If you're reading this because you're learning about crypto and/or designing a new system that will use merkle trees, keep in mind @@ -28,10 +30,10 @@ uint256 CBlock::BuildMerkleTree(bool* fMutated) const transactions leading to the same merkle root. For example, these two trees: - A A - / \ / \ - B C B C - / \ | / \ / \ + A A + / \ / \ + B C B C + / \ \ / \ / \ D E F D E F F / \ / \ / \ / \ / \ / \ / \ 1 2 3 4 5 6 1 2 3 4 5 6 5 6 @@ -52,13 +54,14 @@ uint256 CBlock::BuildMerkleTree(bool* fMutated) const known ways of changing the transactions without affecting the merkle root. */ + vMerkleTree.clear(); - vMerkleTree.reserve(vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes. - for (std::vector::const_iterator it(vtx.begin()); it != vtx.end(); ++it) - vMerkleTree.push_back(it->GetHash()); + vMerkleTree.reserve(leaves.size() * 2 + 16); // Safe upper bound for the number of total nodes. + for (std::vector::const_iterator it(leaves.begin()); it != leaves.end(); ++it) + vMerkleTree.push_back(*it); int j = 0; bool mutated = false; - for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) + for (int nSize = leaves.size(); nSize > 1; nSize = (nSize + 1) / 2) { for (int i = 0; i < nSize; i += 2) { @@ -78,13 +81,20 @@ uint256 CBlock::BuildMerkleTree(bool* fMutated) const return (vMerkleTree.empty() ? uint256() : vMerkleTree.back()); } -std::vector CBlock::GetMerkleBranch(int nIndex) const + +uint256 CBlock::BuildMerkleTree(bool* fMutated) const +{ + std::vector leaves; + for (int i=0; i GetMerkleBranch(int nIndex, int nLeaves, const std::vector &vMerkleTree) { - if (vMerkleTree.empty()) - BuildMerkleTree(); std::vector vMerkleBranch; int j = 0; - for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) + for (int nSize = nLeaves; nSize > 1; nSize = (nSize + 1) / 2) { int i = std::min(nIndex^1, nSize-1); vMerkleBranch.push_back(vMerkleTree[j+i]); @@ -94,6 +104,15 @@ std::vector CBlock::GetMerkleBranch(int nIndex) const return vMerkleBranch; } + +std::vector CBlock::GetMerkleBranch(int nIndex) const +{ + if (vMerkleTree.empty()) + BuildMerkleTree(); + return ::GetMerkleBranch(nIndex, vtx.size(), vMerkleTree); +} + + uint256 CBlock::CheckMerkleBranch(uint256 hash, const std::vector& vMerkleBranch, int nIndex) { if (nIndex == -1) diff --git a/src/primitives/block.h b/src/primitives/block.h index 6b3f13a86..6bc06f426 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -139,6 +139,12 @@ public: }; +uint256 BuildMerkleTree(bool* fMutated, const std::vector leaves, + std::vector &vMerkleTree); + +std::vector GetMerkleBranch(int nIndex, int nLeaves, const std::vector &vMerkleTree); + + /** * Custom serializer for CBlockHeader that omits the nonce and solution, for use * as input to Equihash. diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 35c12abc8..88ee9a312 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -452,11 +452,21 @@ public: // Compute modified tx size for priority calculation (optionally given tx size) unsigned int CalculateModifiedSize(unsigned int nTxSize=0) const; + bool IsMint() const + { + return IsCoinImport() || IsCoinBase(); + } + bool IsCoinBase() const { return (vin.size() == 1 && vin[0].prevout.IsNull()); } + bool IsCoinImport() const + { + return (vin.size() == 1 && vin[0].prevout.n == 10e8); + } + friend bool operator==(const CTransaction& a, const CTransaction& b) { return a.hash == b.hash; diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index d8a0a184b..170e45d59 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -264,7 +264,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco if (wtx.IsCoinBase()) { - extern char ASSETCHAINS_SYMBOL[]; + extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; if ( ASSETCHAINS_SYMBOL[0] == 0 ) COINBASE_MATURITY = _COINBASE_MATURITY; quint32 numBlocksToMaturity = COINBASE_MATURITY + 1; diff --git a/src/rest.cpp b/src/rest.cpp index eb0bf8fc4..8e2e4d1e6 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -214,7 +214,7 @@ static bool rest_block(HTTPRequest* req, if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not available (pruned data)"); - if (!ReadBlockFromDisk(block, pblockindex)) + if (!ReadBlockFromDisk(block, pblockindex,1)) return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found"); } @@ -563,7 +563,6 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) utxo.push_back(Pair("txvers", (int32_t)coin.nTxVer)); utxo.push_back(Pair("height", (int32_t)coin.nHeight)); utxo.push_back(Pair("value", ValueFromAmount(coin.out.nValue))); - //utxo.push_back(Pair("interest", ValueFromAmount(komodo_interest(coin.out.nValue,coin.nLockTime,chainActive.Tip()->nTime)))); // include the script in a json output UniValue o(UniValue::VOBJ); diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index c850492b5..42cf7f2b0 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -7,9 +7,10 @@ #include "chain.h" #include "chainparams.h" #include "checkpoints.h" +#include "crosschain.h" #include "base58.h" #include "consensus/validation.h" -#include "cc/betprotocol.h" +#include "cc/eval.h" #include "main.h" #include "primitives/transaction.h" #include "rpcserver.h" @@ -171,9 +172,11 @@ UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex) if (GetSpentIndex(spentKey, spentInfo)) { if (spentInfo.addressType == 1) { delta.push_back(Pair("address", CBitcoinAddress(CKeyID(spentInfo.addressHash)).ToString())); - } else if (spentInfo.addressType == 2) { + } + else if (spentInfo.addressType == 2) { delta.push_back(Pair("address", CBitcoinAddress(CScriptID(spentInfo.addressHash)).ToString())); - } else { + } + else { continue; } delta.push_back(Pair("satoshis", -1 * spentInfo.satoshis)); @@ -202,10 +205,21 @@ UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex) vector hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22); delta.push_back(Pair("address", CBitcoinAddress(CScriptID(uint160(hashBytes))).ToString())); - } else if (out.scriptPubKey.IsPayToPublicKeyHash()) { + } + else if (out.scriptPubKey.IsPayToPublicKeyHash()) { vector hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23); delta.push_back(Pair("address", CBitcoinAddress(CKeyID(uint160(hashBytes))).ToString())); - } else { + } + else if (out.scriptPubKey.IsPayToPublicKey()) { + CTxDestination address; + if (ExtractDestination(out.scriptPubKey, address)) + { + //vector hashBytes(out.scriptPubKey.begin()+1, out.scriptPubKey.begin()+34); + //xxx delta.push_back(Pair("address", CBitcoinAddress(CKeyID(uint160(hashBytes))).ToString())); + delta.push_back(Pair("address", CBitcoinAddress(address).ToString())); + } + } + else { continue; } @@ -438,7 +452,7 @@ UniValue getblockdeltas(const UniValue& params, bool fHelp) if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); - if(!ReadBlockFromDisk(block, pblockindex)) + if(!ReadBlockFromDisk(block, pblockindex,1)) throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); return blockToDeltasJSON(block, pblockindex); @@ -693,7 +707,7 @@ UniValue getblock(const UniValue& params, bool fHelp) if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); - if(!ReadBlockFromDisk(block, pblockindex)) + if(!ReadBlockFromDisk(block, pblockindex,1)) throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); if (!fVerbose) @@ -746,26 +760,45 @@ UniValue gettxoutsetinfo(const UniValue& params, bool fHelp) } #include "komodo_defs.h" +#include "komodo_structs.h" #define IGUANA_MAXSCRIPTSIZE 10001 #define KOMODO_KVDURATION 1440 #define KOMODO_KVBINARY 2 extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume); int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel); int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len); -//uint32_t komodo_interest_args(int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n); int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width); int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); -int32_t komodo_MoM(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip); UniValue kvsearch(const UniValue& params, bool fHelp) { UniValue ret(UniValue::VOBJ); uint32_t flags; uint8_t value[IGUANA_MAXSCRIPTSIZE],key[IGUANA_MAXSCRIPTSIZE]; int32_t duration,j,height,valuesize,keylen; uint256 refpubkey; static uint256 zeroes; if (fHelp || params.size() != 1 ) - throw runtime_error("kvsearch key"); + throw runtime_error( + "kvsearch key\n" + "\nSearch for a key stored via the kvupdate command. This feature is only available for asset chains.\n" + "\nArguments:\n" + "1. key (string, required) search the chain for this key\n" + "\nResult:\n" + "{\n" + " \"coin\": \"xxxxx\", (string) chain the key is stored on\n" + " \"currentheight\": xxxxx, (numeric) current height of the chain\n" + " \"key\": \"xxxxx\", (string) key\n" + " \"keylen\": xxxxx, (string) length of the key \n" + " \"owner\": \"xxxxx\" (string) hex string representing the owner of the key \n" + " \"height\": xxxxx, (numeric) height the key was stored at\n" + " \"expiration\": xxxxx, (numeric) height the key will expire\n" + " \"flags\": x (numeric) 1 if the key was created with a password; 0 otherwise.\n" + " \"value\": \"xxxxx\", (string) stored value\n" + " \"valuesize\": xxxxx (string) amount of characters stored\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("kvsearch", "examplekey") + + HelpExampleRpc("kvsearch", "examplekey") + ); LOCK(cs_main); if ( (keylen= (int32_t)strlen(params[0].get_str().c_str())) > 0 ) { @@ -796,134 +829,6 @@ UniValue kvsearch(const UniValue& params, bool fHelp) return ret; } -UniValue height_MoM(const UniValue& params, bool fHelp) -{ - int32_t height,depth,notarized_height,MoMoMdepth,MoMoMoffset,kmdstarti,kmdendi; uint256 MoM,MoMoM,kmdtxid; uint32_t timestamp = 0; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR); - if ( fHelp || params.size() != 1 ) - throw runtime_error("height_MoM height\n"); - LOCK(cs_main); - height = atoi(params[0].get_str().c_str()); - if ( height <= 0 ) - { - if ( chainActive.Tip() == 0 ) - { - ret.push_back(Pair("error",(char *)"no active chain yet")); - return(ret); - } - height = chainActive.Tip()->nHeight; - } - //fprintf(stderr,"height_MoM height.%d\n",height); - depth = komodo_MoM(¬arized_height,&MoM,&kmdtxid,height,&MoMoM,&MoMoMoffset,&MoMoMdepth,&kmdstarti,&kmdendi); - ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL))); - ret.push_back(Pair("height",height)); - ret.push_back(Pair("timestamp",(uint64_t)timestamp)); - if ( depth > 0 ) - { - ret.push_back(Pair("depth",depth)); - ret.push_back(Pair("notarized_height",notarized_height)); - ret.push_back(Pair("MoM",MoM.GetHex())); - ret.push_back(Pair("kmdtxid",kmdtxid.GetHex())); - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - { - ret.push_back(Pair("MoMoM",MoMoM.GetHex())); - ret.push_back(Pair("MoMoMoffset",MoMoMoffset)); - ret.push_back(Pair("MoMoMdepth",MoMoMdepth)); - ret.push_back(Pair("kmdstarti",kmdstarti)); - ret.push_back(Pair("kmdendi",kmdendi)); - } - } else ret.push_back(Pair("error",(char *)"no MoM for height")); - - return ret; -} - -UniValue txMoMproof(const UniValue& params, bool fHelp) -{ - uint256 hash, notarisationHash, MoM,MoMoM; int32_t notarisedHeight, depth; CBlockIndex* blockIndex; - std::vector branch; - int nIndex,MoMoMdepth,MoMoMoffset,kmdstarti,kmdendi; - - // parse params and get notarisation data for tx - { - if ( fHelp || params.size() != 1) - throw runtime_error("txMoMproof needs a txid"); - - hash = uint256S(params[0].get_str()); - - uint256 blockHash; - CTransaction tx; - if (!GetTransaction(hash, tx, blockHash, true)) - throw runtime_error("cannot find transaction"); - - blockIndex = mapBlockIndex[blockHash]; - - depth = komodo_MoM(¬arisedHeight, &MoM, ¬arisationHash, blockIndex->nHeight,&MoMoM,&MoMoMoffset,&MoMoMdepth,&kmdstarti,&kmdendi); - - if (!depth) - throw runtime_error("notarisation not found"); - - // index of block in MoM leaves - nIndex = notarisedHeight - blockIndex->nHeight; - } - - // build merkle chain from blocks to MoM - { - // since the merkle branch code is tied up in a block class - // and we want to make a merkle branch for something that isnt transactions - CBlock fakeBlock; - for (int i=0; ihashMerkleRoot; - CTransaction fakeTx; - // first value in CTransaction memory is it's hash - memcpy((void*)&fakeTx, mRoot.begin(), 32); - fakeBlock.vtx.push_back(fakeTx); - } - branch = fakeBlock.GetMerkleBranch(nIndex); - - // Check branch - if (MoM != CBlock::CheckMerkleBranch(blockIndex->hashMerkleRoot, branch, nIndex)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Failed merkle block->MoM"); - } - - // Now get the tx merkle branch - { - CBlock block; - - if (fHavePruned && !(blockIndex->nStatus & BLOCK_HAVE_DATA) && blockIndex->nTx > 0) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); - - if(!ReadBlockFromDisk(block, blockIndex)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); - - // Locate the transaction in the block - int nTxIndex; - for (nTxIndex = 0; nTxIndex < (int)block.vtx.size(); nTxIndex++) - if (block.vtx[nTxIndex].GetHash() == hash) - break; - - if (nTxIndex == (int)block.vtx.size()) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Error locating tx in block"); - - std::vector txBranch = block.GetMerkleBranch(nTxIndex); - - // Check branch - if (block.hashMerkleRoot != CBlock::CheckMerkleBranch(hash, txBranch, nTxIndex)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Failed merkle tx->block"); - - // concatenate branches - nIndex = (nIndex << txBranch.size()) + nTxIndex; - branch.insert(branch.begin(), txBranch.begin(), txBranch.end()); - } - - // Check the proof - if (MoM != CBlock::CheckMerkleBranch(hash, branch, nIndex)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Failed validating MoM"); - - // Encode and return - CDataStream ssProof(SER_NETWORK, PROTOCOL_VERSION); - ssProof << MoMProof(nIndex, branch, notarisationHash); - return HexStr(ssProof.begin(), ssProof.end()); -} - UniValue minerids(const UniValue& params, bool fHelp) { uint32_t timestamp = 0; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR); uint8_t minerids[2000],pubkeys[65][33]; int32_t i,j,n,numnotaries,tally[129]; @@ -939,7 +844,7 @@ UniValue minerids(const UniValue& params, bool fHelp) if ( pblockindex != 0 ) timestamp = pblockindex->GetBlockTime(); } - if ( 0 && (n= komodo_minerids(minerids,height,(int32_t)(sizeof(minerids)/sizeof(*minerids)))) > 0 ) + if ( (n= komodo_minerids(minerids,height,(int32_t)(sizeof(minerids)/sizeof(*minerids)))) > 0 ) { memset(tally,0,sizeof(tally)); numnotaries = komodo_notaries(pubkeys,height,timestamp); @@ -977,6 +882,7 @@ UniValue minerids(const UniValue& params, bool fHelp) a.push_back(item); } ret.push_back(Pair("mined", a)); + ret.push_back(Pair("numnotaries", numnotaries)); } else ret.push_back(Pair("error", (char *)"couldnt extract minerids")); return ret; } @@ -1013,14 +919,14 @@ UniValue notaries(const UniValue& params, bool fHelp) for (j=0; j<33; j++) sprintf(&hexstr[j*2],"%02x",pubkeys[i][j]); item.push_back(Pair("pubkey", hex)); - + bitcoin_address(btcaddr,0,pubkeys[i],33); m = (int32_t)strlen(btcaddr); btcaddress.resize(m); ptr = (char *)btcaddress.data(); memcpy(ptr,btcaddr,m); item.push_back(Pair("BTCaddress", btcaddress)); - + bitcoin_address(kmdaddr,60,pubkeys[i],33); m = (int32_t)strlen(kmdaddr); kmdaddress.resize(m); @@ -1168,8 +1074,8 @@ UniValue gettxout(const UniValue& params, bool fHelp) " \"hex\" : \"hex\", (string) \n" " \"reqSigs\" : n, (numeric) Number of required signatures\n" " \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n" - " \"addresses\" : [ (array of string) array of Zcash addresses\n" - " \"zcashaddress\" (string) Zcash address\n" + " \"addresses\" : [ (array of string) array of Komodo addresses\n" + " \"komodoaddress\" (string) Komodo address\n" " ,...\n" " ]\n" " },\n" diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 9eb731b1c..9d1d0b336 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -134,15 +134,20 @@ static const CRPCConvertParam vRPCConvertParams[] = { "paxprices", 3 }, { "paxpending", 0 }, { "notaries", 2 }, - { "height_MoM", 1 }, - { "txMoMproof", 1 }, { "minerids", 1 }, { "kvsearch", 1 }, { "kvupdate", 4 }, { "z_importkey", 2 }, { "z_importviewingkey", 2 }, { "z_getpaymentdisclosure", 1}, - { "z_getpaymentdisclosure", 2} + { "z_getpaymentdisclosure", 2}, + + // crosschain + { "assetchainproof", 1}, + { "crosschainproof", 1}, + { "getproofroot", 2}, + { "height_MoM", 1}, + { "calc_MoM", 2}, }; class CRPCConvertTable diff --git a/src/rpccrosschain.cpp b/src/rpccrosschain.cpp new file mode 100644 index 000000000..35542613a --- /dev/null +++ b/src/rpccrosschain.cpp @@ -0,0 +1,253 @@ +#include "amount.h" +#include "chain.h" +#include "chainparams.h" +#include "checkpoints.h" +#include "crosschain.h" +#include "importcoin.h" +#include "base58.h" +#include "consensus/validation.h" +#include "cc/eval.h" +#include "cc/utils.h" +#include "main.h" +#include "primitives/transaction.h" +#include "rpcserver.h" +#include "sync.h" +#include "util.h" +#include "script/script.h" +#include "script/script_error.h" +#include "script/sign.h" +#include "script/standard.h" + +#include +#include +#include + + +using namespace std; + +int32_t komodo_MoM(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip); +int32_t komodo_MoMoMdata(char *hexstr,int32_t hexsize,struct komodo_ccdataMoMoM *mdata,char *symbol,int32_t kmdheight,int32_t notarized_height); +struct komodo_ccdata_entry *komodo_allMoMs(int32_t *nump,uint256 *MoMoMp,int32_t kmdstarti,int32_t kmdendi); +uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth); + + +UniValue assetchainproof(const UniValue& params, bool fHelp) +{ + uint256 hash; + + // parse params and get notarisation data for tx + if ( fHelp || params.size() != 1) + throw runtime_error("assetchainproof needs a txid"); + + hash = uint256S(params[0].get_str()); + + auto proof = GetAssetchainProof(hash); + auto proofData = E_MARSHAL(ss << proof); + return HexStr(proofData); +} + + +UniValue crosschainproof(const UniValue& params, bool fHelp) +{ + +} + + +UniValue height_MoM(const UniValue& params, bool fHelp) +{ + int32_t height,depth,notarized_height,MoMoMdepth,MoMoMoffset,kmdstarti,kmdendi; uint256 MoM,MoMoM,kmdtxid; uint32_t timestamp = 0; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR); + if ( fHelp || params.size() != 1 ) + throw runtime_error("height_MoM height\n"); + LOCK(cs_main); + height = atoi(params[0].get_str().c_str()); + if ( height <= 0 ) + { + if ( chainActive.Tip() == 0 ) + { + ret.push_back(Pair("error",(char *)"no active chain yet")); + return(ret); + } + height = chainActive.Tip()->nHeight; + } + //fprintf(stderr,"height_MoM height.%d\n",height); + depth = komodo_MoM(¬arized_height,&MoM,&kmdtxid,height,&MoMoM,&MoMoMoffset,&MoMoMdepth,&kmdstarti,&kmdendi); + ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL))); + ret.push_back(Pair("height",height)); + ret.push_back(Pair("timestamp",(uint64_t)timestamp)); + if ( depth > 0 ) + { + ret.push_back(Pair("depth",depth)); + ret.push_back(Pair("notarized_height",notarized_height)); + ret.push_back(Pair("MoM",MoM.GetHex())); + ret.push_back(Pair("kmdtxid",kmdtxid.GetHex())); + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + { + ret.push_back(Pair("MoMoM",MoMoM.GetHex())); + ret.push_back(Pair("MoMoMoffset",MoMoMoffset)); + ret.push_back(Pair("MoMoMdepth",MoMoMdepth)); + ret.push_back(Pair("kmdstarti",kmdstarti)); + ret.push_back(Pair("kmdendi",kmdendi)); + } + } else ret.push_back(Pair("error",(char *)"no MoM for height")); + + return ret; +} + +UniValue MoMoMdata(const UniValue& params, bool fHelp) +{ + if ( fHelp || params.size() != 3 ) + throw runtime_error("MoMoMdata symbol kmdheight ccid\n"); + UniValue ret(UniValue::VOBJ); + char* symbol = (char *)params[0].get_str().c_str(); + int kmdheight = atoi(params[1].get_str().c_str()); + uint32_t ccid = atoi(params[2].get_str().c_str()); + ret.push_back(Pair("coin",symbol)); + ret.push_back(Pair("kmdheight",kmdheight)); + ret.push_back(Pair("ccid", (int) ccid)); + + uint256 destNotarisationTxid; + std::vector moms; + uint256 MoMoM = CalculateProofRoot(symbol, ccid, kmdheight, moms, destNotarisationTxid); + + UniValue valMoms(UniValue::VARR); + for (int i=0; i= height ) + throw runtime_error("calc_MoM illegal height or MoMdepth\n"); + //fprintf(stderr,"height_MoM height.%d\n",height); + MoM = komodo_calcMoM(height,MoMdepth); + ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL))); + ret.push_back(Pair("height",height)); + ret.push_back(Pair("MoMdepth",MoMdepth)); + ret.push_back(Pair("MoM",MoM.GetHex())); + return ret; +} + + +UniValue migrate_converttoexport(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 3) + throw runtime_error( + "migrate_converttoexport rawTx dest_symbol export_amount\n" + "\nConvert a raw transaction to a cross-chain export.\n" + "If neccesary, the transaction should be funded using fundrawtransaction.\n" + "Finally, the transaction should be signed using signrawtransaction\n" + "The finished export transaction, plus the payouts, should be passed to " + "the \"migrate_createimporttransaction\" method on a KMD node to get the corresponding " + "import transaction.\n" + ); + + if (ASSETCHAINS_CC < 2) + throw runtime_error("-ac_cc < 2"); + + if (ASSETCHAINS_SYMBOL[0] == 0) + throw runtime_error("Must be called on assetchain"); + + vector txData(ParseHexV(params[0], "argument 1")); + CMutableTransaction tx; + if (!E_UNMARSHAL(txData, ss >> tx)) + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); + + string targetSymbol = params[1].get_str(); + if (targetSymbol.size() == 0 || targetSymbol.size() > 32) + throw runtime_error("targetSymbol length must be >0 and <=32"); + + CAmount burnAmount = AmountFromValue(params[2]); + if (burnAmount <= 0) + throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for export"); + { + CAmount needed = 0; + for (int i=0; i txData(ParseHexV(params[0], "argument 1")); + + CTransaction burnTx; + if (!E_UNMARSHAL(txData, ss >> burnTx)) + throw runtime_error("Couldn't parse burnTx"); + + + vector payouts; + if (!E_UNMARSHAL(ParseHexV(params[1], "argument 2"), ss >> payouts)) + throw runtime_error("Couldn't parse payouts"); + + uint256 txid = burnTx.GetHash(); + TxProof proof = GetAssetchainProof(burnTx.GetHash()); + + CTransaction importTx = MakeImportCoinTransaction(proof, burnTx, payouts); + return HexStr(E_MARSHAL(ss << importTx)); +} + + +UniValue migrate_completeimporttransaction(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error("migrate_completeimporttransaction importTx\n\n" + "Takes a cross chain import tx with proof generated on assetchain " + "and extends proof to target chain proof root"); + + if (ASSETCHAINS_SYMBOL[0] != 0) + throw runtime_error("Must be called on KMD"); + + CTransaction importTx; + if (!E_UNMARSHAL(ParseHexV(params[0], "argument 1"), ss >> importTx)) + throw runtime_error("Couldn't parse importTx"); + + CompleteImportTransaction(importTx); + + return HexStr(E_MARSHAL(ss << importTx)); +} diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index da1d5207f..7f66f23f6 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -32,6 +32,7 @@ using namespace std; + /** * Return average network hashes per second based on the last 'lookup' blocks, * or over the difficulty averaging window if 'lookup' is nonpositive. @@ -182,7 +183,7 @@ UniValue generate(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set"); } #else - throw JSONRPCError(RPC_METHOD_NOT_FOUND, "zcashd compiled without wallet and -mineraddress not set"); + throw JSONRPCError(RPC_METHOD_NOT_FOUND, "komodod compiled without wallet and -mineraddress not set"); #endif } if (!Params().MineBlocksOnDemand()) @@ -214,7 +215,7 @@ UniValue generate(const UniValue& params, bool fHelp) lastTime = GetTime(); #ifdef ENABLE_WALLET - std::unique_ptr pblocktemplate(CreateNewBlockWithKey(reservekey)); + std::unique_ptr pblocktemplate(CreateNewBlockWithKey(reservekey,nHeight,KOMODO_MAXGPUCOUNT)); #else std::unique_ptr pblocktemplate(CreateNewBlockWithKey()); #endif @@ -257,7 +258,7 @@ UniValue generate(const UniValue& params, bool fHelp) LOCK(cs_main); pblock->nSolution = soln; solutionTargetChecks.increment(); - return CheckProofOfWork(chainActive.Height(),NOTARY_PUBKEY33,pblock->GetHash(), pblock->nBits, Params().GetConsensus()); + return CheckProofOfWork(chainActive.Height(),NOTARY_PUBKEY33,pblock->GetHash(), pblock->nBits, Params().GetConsensus(),pblock->nTime); }; bool found = EhBasicSolveUncancellable(n, k, curr_state, validBlock); ehSolverRuns.increment(); @@ -267,7 +268,7 @@ UniValue generate(const UniValue& params, bool fHelp) } endloop: CValidationState state; - if (!ProcessNewBlock(chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL)) + if (!ProcessNewBlock(1,chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL)) throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); ++nHeight; blockHashes.push_back(pblock->GetHash().GetHex()); @@ -304,7 +305,7 @@ UniValue setgenerate(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set"); } #else - throw JSONRPCError(RPC_METHOD_NOT_FOUND, "zcashd compiled without wallet and -mineraddress not set"); + throw JSONRPCError(RPC_METHOD_NOT_FOUND, "komodod compiled without wallet and -mineraddress not set"); #endif } if (Params().MineBlocksOnDemand()) @@ -506,7 +507,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set"); } #else - throw JSONRPCError(RPC_METHOD_NOT_FOUND, "zcashd compiled without wallet and -mineraddress not set"); + throw JSONRPCError(RPC_METHOD_NOT_FOUND, "komodod compiled without wallet and -mineraddress not set"); #endif } @@ -563,7 +564,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); if (vNodes.empty()) - throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Zcash is not connected!"); + throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Komodo is not connected!"); //if (IsInitialBlockDownload()) // throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Zcash is downloading blocks..."); @@ -639,7 +640,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) } #ifdef ENABLE_WALLET CReserveKey reservekey(pwalletMain); - pblocktemplate = CreateNewBlockWithKey(reservekey); + pblocktemplate = CreateNewBlockWithKey(reservekey,chainActive.Tip()->nHeight+1,KOMODO_MAXGPUCOUNT); #else pblocktemplate = CreateNewBlockWithKey(); #endif @@ -692,7 +693,8 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) // Correct this if GetBlockTemplate changes the order // entry.push_back(Pair("foundersreward", (int64_t)tx.vout[1].nValue)); //} - entry.push_back(Pair("coinbasevalue", 3*COIN)); + CAmount nReward = GetBlockSubsidy(chainActive.Tip()->nHeight+1, Params().GetConsensus()); + entry.push_back(Pair("coinbasevalue", nReward)); entry.push_back(Pair("required", true)); txCoinbase = entry; } else @@ -807,7 +809,7 @@ UniValue submitblock(const UniValue& params, bool fHelp) CValidationState state; submitblock_StateCatcher sc(block.GetHash()); RegisterValidationInterface(&sc); - bool fAccepted = ProcessNewBlock(chainActive.Tip()->nHeight+1,state, NULL, &block, true, NULL); + bool fAccepted = ProcessNewBlock(1,chainActive.Tip()->nHeight+1,state, NULL, &block, true, NULL); UnregisterValidationInterface(&sc); if (fBlockPresent) { diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 20ea27f0a..065739a9a 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -46,17 +46,23 @@ int32_t Jumblr_depositaddradd(char *depositaddr); int32_t Jumblr_secretaddradd(char *secretaddr); uint64_t komodo_interestsum(); int32_t komodo_longestchain(); -int32_t komodo_notarized_height(uint256 *hashp,uint256 *txidp); +int32_t komodo_notarized_height(int32_t *prevhtp,uint256 *hashp,uint256 *txidp); uint32_t komodo_chainactive_timestamp(); int32_t komodo_whoami(char *pubkeystr,int32_t height,uint32_t timestamp); -extern int32_t KOMODO_LASTMINED,JUMBLR_PAUSE; -extern char ASSETCHAINS_SYMBOL[]; +extern uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; +extern int32_t KOMODO_LASTMINED,JUMBLR_PAUSE,KOMODO_LONGESTCHAIN; +extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; +uint32_t komodo_segid32(char *coinaddr); int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp); #define KOMODO_VERSION "0.1.1" +extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; +extern uint32_t ASSETCHAINS_CC; +extern uint32_t ASSETCHAINS_MAGIC; +extern uint64_t ASSETCHAINS_ENDSUBSIDY,ASSETCHAINS_REWARD,ASSETCHAINS_HALVING,ASSETCHAINS_DECAY,ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED,ASSETCHAINS_SUPPLY; UniValue getinfo(const UniValue& params, bool fHelp) { - uint256 notarized_hash,notarized_desttxid; int32_t notarized_height,longestchain,kmdnotarized_height,txid_height; + uint256 notarized_hash,notarized_desttxid; int32_t prevMoMheight,notarized_height,longestchain,kmdnotarized_height,txid_height; if (fHelp || params.size() != 0) throw runtime_error( "getinfo\n" @@ -66,7 +72,7 @@ UniValue getinfo(const UniValue& params, bool fHelp) " \"version\": xxxxx, (numeric) the server version\n" " \"protocolversion\": xxxxx, (numeric) the protocol version\n" " \"walletversion\": xxxxx, (numeric) the wallet version\n" - " \"balance\": xxxxxxx, (numeric) the total Zcash balance of the wallet\n" + " \"balance\": xxxxxxx, (numeric) the total Komodo balance of the wallet\n" " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n" " \"timeoffset\": xxxxx, (numeric) the time offset\n" " \"connections\": xxxxx, (numeric) the number of connections\n" @@ -84,22 +90,23 @@ UniValue getinfo(const UniValue& params, bool fHelp) + HelpExampleCli("getinfo", "") + HelpExampleRpc("getinfo", "") ); - -#ifdef ENABLE_WALLET - LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL); -#else +//#ifdef ENABLE_WALLET +// LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL); +//#else LOCK(cs_main); -#endif +//#endif proxyType proxy; GetProxy(NET_IPV4, proxy); - notarized_height = komodo_notarized_height(¬arized_hash,¬arized_desttxid); + notarized_height = komodo_notarized_height(&prevMoMheight,¬arized_hash,¬arized_desttxid); + //fprintf(stderr,"after notarized_height %u\n",(uint32_t)time(NULL)); UniValue obj(UniValue::VOBJ); obj.push_back(Pair("version", CLIENT_VERSION)); obj.push_back(Pair("protocolversion", PROTOCOL_VERSION)); obj.push_back(Pair("KMDversion", KOMODO_VERSION)); obj.push_back(Pair("notarized", notarized_height)); + obj.push_back(Pair("prevMoMheight", prevMoMheight)); obj.push_back(Pair("notarizedhash", notarized_hash.ToString())); obj.push_back(Pair("notarizedtxid", notarized_desttxid.ToString())); txid_height = notarizedtxid_height(ASSETCHAINS_SYMBOL[0] != 0 ? (char *)"KMD" : (char *)"BTC",(char *)notarized_desttxid.ToString().c_str(),&kmdnotarized_height); @@ -109,17 +116,20 @@ UniValue getinfo(const UniValue& params, bool fHelp) if ( ASSETCHAINS_SYMBOL[0] != 0 ) obj.push_back(Pair("KMDnotarized_height", kmdnotarized_height)); obj.push_back(Pair("notarized_confirms", txid_height < kmdnotarized_height ? (kmdnotarized_height - txid_height + 1) : 0)); + //fprintf(stderr,"after notarized_confirms %u\n",(uint32_t)time(NULL)); #ifdef ENABLE_WALLET if (pwalletMain) { obj.push_back(Pair("walletversion", pwalletMain->GetVersion())); - obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance()))); + obj.push_back(Pair("balance", ValueFromAmount(KOMODO_WALLETBALANCE))); //pwalletMain->GetBalance() if ( ASSETCHAINS_SYMBOL[0] == 0 ) - obj.push_back(Pair("interest", ValueFromAmount(komodo_interestsum()))); + obj.push_back(Pair("interest", ValueFromAmount(KOMODO_INTERESTSUM))); //komodo_interestsum() } #endif + //fprintf(stderr,"after wallet %u\n",(uint32_t)time(NULL)); obj.push_back(Pair("blocks", (int)chainActive.Height())); - if ( (longestchain= komodo_longestchain()) != 0 && chainActive.Height() > longestchain ) + if ( (longestchain= KOMODO_LONGESTCHAIN) != 0 && chainActive.Height() > longestchain ) longestchain = chainActive.Height(); + //fprintf(stderr,"after longestchain %u\n",(uint32_t)time(NULL)); obj.push_back(Pair("longestchain", longestchain)); obj.push_back(Pair("timeoffset", GetTimeOffset())); if ( chainActive.Tip() != 0 ) @@ -149,6 +159,30 @@ UniValue getinfo(const UniValue& params, bool fHelp) obj.push_back(Pair("lastmined", KOMODO_LASTMINED)); } } + if ( ASSETCHAINS_CC != 0 ) + obj.push_back(Pair("CCid", (int)ASSETCHAINS_CC)); + obj.push_back(Pair("name", ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL)); + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + { + //obj.push_back(Pair("name", ASSETCHAINS_SYMBOL)); + obj.push_back(Pair("p2pport", ASSETCHAINS_P2PPORT)); + obj.push_back(Pair("rpcport", ASSETCHAINS_RPCPORT)); + obj.push_back(Pair("magic", (int)ASSETCHAINS_MAGIC)); + if ( ASSETCHAINS_SUPPLY != 0 ) + obj.push_back(Pair("premine", ASSETCHAINS_SUPPLY)); + if ( ASSETCHAINS_REWARD != 0 ) + obj.push_back(Pair("reward", ASSETCHAINS_REWARD)); + if ( ASSETCHAINS_HALVING != 0 ) + obj.push_back(Pair("halving", ASSETCHAINS_HALVING)); + if ( ASSETCHAINS_DECAY != 0 ) + obj.push_back(Pair("decay", ASSETCHAINS_DECAY)); + if ( ASSETCHAINS_ENDSUBSIDY != 0 ) + obj.push_back(Pair("endsubsidy", ASSETCHAINS_ENDSUBSIDY)); + if ( ASSETCHAINS_COMMISSION != 0 ) + obj.push_back(Pair("commission", ASSETCHAINS_COMMISSION)); + if ( ASSETCHAINS_STAKED != 0 ) + obj.push_back(Pair("staked", ASSETCHAINS_STAKED)); + } return obj; } @@ -203,7 +237,10 @@ UniValue jumblr_deposit(const UniValue& params, bool fHelp) { string addr = params[0].get_str(); if ( (retval= Jumblr_depositaddradd((char *)addr.c_str())) >= 0 ) + { result.push_back(Pair("result", retval)); + JUMBLR_PAUSE = 0; + } else result.push_back(Pair("error", retval)); } else result.push_back(Pair("error", "invalid address")); return(result); @@ -222,6 +259,7 @@ UniValue jumblr_secret(const UniValue& params, bool fHelp) retval = Jumblr_secretaddradd((char *)addr.c_str()); result.push_back(Pair("result", "success")); result.push_back(Pair("num", retval)); + JUMBLR_PAUSE = 0; } else result.push_back(Pair("error", "invalid address")); return(result); } @@ -250,14 +288,14 @@ UniValue validateaddress(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error( - "validateaddress \"zcashaddress\"\n" - "\nReturn information about the given Zcash address.\n" + "validateaddress \"komodoaddress\"\n" + "\nReturn information about the given Komodo address.\n" "\nArguments:\n" - "1. \"zcashaddress\" (string, required) The Zcash address to validate\n" + "1. \"komodoaddress\" (string, required) The Komodo address to validate\n" "\nResult:\n" "{\n" " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n" - " \"address\" : \"zcashaddress\", (string) The Zcash address validated\n" + " \"address\" : \"komodoaddress\", (string) The Komodo address validated\n" " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n" " \"ismine\" : true|false, (boolean) If the address is yours or not\n" " \"isscript\" : true|false, (boolean) If the key is a script\n" @@ -266,8 +304,8 @@ UniValue validateaddress(const UniValue& params, bool fHelp) " \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n" "}\n" "\nExamples:\n" - + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") - + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") + + HelpExampleCli("validateaddress", "\"RTZMZHDFSTFQst8XmX2dR4DaH87cEUs3gC\"") + + HelpExampleRpc("validateaddress", "\"RTZMZHDFSTFQst8XmX2dR4DaH87cEUs3gC\"") ); #ifdef ENABLE_WALLET @@ -289,7 +327,7 @@ UniValue validateaddress(const UniValue& params, bool fHelp) CScript scriptPubKey = GetScriptForDestination(dest); ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()))); - + ret.push_back(Pair("segid", (int32_t)komodo_segid32((char *)params[0].get_str().c_str()) & 0x3f)); #ifdef ENABLE_WALLET isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO; ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false)); @@ -441,9 +479,9 @@ UniValue createmultisig(const UniValue& params, bool fHelp) "\nArguments:\n" "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n" - "2. \"keys\" (string, required) A json array of keys which are Zcash addresses or hex-encoded public keys\n" + "2. \"keys\" (string, required) A json array of keys which are Komodo addresses or hex-encoded public keys\n" " [\n" - " \"key\" (string) Zcash address or hex-encoded public key\n" + " \"key\" (string) Komodo address or hex-encoded public key\n" " ,...\n" " ]\n" @@ -455,9 +493,9 @@ UniValue createmultisig(const UniValue& params, bool fHelp) "\nExamples:\n" "\nCreate a multisig address from 2 addresses\n" - + HelpExampleCli("createmultisig", "2 \"[\\\"t16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"t171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") + + + HelpExampleCli("createmultisig", "2 \"[\\\"RTZMZHDFSTFQst8XmX2dR4DaH87cEUs3gC\\\",\\\"RNKiEBduBru6Siv1cZRVhp4fkZNyPska6z\\\"]\"") + "\nAs a json rpc call\n" - + HelpExampleRpc("createmultisig", "2, \"[\\\"t16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"t171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") + + HelpExampleRpc("createmultisig", "2, \"[\\\"RTZMZHDFSTFQst8XmX2dR4DaH87cEUs3gC\\\",\\\"RNKiEBduBru6Siv1cZRVhp4fkZNyPska6z\\\"]\"") ; throw runtime_error(msg); } @@ -478,10 +516,10 @@ UniValue verifymessage(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 3) throw runtime_error( - "verifymessage \"zcashaddress\" \"signature\" \"message\"\n" + "verifymessage \"komodoaddress\" \"signature\" \"message\"\n" "\nVerify a signed message\n" "\nArguments:\n" - "1. \"zcashaddress\" (string, required) The Zcash address to use for the signature.\n" + "1. \"komodoaddress\" (string, required) The Komodo address to use for the signature.\n" "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n" "3. \"message\" (string, required) The message that was signed.\n" "\nResult:\n" @@ -490,11 +528,11 @@ UniValue verifymessage(const UniValue& params, bool fHelp) "\nUnlock the wallet for 30 seconds\n" + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") + "\nCreate the signature\n" - + HelpExampleCli("signmessage", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\" \"my message\"") + + + HelpExampleCli("signmessage", "\"RNKiEBduBru6Siv1cZRVhp4fkZNyPska6z\" \"my message\"") + "\nVerify the signature\n" - + HelpExampleCli("verifymessage", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\" \"signature\" \"my message\"") + + + HelpExampleCli("verifymessage", "\"RNKiEBduBru6Siv1cZRVhp4fkZNyPska6z\" \"signature\" \"my message\"") + "\nAs json rpc\n" - + HelpExampleRpc("verifymessage", "\"t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1\", \"signature\", \"my message\"") + + HelpExampleRpc("verifymessage", "\"RNKiEBduBru6Siv1cZRVhp4fkZNyPska6z\", \"signature\", \"my message\"") ); LOCK(cs_main); @@ -565,7 +603,8 @@ bool getAddressFromIndex(const int &type, const uint160 &hash, std::string &addr address = CBitcoinAddress(CScriptID(hash)).ToString(); } else if (type == 1) { address = CBitcoinAddress(CKeyID(hash)).ToString(); - } else { + } + else { return false; } return true; @@ -596,12 +635,12 @@ bool getAddressesFromParams(const UniValue& params, std::vector > addresses; @@ -715,8 +754,8 @@ UniValue getaddressutxos(const UniValue& params, bool fHelp) " }\n" "]\n" "\nExamples:\n" - + HelpExampleCli("getaddressutxos", "'{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}'") - + HelpExampleRpc("getaddressutxos", "{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}") + + HelpExampleCli("getaddressutxos", "'{\"addresses\": [\"RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87\"]}'") + + HelpExampleRpc("getaddressutxos", "{\"addresses\": [\"RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87\"]}") ); bool includeChainInfo = false; @@ -802,8 +841,8 @@ UniValue getaddressdeltas(const UniValue& params, bool fHelp) " }\n" "]\n" "\nExamples:\n" - + HelpExampleCli("getaddressdeltas", "'{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}'") - + HelpExampleRpc("getaddressdeltas", "{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}") + + HelpExampleCli("getaddressdeltas", "'{\"addresses\": [\"RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87\"]}'") + + HelpExampleRpc("getaddressdeltas", "{\"addresses\": [\"RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87\"]}") ); @@ -919,8 +958,8 @@ UniValue getaddressbalance(const UniValue& params, bool fHelp) " \"received\" (string) The total number of satoshis received (including change)\n" "}\n" "\nExamples:\n" - + HelpExampleCli("getaddressbalance", "'{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}'") - + HelpExampleRpc("getaddressbalance", "{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}") + + HelpExampleCli("getaddressbalance", "'{\"addresses\": [\"RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87\"]}'") + + HelpExampleRpc("getaddressbalance", "{\"addresses\": [\"RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87\"]}") ); std::vector > addresses; @@ -955,6 +994,23 @@ UniValue getaddressbalance(const UniValue& params, bool fHelp) } +int32_t komodo_snapshot(); + +UniValue getsnapshot(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); int64_t total; + if ( fHelp || params.size() > 0 ) + { + throw runtime_error( + "getsnapshot\n" + ); + } + if ( (total= komodo_snapshot()) >= 0 ) + result.push_back(Pair("total", (double)total/COIN)); + else result.push_back(Pair("error", "no addressindex")); + return(result); +} + UniValue getaddresstxids(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) @@ -977,8 +1033,8 @@ UniValue getaddresstxids(const UniValue& params, bool fHelp) " ,...\n" "]\n" "\nExamples:\n" - + HelpExampleCli("getaddresstxids", "'{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}'") - + HelpExampleRpc("getaddresstxids", "{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}") + + HelpExampleCli("getaddresstxids", "'{\"addresses\": [\"RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87\"]}'") + + HelpExampleRpc("getaddresstxids", "{\"addresses\": [\"RY5LccmGiX9bUHYGtSWQouNy1yFhc5rM87\"]}") ); std::vector > addresses; @@ -1084,4 +1140,4 @@ UniValue getspentinfo(const UniValue& params, bool fHelp) obj.push_back(Pair("height", value.blockHeight)); return obj; -} \ No newline at end of file +} diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index a7a4bf051..ec4c7be2a 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -169,11 +169,14 @@ int32_t KOMODO_LONGESTCHAIN; int32_t komodo_longestchain() { int32_t ht,n=0,num=0,maxheight=0,height = 0; - LOCK(cs_main); vector vstats; - CopyNodeStats(vstats); + { + LOCK(cs_main); + CopyNodeStats(vstats); + } BOOST_FOREACH(const CNodeStats& stats, vstats) { + //fprintf(stderr,"komodo_longestchain iter.%d\n",n); CNodeStateStats statestats; bool fStateStats = GetNodeStateStats(stats.nodeid,statestats); ht = 0; @@ -291,7 +294,7 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp) " \"connected\" : true|false, (boolean) If connected\n" " \"addresses\" : [\n" " {\n" - " \"address\" : \"192.168.0.201:8233\", (string) The Zcash server host and port\n" + " \"address\" : \"192.168.0.201:8233\", (string) The Komodo server host and port\n" " \"connected\" : \"outbound\" (string) connection, inbound or outbound\n" " }\n" " ,...\n" diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 3f93e07d6..a9aff1b7f 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -57,7 +57,6 @@ void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fInclud out.push_back(Pair("addresses", a)); } - UniValue TxJoinSplitToJSON(const CTransaction& tx) { UniValue vjoinsplit(UniValue::VARR); for (unsigned int i = 0; i < tx.vjoinsplit.size(); i++) { @@ -115,7 +114,7 @@ UniValue TxJoinSplitToJSON(const CTransaction& tx) { return vjoinsplit; } -uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); +uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue& entry, int nHeight = 0, int nConfirmations = 0, int nBlockTime = 0) { @@ -135,9 +134,20 @@ void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue& UniValue in(UniValue::VOBJ); if (tx.IsCoinBase()) in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); + else if (tx.IsCoinImport()) { + in.push_back(Pair("is_import", "1")); + } else { in.push_back(Pair("txid", txin.prevout.hash.GetHex())); in.push_back(Pair("vout", (int64_t)txin.prevout.n)); + { + uint256 hash; CTransaction tx; CTxDestination address; + if (GetTransaction(txin.prevout.hash,tx,hash,false)) + { + if (ExtractDestination(tx.vout[txin.prevout.n].scriptPubKey, address)) + in.push_back(Pair("address", CBitcoinAddress(address).ToString())); + } + } UniValue o(UniValue::VOBJ); o.push_back(Pair("asm", txin.scriptSig.ToString())); o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); @@ -151,7 +161,8 @@ void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue& in.push_back(Pair("valueSat", spentInfo.satoshis)); if (spentInfo.addressType == 1) { in.push_back(Pair("address", CBitcoinAddress(CKeyID(spentInfo.addressHash)).ToString())); - } else if (spentInfo.addressType == 2) { + } + else if (spentInfo.addressType == 2) { in.push_back(Pair("address", CBitcoinAddress(CScriptID(spentInfo.addressHash)).ToString())); } } @@ -168,12 +179,14 @@ void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue& const CTxOut& txout = tx.vout[i]; UniValue out(UniValue::VOBJ); out.push_back(Pair("value", ValueFromAmount(txout.nValue))); - if ( pindex != 0 && tx.nLockTime > 500000000 && (tipindex= chainActive.Tip()) != 0 ) + if ( pindex != 0 && tx.nLockTime >= 500000000 && (tipindex= chainActive.Tip()) != 0 ) { - interest = komodo_interest(pindex->nHeight,txout.nValue,tx.nLockTime,tipindex->nTime); + int64_t interest; int32_t txheight; uint32_t locktime; + interest = komodo_accrued_interest(&txheight,&locktime,tx.GetHash(),i,0,txout.nValue,(int32_t)tipindex->nHeight); out.push_back(Pair("interest", ValueFromAmount(interest))); } out.push_back(Pair("valueZat", txout.nValue)); + out.push_back(Pair("valueSat", txout.nValue)); // [+] Decker out.push_back(Pair("n", (int64_t)i)); UniValue o(UniValue::VOBJ); ScriptPubKeyToJSON(txout.scriptPubKey, o, true); @@ -317,7 +330,7 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp) " \"reqSigs\" : n, (numeric) The required sigs\n" " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n" " \"addresses\" : [ (json array of string)\n" - " \"zcashaddress\" (string) Zcash address\n" + " \"komodoaddress\" (string) Komodo address\n" " ,...\n" " ]\n" " }\n" @@ -443,7 +456,7 @@ int32_t gettxout_scriptPubKey(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid }*/ CTransaction tx; uint256 hashBlock; - if ( GetTransaction(txid,tx,hashBlock,true) == 0 ) + if ( GetTransaction(txid,tx,hashBlock,false) == 0 ) return(-1); else if ( n <= tx.vout.size() ) // vout.size() seems off by 1 { @@ -521,7 +534,7 @@ UniValue gettxoutproof(const UniValue& params, bool fHelp) } CBlock block; - if(!ReadBlockFromDisk(block, pblockindex)) + if(!ReadBlockFromDisk(block, pblockindex,1)) throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); unsigned int ntxFound = 0; @@ -592,7 +605,7 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) " ]\n" "2. \"addresses\" (string, required) a json object with addresses as keys and amounts as values\n" " {\n" - " \"address\": x.xxx (numeric, required) The key is the Zcash address, the value is the " + CURRENCY_UNIT + " amount\n" + " \"address\": x.xxx (numeric, required) The key is the Komodo address, the value is the " + CURRENCY_UNIT + " amount\n" " ,...\n" " }\n" @@ -613,7 +626,7 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) int nextBlockHeight = chainActive.Height() + 1; CMutableTransaction rawTx = CreateNewContextualCMutableTransaction( Params().GetConsensus(), nextBlockHeight); - + if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) { rawTx.nExpiryHeight = nextBlockHeight + expiryDelta; if (rawTx.nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD){ @@ -643,7 +656,7 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) BOOST_FOREACH(const string& name_, addrList) { CBitcoinAddress address(name_); if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Zcash address: ")+name_); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Komodo address: ")+name_); if (setAddress.count(address)) throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+name_); @@ -699,7 +712,7 @@ UniValue decoderawtransaction(const UniValue& params, bool fHelp) " \"reqSigs\" : n, (numeric) The required sigs\n" " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n" " \"addresses\" : [ (json array of string)\n" - " \"t12tvKAXCxZjSmdNbao16dKXC8tRWfcF5oc\" (string) zcash address\n" + " \"RTZMZHDFSTFQst8XmX2dR4DaH87cEUs3gC\" (string) komodo address\n" " ,...\n" " ]\n" " }\n" @@ -769,7 +782,7 @@ UniValue decodescript(const UniValue& params, bool fHelp) " \"type\":\"type\", (string) The output type\n" " \"reqSigs\": n, (numeric) The required signatures\n" " \"addresses\": [ (json array of string)\n" - " \"address\" (string) Zcash address\n" + " \"address\" (string) Komodo address\n" " ,...\n" " ],\n" " \"p2sh\",\"address\" (string) script address\n" diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index bac3adc97..bc1ba5b37 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -238,9 +238,11 @@ UniValue help(const UniValue& params, bool fHelp) return tableRPC.help(strCommand); } +extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; UniValue stop(const UniValue& params, bool fHelp) { + char buf[64]; // Accept the deprecated and ignored 'detach' boolean argument if (fHelp || params.size() > 1) throw runtime_error( @@ -248,7 +250,8 @@ UniValue stop(const UniValue& params, bool fHelp) "\nStop Komodo server."); // Shutdown will take long enough that the response should get back StartShutdown(); - return "Komodo server stopping"; + sprintf(buf,"%s Komodo server stopping",ASSETCHAINS_SYMBOL); + return buf; } /** @@ -299,12 +302,20 @@ static const CRPCCommand vRPCCommands[] = { "blockchain", "paxpending", &paxpending, true }, { "blockchain", "paxprices", &paxprices, true }, { "blockchain", "notaries", ¬aries, true }, - { "blockchain", "height_MoM", &height_MoM, true }, - { "blockchain", "txMoMproof", &txMoMproof, true }, { "blockchain", "minerids", &minerids, true }, { "blockchain", "kvsearch", &kvsearch, true }, { "blockchain", "kvupdate", &kvupdate, true }, + /* Cross chain utilities */ + { "crosschain", "MoMoMdata", &MoMoMdata, true }, + { "crosschain", "calc_MoM", &calc_MoM, true }, + { "crosschain", "height_MoM", &height_MoM, true }, + { "crosschain", "assetchainproof", &assetchainproof, true }, + { "crosschain", "crosschainproof", &crosschainproof, true }, + { "crosschain", "migrate_converttoexport", &migrate_converttoexport, true }, + { "crosschain", "migrate_createimporttransaction", &migrate_createimporttransaction, true }, + { "crosschain", "migrate_completeimporttransaction", &migrate_completeimporttransaction, true }, + /* Mining */ { "mining", "getblocktemplate", &getblocktemplate, true }, { "mining", "getmininginfo", &getmininginfo, true }, @@ -339,6 +350,7 @@ static const CRPCCommand vRPCCommands[] = { "addressindex", "getaddressdeltas", &getaddressdeltas, false }, { "addressindex", "getaddresstxids", &getaddresstxids, false }, { "addressindex", "getaddressbalance", &getaddressbalance, false }, + { "addressindex", "getsnapshot", &getsnapshot, false }, /* Utility functions */ { "util", "createmultisig", &createmultisig, true }, @@ -352,12 +364,12 @@ static const CRPCCommand vRPCCommands[] = { "util", "jumblr_pause", &jumblr_pause, true }, { "util", "jumblr_resume", &jumblr_resume, true }, + { "util", "invalidateblock", &invalidateblock, true }, + { "util", "reconsiderblock", &reconsiderblock, true }, /* Not shown in help */ - { "hidden", "invalidateblock", &invalidateblock, true }, - { "hidden", "reconsiderblock", &reconsiderblock, true }, { "hidden", "setmocktime", &setmocktime, true }, #ifdef ENABLE_WALLET - { "hidden", "resendwallettransactions", &resendwallettransactions, true}, + { "wallet", "resendwallettransactions", &resendwallettransactions, true}, #endif #ifdef ENABLE_WALLET diff --git a/src/rpcserver.h b/src/rpcserver.h index 7766e6a31..40cb96288 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -177,6 +177,7 @@ extern UniValue getaddressmempool(const UniValue& params, bool fHelp); extern UniValue getaddressutxos(const UniValue& params, bool fHelp); extern UniValue getaddressdeltas(const UniValue& params, bool fHelp); extern UniValue getaddresstxids(const UniValue& params, bool fHelp); +extern UniValue getsnapshot(const UniValue& params, bool fHelp); extern UniValue getaddressbalance(const UniValue& params, bool fHelp); extern UniValue getpeerinfo(const UniValue& params, bool fHelp); extern UniValue ping(const UniValue& params, bool fHelp); @@ -312,8 +313,15 @@ extern UniValue z_validateaddress(const UniValue& params, bool fHelp); // in rpc extern UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp); // in rpcdisclosure.cpp extern UniValue z_validatepaymentdisclosure(const UniValue ¶ms, bool fHelp); // in rpcdisclosure.cpp +extern UniValue MoMoMdata(const UniValue& params, bool fHelp); +extern UniValue calc_MoM(const UniValue& params, bool fHelp); extern UniValue height_MoM(const UniValue& params, bool fHelp); -extern UniValue txMoMproof(const UniValue& params, bool fHelp); +extern UniValue assetchainproof(const UniValue& params, bool fHelp); +extern UniValue crosschainproof(const UniValue& params, bool fHelp); +extern UniValue migrate_converttoexport(const UniValue& params, bool fHelp); +extern UniValue migrate_createimporttransaction(const UniValue& params, bool fHelp); +extern UniValue migrate_completeimporttransaction(const UniValue& params, bool fHelp); + extern UniValue notaries(const UniValue& params, bool fHelp); extern UniValue minerids(const UniValue& params, bool fHelp); extern UniValue kvsearch(const UniValue& params, bool fHelp); diff --git a/src/script/cc.h b/src/script/cc.h index dc019beba..246f19052 100644 --- a/src/script/cc.h +++ b/src/script/cc.h @@ -1,6 +1,8 @@ #ifndef SCRIPT_CC_H #define SCRIPT_CC_H +#include + #include "pubkey.h" #include "script/script.h" #include "cryptoconditions/include/cryptoconditions.h" @@ -79,5 +81,4 @@ bool GetPushData(const CScript &sig, std::vector &data); */ bool GetOpReturnData(const CScript &sig, std::vector &data); - #endif /* SCRIPT_CC_H */ diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 5438102c3..4a2eac2bc 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -3,17 +3,20 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include + #include "interpreter.h" #include "consensus/upgrades.h" #include "primitives/transaction.h" +#include "cc/eval.h" #include "crypto/ripemd160.h" #include "crypto/sha1.h" #include "crypto/sha256.h" #include "pubkey.h" #include "script/script.h" #include "uint256.h" -#include "cryptoconditions/include/cryptoconditions.h" + using namespace std; diff --git a/src/script/interpreter.h b/src/script/interpreter.h index 7aa0d5099..b4c537a2d 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -186,5 +186,4 @@ bool VerifyScript( const BaseSignatureChecker& checker, uint32_t consensusBranchId, ScriptError* serror = NULL); - #endif // BITCOIN_SCRIPT_INTERPRETER_H diff --git a/src/script/script.cpp b/src/script/script.cpp index a130df4aa..4cffc6c5a 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -8,8 +8,10 @@ #include "tinyformat.h" #include "utilstrencodings.h" #include "script/cc.h" +#include "cc/eval.h" #include "cryptoconditions/include/cryptoconditions.h" + namespace { inline std::string ValueString(const std::vector& vch) { @@ -227,6 +229,14 @@ bool CScript::IsPayToPublicKeyHash() const (*this)[24] == OP_CHECKSIG); } +bool CScript::IsPayToPublicKey() const +{ + // Extra-fast test for pay-to-pubkey CScripts: + return (this->size() == 35 && + (*this)[0] == 33 && + (*this)[34] == OP_CHECKSIG); +} + bool CScript::IsPayToScriptHash() const { // Extra-fast test for pay-to-script-hash CScripts: @@ -266,6 +276,17 @@ bool CScript::MayAcceptCryptoCondition() const return out; } +bool CScript::IsCoinImport() const +{ + const_iterator pc = this->begin(); + vector data; + opcodetype opcode; + if (this->GetOp(pc, opcode, data)) + if (opcode > OP_0 && opcode <= OP_PUSHDATA4) + return data.begin()[0] == EVAL_IMPORTCOIN; + return false; +} + bool CScript::IsPushOnly() const { const_iterator pc = begin(); diff --git a/src/script/script.h b/src/script/script.h index e5328cf06..56d2ff0b6 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -567,9 +567,11 @@ public: unsigned int GetSigOpCount(const CScript& scriptSig) const; bool IsPayToPublicKeyHash() const; + bool IsPayToPublicKey() const; bool IsPayToScriptHash() const; bool IsPayToCryptoCondition() const; + bool IsCoinImport() const; bool MayAcceptCryptoCondition() const; /** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */ diff --git a/src/snark/AUTHORS b/src/snark/AUTHORS index 1b2d7a247..cdc8d66af 100644 --- a/src/snark/AUTHORS +++ b/src/snark/AUTHORS @@ -17,3 +17,6 @@ External contributors: Tadanori TERUYA Sean Bowe Daira Hopwood + @mugatu on forum.z.cash + David Mercer + Joshua Yabut diff --git a/src/snark/Makefile b/src/snark/Makefile index b865f992f..17dcfdc6e 100644 --- a/src/snark/Makefile +++ b/src/snark/Makefile @@ -6,6 +6,13 @@ #* @copyright MIT license (see LICENSE file) #*******************************************************************************/ +# Determine building operating system +ifeq ($(OS),Windows_NT) + uname_S := Windows +else + uname_S := $(shell uname -s) +endif + # To override these, use "make OPTFLAGS=..." etc. CURVE = BN128 OPTFLAGS = -O2 -march=native -mtune=native @@ -106,18 +113,9 @@ EXECUTABLES_WITH_GTEST = EXECUTABLES_WITH_SUPERCOP = \ libsnark/zk_proof_systems/ppzkadsnark/r1cs_ppzkadsnark/examples/demo_r1cs_ppzkadsnark -GTEST_TESTS = libsnark/gtests +GTEST_TESTS = -GTEST_SRCS = \ - libsnark/algebra/curves/tests/test_bilinearity.cpp \ - libsnark/algebra/curves/tests/test_groups.cpp \ - libsnark/algebra/fields/tests/test_bigint.cpp \ - libsnark/algebra/fields/tests/test_fields.cpp \ - libsnark/gadgetlib1/gadgets/hashes/sha256/tests/test_sha256_gadget.cpp \ - libsnark/gadgetlib1/gadgets/merkle_tree/tests/test_merkle_tree_gadgets.cpp \ - libsnark/relations/arithmetic_programs/qap/tests/test_qap.cpp \ - libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/tests/test_r1cs_ppzksnark.cpp \ - libsnark/gtests.cpp +GTEST_SRCS = DOCS = README.html @@ -175,6 +173,7 @@ all: \ $(if $(NO_GTEST),,$(EXECUTABLES_WITH_GTEST) $(GTEST_TESTS)) \ $(if $(NO_SUPERCOP),,$(EXECUTABLES_WITH_SUPERCOP)) \ $(EXECUTABLES) \ + $(LIBSNARK_A) \ $(if $(NO_DOCS),,doc) doc: $(DOCS) diff --git a/src/snark/README.md b/src/snark/README.md index 89183b43a..d5aa34006 100644 --- a/src/snark/README.md +++ b/src/snark/README.md @@ -14,7 +14,7 @@ Copyright (c) 2012-2014 SCIPR Lab and contributors (see [AUTHORS] file). [TOC]