diff --git a/.travis.yml b/.travis.yml index d9237a104..bfc8b8b4a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,22 +5,32 @@ matrix: - os: linux dist: xenial sudo: required + env: LINUX_DEPLOY="true" OSX_DEPLOY="false" $TRAVIS_OS_NAME="linux" - os: osx - osx_image: xcode8 + osx_image: xcode8 + env: OSX_DEPLOY="true" LINUX_DEPLOY="false" $TRAVIS_OS_NAME="osx" +branches: + only: + - master + - dev + - cctests compiler: -- gcc + - gcc before_install: -- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa; fi -- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update -qq; fi -- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install libgnutls28-dev; fi -- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install build-essential pkg-config libcurl3-gnutls-dev libc6-dev libevent-dev m4 g++-multilib autoconf libtool ncurses-dev unzip git python zlib1g-dev wget bsdmainutils automake libssl-dev libprotobuf-dev protobuf-compiler libdb++-dev ntp ntpdate; fi -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then rm '/usr/local/include/c++'; fi -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install gcc@6; fi -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew link --overwrite gcc@6; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update -qq; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install libgnutls28-dev; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install build-essential pkg-config libcurl3-gnutls-dev libc6-dev libevent-dev m4 g++-multilib autoconf libtool ncurses-dev unzip git python zlib1g-dev wget bsdmainutils automake libssl-dev libprotobuf-dev protobuf-compiler libdb++-dev ntp ntpdate; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then rm '/usr/local/include/c++'; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install gcc@6; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew link --overwrite gcc@6; fi script: -- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./zcutil/build.sh -j 5; fi -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./zcutil/build-mac.sh -j 5; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./zcutil/build.sh -j 5; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then tar cvfz komodo_linux_$TRAVIS_BRANCH.tar.gz src/komodod src/komodo-cli; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./zcutil/build-mac.sh -j 5; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./makeRelease.sh; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then tar cvfz komodo_osx_$TRAVIS_BRANCH.tar.gz src/komodod src/komodo-cli src/libgcc_s.1.dylib src/libgomp.1.dylib src/libstdc++.6.dylib; fi notifications: irc: channels: @@ -32,15 +42,50 @@ notifications: - 'Change view : %{compare_url}' - 'Build details : %{build_url}' before_deploy: - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then git tag "linux-$(date +'%Y%m%d%H%M')-$(git log --format=%h -1)"; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then git tag "osx-$(date +'%Y%m%d%H%M')-$(git log --format=%h -1)"; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then git tag "$TRAVIS_BRANCH-linux-$(date +'%Y%m%d%H%M')-$(git log --format=%h -1)"; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then git tag "$TRAVIS_BRANCH-osx-$(date +'%Y%m%d%H%M')-$(git log --format=%h -1)"; fi deploy: - provider: releases - api_key: - secure: Jms7dz5GMZmuXUCHl5u6iZUtAybv86oW3x36DCJfdzbDiO4B9EWB04z7zA0qvoomefyujHTmQUHxyOKfd4h9/rVMFFv9hgmUxWkrcg7KyLNisOQRaovVOuNtu2lRNXTOSF16Cy+xFGkVh1ObBRhAoMsVKPhMl6PCDiKhNWIekRR9pBtjafKsClQ2ieknUYfqhuvgj7zmqCedeyVaVQyt2W/J65leD0BkfCUESTpANSprHs4bQB65VuQIKKMi+URKx2VgpDdUcWJySt9jAHVPIbI5cT5maAT6RUMnE4oha7Ca1Ox8StBqjQ/hkkMyDbN0keIlN7RjZlwdZQf/qUnT/dPQhsyUCdPXOxmEJ2jekezEK/LGr4Fb+v+vjd9dhLNkD5nVn9zp36biGSCjiMpffQ3fjMeM0YGmVEVRP9kZXLWVRYQoVKrzjyzg5dY8iChbiQEfYpTeBuU+e2rqj4mns+Jvy0zjUbMy6Tyva+iqdZ/PdsBDbiB7c+FIgB1IUTVOD+GgKx6dhCtBZEccn5EyWFwZF9IdQJHZCYV4PA7nuzfm1Ol9SDdZkGHd2OgRCqK/sTwyfTHv8exNqZ1k+epGJp2a0q4IOEknc9aPCAF+m9pHahk7s7VO5gmhO6pvbvuKoeEtEXRZHRzCkGkXfzJlBk+23X5gBexKb6inRdBlj6M= - file: - - src/komodod - - src/komodo-cli - skip_cleanup: true - on: - repo: KomodoPlatform/komodo + - provider: releases + api_key: + secure: id69KBVsY0p41WFlqd5cGrAIksJAkUempmdrQwHtfqIbB6es7MVfXuxfmTxk7lZNEItSvLGilYtqhBMNVAVjRRPvk90hveGDMkbpjFz3XBbFEFqtrAr2GdIcpGtII2T3T/TG7j11TMtJ6GvBVt4OcatHFVsKBCFDIx0fB0fd1oLrEAwgRdBO2Jq7bMzoLdzGx3mVtdW5dSRBQzG/Z0yvx+R9mQHSvyPGh6oNPD6mvXPzEaCeRW6Y8g8y1SW/6zDJR6sSdOKA0jsHkr/hM8st3Qkr5Cu3roEbL8598uvfBahjxVHVT8+lu/nJnQyrvtWZKu/uUefybqgZl7UpGvZVFxbNwAB/ZNn0pBKIpZlX/kh6rdGF0XrAG7g+Ths6iklh7wDefYP2JeGwHWJ38YcdF8T/VcSdOXz7EiWwEeZO5sGcTRSl5Ql8mcU3YyyB7BTdViYNTHf5VFFJ/baLZG+shZ/0tb1Ntx5mLDbV8vcYXJpUNTJcXbhcUDSF3QuSz04ftkzgpcsODzcTzD6+2sezV1vlOAlxK04C+zzxG96Md/TegvZYYns78RSgrP/UH1qwEbgxTo3xpErGllzntzZfHJ887Goez+DeB9ga7pUBc5AXGpfRhYqJP66wR10zqfWuWYvjAwRBRNySjr3pUvaA3T1iSZ5HLrpKBfcHXJOTg8M= + name: komodo_linux-$TRAVIS_BRANCH + prerelease: true + file: komodo_linux_$TRAVIS_BRANCH.tar.gz + skip_cleanup: true + on: + repo: KomodoPlatform/komodo + branch: master + condition: $LINUX_DEPLOY = "true" + - provider: releases + api_key: + secure: id69KBVsY0p41WFlqd5cGrAIksJAkUempmdrQwHtfqIbB6es7MVfXuxfmTxk7lZNEItSvLGilYtqhBMNVAVjRRPvk90hveGDMkbpjFz3XBbFEFqtrAr2GdIcpGtII2T3T/TG7j11TMtJ6GvBVt4OcatHFVsKBCFDIx0fB0fd1oLrEAwgRdBO2Jq7bMzoLdzGx3mVtdW5dSRBQzG/Z0yvx+R9mQHSvyPGh6oNPD6mvXPzEaCeRW6Y8g8y1SW/6zDJR6sSdOKA0jsHkr/hM8st3Qkr5Cu3roEbL8598uvfBahjxVHVT8+lu/nJnQyrvtWZKu/uUefybqgZl7UpGvZVFxbNwAB/ZNn0pBKIpZlX/kh6rdGF0XrAG7g+Ths6iklh7wDefYP2JeGwHWJ38YcdF8T/VcSdOXz7EiWwEeZO5sGcTRSl5Ql8mcU3YyyB7BTdViYNTHf5VFFJ/baLZG+shZ/0tb1Ntx5mLDbV8vcYXJpUNTJcXbhcUDSF3QuSz04ftkzgpcsODzcTzD6+2sezV1vlOAlxK04C+zzxG96Md/TegvZYYns78RSgrP/UH1qwEbgxTo3xpErGllzntzZfHJ887Goez+DeB9ga7pUBc5AXGpfRhYqJP66wR10zqfWuWYvjAwRBRNySjr3pUvaA3T1iSZ5HLrpKBfcHXJOTg8M= + name: komodo_linux-$TRAVIS_BRANCH + prerelease: true + file: komodo_linux_$TRAVIS_BRANCH.tar.gz + skip_cleanup: true + on: + repo: KomodoPlatform/komodo + branch: dev + condition: $LINUX_DEPLOY = "true" + - provider: releases + api_key: + secure: id69KBVsY0p41WFlqd5cGrAIksJAkUempmdrQwHtfqIbB6es7MVfXuxfmTxk7lZNEItSvLGilYtqhBMNVAVjRRPvk90hveGDMkbpjFz3XBbFEFqtrAr2GdIcpGtII2T3T/TG7j11TMtJ6GvBVt4OcatHFVsKBCFDIx0fB0fd1oLrEAwgRdBO2Jq7bMzoLdzGx3mVtdW5dSRBQzG/Z0yvx+R9mQHSvyPGh6oNPD6mvXPzEaCeRW6Y8g8y1SW/6zDJR6sSdOKA0jsHkr/hM8st3Qkr5Cu3roEbL8598uvfBahjxVHVT8+lu/nJnQyrvtWZKu/uUefybqgZl7UpGvZVFxbNwAB/ZNn0pBKIpZlX/kh6rdGF0XrAG7g+Ths6iklh7wDefYP2JeGwHWJ38YcdF8T/VcSdOXz7EiWwEeZO5sGcTRSl5Ql8mcU3YyyB7BTdViYNTHf5VFFJ/baLZG+shZ/0tb1Ntx5mLDbV8vcYXJpUNTJcXbhcUDSF3QuSz04ftkzgpcsODzcTzD6+2sezV1vlOAlxK04C+zzxG96Md/TegvZYYns78RSgrP/UH1qwEbgxTo3xpErGllzntzZfHJ887Goez+DeB9ga7pUBc5AXGpfRhYqJP66wR10zqfWuWYvjAwRBRNySjr3pUvaA3T1iSZ5HLrpKBfcHXJOTg8M= + name: komodo_osx-$TRAVIS_BRANCH + prerelease: true + file: komodo_osx_$TRAVIS_BRANCH.tar.gz + skip_cleanup: true + on: + repo: KomodoPlatform/komodo + branch: master + condition: $OSX_DEPLOY = "true" + - provider: releases + api_key: + secure: id69KBVsY0p41WFlqd5cGrAIksJAkUempmdrQwHtfqIbB6es7MVfXuxfmTxk7lZNEItSvLGilYtqhBMNVAVjRRPvk90hveGDMkbpjFz3XBbFEFqtrAr2GdIcpGtII2T3T/TG7j11TMtJ6GvBVt4OcatHFVsKBCFDIx0fB0fd1oLrEAwgRdBO2Jq7bMzoLdzGx3mVtdW5dSRBQzG/Z0yvx+R9mQHSvyPGh6oNPD6mvXPzEaCeRW6Y8g8y1SW/6zDJR6sSdOKA0jsHkr/hM8st3Qkr5Cu3roEbL8598uvfBahjxVHVT8+lu/nJnQyrvtWZKu/uUefybqgZl7UpGvZVFxbNwAB/ZNn0pBKIpZlX/kh6rdGF0XrAG7g+Ths6iklh7wDefYP2JeGwHWJ38YcdF8T/VcSdOXz7EiWwEeZO5sGcTRSl5Ql8mcU3YyyB7BTdViYNTHf5VFFJ/baLZG+shZ/0tb1Ntx5mLDbV8vcYXJpUNTJcXbhcUDSF3QuSz04ftkzgpcsODzcTzD6+2sezV1vlOAlxK04C+zzxG96Md/TegvZYYns78RSgrP/UH1qwEbgxTo3xpErGllzntzZfHJ887Goez+DeB9ga7pUBc5AXGpfRhYqJP66wR10zqfWuWYvjAwRBRNySjr3pUvaA3T1iSZ5HLrpKBfcHXJOTg8M= + name: komodo_osx-$TRAVIS_BRANCH + prerelease: true + file: komodo_osx_$TRAVIS_BRANCH.tar.gz + skip_cleanup: true + on: + repo: KomodoPlatform/komodo + branch: dev + condition: $OSX_DEPLOY = "true" diff --git a/COPYING b/COPYING index 7c046110d..587a47035 100644 --- a/COPYING +++ b/COPYING @@ -1,7 +1,7 @@ Copyright (c) 2009-2017 The Bitcoin Core developers Copyright (c) 2009-2018 Bitcoin Developers Copyright (c) 2016-2017 The Zcash developers -Copyright (c) 2016-2018 The Komodo developers +Copyright (c) 2016-2019 The Komodo developers Copyright (c) 2018 The VerusCoin developers Permission is hereby granted, free of charge, to any person obtaining a copy @@ -38,3 +38,345 @@ Although almost all of the Zcash/Komodo/VerusCoin code is licensed under "permis licenses, users and distributors should note that when built using the default build options, Zcash depends on Oracle Berkeley DB 6.2.x, which is licensed under the GNU Affero General Public License. + +SuperNET COPYING terms: +GNU GENERAL PUBLIC LICENSE +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + +We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + +Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and +modification follow. + +GNU GENERAL PUBLIC LICENSE +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + +a) You must cause the modified files to carry prominent notices +stating that you changed the files and the date of any change. + +b) You must cause any work that you distribute or publish, that in +whole or in part contains or is derived from the Program or any +part thereof, to be licensed as a whole at no charge to all third +parties under the terms of this License. + +c) If the modified program normally reads commands interactively +when run, you must cause it, when started running for such +interactive use in the most ordinary way, to print or display an +announcement including an appropriate copyright notice and a +notice that there is no warranty (or else, saying that you provide +a warranty) and that users may redistribute the program under +these conditions, and telling the user how to view a copy of this +License. (Exception: if the Program itself is interactive but +does not normally print such an announcement, your work based on +the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + +3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + +a) Accompany it with the complete corresponding machine-readable +source code, which must be distributed under the terms of Sections +1 and 2 above on a medium customarily used for software interchange; or, + +b) Accompany it with a written offer, valid for at least three +years, to give any third party, for a charge no more than your +cost of physically performing source distribution, a complete +machine-readable copy of the corresponding source code, to be +distributed under the terms of Sections 1 and 2 above on a medium +customarily used for software interchange; or, + +c) Accompany it with the information you received as to the offer +to distribute corresponding source code. (This alternative is +allowed only for noncommercial distribution and only if you +received the program in object code or executable form with such +an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + +5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + +7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + +10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + +Copyright (C) + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + +Gnomovision version 69, Copyright (C) year name of author +Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. +This is free software, and you are welcome to redistribute it +under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in the program +`Gnomovision' (which makes passes at compilers) written by James Hacker. + +, 1 April 1989 +Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. + diff --git a/depends/packages/libsodium.mk b/depends/packages/libsodium.mk index 67e096fae..76f0d9a28 100644 --- a/depends/packages/libsodium.mk +++ b/depends/packages/libsodium.mk @@ -9,7 +9,7 @@ $(package)_config_opts= else package=libsodium $(package)_version=1.0.15 -$(package)_download_path=https://download.libsodium.org/libsodium/releases +$(package)_download_path=https://download.libsodium.org/libsodium/releases/old $(package)_file_name=$(package)-$($(package)_version).tar.gz $(package)_sha256_hash=fb6a9e879a2f674592e4328c5d9f79f082405ee4bb05cb6e679b90afe9e178f4 $(package)_dependencies= diff --git a/qa/pull-tester/cc-tests.sh b/qa/pull-tester/cc-tests.sh index 4e8dde894..9bc8c155d 100755 --- a/qa/pull-tester/cc-tests.sh +++ b/qa/pull-tester/cc-tests.sh @@ -13,12 +13,13 @@ export BITCOIND=${REAL_BITCOIND} testScripts=( 'cryptoconditions_faucet.py' - 'cryptoconditions_channels.py' 'cryptoconditions_dice.py' 'cryptoconditions_oracles.py' 'cryptoconditions_rewards.py' 'cryptoconditions_token.py' - 'cryptoconditions_gateways.py' + #'cryptoconditions_gateways.py' + # TODO: cant reconnect nodes back in channels test because of crash (seems regtest only specific) + 'cryptoconditions_channels.py' ); extArg="-extended" diff --git a/qa/rpc-tests/cryptoconditions_channels.py b/qa/rpc-tests/cryptoconditions_channels.py index 053b532cb..b2a49b477 100755 --- a/qa/rpc-tests/cryptoconditions_channels.py +++ b/qa/rpc-tests/cryptoconditions_channels.py @@ -4,6 +4,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. +import time from test_framework.test_framework import CryptoconditionsTestFramework from test_framework.authproxy import JSONRPCException from test_framework.util import assert_equal, assert_greater_than, \ @@ -26,10 +27,10 @@ class CryptoconditionsChannelsTest(CryptoconditionsTestFramework): rpc1 = self.nodes[1] # getting empty channels list - result = rpc.channelsinfo() + result = rpc.channelslist() assert_equal(len(result), 2) assert_equal(result["result"], "success") - assert_equal(result["name"], "Channels Info") + assert_equal(result["name"], "Channels List") # 10 payments, 100000 sat denomination channel opening with second node pubkey new_channel_hex = rpc.channelsopen(self.pubkey1, "10", "100000") @@ -38,13 +39,13 @@ class CryptoconditionsChannelsTest(CryptoconditionsTestFramework): assert channel_txid, "got channel txid" # checking if our new channel in common channels list - result = rpc.channelsinfo() + result = rpc.channelslist() assert_equal(len(result), 3) # checking info about channel directly result = rpc.channelsinfo(channel_txid) assert_success(result) - assert_equal(result["Open"], "10 payments of 100000 satoshi") + assert_equal(result["Transactions"][0]["Open"], channel_txid) # open transaction should be confirmed rpc.generate(1) @@ -69,7 +70,59 @@ class CryptoconditionsChannelsTest(CryptoconditionsTestFramework): # now in channelinfo payment information should appear result = rpc.channelsinfo(channel_txid) - assert_equal(result["Payment"], "100000 satoshi to {}, 9 payments left".format(self.addr1)) + assert_equal(result["Transactions"][1]["Payment"], payment_tx_id) + + # number of payments should be equal 1 (one denomination used) + result = rpc.channelsinfo(channel_txid)["Transactions"][1]["Number of payments"] + assert_equal(result, 1) + # payments left param should reduce 1 and be equal 9 now ( 10 - 1 = 9 ) + result = rpc.channelsinfo(channel_txid)["Transactions"][1]["Payments left"] + assert_equal(result, 9) + + # lets try payment with x2 amount to ensure that counters works correct + result = rpc.channelspayment(channel_txid, "200000") + assert_success(result) + payment_tx_id = self.send_and_mine(result["hex"], rpc) + assert payment_tx_id, "got txid" + + result = rpc.channelsinfo(channel_txid) + assert_equal(result["Transactions"][2]["Payment"], payment_tx_id) + + result = rpc.channelsinfo(channel_txid)["Transactions"][2]["Number of payments"] + assert_equal(result, 2) + + result = rpc.channelsinfo(channel_txid)["Transactions"][2]["Payments left"] + assert_equal(result, 7) + + # check if payment value really transferred + raw_transaction = rpc.getrawtransaction(payment_tx_id, 1) + + result = raw_transaction["vout"][3]["valueSat"] + assert_equal(result, 200000) + + result = rpc1.validateaddress(raw_transaction["vout"][3]["scriptPubKey"]["addresses"][0])["ismine"] + assert_equal(result, True) + + # have to check that second node have coins to cover txfee at least + rpc.sendtoaddress(rpc1.getnewaddress(), 1) + rpc.sendtoaddress(rpc1.getnewaddress(), 1) + rpc.generate(2) + self.sync_all() + result = rpc1.getbalance() + assert_greater_than(result, 0.1) + + # trying to initiate channels payment from node B without any secret + # TODO: have to add RPC validation + payment_hex = rpc1.channelspayment(channel_txid, "100000") + try: + result = rpc1.sendrawtransaction(payment_hex["hex"]) + except Exception as e: + pass + + # trying to initiate channels payment from node B with secret from previous payment + result = rpc1.channelspayment(channel_txid, "100000", rpc1.channelsinfo(channel_txid)["Transactions"][1]["Secret"]) + #result = rpc1.sendrawtransaction(payment_hex["hex"]) + assert_error(result) # executing channel close result = rpc.channelsclose(channel_txid) @@ -82,7 +135,7 @@ class CryptoconditionsChannelsTest(CryptoconditionsTestFramework): # now in channelinfo closed flag should appear result = rpc.channelsinfo(channel_txid) - assert_equal(result["Close"], "channel") + assert_equal(result["Transactions"][3]["Close"], channel_close_txid) # executing channel refund result = rpc.channelsrefund(channel_txid, channel_close_txid) @@ -90,6 +143,92 @@ class CryptoconditionsChannelsTest(CryptoconditionsTestFramework): refund_txid = self.send_and_mine(result["hex"], rpc) assert refund_txid, "got txid" + # TODO: check if it refunded to opener address + raw_transaction = rpc.getrawtransaction(refund_txid, 1) + + result = raw_transaction["vout"][2]["valueSat"] + assert_equal(result, 700000) + + result = rpc.validateaddress(raw_transaction["vout"][2]["scriptPubKey"]["addresses"][0])["ismine"] + assert_equal(result, True) + + + # creating and draining channel (10 payment by 100000 satoshies in total to fit full capacity) + new_channel_hex1 = rpc.channelsopen(self.pubkey1, "10", "100000") + assert_success(new_channel_hex1) + channel1_txid = self.send_and_mine(new_channel_hex1["hex"], rpc) + assert channel1_txid, "got channel txid" + + # need to have 2+ confirmations in the test mode + rpc.generate(2) + self.sync_all() + + for i in range(10): + result = rpc.channelspayment(channel1_txid, "100000") + assert_success(result) + payment_tx_id = self.send_and_mine(result["hex"], rpc) + assert payment_tx_id, "got txid" + + # last payment should indicate that 0 payments left + result = rpc.channelsinfo(channel1_txid)["Transactions"][10]["Payments left"] + assert_equal(result, 0) + + # no more payments possible + result = rpc.channelspayment(channel1_txid, "100000") + assert_error(result) + + # creating new channel to test the case when node B initiate payment when node A revealed secret in offline + # 10 payments, 100000 sat denomination channel opening with second node pubkey + new_channel_hex2 = rpc.channelsopen(self.pubkey1, "10", "100000") + assert_success(new_channel_hex) + channel2_txid = self.send_and_mine(new_channel_hex2["hex"], rpc) + assert channel2_txid, "got channel txid" + + rpc.generate(2) + self.sync_all() + + # disconnecting first node from network + rpc.setban("127.0.0.0/24","add") + assert_equal(rpc.getinfo()["connections"], 0) + assert_equal(rpc1.getinfo()["connections"], 0) + + rpc1.generate(1) + + # sending one payment to mempool to reveal the secret but not mine it + payment_hex = rpc.channelspayment(channel2_txid, "100000") + result = rpc.sendrawtransaction(payment_hex["hex"]) + assert result, "got payment txid" + + secret = rpc.channelsinfo(channel2_txid)["Transactions"][1]["Secret"] + assert secret, "Secret revealed" + + # secret shouldn't be available for node B + secret_not_revealed = None + try: + rpc1.channelsinfo(channel2_txid)["Transactions"][1]["Secret"] + except Exception: + secret_not_revealed = True + assert_equal(secret_not_revealed, True) + + # trying to initiate payment from second node with revealed secret + assert_equal(rpc1.getinfo()["connections"], 0) + dc_payment_hex = rpc1.channelspayment(channel2_txid, "100000", secret) + assert_success(dc_payment_hex) + result = rpc1.sendrawtransaction(dc_payment_hex["hex"]) + assert result, "got channelspayment transaction id" + + # TODO: it crash first node after block generating on mempools merging + # # restoring connection between nodes + # rpc.setban("127.0.0.0/24","remove") + # #rpc.generate(1) + # #rpc1.generate(1) + # sync_blocks(self.nodes) + # rpc.generate(1) + # sync_blocks(self.nodes) + # sync_mempools(self.nodes) + # assert_equal(rpc.getinfo()["connections"], 1) + # assert_equal(rpc1.getinfo()["connections"], 1) + def run_test(self): print("Mining blocks...") rpc = self.nodes[0] diff --git a/qa/rpc-tests/cryptoconditions_oracles.py b/qa/rpc-tests/cryptoconditions_oracles.py index f295bf020..048b577d1 100755 --- a/qa/rpc-tests/cryptoconditions_oracles.py +++ b/qa/rpc-tests/cryptoconditions_oracles.py @@ -112,17 +112,15 @@ class CryptoconditionsOraclesTest(CryptoconditionsTestFramework): # baton oraclesdata_d = self.send_and_mine(result["hex"], rpc) result = rpc.oraclessamples(globals()["oracle_{}".format("d")], oraclesdata_d, "1") - # TODO: working not correct now! - #assert_equal("[u'01']", str(result["samples"][0]), "Data match") + assert_equal("[u'01']", str(result["samples"][0]), "Data match") # D type - result = rpc.oraclesdata(globals()["oracle_{}".format("D")], "0101") + result = rpc.oraclesdata(globals()["oracle_{}".format("D")], "010001") assert_success(result) # baton oraclesdata_D = self.send_and_mine(result["hex"], rpc) result = rpc.oraclessamples(globals()["oracle_{}".format("D")], oraclesdata_D, "1") - # TODO: working not correct now! - #assert_equal("[u'01']", str(result["samples"][0]), "Data match") + assert_equal("[u'01']", str(result["samples"][0]), "Data match") # c type result = rpc.oraclesdata(globals()["oracle_{}".format("c")], "ff") @@ -198,12 +196,12 @@ class CryptoconditionsOraclesTest(CryptoconditionsTestFramework): assert_equal("[u'ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000']", str(result["samples"][0]), "Data match") # Ihh type - result = rpc.oraclesdata(globals()["oracle_{}".format("Ihh")], "00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff") + result = rpc.oraclesdata(globals()["oracle_{}".format("Ihh")], "ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff") assert_success(result) # baton oraclesdata_Ihh = self.send_and_mine(result["hex"], rpc) result = rpc.oraclessamples(globals()["oracle_{}".format("Ihh")], oraclesdata_Ihh, "1") - assert_equal("[u'0']", str(result["samples"][0]), "Data match") + assert_equal("[u'4294967295', u'ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000', u'ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000']", str(result["samples"][0]), "Data match") def run_test(self): diff --git a/qa/rpc-tests/cryptoconditions_token.py b/qa/rpc-tests/cryptoconditions_token.py index 630d8f6e3..97ed86f8d 100755 --- a/qa/rpc-tests/cryptoconditions_token.py +++ b/qa/rpc-tests/cryptoconditions_token.py @@ -15,21 +15,35 @@ from cryptoconditions import assert_success, assert_error, generate_random_strin class CryptoconditionsTokenTest(CryptoconditionsTestFramework): def run_token_tests(self): - rpc = self.nodes[0] + + rpc = self.nodes[0] + rpc1 = self.nodes[1] + result = rpc.tokenaddress() assert_success(result) - for x in ['AssetsCCaddress', 'myCCaddress', 'Assetsmarker', 'myaddress']: + for x in ['TokensCCaddress', 'myCCaddress', 'Tokensmarker', 'myaddress']: assert_equal(result[x][0], 'R') result = rpc.tokenaddress(self.pubkey) assert_success(result) + for x in ['TokensCCaddress', 'myCCaddress', 'Tokensmarker', 'myaddress', 'CCaddress']: + assert_equal(result[x][0], 'R') + + result = rpc.assetsaddress() + assert_success(result) + for x in ['AssetsCCaddress', 'myCCaddress', 'Assetsmarker', 'myaddress']: + assert_equal(result[x][0], 'R') + + result = rpc.assetsaddress(self.pubkey) + assert_success(result) for x in ['AssetsCCaddress', 'myCCaddress', 'Assetsmarker', 'myaddress', 'CCaddress']: assert_equal(result[x][0], 'R') + # there are no tokens created yet result = rpc.tokenlist() assert_equal(result, []) - # trying to create token with negaive supply + # trying to create token with negative supply result = rpc.tokencreate("NUKE", "-1987420", "no bueno supply") assert_error(result) @@ -50,12 +64,9 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework): result = rpc.tokenorders() assert_equal(result, []) - # getting token balance for pubkey + # getting token balance for non existing tokenid result = rpc.tokenbalance(self.pubkey) - assert_success(result) - assert_equal(result['balance'], 0) - assert_equal(result['CCaddress'], 'RCRsm3VBXz8kKTsYaXKpy7pSEzrtNNQGJC') - assert_equal(result['tokenid'], self.pubkey) + assert_error(result) # get token balance for token with pubkey result = rpc.tokenbalance(tokenid, self.pubkey) @@ -131,11 +142,25 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework): # checking ask cancellation testorder = rpc.tokenask("100", tokenid, "7.77") testorderid = self.send_and_mine(testorder['hex'], rpc) + # from other node (ensuring that second node have enough balance to cover txfee + # to get the actual error - not "not enough balance" one + rpc.sendtoaddress(rpc1.getnewaddress(), 1) + rpc.sendtoaddress(rpc1.getnewaddress(), 1) + rpc.generate(2) + self.sync_all() + result = rpc1.getbalance() + assert_greater_than(result, 0.1) + + result = rpc1.tokencancelask(tokenid, testorderid) + assert_error(result) + + # from valid node cancel = rpc.tokencancelask(tokenid, testorderid) self.send_and_mine(cancel["hex"], rpc) result = rpc.tokenorders() assert_equal(result, []) + # invalid numtokens bid result = rpc.tokenbid("-1", tokenid, "1") assert_error(result) @@ -184,6 +209,15 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework): # checking bid cancellation testorder = rpc.tokenbid("100", tokenid, "7.77") testorderid = self.send_and_mine(testorder['hex'], rpc) + + # from other node + result = rpc1.getbalance() + assert_greater_than(result, 0.1) + + result = rpc1.tokencancelbid(tokenid, testorderid) + assert_error(result) + + # from valid node cancel = rpc.tokencancelbid(tokenid, testorderid) self.send_and_mine(cancel["hex"], rpc) result = rpc.tokenorders() @@ -220,5 +254,6 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework): rpc1.importprivkey(self.privkey1) self.run_token_tests() + if __name__ == '__main__': CryptoconditionsTokenTest().main() diff --git a/src/Makefile.am b/src/Makefile.am index 874c3a8b4..ad9842f09 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -290,6 +290,7 @@ libbitcoin_server_a_SOURCES = \ cc/CCcustom.cpp \ cc/CCtx.cpp \ cc/CCutils.cpp \ + cc/CCtokens.cpp \ cc/assets.cpp \ cc/faucet.cpp \ cc/rewards.cpp \ @@ -300,7 +301,7 @@ libbitcoin_server_a_SOURCES = \ cc/oracles.cpp \ cc/prices.cpp \ cc/pegs.cpp \ - cc/triggers.cpp \ + cc/marmara.cpp \ cc/payments.cpp \ cc/gateways.cpp \ cc/channels.cpp \ @@ -383,6 +384,8 @@ libbitcoin_wallet_a_SOURCES = \ transaction_builder.cpp \ wallet/rpcdisclosure.cpp \ wallet/rpcdump.cpp \ + cc/CCtokens.cpp \ + cc/CCassetsCore.cpp \ cc/CCassetstx.cpp \ cc/CCtx.cpp \ wallet/rpcwallet.cpp \ @@ -568,7 +571,8 @@ komodod_LDADD += \ $(LIBBITCOIN_CRYPTO) \ $(LIBVERUS_CRYPTO) \ $(LIBVERUS_PORTABLE_CRYPTO) \ - $(LIBZCASH_LIBS) + $(LIBZCASH_LIBS) \ + libcc.so if ENABLE_PROTON komodod_LDADD += $(LIBBITCOIN_PROTON) $(PROTON_LIBS) diff --git a/src/ac/ksb b/src/ac/ksb new file mode 100755 index 000000000..450c3b3f6 --- /dev/null +++ b/src/ac/ksb @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=KSB $1 $2 $3 $4 $5 $6 diff --git a/src/addrman.cpp b/src/addrman.cpp index c4a2e6e80..1c8bf4b7c 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "addrman.h" #include "hash.h" diff --git a/src/addrman.h b/src/addrman.h index 5c77a4fdb..0390b4e9b 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_ADDRMAN_H #define BITCOIN_ADDRMAN_H diff --git a/src/alert.cpp b/src/alert.cpp index ea9cbad21..4d832da7c 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "alert.h" #include "clientversion.h" diff --git a/src/alert.h b/src/alert.h index 4e3b88775..16204c9c5 100644 --- a/src/alert.h +++ b/src/alert.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_ALERT_H #define BITCOIN_ALERT_H diff --git a/src/alertkeys.h b/src/alertkeys.h index 32d26638e..106576add 100644 --- a/src/alertkeys.h +++ b/src/alertkeys.h @@ -1,3 +1,18 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_ALERTKEYS_H #define BITCOIN_ALERTKEYS_H diff --git a/src/amount.cpp b/src/amount.cpp index 4e32ff45b..3feb37ccc 100644 --- a/src/amount.cpp +++ b/src/amount.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "amount.h" #include "tinyformat.h" diff --git a/src/amount.h b/src/amount.h index 7423fdaa1..be1c39a6e 100644 --- a/src/amount.h +++ b/src/amount.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_AMOUNT_H #define BITCOIN_AMOUNT_H diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp index c9074fe91..e9c0dd056 100644 --- a/src/arith_uint256.cpp +++ b/src/arith_uint256.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "arith_uint256.h" #include "uint256.h" diff --git a/src/arith_uint256.h b/src/arith_uint256.h index 103c78bb8..b51f82f14 100644 --- a/src/arith_uint256.h +++ b/src/arith_uint256.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_ARITH_UINT256_H #define BITCOIN_ARITH_UINT256_H diff --git a/src/assetchains.json b/src/assetchains.json index 1a0ae25e2..1b23bc616 100644 --- a/src/assetchains.json +++ b/src/assetchains.json @@ -215,5 +215,14 @@ "addnode": [ "5.9.102.210" ] - } + }, + { + "ac_name": "KSB", + "ac_supply": "1000000000", + "ac_end": "1", + "ac_public": "1", + "addnode": [ + "37.187.225.231" + ] + } ] diff --git a/src/assetchains.old b/src/assetchains.old index 6df854903..136f7c709 100755 --- a/src/assetchains.old +++ b/src/assetchains.old @@ -45,3 +45,4 @@ echo $pubkey ./komodod -pubkey=$pubkey -ac_name=KMDICE -ac_supply=10500000 -ac_reward=2500000000 -ac_halving=210000 -ac_cc=2 -addressindex=1 -spentindex=1 -addnode=144.76.217.232 & ./komodod -pubkey=$pubkey -ac_name=DION -ac_supply=3900000000 -ac_reward=22260000000 -ac_staked=100 -ac_cc=1 -ac_end=4300000000 -addnode=51.75.124.34 & ./komodod -pubkey=$pubkey -ac_name=ZEX -ac_cc=2 -ac_founders=1 -ac_halving=525600 -ac_reward=13000000000 -ac_pubkey=039d4a50cc70d1184e462a22edb3b66385da97cc8059196f8305c184a3e21440af -addnode=5.9.102.210 & +./komodod -pubkey=$pubkey -ac_name=KSB -ac_supply=1000000000 -ac_end=1 -ac_public=1 -addnode=37.187.225.231 & diff --git a/src/asyncrpcoperation.cpp b/src/asyncrpcoperation.cpp index ff5c4cb9f..75c8da9e6 100644 --- a/src/asyncrpcoperation.cpp +++ b/src/asyncrpcoperation.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "asyncrpcoperation.h" #include diff --git a/src/asyncrpcoperation.h b/src/asyncrpcoperation.h index 2b821e256..3fe966977 100644 --- a/src/asyncrpcoperation.h +++ b/src/asyncrpcoperation.h @@ -2,6 +2,20 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ #ifndef ASYNCRPCOPERATION_H #define ASYNCRPCOPERATION_H diff --git a/src/asyncrpcqueue.cpp b/src/asyncrpcqueue.cpp index afe6d4bef..5bcb20f8d 100644 --- a/src/asyncrpcqueue.cpp +++ b/src/asyncrpcqueue.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "asyncrpcqueue.h" static std::atomic workerCounter(0); diff --git a/src/asyncrpcqueue.h b/src/asyncrpcqueue.h index 1a099a263..0d228564f 100644 --- a/src/asyncrpcqueue.h +++ b/src/asyncrpcqueue.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef ASYNCRPCQUEUE_H #define ASYNCRPCQUEUE_H diff --git a/src/base58.cpp b/src/base58.cpp index 12978fa1c..9d10b7e6a 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "base58.h" #include diff --git a/src/base58.h b/src/base58.h index 66cb7e7a0..4decb4922 100644 --- a/src/base58.h +++ b/src/base58.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + /** * Why base-58 instead of standard base-64 encoding? * - Don't want 0OIl characters that look the same in some fonts and diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 64830d463..544972586 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "chainparamsbase.h" #include "clientversion.h" #include "rpc/client.h" diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 34e1b5d91..b2fa534a1 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "clientversion.h" #include "rpc/server.h" #include "init.h" @@ -79,7 +94,8 @@ void WaitForShutdown(boost::thread_group* threadGroup) // // Start // -extern int32_t IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,ASSETCHAIN_INIT; +extern int32_t IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY; +extern uint32_t ASSETCHAIN_INIT; extern std::string NOTARY_PUBKEY; int32_t komodo_is_issuer(); void komodo_passport_iteration(); diff --git a/src/bloom.cpp b/src/bloom.cpp index de8720659..d7a7742fe 100644 --- a/src/bloom.cpp +++ b/src/bloom.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "bloom.h" #include "primitives/transaction.h" diff --git a/src/bloom.h b/src/bloom.h index df5c30b1e..e4677d6d0 100644 --- a/src/bloom.h +++ b/src/bloom.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_BLOOM_H #define BITCOIN_BLOOM_H diff --git a/src/cJSON.c b/src/cJSON.c index b67ca698d..09da06889 100644 --- a/src/cJSON.c +++ b/src/cJSON.c @@ -20,6 +20,21 @@ THE SOFTWARE. */ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + /* cJSON */ /* JSON parser in C. */ diff --git a/src/cJSON.h b/src/cJSON.h index 1e388137e..2a6139680 100644 --- a/src/cJSON.h +++ b/src/cJSON.h @@ -20,6 +20,21 @@ THE SOFTWARE. */ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef cJSON__h #define cJSON__h diff --git a/src/cc/CC made easy.md b/src/cc/CC made easy.md index 3f15a6b6b..2d1081003 100644 --- a/src/cc/CC made easy.md +++ b/src/cc/CC made easy.md @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -212,7 +212,7 @@ bool FaucetExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction bool FaucetValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx) -int64_t AddFaucetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs) +int64_t AddFaucetInputs(struct CCcontract_infoCC_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs) std::string FaucetGet(uint64_t txfee) diff --git a/src/cc/CCGateways.h b/src/cc/CCGateways.h index 2470665d4..b629ade1f 100644 --- a/src/cc/CCGateways.h +++ b/src/cc/CCGateways.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cc/CCHeir.h b/src/cc/CCHeir.h index 9a8193428..30334f6e1 100644 --- a/src/cc/CCHeir.h +++ b/src/cc/CCHeir.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -18,12 +18,24 @@ #define CC_HEIR_H #include "CCinclude.h" +#include "CCtokens.h" -#define EVAL_HEIR 0xea +//#define EVAL_HEIR 0xea bool HeirValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn); -// CCcustom -UniValue HeirInfo(); +class CoinHelper; +class TokenHelper; + +UniValue HeirFundCoinCaller(int64_t txfee, int64_t satoshis, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid); +UniValue HeirFundTokenCaller(int64_t txfee, int64_t satoshis, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid); +UniValue HeirClaimCaller(uint256 fundingtxid, int64_t txfee, std::string amount); +UniValue HeirAddCaller(uint256 fundingtxid, int64_t txfee, std::string amount); + +UniValue HeirInfo(uint256 fundingtxid); +UniValue HeirList(); +//std::string Heir_MakeBadTx(uint256 fundingtxid, uint8_t funcId, int64_t amount, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTime, uint32_t errMask); + +//bool HeirExactTokenAmounts(bool compareTotals, struct CCcontract_info *cpHeir, Eval* eval, uint256 assetid, const CTransaction &tx); #endif diff --git a/src/cc/CCMarmara.h b/src/cc/CCMarmara.h new file mode 100644 index 000000000..65269df77 --- /dev/null +++ b/src/cc/CCMarmara.h @@ -0,0 +1,46 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + + +#ifndef CC_TRIGGERS_H +#define CC_TRIGGERS_H + +#include "CCinclude.h" +#include "../komodo_cJSON.h" + +#define MARMARA_GROUPSIZE 60 +#define MARMARA_MINLOCK (1440 * 3 * 30) +#define MARMARA_MAXLOCK (1440 * 24 * 30) +#define MARMARA_VINS 16 + +extern uint8_t ASSETCHAINS_MARMARA; +uint64_t komodo_block_prg(uint32_t nHeight); +int32_t MarmaraGetcreatetxid(uint256 &createtxid,uint256 txid); +int32_t MarmaraGetbatontxid(std::vector &creditloop,uint256 &batontxid,uint256 txid); +UniValue MarmaraCreditloop(uint256 txid); +UniValue MarmaraSettlement(uint64_t txfee,uint256 batontxid); +UniValue MarmaraLock(uint64_t txfee,int64_t amount,int32_t height); + +UniValue MarmaraPoolPayout(uint64_t txfee,int32_t firstheight,double perc,char *jsonstr); // [[pk0, shares0], [pk1, shares1], ...] +UniValue MarmaraReceive(uint64_t txfee,CPubKey senderpk,int64_t amount,std::string currency,int32_t matures,uint256 batontxid,bool automaticflag); +UniValue MarmaraIssue(uint64_t txfee,uint8_t funcid,CPubKey receiverpk,int64_t amount,std::string currency,int32_t matures,uint256 approvaltxid,uint256 batontxid); +UniValue MarmaraInfo(CPubKey refpk,int32_t firstheight,int32_t lastheight,int64_t minamount,int64_t maxamount,std::string currency); + +bool MarmaraValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn); + +// CCcustom +UniValue MarmaraInfo(); + +#endif diff --git a/src/cc/CCOracles.h b/src/cc/CCOracles.h index 5e2fcc8b9..7f952e5f5 100644 --- a/src/cc/CCOracles.h +++ b/src/cc/CCOracles.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cc/CCPayments.h b/src/cc/CCPayments.h index 18f6cb7ef..187d9c9ad 100644 --- a/src/cc/CCPayments.h +++ b/src/cc/CCPayments.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cc/CCPegs.h b/src/cc/CCPegs.h index 0e20d278f..8d2a268f1 100644 --- a/src/cc/CCPegs.h +++ b/src/cc/CCPegs.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cc/CCPrices.h b/src/cc/CCPrices.h index 55877cce0..1a68be7dd 100644 --- a/src/cc/CCPrices.h +++ b/src/cc/CCPrices.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cc/CCTriggers.h b/src/cc/CCTriggers.h deleted file mode 100644 index bd243842f..000000000 --- a/src/cc/CCTriggers.h +++ /dev/null @@ -1,27 +0,0 @@ -/****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * - * * - * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * - * the top-level directory of this distribution for the individual copyright * - * holder information and the developer policies on copyright and licensing. * - * * - * Unless otherwise agreed in a custom licensing agreement, no part of the * - * SuperNET software, including this file may be copied, modified, propagated * - * or distributed except according to the terms contained in the LICENSE file * - * * - * Removal or modification of this copyright notice is prohibited. * - * * - ******************************************************************************/ - - -#ifndef CC_TRIGGERS_H -#define CC_TRIGGERS_H - -#include "CCinclude.h" - -bool TriggersValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn); - -// CCcustom -UniValue TriggersInfo(); - -#endif diff --git a/src/cc/CCassets.h b/src/cc/CCassets.h index 67bed7941..69fcfacbb 100644 --- a/src/cc/CCassets.h +++ b/src/cc/CCassets.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -30,12 +30,12 @@ bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx // CCassetsCore //CTxOut MakeAssetsVout(CAmount nValue,CPubKey pk); -CScript EncodeAssetCreateOpRet(uint8_t funcid,std::vector origpubkey,std::string name,std::string description); -CScript EncodeAssetOpRet(uint8_t funcid,uint256 assetid,uint256 assetid2,int64_t price,std::vector origpubkey); -bool DecodeAssetCreateOpRet(const CScript &scriptPubKey,std::vector &origpubkey,std::string &name,std::string &description); -uint8_t DecodeAssetOpRet(const CScript &scriptPubKey,uint256 &assetid,uint256 &assetid2,int64_t &price,std::vector &origpubkey); +//CScript EncodeAssetCreateOpRet(uint8_t funcid,std::vector origpubkey,std::string name,std::string description); +//CScript EncodeAssetOpRet(uint8_t assetFuncId, uint256 tokenid, uint256 assetid2, int64_t price, std::vector origpubkey); +//bool DecodeAssetCreateOpRet(const CScript &scriptPubKey,std::vector &origpubkey,std::string &name,std::string &description); +//uint8_t DecodeAssetOpRet(const CScript &scriptPubKey, uint8_t &evalCode, uint256 &assetid, uint256 &assetid2, int64_t &price, std::vector &origpubkey); bool SetAssetOrigpubkey(std::vector &origpubkey,int64_t &price,const CTransaction &tx); -int64_t IsAssetvout(int32_t maxAssetExactAmountDepth, struct CCcontract_info *cp, Eval* eval, int64_t &price,std::vector &origpubkey,const CTransaction& tx,int32_t v,uint256 refassetid); +int64_t IsAssetvout(struct CCcontract_info *cp, int64_t &price, std::vector &origpubkey, const CTransaction& tx, int32_t v, uint256 refassetid); bool ValidateBidRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice); bool ValidateAskRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice); bool ValidateSwapRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice); @@ -44,18 +44,18 @@ bool SetAskFillamounts(int64_t &paid,int64_t &remaining_price,int64_t orig_nValu bool SetSwapFillamounts(int64_t &paid,int64_t &remaining_price,int64_t orig_nValue,int64_t &received,int64_t totalprice); int64_t AssetValidateBuyvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpprice,std::vector &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 refassetid); int64_t AssetValidateSellvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpprice,std::vector &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 assetid); -bool AssetExactAmounts(int32_t maxDepth, struct CCcontract_info *cp,int64_t &inputs,int32_t starti,int64_t &outputs,Eval* eval,const CTransaction &tx,uint256 assetid); -//bool AssetExactAmounts(bool doValidateTx, struct CCcontract_info *cp, int64_t &inputs, int32_t starti, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 assetid, std::vector &ccVinsTxs); +bool AssetCalcAmounts(struct CCcontract_info *cpAssets, int64_t &inputs, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 assetid); // CCassetstx -int64_t GetAssetBalance(CPubKey pk,uint256 tokenid); -int64_t AddAssetInputs(CMutableTransaction &mtx,CPubKey pk,uint256 assetid,int64_t total,int32_t maxinputs); +//int64_t GetAssetBalance(CPubKey pk,uint256 tokenid); // --> GetTokenBalance() +int64_t AddAssetInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 assetid, int64_t total, int32_t maxinputs); + UniValue AssetOrders(uint256 tokenid); -UniValue AssetInfo(uint256 tokenid); -UniValue AssetList(); -std::string CreateAsset(int64_t txfee,int64_t assetsupply,std::string name,std::string description); -std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector destpubkey,int64_t total); -std::string AssetConvert(int64_t txfee,uint256 assetid,std::vector destpubkey,int64_t total,int32_t evalcode); +//UniValue AssetInfo(uint256 tokenid); +//UniValue AssetList(); +//std::string CreateAsset(int64_t txfee,int64_t assetsupply,std::string name,std::string description); +//std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector destpubkey,int64_t total); +//std::string AssetConvert(int64_t txfee,uint256 assetid,std::vector destpubkey,int64_t total,int32_t evalcode); std::string CreateBuyOffer(int64_t txfee,int64_t bidamount,uint256 assetid,int64_t pricetotal); std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid); diff --git a/src/cc/CCassetsCore.cpp b/src/cc/CCassetsCore.cpp index 3fce95f0c..1b8e46189 100644 --- a/src/cc/CCassetsCore.cpp +++ b/src/cc/CCassetsCore.cpp @@ -33,7 +33,7 @@ Yes, this is quite confusing... - In ValudateAssetRemainder the naming convention is nValue is the coin/asset with the offer on the books and "units" is what it is being paid in. The high level check is to make sure we didnt lose any coins or assets, the harder to validate is the actual price paid as the "orderbook" is in terms of the combined nValue for the combined totalunits. + In ValidateAssetRemainder the naming convention is nValue is the coin/asset with the offer on the books and "units" is what it is being paid in. The high level check is to make sure we didnt lose any coins or assets, the harder to validate is the actual price paid as the "orderbook" is in terms of the combined nValue for the combined totalunits. We assume that the effective unit cost in the orderbook is valid and that that amount was paid and also that any remainder will be close enough in effective unit cost to not matter. At the edge cases, this will probably be not true and maybe some orders wont be practically fillable when reduced to fractional state. However, the original pubkey that created the offer can always reclaim it. */ @@ -230,38 +230,43 @@ bool ValidateSwapRemainder(int64_t remaining_price,int64_t remaining_nValue,int6 return(true); } +/* use EncodeTokenCreateOpRet instead: CScript EncodeAssetCreateOpRet(uint8_t funcid,std::vector origpubkey,std::string name,std::string description) { CScript opret; uint8_t evalcode = EVAL_ASSETS; opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << origpubkey << name << description); return(opret); } +*/ -CScript EncodeAssetOpRet(uint8_t funcid,uint256 assetid,uint256 assetid2,int64_t price,std::vector origpubkey) +CScript EncodeAssetOpRet(uint8_t assetFuncId, uint256 assetid2, int64_t price, std::vector origpubkey) { - CScript opret; uint8_t evalcode = EVAL_ASSETS; - assetid = revuint256(assetid); - switch ( funcid ) + CScript opret; + uint8_t evalcode = EVAL_ASSETS; + + switch ( assetFuncId ) { - case 't': case 'x': case 'o': - opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << assetid); + //case 't': this cannot be here + case 'x': case 'o': + opret << OP_RETURN << E_MARSHAL(ss << evalcode << assetFuncId); break; case 's': case 'b': case 'S': case 'B': - opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << assetid << price << origpubkey); + opret << OP_RETURN << E_MARSHAL(ss << evalcode << assetFuncId << price << origpubkey); break; case 'E': case 'e': assetid2 = revuint256(assetid2); - opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << assetid << assetid2 << price << origpubkey); + opret << OP_RETURN << E_MARSHAL(ss << evalcode << assetFuncId << assetid2 << price << origpubkey); break; default: - fprintf(stderr,"EncodeOpRet: illegal funcid.%02x\n",funcid); + fprintf(stderr,"EncodeAssetOpRet: illegal funcid.%02x\n", assetFuncId); opret << OP_RETURN; break; } return(opret); } -bool DecodeAssetCreateOpRet(const CScript &scriptPubKey,std::vector &origpubkey,std::string &name,std::string &description) +/* it is for compatibility, do not use this for new contracts (use DecodeTokenCreateOpRet) +bool DecodeAssetCreateOpRet(const CScript &scriptPubKey, std::vector &origpubkey, std::string &name, std::string &description) { std::vector vopret; uint8_t evalcode,funcid,*script; GetOpReturnData(scriptPubKey, vopret); @@ -272,173 +277,187 @@ bool DecodeAssetCreateOpRet(const CScript &scriptPubKey,std::vector &or return(true); } return(0); -} +} */ -uint8_t DecodeAssetOpRet(const CScript &scriptPubKey,uint256 &assetid,uint256 &assetid2,int64_t &price,std::vector &origpubkey) +uint8_t DecodeAssetTokenOpRet(const CScript &scriptPubKey, uint8_t &evalCodeInOpret, uint256 &tokenid, uint256 &assetid2, int64_t &price, std::vector &origpubkey) { - std::vector vopret; uint8_t funcid=0,*script,e,f; - GetOpReturnData(scriptPubKey, vopret); + std::vector vopretExtra, vopretStripped; + uint8_t *script, funcId = 0, assetFuncId = 0, dummyEvalCode, dummyAssetFuncId; + uint256 dummyTokenid; + std::vector voutPubkeysDummy; + + tokenid = zeroid; + assetid2 = zeroid; + price = 0; + + // First - decode token opret: + funcId = DecodeTokenOpRet(scriptPubKey, evalCodeInOpret, tokenid, voutPubkeysDummy, vopretExtra); + + /*GetOpReturnData(scriptPubKey, vopret); script = (uint8_t *)vopret.data(); - memset(&assetid,0,sizeof(assetid)); - memset(&assetid2,0,sizeof(assetid2)); - price = 0; - if ( script != 0 && script[0] == EVAL_ASSETS ) - { - funcid = script[1]; - //fprintf(stderr,"decode.[%c]\n",funcid); - switch ( funcid ) + if (script == 0) { + std::cerr << "DecodeAssetOpRet() script is empty" << std::endl; + return (uint8_t)0; + }*/ + //bool isEof = true; // NOTE: if parse error occures, parse might not be able to set error. It is safer to treat that it was eof if it is not set! + //bool result = E_UNMARSHAL(vopret, ss >> evalCodeInOpret; ss >> funcId; ss >> tokenid; ss >> assetFuncId; isEof = ss.eof()); + + if (funcId == 0 || vopretExtra.size() < 2) { + std::cerr << "DecodeAssetOpRet() incorrect opret or no asset's payload" << " funcId=" << (int)funcId << " vopretExtra.size()=" << vopretExtra.size() << std::endl; + return (uint8_t)0; + } + + if (!E_UNMARSHAL(vopretExtra, { ss >> vopretStripped; })) { //strip string size + std::cerr << "DecodeAssetTokenOpRet() could not unmarshal vopretStripped" << std::endl; + return (uint8_t)0; + } + + ////tokenid = revuint256(tokenid); already done in DecodeToken! + evalCodeInOpret = vopretStripped.begin()[0]; + assetFuncId = vopretStripped.begin()[1]; + + //std::cerr << "DecodeAssetOpRet() evalCodeInOpret=" << (int)evalCodeInOpret << " funcId=" << (char)(funcId ? funcId : ' ') << " assetFuncId=" << (char)(assetFuncId ? assetFuncId : ' ') << std::endl; + + if(evalCodeInOpret == EVAL_ASSETS) + { + //fprintf(stderr,"decode.[%c] assetFuncId.[%c]\n", funcId, assetFuncId); + switch( assetFuncId ) { - case 'c': return(funcid); - break; - case 't': case 'x': case 'o': - if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> assetid) != 0 ) + case 'x': case 'o': + if (vopretStripped.size() == 2) // no data after 'evalcode assetFuncId' allowed { - assetid = revuint256(assetid); - return(funcid); + return(assetFuncId); } break; case 's': case 'b': case 'S': case 'B': - if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> assetid; ss >> price; ss >> origpubkey) != 0 ) + if (E_UNMARSHAL(vopretStripped, ss >> dummyEvalCode; ss >> dummyAssetFuncId; ss >> price; ss >> origpubkey) != 0) { - assetid = revuint256(assetid); - //fprintf(stderr,"got price %llu\n",(long long)price); - return(funcid); + //fprintf(stderr,"DecodeAssetTokenOpRet got price %llu\n",(long long)price); + return(assetFuncId); } break; case 'E': case 'e': - if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> assetid; ss >> assetid2; ss >> price; ss >> origpubkey) != 0 ) + if ( E_UNMARSHAL(vopretStripped, ss >> dummyEvalCode; ss >> dummyAssetFuncId; ss >> assetid2; ss >> price; ss >> origpubkey) != 0 ) { - //fprintf(stderr,"got price %llu\n",(long long)price); - assetid = revuint256(assetid); + //fprintf(stderr,"DecodeAssetTokenOpRet got price %llu\n",(long long)price); assetid2 = revuint256(assetid2); - return(funcid); + return(assetFuncId); } break; default: - fprintf(stderr,"DecodeAssetOpRet: illegal funcid.%02x\n",funcid); - funcid = 0; + fprintf(stderr,"DecodeAssetTokenOpRet: illegal assetFuncId.%02x\n", assetFuncId); + //funcId = 0; break; } } - return(funcid); + return (uint8_t)0; } +// extract sell/buy owner's pubkey from the opret bool SetAssetOrigpubkey(std::vector &origpubkey,int64_t &price,const CTransaction &tx) { uint256 assetid,assetid2; - if ( tx.vout.size() > 0 && DecodeAssetOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,assetid,assetid2,price,origpubkey) != 0 ) + uint8_t evalCode; + if ( tx.vout.size() > 0 && DecodeAssetTokenOpRet(tx.vout[tx.vout.size()-1].scriptPubKey, evalCode, assetid, assetid2, price, origpubkey) != 0 ) return(true); - else return(false); + else + return(false); } - -bool GetAssetorigaddrs(struct CCcontract_info *cp,char *CCaddr,char *destaddr,const CTransaction& tx) + +// Calculate sell/buy owner's source token/asset address from ask/bid tx +bool GetAssetorigaddrs(struct CCcontract_info *cp, char *userCCaddr, char *destaddr, const CTransaction& tx) { - uint256 assetid,assetid2; int64_t price,nValue=0; int32_t n; uint8_t funcid; std::vector origpubkey; CScript script; + uint256 assetid,assetid2; int64_t price,nValue=0; int32_t n; uint8_t funcid; + std::vector origpubkey; + CScript script; + uint8_t evalCode; + n = tx.vout.size(); - if ( n == 0 || (funcid= DecodeAssetOpRet(tx.vout[n-1].scriptPubKey,assetid,assetid2,price,origpubkey)) == 0 ) + if( n == 0 || (funcid = DecodeAssetTokenOpRet(tx.vout[n-1].scriptPubKey, evalCode, assetid, assetid2, price, origpubkey)) == 0 ) return(false); - if ( GetCCaddress(cp,CCaddr,pubkey2pk(origpubkey)) != 0 && Getscriptaddress(destaddr,CScript() << origpubkey << OP_CHECKSIG) != 0 ) + + bool bGetCCaddr = false; + if (funcid == 's' || funcid == 'S') { + struct CCcontract_info *cpTokens, tokensC; + cpTokens = CCinit(&tokensC, EVAL_TOKENS); + bGetCCaddr = GetCCaddress(cpTokens, userCCaddr, pubkey2pk(origpubkey)); + //bGetCCaddr = GetTokensCCaddress(cp, CCaddr, pubkey2pk(origpubkey)); + } + else if (funcid == 'b' || funcid == 'B') { + struct CCcontract_info *cpTokens, tokensC; + cpTokens = CCinit(&tokensC, EVAL_TOKENS); + bGetCCaddr = GetCCaddress(cpTokens, userCCaddr, pubkey2pk(origpubkey)); + } + else { + std::cerr << "GetAssetorigaddrs incorrect funcid=" << (char)(funcid?funcid:' ') << std::endl; + return false; + } + + if( bGetCCaddr && Getscriptaddress(destaddr, CScript() << origpubkey << OP_CHECKSIG)) return(true); - else return(false); + else + return(false); } -// Checks if the vout is a really Asset CC vout -// if maxAssetExactAmountDepth > 0, it also validates the vin transaction itself: -// it should be either sum(cc vins) == sum(cc vouts) or the transaction is the 'tokenbase' ('c') tx -int64_t IsAssetvout(int32_t maxAssetExactAmountDepth, struct CCcontract_info *cp, Eval* eval, int64_t &price,std::vector &origpubkey,const CTransaction& tx,int32_t v,uint256 refassetid) -{ - uint256 assetid,assetid2; int64_t nValue=0; int32_t n; uint8_t funcid; - - if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) // maybe check address too? - { - - if (maxAssetExactAmountDepth > 0) { - //validate all tx - int64_t myCCVinsAmount = 0, myCCVoutsAmount = 0; - std::vector ccVinsTxs; - - //std::cerr << "IsAssetvout() validate=yes" << std::endl; - const bool validateVinTxs = false; - bool isEqualAmounts = AssetExactAmounts(maxAssetExactAmountDepth, cp, myCCVinsAmount, 0, myCCVoutsAmount, eval, tx, refassetid); - - // if ccInputs != ccOutputs and it is not the tokenbase tx means it is possibly fake tx (dimxy): - if (!isEqualAmounts && refassetid != tx.GetHash()) { // checking that this is the true tokenbase tx, by verifying that funcid=c, is done further in this function (dimxy) - std::cerr << "IsAssetvout() detected bad tx=" << tx.GetHash().GetHex() << ": cc inputs != cc outputs and not the 'tokenbase' tx" << std::endl; - return 0; - } - } - - - n = tx.vout.size(); - if (v >= n - 1) { // just moved this up (dimxy) - std::cerr << "isAssetVout() internal err: (v >= n - 1), returning 0" << std::endl; - return(0); - } - nValue = tx.vout[v].nValue; - - // fprintf(stderr,"IsAssetvout() CC vout v.%d of n=%d amount=%.8f\n",v,n,(double)nValue/COIN); - - if ( (funcid= DecodeAssetOpRet(tx.vout[n-1].scriptPubKey,assetid,assetid2,price,origpubkey)) == 0 ) - { - fprintf(stderr,"IsAssetvout() null decodeopret v.%d\n",v); - return(0); - } - else if ( funcid == 'c' ) - { - if (refassetid == tx.GetHash() && v == 0) { - std::cerr << "isAssetVout() this is the tokenbase 'c' tx, txid=" << tx.GetHash().GetHex() << " returning nValue=" << nValue << std::endl; - return(nValue); - } - } - else if ( (funcid == 'b' || funcid == 'B') && v == 0 ) // critical! 'b'/'B' vout0 is NOT asset - return(0); - else if ( funcid != 'E' ) - { - if ( assetid == refassetid ) - { - fprintf(stderr,"IsAssetvout() returning %.8f\n",(double)nValue/COIN); - return(nValue); - } - } - else if ( funcid == 'E' ) - { - if ( v < 2 && assetid == refassetid ) - return(nValue); - else if ( v == 2 && assetid2 == refassetid ) - return(nValue); - } - } - //fprintf(stderr,"Isassetvout: normal output v.%d %.8f\n",v,(double)tx.vout[v].nValue/COIN); - return(0); -} - int64_t AssetValidateCCvin(struct CCcontract_info *cp,Eval* eval,char *CCaddr,char *origaddr,const CTransaction &tx,int32_t vini,CTransaction &vinTx) { - uint256 hashBlock; char destaddr[64]; + uint256 hashBlock; + uint256 assetid, assetid2; + int64_t tmpprice; + std::vector tmporigpubkey; + uint8_t evalCode; + + char destaddr[64], unspendableAddr[64]; + origaddr[0] = destaddr[0] = CCaddr[0] = 0; - if ( tx.vin.size() < 2 ) + + uint8_t funcid = 0; + if (tx.vout.size() > 0) { + uint256 assetid, assetid2; + int64_t tmpprice; + std::vector tmporigpubkey; + uint8_t evalCode; + funcid = DecodeAssetTokenOpRet(tx.vout[tx.vout.size() - 1].scriptPubKey, evalCode, assetid, assetid2, tmpprice, tmporigpubkey); + } + + if( tx.vin.size() < 2 ) return eval->Invalid("not enough for CC vins"); - else if ( tx.vin[vini].prevout.n != 0 ) + else if( tx.vin[vini].prevout.n != 0 ) return eval->Invalid("vin1 needs to be buyvin.vout[0]"); - else if ( eval->GetTxUnconfirmed(tx.vin[vini].prevout.hash,vinTx,hashBlock) == 0 ) + else if( eval->GetTxUnconfirmed(tx.vin[vini].prevout.hash, vinTx,hashBlock) == 0 ) { - int32_t z; + /* int32_t z; for (z=31; z>=0; z--) fprintf(stderr,"%02x",((uint8_t *)&tx.vin[vini].prevout.hash)[z]); - fprintf(stderr," vini.%d\n",vini); + fprintf(stderr," vini.%d\n",vini); */ + std::cerr << "AssetValidateCCvin cannot load vintx for vin=" << vini << " vintx id=" << tx.vin[vini].prevout.hash.GetHex() << std::endl; return eval->Invalid("always should find CCvin, but didnt"); } - else if ( Getscriptaddress(destaddr,vinTx.vout[tx.vin[vini].prevout.n].scriptPubKey) == 0 || strcmp(destaddr,(char *)cp->unspendableCCaddr) != 0 ) + // if fillSell or cancelSell --> to spend tokens from dual-eval token-assets unspendable addr + else if( (funcid == 'S' || funcid == 'x') && + (Getscriptaddress(destaddr, vinTx.vout[tx.vin[vini].prevout.n].scriptPubKey) == 0 || + !GetTokensCCaddress(cp, unspendableAddr, GetUnspendable(cp, NULL)) || + strcmp(destaddr, unspendableAddr) != 0)) { - fprintf(stderr,"%s vs %s\n",destaddr,(char *)cp->unspendableCCaddr); + fprintf(stderr,"AssetValidateCCvin cc addr %s is not dual token-evalcode=0x%02x asset unspendable addr %s\n", destaddr, (int)cp->evalcode, unspendableAddr); return eval->Invalid("invalid vin AssetsCCaddr"); } + // if fillBuy or cancelBuy --> to spend coins from asset unspendable addr + else if ((funcid == 'B' || funcid == 'o') && + (Getscriptaddress(destaddr, vinTx.vout[tx.vin[vini].prevout.n].scriptPubKey) == 0 || + !GetCCaddress(cp, unspendableAddr, GetUnspendable(cp, NULL)) || + strcmp(destaddr, unspendableAddr) != 0)) + { + fprintf(stderr, "AssetValidateCCvin cc addr %s is not evalcode=0x%02x asset unspendable addr %s\n", destaddr, (int)cp->evalcode, unspendableAddr); + return eval->Invalid("invalid vin AssetsCCaddr"); + } + //else if ( vinTx.vout[0].nValue < 10000 ) // return eval->Invalid("invalid dust for buyvin"); - else if ( GetAssetorigaddrs(cp,CCaddr,origaddr,vinTx) == 0 ) + else if( GetAssetorigaddrs(cp, CCaddr, origaddr, vinTx) == 0 ) return eval->Invalid("couldnt get origaddr for buyvin"); - fprintf(stderr,"Got %.8f to origaddr.(%s)\n",(double)vinTx.vout[tx.vin[vini].prevout.n].nValue/COIN,origaddr); + fprintf(stderr,"AssetValidateCCvin got %.8f to origaddr.(%s)\n",(double)vinTx.vout[tx.vin[vini].prevout.n].nValue/COIN,origaddr); if ( vinTx.vout[0].nValue == 0 ) return eval->Invalid("null value CCvin"); return(vinTx.vout[0].nValue); @@ -446,16 +465,21 @@ int64_t AssetValidateCCvin(struct CCcontract_info *cp,Eval* eval,char *CCaddr,ch int64_t AssetValidateBuyvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpprice,std::vector &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 refassetid) { - CTransaction vinTx; int64_t nValue; uint256 assetid,assetid2; uint8_t funcid; + CTransaction vinTx; int64_t nValue; uint256 assetid,assetid2; uint8_t funcid, evalCode; CCaddr[0] = origaddr[0] = 0; - if ( (nValue= AssetValidateCCvin(cp,eval,CCaddr,origaddr,tx,1,vinTx)) == 0 ) - return(0); + + // validate locked coins on Assets vin[1] + if ( (nValue= AssetValidateCCvin(cp, eval, CCaddr, origaddr, tx, 1, vinTx)) == 0 ) + return(0); else if ( vinTx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) return eval->Invalid("invalid normal vout0 for buyvin"); + else if ((funcid = DecodeAssetTokenOpRet(vinTx.vout[vinTx.vout.size() - 1].scriptPubKey, evalCode, assetid, assetid2, tmpprice, tmporigpubkey)) == 'b' && + vinTx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) // marker is only in 'b'? + return eval->Invalid("invalid normal vout1 for buyvin"); else { //fprintf(stderr,"have %.8f checking assetid origaddr.(%s)\n",(double)nValue/COIN,origaddr); - if ( vinTx.vout.size() > 0 && (funcid= DecodeAssetOpRet(vinTx.vout[vinTx.vout.size()-1].scriptPubKey,assetid,assetid2,tmpprice,tmporigpubkey)) != 'b' && funcid != 'B' ) + if ( vinTx.vout.size() > 0 && funcid != 'b' && funcid != 'B' ) return eval->Invalid("invalid opreturn for buyvin"); else if ( refassetid != assetid ) return eval->Invalid("invalid assetid for buyvin"); @@ -469,88 +493,162 @@ int64_t AssetValidateBuyvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmppr int64_t AssetValidateSellvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpprice,std::vector &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 assetid) { CTransaction vinTx; int64_t nValue,assetoshis; - fprintf(stderr,"AssetValidateSellvin\n"); - if ( (nValue= AssetValidateCCvin(cp,eval,CCaddr,origaddr,tx,1,vinTx)) == 0 ) + //fprintf(stderr,"AssetValidateSellvin\n"); + if ( (nValue = AssetValidateCCvin(cp, eval, CCaddr, origaddr, tx, 1, vinTx)) == 0 ) return(0); - if ( (assetoshis= IsAssetvout(1, cp, NULL, tmpprice,tmporigpubkey,vinTx,0,assetid)) == 0 ) + if ( (assetoshis= IsAssetvout(cp, tmpprice, tmporigpubkey, vinTx, 0, assetid)) == 0 ) return eval->Invalid("invalid missing CC vout0 for sellvin"); - else return(assetoshis); + else + return(assetoshis); } -// overload with additional params for deep tx validation (dimxy) -bool AssetExactAmounts(int maxDepth, struct CCcontract_info *cp, int64_t &inputs, int32_t starti, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 assetid) +// validates opret for asset tx: +bool ValidateAssetOpret(CTransaction tx, int32_t v, uint256 assetid, int64_t &price, std::vector &origpubkey) { + + uint256 assetidOpret, assetidOpret2; + uint8_t funcid, evalCode; + + // this is just for log messages indentation fur debugging recursive calls: + int32_t n = tx.vout.size(); + + if ((funcid = DecodeAssetTokenOpRet(tx.vout[n - 1].scriptPubKey, evalCode, assetidOpret, assetidOpret2, price, origpubkey)) == 0) + { + std::cerr << "ValidateAssetOpret() DecodeAssetTokenOpRet returned null for the opret for txid=" << tx.GetHash().GetHex() << std::endl; + return(false); + } +/* it is now on token level: + else if (funcid == 'c') + { + if (assetid != zeroid && assetid == tx.GetHash() && v == 0) { + //std::cerr << "ValidateAssetOpret() this is the tokenbase 'c' tx, txid=" << tx.GetHash().GetHex() << " vout=" << v << " returning true" << std::endl; + return(true); + } + } + else if (funcid == 't') // TODO: check if this new block does not influence IsAssetVout + { + //std::cerr << "ValidateAssetOpret() assetid=" << assetid.GetHex() << " assetIdOpret=" << assetidOpret.GetHex() << " txid=" << tx.GetHash().GetHex() << std::endl; + if (assetid != zeroid && assetid == assetidOpret) { + //std::cerr << "ValidateAssetOpret() this is a transfer 't' tx, txid=" << tx.GetHash().GetHex() << " vout=" << v << " returning true" << std::endl; + return(true); + } + } */ + //else if ((funcid == 'b' || funcid == 'B') && v == 0) // critical! 'b'/'B' vout0 is NOT asset + // return(false); + else if (funcid != 'E') + { + if (assetid != zeroid && assetidOpret == assetid) + { + //std::cerr << "ValidateAssetOpret() returns true for not 'E', funcid=" << (char)funcid << std::endl; + return(true); + } + } + else if (funcid == 'E') // NOTE: not implemented yet! + { + if (v < 2 && assetid != zeroid && assetidOpret == assetid) + return(true); + else if (v == 2 && assetid != zeroid && assetidOpret2 == assetid) + return(true); + } + + //std::cerr << "ValidateAssetOpret() return false funcid=" << (char)funcid << " assetid=" << assetid.GetHex() << " assetIdOpret=" << assetidOpret.GetHex() << " txid=" << tx.GetHash().GetHex() << std::endl; + return false; +} + +// Checks if the vout is a really Asset CC vout +// compareTotals == true, the func also validates the passed transaction itself: +// it should be either sum(cc vins) == sum(cc vouts) or the transaction is the 'tokenbase' ('c') tx +int64_t IsAssetvout(struct CCcontract_info *cp, int64_t &price, std::vector &origpubkey, const CTransaction& tx, int32_t v, uint256 refassetid) { - CTransaction vinTx; uint256 hashBlock,id,id2; int32_t i,flag,numvins,numvouts; int64_t assetoshis; std::vector tmporigpubkey; int64_t tmpprice; - numvins = tx.vin.size(); - numvouts = tx.vout.size(); - inputs = outputs = 0; - maxDepth--; + //std::cerr << "IsAssetvout() entered for txid=" << tx.GetHash().GetHex() << " v=" << v << " for assetid=" << refassetid.GetHex() << std::endl; - for (i=starti; iismyvin)(tx.vin[i].scriptSig) != 0 ) - { - //std::cerr << "AssetExactAmounts() eval is true=" << (eval != NULL) << " ismyvin=ok for_i=" << i << std::endl; - // we are really not inside validation! -- dimxy - if ( (eval && eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0) || (!eval && !myGetTransaction(tx.vin[i].prevout.hash, vinTx, hashBlock)) ) - { - fprintf(stderr,"AssetExactAmounts() cannot read vintx i.%d starti.%d numvins.%d\n", i,starti,numvins); - return (!eval) ? false : eval->Invalid("always should find vin, but didnt"); + if (tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0) // maybe check address too? dimxy: possibly no, because there are too many cases with different addresses here + { + int32_t n = tx.vout.size(); + // just check boundaries: + if (v >= n - 1) { // just moved this up (dimxy) + std::cerr << "isAssetVout() internal err: (v >= n - 1), returning 0" << std::endl; + return(0); + } - } // false means 'don't go deeper' -- dimxy - else if ( (assetoshis= IsAssetvout( maxDepth, cp, eval, tmpprice,tmporigpubkey,vinTx,tx.vin[i].prevout.n,assetid)) != 0 ) - { - fprintf(stderr,"AssetExactAmounts() vin%d %llu, ",i,(long long)assetoshis); - inputs += assetoshis; - } - else - { - if ( vinTx.vout[i].scriptPubKey.IsPayToCryptoCondition() != 0 && DecodeAssetOpRet(vinTx.vout[vinTx.vout.size()-1].scriptPubKey,id,id2,tmpprice,tmporigpubkey) == 't' && id == assetid ) - { - assetoshis = vinTx.vout[i].nValue; - fprintf(stderr,"AssetExactAmounts() vin%d assetoshis=%llu special case, ",i,(long long)assetoshis); - inputs += assetoshis; - } - } - } - } + // moved opret checking to this new reusable func (dimxy): + const bool valOpret = ValidateAssetOpret(tx, v, refassetid, price, origpubkey); + //std::cerr << "IsAssetvout() ValidateAssetOpret returned=" << std::boolalpha << valOpret << " for txid=" << tx.GetHash().GetHex() << " for assetid=" << refassetid.GetHex() << std::endl; + if (valOpret) { + //std::cerr << "IsAssetvout() ValidateAssetOpret returned true, returning nValue=" << tx.vout[v].nValue << " for txid=" << tx.GetHash().GetHex() << " for assetid=" << refassetid.GetHex() << std::endl; + return tx.vout[v].nValue; + } + //fprintf(stderr,"IsAssetvout() CC vout v.%d of n=%d amount=%.8f txid=%s\n",v,n,(double)0/COIN, tx.GetHash().GetHex().c_str()); + } + //fprintf(stderr,"IsAssetvout() normal output v.%d %.8f\n",v,(double)tx.vout[v].nValue/COIN); + return(0); +} - if ( DecodeAssetOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,id,id2,tmpprice,tmporigpubkey) == 't' && id == assetid ) - flag = 1; - else flag = 0; +// sets cc inputs vs cc outputs and ensures they are equal: +bool AssetCalcAmounts(struct CCcontract_info *cpAssets, int64_t &inputs, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 assetid) +{ + CTransaction vinTx; uint256 hashBlock, id, id2; int32_t flag; int64_t assetoshis; std::vector tmporigpubkey; int64_t tmpprice; + int32_t numvins = tx.vin.size(); + int32_t numvouts = tx.vout.size(); + inputs = outputs = 0; - for (i=0; iInvalid("always should find vin tx, but didnt"); + } + else { + // validate vouts of vintx + //std::cerr << indentStr << "AssetExactAmounts() check vin i=" << i << " nValue=" << vinTx.vout[tx.vin[i].prevout.n].nValue << std::endl; + //assetoshis = IsAssetvout(cpAssets, tmpprice, tmporigpubkey, vinTx, tx.vin[i].prevout.n, assetid); + std::vector vopretExtra; + std::vector vinPubkeysEmpty; + + // TODO: maybe we do not need call to IsTokensVout here, cause we've already selected token vins + assetoshis = IsTokensvout(false, false, cpTokens, NULL, vinTx, tx.vin[i].prevout.n, assetid); + if (assetoshis != 0) + { + std::cerr << "AssetCalcAmounts() vin i=" << i << " assetoshis=" << assetoshis << std::endl; + inputs += assetoshis; + } + } + } + } + + for (int32_t i = 0; i < numvouts; i++) + { + // Note: we pass in here 'false' because we don't need to call AssetExactAmounts() recursively from IsAssetvout + // indeed, in this case we'll be checking this tx again + assetoshis = IsAssetvout(cpAssets, tmpprice, tmporigpubkey, tx, i, assetid); + + if (assetoshis != 0) + { + std::cerr << "AssetCalcAmounts() vout i=" << i << " assetoshis=" << assetoshis << std::endl; + outputs += assetoshis; + } + } + + //std::cerr << "AssetCalcAmounts() inputs=" << inputs << " outputs=" << outputs << " for txid=" << tx.GetHash().GetHex() << std::endl; + + /* we do not verify inputs == outputs here, + it's done in Tokens: + if (inputs != outputs) { + if (tx.GetHash() != assetid) { + std::cerr << "AssetCalcAmounts() unequal inputs=" << inputs << " vs outputs=" << outputs << " for txid=" << tx.GetHash().GetHex() << std::endl; + return (!eval) ? false : eval->Invalid("assets cc inputs != cc outputs"); + } + } */ + return(true); } - -// overload for existing calls of this function (dimxy) -/*bool AssetExactAmounts(struct CCcontract_info *cp, int64_t &inputs, int32_t starti, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 assetid) { - std::vector ccVinsTxs; - - return AssetExactAmounts(true, cp, inputs, starti, outputs, eval, tx, assetid); -}*/ \ No newline at end of file diff --git a/src/cc/CCassetstx.cpp b/src/cc/CCassetstx.cpp index f96170267..9d83beb2c 100644 --- a/src/cc/CCassetstx.cpp +++ b/src/cc/CCassetstx.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -14,6 +14,8 @@ ******************************************************************************/ #include "CCassets.h" +//#include "CCtokens.h" + int64_t AddAssetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 assetid,int64_t total,int32_t maxinputs) { @@ -21,25 +23,31 @@ int64_t AddAssetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubK std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); SetCCunspents(unspentOutputs,coinaddr); - threshold = total/(maxinputs!=0?maxinputs:64); + + threshold = total/(maxinputs!=0?maxinputs:64); // TODO: is maxinputs really not over 64, what if i want to calc total balance? + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { txid = it->first.txhash; vout = (int32_t)it->first.index; - if ( it->second.satoshis < threshold ) + + if (it->second.satoshis < threshold) continue; + for (j=0; junspendableCCaddr) != 0 && strcmp(destaddr,cp->unspendableaddr2) != 0 ) + if( strcmp(destaddr,coinaddr) != 0 && strcmp(destaddr,cp->unspendableCCaddr) != 0 && strcmp(destaddr,cp->unspendableaddr2) != 0 ) continue; fprintf(stderr,"AddAssetInputs() check destaddress=%s vout amount=%.8f\n",destaddr,(double)vintx.vout[vout].nValue/COIN); - if ( (nValue= IsAssetvout(1, cp, NULL, price,origpubkey,vintx,vout,assetid)) > 0 && myIsutxo_spentinmempool(txid,vout) == 0 ) + if( (nValue = IsAssetvout(cp, price, origpubkey, vintx, vout, assetid)) > 0 && myIsutxo_spentinmempool(txid,vout) == 0 ) { if ( total != 0 && maxinputs != 0 ) mtx.vin.push_back(CTxIn(txid,vout,CScript())); @@ -57,72 +65,37 @@ int64_t AddAssetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubK return(totalinputs); } -int64_t GetAssetBalance(CPubKey pk,uint256 tokenid) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - struct CCcontract_info *cp,C; - cp = CCinit(&C,EVAL_ASSETS); - return(AddAssetInputs(cp,mtx,pk,tokenid,0,0)); -} - -UniValue AssetInfo(uint256 assetid) -{ - UniValue result(UniValue::VOBJ); uint256 hashBlock; CTransaction vintx; std::vector origpubkey; std::string name,description; char str[67],numstr[65]; - if ( GetTransaction(assetid,vintx,hashBlock,false) == 0 ) - { - fprintf(stderr,"cant find assetid\n"); - result.push_back(Pair("result","error")); - result.push_back(Pair("error","cant find assetid")); - return(result); - } - if ( vintx.vout.size() > 0 && DecodeAssetCreateOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,origpubkey,name,description) == 0 ) - { - fprintf(stderr,"assetid isnt assetcreation txid\n"); - result.push_back(Pair("result","error")); - result.push_back(Pair("error","assetid isnt assetcreation txid")); - } - result.push_back(Pair("result","success")); - result.push_back(Pair("tokenid",uint256_str(str,assetid))); - result.push_back(Pair("owner",pubkey33_str(str,origpubkey.data()))); - result.push_back(Pair("name",name)); - result.push_back(Pair("supply",vintx.vout[0].nValue)); - result.push_back(Pair("description",description)); - return(result); -} - -UniValue AssetList() -{ - UniValue result(UniValue::VARR); std::vector > addressIndex; struct CCcontract_info *cp,C; uint256 txid,hashBlock; CTransaction vintx; std::vector origpubkey; std::string name,description; char str[65]; - cp = CCinit(&C,EVAL_ASSETS); - SetCCtxids(addressIndex,cp->normaladdr); - for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) - { - txid = it->first.txhash; - if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) - { - if ( vintx.vout.size() > 0 && DecodeAssetCreateOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,origpubkey,name,description) != 0 ) - { - result.push_back(uint256_str(str,txid)); - } - } - } - return(result); -} UniValue AssetOrders(uint256 refassetid) { static uint256 zero; - int64_t price; uint256 txid,hashBlock,assetid,assetid2; std::vector origpubkey; CTransaction vintx; UniValue result(UniValue::VARR); std::vector > unspentOutputs; uint8_t funcid; char numstr[32],funcidstr[16],origaddr[64],assetidstr[65]; struct CCcontract_info *cp,C; - cp = CCinit(&C,EVAL_ASSETS); - SetCCunspents(unspentOutputs,(char *)cp->unspendableCCaddr); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { + UniValue result(UniValue::VARR); + std::vector > unspentOutputsTokens, unspentOutputsAssets; + + struct CCcontract_info *cpTokens, tokensC; + struct CCcontract_info *cpAssets, assetsC; + + cpTokens = CCinit(&tokensC, EVAL_TOKENS); + cpAssets = CCinit(&assetsC, EVAL_ASSETS); + + auto addOrders = [&](struct CCcontract_info *cp, std::vector >::const_iterator it) + { + uint256 txid, hashBlock, assetid, assetid2; + int64_t price; + std::vector origpubkey; + CTransaction vintx; + uint8_t funcid, evalCode; + char numstr[32], funcidstr[16], origaddr[64], assetidstr[65]; + txid = it->first.txhash; - if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) + //std::cerr << "addOrders() txid=" << txid.GetHex() << std::endl; + if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) { - if ( vintx.vout.size() > 0 && (funcid= DecodeAssetOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,assetid,assetid2,price,origpubkey)) != 0 ) + // for logging: funcid = DecodeAssetOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, evalCode, assetid, assetid2, price, origpubkey); + //std::cerr << "addOrders() vintx.vout.size()=" << vintx.vout.size() << " funcid=" << (char)(funcid ? funcid : ' ') << " assetid=" << assetid.GetHex() << std::endl; + if (vintx.vout.size() > 0 && (funcid = DecodeAssetTokenOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey, evalCode, assetid, assetid2, price, origpubkey)) != 0) { - if ( refassetid != zero && assetid != refassetid ) + if (refassetid != zero && assetid != refassetid) { //int32_t z; //for (z=31; z>=0; z--) fprintf(stderr,"%02x",((uint8_t *)&txid)[z]); @@ -131,11 +104,15 @@ UniValue AssetOrders(uint256 refassetid) //fprintf(stderr," assetid\n"); //for (z=31; z>=0; z--) fprintf(stderr,"%02x",((uint8_t *)&refassetid)[z]); //fprintf(stderr," refassetid\n"); - continue; + return; } - if ( vintx.vout[it->first.index].nValue == 0 ) - continue; + + //std::cerr << "addOrders() it->first.index=" << it->first.index << " vintx.vout[it->first.index].nValue=" << vintx.vout[it->first.index].nValue << std::endl; + if (vintx.vout[it->first.index].nValue == 0) + return; + UniValue item(UniValue::VOBJ); + funcidstr[0] = funcid; funcidstr[1] = 0; item.push_back(Pair("funcid", funcidstr)); @@ -157,8 +134,8 @@ UniValue AssetOrders(uint256 refassetid) } if ( origpubkey.size() == 33 ) { - GetCCaddress(cp,origaddr,pubkey2pk(origpubkey)); - item.push_back(Pair("origaddress",origaddr)); + GetCCaddress(cp, origaddr, pubkey2pk(origpubkey)); // TODO: what is this? is it asset or token?? + item.push_back(Pair("origaddress", origaddr)); } if ( assetid != zeroid ) item.push_back(Pair("tokenid",uint256_str(assetidstr,assetid))); @@ -181,14 +158,35 @@ UniValue AssetOrders(uint256 refassetid) } } result.push_back(item); - //fprintf(stderr,"func.(%c) %s/v%d %.8f\n",funcid,uint256_str(assetidstr,txid),(int32_t)it->first.index,(double)vintx.vout[it->first.index].nValue/COIN); + //fprintf(stderr,"addOrders() func.(%c) %s/v%d %.8f\n",funcid,uint256_str(assetidstr,txid),(int32_t)it->first.index,(double)vintx.vout[it->first.index].nValue/COIN); } } - } + }; + + + char assetsUnspendableAddr[64]; + GetCCaddress(cpAssets, assetsUnspendableAddr, GetUnspendable(cpAssets, NULL)); + SetCCunspents(unspentOutputsAssets, assetsUnspendableAddr /*(char *)cpTokens->unspendableCCaddr*/); + + char tokensUnspendableAddr[64]; + GetTokensCCaddress(cpAssets, tokensUnspendableAddr, GetUnspendable(cpAssets, NULL)); + SetCCunspents(unspentOutputsAssets, tokensUnspendableAddr /*(char *)cpAssets->unspendableCCaddr*/); + + for (std::vector >::const_iterator itTokens = unspentOutputsTokens.begin(); + itTokens != unspentOutputsTokens.end(); + itTokens++) + addOrders(cpTokens, itTokens); + + for (std::vector >::const_iterator itAssets = unspentOutputsAssets.begin(); + itAssets != unspentOutputsAssets.end(); + itAssets++) + addOrders(cpAssets, itAssets); + return(result); } -std::string CreateAsset(int64_t txfee,int64_t assetsupply,std::string name,std::string description) +// not used (use TokenCreate instead) +/* std::string CreateAsset(int64_t txfee,int64_t assetsupply,std::string name,std::string description) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CPubKey mypk; struct CCcontract_info *cp,C; @@ -213,9 +211,10 @@ std::string CreateAsset(int64_t txfee,int64_t assetsupply,std::string name,std:: return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeAssetCreateOpRet('c',Mypubkey(),name,description))); } return(""); -} - -std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector destpubkey,int64_t total) +} */ + +// not used (use TokenTransfer instead) +/* std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector destpubkey,int64_t total) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CPubKey mypk; uint64_t mask; int64_t CCchange=0,inputs=0; struct CCcontract_info *cp,C; @@ -230,11 +229,11 @@ std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector des mypk = pubkey2pk(Mypubkey()); if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) { - /*n = outputs.size(); - if ( n == amounts.size() ) - { - for (i=0; i 0 ) { @@ -254,9 +253,10 @@ std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector des //} else fprintf(stderr,"numoutputs.%d != numamounts.%d\n",n,(int32_t)amounts.size()); } return(""); -} +} */ -std::string AssetConvert(int64_t txfee,uint256 assetid,std::vector destpubkey,int64_t total,int32_t evalcode) +// deprecated +/* std::string AssetConvert(int64_t txfee,uint256 assetid,std::vector destpubkey,int64_t total,int32_t evalcode) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CPubKey mypk; int64_t CCchange=0,inputs=0; struct CCcontract_info *cp,C; @@ -281,76 +281,121 @@ std::string AssetConvert(int64_t txfee,uint256 assetid,std::vector dest } else fprintf(stderr,"not enough CC asset inputs for %.8f\n",(double)total/COIN); } return(""); -} +} */ -std::string CreateBuyOffer(int64_t txfee,int64_t bidamount,uint256 assetid,int64_t pricetotal) +// rpc tokenbid implementation, locks 'bidamount' coins for the 'pricetotal' of tokens +std::string CreateBuyOffer(int64_t txfee, int64_t bidamount, uint256 assetid, int64_t pricetotal) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk; struct CCcontract_info *cp,C; uint256 hashBlock; CTransaction vintx; std::vector origpubkey; std::string name,description; - if ( bidamount < 0 || pricetotal < 0 ) + CPubKey mypk; + struct CCcontract_info *cpAssets, C; + uint256 hashBlock; + CTransaction vintx; + std::vector origpubkey; + std::string name,description; + int64_t inputs; + + std::cerr << "CreateBuyOffer() bidamount=" << bidamount << " numtokens(pricetotal)=" << pricetotal << std::endl; + + if (bidamount < 0 || pricetotal < 0) { - fprintf(stderr,"negative bidamount %lld, pricetotal %lld\n",(long long)bidamount,(long long)pricetotal); + fprintf(stderr,"negative bidamount %lld, pricetotal %lld\n", (long long)bidamount, (long long)pricetotal); return(""); } - if ( GetTransaction(assetid,vintx,hashBlock,false) == 0 ) + if (GetTransaction(assetid, vintx, hashBlock, false) == 0) { fprintf(stderr,"cant find assetid\n"); return(""); } - if ( vintx.vout.size() > 0 && DecodeAssetCreateOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,origpubkey,name,description) == 0 ) + if (vintx.vout.size() > 0 && DecodeTokenCreateOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey, origpubkey, name, description) == 0) { fprintf(stderr,"assetid isnt assetcreation txid\n"); return(""); } - cp = CCinit(&C,EVAL_ASSETS); - if ( txfee == 0 ) + + cpAssets = CCinit(&C,EVAL_ASSETS); // NOTE: assets here! + if (txfee == 0) txfee = 10000; + mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,bidamount+txfee,64) > 0 ) + + if ((inputs = AddNormalinputs(mtx, mypk, bidamount+(2*txfee), 64)) > 0) { - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,bidamount,GetUnspendable(cp,0))); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeAssetOpRet('b',assetid,zeroid,pricetotal,Mypubkey()))); + std::cerr << "CreateBuyOffer() inputs=" << inputs << std::endl; + if (inputs < bidamount+txfee) { + std::cerr << "CreateBuyOffer(): insufficient coins to make buy offer" << std::endl; + CCerror = strprintf("insufficient coins to make buy offer"); + return (""); + } + + CPubKey unspendablePubkey = GetUnspendable(cpAssets, 0); + mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, bidamount, unspendablePubkey)); + mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, txfee, mypk)); + std::vector voutTokenPubkeys; // should be empty - no token vouts + + return(FinalizeCCTx(0, cpAssets, mtx, mypk, txfee, + EncodeTokenOpRet(assetid, voutTokenPubkeys, + EncodeAssetOpRet('b', zeroid, pricetotal, Mypubkey())))); } + CCerror = strprintf("no coins found to make buy offer"); return(""); } +// rpc tokenask implementation, locks 'askamount' tokens for the 'pricetotal' std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t pricetotal) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk; uint64_t mask; int64_t inputs,CCchange; CScript opret; struct CCcontract_info *cp,C; + CPubKey mypk; + uint64_t mask; + int64_t inputs, CCchange; + CScript opret; + struct CCcontract_info *cpAssets, assetsC; + struct CCcontract_info *cpTokens, tokensC; //std::cerr << "CreateSell() askamount=" << askamount << " pricetotal=" << pricetotal << std::endl; - if ( askamount < 0 || pricetotal < 0 ) - { + if (askamount < 0 || pricetotal < 0) { fprintf(stderr,"negative askamount %lld, askamount %lld\n",(long long)pricetotal,(long long)askamount); return(""); } - cp = CCinit(&C,EVAL_ASSETS); - if ( txfee == 0 ) + + cpAssets = CCinit(&assetsC, EVAL_ASSETS); // NOTE: this is for signing + + if (txfee == 0) txfee = 10000; + mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) + if (AddNormalinputs(mtx, mypk, 2*txfee, 3) > 0) { mask = ~((1LL << mtx.vin.size()) - 1); - if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,askamount,60)) > 0 ) + // add single-eval tokens: + cpTokens = CCinit(&tokensC, EVAL_TOKENS); // NOTE: tokens is here + if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, assetid, askamount, 60)) > 0) { if (inputs < askamount) { - //askamount = inputs; + //was: askamount = inputs; std::cerr << "CreateSell(): insufficient tokens for ask" << std::endl; + CCerror = strprintf("insufficient tokens for ask"); return (""); } - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,askamount,GetUnspendable(cp,0))); - if ( inputs > askamount ) + CPubKey unspendablePubkey = GetUnspendable(cpAssets, NULL); + mtx.vout.push_back(MakeTokensCC1vout(EVAL_ASSETS, askamount, unspendablePubkey)); + mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, txfee, mypk)); //marker + if (inputs > askamount) CCchange = (inputs - askamount); - if ( CCchange != 0 ) - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk)); - opret = EncodeAssetOpRet('s',assetid,zeroid,pricetotal,Mypubkey()); - return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,opret)); + if (CCchange != 0) + mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, CCchange, mypk)); // change to single-eval token vout + + std::vector voutTokenPubkeys; + voutTokenPubkeys.push_back(unspendablePubkey); + + opret = EncodeTokenOpRet(assetid, voutTokenPubkeys, + EncodeAssetOpRet('s', zeroid, pricetotal, Mypubkey())); + return(FinalizeCCTx(mask,cpAssets, mtx, mypk, txfee, opret)); } else { - fprintf(stderr, "need some assets to place ask\n"); + fprintf(stderr, "need some tokens to place ask\n"); } } else { // dimxy added 'else', because it was misleading message before @@ -359,39 +404,62 @@ std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t p return(""); } +////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 assetid2,int64_t pricetotal) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CPubKey mypk; uint64_t mask; int64_t inputs,CCchange; CScript opret; struct CCcontract_info *cp,C; + + ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// fprintf(stderr,"asset swaps disabled\n"); return(""); + ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// + if ( askamount < 0 || pricetotal < 0 ) { fprintf(stderr,"negative askamount %lld, askamount %lld\n",(long long)pricetotal,(long long)askamount); return(""); } - cp = CCinit(&C,EVAL_ASSETS); + cp = CCinit(&C, EVAL_ASSETS); + if ( txfee == 0 ) txfee = 10000; + ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) + + if (AddNormalinputs(mtx, mypk, txfee, 3) > 0) { mask = ~((1LL << mtx.vin.size()) - 1); - if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,askamount,60)) > 0 ) + if ((inputs = AddAssetInputs(cp, mtx, mypk, assetid, askamount, 60)) > 0) { - if ( inputs < askamount ) - askamount = inputs; - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,askamount,GetUnspendable(cp,0))); - if ( inputs > askamount ) + ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// + if (inputs < askamount) { + //was: askamount = inputs; + std::cerr << "CreateSwap(): insufficient tokens for ask" << std::endl; + CCerror = strprintf("insufficient tokens for ask"); + return (""); + } + ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// + CPubKey unspendablePubkey = GetUnspendable(cp, 0); + mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, askamount, unspendablePubkey)); + + if (inputs > askamount) CCchange = (inputs - askamount); - if ( CCchange != 0 ) - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk)); - if ( assetid2 == zeroid ) - opret = EncodeAssetOpRet('s',assetid,zeroid,pricetotal,Mypubkey()); - else - { - opret = EncodeAssetOpRet('e',assetid,assetid2,pricetotal,Mypubkey()); + if (CCchange != 0) + mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, CCchange, mypk)); + + ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// + std::vector voutTokenPubkeys; // should be empty - no token vouts + + if (assetid2 == zeroid) { + opret = EncodeTokenOpRet(assetid, voutTokenPubkeys, + EncodeAssetOpRet('s', zeroid, pricetotal, Mypubkey())); + } + else { + opret = EncodeTokenOpRet(assetid, voutTokenPubkeys, + EncodeAssetOpRet('e', assetid2, pricetotal, Mypubkey())); } + ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,opret)); } else { @@ -403,148 +471,306 @@ std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 a } return(""); -} +} ////////////////////////// NOT IMPLEMENTED YET///////////////////////////////// +// unlocks coins std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CTransaction vintx; uint64_t mask; uint256 hashBlock; int64_t bidamount; CPubKey mypk; struct CCcontract_info *cp,C; - cp = CCinit(&C,EVAL_ASSETS); - if ( txfee == 0 ) + CTransaction vintx; uint64_t mask; + uint256 hashBlock; int64_t bidamount; + CPubKey mypk; struct CCcontract_info *cpAssets, C; + uint8_t funcid,dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; std::vector dummyOrigpubkey; + + cpAssets = CCinit(&C, EVAL_ASSETS); + + if (txfee == 0) txfee = 10000; + mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) + + if (AddNormalinputs(mtx, mypk, txfee, 3) > 0) { mask = ~((1LL << mtx.vin.size()) - 1); - if ( GetTransaction(bidtxid,vintx,hashBlock,false) != 0 ) + if (GetTransaction(bidtxid, vintx, hashBlock, false) != 0) { bidamount = vintx.vout[0].nValue; - mtx.vin.push_back(CTxIn(bidtxid,0,CScript())); + mtx.vin.push_back(CTxIn(bidtxid, 0, CScript())); // coins in Assets + + if((funcid=DecodeAssetTokenOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey))!=0) + { + + if (funcid == 's') mtx.vin.push_back(CTxIn(bidtxid, 1, CScript())); // spend marker if funcid='b' + else if (funcid=='S') mtx.vin.push_back(CTxIn(bidtxid, 3, CScript())); // spend marker if funcid='B' + } + mtx.vout.push_back(CTxOut(bidamount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,EncodeAssetOpRet('o',assetid,zeroid,0,Mypubkey()))); + mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + + std::vector voutTokenPubkeys; // should be empty, no token vouts + + return(FinalizeCCTx(mask, cpAssets, mtx, mypk, txfee, + EncodeTokenOpRet(assetid, voutTokenPubkeys, + EncodeAssetOpRet('o', zeroid, 0, Mypubkey())))); } } return(""); } +//unlocks tokens std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CTransaction vintx; uint64_t mask; uint256 hashBlock; int64_t askamount; CPubKey mypk; struct CCcontract_info *cp,C; - cp = CCinit(&C,EVAL_ASSETS); - if ( txfee == 0 ) + CTransaction vintx; uint64_t mask; + uint256 hashBlock; int64_t askamount; + CPubKey mypk; struct CCcontract_info *cpTokens, *cpAssets, tokensC, assetsC; + uint8_t funcid,dummyEvalCode; uint256 dummyAssetid, dummyAssetid2; int64_t dummyPrice; std::vector dummyOrigpubkey; + + cpAssets = CCinit(&assetsC, EVAL_ASSETS); + + if (txfee == 0) txfee = 10000; + mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) + + if (AddNormalinputs(mtx, mypk, txfee, 3) > 0) { mask = ~((1LL << mtx.vin.size()) - 1); - if ( GetTransaction(asktxid,vintx,hashBlock,false) != 0 ) + if (GetTransaction(asktxid, vintx, hashBlock, false) != 0) { askamount = vintx.vout[0].nValue; - mtx.vin.push_back(CTxIn(asktxid,0,CScript())); - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,askamount,mypk)); - return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,EncodeAssetOpRet('x',assetid,zeroid,0,Mypubkey()))); + mtx.vin.push_back(CTxIn(asktxid, 0, CScript())); + + if ((funcid=DecodeAssetTokenOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, dummyEvalCode, dummyAssetid, dummyAssetid2, dummyPrice, dummyOrigpubkey))!=0) + { + if (funcid == 's') mtx.vin.push_back(CTxIn(asktxid, 1, CScript())); // marker if funcid='s' + else if (funcid=='S') mtx.vin.push_back(CTxIn(asktxid, 3, CScript())); // marker if funcid='S' + } + + mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, askamount, mypk)); // one-eval token vout + mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + + std::vector voutTokenPubkeys; + voutTokenPubkeys.push_back(mypk); + + /* char myCCaddr[65]; + uint8_t myPrivkey[32]; + Myprivkey(myPrivkey); + cpAssets = CCinit(&assetsC, EVAL_ASSETS); + GetCCaddress(cpAssets, myCCaddr, mypk); */ + + // this is only for unspendable addresses: + //CCaddr2set(cpTokens, EVAL_ASSETS, mypk, myPrivkey, myCCaddr); //do we need this? Seems FinalizeCCTx can attach to any evalcode cc addr by calling Getscriptaddress + + uint8_t unspendableAssetsPrivkey[32]; + char unspendableAssetsAddr[64]; + // init assets 'unspendable' privkey and pubkey + CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); + GetCCaddress(cpAssets, unspendableAssetsAddr, unspendableAssetsPk); + + // add additional eval-tokens unspendable assets privkey: + CCaddr2set(cpAssets, EVAL_TOKENS, unspendableAssetsPk, unspendableAssetsPrivkey, unspendableAssetsAddr); + + return(FinalizeCCTx(mask, cpAssets, mtx, mypk, txfee, + EncodeTokenOpRet(assetid, voutTokenPubkeys, + EncodeAssetOpRet('x', zeroid, 0, Mypubkey())))); } } return(""); } +//send tokens, receive coins: std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t fillamount) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CTransaction vintx; uint256 hashBlock; CPubKey mypk; std::vector origpubkey; int32_t bidvout=0; uint64_t mask; int64_t origprice,bidamount,paid_amount,remaining_required,inputs,CCchange=0; struct CCcontract_info *cp,C; - if ( fillamount < 0 ) + CTransaction vintx; + uint256 hashBlock; + CPubKey mypk; + std::vector origpubkey; + int32_t bidvout=0; + uint64_t mask; + int64_t origprice, bidamount, paid_amount, remaining_required, inputs, CCchange=0; + struct CCcontract_info *cpTokens, tokensC; + struct CCcontract_info *cpAssets, assetsC; + + if (fillamount < 0) { - fprintf(stderr,"negative fillamount %lld\n",(long long)fillamount); + fprintf(stderr,"negative fillamount %lld\n", (long long)fillamount); return(""); } - cp = CCinit(&C,EVAL_ASSETS); - if ( txfee == 0 ) + cpTokens = CCinit(&tokensC, EVAL_TOKENS); + + if (txfee == 0) txfee = 10000; + mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) + + if (AddNormalinputs(mtx, mypk, 2*txfee, 3) > 0) { mask = ~((1LL << mtx.vin.size()) - 1); - if ( GetTransaction(bidtxid,vintx,hashBlock,false) != 0 ) + if (GetTransaction(bidtxid, vintx, hashBlock, false) != 0) { bidamount = vintx.vout[bidvout].nValue; - SetAssetOrigpubkey(origpubkey,origprice,vintx); - mtx.vin.push_back(CTxIn(bidtxid,bidvout,CScript())); - if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,fillamount,60)) > 0 ) + SetAssetOrigpubkey(origpubkey, origprice, vintx); + + mtx.vin.push_back(CTxIn(bidtxid, bidvout, CScript())); // Coins on Assets unspendable + + if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, assetid, fillamount, 60)) > 0) { - if ( inputs < fillamount ) - fillamount = inputs; - SetBidFillamounts(paid_amount,remaining_required,bidamount,fillamount,origprice); - if ( inputs > fillamount ) + if (inputs < fillamount) { + std::cerr << "FillBuyOffer(): insufficient tokens to fill buy offer" << std::endl; + CCerror = strprintf("insufficient tokens to fill buy offer"); + return (""); + } + + SetBidFillamounts(paid_amount, remaining_required, bidamount, fillamount, origprice); + + if (inputs > fillamount) CCchange = (inputs - fillamount); - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,bidamount - paid_amount,GetUnspendable(cp,0))); - mtx.vout.push_back(CTxOut(paid_amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,fillamount,pubkey2pk(origpubkey))); - if ( CCchange != 0 ) - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk)); - fprintf(stderr,"remaining %llu -> origpubkey\n",(long long)remaining_required); - return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,EncodeAssetOpRet('B',assetid,zeroid,remaining_required,origpubkey))); - } else return("dont have any assets to fill bid\n"); + + uint8_t unspendableAssetsPrivkey[32]; + cpAssets = CCinit(&assetsC, EVAL_ASSETS); + CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); + + mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, bidamount - paid_amount, unspendableAssetsPk)); // vout0 coins remainder + mtx.vout.push_back(CTxOut(paid_amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); // vout1 coins to normal + mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, fillamount, pubkey2pk(origpubkey))); // vout2 single-eval tokens sent to the buyer + mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,txfee,origpubkey)); // vout3 marker to origpubkey + + if (CCchange != 0) + mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, CCchange, mypk)); // vout4 change in single-eval tokens + + fprintf(stderr,"FillBuyOffer remaining %llu -> origpubkey\n", (long long)remaining_required); + + char unspendableAssetsAddr[64]; + cpAssets = CCinit(&assetsC, EVAL_ASSETS); + GetCCaddress(cpAssets, unspendableAssetsAddr, unspendableAssetsPk); + + // add additional unspendable addr from Assets: + CCaddr2set(cpTokens, EVAL_ASSETS, unspendableAssetsPk, unspendableAssetsPrivkey, unspendableAssetsAddr); + + // token vout verification pubkeys: + std::vector voutTokenPubkeys; + voutTokenPubkeys.push_back(pubkey2pk(origpubkey)); + + return(FinalizeCCTx(mask,cpTokens,mtx,mypk,txfee, + EncodeTokenOpRet(assetid, voutTokenPubkeys, + EncodeAssetOpRet('B', zeroid, remaining_required, origpubkey)))); + } else return("dont have any assets to fill bid"); } } return("no normal coins left"); } -std::string FillSell(int64_t txfee,uint256 assetid,uint256 assetid2,uint256 asktxid,int64_t fillunits) + +// send coins, receive tokens +std::string FillSell(int64_t txfee, uint256 assetid, uint256 assetid2, uint256 asktxid, int64_t fillunits) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CTransaction vintx,filltx; uint256 hashBlock; CPubKey mypk; std::vector origpubkey; double dprice; uint64_t mask; int32_t askvout=0; int64_t received_assetoshis,total_nValue,orig_assetoshis,paid_nValue,remaining_nValue,inputs,CCchange=0; struct CCcontract_info *cp,C; - if ( fillunits < 0 ) + CTransaction vintx,filltx; + uint256 hashBlock; + CPubKey mypk; + std::vector origpubkey; + double dprice; + uint64_t mask = 0; + int32_t askvout = 0; + int64_t received_assetoshis, total_nValue, orig_assetoshis, paid_nValue, remaining_nValue, inputs, CCchange=0; + //struct CCcontract_info *cpTokens, tokensC; + struct CCcontract_info *cpAssets, assetsC; + + if (fillunits < 0) { CCerror = strprintf("negative fillunits %lld\n",(long long)fillunits); fprintf(stderr,"%s\n",CCerror.c_str()); return(""); } - if ( assetid2 != zeroid ) + if (assetid2 != zeroid) { CCerror = "asset swaps disabled"; fprintf(stderr,"%s\n",CCerror.c_str()); return(""); } - cp = CCinit(&C,EVAL_ASSETS); - if ( txfee == 0 ) + cpAssets = CCinit(&assetsC, EVAL_ASSETS); + + if (txfee == 0) txfee = 10000; + mypk = pubkey2pk(Mypubkey()); - if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) + if (AddNormalinputs(mtx, mypk, 2*txfee, 3) > 0) { mask = ~((1LL << mtx.vin.size()) - 1); - if ( GetTransaction(asktxid,vintx,hashBlock,false) != 0 ) + if (GetTransaction(asktxid, vintx, hashBlock, false) != 0) { orig_assetoshis = vintx.vout[askvout].nValue; - SetAssetOrigpubkey(origpubkey,total_nValue,vintx); + SetAssetOrigpubkey(origpubkey, total_nValue, vintx); dprice = (double)total_nValue / orig_assetoshis; paid_nValue = dprice * fillunits; - mtx.vin.push_back(CTxIn(asktxid,askvout,CScript())); - if ( assetid2 != zeroid ) - inputs = AddAssetInputs(cp,mtx,mypk,assetid2,paid_nValue,60); + + mtx.vin.push_back(CTxIn(asktxid, askvout, CScript())); // NOTE: this is the reference to tokens -> send cpTokens for signing into FinalizeCCTx! + + if (assetid2 != zeroid) + inputs = AddAssetInputs(cpAssets, mtx, mypk, assetid2, paid_nValue, 60); // not implemented yet else { - inputs = AddNormalinputs(mtx,mypk,paid_nValue,60); + inputs = AddNormalinputs(mtx, mypk, paid_nValue, 60); mask = ~((1LL << mtx.vin.size()) - 1); } - if ( inputs > 0 ) + if (inputs > 0) { - if ( inputs < paid_nValue ) - paid_nValue = inputs; - if ( assetid2 != zeroid ) - SetSwapFillamounts(received_assetoshis,remaining_nValue,orig_assetoshis,paid_nValue,total_nValue); - else SetAskFillamounts(received_assetoshis,remaining_nValue,orig_assetoshis,paid_nValue,total_nValue); - if ( assetid2 != zeroid && inputs > paid_nValue ) + if (inputs < paid_nValue) { + std::cerr << "FillSell(): insufficient coins to fill sell" << std::endl; + CCerror = strprintf("insufficient coins to fill sell"); + return (""); + } + + if (assetid2 != zeroid) + SetSwapFillamounts(received_assetoshis, remaining_nValue, orig_assetoshis, paid_nValue, total_nValue); //not implemented correctly yet + else + SetAskFillamounts(received_assetoshis, remaining_nValue, orig_assetoshis, paid_nValue, total_nValue); + + if (assetid2 != zeroid && inputs > paid_nValue) CCchange = (inputs - paid_nValue); - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,orig_assetoshis - received_assetoshis,GetUnspendable(cp,0))); - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,received_assetoshis,mypk)); - if ( assetid2 != zeroid ) - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,paid_nValue,origpubkey)); - else mtx.vout.push_back(CTxOut(paid_nValue,CScript() << origpubkey << OP_CHECKSIG)); - if ( CCchange != 0 ) - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk)); - return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,EncodeAssetOpRet(assetid2!=zeroid?'E':'S',assetid,assetid2,remaining_nValue,origpubkey))); + + mtx.vout.push_back(MakeTokensCC1vout(EVAL_ASSETS, orig_assetoshis - received_assetoshis, GetUnspendable(cpAssets, NULL))); // vout.0 tokens remainder to unspendable cc addr + mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, received_assetoshis, mypk)); //vout.1 purchased tokens to self single-eval addr + + // NOTE: no marker here + + if (assetid2 != zeroid) { + std::cerr << "FillSell() WARNING: asset swap not implemented yet! (paid_nValue)" << std::endl; + // TODO: change MakeCC1vout appropriately when implementing: + //mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, paid_nValue, origpubkey)); //vout.2 tokens... (swap is not implemented yet) + } + else { + //std::cerr << "FillSell() paid_value=" << paid_nValue << " origpubkey=" << HexStr(pubkey2pk(origpubkey)) << std::endl; + mtx.vout.push_back(CTxOut(paid_nValue, CScript() << origpubkey << OP_CHECKSIG)); //vout.2 coins to tokens seller's normal addr + } + mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,txfee,origpubkey)); //vout.3 marker to origpubkey + + // not implemented + if (CCchange != 0) { + std::cerr << "FillSell() WARNING: asset swap not implemented yet! (CCchange)" << std::endl; + // TODO: change MakeCC1vout appropriately when implementing: + //mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, CCchange, mypk)); //vout.3 coins in Assets cc addr (swap not implemented) + } + + uint8_t unspendableAssetsPrivkey[32]; + char unspendableAssetsAddr[64]; + // init assets 'unspendable' privkey and pubkey + CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, unspendableAssetsPrivkey); + GetCCaddress(cpAssets, unspendableAssetsAddr, unspendableAssetsPk); + + // add additional eval-tokens unspendable assets privkey: + CCaddr2set(cpAssets, EVAL_TOKENS, unspendableAssetsPk, unspendableAssetsPrivkey, unspendableAssetsAddr); + + // vout verification pubkeys: + std::vector voutTokenPubkeys; + voutTokenPubkeys.push_back(mypk); + + return(FinalizeCCTx(mask, cpAssets, mtx, mypk, txfee, + EncodeTokenOpRet(assetid, voutTokenPubkeys, + EncodeAssetOpRet(assetid2 != zeroid ? 'E' : 'S', assetid2, remaining_nValue, origpubkey)))); } else { CCerror = strprintf("filltx not enough utxos"); fprintf(stderr,"%s\n", CCerror.c_str()); diff --git a/src/cc/CCauction.h b/src/cc/CCauction.h index be636e76b..cfcd615cc 100644 --- a/src/cc/CCauction.h +++ b/src/cc/CCauction.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cc/CCchannels.h b/src/cc/CCchannels.h index 7715a31b8..10cb4d224 100644 --- a/src/cc/CCchannels.h +++ b/src/cc/CCchannels.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -21,11 +21,11 @@ #define CHANNELS_MAXPAYMENTS 1000 bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn); -std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment); +std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment,uint256 tokenid); std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint256 secret); std::string ChannelClose(uint64_t txfee,uint256 opentxid); std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid); - +UniValue ChannelsList(); // CCcustom UniValue ChannelsInfo(uint256 opentxid); diff --git a/src/cc/CCcustom.cpp b/src/cc/CCcustom.cpp index b17a7cd89..577332b63 100644 --- a/src/cc/CCcustom.cpp +++ b/src/cc/CCcustom.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -27,9 +27,10 @@ #include "CCOracles.h" #include "CCPrices.h" #include "CCPegs.h" -#include "CCTriggers.h" +#include "CCMarmara.h" #include "CCPayments.h" #include "CCGateways.h" +#include "CCtokens.h" /* CCcustom has most of the functions that need to be extended to create a new CC contract. @@ -189,13 +190,13 @@ uint8_t PegsCCpriv[32] = { 0x52, 0x56, 0x4c, 0x78, 0x87, 0xf7, 0xa2, 0x39, 0xb0, #undef FUNCNAME #undef EVALCODE -// Triggers -#define FUNCNAME IsTriggersInput -#define EVALCODE EVAL_TRIGGERS -const char *TriggersCCaddr = "RGLSRDnUqTB43bYtRtNVgmwSSd1sun2te8"; -const char *TriggersNormaladdr = "RMN25Tn8NNzcyQDiQNuMp8UmwLMFd9thYc"; -char TriggersCChexstr[67] = { "03afc5be570d0ff419425cfcc580cc762ab82baad88c148f5b028d7db7bfeee61d" }; -uint8_t TriggersCCpriv[32] = { 0x7c, 0x0b, 0x54, 0x9b, 0x65, 0xd4, 0x89, 0x57, 0xdf, 0x05, 0xfe, 0xa2, 0x62, 0x41, 0xa9, 0x09, 0x0f, 0x2a, 0x6b, 0x11, 0x2c, 0xbe, 0xbd, 0x06, 0x31, 0x8d, 0xc0, 0xb9, 0x96, 0x76, 0x3f, 0x24 }; +// Marmara +#define FUNCNAME IsMarmaraInput +#define EVALCODE EVAL_MARMARA +const char *MarmaraCCaddr = "RGLSRDnUqTB43bYtRtNVgmwSSd1sun2te8"; +const char *MarmaraNormaladdr = "RMN25Tn8NNzcyQDiQNuMp8UmwLMFd9thYc"; +char MarmaraCChexstr[67] = { "03afc5be570d0ff419425cfcc580cc762ab82baad88c148f5b028d7db7bfeee61d" }; +uint8_t MarmaraCCpriv[32] = { 0x7c, 0x0b, 0x54, 0x9b, 0x65, 0xd4, 0x89, 0x57, 0xdf, 0x05, 0xfe, 0xa2, 0x62, 0x41, 0xa9, 0x09, 0x0f, 0x2a, 0x6b, 0x11, 0x2c, 0xbe, 0xbd, 0x06, 0x31, 0x8d, 0xc0, 0xb9, 0x96, 0x76, 0x3f, 0x24 }; #include "CCcustom.inc" #undef FUNCNAME #undef EVALCODE @@ -222,6 +223,46 @@ uint8_t GatewaysCCpriv[32] = { 0xf7, 0x4b, 0x5b, 0xa2, 0x7a, 0x5e, 0x9c, 0xda, 0 #undef FUNCNAME #undef EVALCODE +// Tokens +#define FUNCNAME IsTokensInput +#define EVALCODE EVAL_TOKENS +const char *TokensCCaddr = "RAMvUfoyURBRxAdVeTMHxn3giJZCFWeha2"; +const char *TokensNormaladdr = "RCNgAngYAdrfzujYyPgfbjCGNVQZzCgTad"; +char TokensCChexstr[67] = { "03e6191c70c9c9a28f9fd87089b9488d0e6c02fb629df64979c9cdb6b2b4a68d95" }; +uint8_t TokensCCpriv[32] = { 0x1d, 0x0d, 0x0d, 0xce, 0x2d, 0xd2, 0xe1, 0x9d, 0xf5, 0xb6, 0x26, 0xd5, 0xad, 0xa0, 0xf0, 0x0a, 0xdd, 0x7a, 0x72, 0x7d, 0x17, 0x35, 0xb5, 0xe3, 0x2c, 0x6c, 0xa9, 0xa2, 0x03, 0x16, 0x4b, 0xcf }; +#include "CCcustom.inc" +#undef FUNCNAME +#undef EVALCODE + +#define FUNCNAME IsCClibInput +#define EVALCODE EVAL_FIRSTUSER +const char *CClibNormaladdr = "RVVeUg43rNcq3mZFnvZ8yqagyzqFgUnq4u"; +char CClibCChexstr[67] = { "032447d97655da079729dc024c61088ea415b22f4c15d4810ddaf2069ac6468d2f" }; +uint8_t CClibCCpriv[32] = { 0x57, 0xcf, 0x49, 0x71, 0x7d, 0xb4, 0x15, 0x1b, 0x4f, 0x98, 0xc5, 0x45, 0x8d, 0x26, 0x52, 0x4b, 0x7b, 0xe9, 0xbd, 0x55, 0xd8, 0x20, 0xd6, 0xc4, 0x82, 0x0f, 0xf5, 0xec, 0x6c, 0x1c, 0xa0, 0xc0 }; +#include "CCcustom.inc" +#undef FUNCNAME +#undef EVALCODE + +int32_t CClib_initcp(struct CCcontract_info *cp,uint8_t evalcode) +{ + CPubKey pk; uint8_t pub33[33]; char CCaddr[64]; + if ( evalcode == EVAL_FIRSTUSER ) // eventually make a hashchain for each evalcode + { + cp->evalcode = evalcode; + cp->ismyvin = IsCClibInput; + strcpy(cp->CChexstr,CClibCChexstr); + memcpy(cp->CCpriv,CClibCCpriv,32); + decode_hex(pub33,33,cp->CChexstr); + pk = buf2pk(pub33); + Getscriptaddress(cp->normaladdr,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG); + if ( strcmp(cp->normaladdr,CClibNormaladdr) != 0 ) + fprintf(stderr,"CClib_initcp addr mismatch %s vs %s\n",cp->normaladdr,CClibNormaladdr); + GetCCaddress(cp,cp->unspendableCCaddr,pk); + return(0); + } + return(-1); +} + struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) { cp->evalcode = evalcode; @@ -323,13 +364,13 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) cp->validate = PegsValidate; cp->ismyvin = IsPegsInput; break; - case EVAL_TRIGGERS: - strcpy(cp->unspendableCCaddr,TriggersCCaddr); - strcpy(cp->normaladdr,TriggersNormaladdr); - strcpy(cp->CChexstr,TriggersCChexstr); - memcpy(cp->CCpriv,TriggersCCpriv,32); - cp->validate = TriggersValidate; - cp->ismyvin = IsTriggersInput; + case EVAL_MARMARA: + strcpy(cp->unspendableCCaddr,MarmaraCCaddr); + strcpy(cp->normaladdr,MarmaraNormaladdr); + strcpy(cp->CChexstr,MarmaraCChexstr); + memcpy(cp->CCpriv,MarmaraCCpriv,32); + cp->validate = MarmaraValidate; + cp->ismyvin = IsMarmaraInput; break; case EVAL_PAYMENTS: strcpy(cp->unspendableCCaddr,PaymentsCCaddr); @@ -347,6 +388,19 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) cp->validate = GatewaysValidate; cp->ismyvin = IsGatewaysInput; break; + + case EVAL_TOKENS: + strcpy(cp->unspendableCCaddr, TokensCCaddr); + strcpy(cp->normaladdr, TokensNormaladdr); + strcpy(cp->CChexstr, TokensCChexstr); + memcpy(cp->CCpriv, TokensCCpriv, 32); + cp->validate = TokensValidate; + cp->ismyvin = IsTokensInput; + break; + default: + if ( CClib_initcp(cp,evalcode) < 0 ) + return(0); + break; } return(cp); } diff --git a/src/cc/CCdice.h b/src/cc/CCdice.h index cb0398129..363aad735 100644 --- a/src/cc/CCdice.h +++ b/src/cc/CCdice.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cc/CCfaucet.h b/src/cc/CCfaucet.h index 895327d09..3cb6c66e5 100644 --- a/src/cc/CCfaucet.h +++ b/src/cc/CCfaucet.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cc/CCfsm.h b/src/cc/CCfsm.h index 0aafdb6b9..2bce35597 100644 --- a/src/cc/CCfsm.h +++ b/src/cc/CCfsm.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 28091b957..66c001969 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -51,18 +51,20 @@ one other technical note is that komodod has the insight-explorer extensions bui #include "../utlist.h" #include "../uthash.h" -extern int32_t KOMODO_CONNECTING,KOMODO_CCACTIVATE,KOMODO_DEALERNODE; -extern uint32_t ASSETCHAINS_CC; -extern char ASSETCHAINS_SYMBOL[]; -extern std::string CCerror; + +#define CC_MAXVINS 1024 #define SMALLVAL 0.000000000000001 +#define SATOSHIDEN ((uint64_t)100000000L) +#define dstr(x) ((double)(x) / SATOSHIDEN) + #ifndef _BITS256 #define _BITS256 union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; typedef union _bits256 bits256; #endif +#include "../komodo_cJSON.h" struct CC_utxo { @@ -84,12 +86,31 @@ struct CC_meta struct CCcontract_info { - char unspendableCCaddr[64],CChexstr[72],normaladdr[64],unspendableaddr2[64],unspendableaddr3[64]; - uint8_t CCpriv[32],unspendablepriv2[32],unspendablepriv3[32]; - CPubKey unspendablepk2,unspendablepk3; - bool (*validate)(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn); - bool (*ismyvin)(CScript const& scriptSig); - uint8_t evalcode,evalcode2,evalcode3,didinit; + // this is for spending from 'unspendable' CC address + uint8_t evalcode; + char unspendableCCaddr[64], CChexstr[72], normaladdr[64]; + uint8_t CCpriv[32]; + + // this for 1of2 keys coins cryptocondition (for this evalcode) + // NOTE: only one evalcode is allowed at this time + char coins1of2addr[64]; + CPubKey coins1of2pk[2]; + + // the same for tokens 1of2 keys cc + char tokens1of2addr[64]; + CPubKey tokens1of2pk[2]; + + // this is for spending from two additional 'unspendable' CC addresses of other eval codes + // (that is, for spending from several cc contract 'unspendable' addresses): + uint8_t evalcode2, evalcode3; + char unspendableaddr2[64], unspendableaddr3[64]; + uint8_t unspendablepriv2[32], unspendablepriv3[32]; + CPubKey unspendablepk2, unspendablepk3; + + bool (*validate)(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn); // cc contract tx validation callback + bool (*ismyvin)(CScript const& scriptSig); // checks if evalcode is present in the scriptSig param + + uint8_t didinit; }; struct CCcontract_info *CCinit(struct CCcontract_info *cp,uint8_t evalcode); @@ -103,15 +124,21 @@ struct oracleprice_info #ifdef ENABLE_WALLET extern CWallet* pwalletMain; #endif +//extern CCoinsViewCache *pcoinsTip; bool GetAddressUnspent(uint160 addressHash, int type,std::vector > &unspentOutputs); CBlockIndex *komodo_getblockindex(uint256 hash); int32_t komodo_nextheight(); +int32_t CCgetspenttxid(uint256 &spenttxid,int32_t &vini,int32_t &height,uint256 txid,int32_t vout); +void CCclearvars(struct CCcontract_info *cp); +UniValue CClib(struct CCcontract_info *cp,char *method,cJSON *params); +UniValue CClib_info(struct CCcontract_info *cp); + static const uint256 zeroid; bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock); int32_t is_hexstr(char *str,int32_t n); bool myAddtomempool(CTransaction &tx, CValidationState *pstate = NULL, bool fSkipExpiry = false); -//uint64_t myGettxout(uint256 hash,int32_t n); +int32_t CCgettxout(uint256 txid,int32_t vout,int32_t mempoolflag); bool myIsutxo_spentinmempool(uint256 txid,int32_t vout); bool mytxid_inmempool(uint256 txid); int32_t myIsutxo_spent(uint256 &spenttxid,uint256 txid,int32_t vout); @@ -128,13 +155,25 @@ int64_t OraclePrice(int32_t height,uint256 reforacletxid,char *markeraddr,char * uint8_t DecodeOraclesCreateOpRet(const CScript &scriptPubKey,std::string &name,std::string &description,std::string &format); uint256 OracleMerkle(int32_t height,uint256 reforacletxid,char *format,std::vectorpublishers); uint256 OraclesBatontxid(uint256 oracletxid,CPubKey pk); -int64_t AddAssetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 assetid,int64_t total,int32_t maxinputs); + +//int64_t AddAssetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 assetid,int64_t total,int32_t maxinputs); +int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 tokenid, int64_t total, int32_t maxinputs); +int64_t IsTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 reftokenid); + bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx); -bool DecodeAssetCreateOpRet(const CScript &scriptPubKey,std::vector &origpubkey,std::string &name,std::string &description); -uint8_t DecodeAssetOpRet(const CScript &scriptPubKey,uint256 &assetid,uint256 &assetid2,int64_t &price,std::vector &origpubkey); +CScript EncodeAssetOpRet(uint8_t assetFuncId, uint256 assetid2, int64_t price, std::vector origpubkey); +//bool DecodeAssetCreateOpRet(const CScript &scriptPubKey, std::vector &origpubkey, std::string &name, std::string &description); +uint8_t DecodeAssetTokenOpRet(const CScript &scriptPubKey, uint8_t &evalCodeInOpret, uint256 &tokenid, uint256 &assetid2, int64_t &price, std::vector &origpubkey); + +CScript EncodeTokenOpRet(uint256 tokenid, std::vector voutPubkeys, CScript payload); +CScript EncodeTokenOpRet(uint8_t tokenFuncId, uint8_t evalCodeInOpret, uint256 tokenid, std::vector voutPubkeys, CScript payload); +uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey, std::vector &origpubkey, std::string &name, std::string &description); +uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCode, uint256 &tokenid, std::vector &voutPubkeys, std::vector &vopretExtra); + uint8_t DecodeOraclesData(const CScript &scriptPubKey,uint256 &oracletxid,uint256 &batontxid,CPubKey &pk,std::vector &data); int32_t oracle_format(uint256 *hashp,int64_t *valp,char *str,uint8_t fmt,uint8_t *data,int32_t offset,int32_t datalen); -CScript EncodeAssetOpRet(uint8_t funcid,uint256 assetid,uint256 assetid2,int64_t price,std::vector origpubkey); + + // CCcustom CPubKey GetUnspendable(struct CCcontract_info *cp,uint8_t *unspendablepriv); @@ -150,6 +189,18 @@ CC *MakeCCcond1of2(uint8_t evalcode,CPubKey pk1,CPubKey pk2); CC* GetCryptoCondition(CScript const& scriptSig); void CCaddr2set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr); void CCaddr3set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr); +void CCaddr1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, char *coinaddr); + +CTxOut MakeTokensCC1of2vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2); +CTxOut MakeTokensCC1vout(uint8_t evalcode, CAmount nValue, CPubKey pk); +CC *MakeTokensCCcond1of2(uint8_t evalcode, CPubKey pk1, CPubKey pk2); +CC *MakeTokensCCcond1(uint8_t evalcode, CPubKey pk); + +bool GetTokensCCaddress(struct CCcontract_info *cp, char *destaddr, CPubKey pk); +bool GetTokensCCaddress1of2(struct CCcontract_info *cp, char *destaddr, CPubKey pk, CPubKey pk2); +void CCaddrTokens1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, char *coinaddr); +int32_t CClib_initcp(struct CCcontract_info *cp,uint8_t evalcode); + bool IsCCInput(CScript const& scriptSig); int32_t unstringbits(char *buf,uint64_t bits); uint64_t stringbits(char *str); @@ -172,9 +223,11 @@ std::vector Mypubkey(); bool Myprivkey(uint8_t myprivkey[]); int64_t CCduration(int32_t &numblocks,uint256 txid); bool komodo_txnotarizedconfirmed(uint256 txid); +CPubKey check_signing_pubkey(CScript scriptSig); // CCtx bool SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScript scriptPubKey); -std::string FinalizeCCTx(uint64_t skipmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret); +extern std::vector NULL_pubkeys; +std::string FinalizeCCTx(uint64_t skipmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret,std::vector pubkeys = NULL_pubkeys); void SetCCunspents(std::vector > &unspentOutputs,char *coinaddr); void SetCCtxids(std::vector > &addressIndex,char *coinaddr); int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs); @@ -187,5 +240,6 @@ bits256 curve25519_basepoint9(); bits256 curve25519(bits256 mysecret,bits256 basepoint); void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len); bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen); +UniValue ValueFromAmount(const CAmount& amount); #endif diff --git a/src/cc/CClotto.h b/src/cc/CClotto.h index 838aac338..2f0595371 100644 --- a/src/cc/CClotto.h +++ b/src/cc/CClotto.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cc/CCrewards.h b/src/cc/CCrewards.h index ac90423b2..4d6cc80f9 100644 --- a/src/cc/CCrewards.h +++ b/src/cc/CCrewards.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp new file mode 100644 index 000000000..d7db32b99 --- /dev/null +++ b/src/cc/CCtokens.cpp @@ -0,0 +1,768 @@ +/****************************************************************************** + * 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. * + * * + ******************************************************************************/ + +#include "CCtokens.h" + +/* TODO: correct this: +----------------------------- + The SetTokenFillamounts() and ValidateTokenRemainder() work in tandem to calculate the vouts for a fill and to validate the vouts, respectively. + + This pair of functions are critical to make sure the trading is correct and is the trickiest part of the tokens contract. + + //vin.0: normal input + //vin.1: unspendable.(vout.0 from buyoffer) buyTx.vout[0] + //vin.2+: valid CC output satisfies buyoffer (*tx.vin[2])->nValue + //vout.0: remaining amount of bid to unspendable + //vout.1: vin.1 value to signer of vin.2 + //vout.2: vin.2 tokenoshis to original pubkey + //vout.3: CC output for tokenoshis change (if any) + //vout.4: normal output for change (if any) + //vout.n-1: opreturn [EVAL_ASSETS] ['B'] [tokenid] [remaining token required] [origpubkey] + ValidateTokenRemainder(remaining_price,tx.vout[0].nValue,nValue,tx.vout[1].nValue,tx.vout[2].nValue,totalunits); + + Yes, this is quite confusing... + + In ValudateTokenRemainder the naming convention is nValue is the coin/token with the offer on the books and "units" is what it is being paid in. The high level check is to make sure we didnt lose any coins or tokens, the harder to validate is the actual price paid as the "orderbook" is in terms of the combined nValue for the combined totalunits. + + We assume that the effective unit cost in the orderbook is valid and that that amount was paid and also that any remainder will be close enough in effective unit cost to not matter. At the edge cases, this will probably be not true and maybe some orders wont be practically fillable when reduced to fractional state. However, the original pubkey that created the offer can always reclaim it. + ------------------------------ +*/ + + +// NOTE: this inital tx won't be used by other contract +// for tokens to be used there should be at least one 't' tx with other contract's custom opret +CScript EncodeTokenCreateOpRet(uint8_t funcid,std::vector origpubkey,std::string name,std::string description) +{ + CScript opret; uint8_t evalcode = EVAL_TOKENS; + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << origpubkey << name << description); + return(opret); +} + +// this is for other contracts which use tokens and build customized extra payloads to token's opret: +CScript EncodeTokenOpRet(uint256 tokenid, std::vector voutPubkeys, CScript payload) +{ + CScript opret; + uint8_t tokenFuncId = 't'; + uint8_t evalCodeInOpret = EVAL_TOKENS; + + tokenid = revuint256(tokenid); + + uint8_t ccType = 0; + if (voutPubkeys.size() >= 1 && voutPubkeys.size() <= 2) + ccType = voutPubkeys.size(); + + std::vector vpayload; + GetOpReturnData(payload, vpayload); + + opret << OP_RETURN << E_MARSHAL(ss << evalCodeInOpret << tokenFuncId << tokenid << ccType; \ + if (ccType >= 1) ss << voutPubkeys[0]; \ + if (ccType == 2) ss << voutPubkeys[1]; \ + if (vpayload.size() > 0) ss << vpayload;); + + + // "error 64: scriptpubkey": + // if (payload.size() > 0) + // opret += payload; + + // error 64: scriptpubkey: + // CScript opretPayloadNoOpcode(vpayload); + // return opret + opretPayloadNoOpcode; + + // how to attach payload without re-serialization: + // sig_aborted: + // opret.resize(opret.size() + vpayload.size()); + // CScript::iterator it = opret.begin() + opret.size(); + // for (int i = 0; i < vpayload.size(); i++, it++) + // *it = vpayload[i]; + + return opret; +} + +// overload for compatibility +CScript EncodeTokenOpRet(uint8_t tokenFuncId, uint8_t evalCodeInOpret, uint256 tokenid, std::vector voutPubkeys, CScript payload) +{ + return EncodeTokenOpRet(tokenid, voutPubkeys, payload); +} + +uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey,std::vector &origpubkey,std::string &name,std::string &description) +{ + std::vector vopret; uint8_t dummyEvalcode, funcid, *script; + + GetOpReturnData(scriptPubKey, vopret); + script = (uint8_t *)vopret.data(); + if ( script != 0 && vopret.size() > 2 && script[0] == EVAL_TOKENS && script[1] == 'c' ) + { + if ( E_UNMARSHAL(vopret, ss >> dummyEvalcode; ss >> funcid; ss >> origpubkey; ss >> name; ss >> description) != 0 ) + return(funcid); + } + return (uint8_t)0; +} + +uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCode, uint256 &tokenid, std::vector &voutPubkeys, std::vector &vopretExtra) +{ + std::vector vopret, extra, dummyPubkey; + uint8_t funcId=0, *script, dummyEvalCode, dummyFuncId, ccType; + std::string dummyName; std::string dummyDescription; + CPubKey voutPubkey1, voutPubkey2; + + GetOpReturnData(scriptPubKey, vopret); + script = (uint8_t *)vopret.data(); + tokenid = zeroid; + + if (script != 0 && vopret.size() > 2) + { + // NOTE: if parse error occures, parse might not be able to set error. It is safer to treat that it was eof if it is not set! + bool isEof = true; + + evalCode = script[0]; + if (evalCode != EVAL_TOKENS) + return (uint8_t)0; + + funcId = script[1]; + //fprintf(stderr,"decode.[%c]\n",funcId); + + switch( funcId ) + { + case 'c': + return DecodeTokenCreateOpRet(scriptPubKey, dummyPubkey, dummyName, dummyDescription); + //break; + case 't': + //not used yet: case 'l': + // NOTE: 'E_UNMARSHAL result==false' means 'parse error' OR 'not eof state'. Consequently, 'result==false' but 'isEof==true' means just 'parse error' + if (E_UNMARSHAL(vopret, ss >> dummyEvalCode; ss >> dummyFuncId; ss >> tokenid; ss >> ccType; if (ccType >= 1) ss >> voutPubkey1; if (ccType == 2) ss >> voutPubkey2; isEof = ss.eof(); vopretExtra = std::vector(ss.begin(), ss.end())) + || !isEof) + { + + if (!(ccType >= 0 && ccType <= 2)) { //incorrect ccType + std::cerr << "DecodeTokenOpRet() incorrect ccType=" << (int)ccType << " tokenid=" << revuint256(tokenid).GetHex() << std::endl; + return (uint8_t)0; + } + + // add verification pubkeys: + voutPubkeys.clear(); + if (voutPubkey1.IsValid()) + voutPubkeys.push_back(voutPubkey1); + if (voutPubkey2.IsValid()) + voutPubkeys.push_back(voutPubkey2); + + tokenid = revuint256(tokenid); + return(funcId); + } + std::cerr << "DecodeTokenOpRet() bad opret format, isEof=" << isEof << " ccType=" << ccType << " tokenid=" << revuint256(tokenid).GetHex() << std::endl; + return (uint8_t)0; + + default: + std::cerr << "DecodeTokenOpRet() illegal funcid=" << (int)funcId << std::endl; + return (uint8_t)0; + } + } + else { + std::cerr << "DecodeTokenOpRet() empty opret, could not parse" << std::endl; + } + return (uint8_t)0; +} + + + +// tx validation +bool TokensValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn) +{ + static uint256 zero; + CTxDestination address; CTransaction vinTx, createTx; uint256 hashBlock, tokenid, tokenid2; + int32_t i, starti, numvins, numvouts, preventCCvins, preventCCvouts; + int64_t remaining_price, nValue, tokenoshis, outputs, inputs, tmpprice, totalunits, ignore; + std::vector vopretExtra, tmporigpubkey, ignorepubkey; + uint8_t funcid, evalCodeInOpret; + char destaddr[64], origaddr[64], CCaddr[64]; + std::vector voutTokenPubkeys; + + //return true; + + numvins = tx.vin.size(); + numvouts = tx.vout.size(); + outputs = inputs = 0; + preventCCvins = preventCCvouts = -1; + + if ((funcid = DecodeTokenOpRet(tx.vout[numvouts - 1].scriptPubKey, evalCodeInOpret, tokenid, voutTokenPubkeys, vopretExtra)) == 0) + return eval->Invalid("TokenValidate: invalid opreturn payload"); + + fprintf(stderr, "TokensValidate (%c) evalcode=0x%0x\n", funcid, cp->evalcode); + + if (eval->GetTxUnconfirmed(tokenid, createTx, hashBlock) == 0) + return eval->Invalid("cant find token create txid"); + else if (IsCCInput(tx.vin[0].scriptSig) != 0) + return eval->Invalid("illegal token vin0"); + else if (numvouts < 1) + return eval->Invalid("no vouts"); + else if (funcid != 'c') + { + if (tokenid == zeroid) + return eval->Invalid("illegal tokenid"); + else if (!TokensExactAmounts(true, cp, inputs, outputs, eval, tx, tokenid)) { + if (!eval->Valid()) + return false; //TokenExactAmounts must call eval->Invalid()! + else + return eval->Invalid("tokens cc inputs != cc outputs"); + } + } + + + switch (funcid) + { + case 'c': // create wont be called to be verified as it has no CC inputs + //vin.0: normal input + //vout.0: issuance tokenoshis to CC + //vout.1: normal output for change (if any) + //vout.n-1: opreturn EVAL_TOKENS 'c' + //if (evalCodeInOpret != EVAL_TOKENS) + // return eval->Invalid("unexpected TokenValidate for createtoken"); + //else + return true; + + case 't': // transfer + //vin.0: normal input + //vin.1 .. vin.n-1: valid CC outputs + //vout.0 to n-2: tokenoshis output to CC + //vout.n-2: normal output for change (if any) + //vout.n-1: opreturn 't' tokenid + if (inputs == 0) + return eval->Invalid("no token inputs for transfer"); + + fprintf(stderr, "token transfer preliminarily validated %.8f -> %.8f (%d %d)\n", (double)inputs / COIN, (double)outputs / COIN, preventCCvins, preventCCvouts); + break; // breaking to other contract validation... + + default: + fprintf(stderr, "illegal tokens funcid.(%c)\n", funcid); + return eval->Invalid("unexpected token funcid"); + } + + // forward validation if evalcode in opret is not EVAL_TOKENS + // init for forwarding validation call + //if (evalCodeInOpret != EVAL_TOKENS) { // TODO: should we check also only allowed for tokens evalcodes, like EVAL_ASSETS, EVAL_GATEWAYS? + // struct CCcontract_info *cpOther = NULL, C; + + // cpOther = CCinit(&C, evalCodeInOpret); + // if (cpOther) + // return cpOther->validate(cpOther, eval, tx, nIn); + // else + // return eval->Invalid("unsupported evalcode in opret"); + //} + return true; + // what does this do? + // return(PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts)); +} + +// helper funcs: + +// extract my vins pubkeys: +bool ExtractTokensVinPubkeys(CTransaction tx, std::vector &vinPubkeys) { + + bool found = false; + CPubKey pubkey; + struct CCcontract_info *cpTokens, tokensC; + + cpTokens = CCinit(&tokensC, EVAL_TOKENS); + + for (int32_t i = 0; i < tx.vin.size(); i++) + { // check for additional contracts which may send tokens to the Tokens contract + if( (*cpTokens->ismyvin)(tx.vin[i].scriptSig) ) + { + + auto findEval = [](CC *cond, struct CCVisitor _) { + bool r = false; //cc_typeId(cond) == CC_Eval && cond->codeLength == 1 && cond->code[0] == EVAL_TOKENS; + + if (cc_typeId(cond) == CC_Secp256k1) { + *(CPubKey*)_.context = buf2pk(cond->publicKey); + //std::cerr << "findEval found pubkey=" << HexStr(*(CPubKey*)_.context) << std::endl; + r = true; + } + // false for a match, true for continue + return r ? 0 : 1; + }; + + CC *cond = GetCryptoCondition(tx.vin[i].scriptSig); + + if (cond) { + CCVisitor visitor = { findEval, (uint8_t*)"", 0, &pubkey }; + bool out = !cc_visit(cond, visitor); + cc_free(cond); + + if (pubkey.IsValid()) { + vinPubkeys.push_back(pubkey); + found = true; + } + } + } + } + return found; +} + +// this is just for log messages indentation fur debugging recursive calls: +thread_local uint32_t tokenValIndentSize = 0; + +// validates opret for token tx: +uint8_t ValidateTokenOpret(CTransaction tx, int32_t v, uint256 tokenid, std::vector &voutPubkeys, std::vector &vopretExtra) { + + uint256 tokenidOpret, tokenidOpret2; + uint8_t funcid; + uint8_t dummyEvalCode; + + // this is just for log messages indentation fur debugging recursive calls: + std::string indentStr = std::string().append(tokenValIndentSize, '.'); + + int32_t n = tx.vout.size(); + + if ((funcid = DecodeTokenOpRet(tx.vout[n - 1].scriptPubKey, dummyEvalCode, tokenidOpret, voutPubkeys, vopretExtra)) == 0) + { + std::cerr << indentStr << "ValidateTokenOpret() DecodeTokenOpret could not parse opret for txid=" << tx.GetHash().GetHex() << std::endl; + return(false); + } + else if (funcid == 'c') + { + if (tokenid != zeroid && tokenid == tx.GetHash() && v == 0) { + //std::cerr << indentStr << "ValidateTokenOpret() this is the tokenbase 'c' tx, txid=" << tx.GetHash().GetHex() << " vout=" << v << " returning true" << std::endl; + return funcid; + } + } + else if (funcid == 't') + { + //std::cerr << indentStr << "ValidateTokenOpret() tokenid=" << tokenid.GetHex() << " tokenIdOpret=" << tokenidOpret.GetHex() << " txid=" << tx.GetHash().GetHex() << std::endl; + if (tokenid != zeroid && tokenid == tokenidOpret) { + //std::cerr << indentStr << "ValidateTokenOpret() this is a transfer 't' tx, txid=" << tx.GetHash().GetHex() << " vout=" << v << " returning true" << std::endl; + return funcid; + } + } + //std::cerr << indentStr << "ValidateTokenOpret() return false funcid=" << (char)funcid << " tokenid=" << tokenid.GetHex() << " tokenIdOpret=" << tokenidOpret.GetHex() << " txid=" << tx.GetHash().GetHex() << std::endl; + return (uint8_t)0; +} + +// Checks if the vout is a really Tokens CC vout +// also checks tokenid in opret or txid if this is 'c' tx +// goDeeper is true: the func also validates amounts of the passed transaction: +// it should be either sum(cc vins) == sum(cc vouts) or the transaction is the 'tokenbase' ('c') tx +// checkPubkeys is true: validates if the vout is token vout1 or token vout1of2. Should always be true! +int64_t IsTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 reftokenid) +{ + + // this is just for log messages indentation fur debugging recursive calls: + std::string indentStr = std::string().append(tokenValIndentSize, '.'); + //std::cerr << indentStr << "IsTokensvout() entered for txid=" << tx.GetHash().GetHex() << " v=" << v << " for tokenid=" << reftokenid.GetHex() << std::endl; + + //TODO: validate cc vouts are EVAL_TOKENS! + if (tx.vout[v].scriptPubKey.IsPayToCryptoCondition()) // maybe check address too? dimxy: possibly no, because there are too many cases with different addresses here + { + int32_t n = tx.vout.size(); + // just check boundaries: + if (v >= n - 1) { // just moved this up (dimxy) + std::cerr << indentStr << "isTokensvout() internal err: (v >= n - 1), returning 0" << std::endl; + return(0); + } + + if (goDeeper) { + //std::cerr << indentStr << "IsTokensvout() maxTokenExactAmountDepth=" << maxTokenExactAmountDepth << std::endl; + //validate all tx + int64_t myCCVinsAmount = 0, myCCVoutsAmount = 0; + + tokenValIndentSize++; + // false --> because we already at the 1-st level ancestor tx and do not need to dereference ancestors of next levels + bool isEqual = TokensExactAmounts(false, cp, myCCVinsAmount, myCCVoutsAmount, eval, tx, reftokenid); + tokenValIndentSize--; + + if (!isEqual) { + // if ccInputs != ccOutputs and it is not the tokenbase tx + // this means it is possibly a fake tx (dimxy): + if (reftokenid != tx.GetHash()) { // checking that this is the true tokenbase tx, by verifying that funcid=c, is done further in this function (dimxy) + std::cerr << indentStr << "IsTokensvout() warning: for the verified tx detected a bad vintx=" << tx.GetHash().GetHex() << ": cc inputs != cc outputs and not the 'tokenbase' tx, skipping the verified tx" << std::endl; + return 0; + } + } + } + + // moved opret checking to this new reusable func (dimxy): + std::vector voutPubkeys; + std::vector vopretExtra; + const uint8_t funcId = ValidateTokenOpret(tx, v, reftokenid, voutPubkeys, vopretExtra); + //std::cerr << indentStr << "IsTokensvout() ValidateTokenOpret returned=" << (char)(funcId?funcId:' ') << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl; + if (funcId != 0) { + //std::cerr << indentStr << "IsTokensvout() ValidateTokenOpret returned not-null" << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl; + + if (checkPubkeys && funcId != 'c') { // verify that the vout is token's (for 'c' there is no pubkeys!): + + //std::cerr << "IsTokensvout() vopretExtra=" << HexStr(vopretExtra) << std::endl; + + uint8_t evalCodeInOpret; + if (vopretExtra.size() >= 2 /*|| vopretExtra.size() != vopretExtra.begin()[0] <-- shold we check this?*/) { + evalCodeInOpret = vopretExtra.begin()[1]; + } + else { + // if payload is empty maybe it is a claim to non-payload-one-token-eval vout? + evalCodeInOpret = EVAL_TOKENS; + } + + // maybe this is dual-eval 1 pubkey or 1of2 pubkey vout? + if (voutPubkeys.size() >= 1 && voutPubkeys.size() <= 2) { + CTxOut testDualVout; + // check dual-eval 1 pubkey vout with the first pubkey + testDualVout = MakeTokensCC1vout(evalCodeInOpret, tx.vout[v].nValue, voutPubkeys[0]); + if (tx.vout[v].scriptPubKey == testDualVout.scriptPubKey) { + //std::cerr << indentStr << "IsTokensvout() this is dual-eval token vout (i=0), eval2=" << (int)evalCodeInOpret << ", returning nValue=" << tx.vout[v].nValue << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl; + return tx.vout[v].nValue; + } + + if(voutPubkeys.size() == 2) { + // check dual eval 1of2 pubkeys vout + testDualVout = MakeTokensCC1of2vout(evalCodeInOpret, tx.vout[v].nValue, voutPubkeys[0], voutPubkeys[1]); + if (tx.vout[v].scriptPubKey == testDualVout.scriptPubKey) { + //std::cerr << indentStr << "IsTokensvout() this is dual-eval token 1of2 vout, eval2=" << (int)evalCodeInOpret << ", returning nValue=" << tx.vout[v].nValue << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl; + return tx.vout[v].nValue; + } + + // check dual eval 1 pubkey vout with the second pubkey + testDualVout = MakeTokensCC1vout(evalCodeInOpret, tx.vout[v].nValue, voutPubkeys[1]); + if (tx.vout[v].scriptPubKey == testDualVout.scriptPubKey) { + //std::cerr << indentStr << "IsTokensvout() this is dual-eval token vout (i=1), eval2=" << (int)evalCodeInOpret << ", returning nValue=" << tx.vout[v].nValue << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl; + return tx.vout[v].nValue; + } + } + + + // maybe this is claim to single-eval token? + CTxOut testTokenVout1; + testTokenVout1 = MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, voutPubkeys[0]); + if (tx.vout[v].scriptPubKey == testTokenVout1.scriptPubKey) { + //std::cerr << indentStr << "IsTokensvout() this is single-eval token vout (i=0), returning nValue=" << tx.vout[v].nValue << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl; + return tx.vout[v].nValue; + } + + if (voutPubkeys.size() == 2) { + testTokenVout1 = MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, voutPubkeys[1]); + if (tx.vout[v].scriptPubKey == testTokenVout1.scriptPubKey) { + //std::cerr << indentStr << "IsTokensvout() this is single-eval token vout (i=1), returning nValue=" << tx.vout[v].nValue << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl; + return tx.vout[v].nValue; + } + } + } + + // maybe it is single-eval or dual-eval token change? + std::vector vinPubkeys; + ExtractTokensVinPubkeys(tx, vinPubkeys); + + for(std::vector::iterator it = vinPubkeys.begin(); it != vinPubkeys.end(); it++) { + CTxOut testTokenVout1 = MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, *it); + CTxOut testDualVout1 = MakeTokensCC1vout(evalCodeInOpret, tx.vout[v].nValue, *it); + + if (tx.vout[v].scriptPubKey == testTokenVout1.scriptPubKey) { + //std::cerr << indentStr << "IsTokensvout() this is single-eval token change, returning nValue=" << tx.vout[v].nValue << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl; + return tx.vout[v].nValue; + } + + if (tx.vout[v].scriptPubKey == testDualVout1.scriptPubKey) { + //std::cerr << indentStr << "IsTokensvout() this is dual-eval token change, vout eval2=" << (int)evalCodeInOpret << ", returning nValue=" << tx.vout[v].nValue << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl; + return tx.vout[v].nValue; + } + } + } + else { + //std::cerr << indentStr << "IsTokensvout() returns without pubkey check value=" << tx.vout[v].nValue << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl; + return tx.vout[v].nValue; + } + } + + //std::cerr << indentStr; fprintf(stderr,"IsTokensvout() CC vout v.%d of n=%d amount=%.8f txid=%s\n",v,n,(double)0/COIN, tx.GetHash().GetHex().c_str()); + } + //std::cerr << indentStr; fprintf(stderr,"IsTokensvout() normal output v.%d %.8f\n",v,(double)tx.vout[v].nValue/COIN); + return(0); +} + +// compares cc inputs vs cc outputs (to prevent feeding vouts from normal inputs) +bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, int64_t &inputs, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 tokenid) +{ + CTransaction vinTx; + uint256 hashBlock; + int64_t tokenoshis; + + struct CCcontract_info *cpTokens, tokensC; + cpTokens = CCinit(&tokensC, EVAL_TOKENS); + + int32_t numvins = tx.vin.size(); + int32_t numvouts = tx.vout.size(); + inputs = outputs = 0; + + // this is just for log messages indentation for debugging recursive calls: + std::string indentStr = std::string().append(tokenValIndentSize, '.'); + + for (int32_t i = 0; iismyvin)(tx.vin[i].scriptSig) /*|| IsVinAllowed(tx.vin[i].scriptSig) != 0*/) + { + //std::cerr << indentStr << "TokensExactAmounts() eval is true=" << (eval != NULL) << " ismyvin=ok for_i=" << i << std::endl; + // we are not inside the validation code -- dimxy + if ((eval && eval->GetTxUnconfirmed(tx.vin[i].prevout.hash, vinTx, hashBlock) == 0) || (!eval && !myGetTransaction(tx.vin[i].prevout.hash, vinTx, hashBlock))) + { + std::cerr << indentStr << "TokensExactAmounts() cannot read vintx for i." << i << " numvins." << numvins << std::endl; + return (!eval) ? false : eval->Invalid("always should find vin tx, but didnt"); + } + else { + tokenValIndentSize++; + // validate vouts of vintx + //std::cerr << indentStr << "TokenExactAmounts() check vin i=" << i << " nValue=" << vinTx.vout[tx.vin[i].prevout.n].nValue << std::endl; + tokenoshis = IsTokensvout(goDeeper, true, cpTokens, eval, vinTx, tx.vin[i].prevout.n, tokenid); + tokenValIndentSize--; + if (tokenoshis != 0) + { + std::cerr << indentStr << "TokensExactAmounts() vin i=" << i << " tokenoshis=" << tokenoshis << std::endl; + inputs += tokenoshis; + } + } + } + } + + + for (int32_t i = 0; iInvalid() here! + } + else + return true; +} + +// add inputs from token cc addr +int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 tokenid, int64_t total, int32_t maxinputs) +{ + char tokenaddr[64], destaddr[64]; + int64_t threshold, nValue, price, totalinputs = 0; + uint256 txid, hashBlock; + //std::vector vopretExtra; + CTransaction vintx; + int32_t j, vout, n = 0; + std::vector > unspentOutputs; + + GetTokensCCaddress(cp, tokenaddr, pk); + SetCCunspents(unspentOutputs, tokenaddr); + + threshold = total / (maxinputs != 0 ? maxinputs : 64); // TODO: is maxinputs really could not be over 64? what if i want to calc total balance? + + for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) + { + txid = it->first.txhash; + vout = (int32_t)it->first.index; + if (it->second.satoshis < threshold) + continue; + for (j = 0; junspendableCCaddr) != 0 && strcmp(destaddr, cp->unspendableaddr2) != 0) + continue; + //fprintf(stderr, "AddTokenCCInputs() check destaddress=%s vout amount=%.8f\n", destaddr, (double)vintx.vout[vout].nValue / COIN); + + std::vector vinPubkeys; + + if ((nValue = IsTokensvout(true, true/*<--add only checked token uxtos */, cp, NULL, vintx, vout, tokenid)) > 0 && myIsutxo_spentinmempool(txid, vout) == 0) + { + if (total != 0 && maxinputs != 0) + mtx.vin.push_back(CTxIn(txid, vout, CScript())); + nValue = it->second.satoshis; + totalinputs += nValue; + std::cerr << "AddTokenInputs() adding input nValue=" << nValue << std::endl; + n++; + if ((total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs)) + break; + } + } + } + + //std::cerr << "AddTokenInputs() found totalinputs=" << totalinputs << std::endl; + return(totalinputs); +} + + +std::string CreateToken(int64_t txfee, int64_t assetsupply, std::string name, std::string description) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CPubKey mypk; struct CCcontract_info *cp, C; + if (assetsupply < 0) + { + fprintf(stderr, "negative assetsupply %lld\n", (long long)assetsupply); + return(""); + } + + cp = CCinit(&C, EVAL_TOKENS); + if (name.size() > 32 || description.size() > 4096) + { + fprintf(stderr, "name.%d or description.%d is too big\n", (int32_t)name.size(), (int32_t)description.size()); + return(""); + } + if (txfee == 0) + txfee = 10000; + mypk = pubkey2pk(Mypubkey()); + + if (AddNormalinputs(mtx, mypk, assetsupply + 2 * txfee, 64) > 0) + { + mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, assetsupply, mypk)); + mtx.vout.push_back(CTxOut(txfee, CScript() << ParseHex(cp->CChexstr) << OP_CHECKSIG)); + return(FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeTokenCreateOpRet('c', Mypubkey(), name, description))); + } + return(""); +} + + +std::string TokenTransfer(int64_t txfee, uint256 assetid, std::vector destpubkey, int64_t total) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CPubKey mypk; uint64_t mask; int64_t CCchange = 0, inputs = 0; struct CCcontract_info *cp, C; + std::vector emptyExtraOpret; + + if (total < 0) + { + fprintf(stderr, "negative total %lld\n", (long long)total); + return(""); + } + cp = CCinit(&C, EVAL_TOKENS); + if (txfee == 0) + txfee = 10000; + mypk = pubkey2pk(Mypubkey()); + if (AddNormalinputs(mtx, mypk, txfee, 3) > 0) + { + //n = outputs.size(); + //if ( n == amounts.size() ) + //{ + // for (i=0; i 0) + { + + if (inputs < total) { //added dimxy + std::cerr << "AssetTransfer(): insufficient funds" << std::endl; + return (""); + } + if (inputs > total) + CCchange = (inputs - total); + //for (i=0; i voutTokenPubkeys; + voutTokenPubkeys.push_back(pubkey2pk(destpubkey)); // dest pubkey for validating vout + + return(FinalizeCCTx(mask, cp, mtx, mypk, txfee, EncodeTokenOpRet('t', EVAL_TOKENS, assetid, voutTokenPubkeys, CScript()))); // By setting EVAL_TOKENS we're getting out from assets validation code + } + else { + fprintf(stderr, "not enough CC token inputs for %.8f\n", (double)total / COIN); + } + //} else fprintf(stderr,"numoutputs.%d != numamounts.%d\n",n,(int32_t)amounts.size()); + } + else { + fprintf(stderr, "not enough normal inputs for txfee\n"); + } + return(""); +} + + +int64_t GetTokenBalance(CPubKey pk, uint256 tokenid) +{ + uint256 hashBlock; + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CTransaction tokentx; + + // CCerror = strprintf("obsolete, cannot return correct value without eval"); + // return 0; + + if (GetTransaction(tokenid, tokentx, hashBlock, false) == 0) + { + fprintf(stderr, "cant find tokenid\n"); + CCerror = strprintf("cant find tokenid"); + return 0; + } + + struct CCcontract_info *cp, C; + cp = CCinit(&C, EVAL_TOKENS); + return(AddTokenCCInputs(cp, mtx, pk, tokenid, 0, 0)); +} + +UniValue TokenInfo(uint256 tokenid) +{ + UniValue result(UniValue::VOBJ); uint256 hashBlock; CTransaction vintx; std::vector origpubkey; std::string name, description; char str[67], numstr[65]; + if (GetTransaction(tokenid, vintx, hashBlock, false) == 0) + { + fprintf(stderr, "cant find assetid\n"); + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "cant find tokenid")); + return(result); + } + if (vintx.vout.size() > 0 && DecodeTokenCreateOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, origpubkey, name, description) == 0) + { + fprintf(stderr, "assetid isnt token creation txid\n"); + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "assetid isnt token creation txid")); + } + result.push_back(Pair("result", "success")); + result.push_back(Pair("tokenid", uint256_str(str, tokenid))); + result.push_back(Pair("owner", pubkey33_str(str, origpubkey.data()))); + result.push_back(Pair("name", name)); + result.push_back(Pair("supply", vintx.vout[0].nValue)); + result.push_back(Pair("description", description)); + return(result); +} + +UniValue TokenList() +{ + UniValue result(UniValue::VARR); + std::vector > addressIndex; + struct CCcontract_info *cp, C; uint256 txid, hashBlock; + CTransaction vintx; std::vector origpubkey; + std::string name, description; char str[65]; + + cp = CCinit(&C, EVAL_TOKENS); + SetCCtxids(addressIndex, cp->normaladdr); + for (std::vector >::const_iterator it = addressIndex.begin(); it != addressIndex.end(); it++) + { + txid = it->first.txhash; + if (GetTransaction(txid, vintx, hashBlock, false) != 0) + { + if (vintx.vout.size() > 0 && DecodeTokenCreateOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, origpubkey, name, description) != 0) + { + result.push_back(uint256_str(str, txid)); + } + } + } + return(result); +} diff --git a/src/cc/CCtokens.h b/src/cc/CCtokens.h new file mode 100644 index 000000000..e7bb62101 --- /dev/null +++ b/src/cc/CCtokens.h @@ -0,0 +1,44 @@ +/****************************************************************************** + * 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. * + * * + ******************************************************************************/ + + +/* + CCassetstx has the functions that create the EVAL_ASSETS transactions. It is expected that rpc calls would call these functions. For EVAL_ASSETS, the rpc functions are in rpcwallet.cpp + + CCassetsCore has functions that are used in two contexts, both during rpc transaction create time and also during the blockchain validation. Using the identical functions is a good way to prevent them from being mismatched. The must match or the transaction will get rejected. + */ + +#ifndef CC_TOKENS_H +#define CC_TOKENS_H + +#include "CCinclude.h" + +// CCcustom +bool TokensValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn); +bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cpTokens, int64_t &inputs, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 tokenid); +//int64_t IsTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *cp, Eval* eval, std::vector &origpubkey, const CTransaction& tx, int32_t v, uint256 reftokenid, std::vector vinPubkeys); +std::string CreateToken(int64_t txfee, int64_t assetsupply, std::string name, std::string description); +std::string TokenTransfer(int64_t txfee, uint256 assetid, std::vector destpubkey, int64_t total); + +int64_t GetTokenBalance(CPubKey pk, uint256 tokenid); +UniValue TokenInfo(uint256 tokenid); +UniValue TokenList(); + +//this is in CCinclude.h int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 tokenid, int64_t total, int32_t maxinputs); + +//this is in CCinclude.h uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey,std::vector &origpubkey,std::string &name,std::string &description); + + +#endif diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index 27d796ba0..ae7483f4d 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -16,6 +16,8 @@ #include "CCinclude.h" #include "key_io.h" +std::vector NULL_pubkeys; + /* FinalizeCCTx is a very useful function that will properly sign both CC and normal inputs, adds normal change and the opreturn. @@ -38,13 +40,18 @@ bool SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScrip return(false); } -std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret) +std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret,std::vector pubkeys) { auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); - CTransaction vintx; std::string hex; uint256 hashBlock; uint64_t mask=0,nmask=0,vinimask=0; - int64_t utxovalues[64],change,normalinputs=0,totaloutputs=0,normaloutputs=0,totalinputs=0,normalvins=0,ccvins=0; - int32_t i,utxovout,n,err = 0; char myaddr[64],destaddr[64],unspendable[64]; - uint8_t *privkey,myprivkey[32],unspendablepriv[32],*msg32 = 0; CC *mycond=0,*othercond=0,*othercond2=0,*othercond3=0,*cond; CPubKey unspendablepk; + CTransaction vintx; std::string hex; CPubKey globalpk; uint256 hashBlock; uint64_t mask=0,nmask=0,vinimask=0; + int64_t utxovalues[CC_MAXVINS],change,normalinputs=0,totaloutputs=0,normaloutputs=0,totalinputs=0,normalvins=0,ccvins=0; + int32_t i,flag,utxovout,n,err = 0; + char myaddr[64], destaddr[64], unspendable[64], mytokensaddr[64], mysingletokensaddr[64], tokensunspendable[64]; + uint8_t *privkey, myprivkey[32], unspendablepriv[32], tokensunspendablepriv[32], *msg32 = 0; + CC *mycond=0, *othercond=0, *othercond2=0,*othercond4=0, *othercond3=0, *othercond1of2=NULL, *othercond1of2tokens = NULL, *cond, *mytokenscond = NULL, *mysingletokenscond = NULL, *othertokenscond = NULL; + CPubKey unspendablepk /*, tokensunspendablepk*/; + struct CCcontract_info *cpTokens, tokensC; + globalpk = GetUnspendable(cp,0); n = mtx.vout.size(); for (i=0; i 64 ) + if ( (n= mtx.vin.size()) > CC_MAXVINS ) { fprintf(stderr,"FinalizeCCTx: %d is too many vins\n",n); return("0"); } Myprivkey(myprivkey); - unspendablepk = GetUnspendable(cp,unspendablepriv); + GetCCaddress(cp,myaddr,mypk); mycond = MakeCCcond1(cp->evalcode,mypk); - GetCCaddress(cp,unspendable,unspendablepk); - othercond = MakeCCcond1(cp->evalcode,unspendablepk); + + // to spend from single-eval evalcode 'unspendable' + unspendablepk = GetUnspendable(cp, unspendablepriv); + GetCCaddress(cp, unspendable, unspendablepk); + othercond = MakeCCcond1(cp->evalcode, unspendablepk); + + // tokens support: + + // to spend from dual-eval mypk vout + GetTokensCCaddress(cp, mytokensaddr, mypk); + mytokenscond = MakeTokensCCcond1(cp->evalcode, mypk); + + // to spend from single-eval EVAL_TOKENS mypk + cpTokens = CCinit(&tokensC, EVAL_TOKENS); + GetCCaddress(cpTokens, mysingletokensaddr, mypk); + mysingletokenscond = MakeCCcond1(EVAL_TOKENS, mypk); + + // to spend from dual-eval EVAL_TOKEN+evalcode 'unspendable' pk + //tokensunspendablepk = GetUnspendable(cpTokens, tokensunspendablepriv); + GetTokensCCaddress(cp, tokensunspendable, unspendablepk); + othertokenscond = MakeTokensCCcond1(cp->evalcode, unspendablepk); + //Reorder vins so that for multiple normal vins all other except vin0 goes to the end //This is a must to avoid hardfork change of validation in every CC, because there could be maximum one normal vin at the begining with current validation. for (i=0; i (%s)\n",i,(double)utxovalues[i]/COIN,destaddr); - if ( strcmp(destaddr,myaddr) == 0 ) + //fprintf(stderr,"FinalizeCCTx() vin.%d is CC %.8f -> (%s)\n",i,(double)utxovalues[i]/COIN,destaddr); + //std::cerr << "FinalizeCCtx() searching destaddr=" << destaddr << " myaddr=" << myaddr << std::endl; + if( strcmp(destaddr,myaddr) == 0 ) { privkey = myprivkey; cond = mycond; - } + else if (strcmp(destaddr, mytokensaddr) == 0) // if this is TokensCC1vout + { + privkey = myprivkey; + cond = mytokenscond; + //fprintf(stderr,"FinalizeCCTx() matched dual-eval TokensCC1vout CC addr.(%s)\n",mytokensaddr); + } + else if (strcmp(destaddr, mysingletokensaddr) == 0) // if this is TokensCC1vout + { + privkey = myprivkey; + cond = mysingletokenscond; + //fprintf(stderr, "FinalizeCCTx() matched single-eval token CC1vout CC addr.(%s)\n", mytokensaddr); + } else if ( strcmp(destaddr,unspendable) == 0 ) { privkey = unspendablepriv; cond = othercond; - //fprintf(stderr,"unspendable CC addr.(%s)\n",unspendable); + //fprintf(stderr,"FinalizeCCTx() matched unspendable CC addr.(%s)\n",unspendable); } + else if (strcmp(destaddr, tokensunspendable) == 0) + { + privkey = unspendablepriv; + cond = othertokenscond; + //fprintf(stderr,"FinalizeCCTx() matched tokensunspendable CC addr.(%s)\n",unspendable); + } + // check if this is the 2nd additional evalcode + 'unspendable' cc addr: else if ( strcmp(destaddr,cp->unspendableaddr2) == 0) { - //fprintf(stderr,"matched %s unspendable2!\n",cp->unspendableaddr2); + //fprintf(stderr,"FinalizeCCTx() matched %s unspendable2!\n",cp->unspendableaddr2); privkey = cp->unspendablepriv2; - if ( othercond2 == 0 && cp->evalcode != EVAL_CHANNELS && cp->evalcode != EVAL_HEIR ) - othercond2 = MakeCCcond1(cp->evalcode2,cp->unspendablepk2); - else if ( othercond2 == 0 && (cp->evalcode == EVAL_CHANNELS || cp->evalcode == EVAL_HEIR) ) - othercond2 = MakeCCcond1of2(cp->evalcode2,cp->unspendablepk2,cp->unspendablepk3); + if ( othercond2 == 0 ) + othercond2 = MakeCCcond1(cp->evalcode2, cp->unspendablepk2); cond = othercond2; } + // check if this is 3rd additional evalcode + 'unspendable' cc addr: else if ( strcmp(destaddr,cp->unspendableaddr3) == 0 ) { - //fprintf(stderr,"matched %s unspendable3!\n",cp->unspendableaddr3); + //fprintf(stderr,"FinalizeCCTx() matched %s unspendable3!\n",cp->unspendableaddr3); privkey = cp->unspendablepriv3; if ( othercond3 == 0 ) othercond3 = MakeCCcond1(cp->evalcode3,cp->unspendablepk3); cond = othercond3; } + // check if this is spending from 1of2 cc coins addr: + else if (strcmp(cp->coins1of2addr, destaddr) == 0) + { + //fprintf(stderr,"FinalizeCCTx() matched %s unspendable1of2!\n",cp->coins1of2addr); + privkey = myprivkey; + if (othercond1of2 == 0) + othercond1of2 = MakeCCcond1of2(cp->evalcode, cp->coins1of2pk[0], cp->coins1of2pk[1]); + cond = othercond1of2; + } + // check if this is spending from 1of2 cc tokens addr: + else if (strcmp(cp->tokens1of2addr, destaddr) == 0) + { + //fprintf(stderr,"FinalizeCCTx() matched %s cp->tokens1of2addr!\n", cp->tokens1of2addr); + privkey = myprivkey; + if (othercond1of2tokens == 0) + othercond1of2tokens = MakeTokensCCcond1of2(cp->evalcode, cp->tokens1of2pk[0], cp->tokens1of2pk[1]); + cond = othercond1of2tokens; + } else { - fprintf(stderr,"CC signing error: vini.%d has unknown CC address.(%s)\n",i,destaddr); - continue; + flag = 0; + if ( pubkeys != NULL_pubkeys ) + { + char coinaddr[64]; + GetCCaddress1of2(cp,coinaddr,globalpk,pubkeys[i]); + //fprintf(stderr,"%s + %s -> %s vs %s\n",HexStr(globalpk).c_str(),HexStr(pubkeys[i]).c_str(),coinaddr,destaddr); + if ( strcmp(destaddr,coinaddr) == 0 ) + { + privkey = cp->CCpriv; + if ( othercond4 != 0 ) + cc_free(othercond4); + othercond4 = MakeCCcond1of2(cp->evalcode,globalpk,pubkeys[i]); + cond = othercond4; + flag = 1; + } + } + if ( flag == 0 ) + { + fprintf(stderr,"CC signing error: vini.%d has unknown CC address.(%s)\n",i,destaddr); + continue; + } } uint256 sighash = SignatureHash(CCPubKey(cond), mtx, i, SIGHASH_ALL, utxovalues[i],consensusBranchId, &txdata); if ( cc_signTreeSecp256k1Msg32(cond,privkey,sighash.begin()) != 0 ) @@ -178,6 +260,7 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran else { fprintf(stderr,"vini.%d has CC signing error address.(%s)\n",i,destaddr); + return(""); } } } else fprintf(stderr,"FinalizeCCTx couldnt find %s\n",mtx.vin[i].prevout.hash.ToString().c_str()); @@ -190,6 +273,8 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran cc_free(othercond2); if ( othercond3 != 0 ) cc_free(othercond3); + if ( othercond4 != 0 ) + cc_free(othercond4); std::string strHex = EncodeHexTx(mtx); if ( strHex.size() > 0 ) return(strHex); @@ -247,6 +332,40 @@ int64_t CCutxovalue(char *coinaddr,uint256 utxotxid,int32_t utxovout) return(0); } +int32_t CCgettxout(uint256 txid,int32_t vout,int32_t mempoolflag) +{ + CCoins coins; + if ( mempoolflag != 0 ) + { + LOCK(mempool.cs); + CCoinsViewMemPool view(pcoinsTip, mempool); + if (!view.GetCoins(txid, coins)) + return(-1); + if ( myIsutxo_spentinmempool(txid,vout) != 0 ) + return(-1); + } + else + { + if (!pcoinsTip->GetCoins(txid, coins)) + return(-1); + } + if ( vout < coins.vout.size() ) + return(coins.vout[vout].nValue); + else return(-1); +} + +int32_t CCgetspenttxid(uint256 &spenttxid,int32_t &vini,int32_t &height,uint256 txid,int32_t vout) +{ + CSpentIndexKey key(txid, vout); + CSpentIndexValue value; + if ( !GetSpentIndex(key, value) ) + return(-1); + spenttxid = value.txid; + vini = (int32_t)value.inputIndex; + height = value.blockHeight; + return(0); +} + int64_t CCaddress_balance(char *coinaddr) { int64_t sum = 0; std::vector > unspentOutputs; @@ -263,7 +382,7 @@ int64_t CCfullsupply(uint256 tokenid) uint256 hashBlock; int32_t numvouts; CTransaction tx; std::vector origpubkey; std::string name,description; if ( GetTransaction(tokenid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 ) { - if ( DecodeAssetCreateOpRet(tx.vout[numvouts-1].scriptPubKey,origpubkey,name,description) > 0 ) + if (DecodeTokenCreateOpRet(tx.vout[numvouts-1].scriptPubKey,origpubkey,name,description)) { return(tx.vout[0].nValue); } @@ -273,8 +392,11 @@ int64_t CCfullsupply(uint256 tokenid) int64_t CCtoken_balance(char *coinaddr,uint256 tokenid) { - int64_t price,sum = 0; int32_t numvouts; CTransaction tx; uint256 assetid,assetid2,txid,hashBlock; std::vector origpubkey; + int64_t price,sum = 0; int32_t numvouts; CTransaction tx; uint256 assetid,assetid2,txid,hashBlock; + std::vector vopretExtra; std::vector > unspentOutputs; + uint8_t evalCode; + SetCCunspents(unspentOutputs,coinaddr); for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { @@ -282,7 +404,8 @@ int64_t CCtoken_balance(char *coinaddr,uint256 tokenid) if ( GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 ) { char str[65]; fprintf(stderr,"check %s %.8f\n",uint256_str(str,txid),(double)it->second.satoshis/COIN); - if ( DecodeAssetOpRet(tx.vout[numvouts-1].scriptPubKey,assetid,assetid2,price,origpubkey) != 0 && assetid == tokenid ) + std::vector voutTokenPubkeys; + if ( DecodeTokenOpRet(tx.vout[numvouts-1].scriptPubKey, evalCode, assetid, voutTokenPubkeys, vopretExtra) != 0 && assetid == tokenid ) { sum += it->second.satoshis; } @@ -350,8 +473,8 @@ int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int3 { int32_t abovei,belowi,ind,vout,i,n = 0,maxutxos=64; int64_t sum,threshold,above,below; int64_t remains,nValue,totalinputs = 0; uint256 txid,hashBlock; std::vector vecOutputs; CTransaction tx; struct CC_utxo *utxos,*up; #ifdef ENABLE_WALLET - const CKeyStore& keystore = *pwalletMain; assert(pwalletMain != NULL); + const CKeyStore& keystore = *pwalletMain; LOCK2(cs_main, pwalletMain->cs_wallet); pwalletMain->AvailableCoins(vecOutputs, false, NULL, true); utxos = (struct CC_utxo *)calloc(maxutxos,sizeof(*utxos)); diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index e10d97224..766ce1188 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -76,6 +76,54 @@ CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk1,CPubKey pk2) return(vout); } +CC *MakeTokensCCcond1of2(uint8_t evalcode, CPubKey pk1, CPubKey pk2) +{ + // make 1of2 sigs cond + std::vector pks; + pks.push_back(CCNewSecp256k1(pk1)); + pks.push_back(CCNewSecp256k1(pk2)); + + std::vector thresholds; + thresholds.push_back( CCNewEval(E_MARSHAL(ss << evalcode)) ); + if( evalcode != EVAL_TOKENS ) // if evalCode == EVAL_TOKENS, it is actually MakeCCcond1of2()! + thresholds.push_back(CCNewEval(E_MARSHAL(ss << (uint8_t)EVAL_TOKENS))); // this is eval token cc + thresholds.push_back(CCNewThreshold(1, pks)); // this is 1 of 2 sigs cc + + return CCNewThreshold(thresholds.size(), thresholds); +} + +CC *MakeTokensCCcond1(uint8_t evalcode, CPubKey pk) +{ + std::vector pks; + pks.push_back(CCNewSecp256k1(pk)); + + std::vector thresholds; + thresholds.push_back(CCNewEval(E_MARSHAL(ss << evalcode))); + if (evalcode != EVAL_TOKENS) // if evalCode == EVAL_TOKENS, it is actually MakeCCcond1()! + thresholds.push_back(CCNewEval(E_MARSHAL(ss << (uint8_t)EVAL_TOKENS))); // this is eval token cc + thresholds.push_back(CCNewThreshold(1, pks)); // signature + + return CCNewThreshold(thresholds.size(), thresholds); +} + +CTxOut MakeTokensCC1of2vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2) +{ + CTxOut vout; + CC *payoutCond = MakeTokensCCcond1of2(evalcode, pk1, pk2); + vout = CTxOut(nValue, CCPubKey(payoutCond)); + cc_free(payoutCond); + return(vout); +} + +CTxOut MakeTokensCC1vout(uint8_t evalcode, CAmount nValue, CPubKey pk) +{ + CTxOut vout; + CC *payoutCond = MakeTokensCCcond1(evalcode, pk); + vout = CTxOut(nValue, CCPubKey(payoutCond)); + cc_free(payoutCond); + return(vout); +} + CC* GetCryptoCondition(CScript const& scriptSig) { auto pc = scriptSig.begin(); @@ -195,6 +243,22 @@ void CCaddr3set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t * strcpy(cp->unspendableaddr3,coinaddr); } +// set pubkeys, myprivkey and 1of2 cc addr for spending from 1of2 cryptocondition vout: +void CCaddr1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, char *coinaddr) +{ + cp->coins1of2pk[0] = pk1; + cp->coins1of2pk[1] = pk2; + strcpy(cp->coins1of2addr, coinaddr); +} + +// set pubkeys, myprivkey and 1of2 cc addr for spending from 1of2 tokens cryptocondition vout: +void CCaddrTokens1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, char *coinaddr) +{ + cp->tokens1of2pk[0] = pk1; + cp->tokens1of2pk[1] = pk2; + strcpy(cp->tokens1of2addr, coinaddr); +} + bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey) { CTxDestination address; txnouttype whichType; @@ -287,6 +351,27 @@ bool GetCCaddress(struct CCcontract_info *cp,char *destaddr,CPubKey pk) return(_GetCCaddress(destaddr,cp->evalcode,pk)); } +bool _GetTokensCCaddress(char *destaddr, uint8_t evalcode, CPubKey pk) +{ + CC *payoutCond; + destaddr[0] = 0; + if ((payoutCond = MakeTokensCCcond1(evalcode, pk)) != 0) + { + Getscriptaddress(destaddr, CCPubKey(payoutCond)); + cc_free(payoutCond); + } + return(destaddr[0] != 0); +} + +bool GetTokensCCaddress(struct CCcontract_info *cp, char *destaddr, CPubKey pk) +{ + destaddr[0] = 0; + if (pk.size() == 0) + pk = GetUnspendable(cp, 0); + return(_GetTokensCCaddress(destaddr, cp->evalcode, pk)); +} + + bool GetCCaddress1of2(struct CCcontract_info *cp,char *destaddr,CPubKey pk,CPubKey pk2) { CC *payoutCond; @@ -299,17 +384,29 @@ bool GetCCaddress1of2(struct CCcontract_info *cp,char *destaddr,CPubKey pk,CPubK return(destaddr[0] != 0); } -bool ConstrainVout(CTxOut vout,int32_t CCflag,char *cmpaddr,int64_t nValue) +bool GetTokensCCaddress1of2(struct CCcontract_info *cp, char *destaddr, CPubKey pk, CPubKey pk2) +{ + CC *payoutCond; + destaddr[0] = 0; + if ((payoutCond = MakeTokensCCcond1of2(cp->evalcode, pk, pk2)) != 0) + { + Getscriptaddress(destaddr, CCPubKey(payoutCond)); + cc_free(payoutCond); + } + return(destaddr[0] != 0); +} + +bool ConstrainVout(CTxOut vout, int32_t CCflag, char *cmpaddr, int64_t nValue) { char destaddr[64]; if ( vout.scriptPubKey.IsPayToCryptoCondition() != CCflag ) { - fprintf(stderr,"constrain vout error isCC %d vs %d CCflag\n",vout.scriptPubKey.IsPayToCryptoCondition(),CCflag); + fprintf(stderr,"constrain vout error isCC %d vs %d CCflag\n", vout.scriptPubKey.IsPayToCryptoCondition(), CCflag); return(false); } - else if ( cmpaddr != 0 && (Getscriptaddress(destaddr,vout.scriptPubKey) == 0 || strcmp(destaddr,cmpaddr) != 0) ) + else if ( cmpaddr != 0 && (Getscriptaddress(destaddr, vout.scriptPubKey) == 0 || strcmp(destaddr, cmpaddr) != 0) ) { - fprintf(stderr,"constrain vout error addr %s vs %s\n",cmpaddr!=0?cmpaddr:"",destaddr!=0?destaddr:""); + fprintf(stderr,"constrain vout error: check addr %s vs script addr %s\n", cmpaddr!=0?cmpaddr:"", destaddr!=0?destaddr:""); return(false); } else if ( nValue != 0 && nValue != vout.nValue ) //(nValue == 0 && vout.nValue < 10000) || ( @@ -396,39 +493,10 @@ CPubKey GetUnspendable(struct CCcontract_info *cp,uint8_t *unspendablepriv) return(pubkey2pk(ParseHex(cp->CChexstr))); } -bool ProcessCC(struct CCcontract_info *cp,Eval* eval, std::vector paramsNull,const CTransaction &ctx, unsigned int nIn) +void CCclearvars(struct CCcontract_info *cp) { - CTransaction createTx; uint256 assetid,assetid2,hashBlock; uint8_t funcid; int32_t height,i,n,from_mempool = 0; int64_t amount; std::vector origpubkey; - height = KOMODO_CONNECTING; - if ( KOMODO_CONNECTING < 0 ) // always comes back with > 0 for final confirmation - return(true); - if ( ASSETCHAINS_CC == 0 || (height & ~(1<<30)) < KOMODO_CCACTIVATE ) - return eval->Invalid("CC are disabled or not active yet"); - if ( (KOMODO_CONNECTING & (1<<30)) != 0 ) - { - from_mempool = 1; - height &= ((1<<30) - 1); - } - //fprintf(stderr,"KOMODO_CONNECTING.%d mempool.%d vs CCactive.%d\n",height,from_mempool,KOMODO_CCACTIVATE); - // there is a chance CC tx is valid in mempool, but invalid when in block, so we cant filter duplicate requests. if any of the vins are spent, for example - //txid = ctx.GetHash(); - //if ( txid == cp->prevtxid ) - // return(true); - //fprintf(stderr,"process CC %02x\n",cp->evalcode); cp->evalcode2 = cp->evalcode3 = 0; cp->unspendableaddr2[0] = cp->unspendableaddr3[0] = 0; - if ( paramsNull.size() != 0 ) // Don't expect params - return eval->Invalid("Cannot have params"); - //else if ( ctx.vout.size() == 0 ) // spend can go to z-addresses - // return eval->Invalid("no-vouts"); - else if ( (*cp->validate)(cp,eval,ctx,nIn) != 0 ) - { - //fprintf(stderr,"done CC %02x\n",cp->evalcode); - //cp->prevtxid = txid; - return(true); - } - //fprintf(stderr,"invalid CC %02x\n",cp->evalcode); - return(false); } int64_t CCduration(int32_t &numblocks,uint256 txid) @@ -502,3 +570,109 @@ bool komodo_txnotarizedconfirmed(uint256 txid) return (true); return (false); } + +CPubKey check_signing_pubkey(CScript scriptSig) +{ + bool found = false; + CPubKey pubkey; + + auto findEval = [](CC *cond, struct CCVisitor _) { + bool r = false; + + if (cc_typeId(cond) == CC_Secp256k1) { + *(CPubKey*)_.context=buf2pk(cond->publicKey); + r = true; + } + // false for a match, true for continue + return r ? 0 : 1; + }; + + CC *cond = GetCryptoCondition(scriptSig); + + if (cond) { + CCVisitor visitor = { findEval, (uint8_t*)"", 0, &pubkey }; + bool out = !cc_visit(cond, visitor); + cc_free(cond); + + if (pubkey.IsValid()) { + return pubkey; + } + } + return CPubKey(); +} + +bool ProcessCC(struct CCcontract_info *cp,Eval* eval, std::vector paramsNull,const CTransaction &ctx, unsigned int nIn) +{ + CTransaction createTx; uint256 assetid,assetid2,hashBlock; uint8_t funcid; int32_t height,i,n,from_mempool = 0; int64_t amount; std::vector origpubkey; + height = KOMODO_CONNECTING; + if ( KOMODO_CONNECTING < 0 ) // always comes back with > 0 for final confirmation + return(true); + if ( ASSETCHAINS_CC == 0 || (height & ~(1<<30)) < KOMODO_CCACTIVATE ) + return eval->Invalid("CC are disabled or not active yet"); + if ( (KOMODO_CONNECTING & (1<<30)) != 0 ) + { + from_mempool = 1; + height &= ((1<<30) - 1); + } + //fprintf(stderr,"KOMODO_CONNECTING.%d mempool.%d vs CCactive.%d\n",height,from_mempool,KOMODO_CCACTIVATE); + // there is a chance CC tx is valid in mempool, but invalid when in block, so we cant filter duplicate requests. if any of the vins are spent, for example + //txid = ctx.GetHash(); + //if ( txid == cp->prevtxid ) + // return(true); + //fprintf(stderr,"process CC %02x\n",cp->evalcode); + CCclearvars(cp); + if ( paramsNull.size() != 0 ) // Don't expect params + return eval->Invalid("Cannot have params"); + //else if ( ctx.vout.size() == 0 ) // spend can go to z-addresses + // return eval->Invalid("no-vouts"); + else if ( (*cp->validate)(cp,eval,ctx,nIn) != 0 ) + { + //fprintf(stderr,"done CC %02x\n",cp->evalcode); + //cp->prevtxid = txid; + return(true); + } + //fprintf(stderr,"invalid CC %02x\n",cp->evalcode); + return(false); +} + +extern struct CCcontract_info CCinfos[0x100]; +extern std::string MYCCLIBNAME; +bool CClib_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx,unsigned int nIn); + +bool CClib_Dispatch(const CC *cond,Eval *eval,std::vector paramsNull,const CTransaction &txTo,unsigned int nIn) +{ + uint8_t evalcode; int32_t height,from_mempool; struct CCcontract_info *cp; + if ( ASSETCHAINS_CCLIB != MYCCLIBNAME ) + { + fprintf(stderr,"-ac_cclib=%s vs myname %s\n",ASSETCHAINS_CCLIB.c_str(),MYCCLIBNAME.c_str()); + return eval->Invalid("-ac_cclib name mismatches myname"); + } + height = KOMODO_CONNECTING; + if ( KOMODO_CONNECTING < 0 ) // always comes back with > 0 for final confirmation + return(true); + if ( ASSETCHAINS_CC == 0 || (height & ~(1<<30)) < KOMODO_CCACTIVATE ) + return eval->Invalid("CC are disabled or not active yet"); + if ( (KOMODO_CONNECTING & (1<<30)) != 0 ) + { + from_mempool = 1; + height &= ((1<<30) - 1); + } + evalcode = cond->code[0]; + if ( evalcode >= EVAL_FIRSTUSER && evalcode <= EVAL_LASTUSER ) + { + cp = &CCinfos[(int32_t)evalcode]; + if ( cp->didinit == 0 ) + { + if ( CClib_initcp(cp,evalcode) == 0 ) + cp->didinit = 1; + else return eval->Invalid("unsupported CClib evalcode"); + } + CCclearvars(cp); + if ( paramsNull.size() != 0 ) // Don't expect params + return eval->Invalid("Cannot have params"); + else if ( CClib_validate(cp,height,eval,txTo,nIn) != 0 ) + return(true); + return(false); //eval->Invalid("error in CClib_validate"); + } + return eval->Invalid("cclib CC must have evalcode between 16 and 127"); +} diff --git a/src/cc/Makefile b/src/cc/Makefile new file mode 100644 index 000000000..92fbe0da9 --- /dev/null +++ b/src/cc/Makefile @@ -0,0 +1,34 @@ +SHELL = /bin/sh +CC = gcc +CC_DARWIN = g++-6 +CC_WIN = x86_64-w64-mingw32-gcc-posix +CFLAGS_DARWIN = -std=c++11 -arch x86_64 -I/usr/local/Cellar/gcc\@6/6.4.0_2/include/c++/6.4.0/ -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -c -Wl,-undefined -Wl,dynamic_lookup -dynamiclib +CFLAGS = -std=c++11 -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c +CFLAGS_WIN = -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c +DEBUGFLAGS = -O0 -D _DEBUG +RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program +$(info $(OS)) +OS := $(shell uname -s) +$(info $(OS)) +TARGET = ../libcc.so +TARGET_DARWIN = ../libcc.dylib +TARGET_WIN = ../libcc.dll +SOURCES = cclib.cpp +#HEADERS = $(shell echo ../cryptoconditions/include/*.h) + +all: $(TARGET) + +$(TARGET): $(SOURCES) + $(info Building cclib to src/) +ifeq ($(OS),Darwin) + $(CC_DARWIN) $(CFLAGS_DARWIN) $(DEBUGFLAGS) -o $(TARGET_DARWIN) $(SOURCES) +else ifeq ($(OS),Linux) + $(CC) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) $(SOURCES) +#else ifeq ($(WIN_HOST),True) - todo: pass ENV var from build.sh if WIN host +else + $(info WINDOWS) + $(CC_WIN) $(CFLAGS_WIN) $(DEBUGFLAGS) -o $(TARGET_WIN) $(SOURCES) +endif + +clean: + rm -rf $(TARGET) diff --git a/src/cc/README.md b/src/cc/README.md new file mode 100644 index 000000000..d12a75c43 --- /dev/null +++ b/src/cc/README.md @@ -0,0 +1,7 @@ +## CCLIB +Please follow the below instructions to build the cryptoconditions library into the Komodo source directory `komodo/src` - supported operating systems are Linux, OSX and Windows (mingw crossbuild): + +``` +make clean +make +``` diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index 378c427a9..2433473b9 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -45,32 +45,22 @@ valid CC output: create or transfer or buyoffer or selloffer or exchange or cancel or fill - create - vin.0: normal input - vout.0: issuance assetoshis to CC - vout.1: tag sent to normal address of AssetsCCaddress - vout.2: normal output for change (if any) - vout.n-1: opreturn [EVAL_ASSETS] ['c'] [origpubkey] "" "" - - transfer - vin.0: normal input - vin.1 .. vin.n-1: valid CC outputs - vout.0 to n-2: assetoshis output to CC - vout.n-2: normal output for change (if any) - vout.n-1: opreturn [EVAL_ASSETS] ['t'] [assetid] buyoffer: vins.*: normal inputs (bid + change) vout.0: amount of bid to unspendable - vout.1: normal output for change (if any) + vout.1: CC output for marker + vout.2: normal output for change (if any) vout.n-1: opreturn [EVAL_ASSETS] ['b'] [assetid] [amount of asset required] [origpubkey] cancelbuy: vin.0: normal input vin.1: unspendable.(vout.0 from buyoffer) buyTx.vout[0] + vin.2: CC marker from buyoffer for txfee vout.0: vin.1 value to original pubkey buyTx.vout[0].nValue -> [origpubkey] - vout.1: normal output for change (if any) - vout.n-1: opreturn [EVAL_ASSETS] ['o'] [assetid] + vout.1: vin.2 back to users pubkey + vout.2: normal output for change (if any) + vout.n-1: opreturn [EVAL_ASSETS] ['o'] [assetid] 0 0 [origpubkey] fillbuy: vin.0: normal input @@ -87,8 +77,9 @@ vin.0: normal input vin.1+: valid CC output for sale vout.0: vin.1 assetoshis output to CC to unspendable - vout.1: CC output for change (if any) - vout.2: normal output for change (if any) + vout.1: CC output for marker + vout.2: CC output for change (if any) + vout.3: normal output for change (if any) vout.n-1: opreturn [EVAL_ASSETS] ['s'] [assetid] [amount of native coin required] [origpubkey] exchange: @@ -102,8 +93,10 @@ cancel: vin.0: normal input vin.1: unspendable.(vout.0 from exchange or selloffer) sellTx/exchangeTx.vout[0] inputTx + vin.2: CC marker from selloffer for txfee vout.0: vin.1 assetoshis to original pubkey CC sellTx/exchangeTx.vout[0].nValue -> [origpubkey] - vout.1: normal output for change (if any) + vout.1: vin.2 back to users pubkey + vout.2: normal output for change (if any) vout.n-1: opreturn [EVAL_ASSETS] ['x'] [assetid] fillsell: @@ -133,45 +126,80 @@ // tx validation -bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) +bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransaction &tx, uint32_t nIn) { static uint256 zero; - CTxDestination address; CTransaction vinTx,createTx; uint256 hashBlock,assetid,assetid2; int32_t i,starti,numvins,numvouts,preventCCvins,preventCCvouts; int64_t remaining_price,nValue,assetoshis,outputs,inputs,tmpprice,totalunits,ignore; std::vector origpubkey,tmporigpubkey,ignorepubkey; uint8_t funcid; char destaddr[64],origaddr[64],CCaddr[64]; + CTxDestination address; CTransaction vinTx,createTx; uint256 hashBlock,assetid,assetid2; + int32_t i,starti,numvins,numvouts,preventCCvins,preventCCvouts; + int64_t remaining_price,nValue,assetoshis,outputs,inputs,tmpprice,totalunits,ignore; std::vector origpubkey,tmporigpubkey,ignorepubkey; + uint8_t funcid, evalCodeInOpret; + char destaddr[64], origaddr[64], assetsCCaddr[64], userTokensCCaddr[64]; //, signleEvalTokensCCaddr[64]; + + //return true; + + //CPubKey unspendableTokensPk = GetUnspendable(cpTokens, NULL); + //CPubKey unspendableAssetsPk = GetUnspendable(cpAssets, NULL); + //GetCCaddress(cpTokens, tokensUnspendableCCaddr, unspendableTokensPk); + numvins = tx.vin.size(); numvouts = tx.vout.size(); outputs = inputs = 0; preventCCvins = preventCCvouts = -1; - if ( (funcid= DecodeAssetOpRet(tx.vout[numvouts-1].scriptPubKey,assetid,assetid2,remaining_price,origpubkey)) == 0 ) - return eval->Invalid("Invalid opreturn payload"); + + if (numvouts == 0) + return eval->Invalid("AssetValidate: no vouts"); + + if((funcid = DecodeAssetTokenOpRet(tx.vout[numvouts-1].scriptPubKey, evalCodeInOpret, assetid, assetid2, remaining_price, origpubkey)) == 0 ) + return eval->Invalid("AssetValidate: invalid opreturn payload"); + + // find dual-eval tokens unspendable addr: + char tokensUnspendableAddr[64],origpubkeyCCaddr[64]; + GetTokensCCaddress(cpAssets, tokensUnspendableAddr, GetUnspendable(cpAssets, NULL)); + GetCCaddress(cpAssets, origpubkeyCCaddr, origpubkey); + + // we need this for validating single-eval tokens' vins/vous: + struct CCcontract_info *cpTokens, tokensC; + cpTokens = CCinit(&tokensC, EVAL_TOKENS); + + // find single-eval token user cc addr: + //GetCCaddress(cpTokens, signleEvalTokensCCaddr, pubkey2pk(origpubkey)); + fprintf(stderr,"AssetValidate (%c)\n",funcid); - if ( funcid != 'o' && funcid != 'x' && eval->GetTxUnconfirmed(assetid,createTx,hashBlock) == 0 ) + + if( funcid != 'o' && funcid != 'x' && eval->GetTxUnconfirmed(assetid, createTx, hashBlock) == 0 ) return eval->Invalid("cant find asset create txid"); - else if ( funcid != 'o' && funcid != 'x' && assetid2 != zero && eval->GetTxUnconfirmed(assetid2,createTx,hashBlock) == 0 ) + else if( funcid != 'o' && funcid != 'x' && assetid2 != zero && eval->GetTxUnconfirmed(assetid2, createTx, hashBlock) == 0 ) return eval->Invalid("cant find asset2 create txid"); - else if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) + else if( IsCCInput(tx.vin[0].scriptSig) != 0 ) return eval->Invalid("illegal asset vin0"); - else if ( numvouts < 1 ) - return eval->Invalid("no vouts"); - else if ( funcid != 'c' ) + else if( numvouts < 2 ) + return eval->Invalid("too few vouts"); // it was if(numvouts < 1) but it refers at least to vout[1] below + else if( funcid != 'c' ) { - if ( funcid == 't' ) + /* if( funcid == 't' ) starti = 0; - else starti = 1; - if ( assetid == zero ) + else + starti = 1; */ + + if( assetid == zero ) return eval->Invalid("illegal assetid"); - else if ( AssetExactAmounts(2, cp,inputs,starti,outputs,eval,tx,assetid) == false ) - return eval->Invalid("asset inputs != outputs"); + + else if (!AssetCalcAmounts(cpAssets, inputs, outputs, eval, tx, assetid)) { // Only set inputs and outputs. NOTE: we do not need to check cc inputs == cc outputs + return false; // returns false if some problems with reading vintxes + } } - - switch ( funcid ) + switch( funcid ) { case 'c': // create wont be called to be verified as it has no CC inputs //vin.0: normal input //vout.0: issuance assetoshis to CC //vout.1: normal output for change (if any) //vout.n-1: opreturn [EVAL_ASSETS] ['c'] [{"":""}] - return eval->Invalid("unexpected AssetValidate for createasset"); + //if (evalCodeInOpret == EVAL_ASSETS) + // return eval->Invalid("unexpected AssetValidate for createasset"); + // return + return eval->Invalid("invalid asset funcid \'c\'"); break; case 't': // transfer //vin.0: normal input @@ -179,36 +207,40 @@ bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx //vout.0 to n-2: assetoshis output to CC //vout.n-2: normal output for change (if any) //vout.n-1: opreturn [EVAL_ASSETS] ['t'] [assetid] - if ( inputs == 0 ) - return eval->Invalid("no asset inputs for transfer"); - fprintf(stderr,"transfer validated %.8f -> %.8f (%d %d)\n",(double)inputs/COIN,(double)outputs/COIN,preventCCvins,preventCCvouts); + //if (inputs == 0) + // return eval->Invalid("no asset inputs for transfer"); + //fprintf(stderr,"transfer preliminarily validated %.8f -> %.8f (%d %d)\n",(double)inputs/COIN,(double)outputs/COIN,preventCCvins,preventCCvouts); + return eval->Invalid("invalid asset funcid \'t\'"); break; case 'b': // buyoffer //vins.*: normal inputs (bid + change) //vout.0: amount of bid to unspendable - //vout.1: normal output for change (if any) + //vout.1: CC output for marker + //vout.2: normal output for change (if any) // vout.n-1: opreturn [EVAL_ASSETS] ['b'] [assetid] [amount of asset required] [origpubkey] - if ( remaining_price == 0 ) + if( remaining_price == 0 ) return eval->Invalid("illegal null amount for buyoffer"); - else if ( ConstrainVout(tx.vout[0],1,cp->unspendableCCaddr,0) == 0 ) + else if( ConstrainVout(tx.vout[0],1,cpAssets->unspendableCCaddr,0) == 0 ) return eval->Invalid("invalid vout for buyoffer"); preventCCvins = 1; preventCCvouts = 1; - fprintf(stderr,"buy offer validated to destaddr.(%s)\n",cp->unspendableCCaddr); + fprintf(stderr,"buy offer validated to destaddr.(%s)\n",cpAssets->unspendableCCaddr); break; case 'o': // cancelbuy //vin.0: normal input //vin.1: unspendable.(vout.0 from buyoffer) buyTx.vout[0] + //vin.2: CC marker from buyoffer for txfee //vout.0: vin.1 value to original pubkey buyTx.vout[0].nValue -> [origpubkey] - //vout.1: normal output for change (if any) + //vout.1: vin.2 back to users pubkey + //vout.2: normal output for change (if any) //vout.n-1: opreturn [EVAL_ASSETS] ['o'] - if ( (nValue= AssetValidateBuyvin(cp,eval,tmpprice,tmporigpubkey,CCaddr,origaddr,tx,assetid)) == 0 ) + if( (nValue= AssetValidateBuyvin(cpAssets, eval, tmpprice, tmporigpubkey, assetsCCaddr, origaddr, tx, assetid)) == 0 ) return(false); - else if ( ConstrainVout(tx.vout[0],0,origaddr,nValue) == 0 ) + else if( ConstrainVout(tx.vout[0],0, origaddr, nValue) == 0 ) return eval->Invalid("invalid refund for cancelbuy"); - preventCCvins = 2; + preventCCvins = 3; preventCCvouts = 0; fprintf(stderr,"cancelbuy validated to origaddr.(%s)\n",origaddr); break; @@ -224,32 +256,35 @@ bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx //vout.4: normal output for change (if any) //vout.n-1: opreturn [EVAL_ASSETS] ['B'] [assetid] [remaining asset required] [origpubkey] preventCCvouts = 4; - if ( (nValue= AssetValidateBuyvin(cp,eval,totalunits,tmporigpubkey,CCaddr,origaddr,tx,assetid)) == 0 ) + + if( (nValue = AssetValidateBuyvin(cpAssets, eval, totalunits, tmporigpubkey, assetsCCaddr, origaddr, tx, assetid)) == 0 ) return(false); - else if ( numvouts < 3 ) + else if( numvouts < 4 ) return eval->Invalid("not enough vouts for fillbuy"); - else if ( tmporigpubkey != origpubkey ) + else if( tmporigpubkey != origpubkey ) return eval->Invalid("mismatched origpubkeys for fillbuy"); else { - if ( nValue != tx.vout[0].nValue+tx.vout[1].nValue ) + if( nValue != tx.vout[0].nValue + tx.vout[1].nValue ) return eval->Invalid("locked value doesnt match vout0+1 fillbuy"); - else if ( tx.vout[3].scriptPubKey.IsPayToCryptoCondition() != 0 ) + else if( tx.vout[4].scriptPubKey.IsPayToCryptoCondition() != 0 ) { - if ( ConstrainVout(tx.vout[2],1,CCaddr,0) == 0 ) + if( ConstrainVout(tx.vout[2], 1, assetsCCaddr, 0) == 0 ) // tokens on user cc addr return eval->Invalid("vout2 doesnt go to origpubkey fillbuy"); - else if ( inputs != tx.vout[2].nValue+tx.vout[3].nValue ) + else if ( inputs != tx.vout[2].nValue + tx.vout[4].nValue ) return eval->Invalid("asset inputs doesnt match vout2+3 fillbuy"); } - else if ( ConstrainVout(tx.vout[2],1,CCaddr,inputs) == 0 ) + else if( ConstrainVout(tx.vout[2], 1, assetsCCaddr, inputs) == 0 ) // tokens on user cc addr return eval->Invalid("vout2 doesnt match inputs fillbuy"); - else if ( ConstrainVout(tx.vout[1],0,0,0) == 0 ) + else if( ConstrainVout(tx.vout[1],0,0,0) == 0 ) return eval->Invalid("vout1 is CC for fillbuy"); - else if ( ValidateBidRemainder(remaining_price,tx.vout[0].nValue,nValue,tx.vout[1].nValue,tx.vout[2].nValue,totalunits) == false ) + else if( ConstrainVout(tx.vout[3], 1, origpubkeyCCaddr, 10000) == 0 ) + return eval->Invalid("invalid marker for original pubkey"); + else if( ValidateBidRemainder(remaining_price, tx.vout[0].nValue, nValue, tx.vout[1].nValue, tx.vout[2].nValue, totalunits) == false ) return eval->Invalid("mismatched remainder for fillbuy"); - else if ( remaining_price != 0 ) + else if( remaining_price != 0 ) { - if ( ConstrainVout(tx.vout[0],1,cp->unspendableCCaddr,0) == 0 ) + if( ConstrainVout(tx.vout[0], 1, cpAssets->unspendableCCaddr, 0) == 0 ) // coins on asset unspendable cc addr return eval->Invalid("mismatched vout0 AssetsCCaddr for fillbuy"); } } @@ -261,36 +296,43 @@ bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx //vin.0: normal input //vin.1+: valid CC output for sale //vout.0: vin.1 assetoshis output to CC to unspendable - //vout.1: CC output for change (if any) - //vout.2: normal output for change (if any) + //vout.1: CC output for marker + //vout.2: CC output for change (if any) + //vout.3: normal output for change (if any) //'s'.vout.n-1: opreturn [EVAL_ASSETS] ['s'] [assetid] [amount of native coin required] [origpubkey] //'e'.vout.n-1: opreturn [EVAL_ASSETS] ['e'] [assetid] [assetid2] [amount of asset2 required] [origpubkey] - preventCCvouts = 1; - if ( remaining_price == 0 ) + preventCCvouts = 2; + if( remaining_price == 0 ) return eval->Invalid("illegal null remaining_price for selloffer"); - if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() != 0 ) + if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("invalid normal vout1 for sellvin"); + if( tx.vout[2].scriptPubKey.IsPayToCryptoCondition() != 0 ) // cc change { preventCCvouts++; - if ( ConstrainVout(tx.vout[0],1,(char *)cp->unspendableCCaddr,0) == 0 ) - return eval->Invalid("mismatched vout0 AssetsCCaddr for selloffer"); - else if ( tx.vout[0].nValue+tx.vout[1].nValue != inputs ) - return eval->Invalid("mismatched vout0+vout1 total for selloffer"); - } else if ( ConstrainVout(tx.vout[0],1,(char *)cp->unspendableCCaddr,inputs) == 0 ) - return eval->Invalid("mismatched vout0 AssetsCCaddr for selloffer"); + if( ConstrainVout(tx.vout[0], 1, (char *)cpTokens->unspendableCCaddr, 0) == 0 ) // check also cc vout[0] + return eval->Invalid("mismatched vout0 TokensCCaddr for selloffer"); + else if( tx.vout[0].nValue + tx.vout[2].nValue != inputs ) + return eval->Invalid("mismatched vout0+vout2 total for selloffer"); + } + else if( ConstrainVout(tx.vout[0], 1, (char *)cpTokens->unspendableCCaddr, inputs) == 0 ) // no cc change, just vout[0] + return eval->Invalid("mismatched vout0 TokensCCaddr for selloffer"); //fprintf(stderr,"remaining.%d for sell\n",(int32_t)remaining_price); break; - case 'x': // cancel + case 'x': // cancel //vin.0: normal input //vin.1: unspendable.(vout.0 from exchange or selloffer) sellTx/exchangeTx.vout[0] inputTx + //vin.2: CC marker from selloffer for txfee //vout.0: vin.1 assetoshis to original pubkey CC sellTx/exchangeTx.vout[0].nValue -> [origpubkey] - //vout.1: normal output for change (if any) + //vout.1: vin.2 back to users pubkey + //vout.2: normal output for change (if any) //vout.n-1: opreturn [EVAL_ASSETS] ['x'] [assetid] - if ( (assetoshis= AssetValidateSellvin(cp,eval,tmpprice,tmporigpubkey,CCaddr,origaddr,tx,assetid)) == 0 ) + + if( (assetoshis = AssetValidateSellvin(cpAssets, eval, tmpprice, tmporigpubkey, userTokensCCaddr, origaddr, tx, assetid)) == 0 ) // NOTE: return(false); - else if ( ConstrainVout(tx.vout[0],1,CCaddr,assetoshis) == 0 ) + else if( ConstrainVout(tx.vout[0], 1, userTokensCCaddr, assetoshis) == 0 ) return eval->Invalid("invalid vout for cancel"); - preventCCvins = 2; + preventCCvins = 3; preventCCvouts = 1; break; @@ -303,31 +345,37 @@ bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx //'S'.vout.2: vin.2 value to original pubkey [origpubkey] //vout.3: normal output for change (if any) //'S'.vout.n-1: opreturn [EVAL_ASSETS] ['S'] [assetid] [amount of coin still required] [origpubkey] - if ( (assetoshis= AssetValidateSellvin(cp,eval,totalunits,tmporigpubkey,CCaddr,origaddr,tx,assetid)) == 0 ) + + if( (assetoshis = AssetValidateSellvin(cpAssets, eval, totalunits, tmporigpubkey, userTokensCCaddr, origaddr, tx, assetid)) == 0 ) return(false); - else if ( numvouts < 3 ) + else if( numvouts < 4 ) return eval->Invalid("not enough vouts for fillask"); - else if ( tmporigpubkey != origpubkey ) + else if( tmporigpubkey != origpubkey ) return eval->Invalid("mismatched origpubkeys for fillask"); else { - if ( assetoshis != tx.vout[0].nValue+tx.vout[1].nValue ) + if( assetoshis != tx.vout[0].nValue + tx.vout[1].nValue ) return eval->Invalid("locked value doesnt match vout0+1 fillask"); - if ( ValidateAskRemainder(remaining_price,tx.vout[0].nValue,assetoshis,tx.vout[1].nValue,tx.vout[2].nValue,totalunits) == false ) + if( ValidateAskRemainder(remaining_price, tx.vout[0].nValue, assetoshis, tx.vout[1].nValue, tx.vout[2].nValue, totalunits) == false ) return eval->Invalid("mismatched remainder for fillask"); - else if ( ConstrainVout(tx.vout[1],1,0,0) == 0 ) + else if( ConstrainVout(tx.vout[1], 1, 0, 0) == 0 ) return eval->Invalid("normal vout1 for fillask"); - else if ( ConstrainVout(tx.vout[2],0,origaddr,0) == 0 ) + else if( ConstrainVout(tx.vout[2], 0, origaddr, 0) == 0 ) return eval->Invalid("normal vout1 for fillask"); - else if ( remaining_price != 0 ) + else if( ConstrainVout(tx.vout[3], 1, origpubkeyCCaddr, 10000) == 0 ) + return eval->Invalid("invalid marker for original pubkey"); + else if( remaining_price != 0 ) { - if ( ConstrainVout(tx.vout[0],1,(char *)cp->unspendableCCaddr,0) == 0 ) - return eval->Invalid("mismatched vout0 AssetsCCaddr for fill"); + //char tokensUnspendableAddr[64]; + //GetTokensCCaddress(cpAssets, tokensUnspendableAddr, GetUnspendable(cpAssets, NULL)); + if ( ConstrainVout(tx.vout[0], 1, tokensUnspendableAddr /*(char *)cpAssets->unspendableCCaddr*/, 0) == 0 ) + return eval->Invalid("mismatched vout0 assets dual unspendable CCaddr for fill sell"); } } fprintf(stderr,"fill validated\n"); break; case 'E': // fillexchange + ////////// not implemented yet //////////// return eval->Invalid("unexpected assets fillexchange funcid"); break; // disable asset swaps //vin.0: normal input @@ -339,51 +387,63 @@ bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx //vout.3: CC output for asset2 change (if any) //vout.3/4: normal output for change (if any) //vout.n-1: opreturn [EVAL_ASSETS] ['E'] [assetid vin0+1] [assetid vin2] [remaining asset2 required] [origpubkey] - if ( AssetExactAmounts(1, cp,inputs,1,outputs,eval,tx,assetid2) == false ) - eval->Invalid("asset2 inputs != outputs"); - if ( (assetoshis= AssetValidateSellvin(cp,eval,totalunits,tmporigpubkey,CCaddr,origaddr,tx,assetid)) == 0 ) + + //if ( AssetExactAmounts(false, cp,inputs,outputs,eval,tx,assetid2) == false ) + // eval->Invalid("asset2 inputs != outputs"); + + ////////// not implemented yet //////////// + if( (assetoshis= AssetValidateSellvin(cpTokens, eval, totalunits, tmporigpubkey, userTokensCCaddr, origaddr, tx, assetid)) == 0 ) return(false); - else if ( numvouts < 3 ) + else if( numvouts < 3 ) return eval->Invalid("not enough vouts for fillex"); - else if ( tmporigpubkey != origpubkey ) + else if( tmporigpubkey != origpubkey ) return eval->Invalid("mismatched origpubkeys for fillex"); else { - if ( assetoshis != tx.vout[0].nValue+tx.vout[1].nValue ) + if( assetoshis != tx.vout[0].nValue + tx.vout[1].nValue ) return eval->Invalid("locked value doesnt match vout0+1 fillex"); - else if ( tx.vout[3].scriptPubKey.IsPayToCryptoCondition() != 0 ) + else if( tx.vout[3].scriptPubKey.IsPayToCryptoCondition() != 0 ) + ////////// not implemented yet //////////// { - if ( ConstrainVout(tx.vout[2],1,CCaddr,0) == 0 ) + if( ConstrainVout(tx.vout[2], 1, userTokensCCaddr, 0) == 0 ) return eval->Invalid("vout2 doesnt go to origpubkey fillex"); - else if ( inputs != tx.vout[2].nValue+tx.vout[3].nValue ) + else if( inputs != tx.vout[2].nValue + tx.vout[3].nValue ) { fprintf(stderr,"inputs %.8f != %.8f + %.8f\n",(double)inputs/COIN,(double)tx.vout[2].nValue/COIN,(double)tx.vout[3].nValue/COIN); return eval->Invalid("asset inputs doesnt match vout2+3 fillex"); } } - else if ( ConstrainVout(tx.vout[2],1,CCaddr,inputs) == 0 ) + ////////// not implemented yet //////////// + else if( ConstrainVout(tx.vout[2], 1, userTokensCCaddr, inputs) == 0 ) return eval->Invalid("vout2 doesnt match inputs fillex"); - else if ( ConstrainVout(tx.vout[1],0,0,0) == 0 ) + else if( ConstrainVout(tx.vout[1], 0, 0, 0) == 0 ) return eval->Invalid("vout1 is CC for fillex"); fprintf(stderr,"assets vout0 %llu, vin1 %llu, vout2 %llu -> orig, vout1 %llu, total %llu\n",(long long)tx.vout[0].nValue,(long long)assetoshis,(long long)tx.vout[2].nValue,(long long)tx.vout[1].nValue,(long long)totalunits); - if ( ValidateSwapRemainder(remaining_price,tx.vout[0].nValue,assetoshis,tx.vout[1].nValue,tx.vout[2].nValue,totalunits) == false ) + if( ValidateSwapRemainder(remaining_price, tx.vout[0].nValue, assetoshis,tx.vout[1].nValue, tx.vout[2].nValue, totalunits) == false ) return eval->Invalid("mismatched remainder for fillex"); - else if ( ConstrainVout(tx.vout[1],1,0,0) == 0 ) + else if( ConstrainVout(tx.vout[1], 1, 0, 0) == 0 ) + ////////// not implemented yet //////////// return eval->Invalid("normal vout1 for fillex"); - else if ( remaining_price != 0 ) + else if( remaining_price != 0 ) { - if ( ConstrainVout(tx.vout[0],1,(char *)cp->unspendableCCaddr,0) == 0 ) + if( ConstrainVout(tx.vout[0], 1, (char *)cpAssets->unspendableCCaddr, 0) == 0 ) // TODO: unsure about this, but this is not impl yet anyway return eval->Invalid("mismatched vout0 AssetsCCaddr for fillex"); } } + ////////// not implemented yet //////////// fprintf(stderr,"fill validated\n"); break; + default: fprintf(stderr,"illegal assets funcid.(%c)\n",funcid); return eval->Invalid("unexpected assets funcid"); - break; + //break; } - return(PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts)); + + // what does this do? + bool bPrevent = PreventCC(eval, tx, preventCCvins, numvins, preventCCvouts, numvouts); + std::cerr << "AssetsValidate() PreventCC returned=" << bPrevent << std::endl; + return (bPrevent); } diff --git a/src/cc/auction.cpp b/src/cc/auction.cpp index 1bc8533ec..0858facfa 100644 --- a/src/cc/auction.cpp +++ b/src/cc/auction.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -73,7 +73,7 @@ bool AuctionExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransactio bool AuctionValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) { int32_t numvins,numvouts,preventCCvins,preventCCvouts,i; bool retval; - return(false); // reject any auction CC for now + return eval->Invalid("no validation yet"); numvins = tx.vin.size(); numvouts = tx.vout.size(); preventCCvins = preventCCvouts = -1; diff --git a/src/cc/betprotocol.cpp b/src/cc/betprotocol.cpp index 3efa4ae37..0724f2fea 100644 --- a/src/cc/betprotocol.cpp +++ b/src/cc/betprotocol.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cc/betprotocol.h b/src/cc/betprotocol.h index ac76f87b1..688db370f 100644 --- a/src/cc/betprotocol.h +++ b/src/cc/betprotocol.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cc/cclib.cpp b/src/cc/cclib.cpp new file mode 100644 index 000000000..971258d90 --- /dev/null +++ b/src/cc/cclib.cpp @@ -0,0 +1,317 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + +#include +#include + +#include "primitives/block.h" +#include "primitives/transaction.h" +#include "script/cc.h" +#include "cc/eval.h" +#include "cc/utils.h" +#include "cc/CCinclude.h" +#include "main.h" +#include "chain.h" +#include "core_io.h" +#include "crosschain.h" + +#define FAUCET2SIZE COIN + +struct CClib_rpcinfo +{ + char *method,*help; + int32_t numrequiredargs,maxargs; // frontloaded with required + uint8_t funcid; +} +CClib_methods[] = +{ + { (char *)"faucet2_fund", (char *)"amount", 1, 1, 'F' }, + { (char *)"faucet2_get", (char *)"", 0, 0, 'G' }, +}; + +std::string MYCCLIBNAME = (char *)"faucet2"; + +char *CClib_name() { return((char *)MYCCLIBNAME.c_str()); } + +std::string CClib_rawtxgen(struct CCcontract_info *cp,uint8_t funcid,cJSON *params); + +UniValue CClib_info(struct CCcontract_info *cp) +{ + UniValue result(UniValue::VOBJ),a(UniValue::VARR); int32_t i; char str[2]; + result.push_back(Pair("result","success")); + result.push_back(Pair("CClib",CClib_name())); + for (i=0; i= 128 ) + obj.push_back(Pair("funcid",CClib_methods[i].funcid)); + else + { + str[0] = CClib_methods[i].funcid; + str[1] = 0; + obj.push_back(Pair("funcid",str)); + } + obj.push_back(Pair("name",CClib_methods[i].method)); + obj.push_back(Pair("help",CClib_methods[i].help)); + obj.push_back(Pair("params_required",CClib_methods[i].numrequiredargs)); + obj.push_back(Pair("params_max",CClib_methods[i].maxargs)); + a.push_back(obj); + } + result.push_back(Pair("methods",a)); + return(result); +} + +UniValue CClib(struct CCcontract_info *cp,char *method,cJSON *params) +{ + UniValue result(UniValue::VOBJ); int32_t i; std::string rawtx; + for (i=0; i 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 ) + return(tx.vout[v].nValue); + } + return(0); +} + +bool CClibExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee) +{ + static uint256 zerohash; + CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis; + numvins = tx.vin.size(); + numvouts = tx.vout.size(); + for (i=0; iismyvin)(tx.vin[i].scriptSig) != 0 ) + { + //fprintf(stderr,"vini.%d check mempool\n",i); + if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 ) + return eval->Invalid("cant find vinTx"); + else + { + //fprintf(stderr,"vini.%d check hash and vout\n",i); + if ( hashBlock == zerohash ) + return eval->Invalid("cant faucet2 from mempool"); + if ( (assetoshis= IsCClibvout(cp,vinTx,tx.vin[i].prevout.n)) != 0 ) + inputs += assetoshis; + } + } + } + for (i=0; iInvalid("mismatched inputs != outputs + FAUCET2SIZE + txfee"); + } + else return(true); +} + +bool CClib_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx,unsigned int nIn) +{ + int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64]; + std::vector > txids; + numvins = tx.vin.size(); + numvouts = tx.vout.size(); + preventCCvins = preventCCvouts = -1; + if ( numvouts < 1 ) + return eval->Invalid("no vouts"); + else + { + for (i=0; iInvalid("illegal normal vini"); + } + } + //fprintf(stderr,"check amounts\n"); + if ( CClibExactAmounts(cp,eval,tx,1,10000) == false ) + { + fprintf(stderr,"faucetget invalid amount\n"); + return false; + } + else + { + preventCCvouts = 1; + if ( IsCClibvout(cp,tx,0) != 0 ) + { + preventCCvouts++; + i = 1; + } else i = 0; + txid = tx.GetHash(); + memcpy(hash,&txid,sizeof(hash)); + fprintf(stderr,"check faucetget txid %s %02x/%02x\n",uint256_str(str,txid),hash[0],hash[31]); + if ( tx.vout[i].nValue != FAUCET2SIZE ) + return eval->Invalid("invalid faucet output"); + else if ( (hash[0] & 0xff) != 0 || (hash[31] & 0xff) != 0 ) + return eval->Invalid("invalid faucetget txid"); + Getscriptaddress(destaddr,tx.vout[i].scriptPubKey); + SetCCtxids(txids,destaddr); + for (std::vector >::const_iterator it=txids.begin(); it!=txids.end(); it++) + { + //int height = it->first.blockHeight; + if ( CCduration(numblocks,it->first.txhash) > 0 && numblocks > 3 ) + { + //fprintf(stderr,"would return error %s numblocks.%d ago\n",uint256_str(str,it->first.txhash),numblocks); + return eval->Invalid("faucet2 is only for brand new addresses"); + } + } + retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts); + if ( retval != 0 ) + fprintf(stderr,"faucet2get validated\n"); + else fprintf(stderr,"faucet2get invalid\n"); + return(retval); + } + } +} + +int64_t AddCClibInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs) +{ + char coinaddr[64]; int64_t threshold,nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t vout,n = 0; + std::vector > unspentOutputs; + GetCCaddress(cp,coinaddr,pk); + SetCCunspents(unspentOutputs,coinaddr); + threshold = total/(maxinputs+1); + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) + { + txid = it->first.txhash; + vout = (int32_t)it->first.index; + if ( it->second.satoshis < threshold ) + continue; + //char str[65]; fprintf(stderr,"check %s/v%d %.8f`\n",uint256_str(str,txid),vout,(double)it->second.satoshis/COIN); + // no need to prevent dup + if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) + { + if ( (nValue= IsCClibvout(cp,vintx,vout)) > 1000000 && myIsutxo_spentinmempool(txid,vout) == 0 ) + { + if ( total != 0 && maxinputs != 0 ) + mtx.vin.push_back(CTxIn(txid,vout,CScript())); + nValue = it->second.satoshis; + totalinputs += nValue; + n++; + if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) + break; + } else fprintf(stderr,"nValue too small or already spent in mempool\n"); + } else fprintf(stderr,"couldnt get tx\n"); + } + return(totalinputs); +} + + +std::string Faucet2Fund(struct CCcontract_info *cp,uint64_t txfee,int64_t funds) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CPubKey mypk,cclibpk; CScript opret; + if ( txfee == 0 ) + txfee = 10000; + mypk = pubkey2pk(Mypubkey()); + cclibpk = GetUnspendable(cp,0); + if ( AddNormalinputs(mtx,mypk,funds+txfee,64) > 0 ) + { + mtx.vout.push_back(MakeCC1vout(cp->evalcode,funds,cclibpk)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret)); + } + return(""); +} + +/*UniValue FaucetInfo() +{ + UniValue result(UniValue::VOBJ); char numstr[64]; + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CPubKey faucetpk; struct CCcontract_info *cp,C; int64_t funding; + result.push_back(Pair("result","success")); + result.push_back(Pair("name","Faucet")); + cp = CCinit(&C,EVAL_FAUCET); + faucetpk = GetUnspendable(cp,0); + funding = AddFaucetInputs(cp,mtx,faucetpk,0,0); + sprintf(numstr,"%.8f",(double)funding/COIN); + result.push_back(Pair("funding",numstr)); + return(result); +}*/ + +std::string CClib_rawtxgen(struct CCcontract_info *cp,uint8_t funcid,cJSON *params) +{ + CMutableTransaction tmpmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CPubKey mypk,cclibpk; int64_t funds,txfee=0,inputs,CCchange=0,nValue=FAUCET2SIZE; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash; + if ( txfee == 0 ) + txfee = 10000; + if ( funcid == 'F' ) + { + if ( cJSON_GetArraySize(params) > 0 ) + { + funds = (int64_t)jdouble(jitem(params,0),0)*COIN + 0.0000000049; + return(Faucet2Fund(cp,0,funds)); + } else return(""); + } + else if ( funcid != 'G' ) + return(""); + cclibpk = GetUnspendable(cp,0); + mypk = pubkey2pk(Mypubkey()); + if ( (inputs= AddCClibInputs(cp,mtx,cclibpk,nValue+txfee,60)) > 0 ) + { + if ( inputs > nValue ) + CCchange = (inputs - nValue - txfee); + if ( CCchange != 0 ) + mtx.vout.push_back(MakeCC1vout(EVAL_FIRSTUSER,CCchange,cclibpk)); + mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + fprintf(stderr,"start at %u\n",(uint32_t)time(NULL)); + j = rand() & 0xfffffff; + for (i=0; i<1000000; i++,j++) + { + tmpmtx = mtx; + rawhex = FinalizeCCTx(-1LL,cp,tmpmtx,mypk,txfee,CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_FIRSTUSER << (uint8_t)'G' << j)); + if ( (len= (int32_t)rawhex.size()) > 0 && len < 65536 ) + { + len >>= 1; + decode_hex(buf,len,(char *)rawhex.c_str()); + hash = bits256_doublesha256(0,buf,len); + if ( (hash.bytes[0] & 0xff) == 0 && (hash.bytes[31] & 0xff) == 0 ) + { + fprintf(stderr,"found valid txid after %d iterations %u\n",i,(uint32_t)time(NULL)); + return(rawhex); + } + //fprintf(stderr,"%02x%02x ",hash.bytes[0],hash.bytes[31]); + } + } + fprintf(stderr,"couldnt generate valid txid %u\n",(uint32_t)time(NULL)); + return(""); + } else fprintf(stderr,"cant find faucet inputs\n"); + return(""); +} diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index 60f907c27..6cd379eed 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -64,22 +64,23 @@ Possible third iteration: int64_t IsChannelsvout(struct CCcontract_info *cp,const CTransaction& tx,CPubKey srcpub, CPubKey destpub,int32_t v) { - char destaddr[65],channeladdr[65]; + char destaddr[65],channeladdr[65],tokenschanneladdr[65]; GetCCaddress1of2(cp,channeladdr,srcpub,destpub); + GetTokensCCaddress1of2(cp,tokenschanneladdr,srcpub,destpub); if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) { - if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,channeladdr) == 0 ) + if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && (strcmp(destaddr,channeladdr) == 0 || strcmp(destaddr,tokenschanneladdr) == 0)) return(tx.vout[v].nValue); } - return(0); + return(0); } -int64_t IsChannelsMarkervout(struct CCcontract_info *cp,const CTransaction& tx,CPubKey srcpub,int32_t v) +int64_t IsChannelsMarkervout(struct CCcontract_info *cp,const CTransaction& tx,CPubKey pubkey,int32_t v) { char destaddr[65],ccaddr[65]; - GetCCaddress(cp,ccaddr,srcpub); + GetCCaddress(cp,ccaddr,pubkey); if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) { if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,ccaddr) == 0 ) @@ -88,17 +89,31 @@ int64_t IsChannelsMarkervout(struct CCcontract_info *cp,const CTransaction& tx,C return(0); } -CScript EncodeChannelsOpRet(uint8_t funcid,uint256 opentxid,CPubKey srcpub,CPubKey destpub,int32_t numpayments,int64_t payment,uint256 hashchain) +CScript EncodeChannelsOpRet(uint8_t funcid,uint256 tokenid,uint256 opentxid,CPubKey srcpub,CPubKey destpub,int32_t numpayments,int64_t payment,uint256 hashchain) { CScript opret; uint8_t evalcode = EVAL_CHANNELS; + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << opentxid << srcpub << destpub << numpayments << payment << hashchain); + if (tokenid!=zeroid) + { + std::vector pks; + pks.push_back(srcpub); + pks.push_back(destpub); + return(EncodeTokenOpRet(tokenid,pks,opret)); + } return(opret); } -uint8_t DecodeChannelsOpRet(const CScript &scriptPubKey,uint256 &opentxid, CPubKey &srcpub,CPubKey &destpub,int32_t &numpayments,int64_t &payment,uint256 &hashchain) +uint8_t DecodeChannelsOpRet(const CScript &scriptPubKey, uint256 &tokenid, uint256 &opentxid, CPubKey &srcpub,CPubKey &destpub,int32_t &numpayments,int64_t &payment,uint256 &hashchain) { - std::vector vopret; uint8_t *script,e,f; - GetOpReturnData(scriptPubKey, vopret); + std::vector vopret; uint8_t *script,e,f,tokenevalcode; + std::vector pubkeys; std::vector vOpretExtra; + + if (DecodeTokenOpRet(scriptPubKey,tokenevalcode,tokenid,pubkeys,vOpretExtra)!=0 && tokenevalcode==EVAL_TOKENS && vOpretExtra.size()>0) + { + if (!E_UNMARSHAL(vOpretExtra, { ss >> vopret; })) return (0); + } + else GetOpReturnData(scriptPubKey, vopret); if ( vopret.size() > 2 ) { script = (uint8_t *)vopret.data(); @@ -115,46 +130,56 @@ uint8_t DecodeChannelsOpRet(const CScript &scriptPubKey,uint256 &opentxid, CPubK bool ChannelsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee) { - static uint256 zerohash; - uint256 txid,param3; + uint256 txid,param3,tokenid; CPubKey srcpub,destpub; - int32_t param1; int64_t param2; uint8_t funcid; - CTransaction vinTx; uint256 hashBlock; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis; - numvins = tx.vin.size(); - numvouts = tx.vout.size(); + int32_t param1,numvouts; int64_t param2; uint8_t funcid; + CTransaction vinTx; uint256 hashBlock; int64_t inputs=0,outputs=0; - if ((numvouts=tx.vout.size()) > 0 && DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, param1, param2, param3)!=0) - { - for (i=0; i 0 && (funcid=DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey, tokenid, txid, srcpub, destpub, param1, param2, param3))!=0) + { + switch (funcid) { - if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 ) - return eval->Invalid("cant find vinTx"); - else - { - inputs += vinTx.vout[tx.vin[i].prevout.n].nValue; - } + case 'O': + return (true); + case 'P': + if ( eval->GetTxUnconfirmed(tx.vin[1].prevout.hash,vinTx,hashBlock) == 0 ) + return eval->Invalid("cant find vinTx"); + inputs = vinTx.vout[tx.vin[1].prevout.n].nValue; + outputs = tx.vout[0].nValue + tx.vout[3].nValue; + break; + case 'C': + if ( eval->GetTxUnconfirmed(tx.vin[1].prevout.hash,vinTx,hashBlock) == 0 ) + return eval->Invalid("cant find vinTx"); + inputs = vinTx.vout[tx.vin[1].prevout.n].nValue; + outputs = tx.vout[0].nValue; + break; + case 'R': + if ( eval->GetTxUnconfirmed(tx.vin[1].prevout.hash,vinTx,hashBlock) == 0 ) + return eval->Invalid("cant find vinTx"); + inputs = vinTx.vout[tx.vin[1].prevout.n].nValue; + outputs = tx.vout[2].nValue; + break; + default: + return (false); } + if ( inputs != outputs ) + { + fprintf(stderr,"inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs); + return eval->Invalid("mismatched inputs != outputs"); + } + else return (true); } else { return eval->Invalid("invalid op_return data"); } - for (i=0; iInvalid("mismatched inputs != outputs + txfee"); - } - else return(true); + return(false); } bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) { int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numpayments,p1,param1; bool retval; - uint256 txid,hashblock,p3,param3,opentxid,tmp_txid,genhashchain,hashchain; + uint256 txid,hashblock,p3,param3,opentxid,tmp_txid,genhashchain,hashchain,tokenid; uint8_t funcid,hash[32],hashdest[32]; int64_t p2,param2,payment; CPubKey srcpub, destpub; @@ -169,15 +194,13 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & { if (ChannelsExactAmounts(cp,eval,tx,1,10000) == false ) { - fprintf(stderr,"Channelsget invalid amount\n"); - return false; + return eval->Invalid("invalid channel inputs vs. outputs!"); } else { txid = tx.GetHash(); memcpy(hash,&txid,sizeof(hash)); - - if ( (funcid = DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey, opentxid, srcpub, destpub, param1, param2, param3)) != 0) + if ( (funcid = DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey, tokenid, opentxid, srcpub, destpub, param1, param2, param3)) != 0) { switch ( funcid ) { @@ -207,15 +230,19 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return eval->Invalid("vin.1 is CC for channelPayment!"); else if ( IsCCInput(tx.vin[2].scriptSig) == 0 ) return eval->Invalid("vin.2 is CC for channelPayment!"); - else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) + else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition()==0 ) return eval->Invalid("vout.0 is CC for channelPayment!"); - else if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) + else if ( IsChannelsMarkervout(cp,tx,srcpub,1)==0 ) return eval->Invalid("vout.1 is CC for channelPayment (marker to srcPub)!"); - else if ( tx.vout[2].scriptPubKey.IsPayToCryptoCondition() == 0 ) + else if ( IsChannelsMarkervout(cp,tx,destpub,2)==0 ) return eval->Invalid("vout.2 is CC for channelPayment (marker to dstPub)!"); - else if ( tx.vout[3].scriptPubKey.IsPayToCryptoCondition() != 0 ) + else if ( tokenid!=zeroid && tx.vout[3].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("vout.3 is CC for channelPayment!"); + else if ( tokenid==zeroid && tx.vout[3].scriptPubKey.IsPayToCryptoCondition() != 0 ) return eval->Invalid("vout.3 is normal for channelPayment!"); - else if ( tx.vout[3].scriptPubKey!=CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG) + else if ( tokenid!=zeroid && tx.vout[3].scriptPubKey!=MakeCC1vout(EVAL_TOKENS,tx.vout[3].nValue,destpub).scriptPubKey) + return eval->Invalid("payment funds do not go to receiver!"); + else if ( tokenid==zeroid && tx.vout[3].scriptPubKey!=CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG) return eval->Invalid("payment funds do not go to receiver!"); else if ( param1 > CHANNELS_MAXPAYMENTS) return eval->Invalid("too many payment increments!"); @@ -223,7 +250,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & { if (myGetTransaction(opentxid,channelOpenTx,hashblock) != 0) { - if ((numvouts=channelOpenTx.vout.size()) > 0 && (funcid=DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain)) != 0 && funcid!='O') + if ((numvouts=channelOpenTx.vout.size()) > 0 && (funcid=DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, numpayments, payment, hashchain)) != 0 && funcid!='O') return eval->Invalid("invalid channelopen OP_RETURN data!"); endiancpy(hash, (uint8_t * ) & param3, 32); for (i = 0; i < numpayments-param1; i++) @@ -239,7 +266,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & } if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0) { - if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, p1, p2, p3) == 0) + if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, p1, p2, p3) == 0) return eval->Invalid("invalid previous tx OP_RETURN data!"); else if (tx.vout[1].scriptPubKey != prevTx.vout[1].scriptPubKey) return eval->Invalid("invalid destination for sender marker!"); @@ -269,23 +296,23 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return eval->Invalid("vin.1 is CC for channelClose!"); else if ( IsCCInput(tx.vin[2].scriptSig) == 0 ) return eval->Invalid("vin.2 is CC for channelClose!"); - else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) + else if ( IsChannelsvout(cp,tx,srcpub,destpub,0)==0 ) return eval->Invalid("vout.0 is CC for channelClose!"); - else if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) + else if ( IsChannelsMarkervout(cp,tx,srcpub,1)==0 ) return eval->Invalid("vout.1 is CC for channelClose (marker to srcPub)!"); - else if ( tx.vout[2].scriptPubKey.IsPayToCryptoCondition() == 0 ) + else if ( IsChannelsMarkervout(cp,tx,destpub,2)==0 ) return eval->Invalid("vout.2 is CC for channelClose (marker to dstPub)!"); else if ( param1 > CHANNELS_MAXPAYMENTS) return eval->Invalid("too many payment increments!"); else if (myGetTransaction(opentxid,channelOpenTx,hashblock) == 0) return eval->Invalid("invalid open txid!"); - else if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain) != 'O') + else if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, numpayments, payment, hashchain) != 'O') return eval->Invalid("invalid channelopen OP_RETURN data!"); else if (tx.vout[0].nValue != param1*payment) return eval->Invalid("vout amount does not match number_of_payments*payment!"); else if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0) { - if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, p1, p2, p3) == 0) + if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, p1, p2, p3) == 0) return eval->Invalid("invalid previous tx OP_RETURN data!"); else if (tx.vout[1].scriptPubKey != prevTx.vout[1].scriptPubKey) return eval->Invalid("invalid destination for sender marker!"); @@ -314,23 +341,27 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return eval->Invalid("vin.1 is CC for channelRefund!"); else if ( IsCCInput(tx.vin[2].scriptSig) == 0 ) return eval->Invalid("vin.2 is CC for channelRefund!"); - else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 ) + else if ( IsChannelsMarkervout(cp,tx,srcpub,0)==0 ) return eval->Invalid("vout.0 is CC for channelRefund (marker to srcPub)!"); - else if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 ) + else if ( IsChannelsMarkervout(cp,tx,destpub,1)==0 ) return eval->Invalid("vout.1 is CC for channelRefund (marker to dstPub)!"); - else if ( tx.vout[2].scriptPubKey.IsPayToCryptoCondition() != 0 ) - return eval->Invalid("vout.2 is normal for channelRefund!"); - else if ( tx.vout[2].scriptPubKey!=CScript() << ParseHex(HexStr(srcpub)) << OP_CHECKSIG) + else if ( tokenid!=zeroid && tx.vout[2].scriptPubKey.IsPayToCryptoCondition() == 0 ) + return eval->Invalid("vout.2 is CC for channelPayment!"); + else if ( tokenid==zeroid && tx.vout[2].scriptPubKey.IsPayToCryptoCondition() != 0 ) + return eval->Invalid("vout.2 is normal for channelPayment!"); + else if ( tokenid!=zeroid && tx.vout[2].scriptPubKey!=MakeCC1vout(EVAL_TOKENS,tx.vout[2].nValue,srcpub).scriptPubKey) + return eval->Invalid("payment funds do not go to sender!"); + else if ( tokenid==zeroid && tx.vout[2].scriptPubKey!=CScript() << ParseHex(HexStr(srcpub)) << OP_CHECKSIG) return eval->Invalid("payment funds do not go to sender!"); else if ( param1 > CHANNELS_MAXPAYMENTS) return eval->Invalid("too many payment increments!"); else if (myGetTransaction(opentxid,channelOpenTx,hashblock) == 0) return eval->Invalid("invalid open txid!"); - else if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, numpayments, payment, hashchain) != 'O') + else if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, numpayments, payment, hashchain) != 'O') return eval->Invalid("invalid channelopen OP_RETURN data!"); else if (myGetTransaction(param3,channelCloseTx,hashblock) == 0) return eval->Invalid("invalid close txid!"); - else if ((numvouts=channelCloseTx.vout.size()) > 0 && DecodeChannelsOpRet(channelCloseTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, param1, param2, param3) != 'C') + else if ((numvouts=channelCloseTx.vout.size()) > 0 && DecodeChannelsOpRet(channelCloseTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, param1, param2, param3) != 'C') return eval->Invalid("invalid channelclose OP_RETURN data!"); else if (tmp_txid!=opentxid) return eval->Invalid("invalid close tx, opentxid do not match on close and refund!"); @@ -338,7 +369,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return eval->Invalid("vout amount does not match number_of_payments*payment!"); else if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0) { - if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tmp_txid, srcpub, destpub, p1, p2, p3) == 0) + if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, p1, p2, p3) == 0) return eval->Invalid("invalid previous tx OP_RETURN data!"); else if (tx.vout[0].scriptPubKey != prevTx.vout[1].scriptPubKey) return eval->Invalid("invalid destination for sender marker!"); @@ -351,9 +382,9 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & default: fprintf(stderr,"illegal channels funcid.(%c)\n",funcid); return eval->Invalid("unexpected channels funcid"); - break; } - } else return eval->Invalid("unexpected channels missing funcid"); + } + else return eval->Invalid("unexpected channels missing funcid"); retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts); if ( retval != 0 ) fprintf(stderr,"Channel tx validated\n"); @@ -366,16 +397,17 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & // helper functions for rpc calls in rpcwallet.cpp -int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, CTransaction openTx, uint256 &prevtxid) +int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, CTransaction openTx, uint256 &prevtxid, CPubKey mypk) { - char coinaddr[65]; int64_t param2,totalinputs = 0,numvouts; uint256 txid=zeroid,tmp_txid,hashBlock,param3; CTransaction tx; int32_t param1; + char coinaddr[65]; int64_t param2,totalinputs = 0,numvouts; uint256 txid=zeroid,tmp_txid,hashBlock,param3,tokenid; CTransaction tx; int32_t marker,param1; std::vector > unspentOutputs; CPubKey srcpub,destpub; - uint8_t myprivkey[32]; + uint8_t myprivkey[32]; - if ((numvouts=openTx.vout.size()) > 0 && DecodeChannelsOpRet(openTx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)=='O') + if ((numvouts=openTx.vout.size()) > 0 && DecodeChannelsOpRet(openTx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3)=='O') { - GetCCaddress1of2(cp,coinaddr,srcpub,destpub); + if (tokenid!=zeroid) GetTokensCCaddress1of2(cp,coinaddr,srcpub,destpub); + else GetCCaddress1of2(cp,coinaddr,srcpub,destpub); SetCCunspents(unspentOutputs,coinaddr); } else @@ -383,14 +415,15 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C fprintf(stderr,"invalid channel open txid\n"); return 0; } - + if (srcpub==mypk) marker=1; + else marker=2; for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { if ( (int32_t)it->first.index==0 && GetTransaction(it->first.txhash,tx,hashBlock,false) != 0 && (numvouts=tx.vout.size()) > 0) { - if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3)!=0 && - (tmp_txid==openTx.GetHash() || tx.GetHash()==openTx.GetHash()) && - (totalinputs=IsChannelsvout(cp,tx,srcpub,destpub,0)+IsChannelsMarkervout(cp,tx,srcpub,1))>0) + if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3)!=0 && + (tmp_txid==openTx.GetHash() || tx.GetHash()==openTx.GetHash()) && IsChannelsMarkervout(cp,tx,marker==1?srcpub:destpub,marker)>0 && + (totalinputs=IsChannelsvout(cp,tx,srcpub,destpub,0))>0) { txid = it->first.txhash; break; @@ -406,11 +439,11 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C const CTransaction &txmempool = e.GetTx(); const uint256 &hash = txmempool.GetHash(); - if ((numvouts=txmempool.vout.size()) > 0 && DecodeChannelsOpRet(txmempool.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3) != 0 && + if ((numvouts=txmempool.vout.size()) > 0 && DecodeChannelsOpRet(txmempool.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3) != 0 && tmp_txid==openTx.GetHash() && param1 < mindepth) { txid=hash; - totalinputs=txmempool.vout[0].nValue+txmempool.vout[1].nValue; + totalinputs=txmempool.vout[0].nValue; mindepth=param1; } } @@ -419,20 +452,20 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C { prevtxid=txid; mtx.vin.push_back(CTxIn(txid,0,CScript())); - mtx.vin.push_back(CTxIn(txid,1,CScript())); - Myprivkey(myprivkey); - CCaddr2set(cp,EVAL_CHANNELS,srcpub,myprivkey,coinaddr); - CCaddr3set(cp,EVAL_CHANNELS,destpub,myprivkey,coinaddr); + mtx.vin.push_back(CTxIn(txid,marker,CScript())); + Myprivkey(myprivkey); + if (tokenid!=zeroid) CCaddrTokens1of2set(cp,srcpub,destpub,coinaddr); + else CCaddr1of2set(cp,srcpub,destpub,coinaddr); return totalinputs; } else return 0; } -std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment) +std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment, uint256 tokenid) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - uint8_t hash[32],hashdest[32]; uint64_t funds; int32_t i; uint256 hashchain,entropy,hentropy; - CPubKey mypk; struct CCcontract_info *cp,C; + uint8_t hash[32],hashdest[32]; uint64_t amount,tokens=0,funds; int32_t i; uint256 hashchain,entropy,hentropy; + CPubKey mypk; struct CCcontract_info *cp,*cpTokens,C,CTokens; if ( numpayments <= 0 || payment <= 0 || numpayments > CHANNELS_MAXPAYMENTS ) { @@ -441,11 +474,18 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64 return(""); } cp = CCinit(&C,EVAL_CHANNELS); + cpTokens = CCinit(&CTokens,EVAL_TOKENS); if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); funds = numpayments * payment; - if ( AddNormalinputs(mtx,mypk,funds+3*txfee,64) > 0 ) + if (tokenid!=zeroid) + { + amount=AddNormalinputs(mtx,mypk,3*txfee,5); + tokens=AddTokenCCInputs(cpTokens, mtx, mypk, tokenid, funds, 64); + } + else amount=AddNormalinputs(mtx,mypk,funds+3*txfee,64); + if (amount+tokens >= funds+2*txfee) { hentropy = DiceHashEntropy(entropy,mtx.vin[0].prevout.hash,mtx.vin[0].prevout.n,1); endiancpy(hash,(uint8_t *)&hentropy,32); @@ -455,18 +495,22 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64 memcpy(hash,hashdest,32); } endiancpy((uint8_t *)&hashchain,hashdest,32); - mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS,funds,mypk,destpub)); + if (tokenid!=zeroid) mtx.vout.push_back(MakeTokensCC1of2vout(EVAL_CHANNELS,funds,mypk,destpub)); + else mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS,funds,mypk,destpub)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('O',zeroid,mypk,destpub,numpayments,payment,hashchain))); + if (tokenid!=zeroid && tokens>funds) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS,tokens-funds,mypk)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('O',tokenid,zeroid,mypk,destpub,numpayments,payment,hashchain))); } + CCerror = strprintf("error adding funds"); + fprintf(stderr,"%s\n",CCerror.c_str()); return(""); } std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint256 secret) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk,srcpub,destpub; uint256 txid,hashchain,gensecret,hashblock,entropy,hentropy,prevtxid,param3; + CPubKey mypk,srcpub,destpub; uint256 txid,hashchain,gensecret,hashblock,entropy,hentropy,prevtxid,param3,tokenid; struct CCcontract_info *cp,C; int32_t i,funcid,prevdepth,numvouts,numpayments,totalnumpayments; int64_t payment,change,funds,param2; uint8_t hash[32],hashdest[32]; @@ -478,94 +522,106 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2 mypk = pubkey2pk(Mypubkey()); if (GetTransaction(opentxid,channelOpenTx,hashblock,false) == 0) { - fprintf(stderr, "invalid channel open txid\n"); + CCerror = strprintf("invalid channel open txid"); + fprintf(stderr,"%s\n",CCerror.c_str()); + return(""); + } + if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tokenid, txid, srcpub, destpub, totalnumpayments, payment, hashchain)=='O') + { + if (mypk != srcpub && mypk != destpub) + { + CCerror = strprintf("this is not our channel"); + fprintf(stderr,"%s\n",CCerror.c_str()); + return(""); + } + else if (amount % payment != 0 || amount 0) { - if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0 && (change=funds-amount-txfee)>=0) - { - if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, totalnumpayments, payment, hashchain)=='O') + if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid,mypk)) !=0 && (change=funds-amount)>=0) + { + numpayments=amount/payment; + if (GetTransaction(prevtxid,prevTx,hashblock,false) != 0 && (numvouts=prevTx.vout.size()) > 0 && + ((funcid = DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, txid, srcpub, destpub, prevdepth, param2, param3)) != 0) && + (funcid == 'P' || funcid=='O')) { - if (mypk != srcpub && mypk != destpub) + if (numpayments > prevdepth) { - fprintf(stderr,"this is not our channel\n"); - return(""); - } - else if (amount % payment != 0 || amount 0 && - ((funcid = DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, prevdepth, param2, param3)) != 0) && - (funcid == 'P' || funcid=='O')) + if (secret!=zeroid) { - if (numpayments > prevdepth) + endiancpy(hash, (uint8_t * ) & secret, 32); + for (i = 0; i < totalnumpayments-(prevdepth-numpayments); i++) { - fprintf(stderr,"not enough funds in channel for that amount\n"); - return (""); - } else if (numpayments == 0) - { - fprintf(stderr,"invalid amount\n"); - return (""); + vcalc_sha256(0, hashdest, hash, 32); + memcpy(hash, hashdest, 32); } - if (secret!=zeroid) + endiancpy((uint8_t * ) & gensecret, hashdest, 32); + if (gensecret!=hashchain) { - endiancpy(hash, (uint8_t * ) & secret, 32); - for (i = 0; i < totalnumpayments-(prevdepth-numpayments); i++) - { - vcalc_sha256(0, hashdest, hash, 32); - memcpy(hash, hashdest, 32); - } - endiancpy((uint8_t * ) & gensecret, hashdest, 32); - if (gensecret!=hashchain) - { - fprintf(stderr,"invalid secret supplied\n"); - return(""); - } - } - else - { - hentropy = DiceHashEntropy(entropy,channelOpenTx.vin[0].prevout.hash,channelOpenTx.vin[0].prevout.n,1); - if (prevdepth-numpayments) - { - endiancpy(hash, (uint8_t * ) & hentropy, 32); - for (i = 0; i < prevdepth-numpayments; i++) - { - vcalc_sha256(0, hashdest, hash, 32); - memcpy(hash, hashdest, 32); - } - endiancpy((uint8_t * ) & secret, hashdest, 32); - } - else endiancpy((uint8_t * ) & secret, (uint8_t * ) & hentropy, 32); + CCerror = strprintf("invalid secret supplied"); + fprintf(stderr,"%s\n",CCerror.c_str()); + return(""); } } else { - fprintf(stderr,"invalid previous tx\n"); - return(""); + hentropy = DiceHashEntropy(entropy,channelOpenTx.vin[0].prevout.hash,channelOpenTx.vin[0].prevout.n,1); + if (prevdepth-numpayments) + { + endiancpy(hash, (uint8_t * ) & hentropy, 32); + for (i = 0; i < prevdepth-numpayments; i++) + { + vcalc_sha256(0, hashdest, hash, 32); + memcpy(hash, hashdest, 32); + } + endiancpy((uint8_t * ) & secret, hashdest, 32); + } + else endiancpy((uint8_t * ) & secret, (uint8_t * ) & hentropy, 32); } } else { - fprintf(stderr, "invalid channel open tx\n"); - return (""); - } - mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, change, mypk, destpub)); - mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); + CCerror = strprintf("invalid previous tx"); + fprintf(stderr,"%s\n",CCerror.c_str()); + return(""); + } + if (tokenid!=zeroid) mtx.vout.push_back(MakeTokensCC1of2vout(EVAL_CHANNELS, change, srcpub, destpub)); + else mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, change, srcpub, destpub)); + mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,srcpub)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub)); - mtx.vout.push_back(CTxOut(amount, CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG)); - return (FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeChannelsOpRet('P', opentxid, mypk, destpub, prevdepth-numpayments, numpayments, secret))); + if (tokenid!=zeroid) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, amount, destpub)); + else mtx.vout.push_back(CTxOut(amount, CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG)); + return (FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeChannelsOpRet('P', tokenid, opentxid, srcpub, destpub, prevdepth-numpayments, numpayments, secret))); } else { - fprintf(stderr,"error adding CC inputs\n"); + CCerror = strprintf("error adding CC inputs"); + fprintf(stderr,"%s\n",CCerror.c_str()); return(""); } } - fprintf(stderr,"error adding normal inputs\n"); + CCerror = strprintf("error adding normal inputs"); + fprintf(stderr,"%s\n",CCerror.c_str()); return(""); } @@ -574,7 +630,7 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid) CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CPubKey mypk,srcpub,destpub; struct CCcontract_info *cp,C; CTransaction channelOpenTx; - uint256 hashblock,tmp_txid,prevtxid,hashchain; + uint256 hashblock,tmp_txid,prevtxid,hashchain,tokenid; int32_t numvouts,numpayments; int64_t payment,funds; @@ -585,35 +641,41 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid) mypk = pubkey2pk(Mypubkey()); if (GetTransaction(opentxid,channelOpenTx,hashblock,false) == 0) { - fprintf(stderr, "invalid channel open txid\n"); + CCerror = strprintf("invalid channel open txid"); + fprintf(stderr,"%s\n",CCerror.c_str()); return (""); } - if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,numpayments,payment,hashchain)!='O') + if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,numpayments,payment,hashchain)!='O') { - fprintf(stderr, "invalid channel open tx\n"); + CCerror = strprintf("invalid channel open tx"); + fprintf(stderr,"%s\n",CCerror.c_str()); return (""); } if (mypk != srcpub) { - fprintf(stderr,"cannot close, you are not channel owner\n"); + CCerror = strprintf("cannot close, you are not channel owner"); + fprintf(stderr,"%s\n",CCerror.c_str()); return(""); } if ( AddNormalinputs(mtx,mypk,2*txfee,3) > 0 ) { - if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0 && funds-txfee>0) + if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid,mypk)) !=0 && funds>0) { - mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, funds-txfee, mypk, destpub)); + if (tokenid!=zeroid) mtx.vout.push_back(MakeTokensCC1of2vout(EVAL_CHANNELS, funds, mypk, destpub)); + else mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, funds, mypk, destpub)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('C',opentxid,mypk,destpub,funds/payment,payment,zeroid))); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('C',tokenid,opentxid,mypk,destpub,funds/payment,payment,zeroid))); } else { - fprintf(stderr,"error adding CC inputs\n"); + CCerror = strprintf("error adding CC inputs"); + fprintf(stderr,"%s\n",CCerror.c_str()); return(""); } } - fprintf(stderr,"error adding normal inputs\n"); + CCerror = strprintf("error adding normal inputs"); + fprintf(stderr,"%s\n",CCerror.c_str()); return(""); } @@ -622,10 +684,9 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid) CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CPubKey mypk; struct CCcontract_info *cp,C; int64_t funds,payment,param2; int32_t i,numpayments,numvouts,param1; - uint256 hashchain,hashblock,txid,prevtxid,param3,entropy,hentropy,secret; + uint256 hashchain,hashblock,txid,prevtxid,param3,tokenid; CTransaction channelOpenTx,channelCloseTx,prevTx; CPubKey srcpub,destpub; - uint8_t funcid,hash[32],hashdest[32];; // verify stoptxid and origtxid match and are mine cp = CCinit(&C,EVAL_CHANNELS); @@ -634,146 +695,193 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid) mypk = pubkey2pk(Mypubkey()); if (GetTransaction(closetxid,channelCloseTx,hashblock,false) == 0) { - fprintf(stderr, "invalid channel close txid\n"); + CCerror = strprintf("invalid channel close txid"); + fprintf(stderr,"%s\n",CCerror.c_str()); return (""); } - if ((numvouts=channelCloseTx.vout.size()) < 1 || DecodeChannelsOpRet(channelCloseTx.vout[numvouts-1].scriptPubKey,txid,srcpub,destpub,param1,param2,param3)!='C') + if ((numvouts=channelCloseTx.vout.size()) < 1 || DecodeChannelsOpRet(channelCloseTx.vout[numvouts-1].scriptPubKey,tokenid,txid,srcpub,destpub,param1,param2,param3)!='C') { - fprintf(stderr, "invalid channel close tx\n"); + CCerror = strprintf("invalid channel close tx"); + fprintf(stderr,"%s\n",CCerror.c_str()); return (""); } if (txid!=opentxid) { - fprintf(stderr, "open and close txid are not from same channel\n"); + CCerror = strprintf("open and close txid are not from same channel"); + fprintf(stderr,"%s\n",CCerror.c_str()); return (""); } if (GetTransaction(opentxid,channelOpenTx,hashblock,false) == 0) { - fprintf(stderr, "invalid channel open txid\n"); + CCerror = strprintf("invalid channel open txid"); + fprintf(stderr,"%s\n",CCerror.c_str()); return (""); } - if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,txid,srcpub,destpub,numpayments,payment,hashchain)!='O') + if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tokenid,txid,srcpub,destpub,numpayments,payment,hashchain)!='O') { - fprintf(stderr, "invalid channel open tx\n"); + CCerror = strprintf("invalid channel open tx"); + fprintf(stderr,"%s\n",CCerror.c_str()); return (""); } if (mypk != srcpub) { - fprintf(stderr,"cannot refund, you are not the channel owenr\n"); + CCerror = strprintf("cannot refund, you are not the channel owner"); + fprintf(stderr,"%s\n",CCerror.c_str()); return(""); } if ( AddNormalinputs(mtx,mypk,2*txfee,3) > 0 ) { - if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid)) !=0 && funds-txfee>0) + if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid,mypk)) !=0 && funds>0) { if ((GetTransaction(prevtxid,prevTx,hashblock,false) != 0) && (numvouts=prevTx.vout.size()) > 0 && - DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, txid, srcpub, destpub, param1, param2, param3) != 0) + DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, txid, srcpub, destpub, param1, param2, param3) != 0) { - hentropy = DiceHashEntropy(entropy, channelOpenTx.vin[0].prevout.hash, channelOpenTx.vin[0].prevout.n,1); - endiancpy(hash, (uint8_t * ) & hentropy, 32); - for (i = 0; i < param1; i++) - { - vcalc_sha256(0, hashdest, hash, 32); - memcpy(hash, hashdest, 32); - } - endiancpy((uint8_t * ) & secret, hashdest, 32); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,txfee,destpub)); - mtx.vout.push_back(CTxOut(funds-txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('R',opentxid,mypk,destpub,param1,payment,closetxid))); + if (tokenid!=zeroid) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS,funds,mypk)); + else mtx.vout.push_back(CTxOut(funds,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('R',tokenid,opentxid,mypk,destpub,funds/payment,payment,closetxid))); } else { - fprintf(stderr,"previous tx is invalid\n"); + CCerror = strprintf("previous tx is invalid"); + fprintf(stderr,"%s\n",CCerror.c_str()); return(""); } } else { - fprintf(stderr,"error adding CC inputs\n"); + CCerror = strprintf("error adding CC inputs"); + fprintf(stderr,"%s\n",CCerror.c_str()); return(""); } } + CCerror = strprintf("error adding normal inputs"); + fprintf(stderr,"%s\n",CCerror.c_str()); return(""); } -UniValue ChannelsInfo(uint256 channeltxid) +UniValue ChannelsList() { - UniValue result(UniValue::VOBJ); CTransaction tx,opentx; uint256 txid,tmp_txid,hashBlock,param3,opentxid,hashchain,prevtxid; - struct CCcontract_info *cp,C; char myCCaddr[65],addr[65],str1[512],str2[256]; int32_t vout,numvouts,param1,numpayments; - int64_t nValue,param2,payment; CPubKey srcpub,destpub,mypk; - std::vector > txids; + UniValue result(UniValue::VOBJ); std::vector > txids; struct CCcontract_info *cp,C; uint256 txid,hashBlock,tmp_txid,param3,tokenid; + CTransaction tx; char myCCaddr[65],addr[65],str[256]; CPubKey mypk,srcpub,destpub; int32_t vout,numvouts,param1; + int64_t nValue,param2; - result.push_back(Pair("result","success")); cp = CCinit(&C,EVAL_CHANNELS); mypk = pubkey2pk(Mypubkey()); - if (channeltxid==zeroid) + GetCCaddress(cp,myCCaddr,mypk); + SetCCtxids(txids,myCCaddr); + result.push_back(Pair("result","success")); + result.push_back(Pair("name","Channels List")); + for (std::vector >::const_iterator it=txids.begin(); it!=txids.end(); it++) { - result.push_back(Pair("name","Channels Info")); - GetCCaddress(cp,myCCaddr,mypk); - SetCCtxids(txids,myCCaddr); - for (std::vector >::const_iterator it=txids.begin(); it!=txids.end(); it++) + txid = it->first.txhash; + vout = (int32_t)it->first.index; + nValue = (int64_t)it->second; + if ( (vout == 1 || vout == 2) && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 ) { - //int height = it->first.blockHeight; - txid = it->first.txhash; - vout = (int32_t)it->first.index; - nValue = (int64_t)it->second; - if ( (vout == 1 || vout == 2) && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 ) - { - if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3) == 'O') - { - GetCCaddress1of2(cp,addr,srcpub,destpub); - sprintf(str1,"%s - %lld payments of %lld satoshi - %s",addr,(long long)param1,(long long)param2,tx.GetHash().ToString().c_str()); - result.push_back(Pair("Channel", str1)); - } - } - } - } - else - { - if (GetTransaction(channeltxid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 && - (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'O')) - { - GetCCaddress1of2(cp,addr,srcpub,destpub); - sprintf(str1,"Channel %s",addr); - result.push_back(Pair("name",str1)); - SetCCtxids(txids,addr); - prevtxid=zeroid; - for (std::vector >::const_iterator it=txids.begin(); it!=txids.end(); it++) - { - - txid = it->first.txhash; - if (txid!=prevtxid && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 ) - { - if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,param1,param2,param3) == 'O' && tx.GetHash()==channeltxid) - { - sprintf(str1,"%lld payments of %lld satoshi",(long long)param1,(long long)param2); - result.push_back(Pair("Open", str1)); - } - else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'P' && opentxid==channeltxid) - { - if (GetTransaction(opentxid,opentx,hashBlock,false) != 0 && (numvouts=opentx.vout.size()) > 0 && - DecodeChannelsOpRet(opentx.vout[numvouts-1].scriptPubKey,tmp_txid,srcpub,destpub,numpayments,payment,hashchain) == 'O') - { - Getscriptaddress(str2,tx.vout[3].scriptPubKey); - sprintf(str1,"%lld satoshi to %s, %lld payments left",(long long)(param2*payment),str2,(long long)param1); - result.push_back(Pair("Payment",str1)); - } - } - else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'C' && opentxid==channeltxid) - { - result.push_back(Pair("Close","channel")); - } - else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,opentxid,srcpub,destpub,param1,param2,param3) == 'R' && opentxid==channeltxid) - { - Getscriptaddress(str2,tx.vout[2].scriptPubKey); - sprintf(str1,"%lld satoshi back to %s",(long long)(param1*param2),str2); - result.push_back(Pair("Refund",str1)); - } - } - prevtxid=txid; + if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3) == 'O') + { + GetCCaddress1of2(cp,addr,srcpub,destpub); + sprintf(str,"%s - %lld payments of %lld satoshi",addr,(long long)param1,(long long)param2); + result.push_back(Pair(txid.GetHex().data(),str)); } } } return(result); } + +UniValue ChannelsInfo(uint256 channeltxid) +{ + UniValue result(UniValue::VOBJ),array(UniValue::VARR); CTransaction tx,opentx; uint256 txid,tmp_txid,hashBlock,param3,opentxid,hashchain,prevtxid,tokenid; + struct CCcontract_info *cp,C; char CCaddr[65],addr[65],str[512]; int32_t vout,numvouts,param1,numpayments; + int64_t param2,payment; CPubKey srcpub,destpub,mypk; + std::vector > addressIndex; std::vector txids; + + cp = CCinit(&C,EVAL_CHANNELS); + mypk = pubkey2pk(Mypubkey()); + + if (GetTransaction(channeltxid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 && + (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,opentxid,srcpub,destpub,param1,param2,param3) == 'O')) + { + GetCCaddress(cp,CCaddr,mypk); + Getscriptaddress(addr,CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG); + result.push_back(Pair("result","success")); + result.push_back(Pair("Channel CC address",CCaddr)); + result.push_back(Pair("Destination address",addr)); + result.push_back(Pair("Number of payments",param1)); + if(tokenid!=zeroid) + { + result.push_back(Pair("Token id",tokenid.GetHex().data())); + result.push_back(Pair("Denomination (token satoshi)",i64tostr(param2))); + result.push_back(Pair("Amount (token satoshi)",i64tostr(param1*param2))); + } + else + { + result.push_back(Pair("Denomination (satoshi)",i64tostr(param2))); + result.push_back(Pair("Amount (satoshi)",i64tostr(param1*param2))); + } + SetCCtxids(addressIndex,CCaddr); + for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) + { + if (GetTransaction(it->first.txhash,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 ) + if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3)!=0 && (tmp_txid==channeltxid || tx.GetHash()==channeltxid)) + txids.push_back(it->first.txhash); + } + BOOST_FOREACH(const CTxMemPoolEntry &e, mempool.mapTx) + { + const CTransaction &txmempool = e.GetTx(); + const uint256 &hash = txmempool.GetHash(); + + if ((numvouts=txmempool.vout.size()) > 0 && DecodeChannelsOpRet(txmempool.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3) == 'P' && tmp_txid==channeltxid) + txids.push_back(hash); + } + prevtxid=zeroid; + for (std::vector::const_iterator it=txids.begin(); it!=txids.end(); it++) + { + txid=*it; + if (txid!=prevtxid && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 ) + { + UniValue obj(UniValue::VOBJ); + if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3) == 'O' && tx.GetHash()==channeltxid) + { + obj.push_back(Pair("Open",txid.GetHex().data())); + } + else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,opentxid,srcpub,destpub,param1,param2,param3) == 'P' && opentxid==channeltxid) + { + if (GetTransaction(opentxid,opentx,hashBlock,false) != 0 && (numvouts=opentx.vout.size()) > 0 && + DecodeChannelsOpRet(opentx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,numpayments,payment,hashchain) == 'O') + { + Getscriptaddress(str,tx.vout[3].scriptPubKey); + obj.push_back(Pair("Payment",txid.GetHex().data())); + obj.push_back(Pair("Number of payments",param2)); + obj.push_back(Pair("Amount",param2*payment)); + obj.push_back(Pair("Destination",str)); + obj.push_back(Pair("Secret",param3.ToString().c_str())); + obj.push_back(Pair("Payments left",param1)); + } + } + else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,opentxid,srcpub,destpub,param1,param2,param3) == 'C' && opentxid==channeltxid) + { + obj.push_back(Pair("Close",txid.GetHex().data())); + } + else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,opentxid,srcpub,destpub,param1,param2,param3) == 'R' && opentxid==channeltxid) + { + Getscriptaddress(str,tx.vout[2].scriptPubKey); + obj.push_back(Pair("Refund",txid.GetHex().data())); + obj.push_back(Pair("Amount",param1*param2)); + obj.push_back(Pair("Destination",str)); + } + array.push_back(obj); + } + prevtxid=txid; + } + result.push_back(Pair("Transactions",array)); + } + else + { + result.push_back(Pair("result","error")); + result.push_back(Pair("Error","Channel not found!")); + } + return(result); +} diff --git a/src/cc/crypto777/OS_portable.h b/src/cc/crypto777/OS_portable.h index 9da753811..d6abc98c5 100755 --- a/src/cc/crypto777/OS_portable.h +++ b/src/cc/crypto777/OS_portable.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cc/dapps/cJSON.c b/src/cc/dapps/cJSON.c index e0665e378..62f46444c 100755 --- a/src/cc/dapps/cJSON.c +++ b/src/cc/dapps/cJSON.c @@ -669,7 +669,7 @@ void cJSON_Minify(char *json) // the following written by jl777 /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cc/dapps/oraclefeed.c b/src/cc/dapps/oraclefeed.c index 68c02310b..8a819a147 100644 --- a/src/cc/dapps/oraclefeed.c +++ b/src/cc/dapps/oraclefeed.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -822,22 +822,6 @@ int32_t get_gatewaysinfo(char *refcoin,char *acname,char *depositaddr,int32_t *M else return(0); } -int32_t tx_notarizedconfirmed(char *refcoin,char *acname,bits256 txid) -{ - char *retstr,str[65]; cJSON *retjson; int32_t result; - if ( (retjson= get_komodocli(refcoin,&retstr,acname,"txnotarizedconfirmed",bits256_str(str,txid),"","","")) != 0 ) - { - if (is_cJSON_True(jobj(retjson,"result")) != 0 ) result=1; - else result=0; - free_json(retjson); - } - else if ( retstr != 0 ) - { - printf("error parsing txnotarizedconfirmed.(%s)\n",retstr); - free(retstr); - } -} - int32_t tx_has_voutaddress(char *refcoin,char *acname,bits256 txid,char *coinaddr) { cJSON *txobj,*vouts,*vout,*vins,*vin,*sobj,*addresses; char *addr,str[65]; int32_t i,j,n,numarray,retval = 0, hasvout=0; diff --git a/src/cc/dapps/zmigrate.c b/src/cc/dapps/zmigrate.c index 3f26c50a1..cfbd29d70 100644 --- a/src/cc/dapps/zmigrate.c +++ b/src/cc/dapps/zmigrate.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -647,21 +647,57 @@ int64_t z_getbalance(char *refcoin,char *acname,char *coinaddr) return (amount); } +int32_t z_exportkey(char *privkey,char *refcoin,char *acname,char *zaddr) +{ + cJSON *retjson; char *retstr,cmpstr[64]; int64_t amount=0; int32_t retval = -1; + privkey[0] = 0; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"z_exportkey",zaddr,"","","")) != 0 ) + { + fprintf(stderr,"z_exportkey.(%s) %s returned json!\n",refcoin,acname); + free_json(retjson); + } + else if ( retstr != 0 ) + { + //printf("retstr %s -> %.8f\n",retstr,dstr(amount)); + strcpy(privkey,retstr); + free(retstr); + retval = 0; + } + return(retval); +} + int32_t getnewaddress(char *coinaddr,char *refcoin,char *acname) { - cJSON *retjson; char *retstr; int64_t amount=0; + cJSON *retjson; char *retstr; int64_t amount=0; int32_t retval = -1; if ( (retjson= get_komodocli(refcoin,&retstr,acname,"getnewaddress","","","","")) != 0 ) { fprintf(stderr,"getnewaddress.(%s) %s returned json!\n",refcoin,acname); free_json(retjson); - return(-1); } else if ( retstr != 0 ) { strcpy(coinaddr,retstr); free(retstr); - return(0); + retval = 0; } + return(retval); +} + +int32_t z_getnewaddress(char *coinaddr,char *refcoin,char *acname,char *typestr) +{ + cJSON *retjson; char *retstr; int64_t amount=0; int32_t retval = -1; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"z_getnewaddress",typestr,"","","")) != 0 ) + { + fprintf(stderr,"z_getnewaddress.(%s) %s returned json!\n",refcoin,acname); + free_json(retjson); + } + else if ( retstr != 0 ) + { + strcpy(coinaddr,retstr); + free(retstr); + retval = 0; + } + return(retval); } int64_t find_onetime_amount(char *coinstr,char *coinaddr) @@ -676,6 +712,10 @@ int64_t find_onetime_amount(char *coinstr,char *coinaddr) for (i=0; i %s\n",srcaddr,params); @@ -740,15 +780,48 @@ int32_t z_sendmany(char *opidstr,char *coinstr,char *acname,char *srcaddr,char * { printf("unexpected json z_sendmany.(%s)\n",jprint(retjson,0)); free_json(retjson); - return(-1); } else if ( retstr != 0 ) { fprintf(stderr,"z_sendmany.(%s) -> opid.(%s)\n",coinstr,retstr); strcpy(opidstr,retstr); free(retstr); - return(0); + retval = 0; } + return(retval); +} + +int32_t z_mergetoaddress(char *opidstr,char *coinstr,char *acname,char *destaddr) +{ + cJSON *retjson; char *retstr,addr[128],*opstr; int32_t retval = -1; + sprintf(addr,"[\\\"ANY_SPROUT\\\"]"); + //printf("z_sendmany from.(%s) -> %s\n",addr,destaddr); + if ( (retjson= get_komodocli(coinstr,&retstr,acname,"z_mergetoaddress",addr,destaddr,"","")) != 0 ) + { + /*{ + "remainingUTXOs": 0, + "remainingTransparentValue": 0.00000000, + "remainingNotes": 222, + "remainingShieldedValue": 5413.39093055, + "mergingUTXOs": 0, + "mergingTransparentValue": 0.00000000, + "mergingNotes": 10, + "mergingShieldedValue": 822.47447172, + "opid": "opid-f28f6261-4120-436c-aca5-859870a40a70" + }*/ + if ( (opstr= jstr(retjson,"opid")) != 0 ) + strcpy(opidstr,opstr); + retval = jint(retjson,"remainingNotes"); + fprintf(stderr,"%s\n",jprint(retjson,0)); + free_json(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"z_mergetoaddress.(%s) -> opid.(%s)\n",coinstr,retstr); + strcpy(opidstr,retstr); + free(retstr); + } + return(retval); } int32_t empty_mempool(char *coinstr,char *acname) @@ -907,10 +980,25 @@ int32_t main(int32_t argc,char **argv) } zsaddr = clonestr(argv[2]); printf("%s: %s %s\n",REFCOIN_CLI,coinstr,zsaddr); - uint32_t lastopid; char coinaddr[64],zcaddr[128],opidstr[128]; int32_t finished; int64_t amount,stdamount,txfee; + uint32_t lastopid; char coinaddr[64],privkey[1024],zcaddr[128],opidstr[128]; int32_t finished; int64_t amount,stdamount,txfee; //stdamount = 500 * SATOSHIDEN; txfee = 10000; again: + if ( z_getnewaddress(zcaddr,coinstr,"","sprout") == 0 ) + { + z_exportkey(privkey,coinstr,"",zcaddr); + printf("zcaddr.(%s) -> z_exportkey.(%s)\n",zcaddr,privkey); + while ( 1 ) + { + if ( have_pending_opid(coinstr,0) != 0 ) + { + sleep(10); + continue; + } + if ( z_mergetoaddress(opidstr,coinstr,"",zcaddr) <= 0 ) + break; + } + } printf("start processing zmigrate\n"); lastopid = (uint32_t)time(NULL); finished = 0; diff --git a/src/cc/dice.cpp b/src/cc/dice.cpp index 45e101e9c..05dad9bf6 100644 --- a/src/cc/dice.cpp +++ b/src/cc/dice.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cc/disputepayout.cpp b/src/cc/disputepayout.cpp index 1271b0da5..60924b00b 100644 --- a/src/cc/disputepayout.cpp +++ b/src/cc/disputepayout.cpp @@ -1,3 +1,18 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include #include "hash.h" diff --git a/src/cc/eval.cpp b/src/cc/eval.cpp index 35644a82a..ca2703bff 100644 --- a/src/cc/eval.cpp +++ b/src/cc/eval.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -27,6 +27,8 @@ #include "core_io.h" #include "crosschain.h" +bool CClib_Dispatch(const CC *cond,Eval *eval,std::vector paramsNull,const CTransaction &txTo,unsigned int nIn); +char *CClib_name(); Eval* EVAL_TEST = 0; struct CCcontract_info CCinfos[0x100]; @@ -38,8 +40,9 @@ bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn) pthread_mutex_lock(&KOMODO_CC_mutex); bool out = eval->Dispatch(cond, tx, nIn); pthread_mutex_unlock(&KOMODO_CC_mutex); - //fprintf(stderr,"out %d vs %d isValid\n",(int32_t)out,(int32_t)eval->state.IsValid()); - assert(eval->state.IsValid() == out); + if ( eval->state.IsValid() != out) + fprintf(stderr,"out %d vs %d isValid\n",(int32_t)out,(int32_t)eval->state.IsValid()); + //assert(eval->state.IsValid() == out); if (eval->state.IsValid()) return true; @@ -64,13 +67,24 @@ bool Eval::Dispatch(const CC *cond, const CTransaction &txTo, unsigned int nIn) return Invalid("empty-eval"); uint8_t ecode = cond->code[0]; + if ( ASSETCHAINS_CCDISABLES[ecode] != 0 ) + { + fprintf(stderr,"%s evalcode.%d %02x\n",txTo.GetHash().GetHex().c_str(),ecode,ecode); + return Invalid("disabled-code, -ac_ccenables didnt include this ecode"); + } + std::vector vparams(cond->code+1, cond->code+cond->codeLength); + if ( ecode >= EVAL_FIRSTUSER && ecode <= EVAL_LASTUSER ) + { + if ( ASSETCHAINS_CCLIB.size() > 0 && ASSETCHAINS_CCLIB == CClib_name() ) + return CClib_Dispatch(cond,this,vparams,txTo,nIn); + else return Invalid("mismatched -ac_cclib vs CClib_name"); + } cp = &CCinfos[(int32_t)ecode]; if ( cp->didinit == 0 ) { CCinit(cp,ecode); cp->didinit = 1; } - std::vector vparams(cond->code+1, cond->code+cond->codeLength); switch ( ecode ) { case EVAL_IMPORTPAYOUT: diff --git a/src/cc/eval.h b/src/cc/eval.h index 006fca950..a42bbdb2f 100644 --- a/src/cc/eval.h +++ b/src/cc/eval.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -53,11 +53,16 @@ EVAL(EVAL_ORACLES, 0xec) \ EVAL(EVAL_PRICES, 0xed) \ EVAL(EVAL_PEGS, 0xee) \ - EVAL(EVAL_TRIGGERS, 0xef) \ + EVAL(EVAL_MARMARA, 0xef) \ EVAL(EVAL_PAYMENTS, 0xf0) \ - EVAL(EVAL_GATEWAYS, 0xf1) + EVAL(EVAL_GATEWAYS, 0xf1) \ + EVAL(EVAL_TOKENS, 0xf2) +// evalcodes 0x10 to 0x7f are reserved for cclib dynamic CC +#define EVAL_FIRSTUSER 0x10 +#define EVAL_LASTUSER 0x7f + typedef uint8_t EvalCode; diff --git a/src/cc/faucet.cpp b/src/cc/faucet.cpp index afd97c1aa..6e59b6c1a 100644 --- a/src/cc/faucet.cpp +++ b/src/cc/faucet.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cc/fsm.cpp b/src/cc/fsm.cpp index e75c53bcc..0bcc61a1b 100644 --- a/src/cc/fsm.cpp +++ b/src/cc/fsm.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -75,7 +75,7 @@ bool FSMExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &t bool FSMValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) { int32_t numvins,numvouts,preventCCvins,preventCCvouts,i; bool retval; - return(false); // reject any FSM CC for now + return eval->Invalid("no validation yet"); numvins = tx.vin.size(); numvouts = tx.vout.size(); preventCCvins = preventCCvouts = -1; diff --git a/src/cc/gateways.cpp b/src/cc/gateways.cpp index 94d662193..c64d56b80 100644 --- a/src/cc/gateways.cpp +++ b/src/cc/gateways.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -132,14 +132,18 @@ Implementation Issues: - When thinking about validation, it is clear that we cant use EVAL_ASSETS for the locked coins as there wont be any enforcement of the gateways locking. This means we need a way to transfer assets into gateways outputs and back. It seems a tokenconvert rpc will be needed and hopefully that will be enough to make it all work properly. + -- When thinking about validation, it is clear that we cant use EVAL_ASSETS for the locked coins as there wont be any enforcement of the gateways locking. + -- This means we need a way to transfer assets into gateways outputs and back. It seems a tokenconvert rpc will be needed and hopefully that will be enough to make it all work properly. + ++ The use of tokenconvert has been changed to the use of the new Tokens contract which can enforce other contracts validation by forwarding eval->validate call to GatewaysValidate + ++ So all tokens remain within that Tokens contract eval code. - Care must be taken so that tokens are not lost and can be converted back. - - This changes the usage to require tokenconvert before doing the bind and also tokenconvert before doing a withdraw. EVAL_GATEWAYS has evalcode of 241 - - The gatewaysclaim automatically converts the deposit amount of tokens back to EVAL_ASSETS. + -- Care must be taken so that tokens are not lost and can be converted back. + -- This changes the usage to require tokenconvert before doing the bind and also tokenconvert before doing a withdraw. EVAL_GATEWAYS has evalcode of 241 + ++ tokenconvert now returns 'not implemented', no need to use it at all. + -- The gatewaysclaim automatically converts the deposit amount of tokens back to EVAL_ASSETS. + ++ The gatewaysclaim automatically transfers the deposit amount of tokens to depositor's address (within EVAL_TOKENS). + */ @@ -204,38 +208,42 @@ uint8_t DecodeGatewaysDepositOpRet(const CScript &scriptPubKey,std::string &coin return(0); } -CScript EncodeGatewaysClaimOpRet(uint8_t funcid,uint256 assetid,std::string refcoin,uint256 bindtxid,uint256 deposittxid,CPubKey destpub,int64_t amount) +// encodes payload for the token opret (needs to be added to the tail of it) +CScript EncodeGatewaysClaimOpRet(uint8_t funcid, std::string refcoin, uint256 bindtxid, uint256 deposittxid, CPubKey destpub, int64_t amount) { - CScript opret; uint8_t evalcode = EVAL_ASSETS; - opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << assetid << refcoin << bindtxid << deposittxid << destpub << amount); + CScript opret; + + opret << OP_RETURN << E_MARSHAL(ss << funcid << refcoin << bindtxid << deposittxid << destpub << amount); return(opret); } -uint8_t DecodeGatewaysClaimOpRet(const CScript &scriptPubKey,uint256 &assetid,std::string &refcoin,uint256 &bindtxid,uint256 &deposittxid,CPubKey &destpub,int64_t &amount) +uint8_t DecodeGatewaysClaimOpRet(const CScript &scriptPubKey,uint256 &tokenid,std::string &refcoin,uint256 &bindtxid,uint256 &deposittxid,CPubKey &destpub,int64_t &amount) { std::vector vopret; uint8_t *script,e,f; GetOpReturnData(scriptPubKey, vopret); script = (uint8_t *)vopret.data(); - if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> assetid; ss >> refcoin; ss >> bindtxid; ss >> deposittxid; ss >> destpub; ss >> amount) != 0 ) + if ( vopret.size() > 2 && E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> tokenid; ss >> refcoin; ss >> bindtxid; ss >> deposittxid; ss >> destpub; ss >> amount) != 0 ) { return(f); } return(0); } -CScript EncodeGatewaysWithdrawOpRet(uint8_t funcid,uint256 assetid, std::string refcoin, CPubKey withdrawpub, int64_t amount) +CScript EncodeGatewaysWithdrawOpRet(uint8_t funcid, std::string refcoin, CPubKey withdrawpub, int64_t amount) { - CScript opret; uint8_t evalcode = EVAL_GATEWAYS; - opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << assetid << refcoin << withdrawpub << amount); + CScript opret; + opret << OP_RETURN << E_MARSHAL(ss << funcid << refcoin << withdrawpub << amount); return(opret); } -uint8_t DecodeGatewaysWithdrawOpRet(const CScript &scriptPubKey, uint256 &assetid, std::string &refcoin, CPubKey &withdrawpub, int64_t &amount) +uint8_t DecodeGatewaysWithdrawOpRet(const CScript &scriptPubKey, uint256 &tokenid, std::string &refcoin, CPubKey &withdrawpub, int64_t &amount) { std::vector vopret; uint8_t *script,e,f; + + GetOpReturnData(scriptPubKey, vopret); script = (uint8_t *)vopret.data(); - if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> assetid; ss >> refcoin; ss >> withdrawpub; ss >> amount) != 0 ) + if ( vopret.size() > 2 && E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> tokenid; ss >> refcoin; ss >> withdrawpub; ss >> amount) != 0 ) { return(f); } @@ -304,7 +312,7 @@ uint8_t DecodeGatewaysOpRet(const CScript &scriptPubKey) std::vector vopret; uint8_t *script,e,f; GetOpReturnData(scriptPubKey, vopret); script = (uint8_t *)vopret.data(); - if ( vopret.size() > 2 && (script[0] == EVAL_GATEWAYS || script[0] == EVAL_ASSETS) && E_UNMARSHAL(vopret,ss >> e; ss >> f) != 0 ) + if ( vopret.size() > 2 && (script[0] == EVAL_GATEWAYS || script[0] == EVAL_TOKENS) && E_UNMARSHAL(vopret,ss >> e; ss >> f) != 0 ) { if (f == 'B' && f == 'D' && f == 't' && f == 'W' && f == 'P' && f == 'M') return(f); @@ -512,7 +520,7 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction & int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks,height,claimvout; bool retval; uint8_t funcid,hash[32],M,N,taddr,prefix,prefix2; char str[65],destaddr[64],depositaddr[65],validationError[512]; std::vector txids; std::vector pubkeys,publishers,tmppublishers; std::vector proof; int64_t totalsupply,amount,tmpamount; - uint256 hashblock,txid,bindtxid,deposittxid,assetid,oracletxid,tokenid,cointxid,tmptxid,tmpxtxid2,merkleroot,mhash; CTransaction bindtx,deposittx,oracletx; + uint256 hashblock,txid,bindtxid,deposittxid,tokenidClaim,oracletxid,tokenidBind,cointxid,tmptxid,tmpxtxid2,merkleroot,mhash; CTransaction bindtx,deposittx,oracletx; std::string refcoin,tmprefcoin,deposithex; CPubKey destpub,tmpdestpub; fprintf(stderr,"return true without gateways validation\n"); @@ -565,8 +573,8 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction & //vin.2: CC input of marker from gatewaysdeposit tx //vout.0: CC vout of total tokens from deposit amount to asset eval code //(vout.1): CC vout if there is change of unused tokens back to owner of tokens (deposit amount less than available tokens) - //vout.n-1: opreturn - 't' assetid zeroid 0 mypubkey (NOTE: opreturn is with asset eval code) - if ((numvouts=tx.vout.size()) > 0 && DecodeGatewaysClaimOpRet(tx.vout[numvouts-1].scriptPubKey,assetid,refcoin,bindtxid,deposittxid,destpub,amount)==0) + //vout.n-1: opreturn - 't' tokenid zeroid 0 mypubkey (NOTE: opreturn is with asset eval code) + if ((numvouts=tx.vout.size()) > 0 && DecodeGatewaysClaimOpRet(tx.vout[numvouts-1].scriptPubKey,tokenidClaim,refcoin,bindtxid,deposittxid,destpub,amount)==0) return eval->Invalid("invalid gatewaysclaim OP_RETURN data!"); else if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) return eval->Invalid("vin.0 is normal for gatewaysClaim!"); @@ -580,12 +588,12 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction & return eval->Invalid("vout.1 is CC for gatewaysClaim!"); else if (myGetTransaction(bindtxid,bindtx,hashblock) == 0) return eval->Invalid("invalid gatewaysbind txid!"); - else if ((numvouts=bindtx.vout.size()) > 0 && DecodeGatewaysBindOpRet(depositaddr,bindtx.vout[numvouts-1].scriptPubKey,tmprefcoin,tokenid,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2) != 'B') + else if ((numvouts=bindtx.vout.size()) > 0 && DecodeGatewaysBindOpRet(depositaddr,bindtx.vout[numvouts-1].scriptPubKey,tmprefcoin,tokenidBind,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2) != 'B') return eval->Invalid("invalid gatewaysbind OP_RETURN data!"); else if (tmprefcoin!=refcoin) return eval->Invalid("refcoin different in bind tx"); - else if (tokenid!=assetid) - return eval->Invalid("assetid does not match tokenid from gatewaysbind"); + else if (tokenidClaim!=tokenidBind) + return eval->Invalid("tokenid does not match tokenid from gatewaysbind"); else if (komodo_txnotarizedconfirmed(bindtxid) == false) return eval->Invalid("gatewaysbind tx is not yet confirmed(notarised)!"); else if (myGetTransaction(deposittxid,deposittx,hashblock) == 0) @@ -642,7 +650,7 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction & //vout.1: normal vout txfee marker to withdraw destination pubkey //vout.2: CC vout txfee marker to gateways CC address //vout.n-2: CC vout if there is change of unused tokens back to owner of tokens (withdraw amount less than owner available tokens) - //vout.n-1: opreturn - 'W' assetid refcoin withdrawpub amount + //vout.n-1: opreturn - 'W' tokenid refcoin withdrawpub amount break; case 'P': //vin.0: normal input @@ -675,9 +683,9 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction & // helper functions for rpc calls in rpcwallet.cpp -int64_t AddGatewaysInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 refassetid,int64_t total,int32_t maxinputs) +int64_t AddGatewaysInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 reftokenid,int64_t total,int32_t maxinputs) { - char coinaddr[64],destaddr[64]; int64_t threshold,nValue,price,totalinputs = 0; uint256 assetid,txid,hashBlock; std::vector origpubkey; std::vector vopret; CTransaction vintx; int32_t j,vout,n = 0; uint8_t evalcode,funcid; + char coinaddr[64],destaddr[64]; int64_t threshold,nValue,price,totalinputs = 0; uint256 tokenid,txid,hashBlock; std::vector origpubkey; std::vector vopret; CTransaction vintx; int32_t j,vout,n = 0; uint8_t evalcode,funcid; std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); SetCCunspents(unspentOutputs,coinaddr); @@ -701,11 +709,11 @@ int64_t AddGatewaysInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CP if ( strcmp(destaddr,coinaddr) != 0 && strcmp(destaddr,cp->unspendableCCaddr) != 0 && strcmp(destaddr,cp->unspendableaddr2) != 0 ) continue; GetOpReturnData(vintx.vout[vintx.vout.size()-1].scriptPubKey, vopret); - if ( E_UNMARSHAL(vopret,ss >> evalcode; ss >> funcid; ss >> assetid) != 0 ) + if ( E_UNMARSHAL(vopret,ss >> evalcode; ss >> funcid; ss >> tokenid) != 0 ) { - assetid = revuint256(assetid); - char str[65],str2[65]; fprintf(stderr,"vout.%d %d:%d (%c) check for refassetid.%s vs %s %.8f\n",vout,evalcode,cp->evalcode,funcid,uint256_str(str,refassetid),uint256_str(str2,assetid),(double)vintx.vout[vout].nValue/COIN); - if ( assetid == refassetid && funcid == 't' && (nValue= vintx.vout[vout].nValue) > 0 && myIsutxo_spentinmempool(txid,vout) == 0 ) + tokenid = revuint256(tokenid); + char str[65],str2[65]; fprintf(stderr,"vout.%d %d:%d (%c) check for reftokenid.%s vs %s %.8f\n",vout,evalcode,cp->evalcode,funcid,uint256_str(str,reftokenid),uint256_str(str2,tokenid),(double)vintx.vout[vout].nValue/COIN); + if ( tokenid == reftokenid && funcid == 't' && (nValue= vintx.vout[vout].nValue) > 0 && myIsutxo_spentinmempool(txid,vout) == 0 ) { //fprintf(stderr,"total %llu maxinputs.%d %.8f\n",(long long)total,maxinputs,(double)it->second.satoshis/COIN); if ( total != 0 && maxinputs != 0 ) @@ -905,7 +913,7 @@ std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,ui CTransaction tx; CPubKey mypk,gatewayspk,tmpdestpub; struct CCcontract_info *cp,C; uint8_t M,N,taddr,prefix,prefix2; std::string coin, deposithex; std::vector msigpubkeys,publishers; int64_t totalsupply,depositamount,tmpamount,inputs,CCchange=0; int32_t numvouts,claimvout,height; std::vector proof; - uint256 hashBlock,assetid,oracletxid,tmptxid,cointxid; char str[65],depositaddr[64],coinaddr[64],destaddr[64]; std::vector txids; + uint256 hashBlock,tokenid,oracletxid,tmptxid,cointxid; char str[65],depositaddr[64],coinaddr[64],destaddr[64]; std::vector txids; cp = CCinit(&C,EVAL_GATEWAYS); if ( txfee == 0 ) @@ -917,7 +925,7 @@ std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,ui fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid)); return(""); } - if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,coin,assetid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || coin != refcoin ) + if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,coin,tokenid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || coin != refcoin ) { fprintf(stderr,"invalid coin - bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin.c_str()); return(""); @@ -945,17 +953,24 @@ std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,ui //fprintf(stderr,"depositaddr.(%s) vs %s\n",depositaddr,cp->unspendableaddr2); if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 ) { - if ( (inputs= AddGatewaysInputs(cp,mtx,gatewayspk,assetid,amount,60)) > 0 ) + ///////// if ( (inputs= AddGatewaysInputs(cp,mtx,gatewayspk,tokenid,amount,60)) > 0 ) + if ((inputs = AddTokenCCInputs(cp, mtx, gatewayspk, tokenid, amount, 60)) > 0) { if ( inputs > amount ) CCchange = (inputs - amount); _GetCCaddress(destaddr,EVAL_GATEWAYS,mypk); //printf("expecting deposittxid/v0 to be to %s\n",destaddr); mtx.vin.push_back(CTxIn(deposittxid,0,CScript())); // triggers EVAL_GATEWAYS validation - mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,amount,mypk)); // transfer back to normal token + mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS,amount,mypk)); // transfer back to normal token if ( CCchange != 0 ) - mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CCchange,gatewayspk)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysClaimOpRet('t',assetid,refcoin,bindtxid,deposittxid,destpub,amount))); + mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CCchange,gatewayspk)); + + std::vector voutTokenPubkeys; + voutTokenPubkeys.push_back(mypk); // the pubkey where tokens are going (vout[0]) + + return(FinalizeCCTx(0,cp,mtx,mypk,txfee, + EncodeTokenOpRet('t', EVAL_GATEWAYS, tokenid, voutTokenPubkeys, + EncodeGatewaysClaimOpRet('t', refcoin, bindtxid, deposittxid, destpub, amount)))); // yes, 't' is passed twice } } CCerror = strprintf("cant find enough inputs or mismatched total"); @@ -966,39 +981,67 @@ std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,ui std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,CPubKey withdrawpub,int64_t amount) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CTransaction tx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C; - uint256 assetid,hashBlock,oracletxid; int32_t numvouts; int64_t totalsupply,inputs,CCchange=0; uint8_t M,N,taddr,prefix,prefix2; std::string coin; + CTransaction tx; + CPubKey mypk, gatewayspk; + uint256 tokenid,hashBlock,oracletxid; int32_t numvouts; int64_t totalsupply,inputs,CCchange=0; uint8_t M,N,taddr,prefix,prefix2; std::string coin; std::vector msigpubkeys; char depositaddr[64],str[65],coinaddr[64]; - cp = CCinit(&C,EVAL_GATEWAYS); + struct CCcontract_info *cpGateways, gatewaysC; + struct CCcontract_info *cpTokens, tokensC; + + cpGateways = CCinit(&gatewaysC, EVAL_GATEWAYS); + cpTokens = CCinit(&tokensC, EVAL_TOKENS); + if ( txfee == 0 ) txfee = 10000; + mypk = pubkey2pk(Mypubkey()); - gatewayspk = GetUnspendable(cp,0); - if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 ) + gatewayspk = GetUnspendable(cpGateways, 0); + + if( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 ) { fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid)); return(""); } - if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,coin,assetid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || coin != refcoin ) + if( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,coin,tokenid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || coin != refcoin ) { fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),coin.c_str()); return(""); } - if ( AddNormalinputs(mtx,mypk,3*txfee,4) > 0 ) + if( AddNormalinputs(mtx, mypk, 3*txfee, 4) > 0 ) { - if ( (inputs= AddGatewaysInputs(cp,mtx,mypk,assetid,amount,60)) > 0 ) + /////if ( (inputs= AddGatewaysInputs(cp,mtx,mypk,tokenid,amount,60)) > 0 ) + if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, tokenid, amount, 60)) > 0) { if ( inputs > amount ) CCchange = (inputs - amount); - mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,amount,gatewayspk)); + mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, amount, gatewayspk)); mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(withdrawpub)) << OP_CHECKSIG)); - mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,txfee,gatewayspk)); + mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS, txfee, gatewayspk)); if ( CCchange != 0 ) - mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CCchange,mypk)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysWithdrawOpRet('W',assetid,refcoin,withdrawpub,amount))); + mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, CCchange, mypk)); + + char unspendableGatewaysAddr[64]; + GetCCaddress(cpGateways, unspendableGatewaysAddr, gatewayspk); + + uint8_t unspendableGatewaysPrivkey[32]; + GetUnspendable(cpGateways, unspendableGatewaysPrivkey); + + // add additional unspendable addr from Gateways: + CCaddr2set(cpTokens, EVAL_GATEWAYS, gatewayspk, unspendableGatewaysPrivkey, unspendableGatewaysAddr); + + std::vector voutTokenPubkeys; + voutTokenPubkeys.push_back(gatewayspk); // the pubkey where tokens are going vout[0] (and for checking the 'change' the Tokens contract will find pubkeys itself) + + return(FinalizeCCTx(0, cpTokens, mtx, mypk, txfee, + EncodeTokenOpRet('t', EVAL_GATEWAYS, tokenid, voutTokenPubkeys, + EncodeGatewaysWithdrawOpRet('W', refcoin, withdrawpub, amount)))); } + CCerror = strprintf("cant find enough token inputs or mismatched total"); + fprintf(stderr, "%s\n", CCerror.c_str()); + return(""); + } - CCerror = strprintf("cant find enough inputs or mismatched total"); + CCerror = strprintf("cant find enough normal inputs or mismatched total"); fprintf(stderr,"%s\n", CCerror.c_str() ); return(""); } @@ -1073,7 +1116,7 @@ std::string GatewaysMarkDone(uint64_t txfee,uint256 completetxid,std::string ref UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin) { UniValue result(UniValue::VOBJ),pending(UniValue::VARR); CTransaction tx; std::string tmprefcoin; CPubKey mypk,gatewayspk,withdrawpub; std::vector msigpubkeys; - uint256 hashBlock,assetid,txid,oracletxid; uint8_t M,N,taddr,prefix,prefix2; + uint256 hashBlock,tokenid,txid,oracletxid; uint8_t M,N,taddr,prefix,prefix2; char depositaddr[64],coinaddr[64],destaddr[64],str[65],withaddr[64],numstr[32],txidaddr[64],cctxidaddr[64],signeraddr[64]; int32_t i,n,numvouts,vout,queueflag; int64_t totalsupply,amount,nValue; struct CCcontract_info *cp,C; std::vector > unspentOutputs; @@ -1087,7 +1130,7 @@ UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin) fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid)); return(result); } - if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tmprefcoin,assetid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || tmprefcoin != refcoin ) + if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tmprefcoin,tokenid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || tmprefcoin != refcoin ) { fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),tmprefcoin.c_str()); return(result); @@ -1108,7 +1151,7 @@ UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin) nValue = (int64_t)it->second.satoshis; fprintf(stderr,"%s %d %ld\n",txid.ToString().c_str(),vout,(long)nValue); if ( vout == 2 && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size())>0 && - DecodeGatewaysWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,assetid,tmprefcoin,withdrawpub,amount) == 'W' && myIsutxo_spentinmempool(txid,vout) == 0) + DecodeGatewaysWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,tmprefcoin,withdrawpub,amount) == 'W' && myIsutxo_spentinmempool(txid,vout) == 0) { Getscriptaddress(destaddr,tx.vout[0].scriptPubKey); Getscriptaddress(withaddr,tx.vout[1].scriptPubKey); @@ -1141,7 +1184,7 @@ UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin) UniValue GatewaysProcessedWithdraws(uint256 bindtxid,std::string refcoin) { UniValue result(UniValue::VOBJ),processed(UniValue::VARR); CTransaction tx; std::string tmprefcoin,hex; CPubKey mypk,gatewayspk,withdrawpub; std::vector msigpubkeys; - uint256 withdrawtxid,hashBlock,txid,assetid,oracletxid; uint8_t M,N,taddr,prefix,prefix2; + uint256 withdrawtxid,hashBlock,txid,tokenid,oracletxid; uint8_t M,N,taddr,prefix,prefix2; char depositaddr[64],coinaddr[64],str[65],numstr[32],txidaddr[64],cctxidaddr[64],withaddr[64]; int32_t i,n,numvouts,vout,queueflag; int64_t totalsupply,nValue,amount; struct CCcontract_info *cp,C; std::vector > unspentOutputs; @@ -1155,7 +1198,7 @@ UniValue GatewaysProcessedWithdraws(uint256 bindtxid,std::string refcoin) fprintf(stderr,"cant find bindtxid %s\n",uint256_str(str,bindtxid)); return(result); } - if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tmprefcoin,assetid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || tmprefcoin != refcoin ) + if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tmprefcoin,tokenid,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2) != 'B' || tmprefcoin != refcoin ) { fprintf(stderr,"invalid bindtxid %s coin.%s\n",uint256_str(str,bindtxid),tmprefcoin.c_str()); return(result); @@ -1178,7 +1221,7 @@ UniValue GatewaysProcessedWithdraws(uint256 bindtxid,std::string refcoin) if ( vout == 0 && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size())>0 && DecodeGatewaysCompleteSigningOpRet(tx.vout[numvouts-1].scriptPubKey,tmprefcoin,withdrawtxid,hex) == 'C' && myIsutxo_spentinmempool(txid,vout) == 0) { - if (GetTransaction(withdrawtxid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size())>0 && DecodeGatewaysWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,assetid,tmprefcoin,withdrawpub,amount) == 'W') + if (GetTransaction(withdrawtxid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size())>0 && DecodeGatewaysWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,tmprefcoin,withdrawpub,amount) == 'W') { UniValue obj(UniValue::VOBJ); obj.push_back(Pair("txid",uint256_str(str,txid))); diff --git a/src/cc/heir.cpp b/src/cc/heir.cpp index 24aa35f59..d00cab795 100644 --- a/src/cc/heir.cpp +++ b/src/cc/heir.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -14,203 +14,1291 @@ ******************************************************************************/ #include "CCHeir.h" +#include "heir_validate.h" +#include + +class CoinHelper; +class TokenHelper; /* The idea of Heir CC is to allow crypto inheritance. - A special 1of2 CC address is created that is freely spendable by the creator. The heir is only allowed to spend after the specified amount of idle blocks. The idea is that if the address doesnt spend any funds for a year (or whatever amount set), then it is time to allow the heir to spend. The design requires the heir to spend all the funds at once -*/ + A special 1of2 CC address is created that is freely spendable by the creator (funds owner). + The owner may add additional funds to this 1of2 address. + The heir is only allowed to spend after "the specified amount of idle blocks" (changed to "the owner inactivityTime"). + The idea is that if the address doesnt spend any funds for a year (or whatever amount set), then it is time to allow the heir to spend. + "The design requires the heir to spend all the funds at once" (this requirement was changed to "after the inactivity time both the heir and owner may freely spend available funds") + After the first heir spending a flag is set that spending is allowed for the heir whether the owner adds more funds or spends them. + This Heir contract supports both coins and tokens. + */ -// start of consensus code +// tx validation code -int64_t IsHeirvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) +// Plan validation runner, it may be called twice - for coins and tokens +// (sadly we cannot have yet 'templatized' lambdas, if we could we could capture all these params inside HeirValidation()...) +template bool RunValidationPlans(uint8_t funcId, struct CCcontract_info* cp, Eval* eval, const CTransaction& tx, uint256 latestTxid, CScript fundingOpretScript, uint8_t hasHeirSpendingBegun) { - char destaddr[64]; - if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) - { - if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 ) - return(tx.vout[v].nValue); + int32_t numvins = tx.vin.size(); + int32_t numvouts = tx.vout.size(); + + // setup validation framework (please see its description in heir_validate.h): + // validation 'plans': + CInputValidationPlan vinPlan; + COutputValidationPlan voutPlan; + + // vin 'identifiers' + CNormalInputIdentifier normalInputIdentifier(cp); + CCCInputIdentifier ccInputIdentifier(cp); + + // vin and vout 'validators' + // not used, too strict for 2 pubkeys: CMyPubkeyVoutValidator normalInputValidator(cp, fundingOpretScript, true); // check normal input for this opret cause this is first tx + CCC1of2AddressValidator cc1of2ValidatorThis(cp, fundingOpretScript, "checking this tx opreturn:"); // 1of2add validator with pubkeys from this tx opreturn + CHeirSpendValidator heirSpendValidator(cp, fundingOpretScript, latestTxid, hasHeirSpendingBegun); // check if heir allowed to spend + + // only for tokens: + CMyPubkeyVoutValidator ownerCCaddrValidator(cp, fundingOpretScript, false); // check if this correct owner's cc user addr corresponding to opret + COpRetValidator opRetValidator(cp, fundingOpretScript); // compare opRets in this and last tx + CMarkerValidator markerValidator(cp); // initial tx marker spending protection + CNullValidator nullValidator(cp); + + switch (funcId) { + case 'F': // fund tokens (only for tokens) + // vin validation plan: + vinPlan.pushValidators((CInputIdentifierBase*)&normalInputIdentifier, &nullValidator); // txfee vin + vinPlan.pushValidators((CInputIdentifierBase*)&ccInputIdentifier, &markerValidator, &ownerCCaddrValidator); // check cc owner addr + + // vout validation plan: + voutPlan.pushValidators(0, &cc1of2ValidatorThis); // check 1of2 addr funding + // do not check change at this time + // no checking for opret yet + break; + + case 'A': // add tokens (only for tokens) + // vin validation plan: + vinPlan.pushValidators((CInputIdentifierBase*)&normalInputIdentifier, &nullValidator); // txfee vin + vinPlan.pushValidators((CInputIdentifierBase*)&ccInputIdentifier, &markerValidator, &ownerCCaddrValidator); // check cc owner addr + + // vout validation plan: + voutPlan.pushValidators(0, &cc1of2ValidatorThis); // check 1of2 addr funding + // do not check change at this time + voutPlan.pushValidators(numvouts - 1, &opRetValidator); // opreturn check, NOTE: only for C or A: + break; + + case 'C': // spend coins or tokens + // vin validation plan: + vinPlan.pushValidators((CInputIdentifierBase*)&normalInputIdentifier, &nullValidator); // txfee vin + vinPlan.pushValidators((CInputIdentifierBase*)&ccInputIdentifier, &markerValidator, &cc1of2ValidatorThis); // cc1of2 funding addr + + // vout validation plan: + voutPlan.pushValidators(0, &heirSpendValidator); // check if heir is allowed to spend + voutPlan.pushValidators(numvouts - 1, &opRetValidator); // opreturn check, NOTE: only for C or A + break; } - return(0); + + // call vin/vout validation + if (!vinPlan.validate(tx, eval)) + return false; + if (!voutPlan.validate(tx, eval)) + return false; + + return true; } -bool HeirExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee) +/** + * Tx validation entry function + */ +bool HeirValidate(struct CCcontract_info* cpHeir, Eval* eval, const CTransaction& tx, uint32_t nIn) { - static uint256 zerohash; - CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis; - numvins = tx.vin.size(); - numvouts = tx.vout.size(); - for (i=0; iismyvin)(tx.vin[i].scriptSig) != 0 ) - { - //fprintf(stderr,"vini.%d check mempool\n",i); - if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 ) - return eval->Invalid("cant find vinTx"); - else - { - //fprintf(stderr,"vini.%d check hash and vout\n",i); - if ( hashBlock == zerohash ) - return eval->Invalid("cant Heir from mempool"); - if ( (assetoshis= IsHeirvout(cp,vinTx,tx.vin[i].prevout.n)) != 0 ) - inputs += assetoshis; - } - } - } - for (i=0; iInvalid("mismatched inputs != outputs + txfee"); - } - else return(true); -} - -bool HeirValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) -{ - int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64]; - return(false); - std::vector > txids; - numvins = tx.vin.size(); - numvouts = tx.vout.size(); - preventCCvins = preventCCvouts = -1; - if ( numvouts < 1 ) + int32_t numvins = tx.vin.size(); + int32_t numvouts = tx.vout.size(); + //int32_t preventCCvins = -1; + //int32_t preventCCvouts = -1; + + struct CCcontract_info *cpTokens, tokensC; + cpTokens = CCinit(&tokensC, EVAL_TOKENS); + + if (numvouts < 1) return eval->Invalid("no vouts"); - else - { - for (i=0; iInvalid("illegal normal vini"); - } + + //if (chainActive.Height() < 741) + // return true; + + uint256 fundingTxidInOpret = zeroid, latestTxid = zeroid, dummyTokenid, tokenidThis, tokenid = zeroid; + + CScript fundingTxOpRetScript; + uint8_t hasHeirSpendingBegun = 0, hasHeirSpendingBegunDummy; + + CScript opret = (tx.vout.size() > 0) ? tx.vout[tx.vout.size() - 1].scriptPubKey : CScript(); // check boundary + uint8_t funcId = DecodeHeirEitherOpRet(opret, tokenidThis, fundingTxidInOpret, hasHeirSpendingBegunDummy, true); + if (funcId == 0) + return eval->Invalid("invalid opreturn format"); + + if (funcId != 'F') { + if (fundingTxidInOpret == zeroid) { + return eval->Invalid("incorrect tx opreturn: no fundingtxid present"); } - //fprintf(stderr,"check amounts\n"); - if ( HeirExactAmounts(cp,eval,tx,1,10000) == false ) - { - fprintf(stderr,"Heirget invalid amount\n"); - return false; - } - else - { - txid = tx.GetHash(); - memcpy(hash,&txid,sizeof(hash)); - retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts); - if ( retval != 0 ) - fprintf(stderr,"Heirget validated\n"); - else fprintf(stderr,"Heirget invalid\n"); - return(retval); + latestTxid = FindLatestFundingTx(fundingTxidInOpret, tokenid, fundingTxOpRetScript, hasHeirSpendingBegun); + + if( tokenid != zeroid && tokenid != tokenidThis ) + return eval->Invalid("incorrect tx tokenid"); + + if (latestTxid == zeroid) { + return eval->Invalid("no fundingtx found"); } } + else { + fundingTxOpRetScript = opret; + } + + std::cerr << "HeirValidate funcid=" << (char)funcId << " evalcode=" << (int)cpHeir->evalcode << std::endl; + + //////////////// temp //////////////////////// + ///return true; + + switch (funcId) { + case 'F': + // fund coins: + // vins.*: normal inputs + // ----------------------------- + // vout.0: funding CC 1of2 addr for the owner and heir + // vout.1: txfee for CC addr used as a marker + // vout.2: normal change + // vout.n-1: opreturn 'F' ownerpk heirpk inactivitytime heirname + + // fund tokens: + // vin.0: normal inputs txfee + // vins.1+: user's CC addr inputs + // ----------------------- + // vout.0: funding heir CC 1of2 addr for the owner and heir + // vout.1: txfee for CC addr used as a marker + // vout.2: normal change + // vout.n-1: opreturn 't' tokenid 'F' ownerpk heirpk inactivitytime heirname tokenid + if (tokenid != zeroid) + return RunValidationPlans(funcId, cpTokens, eval, tx, latestTxid, fundingTxOpRetScript, hasHeirSpendingBegun); + else + return eval->Invalid("unexpected HeirValidate for heirfund"); + // break; + + case 'A': + // add funding coins: + // vins.*: normal inputs + // ------------------------ + // vout.0: funding CC 1of2 addr for the owner and heir + // vout.1: normal change + // vout.n-1: opreturn 'A' ownerpk heirpk inactivitytime fundingtx + + // add funding tokens: + // vins.0: normal inputs txfee + // vins.1+: user's CC addr inputs + // ------------------------ + // vout.0: funding CC 1of2 addr for the owner and heir + // vout.1: normal change + // vout.n-1: opreturn 't' tokenid 'A' ownerpk heirpk inactivitytime fundingtx + if (tokenid != zeroid) + return RunValidationPlans(funcId, cpTokens, eval, tx, latestTxid, fundingTxOpRetScript, hasHeirSpendingBegun); + else + return eval->Invalid("unexpected HeirValidate for heiradd"); + //break; + + case 'C': + // claim coins: + // vin.0: normal input txfee + // vin.1+: input from CC 1of2 addr + // ------------------------------------- + // vout.0: normal output to owner or heir address + // vout.1: change to CC 1of2 addr + // vout.2: change to user's addr from txfee input if any + // vout.n-1: opreturn 'C' ownerpk heirpk inactivitytime fundingtx + + // claim tokens: + // vin.0: normal input txfee + // vin.1+: input from CC 1of2 addr + // -------------------------------------------- + // vout.0: output to user's cc address + // vout.1: change to CC 1of2 addr + // vout.2: change to normal from txfee input if any + // vout.n-1: opreturn 't' tokenid 'C' ownerpk heirpk inactivitytime fundingtx + if (tokenid != zeroid) + return RunValidationPlans(funcId, cpTokens, eval, tx, latestTxid, fundingTxOpRetScript, hasHeirSpendingBegun); + else + return RunValidationPlans(funcId, cpHeir, eval, tx, latestTxid, fundingTxOpRetScript, hasHeirSpendingBegun); + // break; + + default: + std::cerr << "HeirValidate() illegal heir funcid=" << (char)funcId << std::endl; + return eval->Invalid("unexpected HeirValidate funcid"); + // break; + } + return eval->Invalid("unexpected"); // (PreventCC(eval, tx, preventCCvins, numvins, preventCCvouts, numvouts)); } // end of consensus code -// helper functions for rpc calls in rpcwallet.cpp -int64_t AddHeirInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs) +// helper functions used in implementations of rpc calls (in rpcwallet.cpp) or validation code + +/** + * Checks if vout is to cryptocondition address + * @return vout value in satoshis + */ +template int64_t IsHeirFundingVout(struct CCcontract_info* cp, const CTransaction& tx, int32_t voutIndex, CPubKey ownerPubkey, CPubKey heirPubkey) { - // add threshold check - char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t vout,n = 0; - std::vector > unspentOutputs; - GetCCaddress(cp,coinaddr,pk); - SetCCunspents(unspentOutputs,coinaddr); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; + char destaddr[65], heirFundingAddr[65]; + + Helper::GetCoinsOrTokensCCaddress1of2(cp, heirFundingAddr, ownerPubkey, heirPubkey); + if (tx.vout[voutIndex].scriptPubKey.IsPayToCryptoCondition() != 0) { + // NOTE: dimxy it was unsafe 'Getscriptaddress(destaddr,tx.vout[voutIndex].scriptPubKey) > 0' here: + if (Getscriptaddress(destaddr, tx.vout[voutIndex].scriptPubKey) && strcmp(destaddr, heirFundingAddr) == 0) + return (tx.vout[voutIndex].nValue); + else + std::cerr << "IsHeirFundingVout() heirFundingAddr=" << heirFundingAddr << " not equal to destaddr=" << destaddr << std::endl; + } + return (0); +} + +// makes coin initial tx opret +CScript EncodeHeirCreateOpRet(uint8_t funcid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName) +{ + uint8_t evalcode = EVAL_HEIR; + + return CScript() << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << ownerPubkey << heirPubkey << inactivityTimeSec << heirName); +} + +// makes coin additional tx opret +CScript EncodeHeirOpRet(uint8_t funcid, uint256 fundingtxid, uint8_t hasHeirSpendingBegun) +{ + uint8_t evalcode = EVAL_HEIR; + + fundingtxid = revuint256(fundingtxid); + return CScript() << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << fundingtxid << hasHeirSpendingBegun); +} + + +// decode opret vout for Heir contract +uint8_t _DecodeHeirOpRet(std::vector vopret, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, uint256& fundingTxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging) +{ + uint8_t evalCodeInOpret = 0; + uint8_t heirFuncId = 0; + + fundingTxidInOpret = zeroid; //to init + + evalCodeInOpret = vopret.begin()[0]; + + if (vopret.size() > 1 && evalCodeInOpret == EVAL_HEIR) { + // NOTE: it unmarshals for all F, A and C + uint8_t heirFuncId = 0; + hasHeirSpendingBegun = 0; + + bool result = E_UNMARSHAL(vopret, { ss >> evalCodeInOpret; ss >> heirFuncId; \ + if (heirFuncId == 'F') { \ + ss >> ownerPubkey; ss >> heirPubkey; ss >> inactivityTime; ss >> heirName; \ + } \ + else { \ + ss >> fundingTxidInOpret >> hasHeirSpendingBegun; \ + } \ + }); + + if (!result) { + if (!noLogging) std::cerr << "_DecodeHeirOpRet() could not unmarshal opret, evalCode=" << (int)evalCodeInOpret << std::endl; + return (uint8_t)0; + } + + /* std::cerr << "DecodeHeirOpRet()" + << " heirFuncId=" << (char)(heirFuncId ? heirFuncId : ' ') + << " ownerPubkey=" << HexStr(ownerPubkey) + << " heirPubkey=" << HexStr(heirPubkey) + << " heirName=" << heirName << " inactivityTime=" << inactivityTime + << " hasHeirSpendingBegun=" << (int)hasHeirSpendingBegun << std::endl; */ + + if (isMyFuncId(heirFuncId)) { + fundingTxidInOpret = revuint256(fundingTxidInOpret); + return heirFuncId; + } + else { + if(!noLogging) std::cerr << "_DecodeHeirOpRet() unexpected opret type, heirFuncId=" << (char)(heirFuncId ? heirFuncId : ' ') << std::endl; + } + } + else { + if (!noLogging) std::cerr << "_DecodeHeirOpRet() not a heir opret, vopretExtra.size() == 0 or not EVAL_HEIR evalcode=" << (int)evalCodeInOpret << std::endl; + } + return (uint8_t)0; +} + +/* not used, see DecodeHeirOpRet(vopret,...) + // overload for 'F' opret + uint8_t DecodeHeirOpRet(CScript scriptPubKey, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, bool noLogging) + { + uint256 dummytxid; + uint8_t dummyHasHeirSpendingBegun; + std::vector vopret; + + GetOpReturnData(scriptPubKey, vopret); + if (vopret.size() == 0) { + if (!noLogging) std::cerr << "DecodeHeirOpRet() warning: empty opret" << std::endl; + return (uint8_t)0; + } + return _DecodeHeirOpRet(vopret, ownerPubkey, heirPubkey, inactivityTime, heirName, dummytxid, dummyHasHeirSpendingBegun, noLogging); + }*/ + + +/* not used, see DecodeHeirOpRet(vopret,...) + // overload for A, C oprets and AddHeirContractInputs + uint8_t DecodeHeirOpRet(CScript scriptPubKey, uint256& fundingtxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging) + { + CPubKey dummyOwnerPubkey, dummyHeirPubkey; + int64_t dummyInactivityTime; + std::string dummyHeirName; + std::vector vopret; + + GetOpReturnData(scriptPubKey, vopret); + if (vopret.size() == 0) { + if (!noLogging) std::cerr << "DecodeHeirOpRet() warning: empty opret" << std::endl; + return (uint8_t)0; + } + + return _DecodeHeirOpRet(vopret, dummyOwnerPubkey, dummyHeirPubkey, dummyInactivityTime, dummyHeirName, fundingtxidInOpret, hasHeirSpendingBegun, noLogging); + } */ + +// decode combined opret: +uint8_t _DecodeHeirEitherOpRet(CScript scriptPubKey, uint256 &tokenid, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, uint256& fundingTxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging) +{ + uint8_t evalCodeTokens = 0; + std::vector voutPubkeysDummy; + std::vector vopretExtra, vopretStripped; + + if (DecodeTokenOpRet(scriptPubKey, evalCodeTokens, tokenid, voutPubkeysDummy, vopretExtra) != 0) { + if (vopretExtra.size() > 1) { + // restore the second opret: + + if (!E_UNMARSHAL(vopretExtra, { ss >> vopretStripped; })) { //strip string size + if (!noLogging) std::cerr << "_DecodeHeirEitherOpret() could not unmarshal vopretStripped" << std::endl; + return (uint8_t)0; + } + } + else { + if (!noLogging) std::cerr << "_DecodeHeirEitherOpret() empty vopretExtra" << std::endl; + return (uint8_t)0; + } + } + else + GetOpReturnData(scriptPubKey, vopretStripped); + + return _DecodeHeirOpRet(vopretStripped, ownerPubkey, heirPubkey, inactivityTime, heirName, fundingTxidInOpret, hasHeirSpendingBegun, noLogging); + +} + +// overload to decode opret in fundingtxid: +uint8_t DecodeHeirEitherOpRet(CScript scriptPubKey, uint256 &tokenid, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, bool noLogging) { + uint256 dummyFundingTxidInOpret; + uint8_t dummyHasHeirSpendingBegun; + + return _DecodeHeirEitherOpRet(scriptPubKey, tokenid, ownerPubkey, heirPubkey, inactivityTime, heirName, dummyFundingTxidInOpret, dummyHasHeirSpendingBegun, noLogging); +} + +// overload to decode opret in A and C heir tx: +uint8_t DecodeHeirEitherOpRet(CScript scriptPubKey, uint256 &tokenid, uint256 &fundingTxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging) { + CPubKey dummyOwnerPubkey, dummyHeirPubkey; + int64_t dummyInactivityTime; + std::string dummyHeirName; + + return _DecodeHeirEitherOpRet(scriptPubKey, tokenid, dummyOwnerPubkey, dummyHeirPubkey, dummyInactivityTime, dummyHeirName, fundingTxidInOpret, hasHeirSpendingBegun, noLogging); +} + +// check if pubkey is in vins +void CheckVinPubkey(std::vector vins, CPubKey pubkey, bool &hasPubkey, bool &hasOtherPubkey) { + + hasPubkey = false; + hasOtherPubkey = false; + + for (auto vin : vins) { + CPubKey vinPubkey = check_signing_pubkey(vin.scriptSig); + if (vinPubkey.IsValid()) { + if (vinPubkey == pubkey) + hasPubkey = true; + if (vinPubkey != pubkey) + hasOtherPubkey = true; + } + } +} + +/** + * find the latest funding tx: it may be the first F tx or one of A or C tx's + * Note: this function is also called from validation code (use non-locking calls) + */ +uint256 _FindLatestFundingTx(uint256 fundingtxid, uint8_t& funcId, uint256 &tokenid, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, CScript& fundingOpretScript, uint8_t &hasHeirSpendingBegun) +{ + CTransaction fundingtx; + uint256 hashBlock; + const bool allowSlow = false; + + //char markeraddr[64]; + //CCtxidaddr(markeraddr, fundingtxid); + //SetCCunspents(unspentOutputs, markeraddr); + + hasHeirSpendingBegun = 0; + funcId = 0; + + // get initial funding tx and set it as initial lasttx: + if (myGetTransaction(fundingtxid, fundingtx, hashBlock) && fundingtx.vout.size()) { + + CScript heirScript = (fundingtx.vout.size() > 0) ? fundingtx.vout[fundingtx.vout.size() - 1].scriptPubKey : CScript(); + uint8_t funcId = DecodeHeirEitherOpRet(heirScript, tokenid, ownerPubkey, heirPubkey, inactivityTime, heirName, true); + if (funcId != 0) { + // found at least funding tx! + //std::cerr << "FindLatestFundingTx() lasttx currently is fundingtx, txid=" << fundingtxid.GetHex() << " opreturn type=" << (char)funcId << '\n'; + fundingOpretScript = fundingtx.vout[fundingtx.vout.size() - 1].scriptPubKey; + } else { + std::cerr << "FindLatestFundingTx() could not decode opreturn for fundingtxid=" << fundingtxid.GetHex() << '\n'; + return zeroid; + } + } else { + std::cerr << "FindLatestFundingTx() could not find funding tx for fundingtxid=" << fundingtxid.GetHex() << '\n'; + return zeroid; + } + + // TODO: correct cc addr: + std::vector> unspentOutputs; + struct CCcontract_info *cp, C; + cp = CCinit(&C, EVAL_HEIR); + char coinaddr[64]; + GetCCaddress1of2(cp, coinaddr, ownerPubkey, heirPubkey); // get the address of cryptocondition '1 of 2 pubkeys' + + SetCCunspents(unspentOutputs, coinaddr); // get vector with tx's with unspent vouts of 1of2pubkey address: + //std::cerr << "FindLatestFundingTx() using 1of2address=" << coinaddr << " unspentOutputs.size()=" << unspentOutputs.size() << '\n'; + + int32_t maxBlockHeight = 0; // max block height + uint256 latesttxid = fundingtxid; + + // try to find the last funding or spending tx by checking fundingtxid in 'opreturn': + for (std::vector>::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { + CTransaction regtx; + uint256 hash; + + uint256 txid = it->first.txhash; + //std::cerr << "FindLatestFundingTx() checking unspents for txid=" << txid.GetHex() << '\n'; + + int32_t blockHeight = (int32_t)it->second.blockHeight; + + //NOTE: maybe called from validation code: + if (myGetTransaction(txid, regtx, hash)) { + //std::cerr << "FindLatestFundingTx() found tx for txid=" << txid.GetHex() << " blockHeight=" << blockHeight << " maxBlockHeight=" << maxBlockHeight << '\n'; + uint256 fundingTxidInOpret; + uint256 tokenidInOpret; // not to contaminate the tokenid from the params! + uint8_t tmpFuncId; + uint8_t hasHeirSpendingBegunInOpret; + + CScript heirScript = (regtx.vout.size() > 0) ? regtx.vout[regtx.vout.size() - 1].scriptPubKey : CScript(); + tmpFuncId = DecodeHeirEitherOpRet(heirScript, tokenidInOpret, fundingTxidInOpret, hasHeirSpendingBegunInOpret, true); + if (tmpFuncId != 0 && fundingtxid == fundingTxidInOpret && (tokenid == zeroid || tokenid == tokenidInOpret)) { // check tokenid also + + if (blockHeight > maxBlockHeight) { + + // check owner pubkey in vins + bool isOwner = false; + bool isNonOwner = false; + + CheckVinPubkey(regtx.vin, ownerPubkey, isOwner, isNonOwner); + + // we ignore 'donations' tx (with non-owner inputs) for calculating if heir is allowed to spend: + if (isOwner && !isNonOwner) { + hasHeirSpendingBegun = hasHeirSpendingBegunInOpret; + maxBlockHeight = blockHeight; + latesttxid = txid; + funcId = tmpFuncId; + } + + //std::cerr << "FindLatestFundingTx() txid=" << latesttxid.GetHex() << " at blockHeight=" << maxBlockHeight + // << " opreturn type=" << (char)(funcId ? funcId : ' ') << " hasHeirSpendingBegun=" << (int)hasHeirSpendingBegun << " - set as current lasttxid" << '\n'; + } + } + } + } + + return latesttxid; +} + +// overload for validation code +uint256 FindLatestFundingTx(uint256 fundingtxid, uint256 &tokenid, CScript& opRetScript, uint8_t &hasHeirSpendingBegun) +{ + uint8_t funcId; + CPubKey ownerPubkey; + CPubKey heirPubkey; + int64_t inactivityTime; + std::string heirName; + + return _FindLatestFundingTx(fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTime, heirName, opRetScript, hasHeirSpendingBegun); +} + +// overload for transaction creation code +uint256 FindLatestFundingTx(uint256 fundingtxid, uint8_t& funcId, uint256 &tokenid, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, uint8_t &hasHeirSpendingBegun) +{ + CScript opRetScript; + + return _FindLatestFundingTx(fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTime, heirName, opRetScript, hasHeirSpendingBegun); +} + +// add inputs of 1 of 2 cc address +template int64_t Add1of2AddressInputs(struct CCcontract_info* cp, uint256 fundingtxid, CMutableTransaction& mtx, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t total, int32_t maxinputs) +{ + // TODO: add threshold check + int64_t nValue, voutValue, totalinputs = 0; + CTransaction heirtx; + int32_t n = 0; + std::vector> unspentOutputs; + + char coinaddr[64]; + Helper::GetCoinsOrTokensCCaddress1of2(coinaddr, ownerPubkey, heirPubkey); // get address of cryptocondition '1 of 2 pubkeys' + SetCCunspents(unspentOutputs, coinaddr); + + // char markeraddr[64]; + // CCtxidaddr(markeraddr, fundingtxid); + // SetCCunspents(unspentOutputs, markeraddr); + + std::cerr << "Add1of2AddressInputs() using 1of2addr=" << coinaddr << " unspentOutputs.size()=" << unspentOutputs.size() << std::endl; + + for (std::vector>::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { + uint256 txid = it->first.txhash; + uint256 hashBlock; + int32_t voutIndex = (int32_t)it->first.index; // no need to prevent dup - if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) - { - if ( (nValue= IsHeirvout(cp,vintx,vout)) > 1000000 && myIsutxo_spentinmempool(txid,vout) == 0 ) + // dimxy: maybe it is good to put tx's in cache? + + std::cerr << "Add1of2AddressInputs() txid=" << txid.GetHex() << std::endl; + + if (GetTransaction(txid, heirtx, hashBlock, false) != 0) { + uint256 tokenid; + uint256 fundingTxidInOpret; + uint8_t hasHeirSpendingBegunDummy; + + CScript heirScript = (heirtx.vout.size() > 0) ? heirtx.vout[heirtx.vout.size() - 1].scriptPubKey : CScript(); // check boundary + uint8_t funcId = DecodeHeirEitherOpRet(heirScript, tokenid, fundingTxidInOpret, hasHeirSpendingBegunDummy, false); + + if ((txid == fundingtxid || fundingTxidInOpret == fundingtxid) && + funcId != 0 && + isMyFuncId(funcId) && + (typeid(Helper) != typeid(TokenHelper) || IsTokensvout(true, true, cp, nullptr, heirtx, voutIndex, tokenid) > 0) && // token validation logic + //(voutValue = IsHeirFundingVout(cp, heirtx, voutIndex, ownerPubkey, heirPubkey)) > 0 && // heir contract vout validation logic - not used since we moved to 2-eval vouts + !myIsutxo_spentinmempool(txid, voutIndex)) { - if ( total != 0 && maxinputs != 0 ) - mtx.vin.push_back(CTxIn(txid,vout,CScript())); + std::cerr << "Add1of2AddressInputs() satoshis=" << it->second.satoshis << std::endl; + if (total != 0 && maxinputs != 0) + mtx.vin.push_back(CTxIn(txid, voutIndex, CScript())); nValue = it->second.satoshis; totalinputs += nValue; n++; - if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) + if ((total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs)) break; } } } - return(totalinputs); + return totalinputs; } -std::string HeirGet(uint64_t txfee,int64_t nValue) +/** + * enumerate all tx's sending to CCHeir 1of2address and calc total lifetime funds + */ +template int64_t LifetimeHeirContractFunds(struct CCcontract_info* cp, uint256 fundingtxid, CPubKey ownerPubkey, CPubKey heirPubkey) { - CMutableTransaction tmpmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk,Heirpk; int64_t inputs,CCchange=0; struct CCcontract_info *cp,C; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash; - cp = CCinit(&C,EVAL_HEIR); - if ( txfee == 0 ) - txfee = 10000; - Heirpk = GetUnspendable(cp,0); - mypk = pubkey2pk(Mypubkey()); - if ( (inputs= AddHeirInputs(cp,mtx,Heirpk,nValue+txfee,60)) > 0 ) - { - if ( inputs > nValue ) - CCchange = (inputs - nValue - txfee); - if ( CCchange != 0 ) - mtx.vout.push_back(MakeCC1vout(EVAL_HEIR,CCchange,Heirpk)); - mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - fprintf(stderr,"start at %u\n",(uint32_t)time(NULL)); - j = rand() & 0xfffffff; - for (i=0; i<1000000; i++,j++) - { - tmpmtx = mtx; - rawhex = FinalizeCCTx(-1LL,cp,tmpmtx,mypk,txfee,CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'G' << j)); - if ( (len= (int32_t)rawhex.size()) > 0 && len < 65536 ) + char coinaddr[64]; + Helper::GetCoinsOrTokensCCaddress1of2(coinaddr, ownerPubkey, heirPubkey); // get the address of cryptocondition '1 of 2 pubkeys' + + std::vector> addressIndexes; + SetCCtxids(addressIndexes, coinaddr); + + //fprintf(stderr,"LifetimeHeirContractFunds() scan lifetime of %s\n",coinaddr); + int64_t total = 0; + for (std::vector>::const_iterator it = addressIndexes.begin(); it != addressIndexes.end(); it++) { + uint256 hashBlock; + uint256 txid = it->first.txhash; + CTransaction heirtx; + + // TODO: check all funding tx should contain unspendable markers + if (GetTransaction(txid, heirtx, hashBlock, false) && heirtx.vout.size() > 0) { + uint256 tokenid; + uint256 fundingTxidInOpret; + uint8_t hasHeirSpendingBegunDummy; + const int32_t ivout = 0; + + CScript heirScript = (heirtx.vout.size() > 0) ? heirtx.vout[heirtx.vout.size() - 1].scriptPubKey : CScript(); // check boundary + uint8_t funcId = DecodeHeirEitherOpRet(heirScript, tokenid, fundingTxidInOpret, hasHeirSpendingBegunDummy, false); + + //std::cerr << "LifetimeHeirContractFunds() found tx=" << txid.GetHex() << " vout[0].nValue=" << subtx.vout[ccVoutIdx].nValue << " opreturn=" << (char)funcId << '\n'; + + if (funcId != 0 && + (txid == fundingtxid || fundingTxidInOpret == fundingtxid) && + isMyFuncId(funcId) && !isSpendingTx(funcId) && + (typeid(Helper) != typeid(TokenHelper) || IsTokensvout(true, true, cp, nullptr, heirtx, ivout, tokenid) > 0) && + !myIsutxo_spentinmempool(txid, ivout)) // exclude tx in mempool { - len >>= 1; - decode_hex(buf,len,(char *)rawhex.c_str()); - hash = bits256_doublesha256(0,buf,len); - if ( (hash.bytes[0] & 0xff) == 0 && (hash.bytes[31] & 0xff) == 0 ) - { - fprintf(stderr,"found valid txid after %d iterations %u\n",i,(uint32_t)time(NULL)); - return(rawhex); - } - //fprintf(stderr,"%02x%02x ",hash.bytes[0],hash.bytes[31]); + total += it->second; // dont do this: tx.vout[ivout].nValue; // in vin[0] always is the pay to 1of2 addr (funding or change) + //std::cerr << "LifetimeHeirContractFunds() added tx=" << txid.GetHex() << " it->second=" << it->second << " vout[0].nValue=" << tx.vout[ivout].nValue << " opreturn=" << (char)funcId << '\n'; } } - fprintf(stderr,"couldnt generate valid txid %u\n",(uint32_t)time(NULL)); - return(""); - } else fprintf(stderr,"cant find Heir inputs\n"); - return(""); -} - -std::string HeirFund(uint64_t txfee,int64_t funds) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk,Heirpk; CScript opret; struct CCcontract_info *cp,C; - cp = CCinit(&C,EVAL_HEIR); - if ( txfee == 0 ) - txfee = 10000; - mypk = pubkey2pk(Mypubkey()); - Heirpk = GetUnspendable(cp,0); - if ( AddNormalinputs(mtx,mypk,funds+txfee,64) > 0 ) - { - mtx.vout.push_back(MakeCC1vout(EVAL_HEIR,funds,Heirpk)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret)); } - return(""); + return (total); } -UniValue HeirInfo() +/* rpc functions' implementation: */ + +/** + * heirfund rpc call implementation + * creates tx for initial funds deposit on cryptocondition address which locks funds for spending by either of address. + * and also for setting spending plan for the funds' owner and heir + * @return fundingtxid handle for subsequent references to this heir funding plan + */ +template UniValue _HeirFund(int64_t txfee, int64_t amount, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid) { + UniValue result(UniValue::VOBJ); CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - UniValue result(UniValue::VOBJ); char numstr[64]; - CPubKey Heirpk; struct CCcontract_info *cp,C; int64_t funding; - result.push_back(Pair("result","success")); - result.push_back(Pair("name","Heir")); - cp = CCinit(&C,EVAL_HEIR); - Heirpk = GetUnspendable(cp,0); - funding = AddHeirInputs(cp,mtx,Heirpk,0,0); - sprintf(numstr,"%.8f",(double)funding/COIN); - result.push_back(Pair("funding",numstr)); - return(result); + struct CCcontract_info *cp, C; + + cp = CCinit(&C, Helper::getMyEval()); + if (txfee == 0) + txfee = 10000; + + int64_t markerfee = 10000; + + //std::cerr << "HeirFund() amount=" << amount << " txfee=" << txfee << " heirPubkey IsValid()=" << heirPubkey.IsValid() << " inactivityTime(sec)=" << inactivityTimeSec << " tokenid=" << tokenid.GetHex() << std::endl; + + if (!heirPubkey.IsValid()) { + std::cerr << "HeirFund() heirPubkey is not valid!" << std::endl; + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "invalid heir pubkey")); + } + + CPubKey myPubkey = pubkey2pk(Mypubkey()); + + if (AddNormalinputs(mtx, myPubkey, markerfee, 3) > 0) { + int64_t inputs, change; + + if ((inputs=Helper::addOwnerInputs(tokenid, mtx, myPubkey, amount, (int32_t)64)) > 0) { + + mtx.vout.push_back(Helper::make1of2Vout(amount, myPubkey, heirPubkey)); + + // add a marker for finding all plans in HeirList() + // TODO: change marker either to cc or normal txidaddr unspendable + struct CCcontract_info *cpHeir, heirC; + cpHeir = CCinit(&heirC, EVAL_HEIR); + CPubKey heirUnspendablePubKey = GetUnspendable(cpHeir, 0); + // mtx.vout.push_back(CTxOut(txfee, CScript() << ParseHex(HexStr(heirUnspendablePubKey)) << OP_CHECKSIG)); <-- bad marker cause it was spendable by anyone + mtx.vout.push_back(MakeCC1vout(EVAL_HEIR, markerfee, heirUnspendablePubKey)); // this marker spending is disabled in the validation code + + // calc and add change vout: + if (inputs > amount) + change = (inputs - amount); // -txfee <-- txfee pays user + + //std::cerr << "HeirFund() inputs=" << inputs << " amount=" << amount << " txfee=" << txfee << " change=" << change << '\n'; + + if (change != 0) { // vout[1] + mtx.vout.push_back(Helper::makeUserVout(change, myPubkey)); + } + + // check owner pubkey in vins + bool hasMypubkey = false; + bool hasNotMypubkey = false; + + CheckVinPubkey(mtx.vin, myPubkey, hasMypubkey, hasNotMypubkey); + + // for initial funding do not allow to sign by non-owner key: + if (hasNotMypubkey) { + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "using non-owner inputs not allowed")); + return result; + } + + // add 1of2 vout validation pubkeys: + std::vector voutTokenPubkeys; + voutTokenPubkeys.push_back(myPubkey); + voutTokenPubkeys.push_back(heirPubkey); + + // add change for txfee and opreturn vouts and sign tx: + std::string rawhextx = FinalizeCCTx(0, cp, mtx, myPubkey, txfee, + Helper::makeCreateOpRet(tokenid, voutTokenPubkeys, myPubkey, heirPubkey, inactivityTimeSec, heirName)); + if (!rawhextx.empty()) { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hextx", rawhextx)); + } + else { + std::cerr << "HeirAdd error in FinalizeCCtx" << std::endl; + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "sign error")); + } + } + else { // TODO: need result return unification with heiradd and claim + std::cerr << "HeirFund() could not find owner cc inputs" << std::endl; + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "could not find owner cc inputs")); + } + } + else { + std::cerr << "HeirFund() could not find normal inputs" << std::endl; + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "could not find normal inputs")); + } + return result; +} + +// if no these callers - it could not link +UniValue HeirFundCoinCaller(int64_t txfee, int64_t satoshis, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid){ + return _HeirFund(txfee, satoshis, heirName, heirPubkey, inactivityTimeSec, tokenid); +} + +UniValue HeirFundTokenCaller(int64_t txfee, int64_t satoshis, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid) { + return _HeirFund(txfee, satoshis, heirName, heirPubkey, inactivityTimeSec, tokenid); +} + +/** + * heiradd rpc call implementation + * creates tx to add more funds to cryptocondition address for spending by either funds' owner or heir + * @return result object with raw tx or error text + */ +template UniValue _HeirAdd(uint256 fundingtxid, int64_t txfee, int64_t amount, uint256 latesttxid, uint8_t funcId, uint256 tokenid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, uint8_t hasHeirSpendingBegun) +{ + UniValue result(UniValue::VOBJ); + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + int64_t inputs, CCchange = 0; + struct CCcontract_info *cp, C; + std::string rawhex; + + cp = CCinit(&C, Helper::getMyEval()); // for tokens shoud be EVAL_TOKENS to sign it correctly! + + if (txfee == 0) + txfee = 10000; + + int64_t markerfee = 10000; + + CPubKey myPubkey = pubkey2pk(Mypubkey()); + + // check if it is the owner + if (myPubkey != ownerPubkey) { + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "adding funds is only allowed for the owner of this contract")); + return result; + } + + if (AddNormalinputs(mtx, myPubkey, markerfee, 3) > 0) { // some for marker + + int64_t inputs, change; + + if ((inputs = Helper::addOwnerInputs(tokenid, mtx, myPubkey, amount, 64)) > 0) { // TODO: why 64 max inputs? + + // we do not use markers anymore - storing data in opreturn is better + // add marker vout: + /* char markeraddr[64]; + CPubKey markerpubkey = CCtxidaddr(markeraddr, fundingtxid); + mtx.vout.push_back(CTxOut(txfee, CScript() << ParseHex(HexStr(markerpubkey)) << OP_CHECKSIG)); // txfee 1, txfee 2 - for miners + std::cerr << "HeirAdd() adding markeraddr=" << markeraddr << '\n'; */ + + // add cryptocondition to spend this funded amount for either pk + mtx.vout.push_back(Helper::make1of2Vout(amount, ownerPubkey, heirPubkey)); + + char markeraddr[64]; + CPubKey markerPubkey = CCtxidaddr(markeraddr, fundingtxid); + mtx.vout.push_back(CTxOut(markerfee, CScript() << ParseHex(HexStr(markerPubkey)) << OP_CHECKSIG)); // marker to prevent archiving of the funds add vouts + + if (inputs > amount) + change = (inputs - amount); // -txfee <-- txfee pays user + + //std::cerr << "HeirAdd() inputs=" << inputs << " amount=" << amount << " txfee=" << txfee << " change=" << change << '\n'; + + if (change != 0) { // vout[1] + mtx.vout.push_back(Helper::makeUserVout(change, myPubkey)); + } + + // check owner pubkey in vins + bool hasMypubkey = false; + bool hasNotMypubkey = false; + + CheckVinPubkey(mtx.vin, myPubkey, hasMypubkey, hasNotMypubkey); + + // for additional funding do not allow to sign by both owner and non-owner keys (is this a donation or not?): + if (hasMypubkey && hasNotMypubkey) { + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "using both owner and non-owner inputs is not allowed")); + return result; + } + + // warn the user he's making a donation if this is all non-owner keys: + if (hasNotMypubkey) { + result.push_back(Pair("result", "warning")); + result.push_back(Pair("warning", "you are about to make a donation to heir fund")); + } + else { + result.push_back(Pair("result", "success")); + } + + // add 1of2 vout validation pubkeys - needed only for tokens: + std::vector voutTokenPubkeys; + voutTokenPubkeys.push_back(ownerPubkey); + voutTokenPubkeys.push_back(heirPubkey); + + // add opreturn 'A' and sign tx: // this txfee ignored + std::string rawhextx = (FinalizeCCTx(0, cp, mtx, myPubkey, txfee, + Helper::makeAddOpRet(tokenid, voutTokenPubkeys, fundingtxid, hasHeirSpendingBegun))); + + if (!rawhextx.empty()) { + result.push_back(Pair("hextx", rawhextx)); + } + else { + std::cerr << "HeirAdd error in FinalizeCCtx" << std::endl; + result.clear(); + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "sign error")); + } + + } + else { + std::cerr << "HeirAdd cannot find owner cc inputs" << std::endl; + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "can't find owner cc inputs")); + } + } + else { + std::cerr << "HeirAdd cannot find normal inputs for tx fee" << std::endl; + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "can't find normal inputs for tx fee")); + } + + return result; +} + + +UniValue HeirAddCaller(uint256 fundingtxid, int64_t txfee, std::string strAmount) { + + CPubKey ownerPubkey, heirPubkey; + int64_t inactivityTimeSec; + + uint256 latesttxid, tokenid = zeroid; + uint8_t funcId; + std::string heirName; + uint8_t hasHeirSpendingBegun = 0; + + if ((latesttxid = FindLatestFundingTx(fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun)) != zeroid) { + if (tokenid == zeroid) { + int64_t amount = (int64_t)(atof(strAmount.c_str()) * COIN); + if (amount <= 0) { + UniValue result(UniValue::VOBJ); + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "invalid amount")); + return result; + } + + return _HeirAdd(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun); + } + else { + int64_t amount = atoll(strAmount.c_str()); + if (amount <= 0) { + UniValue result(UniValue::VOBJ); + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "invalid amount")); + return result; + } + return _HeirAdd(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun); + } + } + else { + UniValue result(UniValue::VOBJ); + + fprintf(stderr, "HeirAdd() can't find any heir CC funding tx's\n"); + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "can't find any heir CC funding transactions")); + return result; + } +} + + +/** + * heirclaim rpc call implementation + * creates tx to spend funds from cryptocondition address by either funds' owner or heir + * @return result object with raw tx or error text + */ +template UniValue _HeirClaim(uint256 fundingtxid, int64_t txfee, int64_t amount, uint256 latesttxid, uint8_t funcId, uint256 tokenid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, uint8_t hasHeirSpendingBegun) +{ + UniValue result(UniValue::VOBJ); + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CPubKey myPubkey; + int64_t inputs, change = 0; + struct CCcontract_info *cp, C; + + cp = CCinit(&C, EVAL_HEIR); + if (txfee == 0) + txfee = 10000; + + int32_t numblocks; + uint64_t durationSec = 0; + + // we do not need to find duration if spending already has begun + if (!hasHeirSpendingBegun) { + durationSec = CCduration(numblocks, latesttxid); + std::cerr << "HeirClaim() duration=" << durationSec << " inactivityTime=" << inactivityTimeSec << " numblocks=" << numblocks << std::endl; + } + + // spending is allowed if there is already spending tx or inactivity time + //bool isAllowedToHeir = (funcId == 'C' || durationSec > inactivityTimeSec) ? true : false; + bool isAllowedToHeir = (hasHeirSpendingBegun || durationSec > inactivityTimeSec) ? true : false; + myPubkey = pubkey2pk(Mypubkey()); + + // if it is the heir, check if spending not allowed to heir yet + if (myPubkey == heirPubkey && !isAllowedToHeir) { + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "spending is not allowed yet for the heir")); + return result; + } + + // we do not use markers any more: + // we allow owner to spend funds at any time: + // if it is the owner, check if spending already allowed to heir + /* if (myPubkey == ownerPubkey && isAllowedToHeir) { + result.push_back(Pair("result", "spending is not already allowed for the owner")); + return result; + } */ + + // add spending txfee from the calling user + if (AddNormalinputs(mtx, myPubkey, txfee, 3) > 0) { + + // add spending from cc 1of2 address + if ((inputs = Add1of2AddressInputs(cp, fundingtxid, mtx, ownerPubkey, heirPubkey, amount, 60)) >= amount) // TODO: why only 60 inputs? + { + /*if (inputs < amount) { + std::cerr << "HeirClaim() cant find enough HeirCC 1of2 inputs, found=" << inputs << " required=" << amount << std::endl; + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "can't find heir CC funding")); + + return result; + }*/ + + // add vout with amount to claiming address + mtx.vout.push_back(Helper::makeUserVout(amount, myPubkey)); // vout[0] + + // calc and add change vout: + if (inputs > amount) + change = (inputs - amount); // -txfee <-- txfee pays user + + //std::cerr << "HeirClaim() inputs=" << inputs << " amount=" << amount << " txfee=" << txfee << " change=" << change << '\n'; + + // change to 1of2 funding addr: + if (change != 0) { // vout[1] + mtx.vout.push_back(Helper::make1of2Vout(change, ownerPubkey, heirPubkey)); // using always pubkeys from OP_RETURN in order to not mixing them up! + } + + // add marker vout: + /*char markeraddr[64]; + CPubKey markerpubkey = CCtxidaddr(markeraddr, fundingtxid); + // NOTE: amount = 0 is not working: causes error code: -26, error message : 64 : dust + mtx.vout.push_back(CTxOut(txfee, CScript() << ParseHex(HexStr(markerpubkey)) << OP_CHECKSIG)); // txfee 1, txfee 2 - for miners + std::cerr << "HeirClaim() adding markeraddr=" << markeraddr << '\n'; */ + + // get address of 1of2 cond + char coinaddr[64]; + Helper::GetCoinsOrTokensCCaddress1of2(coinaddr, ownerPubkey, heirPubkey); + + // retrieve priv key addresses for FinalizeCCtx: + uint8_t myprivkey[32]; + Myprivkey(myprivkey); + + // set pubkeys for finding 1of2 cc in FinalizeCCtx to sign it: + Helper::CCaddrCoinsOrTokens1of2set(cp, ownerPubkey, heirPubkey, coinaddr); + + // add 1of2 vout validation pubkeys (this is for tokens): + std::vector voutTokenPubkeys; + voutTokenPubkeys.push_back(ownerPubkey); + voutTokenPubkeys.push_back(heirPubkey); + + // add opreturn 'C' and sign tx: // this txfee will be ignored + std::string rawhextx = FinalizeCCTx(0, cp, mtx, myPubkey, txfee, + Helper::makeClaimOpRet(tokenid, voutTokenPubkeys, fundingtxid, (myPubkey == heirPubkey) ? 1 : hasHeirSpendingBegun)); // forward isHeirSpending to the next latest tx + + if (!rawhextx.empty()) { + result.push_back(Pair("result", "success")); + result.push_back(Pair("hextx", rawhextx)); + } + else { + std::cerr << "HeirAdd error in FinalizeCCtx" << std::endl; + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "sign error")); + } + + } else { + fprintf(stderr, "HeirClaim() cant find Heir CC inputs\n"); + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "can't find heir CC funding")); + } + } else { + fprintf(stderr, "HeirClaim() cant find sufficient user inputs for tx fee\n"); + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "can't find sufficient user inputs to pay transaction fee")); + } + + + return result; +} + +UniValue HeirClaimCaller(uint256 fundingtxid, int64_t txfee, std::string strAmount) { + + CPubKey ownerPubkey, heirPubkey; + int64_t inactivityTimeSec; + + uint256 latesttxid, tokenid = zeroid; + uint8_t funcId; + std::string heirName; + uint8_t hasHeirSpendingBegun = 0; + + if ((latesttxid = FindLatestFundingTx(fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun)) != zeroid) { + if (tokenid == zeroid) { + int64_t amount = (int64_t)(atof(strAmount.c_str()) * COIN); + if (amount < 0) { + UniValue result(UniValue::VOBJ); + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "invalid amount")); + return result; + } + return _HeirClaim(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun); + } + else { + int64_t amount = atoll(strAmount.c_str()); + if (amount <= 0) { + UniValue result(UniValue::VOBJ); + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "invalid amount")); + return result; + } + return _HeirClaim(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun); + } + + } + else { + UniValue result(UniValue::VOBJ); + + fprintf(stderr, "HeirClaim() can't find any heir CC funding tx's\n"); + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "can't find any heir CC funding transactions")); + return result; + } +} + + +/** + * heirinfo rpc call implementation + * returns some information about heir CC contract plan by a handle of initial fundingtxid: + * plan name, owner and heir pubkeys, funds deposited and available, flag if spending is enabled for the heir + * @return heir info data + */ +UniValue HeirInfo(uint256 fundingtxid) +{ + UniValue result(UniValue::VOBJ); + + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + CTransaction fundingtx; + uint256 hashBlock; + const bool allowSlow = false; + + //char markeraddr[64]; + //CCtxidaddr(markeraddr, fundingtxid); + //SetCCunspents(unspentOutputs, markeraddr); + + // get initial funding tx and set it as initial lasttx: + if (myGetTransaction(fundingtxid, fundingtx, hashBlock) && fundingtx.vout.size()) { + + CPubKey ownerPubkey, heirPubkey; + uint256 dummyTokenid, tokenid = zeroid; // important to clear tokenid + std::string heirName; + int64_t inactivityTimeSec; + const bool noLogging = false; + uint8_t funcId; + + /*CScript opret = fundingtx.vout.size() > 0 ? fundingtx.vout[fundingtx.vout.size() - 1].scriptPubKey : CScript(); + uint8_t funcId = DecodeHeirEitherOpRet(opret, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, true); + if (funcId == 0) { + std::cerr << "HeirInfo() this fundingtx is incorrect" << std::endl; + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "initial tx F not found")); + return result; + }*/ + + struct CCcontract_info *cp, C; + cp = CCinit(&C, EVAL_HEIR); + + uint8_t hasHeirSpendingBegun = 0; + + uint256 latestFundingTxid = FindLatestFundingTx(fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun); + + if (latestFundingTxid != zeroid) { + int32_t numblocks; + uint64_t durationSec = 0; + + //std::cerr << "HeirInfo() latesttxid=" << latestFundingTxid.GetHex() << '\n'; + + std::ostringstream stream; + std::string msg; + + //sleep(10); + + result.push_back(Pair("fundingtxid", fundingtxid.GetHex())); + result.push_back(Pair("name", heirName.c_str())); + + if (tokenid != zeroid) { // tokens + stream << tokenid.GetHex(); + msg = "tokenid"; + result.push_back(Pair(msg, stream.str().c_str())); + stream.str(""); + stream.clear(); + } + + char hexbuf[67]; + stream << pubkey33_str(hexbuf, (uint8_t*)ownerPubkey.begin()); + result.push_back(Pair("owner", stream.str().c_str())); + stream.str(""); + stream.clear(); + + stream << pubkey33_str(hexbuf, (uint8_t*)heirPubkey.begin()); + result.push_back(Pair("heir", stream.str().c_str())); + stream.str(""); + stream.clear(); + + int64_t total; + if (tokenid == zeroid) + total = LifetimeHeirContractFunds(cp, fundingtxid, ownerPubkey, heirPubkey); + else + total = LifetimeHeirContractFunds(cp, fundingtxid, ownerPubkey, heirPubkey); + + if (tokenid == zeroid) { + msg = "funding total in coins"; + stream << std::fixed << std::setprecision(8) << (double)total / COIN; + } + else { + msg = "funding total in tokens"; + stream << total; + } + result.push_back(Pair(msg, stream.str().c_str())); + stream.str(""); + stream.clear(); + + int64_t inputs; + if (tokenid == zeroid) + inputs = Add1of2AddressInputs(cp, fundingtxid, mtx, ownerPubkey, heirPubkey, 0, 60); //NOTE: amount = 0 means all unspent inputs + else + inputs = Add1of2AddressInputs(cp, fundingtxid, mtx, ownerPubkey, heirPubkey, 0, 60); + + if (tokenid == zeroid) { + msg = "funding available in coins"; + stream << std::fixed << std::setprecision(8) << (double)inputs / COIN; + } + else { + msg = "funding available in tokens"; + stream << inputs; + } + result.push_back(Pair(msg, stream.str().c_str())); + stream.str(""); + stream.clear(); + + if (tokenid != zeroid) { + int64_t ownerInputs = TokenHelper::addOwnerInputs(tokenid, mtx, ownerPubkey, 0, (int32_t)64); + stream << ownerInputs; + msg = "owner funding available in tokens"; + result.push_back(Pair(msg, stream.str().c_str())); + stream.str(""); + stream.clear(); + } + + stream << inactivityTimeSec; + result.push_back(Pair("inactivity time setting, sec", stream.str().c_str())); + stream.str(""); + stream.clear(); + + if (!hasHeirSpendingBegun) { // we do not need find duration if the spending already has begun + durationSec = CCduration(numblocks, latestFundingTxid); + std::cerr << "HeirInfo() duration (sec)=" << durationSec << " inactivityTime (sec)=" << inactivityTimeSec << " numblocks=" << numblocks << '\n'; + } + + stream << std::boolalpha << (hasHeirSpendingBegun || durationSec > inactivityTimeSec); + result.push_back(Pair("spending allowed for the heir", stream.str().c_str())); + stream.str(""); + stream.clear(); + + // adding owner current inactivity time: + if (!hasHeirSpendingBegun && durationSec <= inactivityTimeSec) { + stream << durationSec; + result.push_back(Pair("owner inactivity time, sec", stream.str().c_str())); + stream.str(""); + stream.clear(); + } + + result.push_back(Pair("result", "success")); + } + else { + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "could not find heir cc plan for this txid")); + } + } + else { + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "could not find heir cc plan for this txid (no initial tx)")); + } + return (result); +} + +/** + * heirlist rpc call implementation + * @return list of heir plan handles (fundingtxid) + */ + +void _HeirList(struct CCcontract_info *cp, UniValue &result) +{ + std::vector> unspentOutputs; + char markeraddr[64]; + + GetCCaddress(cp, markeraddr, GetUnspendable(cp, NULL)); + SetCCunspents(unspentOutputs, markeraddr); + + //std::cerr << "HeirList() finding heir marker from unspendable addr=" << markeraddr << " unspentOutputs.size()=" << unspentOutputs.size() << '\n'; + + // TODO: move marker to special cc addr to prevent checking all tokens + for (std::vector>::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) { + uint256 hashBlock; + uint256 txid = it->first.txhash; + uint256 tokenid; + int32_t vout = (int32_t)it->first.index; + + //std::cerr << "HeirList() checking txid=" << txid.GetHex() << " vout=" << vout << '\n'; + + CTransaction fundingtx; + if (GetTransaction(txid, fundingtx, hashBlock, false)) { + CPubKey ownerPubkey, heirPubkey; + std::string heirName; + int64_t inactivityTimeSec; + const bool noLogging = true; + uint256 tokenid; + + CScript opret = (fundingtx.vout.size() > 0) ? fundingtx.vout[fundingtx.vout.size() - 1].scriptPubKey : CScript(); + uint8_t funcId = DecodeHeirEitherOpRet(opret, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, true); + + // note: if it is not Heir token funcId would be equal to 0 + if (funcId == 'F') { + //result.push_back(Pair("fundingtxid kind name", txid.GetHex() + std::string(" ") + (typeid(Helper) == typeid(TokenHelper) ? std::string("token") : std::string("coin")) + std::string(" ") + heirName)); + result.push_back( Pair("fundingtxid", txid.GetHex()) ); + } + else { + std::cerr << "HeirList() this is not the initial F transaction=" << txid.GetHex() << std::endl; + } + } + else { + std::cerr << "HeirList() could not load transaction=" << txid.GetHex() << std::endl; + } + } +} + + +UniValue HeirList() +{ + UniValue result(UniValue::VOBJ); + result.push_back(Pair("result", "success")); + + struct CCcontract_info *cpHeir, *cpTokens, heirC, tokenC; // NOTE we must use a separate 'C' structure for each CCinit! + + cpHeir = CCinit(&heirC, EVAL_HEIR); + //cpTokens = CCinit(&tokenC, EVAL_TOKENS); + + _HeirList(cpHeir, result); + //_HeirList(cpTokens, result); not used anymore + + return result; } diff --git a/src/cc/heir_validate.h b/src/cc/heir_validate.h new file mode 100644 index 000000000..df58e3bf1 --- /dev/null +++ b/src/cc/heir_validate.h @@ -0,0 +1,667 @@ +#ifndef HEIR_VALIDATE_H +#define HEIR_VALIDATE_H + +#include "CCinclude.h" +#include "CCHeir.h" + +#define IS_CHARINSTR(c, str) (std::string(str).find((char)(c)) != std::string::npos) + +// makes coin initial tx opret +CScript EncodeHeirCreateOpRet(uint8_t funcid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName); +CScript EncodeHeirOpRet(uint8_t funcid, uint256 fundingtxid, uint8_t isHeirSpendingBegan); + +uint256 FindLatestFundingTx(uint256 fundingtxid, uint256 &tokenid, CScript& opRetScript, uint8_t &isHeirSpendingBegan); +//uint8_t DecodeHeirOpRet(CScript scriptPubKey, uint256& fundingtxid, uint8_t &isHeirSpendingBegan, bool noLogging = false); +//uint8_t DecodeHeirOpRet(CScript scriptPubKey, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, bool noLogging = false); +uint8_t DecodeHeirEitherOpRet(CScript scriptPubKey, uint256 &tokenid, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, bool noLogging = false); +uint8_t DecodeHeirEitherOpRet(CScript scriptPubKey, uint256 &tokenid, uint256 &fundingTxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging = false); + +inline static bool isMyFuncId(uint8_t funcid) { return IS_CHARINSTR(funcid, "FAC"); } +inline static bool isSpendingTx(uint8_t funcid) { return (funcid == 'C'); } + +// helper class to allow polymorphic behaviour for HeirXXX() functions in case of coins +class CoinHelper { +public: + + static uint8_t getMyEval() { return EVAL_HEIR; } + static int64_t addOwnerInputs(uint256 dummyid, CMutableTransaction& mtx, CPubKey ownerPubkey, int64_t total, int32_t maxinputs) { + return AddNormalinputs(mtx, ownerPubkey, total, maxinputs); + } + + static CScript makeCreateOpRet(uint256 dummyid, std::vector dummyPubkeys, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName) { + return EncodeHeirCreateOpRet((uint8_t)'F', ownerPubkey, heirPubkey, inactivityTimeSec, heirName); + } + static CScript makeAddOpRet(uint256 dummyid, std::vector dummyPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan) { + return EncodeHeirOpRet((uint8_t)'A', fundingtxid, isHeirSpendingBegan); + } + static CScript makeClaimOpRet(uint256 dummyid, std::vector dummyPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan) { + return EncodeHeirOpRet((uint8_t)'C', fundingtxid, isHeirSpendingBegan); + } + static CTxOut make1of2Vout(int64_t amount, CPubKey ownerPubkey, CPubKey heirPubkey) { + return MakeCC1of2vout(EVAL_HEIR, amount, ownerPubkey, heirPubkey); + } + static CTxOut makeUserVout(int64_t amount, CPubKey myPubkey) { + return CTxOut(amount, CScript() << ParseHex(HexStr(myPubkey)) << OP_CHECKSIG); + } + /* static CTxOut makeClaimerVout(int64_t amount, CPubKey myPubkey) { + return CTxOut(amount, CScript() << ParseHex(HexStr(myPubkey)) << OP_CHECKSIG); + } */ + static bool GetCoinsOrTokensCCaddress1of2(char *coinaddr, CPubKey ownerPubkey, CPubKey heirPubkey) { + struct CCcontract_info *cpHeir, heirC; + cpHeir = CCinit(&heirC, EVAL_HEIR); + return GetCCaddress1of2(cpHeir, coinaddr, ownerPubkey, heirPubkey); + } + static void CCaddrCoinsOrTokens1of2set(struct CCcontract_info *cp, CPubKey ownerPubkey, CPubKey heirPubkey, char *coinaddr) { + CCaddr1of2set(cp, ownerPubkey, heirPubkey, coinaddr); + } +}; + +// helper class to allow polymorphic behaviour for HeirXXX() functions in case of tokens +class TokenHelper { +public: + static uint8_t getMyEval() { return EVAL_TOKENS; } + static int64_t addOwnerInputs(uint256 tokenid, CMutableTransaction& mtx, CPubKey ownerPubkey, int64_t total, int32_t maxinputs) { + struct CCcontract_info *cpHeir, heirC; + cpHeir = CCinit(&heirC, EVAL_TOKENS); + return AddTokenCCInputs(cpHeir, mtx, ownerPubkey, tokenid, total, maxinputs); + } + + static CScript makeCreateOpRet(uint256 tokenid, std::vector voutTokenPubkeys, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName) { + return EncodeTokenOpRet(tokenid, voutTokenPubkeys, + EncodeHeirCreateOpRet((uint8_t)'F', ownerPubkey, heirPubkey, inactivityTimeSec, heirName)); + } + static CScript makeAddOpRet(uint256 tokenid, std::vector voutTokenPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan) { + return EncodeTokenOpRet(tokenid, voutTokenPubkeys, + EncodeHeirOpRet((uint8_t)'A', fundingtxid, isHeirSpendingBegan)); + } + static CScript makeClaimOpRet(uint256 tokenid, std::vector voutTokenPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan) { + return EncodeTokenOpRet(tokenid, voutTokenPubkeys, + EncodeHeirOpRet((uint8_t)'C', fundingtxid, isHeirSpendingBegan)); + } + + static CTxOut make1of2Vout(int64_t amount, CPubKey ownerPubkey, CPubKey heirPubkey) { + return MakeTokensCC1of2vout(EVAL_HEIR, amount, ownerPubkey, heirPubkey); + } + static CTxOut makeUserVout(int64_t amount, CPubKey myPubkey) { + return MakeCC1vout(EVAL_TOKENS, amount, myPubkey); // yes EVAL_TOKENS + } + /* static CTxOut makeClaimerVout(int64_t amount, CPubKey myPubkey) { + return MakeCC1vout(EVAL_TOKENS, amount, myPubkey); // yes EVAL_TOKENS + } */ + static bool GetCoinsOrTokensCCaddress1of2(char *coinaddr, CPubKey ownerPubkey, CPubKey heirPubkey) { + struct CCcontract_info *cpHeir, heirC; + cpHeir = CCinit(&heirC, EVAL_HEIR); + return GetTokensCCaddress1of2(cpHeir, coinaddr, ownerPubkey, heirPubkey); + } + + static void CCaddrCoinsOrTokens1of2set(struct CCcontract_info *cp, CPubKey ownerPubkey, CPubKey heirPubkey, char *coinaddr) { + + CCaddrTokens1of2set(cp, ownerPubkey, heirPubkey, coinaddr); + } +}; + + +/** + * Small framework for vins and vouts validation implementing a variation of 'chain of responsibility' pattern: + * It consists of two classes CInputValidationPlan and COutputValidationPlan which both are configured with an array of vectors of validators + * (These validators are derived from the class CValidatorBase). + * + * A example of a validator may verify for a vout if its public key corresponds to the public key which is stored in opreturn. + * Or, vin validator may check if this vin depicts correctly to the CC contract's address. + * + * For validating vins CInputValidator additionally is provided with an instance of a class derived from the CInputIdentifierBase class. + * this identifier class allows to select identical vins (for example, normal vins or cc input vins) and apply validators from the corresponding vector to it. + * Note: CInputValidator treats that at least one identified vin should be present, otherwise it returns eval->invalid() and false. + * + * For validating vouts COutputValidator is configured for each vector of validators with the vout index to which these validators are applied + * (see constructors of both CInputValidator and COutputValidator) + */ + +/** + * base class for all validators + */ +class CValidatorBase +{ +public: + CValidatorBase(CCcontract_info* cp) : m_cp(cp) {} + virtual bool isVinValidator() const = 0; + virtual bool validateVin(CTxIn vin, std::vector prevVout, int32_t prevN, std::string& message) const = 0; + virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const = 0; + +protected: + CCcontract_info * m_cp; +}; + +/** + * Base class for classes which identify vins as normal or cc inputs + */ +class CInputIdentifierBase +{ +public: + CInputIdentifierBase(CCcontract_info* cp) : m_cp(cp) {} + virtual std::string inputName() const = 0; + virtual bool identifyInput(CTxIn vin) const = 0; +protected: + CCcontract_info * m_cp; +}; + +/** + * Encapsulates an array containing rows of validators + * Each row is a vector of validators (zero is possible) for validating vins or prev tx's vouts + * this validation plan is used for validating tx inputs + */ +template +class CInputValidationPlan +{ + using ValidatorsRow = std::vector; + +public: + + // Pushes a row of validators for validating a vin or vout + // @param CInputIdentifierBase* pointer to class-identifier which determines several identical adjacent vins (like in schema "vin.0+: normal inputs") + // @param pargs parameter pack of zero or more pointer to validator objects + // Why pointers? because we store the base class in validators' row and then call its virtual functions + template + void pushValidators(CInputIdentifierBase *identifier, ARGS*... pargs) // validators row passed as variadic arguments CValidatorX *val1, CValidatorY *val2 ... + { + ValidatorsRow vValidators({ (TValidatorBase*)pargs... }); + m_arrayValidators.push_back(std::make_pair(identifier, vValidators)); + } + + // validate tx inputs and corresponding prev tx vouts + bool validate(const CTransaction& tx, Eval* eval) + { + std::string message = ""; + //std::cerr << "CInputValidationPlan::validate() starting vins validation..." << std::endl; + + int32_t ival = 0; + int32_t iv = 0; + int32_t numv = tx.vin.size(); + int32_t numValidators = m_arrayValidators.size(); + + // run over vins: + while (iv < numv && ival < numValidators) { + + int32_t identifiedCount = 0; + CInputIdentifierBase *identifier = m_arrayValidators[ival].first; + // check if this is 'our' input: + while (iv < numv && identifier->identifyInput(tx.vin[iv])) { + + // get prev tx: + CTransaction prevTx, *pPrevTxOrNull = NULL; + uint256 hashBlock; + + if (!eval->GetTxUnconfirmed(tx.vin[iv].prevout.hash, prevTx, hashBlock)) { + std::ostringstream stream; + stream << "can't find vinTx for vin=" << iv << "."; + return eval->Invalid(stream.str().c_str()); + } + pPrevTxOrNull = &prevTx; // TODO: get prev tx only if it required (i.e. if vout validators are present) + + // exec 'validators' from validator row of ival index, for tx.vin[iv] + if (!execValidatorsInRow(&tx, pPrevTxOrNull, iv, ival, message)) { + std::ostringstream stream; + stream << "invalid tx vin[" << iv << "]:" << message; + return eval->Invalid(stream.str().c_str()); // ... if not, return 'invalid' + } + + identifiedCount++; // how many vins we identified + iv++; // advance to the next vin + } + + // CInputValidationPlan treats that there must be at least one identified vin for configured validators' row + // like in 'vin.0: normal input' + if (identifiedCount == 0) { + std::ostringstream stream; + stream << "can't find required vins for " << identifier->inputName() << "."; + return eval->Invalid(stream.str().c_str()); + } + + ival++; // advance to the next validator row + // and it will try the same vin with the new CInputIdentifierBase and validators row + } + + // validation is successful if all validators have been used (i.e. ival = numValidators) + if (ival < numValidators) { + std::cerr << "CInputValidationPlan::validate() incorrect tx" << " ival=" << ival << " numValidators=" << numValidators << std::endl; + return eval->Invalid("incorrect tx structure: not all required vins are present."); + } + + //std::cerr << "CInputValidationPlan::validate() returns with true" << std::endl; + return true; + } + +private: + // Executes validators from the requested row of validators (selected by iValidators) for selected vin or vout (selected by iv) + bool execValidatorsInRow(const CTransaction* pTx, const CTransaction* pPrevTx, int32_t iv, int32_t ival, std::string& refMessage) const + { + // check boundaries: + if (ival < 0 || ival >= m_arrayValidators.size()) { + std::cerr << "CInputValidationPlan::execValidatorsInRow() internal error: incorrect param ival=" << ival << " size=" << m_arrayValidators.size(); + refMessage = "internal error: incorrect param ival index"; + return false; + } + + if (iv < 0 || iv >= pTx->vin.size()) { + std::cerr << "CInputValidationPlan::execValidatorsInRow() internal error: incorrect param iv=" << iv << " size=" << m_arrayValidators.size(); + refMessage = "internal error: incorrect param iv index"; + return false; + } + + // get requested row of validators: + ValidatorsRow vValidators = m_arrayValidators[ival].second; + + //std::cerr << "CInputValidationPlan::execValidatorsInRow() calling validators" << " for vin iv=" << iv << " ival=" << ival << std::endl; + + for (auto v : vValidators) { + bool result; + + if (v->isVinValidator()) + // validate this vin and previous vout: + result = v->validateVin(pTx->vin[iv], pPrevTx->vout, pTx->vin[iv].prevout.n, refMessage); + else + // if it is vout validator pass the previous tx vout: + result = v->validateVout( pPrevTx->vout[pTx->vin[iv].prevout.n], pTx->vin[iv].prevout.n, refMessage); + if (!result) { + return result; + } + } + return true; // validation OK + } + + +private: + //std::map m_arrayValidators; + std::vector< std::pair > m_arrayValidators; + +}; + + +/** + * Encapsulates an array containing rows of validators + * Each row is a vector of validators (zero is possible) for validating vouts + * this validation plan is used for validating tx outputs + */ +template +class COutputValidationPlan +{ + using ValidatorsRow = std::vector; + +public: + // Pushes a row of validators for validating a vout + // @param ivout index to vout to validate + // @param pargs parameter pack of zero or more pointer to validator objects + // Why pointers? because we store base class and call its virtual functions + + template + void pushValidators(int32_t ivout, ARGS*... pargs) // validators row passed as variadic arguments CValidatorX *val1, CValidatorY *val2 ... + { + ValidatorsRow vValidators({ (TValidatorBase*)pargs... }); + m_arrayValidators.push_back(std::make_pair(ivout, vValidators)); + } + + // validate tx outputs + bool validate(const CTransaction& tx, Eval* eval) + { + std::string message = ""; + //std::cerr << "COutputValidationPlan::validateOutputs() starting vouts validation..." << std::endl; + + int32_t ival = 0; + int32_t numVouts = tx.vout.size(); + int32_t numValidators = m_arrayValidators.size(); + + // run over vouts: + while (ival < numValidators) { + + int32_t ivout = m_arrayValidators[ival].first; + if (ivout >= numVouts) { + std::cerr << "COutputValidationPlan::validate() incorrect tx" << "for ival=" << ival << " in tx.vout no such ivout=" << ivout << std::endl; + return eval->Invalid("incorrect tx structure: not all required vouts are present."); + } + else + { + // exec 'validators' from validator row of ival index, for tx.vout[ivout] + if (!execValidatorsInRow(&tx, ivout, ival, message)) { + std::ostringstream stream; + stream << "invalid tx vout[" << ivout << "]:" << message; + return eval->Invalid(stream.str().c_str()); // ... if not, return 'invalid' + } + } + ival++; // advance to the next vout + } + //std::cerr << "COutputValidationPlan::validate() returns with true" << std::endl; + return true; + } + +private: + // Executes validators from the requested row of validators (selected by iValidators) for selected vin or vout (selected by iv) + bool execValidatorsInRow(const CTransaction* pTx, int32_t iv, int32_t ival, std::string& refMessage) const + { + // check boundaries: + if (ival < 0 || ival >= m_arrayValidators.size()) { + std::cerr << "COutputValidationPlan::execValidatorsInRow() internal error: incorrect param ival=" << ival << " size=" << m_arrayValidators.size(); + refMessage = "internal error: incorrect param ival index"; + return false; + } + + if (iv < 0 || iv >= pTx->vout.size()) { + std::cerr << "COutputValidationPlan::execValidatorsInRow() internal error: incorrect param iv=" << iv << " size=" << m_arrayValidators.size(); + refMessage = "internal error: incorrect param iv index"; + return false; + } + + // get requested row of validators: + ValidatorsRow vValidators = m_arrayValidators[ival].second; + + //std::cerr << "COutputValidationPlan::execRow() calling validators" << " for vout iv=" << iv << " ival=" << ival << std::endl; + + for (auto v : vValidators) { + + if (!v->isVinValidator()) { + // if this is a 'in' validation plan then pass the previous tx vout: + bool result = v->validateVout(pTx->vout[iv], iv, refMessage); + if (!result) + return result; + } + } + return true; // validation OK + } + +private: + //std::map m_mapValidators; + std::vector< std::pair > m_arrayValidators; + +}; + +class CNormalInputIdentifier : CInputIdentifierBase { +public: + CNormalInputIdentifier(CCcontract_info* cp) : CInputIdentifierBase(cp) {} + virtual std::string inputName() const { return std::string("normal input"); } + virtual bool identifyInput(CTxIn vin) const { + return !IsCCInput(vin.scriptSig); + } +}; + +class CCCInputIdentifier : CInputIdentifierBase { +public: + CCCInputIdentifier(CCcontract_info* cp) : CInputIdentifierBase(cp) {} + virtual std::string inputName() const { return std::string("CC input"); } + virtual bool identifyInput(CTxIn vin) const { + return IsCCInput(vin.scriptSig); + } +}; + + +/** + * Validates 1of2address for vout (may be used for either this or prev tx) + */ +template class CCC1of2AddressValidator : CValidatorBase +{ +public: + CCC1of2AddressValidator(CCcontract_info* cp, CScript opRetScript, std::string customMessage = "") : + m_fundingOpretScript(opRetScript), m_customMessage(customMessage), CValidatorBase(cp) {} + + virtual bool isVinValidator() const { return false; } + virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const + { + //std::cerr << "CCC1of2AddressValidator::validateVout() entered" << std::endl; + CPubKey ownerPubkey, heirPubkey; + int64_t inactivityTime; + std::string heirName; + uint256 tokenid; + + uint8_t funcId = DecodeHeirEitherOpRet(m_fundingOpretScript, tokenid, ownerPubkey, heirPubkey, inactivityTime, heirName, true); + if (funcId == 0) { + message = m_customMessage + std::string(" invalid opreturn format"); + std::cerr << "CCC1of2AddressValidator::validateVout() exits with false: " << message << std::endl; + return false; + } + + char shouldBeAddr[65], ccAddr[65]; + + //GetCCaddress1of2(m_cp, shouldBeAddr, ownerPubkey, heirPubkey); + Helper::GetCoinsOrTokensCCaddress1of2(shouldBeAddr, ownerPubkey, heirPubkey); + + if (vout.scriptPubKey.IsPayToCryptoCondition()) { + if (Getscriptaddress(ccAddr, vout.scriptPubKey) && strcmp(shouldBeAddr, ccAddr) == 0) { + //std::cerr << "CCC1of2AddressValidator::validateVout() exits with true" << std::endl; + return true; + } + else { + message = m_customMessage + std::string(" incorrect heir funding address: incorrect pubkey(s)"); + } + } + else { + message = m_customMessage + std::string(" incorrect heir funding address: not a 1of2addr"); + } + + std::cerr << "CCC1of2AddressValidator::validateVout() exits with false: " << message << std::endl; + return false; + } + virtual bool validateVin(CTxIn vin, std::vector prevVout, int32_t prevN, std::string& message) const { return false; } + +private: + CScript m_fundingOpretScript; + std::string m_customMessage; +}; + + +/** + * Validates if this is vout to owner or heir from opret (funding or change) + */ +template class CMyPubkeyVoutValidator : CValidatorBase +{ +public: + CMyPubkeyVoutValidator(CCcontract_info* cp, CScript opRetScript, bool checkNormals) + : m_fundingOpretScript(opRetScript), m_checkNormals(checkNormals), CValidatorBase(cp) { } + + virtual bool isVinValidator() const { return false; } + virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const + { + //std::cerr << "CMyPubkeyVoutValidator::validateVout() entered" << std::endl; + + CPubKey ownerPubkey, heirPubkey; + int64_t inactivityTime; + std::string heirName; + uint256 tokenid; + + ///std::cerr << "CMyPubkeyVoutValidator::validateVout() m_opRetScript=" << m_opRetScript.ToString() << std::endl; + + // get both pubkeys: + uint8_t funcId = DecodeHeirEitherOpRet(m_fundingOpretScript, tokenid, ownerPubkey, heirPubkey, inactivityTime, heirName, true); + if (funcId == 0) { + message = std::string("invalid opreturn format"); + return false; + } + + CScript ownerScript; + CScript heirScript; + if (m_checkNormals) { //not used, incorrect check, too strict + ownerScript = CoinHelper::makeUserVout(vout.nValue, ownerPubkey).scriptPubKey; + heirScript = CoinHelper::makeUserVout(vout.nValue, heirPubkey).scriptPubKey; + std::cerr << "CMyPubkeyVoutValidator::validateVout() vout.scriptPubKey=" << vout.scriptPubKey.ToString() << " makeUserVout(coin,owner)=" << CoinHelper::makeUserVout(vout.nValue, ownerPubkey).scriptPubKey.ToString() << " makeUserVout(coin,heir)=" << CoinHelper::makeUserVout(vout.nValue, heirPubkey).scriptPubKey.ToString() << std::endl; + } + else { + ownerScript = Helper::makeUserVout(vout.nValue, ownerPubkey).scriptPubKey; + heirScript = Helper::makeUserVout(vout.nValue, heirPubkey).scriptPubKey; + std::cerr << "CMyPubkeyVoutValidator::validateVout() vout.scriptPubKey=" << vout.scriptPubKey.ToString() << " makeUserVout(owner)=" << Helper::makeUserVout(vout.nValue, ownerPubkey).scriptPubKey.ToString() << " makeUserVout(heir)=" << Helper::makeUserVout(vout.nValue, heirPubkey).scriptPubKey.ToString() << std::endl; + } + + // recreate scriptPubKey for owner and heir and compare it with that of the vout to check: + if (vout.scriptPubKey == ownerScript || vout.scriptPubKey == heirScript) { + // this is vout to owner or heir addr: + //std::cerr << "CMyPubkeyVoutValidator::validateVout() exits with true" << std::endl; + return true; + } + + std::cerr << "CMyPubkeyVoutValidator::validateVout() exits with false (not the owner's or heir's addresses)" << std::endl; + message = std::string("invalid pubkey"); + return false; + } + virtual bool validateVin(CTxIn vin, std::vector prevVout, int32_t prevN, std::string& message) const { return true; } + +private: + CScript m_fundingOpretScript; + //uint256 m_lasttxid; + bool m_checkNormals; +}; + +/** + * Check if the user is the heir and the heir is allowed to spend (duration > inactivityTime) + */ +template class CHeirSpendValidator : CValidatorBase +{ +public: + CHeirSpendValidator(CCcontract_info* cp, CScript opRetScript, uint256 latesttxid, uint8_t isHeirSpendingBegan) + : m_fundingOpretScript(opRetScript), m_latesttxid(latesttxid), m_isHeirSpendingBegan(isHeirSpendingBegan), CValidatorBase(cp) {} + + virtual bool isVinValidator() const { return false; } + virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const + { + //std::cerr << "CHeirSpendValidator::validateVout() entered" << std::endl; + + CPubKey ownerPubkey, heirPubkey; + int64_t inactivityTime; + std::string heirName; + uint256 tokenid; + + // get heir pubkey: + uint8_t funcId = DecodeHeirEitherOpRet(m_fundingOpretScript, tokenid, ownerPubkey, heirPubkey, inactivityTime, heirName, true); + if (funcId == 0) { + message = std::string("invalid opreturn format"); + return false; + } + + int32_t numblocks; + int64_t durationSec = CCduration(numblocks, m_latesttxid); + + // recreate scriptPubKey for heir and compare it with that of the vout: + if (vout.scriptPubKey == Helper::makeUserVout(vout.nValue, heirPubkey).scriptPubKey) { + // this is the heir is trying to spend + if (!m_isHeirSpendingBegan && durationSec <= inactivityTime) { + message = "heir is not allowed yet to spend funds"; + std::cerr << "CHeirSpendValidator::validateVout() heir is not allowed yet to spend funds" << std::endl; + return false; + } + else { + // heir is allowed to spend + return true; + } + } + + //std::cerr << "CHeirSpendValidator::validateVout() exits with true" << std::endl; + + // this is not heir: + return true; + } + virtual bool validateVin(CTxIn vin, std::vector prevVout, int32_t prevN, std::string& message) const { return true; } + +private: + CScript m_fundingOpretScript; + uint256 m_latesttxid; + uint8_t m_isHeirSpendingBegan; +}; + +/** + * Validates this opreturn and compares it with the opreturn from the previous tx + */ +template class COpRetValidator : CValidatorBase +{ +public: + COpRetValidator(CCcontract_info* cp, CScript opret) + : m_fundingOpretScript(opret), CValidatorBase(cp) {} + + virtual bool isVinValidator() const { return false; } + virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const + { + //std::cerr << "COpRetValidator::validateVout() entered" << std::endl; + + uint256 fundingTxidInOpret = zeroid, dummyTxid, tokenid = zeroid, initialTokenid = zeroid; + uint8_t dummyIsHeirSpendingBegan; + + uint8_t funcId = DecodeHeirEitherOpRet(vout.scriptPubKey, tokenid, fundingTxidInOpret, dummyIsHeirSpendingBegan, true); + if (funcId == 0) { + message = std::string("invalid opreturn format"); + return false; + } + + uint8_t initialFuncId = DecodeHeirEitherOpRet(m_fundingOpretScript, initialTokenid, dummyTxid, dummyIsHeirSpendingBegan, true); + if (initialFuncId == 0) { + message = std::string("invalid initial tx opreturn format"); + return false; + } + + // validation rules: + if (!isMyFuncId(funcId)) { + message = std::string("invalid funcid in opret"); + return false; + } + + if (typeid(Helper) == typeid(TokenHelper)) { + if (tokenid != initialTokenid) { + message = std::string("invalid tokenid in opret"); + return false; + } + } + + //std::cerr << "COpRetValidator::validateVout() exits with true" << std::endl; + return true; + } + virtual bool validateVin(CTxIn vin, std::vector prevVout, int32_t prevN, std::string& message) const { return true; } + +private: + CScript m_fundingOpretScript; +}; + + +/** + * marker spending prevention validator, + * returns false if for tx with funcid=F vout.1 is being tried to spend + */ +template class CMarkerValidator : CValidatorBase +{ +public: + CMarkerValidator(CCcontract_info* cp) + : CValidatorBase(cp) { } + + virtual bool isVinValidator() const { return true; } // this is vin validator + virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const { return true; } + virtual bool validateVin(CTxIn vin, std::vector prevVout, int32_t prevN, std::string& message) const { + + uint256 fundingTxidInOpret = zeroid, dummyTxid, tokenid = zeroid, initialTokenid = zeroid; + uint8_t dummyIsHeirSpendingBegan; + + //std::cerr << "CMarkerValidator::validateVin() prevVout.size()=" << prevVout.size() << " prevN=" << prevN << std::endl; + if (prevVout.size() > 0) { + + // get funcId for prev tx: + uint8_t funcId = DecodeHeirEitherOpRet(prevVout[prevVout.size()-1].scriptPubKey, tokenid, fundingTxidInOpret, dummyIsHeirSpendingBegan, true); + + //std::cerr << "CMarkerValidator::validateVin() funcId=" << (funcId?funcId:' ') << std::endl; + + if (funcId == 'F' && prevN == 1) { // do not allow to spend 'F' marker's vout + message = std::string("spending marker not allowed"); + return false; + } + } + //std::cerr << "CMarkerValidator::validateVin() exits with true" << std::endl; + return true; + } +}; + +/** + * empty validator always returns true + */ +template class CNullValidator : CValidatorBase +{ +public: + CNullValidator(CCcontract_info* cp) + : CValidatorBase(cp) { } + + virtual bool isVinValidator() const { return false; } + virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const { return true; } + virtual bool validateVin(CTxIn vin, std::vector prevVout, int32_t prevN, std::string& message) const { return true; } +}; + + +#endif diff --git a/src/cc/import.cpp b/src/cc/import.cpp index b250bb7bf..ea69745b0 100644 --- a/src/cc/import.cpp +++ b/src/cc/import.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -18,46 +18,125 @@ #include "importcoin.h" #include "crosschain.h" #include "primitives/transaction.h" - +#include "cc/CCinclude.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. + + ##### 0xffffffff is a special CCid for single chain/dual daemon imports */ -bool Eval::ImportCoin(const std::vector params, const CTransaction &importTx, unsigned int nIn) + +extern std::string ASSETCHAINS_SELFIMPORT; +extern uint16_t ASSETCHAINS_CODAPORT,ASSETCHAINS_BEAMPORT; +extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33]; + +int32_t GetSelfimportProof(std::string source,CMutableTransaction &mtx,CScript &scriptPubKey,TxProof &proof,uint64_t burnAmount,std::vector rawtx,uint256 txid,std::vector rawproof) // find burnTx with hash from "other" daemon { - if (importTx.vout.size() < 2) + MerkleBranch newBranch; CMutableTransaction tmpmtx; CTransaction tx,vintx; uint256 blockHash; char destaddr[64],pkaddr[64]; + tmpmtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(),komodo_nextheight()); + if ( source == "BEAM" ) + { + if ( ASSETCHAINS_BEAMPORT == 0 ) + return(-1); + // confirm via ASSETCHAINS_BEAMPORT that burnTx/hash is a valid BEAM burn + // return(0); + } + else if ( source == "CODA" ) + { + if ( ASSETCHAINS_CODAPORT == 0 ) + return(-1); + // confirm via ASSETCHAINS_CODAPORT that burnTx/hash is a valid CODA burn + // return(0); + } + else + { + if ( !E_UNMARSHAL(rawtx, ss >> tx) ) + return(-1); + scriptPubKey = tx.vout[0].scriptPubKey; + mtx = tx; + mtx.fOverwintered = tmpmtx.fOverwintered; + mtx.nExpiryHeight = tmpmtx.nExpiryHeight; + mtx.nVersionGroupId = tmpmtx.nVersionGroupId; + mtx.nVersion = tmpmtx.nVersion; + mtx.vout.clear(); + mtx.vout.resize(1); + mtx.vout[0].nValue = burnAmount; + mtx.vout[0].scriptPubKey = scriptPubKey; + if ( tx.GetHash() != txid ) + return(-1); + if ( source == "PUBKEY" ) + { + // make sure vin0 is signed by ASSETCHAINS_OVERRIDE_PUBKEY33 + if ( myGetTransaction(tx.vin[0].prevout.hash,vintx,blockHash) == 0 ) + return(-1); + if ( tx.vin[0].prevout.n < vintx.vout.size() && Getscriptaddress(destaddr,vintx.vout[tx.vin[0].prevout.n].scriptPubKey) != 0 ) + { + pubkey2addr(pkaddr,ASSETCHAINS_OVERRIDE_PUBKEY33); + if ( strcmp(pkaddr,destaddr) == 0 ) + { + proof = std::make_pair(txid,newBranch); + return(0); + } + fprintf(stderr,"mismatched vin0[%d] -> %s vs %s\n",tx.vin[0].prevout.n,destaddr,pkaddr); + } + } + else if ( source == ASSETCHAINS_SELFIMPORT ) + { + // source is external coin is the assetchains symbol in the burnTx OP_RETURN + // burnAmount, rawtx and rawproof should be enough for gatewaysdeposit equivalent + } + } + return(-1); +} + +// use proof from the above functions to validate the import + +int32_t CheckBEAMimport(TxProof proof,std::vector rawproof,CTransaction burnTx,std::vector payouts) +{ + // check with dual-BEAM daemon via ASSETCHAINS_BEAMPORT for validity of burnTx + return(-1); +} + +int32_t CheckCODAimport(TxProof proof,std::vector rawproof,CTransaction burnTx,std::vector payouts) +{ + // check with dual-CODA daemon via ASSETCHAINS_CODAPORT for validity of burnTx + return(-1); +} + +int32_t CheckGATEWAYimport(TxProof proof,std::vector rawproof,CTransaction burnTx,std::vector payouts) +{ + // ASSETCHAINS_SELFIMPORT is coin + // check for valid burn from external coin blockchain and if valid return(0); + return(-1); +} + +int32_t CheckPUBKEYimport(TxProof proof,std::vector rawproof,CTransaction burnTx,std::vector payouts) +{ + // if burnTx has ASSETCHAINS_PUBKEY vin, it is valid return(0); + fprintf(stderr,"proof txid.%s\n",proof.first.GetHex().c_str()); + return(0); + return(-1); +} + +bool Eval::ImportCoin(const std::vector params,const CTransaction &importTx,unsigned int nIn) +{ + TxProof proof; CTransaction burnTx; std::vector payouts; uint64_t txfee = 10000; + uint32_t targetCcid; std::string targetSymbol; uint256 payoutsHash; std::vector rawproof; + 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)) + if (!UnmarshalBurnTx(burnTx, targetSymbol, &targetCcid, payoutsHash,rawproof)) return Invalid("invalid-burn-tx"); - - if (targetCcid != GetAssetchainsCC() || targetSymbol != GetAssetchainsSymbol()) - return Invalid("importcoin-wrong-chain"); - - if (targetCcid < KOMODO_FIRSTFUNGIBLEID) - return Invalid("chain-not-fungible"); - // check burn amount { uint64_t burnAmount = burnTx.vout.back().nValue; @@ -66,21 +145,54 @@ bool Eval::ImportCoin(const std::vector params, const CTransaction &imp uint64_t totalOut = 0; for (int i=0; i burnAmount) - return Invalid("payout-too-high"); + if (totalOut > burnAmount || totalOut < burnAmount-txfee ) + return Invalid("payout-too-high-or-too-low"); } - // Check burntx shows correct outputs hash if (payoutsHash != SerializeHash(payouts)) return Invalid("wrong-payouts"); - + if (targetCcid < KOMODO_FIRSTFUNGIBLEID) + return Invalid("chain-not-fungible"); // Check proof confirms existance of burnTx + if ( targetCcid != 0xffffffff ) { + if ( targetCcid != GetAssetchainsCC() || targetSymbol != GetAssetchainsSymbol() ) + return Invalid("importcoin-wrong-chain"); uint256 target = proof.second.Exec(burnTx.GetHash()); if (!CheckMoMoM(proof.first, target)) return Invalid("momom-check-fail"); } - + else + { + if ( targetSymbol == "BEAM" ) + { + if ( ASSETCHAINS_BEAMPORT == 0 ) + return Invalid("BEAM-import-without-port"); + else if ( CheckBEAMimport(proof,rawproof,burnTx,payouts) < 0 ) + return Invalid("BEAM-import-failure"); + } + else if ( targetSymbol == "CODA" ) + { + if ( ASSETCHAINS_CODAPORT == 0 ) + return Invalid("CODA-import-without-port"); + else if ( CheckCODAimport(proof,rawproof,burnTx,payouts) < 0 ) + return Invalid("CODA-import-failure"); + } + else if ( targetSymbol == "PUBKEY" ) + { + if ( ASSETCHAINS_SELFIMPORT != "PUBKEY" ) + return Invalid("PUBKEY-import-when-notPUBKEY"); + else if ( CheckPUBKEYimport(proof,rawproof,burnTx,payouts) < 0 ) + return Invalid("PUBKEY-import-failure"); + } + else + { + if ( targetSymbol != ASSETCHAINS_SELFIMPORT ) + return Invalid("invalid-gateway-import-coin"); + else if ( CheckGATEWAYimport(proof,rawproof,burnTx,payouts) < 0 ) + return Invalid("GATEWAY-import-failure"); + } + } return Valid(); } diff --git a/src/cc/importpayout.cpp b/src/cc/importpayout.cpp index 1363eb924..be31a8414 100644 --- a/src/cc/importpayout.cpp +++ b/src/cc/importpayout.cpp @@ -1,3 +1,18 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include #include "main.h" diff --git a/src/cc/includes/cJSON.h b/src/cc/includes/cJSON.h index 3ecdadc69..ed8c26b7f 100755 --- a/src/cc/includes/cJSON.h +++ b/src/cc/includes/cJSON.h @@ -20,6 +20,21 @@ THE SOFTWARE. */ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef cJSON__h #define cJSON__h diff --git a/src/cc/includes/curve25519.h b/src/cc/includes/curve25519.h index 9f8c9ba16..19abe8d10 100755 --- a/src/cc/includes/curve25519.h +++ b/src/cc/includes/curve25519.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2015 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cc/includes/libgfshare.h b/src/cc/includes/libgfshare.h index a4d494aff..dc8747fe9 100755 --- a/src/cc/includes/libgfshare.h +++ b/src/cc/includes/libgfshare.h @@ -23,6 +23,21 @@ * */ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef LIBGFSHARE_H #define LIBGFSHARE_H #include diff --git a/src/cc/lotto.cpp b/src/cc/lotto.cpp index e89f2692a..e9c263ff1 100644 --- a/src/cc/lotto.cpp +++ b/src/cc/lotto.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -115,7 +115,7 @@ bool LottoExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction bool LottoValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) { int32_t numvins,numvouts,preventCCvins,preventCCvouts,i; bool retval; - return(false); // reject any lotto CC for now + return eval->Invalid("no validation yet"); numvins = tx.vin.size(); numvouts = tx.vout.size(); preventCCvins = preventCCvouts = -1; diff --git a/src/cc/makecclib b/src/cc/makecclib new file mode 100755 index 000000000..47aec377d --- /dev/null +++ b/src/cc/makecclib @@ -0,0 +1 @@ +gcc -std=c++11 -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o ../cclib.so cclib.cpp diff --git a/src/cc/marmara.cpp b/src/cc/marmara.cpp new file mode 100644 index 000000000..8f8de12e2 --- /dev/null +++ b/src/cc/marmara.cpp @@ -0,0 +1,1097 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + +#include "CCMarmara.h" + +/* + Marmara CC is for the MARMARA project + + 'R': two forms for initial issuance and for accepting existing + vins normal + vout0 approval to senderpk (issuer or owner of baton) + + 'I' + vin0 approval from 'R' + vins1+ normal + vout0 baton to 1st receiverpk + vout1 marker to Marmara so all issuances can be tracked (spent when loop is closed) + + 'T' + vin0 approval from 'R' + vin1 baton from 'I'/'T' + vins2+ normal + vout0 baton to next receiverpk (following the unspent baton back to original is the credit loop) + + 'S' + vin0 'I' marker + vin1 baton + vins CC utxos from credit loop + + 'D' default/partial payment + + 'L' lockfunds + +*/ + +// start of consensus code + +int64_t IsMarmaravout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) +{ + char destaddr[64]; + if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) + { + if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 ) + return(tx.vout[v].nValue); + } + return(0); +} + +int32_t MarmaraRandomize(uint32_t ind) +{ + uint64_t val64; uint32_t val,range = (MARMARA_MAXLOCK - MARMARA_MINLOCK); + val64 = komodo_block_prg(ind); + val = (uint32_t)(val64 >> 32); + val ^= (uint32_t)val64; + return((val % range) + MARMARA_MINLOCK); +} + +int32_t MarmaraUnlockht(int32_t height) +{ + uint32_t ind = height / MARMARA_GROUPSIZE; + height = (height / MARMARA_GROUPSIZE) * MARMARA_GROUPSIZE; + return(height + MarmaraRandomize(ind)); +} + +uint8_t DecodeMaramaraCoinbaseOpRet(const CScript scriptPubKey,CPubKey &pk,int32_t &height,int32_t &unlockht) +{ + std::vector vopret; uint8_t *script,e,f,funcid; + GetOpReturnData(scriptPubKey,vopret); + script = (uint8_t *)vopret.data(); + if ( 0 ) + { + int32_t i; + for (i=0; i 2 && script[0] == EVAL_MARMARA ) + { + if ( script[1] == 'C' || script[1] == 'P' || script[1] == 'L' ) + { + if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> pk; ss >> height; ss >> unlockht) != 0 ) + { + return(script[1]); + } else fprintf(stderr,"DecodeMaramaraCoinbaseOpRet unmarshal error for %c\n",script[1]); + } //else fprintf(stderr,"script[1] is %d != 'C' %d or 'P' %d or 'L' %d\n",script[1],'C','P','L'); + } else fprintf(stderr,"vopret.size() is %d\n",(int32_t)vopret.size()); + return(0); +} + +CScript EncodeMarmaraCoinbaseOpRet(uint8_t funcid,CPubKey pk,int32_t ht) +{ + CScript opret; int32_t unlockht; uint8_t evalcode = EVAL_MARMARA; + unlockht = MarmaraUnlockht(ht); + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << pk << ht << unlockht); + if ( 0 ) + { + std::vector vopret; uint8_t *script,i; + GetOpReturnData(opret,vopret); + script = (uint8_t *)vopret.data(); + { + for (i=0; i vopret; uint8_t *script,e,f; + GetOpReturnData(scriptPubKey, vopret); + script = (uint8_t *)vopret.data(); + if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> createtxid; ss >> senderpk; ss >> amount; ss >> matures; ss >> currency) != 0 ) + { + return(f); + } + return(0); +} + +int32_t MarmaraGetcreatetxid(uint256 &createtxid,uint256 txid) +{ + CTransaction tx; uint256 hashBlock; uint8_t funcid; int32_t numvouts,matures; std::string currency; CPubKey senderpk; int64_t amount; + if ( myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 1 ) + { + if ( (funcid= MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,createtxid,senderpk,amount,matures,currency)) == 'I' || funcid == 'T' ) + return(0); + else if ( funcid == 'R' ) + { + if ( createtxid == zeroid ) + createtxid = txid; + return(0); + } + } + return(-1); +} + +int32_t MarmaraGetbatontxid(std::vector &creditloop,uint256 &batontxid,uint256 txid) +{ + uint256 createtxid,spenttxid; int64_t value; int32_t vini,height,n=0,vout = 0; + memset(&batontxid,0,sizeof(batontxid)); + if ( MarmaraGetcreatetxid(createtxid,txid) == 0 ) + { + txid = createtxid; + //fprintf(stderr,"txid.%s -> createtxid %s\n",txid.GetHex().c_str(),createtxid.GetHex().c_str()); + while ( CCgetspenttxid(spenttxid,vini,height,txid,vout) == 0 ) + { + creditloop.push_back(txid); + //fprintf(stderr,"%d: %s\n",n,txid.GetHex().c_str()); + n++; + if ( (value= CCgettxout(spenttxid,vout,1)) == 10000 ) + { + batontxid = spenttxid; + //fprintf(stderr,"got baton %s %.8f\n",batontxid.GetHex().c_str(),(double)value/COIN); + return(n); + } + else if ( value > 0 ) + { + batontxid = spenttxid; + fprintf(stderr,"n.%d got false baton %s/v%d %.8f\n",n,batontxid.GetHex().c_str(),vout,(double)value/COIN); + return(n); + } + // get funcid + txid = spenttxid; + } + } + return(-1); +} + +CScript Marmara_scriptPubKey(int32_t height,CPubKey pk) +{ + CTxOut ccvout; struct CCcontract_info *cp,C; CPubKey Marmarapk; + cp = CCinit(&C,EVAL_MARMARA); + Marmarapk = GetUnspendable(cp,0); + if ( height > 0 && (height & 1) == 0 && pk.size() == 33 ) + { + ccvout = MakeCC1of2vout(EVAL_MARMARA,0,Marmarapk,pk); + //char coinaddr[64]; + //Getscriptaddress(coinaddr,ccvout.scriptPubKey); + //fprintf(stderr,"Marmara_scriptPubKey %s ht.%d -> %s\n",HexStr(pk).c_str(),height,coinaddr); + } + return(ccvout.scriptPubKey); +} + +CScript MarmaraCoinbaseOpret(uint8_t funcid,int32_t height,CPubKey pk) +{ + uint8_t *ptr; + //fprintf(stderr,"height.%d pksize.%d\n",height,(int32_t)pk.size()); + if ( height > 0 && (height & 1) == 0 && pk.size() == 33 ) + return(EncodeMarmaraCoinbaseOpRet(funcid,pk,height)); + return(CScript()); +} + +int32_t MarmaraValidateCoinbase(int32_t height,CTransaction tx) +{ + struct CCcontract_info *cp,C; CPubKey Marmarapk,pk; int32_t ht,unlockht; CTxOut ccvout; + cp = CCinit(&C,EVAL_MARMARA); + Marmarapk = GetUnspendable(cp,0); + if ( 0 ) + { + int32_t d,histo[365*2+30]; + memset(histo,0,sizeof(histo)); + for (ht=2; ht<100; ht++) + fprintf(stderr,"%d ",MarmaraUnlockht(ht)); + fprintf(stderr," <- first 100 unlock heights\n"); + for (ht=2; ht<1000000; ht+=MARMARA_GROUPSIZE) + { + d = (MarmaraUnlockht(ht) - ht) / 1440; + if ( d < 0 || d > sizeof(histo)/sizeof(*histo) ) + fprintf(stderr,"d error.%d at ht.%d\n",d,ht); + else histo[d]++; + } + for (ht=0; ht unlock.%d\n",ht,unlockht); + ccvout = MakeCC1of2vout(EVAL_MARMARA,0,Marmarapk,pk); + if ( ccvout.scriptPubKey == tx.vout[0].scriptPubKey ) + return(0); + char addr0[64],addr1[64]; + Getscriptaddress(addr0,ccvout.scriptPubKey); + Getscriptaddress(addr1,tx.vout[0].scriptPubKey); + fprintf(stderr,"ht.%d mismatched CCvout scriptPubKey %s vs %s pk.%d %s\n",height,addr0,addr1,(int32_t)pk.size(),HexStr(pk).c_str()); + } else fprintf(stderr,"ht.%d %d vs %d unlock.%d\n",height,MarmaraUnlockht(height),ht,unlockht); + } else fprintf(stderr,"ht.%d error decoding coinbase opret\n",height); + } + return(-1); +} + +bool MarmaraPoScheck(char *destaddr,CScript opret,CTransaction staketx) +{ + CPubKey Marmarapk,pk; int32_t height,unlockht; uint8_t funcid; char coinaddr[64]; struct CCcontract_info *cp,C; + //fprintf(stderr,"%s numvins.%d numvouts.%d %.8f opret[%d]\n",staketx.GetHash().ToString().c_str(),(int32_t)staketx.vin.size(),(int32_t)staketx.vout.size(),(double)staketx.vout[0].nValue/COIN,(int32_t)opret.size()); + if ( staketx.vout.size() == 2 && opret == staketx.vout[1].scriptPubKey ) + { + cp = CCinit(&C,EVAL_MARMARA); + funcid = DecodeMaramaraCoinbaseOpRet(opret,pk,height,unlockht); + Marmarapk = GetUnspendable(cp,0); + GetCCaddress1of2(cp,coinaddr,Marmarapk,pk); + //fprintf(stderr,"matched opret! funcid.%c ht.%d unlock.%d %s\n",funcid,height,unlockht,coinaddr); + return(strcmp(destaddr,coinaddr) == 0); + } + return(0); +} + +bool MarmaraValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) +{ + std::vector vopret; CTransaction vinTx; uint256 hashBlock; int32_t numvins,numvouts,i,ht,unlockht,vht,vunlockht; uint8_t funcid,vfuncid,*script; CPubKey pk,vpk; + if ( ASSETCHAINS_MARMARA == 0 ) + return eval->Invalid("-ac_marmara must be set for marmara CC"); + numvins = tx.vin.size(); + numvouts = tx.vout.size(); + if ( numvouts < 1 ) + return eval->Invalid("no vouts"); + else if ( tx.vout.size() >= 2 ) + { + GetOpReturnData(tx.vout[tx.vout.size()-1].scriptPubKey,vopret); + script = (uint8_t *)vopret.data(); + if ( vopret.size() < 2 || script[0] != EVAL_MARMARA ) + return eval->Invalid("no opreturn"); + funcid = script[1]; + if ( funcid == 'P' ) + { + funcid = DecodeMaramaraCoinbaseOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,pk,ht,unlockht); + for (i=0; iismyvin)(tx.vin[i].scriptSig) != 0 ) + { + if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 ) + return eval->Invalid("cant find vinTx"); + else + { + if ( vinTx.IsCoinBase() == 0 ) + return eval->Invalid("noncoinbase input"); + else if ( vinTx.vout.size() != 2 ) + return eval->Invalid("coinbase doesnt have 2 vouts"); + vfuncid = DecodeMaramaraCoinbaseOpRet(vinTx.vout[1].scriptPubKey,vpk,vht,vunlockht); + if ( vfuncid != 'C' || vpk != pk || vunlockht != unlockht ) + return eval->Invalid("mismatched opreturn"); + } + } + } + return(true); + } + else if ( funcid == 'L' ) // lock -> lock funds with a unlockht + { + return(true); + } + else if ( funcid == 'R' ) // receive -> agree to receive 'I' from pk, amount, currency, dueht + { + return(true); + } + else if ( funcid == 'I' ) // issue -> issue currency to pk with due date height + { + return(true); + } + else if ( funcid == 'T' ) // transfer -> given 'R' transfer 'I' or 'T' to the pk of 'R' + { + return(true); + } + else if ( funcid == 'S' ) // settlement -> automatically spend issuers locked funds, given 'I' + { + return(true); + } + else if ( funcid == 'D' ) // insufficient settlement + { + return(true); + } + else if ( funcid == 'C' ) // coinbase + { + return(true); + } + // staking only for locked utxo + } + return eval->Invalid("fall through error"); +} +// end of consensus code + +// helper functions for rpc calls in rpcwallet.cpp + +int64_t AddMarmaraCoinbases(struct CCcontract_info *cp,CMutableTransaction &mtx,int32_t firstheight,CPubKey poolpk,int32_t maxinputs) +{ + char coinaddr[64]; CPubKey Marmarapk,pk; int64_t nValue,totalinputs = 0; uint256 txid,hashBlock; CTransaction vintx; int32_t unlockht,ht,vout,unlocks,n = 0; + std::vector > unspentOutputs; + Marmarapk = GetUnspendable(cp,0); + GetCCaddress1of2(cp,coinaddr,Marmarapk,poolpk); + SetCCunspents(unspentOutputs,coinaddr); + unlocks = MarmaraUnlockht(firstheight); + //fprintf(stderr,"check coinaddr.(%s)\n",coinaddr); + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) + { + txid = it->first.txhash; + vout = (int32_t)it->first.index; + //fprintf(stderr,"txid.%s/v%d\n",txid.GetHex().c_str(),vout); + if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) + { + if ( vintx.IsCoinBase() != 0 && vintx.vout.size() == 2 && vintx.vout[1].nValue == 0 ) + { + if ( DecodeMaramaraCoinbaseOpRet(vintx.vout[1].scriptPubKey,pk,ht,unlockht) == 'C' && unlockht == unlocks && pk == poolpk && ht >= firstheight ) + { + if ( (nValue= vintx.vout[vout].nValue) > 0 && myIsutxo_spentinmempool(txid,vout) == 0 ) + { + if ( maxinputs != 0 ) + mtx.vin.push_back(CTxIn(txid,vout,CScript())); + nValue = it->second.satoshis; + totalinputs += nValue; + n++; + if ( maxinputs > 0 && n >= maxinputs ) + break; + } //else fprintf(stderr,"nValue.%8f\n",(double)nValue/COIN); + } //else fprintf(stderr,"decode error unlockht.%d vs %d pk.%d\n",unlockht,unlocks,pk == poolpk); + } else fprintf(stderr,"not coinbase\n"); + } else fprintf(stderr,"error getting tx\n"); + } + return(totalinputs); +} + +int64_t AddMarmarainputs(CMutableTransaction &mtx,std::vector &pubkeys,char *coinaddr,int64_t total,int32_t maxinputs) +{ + uint64_t threshold,nValue,totalinputs = 0; uint256 txid,hashBlock; CTransaction tx; int32_t numvouts,ht,unlockht,vout,i,n = 0; uint8_t funcid; CPubKey pk; std::vector vals; + std::vector > unspentOutputs; + SetCCunspents(unspentOutputs,coinaddr); + threshold = total/(maxinputs+1); + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) + { + txid = it->first.txhash; + vout = (int32_t)it->first.index; + if ( it->second.satoshis < threshold ) + continue; + if ( GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 && vout < numvouts && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 && myIsutxo_spentinmempool(txid,vout) == 0 ) + { + if ( (funcid= DecodeMaramaraCoinbaseOpRet(tx.vout[numvouts-1].scriptPubKey,pk,ht,unlockht)) == 'C' || funcid == 'P' || funcid == 'L' ) + { + //char str[64]; fprintf(stderr,"(%s) %s/v%d %.8f ht.%d unlockht.%d\n",coinaddr,uint256_str(str,txid),vout,(double)it->second.satoshis/COIN,ht,unlockht); + if ( total != 0 && maxinputs != 0 ) + { + mtx.vin.push_back(CTxIn(txid,vout,CScript())); + pubkeys.push_back(pk); + } + totalinputs += it->second.satoshis; + vals.push_back(it->second.satoshis); + n++; + if ( maxinputs != 0 && total == 0 ) + continue; + if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) + break; + } else fprintf(stderr,"null funcid\n"); + } + } + if ( maxinputs != 0 && total == 0 ) + { + std::sort(vals.begin(),vals.end()); + totalinputs = 0; + for (i=0; i txfee ) + inputsum = AddNormalinputs2(mtx,val,CC_MAXVINS/2); + //fprintf(stderr,"normal inputs %.8f val %.8f\n",(double)inputsum/COIN,(double)val/COIN); + mtx.vout.push_back(MakeCC1of2vout(EVAL_MARMARA,amount,Marmarapk,mypk)); + if ( inputsum < amount+txfee ) + { + refunlockht = MarmaraUnlockht(height); + result.push_back(Pair("normalfunds",ValueFromAmount(inputsum))); + result.push_back(Pair("height",height)); + result.push_back(Pair("unlockht",refunlockht)); + remains = (amount + txfee) - inputsum; + std::vector > unspentOutputs; + GetCCaddress1of2(cp,coinaddr,Marmarapk,mypk); + SetCCunspents(unspentOutputs,coinaddr); + threshold = remains / (MARMARA_VINS+1); + CCaddr1of2set(cp,Marmarapk,mypk,coinaddr); + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) + { + txid = it->first.txhash; + vout = (int32_t)it->first.index; + if ( (nValue= it->second.satoshis) < threshold ) + continue; + if ( GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 0 && vout < numvouts && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 && myIsutxo_spentinmempool(txid,vout) == 0 ) + { + if ( (funcid= DecodeMaramaraCoinbaseOpRet(tx.vout[numvouts-1].scriptPubKey,pk,ht,unlockht)) == 'C' || funcid == 'P' || funcid == 'L' ) + { + if ( unlockht < refunlockht ) + { + mtx.vin.push_back(CTxIn(txid,vout,CScript())); + //fprintf(stderr,"merge CC vout %s/v%d %.8f unlockht.%d < ref.%d\n",txid.GetHex().c_str(),vout,(double)nValue/COIN,unlockht,refunlockht); + inputsum += nValue; + remains -= nValue; + if ( inputsum >= amount + txfee ) + { + //fprintf(stderr,"inputsum %.8f >= amount %.8f, update amount\n",(double)inputsum/COIN,(double)amount/COIN); + amount = inputsum - txfee; + break; + } + } + } + } + } + } + if ( inputsum >= amount+txfee ) + { + if ( inputsum > amount+txfee ) + { + change = (inputsum - amount); + mtx.vout.push_back(CTxOut(change,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + } + rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraCoinbaseOpret('L',height,mypk)); + if ( rawtx.size() == 0 ) + errorstr = (char *)"couldnt finalize CCtx"; + else + { + result.push_back(Pair("result",(char *)"success")); + result.push_back(Pair("rawtx",rawtx)); + return(result); + } + } else errorstr = (char *)"insufficient funds"; + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",errorstr)); + return(result); +} + +int32_t MarmaraSignature(uint8_t *utxosig,CMutableTransaction &mtx) +{ + uint256 txid,hashBlock; uint8_t *ptr; int32_t i,siglen,vout,numvouts; CTransaction tx; std::string rawtx; CPubKey mypk; std::vector pubkeys; struct CCcontract_info *cp,C; uint64_t txfee; + txfee = 10000; + vout = mtx.vin[0].prevout.n; + if ( GetTransaction(mtx.vin[0].prevout.hash,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 1 && vout < numvouts ) + { + cp = CCinit(&C,EVAL_MARMARA); + mypk = pubkey2pk(Mypubkey()); + pubkeys.push_back(mypk); + rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,tx.vout[numvouts - 1].scriptPubKey,pubkeys); + if ( rawtx.size() > 0 ) + { + siglen = mtx.vin[0].scriptSig.size(); + ptr = &mtx.vin[0].scriptSig[0]; + for (i=0; i from utxo making change + +UniValue MarmaraSettlement(uint64_t txfee,uint256 refbatontxid) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + UniValue result(UniValue::VOBJ),a(UniValue::VARR); std::vector creditloop; uint256 batontxid,createtxid,refcreatetxid,hashBlock; uint8_t funcid; int32_t numerrs=0,i,n,numvouts,matures,refmatures,height; int64_t amount,refamount,remaining,inputsum,change; CPubKey Marmarapk,mypk,pk; std::string currency,refcurrency,rawtx; CTransaction tx,batontx; char coinaddr[64],myCCaddr[64],destaddr[64],batonCCaddr[64],str[2],txidaddr[64]; std::vector pubkeys; struct CCcontract_info *cp,C; + if ( txfee == 0 ) + txfee = 10000; + cp = CCinit(&C,EVAL_MARMARA); + mypk = pubkey2pk(Mypubkey()); + Marmarapk = GetUnspendable(cp,0); + remaining = change = 0; + height = chainActive.LastTip()->GetHeight(); + if ( (n= MarmaraGetbatontxid(creditloop,batontxid,refbatontxid)) > 0 ) + { + if ( GetTransaction(batontxid,batontx,hashBlock,false) != 0 && (numvouts= batontx.vout.size()) > 1 ) + { + if ( (funcid= MarmaraDecodeLoopOpret(batontx.vout[numvouts-1].scriptPubKey,refcreatetxid,pk,refamount,refmatures,refcurrency)) != 0 ) + { + if ( refcreatetxid != creditloop[0] ) + { + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"invalid refcreatetxid, setting to creditloop[0]")); + return(result); + } + else if ( chainActive.LastTip()->GetHeight() < refmatures ) + { + fprintf(stderr,"doesnt mature for another %d blocks\n",refmatures - chainActive.LastTip()->GetHeight()); + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"cant settle immature creditloop")); + return(result); + } + else if ( (refmatures & 1) == 0 ) + { + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"cant automatic settle even maturity heights")); + return(result); + } + else if ( n < 1 ) + { + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"creditloop too short")); + return(result); + } + remaining = refamount; + GetCCaddress(cp,myCCaddr,Mypubkey()); + Getscriptaddress(batonCCaddr,batontx.vout[0].scriptPubKey); + if ( strcmp(myCCaddr,batonCCaddr) == 0 ) + { + mtx.vin.push_back(CTxIn(n == 1 ? batontxid : creditloop[1],1,CScript())); // issuance marker + pubkeys.push_back(Marmarapk); + mtx.vin.push_back(CTxIn(batontxid,0,CScript())); + pubkeys.push_back(mypk); + for (i=1; i 1 ) + { + if ( (funcid= MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,createtxid,pk,amount,matures,currency)) != 0 ) + { + GetCCaddress1of2(cp,coinaddr,Marmarapk,pk); + if ( (inputsum= AddMarmarainputs(mtx,pubkeys,coinaddr,remaining,MARMARA_VINS)) >= remaining ) + { + change = (inputsum - remaining); + mtx.vout.push_back(CTxOut(amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + if ( change > txfee ) + mtx.vout.push_back(MakeCC1of2vout(EVAL_MARMARA,change,Marmarapk,pk)); + rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraLoopOpret('S',createtxid,mypk,0,refmatures,currency),pubkeys); + result.push_back(Pair("result",(char *)"success")); + result.push_back(Pair("rawtx",rawtx)); + return(result); + } else remaining -= inputsum; + if ( mtx.vin.size() >= CC_MAXVINS - MARMARA_VINS ) + break; + } else fprintf(stderr,"null funcid for creditloop[%d]\n",i); + } else fprintf(stderr,"couldnt get creditloop[%d]\n",i); + } + if ( refamount - remaining > 2*txfee ) + { + mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(CCtxidaddr(txidaddr,createtxid))) << OP_CHECKSIG)); // failure marker + if ( refamount-remaining > 3*txfee ) + mtx.vout.push_back(CTxOut(refamount-remaining-2*txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraLoopOpret('D',createtxid,mypk,-remaining,refmatures,currency),pubkeys); + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"insufficient funds")); + result.push_back(Pair("rawtx",rawtx)); + result.push_back(Pair("remaining",ValueFromAmount(remaining))); + } + else + { + // jl777: maybe fund a txfee to report no funds avail + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"no funds available at all")); + } + } + else + { + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"this node does not have the baton")); + result.push_back(Pair("myCCaddr",myCCaddr)); + result.push_back(Pair("batonCCaddr",batonCCaddr)); + } + } + else + { + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"couldnt get batontxid opret")); + } + } + else + { + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"couldnt find batontxid")); + } + } + else + { + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"couldnt get creditloop")); + } + return(result); +} + +int32_t MarmaraGetCreditloops(int64_t &totalamount,std::vector &issuances,int64_t &totalclosed,std::vector &closed,struct CCcontract_info *cp,int32_t firstheight,int32_t lastheight,int64_t minamount,int64_t maxamount,CPubKey refpk,std::string refcurrency) +{ + char coinaddr[64]; CPubKey Marmarapk,senderpk; int64_t amount; uint256 createtxid,txid,hashBlock; CTransaction tx; int32_t numvouts,vout,matures,n=0; std::string currency; + std::vector > unspentOutputs; + Marmarapk = GetUnspendable(cp,0); + GetCCaddress(cp,coinaddr,Marmarapk); + SetCCunspents(unspentOutputs,coinaddr); + // do all txid, conditional on spent/unspent + //fprintf(stderr,"check coinaddr.(%s)\n",coinaddr); + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) + { + txid = it->first.txhash; + vout = (int32_t)it->first.index; + //fprintf(stderr,"txid.%s/v%d\n",txid.GetHex().c_str(),vout); + if ( vout == 1 && GetTransaction(txid,tx,hashBlock,false) != 0 ) + { + if ( tx.IsCoinBase() == 0 && (numvouts= tx.vout.size()) > 2 && tx.vout[numvouts - 1].nValue == 0 ) + { + if ( MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,createtxid,senderpk,amount,matures,currency) == 'I' ) + { + n++; + if ( currency == refcurrency && matures >= firstheight && matures <= lastheight && amount >= minamount && amount <= maxamount && (refpk.size() == 0 || senderpk == refpk) ) + { + issuances.push_back(txid); + totalamount += amount; + } + } + } + } else fprintf(stderr,"error getting tx\n"); + } + return(n); +} + +UniValue MarmaraReceive(uint64_t txfee,CPubKey senderpk,int64_t amount,std::string currency,int32_t matures,uint256 batontxid,bool automaticflag) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + UniValue result(UniValue::VOBJ); CPubKey mypk; struct CCcontract_info *cp,C; std::string rawtx; char *errorstr=0; uint256 createtxid; int64_t batonamount; int32_t needbaton = 0; + cp = CCinit(&C,EVAL_MARMARA); + if ( txfee == 0 ) + txfee = 10000; + if ( automaticflag != 0 && (matures & 1) == 0 ) + matures++; + else if ( automaticflag == 0 && (matures & 1) != 0 ) + matures++; + mypk = pubkey2pk(Mypubkey()); + memset(&createtxid,0,sizeof(createtxid)); + if ( batontxid != zeroid && MarmaraGetcreatetxid(createtxid,batontxid) < 0 ) + errorstr = (char *)"cant get createtxid from batontxid"; + else if ( currency != "MARMARA" ) + errorstr = (char *)"for now, only MARMARA loops are supported"; + else if ( amount <= txfee ) + errorstr = (char *)"amount must be for more than txfee"; + else if ( matures <= chainActive.LastTip()->GetHeight() ) + errorstr = (char *)"it must mature in the future"; + if ( errorstr == 0 ) + { + if ( batontxid != zeroid ) + batonamount = txfee; + else batonamount = 2*txfee; + if ( AddNormalinputs(mtx,mypk,batonamount + txfee,1) > 0 ) + { + errorstr = (char *)"couldnt finalize CCtx"; + mtx.vout.push_back(MakeCC1vout(EVAL_MARMARA,batonamount,senderpk)); + rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraLoopOpret('R',createtxid,senderpk,amount,matures,currency)); + if ( rawtx.size() > 0 ) + errorstr = 0; + } else errorstr = (char *)"dont have enough normal inputs for 2*txfee"; + } + if ( rawtx.size() == 0 || errorstr != 0 ) + { + result.push_back(Pair("result","error")); + if ( errorstr != 0 ) + result.push_back(Pair("error",errorstr)); + } + else + { + result.push_back(Pair("result",(char *)"success")); + result.push_back(Pair("rawtx",rawtx)); + result.push_back(Pair("funcid","R")); + result.push_back(Pair("createtxid",createtxid.GetHex())); + if ( batontxid != zeroid ) + result.push_back(Pair("batontxid",batontxid.GetHex())); + result.push_back(Pair("senderpk",HexStr(senderpk))); + result.push_back(Pair("amount",ValueFromAmount(amount))); + result.push_back(Pair("matures",matures)); + result.push_back(Pair("currency",currency)); + } + return(result); +} + +UniValue MarmaraIssue(uint64_t txfee,uint8_t funcid,CPubKey receiverpk,int64_t amount,std::string currency,int32_t matures,uint256 approvaltxid,uint256 batontxid) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + UniValue result(UniValue::VOBJ); CPubKey mypk,Marmarapk; struct CCcontract_info *cp,C; std::string rawtx; uint256 createtxid; char *errorstr=0; + cp = CCinit(&C,EVAL_MARMARA); + if ( txfee == 0 ) + txfee = 10000; + // make sure less than maxlength + Marmarapk = GetUnspendable(cp,0); + mypk = pubkey2pk(Mypubkey()); + if ( MarmaraGetcreatetxid(createtxid,approvaltxid) < 0 ) + errorstr = (char *)"cant get createtxid from approvaltxid"; + else if ( currency != "MARMARA" ) + errorstr = (char *)"for now, only MARMARA loops are supported"; + else if ( amount <= txfee ) + errorstr = (char *)"amount must be for more than txfee"; + else if ( matures <= chainActive.LastTip()->GetHeight() ) + errorstr = (char *)"it must mature in the future"; + if ( errorstr == 0 ) + { + mtx.vin.push_back(CTxIn(approvaltxid,0,CScript())); + if ( funcid == 'T' ) + mtx.vin.push_back(CTxIn(batontxid,0,CScript())); + if ( funcid == 'I' || AddNormalinputs(mtx,mypk,txfee,1) > 0 ) + { + errorstr = (char *)"couldnt finalize CCtx"; + mtx.vout.push_back(MakeCC1vout(EVAL_MARMARA,txfee,receiverpk)); + if ( funcid == 'I' ) + mtx.vout.push_back(MakeCC1vout(EVAL_MARMARA,txfee,Marmarapk)); + rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraLoopOpret(funcid,createtxid,receiverpk,amount,matures,currency)); + if ( rawtx.size() > 0 ) + errorstr = 0; + } else errorstr = (char *)"dont have enough normal inputs for 2*txfee"; + } + if ( rawtx.size() == 0 || errorstr != 0 ) + { + result.push_back(Pair("result","error")); + if ( errorstr != 0 ) + result.push_back(Pair("error",errorstr)); + } + else + { + result.push_back(Pair("result",(char *)"success")); + result.push_back(Pair("rawtx",rawtx)); + char str[2]; str[0] = funcid, str[1] = 0; + result.push_back(Pair("funcid",str)); + result.push_back(Pair("createtxid",createtxid.GetHex())); + result.push_back(Pair("approvaltxid",approvaltxid.GetHex())); + if ( funcid == 'T' ) + result.push_back(Pair("batontxid",batontxid.GetHex())); + result.push_back(Pair("receiverpk",HexStr(receiverpk))); + result.push_back(Pair("amount",ValueFromAmount(amount))); + result.push_back(Pair("matures",matures)); + result.push_back(Pair("currency",currency)); + } + return(result); +} + +UniValue MarmaraCreditloop(uint256 txid) +{ + UniValue result(UniValue::VOBJ),a(UniValue::VARR); std::vector creditloop; uint256 batontxid,createtxid,refcreatetxid,hashBlock; uint8_t funcid; int32_t numerrs=0,i,n,numvouts,matures,refmatures; int64_t amount,refamount; CPubKey pk; std::string currency,refcurrency; CTransaction tx; char coinaddr[64],myCCaddr[64],destaddr[64],batonCCaddr[64],str[2]; struct CCcontract_info *cp,C; + cp = CCinit(&C,EVAL_MARMARA); + if ( (n= MarmaraGetbatontxid(creditloop,batontxid,txid)) > 0 ) + { + if ( GetTransaction(batontxid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 1 ) + { + result.push_back(Pair("result",(char *)"success")); + Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(Mypubkey())) << OP_CHECKSIG); + result.push_back(Pair("myaddress",coinaddr)); + GetCCaddress(cp,myCCaddr,Mypubkey()); + result.push_back(Pair("myCCaddress",myCCaddr)); + if ( (funcid= MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,refcreatetxid,pk,refamount,refmatures,refcurrency)) != 0 ) + { + str[0] = funcid, str[1] = 0; + result.push_back(Pair("funcid",str)); + result.push_back(Pair("currency",refcurrency)); + if ( funcid == 'S' ) + { + refcreatetxid = creditloop[0]; + result.push_back(Pair("settlement",batontxid.GetHex())); + result.push_back(Pair("createtxid",refcreatetxid.GetHex())); + result.push_back(Pair("remainder",ValueFromAmount(refamount))); + result.push_back(Pair("settled",refmatures)); + result.push_back(Pair("pubkey",HexStr(pk))); + Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG); + result.push_back(Pair("coinaddr",coinaddr)); + result.push_back(Pair("collected",ValueFromAmount(tx.vout[0].nValue))); + Getscriptaddress(destaddr,tx.vout[0].scriptPubKey); + if ( strcmp(coinaddr,destaddr) != 0 ) + { + result.push_back(Pair("destaddr",destaddr)); + numerrs++; + } + refamount = -1; + } + else if ( funcid == 'D' ) + { + refcreatetxid = creditloop[0]; + result.push_back(Pair("settlement",batontxid.GetHex())); + result.push_back(Pair("createtxid",refcreatetxid.GetHex())); + result.push_back(Pair("remainder",ValueFromAmount(refamount))); + result.push_back(Pair("settled",refmatures)); + Getscriptaddress(destaddr,tx.vout[0].scriptPubKey); + result.push_back(Pair("txidaddr",destaddr)); + if ( tx.vout.size() > 1 ) + result.push_back(Pair("collected",ValueFromAmount(tx.vout[1].nValue))); + } + else + { + result.push_back(Pair("batontxid",batontxid.GetHex())); + result.push_back(Pair("createtxid",refcreatetxid.GetHex())); + result.push_back(Pair("amount",ValueFromAmount(refamount))); + result.push_back(Pair("matures",refmatures)); + if ( refcreatetxid != creditloop[0] ) + { + fprintf(stderr,"invalid refcreatetxid, setting to creditloop[0]\n"); + refcreatetxid = creditloop[0]; + numerrs++; + } + result.push_back(Pair("batonpk",HexStr(pk))); + Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG); + result.push_back(Pair("batonaddr",coinaddr)); + GetCCaddress(cp,batonCCaddr,pk); + result.push_back(Pair("batonCCaddr",batonCCaddr)); + Getscriptaddress(coinaddr,tx.vout[0].scriptPubKey); + if ( strcmp(coinaddr,batonCCaddr) != 0 ) + { + result.push_back(Pair("vout0address",coinaddr)); + numerrs++; + } + if ( strcmp(myCCaddr,coinaddr) == 0 ) + result.push_back(Pair("ismine",1)); + else result.push_back(Pair("ismine",0)); + } + for (i=0; i 1 ) + { + if ( (funcid= MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,createtxid,pk,amount,matures,currency)) != 0 ) + { + UniValue obj(UniValue::VOBJ); + obj.push_back(Pair("txid",creditloop[i].GetHex())); + str[0] = funcid, str[1] = 0; + obj.push_back(Pair("funcid",str)); + if ( funcid == 'R' && createtxid == zeroid ) + { + createtxid = creditloop[i]; + obj.push_back(Pair("issuerpk",HexStr(pk))); + Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG); + obj.push_back(Pair("issueraddr",coinaddr)); + GetCCaddress(cp,coinaddr,pk); + obj.push_back(Pair("issuerCCaddr",coinaddr)); + } + else + { + obj.push_back(Pair("receiverpk",HexStr(pk))); + Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG); + obj.push_back(Pair("receiveraddr",coinaddr)); + GetCCaddress(cp,coinaddr,pk); + obj.push_back(Pair("receiverCCaddr",coinaddr)); + } + Getscriptaddress(destaddr,tx.vout[0].scriptPubKey); + if ( strcmp(destaddr,coinaddr) != 0 ) + { + obj.push_back(Pair("vout0address",destaddr)); + numerrs++; + } + if ( i == 0 && refamount < 0 ) + { + refamount = amount; + refmatures = matures; + result.push_back(Pair("amount",ValueFromAmount(refamount))); + result.push_back(Pair("matures",refmatures)); + } + if ( createtxid != refcreatetxid || amount != refamount || matures != refmatures || currency != refcurrency ) + { + numerrs++; + obj.push_back(Pair("objerror",(char *)"mismatched createtxid or amount or matures or currency")); + obj.push_back(Pair("createtxid",createtxid.GetHex())); + obj.push_back(Pair("amount",ValueFromAmount(amount))); + obj.push_back(Pair("matures",matures)); + obj.push_back(Pair("currency",currency)); + } + a.push_back(obj); + } + } + } + result.push_back(Pair("n",n)); + result.push_back(Pair("numerrors",numerrs)); + result.push_back(Pair("creditloop",a)); + } + else + { + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"couldnt get batontxid opret")); + } + } + else + { + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"couldnt find batontxid")); + } + } + else + { + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"couldnt get creditloop")); + } + return(result); +} + +UniValue MarmaraPoolPayout(uint64_t txfee,int32_t firstheight,double perc,char *jsonstr) // [[pk0, shares0], [pk1, shares1], ...] +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + UniValue result(UniValue::VOBJ),a(UniValue::VARR); cJSON *item,*array; std::string rawtx; int32_t i,n; uint8_t buf[33]; CPubKey Marmarapk,pk,poolpk; int64_t payout,poolfee=0,total,totalpayout=0; double poolshares,share,shares = 0.; char *pkstr,*errorstr=0; struct CCcontract_info *cp,C; + poolpk = pubkey2pk(Mypubkey()); + if ( txfee == 0 ) + txfee = 10000; + cp = CCinit(&C,EVAL_MARMARA); + Marmarapk = GetUnspendable(cp,0); + if ( (array= cJSON_Parse(jsonstr)) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; i, ]"; + break; + } + } + if ( errorstr == 0 && shares > SMALLVAL ) + { + shares += shares * perc; + if ( (total= AddMarmaraCoinbases(cp,mtx,firstheight,poolpk,60)) > 0 ) + { + for (i=0; i SMALLVAL ) + { + payout = (share * (total - txfee)) / shares; + if ( payout > 0 ) + { + if ( (pkstr= jstr(jitem(item,0),0)) != 0 && strlen(pkstr) == 66 ) + { + UniValue x(UniValue::VOBJ); + totalpayout += payout; + decode_hex(buf,33,pkstr); + mtx.vout.push_back(MakeCC1of2vout(EVAL_MARMARA,payout,Marmarapk,buf2pk(buf))); + x.push_back(Pair(pkstr, (double)payout/COIN)); + a.push_back(x); + } + } + } + } + if ( totalpayout > 0 && total > totalpayout-txfee ) + { + poolfee = (total - totalpayout - txfee); + mtx.vout.push_back(MakeCC1of2vout(EVAL_MARMARA,poolfee,Marmarapk,poolpk)); + } + rawtx = FinalizeCCTx(0,cp,mtx,poolpk,txfee,MarmaraCoinbaseOpret('P',firstheight,poolpk)); + if ( rawtx.size() == 0 ) + errorstr = (char *)"couldnt finalize CCtx"; + } else errorstr = (char *)"couldnt find any coinbases to payout"; + } + else if ( errorstr == 0 ) + errorstr = (char *)"no valid shares submitted"; + free(array); + } else errorstr = (char *)"couldnt parse poolshares jsonstr"; + if ( rawtx.size() == 0 || errorstr != 0 ) + { + result.push_back(Pair("result","error")); + if ( errorstr != 0 ) + result.push_back(Pair("error",errorstr)); + } + else + { + result.push_back(Pair("result",(char *)"success")); + result.push_back(Pair("rawtx",rawtx)); + if ( totalpayout > 0 && total > totalpayout-txfee ) + { + result.push_back(Pair("firstheight",firstheight)); + result.push_back(Pair("lastheight",((firstheight / MARMARA_GROUPSIZE)+1) * MARMARA_GROUPSIZE - 1)); + result.push_back(Pair("total",ValueFromAmount(total))); + result.push_back(Pair("totalpayout",ValueFromAmount(totalpayout))); + result.push_back(Pair("totalshares",shares)); + result.push_back(Pair("poolfee",ValueFromAmount(poolfee))); + result.push_back(Pair("perc",ValueFromAmount((int64_t)(100. * (double)poolfee/totalpayout * COIN)))); + result.push_back(Pair("payouts",a)); + } + } + return(result); +} + +// get all tx, constrain by vout, issuances[] and closed[] + +UniValue MarmaraInfo(CPubKey refpk,int32_t firstheight,int32_t lastheight,int64_t minamount,int64_t maxamount,std::string currency) +{ + CMutableTransaction mtx; std::vector pubkeys; + UniValue result(UniValue::VOBJ),a(UniValue::VARR),b(UniValue::VARR); int32_t i,n,matches; int64_t totalclosed=0,totalamount=0; std::vector issuances,closed; char coinaddr[64]; + CPubKey Marmarapk; struct CCcontract_info *cp,C; + cp = CCinit(&C,EVAL_MARMARA); + Marmarapk = GetUnspendable(cp,0); + result.push_back(Pair("result","success")); + Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(Mypubkey())) << OP_CHECKSIG); + result.push_back(Pair("myaddress",coinaddr)); + result.push_back(Pair("normal",ValueFromAmount(CCaddress_balance(coinaddr)))); + + GetCCaddress1of2(cp,coinaddr,Marmarapk,Mypubkey()); + result.push_back(Pair("myCCactivated",coinaddr)); + result.push_back(Pair("activated",ValueFromAmount(CCaddress_balance(coinaddr)))); + result.push_back(Pair("activated16",ValueFromAmount(AddMarmarainputs(mtx,pubkeys,coinaddr,0,MARMARA_VINS)))); + + GetCCaddress(cp,coinaddr,Mypubkey()); + result.push_back(Pair("myCCaddress",coinaddr)); + result.push_back(Pair("CCutxos",ValueFromAmount(CCaddress_balance(coinaddr)))); + + if ( refpk.size() == 33 ) + result.push_back(Pair("issuer",HexStr(refpk))); + if ( currency.size() == 0 ) + currency = (char *)"MARMARA"; + if ( firstheight <= lastheight ) + firstheight = 0, lastheight = (1 << 30); + if ( minamount <= maxamount ) + minamount = 0, maxamount = (1LL << 60); + result.push_back(Pair("firstheight",firstheight)); + result.push_back(Pair("lastheight",lastheight)); + result.push_back(Pair("minamount",ValueFromAmount(minamount))); + result.push_back(Pair("maxamount",ValueFromAmount(maxamount))); + result.push_back(Pair("currency",currency)); + if ( (n= MarmaraGetCreditloops(totalamount,issuances,totalclosed,closed,cp,firstheight,lastheight,minamount,maxamount,refpk,currency)) > 0 ) + { + result.push_back(Pair("n",n)); + matches = (int32_t)issuances.size(); + result.push_back(Pair("pending",matches)); + for (i=0; i vopret; uint8_t *script,e,f,funcid; GetOpReturnData(scriptPubKey,vopret); script = (uint8_t *)vopret.data(); - if ( script[0] == EVAL_ORACLES ) + if ( vopret.size() > 2 && script[0] == EVAL_ORACLES ) { if ( script[1] == 'C' ) { @@ -133,7 +133,7 @@ uint8_t DecodeOraclesOpRet(const CScript &scriptPubKey,uint256 &oracletxid,CPubK std::vector vopret; uint8_t *script,e,f; GetOpReturnData(scriptPubKey,vopret); script = (uint8_t *)vopret.data(); - if ( vopret.size() > 1 && script[0] == EVAL_ORACLES ) + if ( vopret.size() > 2 && script[0] == EVAL_ORACLES ) { if (script[0] == EVAL_ORACLES && (script[1]== 'R' || script[1] == 'S') && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> oracletxid; ss >> pk; ss >> num)!=0) return(f); @@ -154,7 +154,7 @@ uint8_t DecodeOraclesData(const CScript &scriptPubKey,uint256 &oracletxid,uint25 std::vector vopret; uint8_t *script,e,f; GetOpReturnData(scriptPubKey,vopret); script = (uint8_t *)vopret.data(); - if ( vopret.size() > 1 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> oracletxid; ss >> batontxid; ss >> pk; ss >> data) != 0 ) + if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> oracletxid; ss >> batontxid; ss >> pk; ss >> data) != 0 ) { if ( e == EVAL_ORACLES && f == 'D' ) return(f); @@ -370,7 +370,7 @@ int32_t oracle_format(uint256 *hashp,int64_t *valp,char *str,uint8_t fmt,uint8_t { for (i=0; i data,std::string format) +{ + int64_t offset=0,len=0; char fmt; + + for (int i=0; idata.size()-offset) return (0); + if (fmt=='S' || fmt=='s') + { + for (int j=offset;j127) return (0); + } + offset+=len; + } + if (offset!=data.size()) return (0); + else return (offset); +} + int64_t _correlate_price(int64_t *prices,int32_t n,int64_t price) { int32_t i,count = 0; int64_t diff,threshold = (price >> 8); @@ -729,13 +765,29 @@ int64_t LifetimeOraclesFunds(struct CCcontract_info *cp,uint256 oracletxid,CPubK std::string OracleCreate(int64_t txfee,std::string name,std::string description,std::string format) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk,Oraclespk; struct CCcontract_info *cp,C; + CPubKey mypk,Oraclespk; struct CCcontract_info *cp,C; char fmt; + cp = CCinit(&C,EVAL_ORACLES); if ( name.size() > 32 || description.size() > 4096 || format.size() > 4096 ) { - fprintf(stderr,"name.%d or description.%d is too big\n",(int32_t)name.size(),(int32_t)description.size()); + CCerror = strprintf("name.%d or description.%d is too big",(int32_t)name.size(),(int32_t)description.size()); + fprintf(stderr,"%s\n", CCerror.c_str() ); return(""); - } + } + for(int i = 0; i < format.size(); i++) + { + fmt=format[i]; + switch (fmt) + { + case 's': case 'S': case 'd': case 'D': + case 'c': case 'C': case 't': case 'T': + case 'i': case 'I': case 'l': case 'L': + case 'h': break; + default: CCerror = strprintf("invalid format type"); + fprintf(stderr,"%s\n", CCerror.c_str() ); + return(""); + } + } if ( txfee == 0 ) txfee = 10000; mypk = pubkey2pk(Mypubkey()); @@ -745,6 +797,8 @@ std::string OracleCreate(int64_t txfee,std::string name,std::string description, mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(Oraclespk)) << OP_CHECKSIG)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeOraclesCreateOpRet('C',name,description,format))); } + CCerror = strprintf("error adding normal inputs"); + fprintf(stderr,"%s\n", CCerror.c_str() ); return(""); } @@ -757,7 +811,8 @@ std::string OracleRegister(int64_t txfee,uint256 oracletxid,int64_t datafee) txfee = 10000; if ( datafee < txfee ) { - fprintf(stderr,"datafee must be txfee or more\n"); + CCerror = strprintf("datafee must be txfee or more"); + fprintf(stderr,"%s\n", CCerror.c_str() ); return(""); } mypk = pubkey2pk(Mypubkey()); @@ -769,6 +824,8 @@ std::string OracleRegister(int64_t txfee,uint256 oracletxid,int64_t datafee) mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,batonpk)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeOraclesOpRet('R',oracletxid,mypk,datafee))); } + CCerror = strprintf("error adding normal inputs"); + fprintf(stderr,"%s\n", CCerror.c_str() ); return(""); } @@ -787,13 +844,17 @@ std::string OracleSubscribe(int64_t txfee,uint256 oracletxid,CPubKey publisher,i mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(markerpubkey)) << OP_CHECKSIG)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeOraclesOpRet('S',oracletxid,mypk,amount))); } + CCerror = strprintf("error adding normal inputs"); + fprintf(stderr,"%s\n", CCerror.c_str() ); return(""); } std::string OracleData(int64_t txfee,uint256 oracletxid,std::vector data) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CScript pubKey; CPubKey mypk,batonpk; int64_t datafee,inputs,CCchange = 0; struct CCcontract_info *cp,C; uint256 batontxid; char coinaddr[64],batonaddr[64]; std::vector prevdata; + CScript pubKey; CPubKey mypk,batonpk; int64_t offset,datafee,inputs,CCchange = 0; struct CCcontract_info *cp,C; uint256 batontxid,hashBlock; + char coinaddr[64],batonaddr[64]; std::vector prevdata; CTransaction tx; std::string name,description,format; int32_t len,numvouts; + cp = CCinit(&C,EVAL_ORACLES); mypk = pubkey2pk(Mypubkey()); if ( data.size() > 8192 ) @@ -808,6 +869,30 @@ std::string OracleData(int64_t txfee,uint256 oracletxid,std::vector da fprintf(stderr,"%s\n", CCerror.c_str() ); return(""); } + if ( GetTransaction(oracletxid,tx,hashBlock,false) != 0 && (numvouts=tx.vout.size()) > 0 ) + { + if ( DecodeOraclesCreateOpRet(tx.vout[numvouts-1].scriptPubKey,name,description,format) == 'C' ) + { + if (oracle_parse_data_format(data,format)==0) + { + CCerror = strprintf("data does not match length or content format specification"); + fprintf(stderr,"%s\n", CCerror.c_str() ); + return(""); + } + } + else + { + CCerror = strprintf("invalid oracle txid opret data"); + fprintf(stderr,"%s\n", CCerror.c_str() ); + return(""); + } + } + else + { + CCerror = strprintf("invalid oracle txid"); + fprintf(stderr,"%s\n", CCerror.c_str() ); + return(""); + } if ( txfee == 0 ) txfee = 10000; GetCCaddress(cp,coinaddr,mypk); @@ -831,7 +916,7 @@ std::string OracleData(int64_t txfee,uint256 oracletxid,std::vector da fprintf(stderr,"%s\n", CCerror.c_str() ); } } else { - CCerror = strprintf("couldnt add normal inputs\n"); + CCerror = strprintf("couldnt add normal inputs"); fprintf(stderr,"%s\n", CCerror.c_str() ); } return(""); @@ -855,7 +940,9 @@ UniValue OracleFormat(uint8_t *data,int32_t datalen,char *format,int32_t formatl UniValue OracleDataSamples(uint256 reforacletxid,uint256 batontxid,int32_t num) { - UniValue result(UniValue::VOBJ),a(UniValue::VARR); CTransaction tx,oracletx; uint256 hashBlock,btxid,oracletxid; CPubKey pk; std::string name,description,format; int32_t numvouts,n=0; std::vector data; char *formatstr = 0; + UniValue result(UniValue::VOBJ),a(UniValue::VARR); CTransaction tx,oracletx; uint256 hashBlock,btxid,oracletxid; + CPubKey pk; std::string name,description,format; int32_t numvouts,n=0; std::vector data; char *formatstr = 0; + result.push_back(Pair("result","success")); if ( GetTransaction(reforacletxid,oracletx,hashBlock,false) != 0 && (numvouts=oracletx.vout.size()) > 0 ) { diff --git a/src/cc/payments.cpp b/src/cc/payments.cpp index 70f1ab914..859a5ba3f 100644 --- a/src/cc/payments.cpp +++ b/src/cc/payments.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -75,7 +75,7 @@ bool PaymentsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransacti bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) { int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64]; - return(false); + return eval->Invalid("no validation yet"); std::vector > txids; numvins = tx.vin.size(); numvouts = tx.vout.size(); diff --git a/src/cc/pegs.cpp b/src/cc/pegs.cpp index 403dfb87a..e2893bec8 100644 --- a/src/cc/pegs.cpp +++ b/src/cc/pegs.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -82,7 +82,7 @@ bool PegsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction & bool PegsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) { int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64]; - return(false); + return eval->Invalid("no validation yet"); std::vector > txids; numvins = tx.vin.size(); numvouts = tx.vout.size(); diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp index 50787fd34..369495b1a 100644 --- a/src/cc/prices.cpp +++ b/src/cc/prices.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -89,7 +89,7 @@ uint8_t DecodePricesFundingOpRet(CScript scriptPubKey,CPubKey &planpk,uint256 &o bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) { int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64]; - return(false); + return eval->Invalid("no validation yet"); std::vector > txids; numvins = tx.vin.size(); numvouts = tx.vout.size(); @@ -326,7 +326,11 @@ std::string PricesAddFunding(uint64_t txfee,uint256 refbettoken,uint256 fundingt CCchange = (inputs - amount); mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange,mypk)); // add addr2 - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeAssetOpRet('t',bettoken,zeroid,0,Mypubkey()))); + + std::vector voutTokenPubkeysEmpty; //TODO: add token vout pubkeys + return(FinalizeCCTx(0,cp,mtx,mypk,txfee, + EncodeTokenOpRet(bettoken, voutTokenPubkeysEmpty, + EncodeAssetOpRet('t',/*bettoken,*/zeroid, 0, Mypubkey())))); } else { diff --git a/src/cc/rewards.cpp b/src/cc/rewards.cpp index 7e4626b19..bd5a6d919 100644 --- a/src/cc/rewards.cpp +++ b/src/cc/rewards.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cc/triggers.cpp b/src/cc/triggers.cpp deleted file mode 100644 index ce6f10f58..000000000 --- a/src/cc/triggers.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/****************************************************************************** - * 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. * - * * - ******************************************************************************/ - -#include "CCTriggers.h" - -/* - Triggers CC is a building block CC that allows creation of event -> action processing, where events are defined during trigger creation and actions to be mostly done via payments, but by making payments to other CC contracts, it can be used to invoke other CC contracts - -*/ - -// start of consensus code - -int64_t IsTriggersvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) -{ - char destaddr[64]; - if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) - { - if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 ) - return(tx.vout[v].nValue); - } - return(0); -} - -bool TriggersExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee) -{ - static uint256 zerohash; - CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis; - numvins = tx.vin.size(); - numvouts = tx.vout.size(); - for (i=0; iismyvin)(tx.vin[i].scriptSig) != 0 ) - { - //fprintf(stderr,"vini.%d check mempool\n",i); - if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 ) - return eval->Invalid("cant find vinTx"); - else - { - //fprintf(stderr,"vini.%d check hash and vout\n",i); - if ( hashBlock == zerohash ) - return eval->Invalid("cant Triggers from mempool"); - if ( (assetoshis= IsTriggersvout(cp,vinTx,tx.vin[i].prevout.n)) != 0 ) - inputs += assetoshis; - } - } - } - for (i=0; iInvalid("mismatched inputs != outputs + txfee"); - } - else return(true); -} - -bool TriggersValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) -{ - int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64]; - return(false); - std::vector > txids; - numvins = tx.vin.size(); - numvouts = tx.vout.size(); - preventCCvins = preventCCvouts = -1; - if ( numvouts < 1 ) - return eval->Invalid("no vouts"); - else - { - for (i=0; iInvalid("illegal normal vini"); - } - } - //fprintf(stderr,"check amounts\n"); - if ( TriggersExactAmounts(cp,eval,tx,1,10000) == false ) - { - fprintf(stderr,"Triggersget invalid amount\n"); - return false; - } - else - { - txid = tx.GetHash(); - memcpy(hash,&txid,sizeof(hash)); - retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts); - if ( retval != 0 ) - fprintf(stderr,"Triggersget validated\n"); - else fprintf(stderr,"Triggersget invalid\n"); - return(retval); - } - } -} -// end of consensus code - -// helper functions for rpc calls in rpcwallet.cpp - -int64_t AddTriggersInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs) -{ - // add threshold check - char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t vout,n = 0; - std::vector > unspentOutputs; - GetCCaddress(cp,coinaddr,pk); - SetCCunspents(unspentOutputs,coinaddr); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - // no need to prevent dup - if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) - { - if ( (nValue= IsTriggersvout(cp,vintx,vout)) > 1000000 && myIsutxo_spentinmempool(txid,vout) == 0 ) - { - if ( total != 0 && maxinputs != 0 ) - mtx.vin.push_back(CTxIn(txid,vout,CScript())); - nValue = it->second.satoshis; - totalinputs += nValue; - n++; - if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) - break; - } - } - } - return(totalinputs); -} - -std::string TriggersGet(uint64_t txfee,int64_t nValue) -{ - CMutableTransaction tmpmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk,Triggerspk; int64_t inputs,CCchange=0; struct CCcontract_info *cp,C; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash; - cp = CCinit(&C,EVAL_TRIGGERS); - if ( txfee == 0 ) - txfee = 10000; - Triggerspk = GetUnspendable(cp,0); - mypk = pubkey2pk(Mypubkey()); - if ( (inputs= AddTriggersInputs(cp,mtx,Triggerspk,nValue+txfee,60)) > 0 ) - { - if ( inputs > nValue ) - CCchange = (inputs - nValue - txfee); - if ( CCchange != 0 ) - mtx.vout.push_back(MakeCC1vout(EVAL_TRIGGERS,CCchange,Triggerspk)); - mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - fprintf(stderr,"start at %u\n",(uint32_t)time(NULL)); - j = rand() & 0xfffffff; - for (i=0; i<1000000; i++,j++) - { - tmpmtx = mtx; - rawhex = FinalizeCCTx(-1LL,cp,tmpmtx,mypk,txfee,CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_TRIGGERS << (uint8_t)'G' << j)); - if ( (len= (int32_t)rawhex.size()) > 0 && len < 65536 ) - { - len >>= 1; - decode_hex(buf,len,(char *)rawhex.c_str()); - hash = bits256_doublesha256(0,buf,len); - if ( (hash.bytes[0] & 0xff) == 0 && (hash.bytes[31] & 0xff) == 0 ) - { - fprintf(stderr,"found valid txid after %d iterations %u\n",i,(uint32_t)time(NULL)); - return(rawhex); - } - //fprintf(stderr,"%02x%02x ",hash.bytes[0],hash.bytes[31]); - } - } - fprintf(stderr,"couldnt generate valid txid %u\n",(uint32_t)time(NULL)); - return(""); - } else fprintf(stderr,"cant find Triggers inputs\n"); - return(""); -} - -std::string TriggersFund(uint64_t txfee,int64_t funds) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk,Triggerspk; CScript opret; struct CCcontract_info *cp,C; - cp = CCinit(&C,EVAL_TRIGGERS); - if ( txfee == 0 ) - txfee = 10000; - mypk = pubkey2pk(Mypubkey()); - Triggerspk = GetUnspendable(cp,0); - if ( AddNormalinputs(mtx,mypk,funds+txfee,64) > 0 ) - { - mtx.vout.push_back(MakeCC1vout(EVAL_TRIGGERS,funds,Triggerspk)); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret)); - } - return(""); -} - -UniValue TriggersInfo() -{ - UniValue result(UniValue::VOBJ); char numstr[64]; - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey Triggerspk; struct CCcontract_info *cp,C; int64_t funding; - result.push_back(Pair("result","success")); - result.push_back(Pair("name","Triggers")); - cp = CCinit(&C,EVAL_TRIGGERS); - Triggerspk = GetUnspendable(cp,0); - funding = AddTriggersInputs(cp,mtx,Triggerspk,0,0); - sprintf(numstr,"%.8f",(double)funding/COIN); - result.push_back(Pair("funding",numstr)); - return(result); -} - diff --git a/src/cc/utils.h b/src/cc/utils.h index f0b91962d..39bce0e95 100644 --- a/src/cc/utils.h +++ b/src/cc/utils.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/chain.cpp b/src/chain.cpp index 0d4ac7f2a..43d893620 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "chain.h" using namespace std; diff --git a/src/chain.h b/src/chain.h index 0b6e2b046..49b206480 100644 --- a/src/chain.h +++ b/src/chain.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_CHAIN_H #define BITCOIN_CHAIN_H diff --git a/src/chainparams.cpp b/src/chainparams.cpp index a04e4131a..c7232761b 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "key_io.h" #include "main.h" #include "crypto/equihash.h" @@ -77,11 +92,6 @@ static CBlock CreateGenesisBlock(uint32_t nTime, const uint256& nNonce, const st void *chainparams_commandline(void *ptr); #include "komodo_defs.h" -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; -extern uint32_t ASSETCHAIN_INIT, ASSETCHAINS_MAGIC; -extern int32_t VERUS_BLOCK_POSUNITS, ASSETCHAINS_LWMAPOS, ASSETCHAINS_SAPLING, ASSETCHAINS_OVERWINTER; -extern uint64_t ASSETCHAINS_SUPPLY, ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH, ASSETCHAINS_VERUSHASH; const arith_uint256 maxUint = UintToArith256(uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); @@ -92,7 +102,7 @@ public: strNetworkID = "main"; strCurrencyUnits = "KMD"; - bip44CoinType = 133; // As registered in https://github.com/satoshilabs/slips/blob/master/slip-0044.md (ZCASH, should be VRSC) + bip44CoinType = 141; // As registered in https://github.com/satoshilabs/slips/blob/master/slip-0044.md consensus.fCoinbaseMustBeProtected = false; // true this is only true wuth Verus and enforced after block 12800 consensus.nSubsidySlowStartInterval = 20000; consensus.nSubsidyHalvingInterval = 840000; @@ -215,7 +225,7 @@ void CChainParams::SetCheckpointData(CChainParams::CCheckpointData checkpointDat CChainParams::checkpointData = checkpointData; } -int32_t MAX_BLOCK_SIZE(int32_t height) +int32_t MAX_BLOCK_SIZE(int32_t height) // make sure to change MAX_PROTOCOL_MESSAGE_LENGTH also!!!! { //fprintf(stderr,"MAX_BLOCK_SIZE %d vs. %d\n",height,mainParams.consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight); if ( height <= 0 || (mainParams.consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight > 0 && height >= mainParams.consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight) ) diff --git a/src/chainparams.h b/src/chainparams.h index 566f07f36..ea700c6ca 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_CHAINPARAMS_H #define BITCOIN_CHAINPARAMS_H diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index 475f200e6..4ec957ba1 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "chainparamsbase.h" #include "util.h" diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h index 33765f0fc..94e3a4238 100644 --- a/src/chainparamsbase.h +++ b/src/chainparamsbase.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_CHAINPARAMSBASE_H #define BITCOIN_CHAINPARAMSBASE_H diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h index 4b091457b..e3dac3ca6 100644 --- a/src/chainparamsseeds.h +++ b/src/chainparamsseeds.h @@ -1,3 +1,18 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_CHAINPARAMSSEEDS_H #define BITCOIN_CHAINPARAMSSEEDS_H /** diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index 70fd1e8f2..7fd94e4e7 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "checkpoints.h" #include "chainparams.h" diff --git a/src/checkpoints.h b/src/checkpoints.h index b75da9ef2..1b21755f0 100644 --- a/src/checkpoints.h +++ b/src/checkpoints.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_CHECKPOINTS_H #define BITCOIN_CHECKPOINTS_H diff --git a/src/checkqueue.h b/src/checkqueue.h index 20ba25bb4..fc3cdb610 100644 --- a/src/checkqueue.h +++ b/src/checkqueue.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_CHECKQUEUE_H #define BITCOIN_CHECKQUEUE_H diff --git a/src/clientversion.cpp b/src/clientversion.cpp index 9b523e582..4f004aac2 100644 --- a/src/clientversion.cpp +++ b/src/clientversion.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "clientversion.h" #include "tinyformat.h" diff --git a/src/clientversion.h b/src/clientversion.h index d8117a6ba..36f37f2e2 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_CLIENTVERSION_H #define BITCOIN_CLIENTVERSION_H diff --git a/src/coincontrol.h b/src/coincontrol.h index 3e8de83c3..02d487a4c 100644 --- a/src/coincontrol.h +++ b/src/coincontrol.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_COINCONTROL_H #define BITCOIN_COINCONTROL_H diff --git a/src/coins.cpp b/src/coins.cpp index 656f2c92e..f97ba5eee 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "coins.h" #include "memusage.h" diff --git a/src/coins.h b/src/coins.h index 39d1e22fc..f83fda7d2 100644 --- a/src/coins.h +++ b/src/coins.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_COINS_H #define BITCOIN_COINS_H diff --git a/src/compat.h b/src/compat.h index 27afc8b2a..44b7dcee2 100644 --- a/src/compat.h +++ b/src/compat.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_COMPAT_H #define BITCOIN_COMPAT_H diff --git a/src/compressor.cpp b/src/compressor.cpp index 20c154fc1..e3479474d 100644 --- a/src/compressor.cpp +++ b/src/compressor.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "compressor.h" #include "hash.h" diff --git a/src/compressor.h b/src/compressor.h index 961365d26..f4e4a256d 100644 --- a/src/compressor.h +++ b/src/compressor.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_COMPRESSOR_H #define BITCOIN_COMPRESSOR_H diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index 3f44bcafd..eba39b644 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_CONSENSUS_CONSENSUS_H #define BITCOIN_CONSENSUS_CONSENSUS_H diff --git a/src/consensus/params.h b/src/consensus/params.h index b7dc8b475..946b11c8d 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_CONSENSUS_PARAMS_H #define BITCOIN_CONSENSUS_PARAMS_H diff --git a/src/consensus/upgrades.cpp b/src/consensus/upgrades.cpp index 5f484e949..3cd30399f 100644 --- a/src/consensus/upgrades.cpp +++ b/src/consensus/upgrades.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "consensus/upgrades.h" /** diff --git a/src/consensus/upgrades.h b/src/consensus/upgrades.h index 920ec1ea8..38eadc9ef 100644 --- a/src/consensus/upgrades.h +++ b/src/consensus/upgrades.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef ZCASH_CONSENSUS_UPGRADES_H #define ZCASH_CONSENSUS_UPGRADES_H diff --git a/src/consensus/validation.h b/src/consensus/validation.h index 6c4db4c59..a3d718c05 100644 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_CONSENSUS_VALIDATION_H #define BITCOIN_CONSENSUS_VALIDATION_H diff --git a/src/core_io.h b/src/core_io.h index ba5b4e648..dbf30b9e9 100644 --- a/src/core_io.h +++ b/src/core_io.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_CORE_IO_H #define BITCOIN_CORE_IO_H diff --git a/src/core_read.cpp b/src/core_read.cpp index 4be24f8e0..9817a2165 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "core_io.h" #include "primitives/block.h" diff --git a/src/core_write.cpp b/src/core_write.cpp index 43344656b..780540027 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "core_io.h" #include "key_io.h" diff --git a/src/crosschain.cpp b/src/crosschain.cpp index e9444c607..8b6cb12a4 100644 --- a/src/crosschain.cpp +++ b/src/crosschain.cpp @@ -1,3 +1,18 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "cc/eval.h" #include "crosschain.h" #include "importcoin.h" @@ -199,16 +214,14 @@ cont: */ void CompleteImportTransaction(CTransaction &importTx) { - TxProof proof; - CTransaction burnTx; - std::vector payouts; + TxProof proof; CTransaction burnTx; std::vector payouts; std::vector rawproof; 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)) + if (!UnmarshalBurnTx(burnTx, targetSymbol, &targetCCid, payoutsHash, rawproof)) throw std::runtime_error("Couldn't parse burnTx"); proof = GetCrossChainProof(burnTx.GetHash(), targetSymbol.data(), targetCCid, proof); @@ -284,13 +297,13 @@ bool CheckMoMoM(uint256 kmdNotarisationHash, uint256 momom) * in: txid * out: pair */ -TxProof GetAssetchainProof(uint256 hash) + +TxProof GetAssetchainProof(uint256 hash,CTransaction burnTx) { int nIndex; CBlockIndex* blockIndex; Notarisation nota; std::vector branch; - { uint256 blockHash; CTransaction tx; diff --git a/src/crosschain.h b/src/crosschain.h index 1fbd7603a..b97afde98 100644 --- a/src/crosschain.h +++ b/src/crosschain.h @@ -1,3 +1,18 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef CROSSCHAIN_H #define CROSSCHAIN_H @@ -5,7 +20,7 @@ /* On assetchain */ -TxProof GetAssetchainProof(uint256 hash); +TxProof GetAssetchainProof(uint256 hash,CTransaction burnTx); /* On KMD */ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeight, diff --git a/src/cryptoconditions/include/cryptoconditions.h b/src/cryptoconditions/include/cryptoconditions.h index 71f9cb460..68fedb946 100644 --- a/src/cryptoconditions/include/cryptoconditions.h +++ b/src/cryptoconditions/include/cryptoconditions.h @@ -1,3 +1,18 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include #include diff --git a/src/cryptoconditions/src/anon.c b/src/cryptoconditions/src/anon.c index f3214995b..55d7a3b7f 100644 --- a/src/cryptoconditions/src/anon.c +++ b/src/cryptoconditions/src/anon.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cryptoconditions/src/cryptoconditions.c b/src/cryptoconditions/src/cryptoconditions.c index 11410a3ec..9bbdfbd95 100644 --- a/src/cryptoconditions/src/cryptoconditions.c +++ b/src/cryptoconditions/src/cryptoconditions.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cryptoconditions/src/ed25519.c b/src/cryptoconditions/src/ed25519.c index 4fb3bbb8d..8d73d3cf1 100644 --- a/src/cryptoconditions/src/ed25519.c +++ b/src/cryptoconditions/src/ed25519.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cryptoconditions/src/eval.c b/src/cryptoconditions/src/eval.c index 544f6dd54..99ff1ebf5 100644 --- a/src/cryptoconditions/src/eval.c +++ b/src/cryptoconditions/src/eval.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cryptoconditions/src/include/cJSON.c b/src/cryptoconditions/src/include/cJSON.c index 306bb5b0d..5c99b8cb2 100644 --- a/src/cryptoconditions/src/include/cJSON.c +++ b/src/cryptoconditions/src/include/cJSON.c @@ -20,6 +20,21 @@ THE SOFTWARE. */ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + /* cJSON */ /* JSON parser in C. */ diff --git a/src/cryptoconditions/src/include/cJSON.h b/src/cryptoconditions/src/include/cJSON.h index 1e388137e..2a6139680 100644 --- a/src/cryptoconditions/src/include/cJSON.h +++ b/src/cryptoconditions/src/include/cJSON.h @@ -20,6 +20,21 @@ THE SOFTWARE. */ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef cJSON__h #define cJSON__h diff --git a/src/cryptoconditions/src/include/libbase58.h b/src/cryptoconditions/src/include/libbase58.h index fafe6539f..78f1b4591 100644 --- a/src/cryptoconditions/src/include/libbase58.h +++ b/src/cryptoconditions/src/include/libbase58.h @@ -1,3 +1,18 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef LIBBASE58_H #define LIBBASE58_H diff --git a/src/cryptoconditions/src/internal.h b/src/cryptoconditions/src/internal.h index 41080186e..790e28962 100644 --- a/src/cryptoconditions/src/internal.h +++ b/src/cryptoconditions/src/internal.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cryptoconditions/src/json_rpc.c b/src/cryptoconditions/src/json_rpc.c index 73377af50..150bcb12b 100644 --- a/src/cryptoconditions/src/json_rpc.c +++ b/src/cryptoconditions/src/json_rpc.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cryptoconditions/src/prefix.c b/src/cryptoconditions/src/prefix.c index 626fc5992..45c6d8033 100644 --- a/src/cryptoconditions/src/prefix.c +++ b/src/cryptoconditions/src/prefix.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cryptoconditions/src/preimage.c b/src/cryptoconditions/src/preimage.c index 7c8e56996..9e7fe12f4 100644 --- a/src/cryptoconditions/src/preimage.c +++ b/src/cryptoconditions/src/preimage.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cryptoconditions/src/secp256k1.c b/src/cryptoconditions/src/secp256k1.c index a95895fa4..31bab06e5 100644 --- a/src/cryptoconditions/src/secp256k1.c +++ b/src/cryptoconditions/src/secp256k1.c @@ -1,3 +1,18 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #define _GNU_SOURCE 1 #if __linux diff --git a/src/cryptoconditions/src/threshold.c b/src/cryptoconditions/src/threshold.c index 13c3fdab3..82f0e1b0a 100644 --- a/src/cryptoconditions/src/threshold.c +++ b/src/cryptoconditions/src/threshold.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/cryptoconditions/src/utils.c b/src/cryptoconditions/src/utils.c index 25783ddfc..6a2167119 100644 --- a/src/cryptoconditions/src/utils.c +++ b/src/cryptoconditions/src/utils.c @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/deprecation.cpp b/src/deprecation.cpp index 9b34b1d0f..6005918ec 100644 --- a/src/deprecation.cpp +++ b/src/deprecation.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "deprecation.h" #include "alert.h" diff --git a/src/deprecation.h b/src/deprecation.h index 16484ed5a..427234b4a 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef ZCASH_DEPRECATION_H #define ZCASH_DEPRECATION_H diff --git a/src/fiat/ksb b/src/fiat/ksb new file mode 100755 index 000000000..450c3b3f6 --- /dev/null +++ b/src/fiat/ksb @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=KSB $1 $2 $3 $4 $5 $6 diff --git a/src/fundnotaries b/src/fundnotaries deleted file mode 100755 index cd6841966..000000000 --- a/src/fundnotaries +++ /dev/null @@ -1,705 +0,0 @@ -./komodo-cli -ac_name=REVS sendtoaddress RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RHPGxpiwRHP4dKZXjYPdpon1nCto7qVE8s 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RLQoAcs1RaqW1xfN2NJwoZWW5twexPhuGB 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RXF3aHUaWDUY4fRRYmBNALoHWkgSQCiJ4f 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RL2SkPSCGMvcHqZ56ErfMxbQGdA4nk7MZp 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RFssbc211PJdVy1bvcvAG5X2N4ovPAoy5o 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RNoz2DKPZ2ppMxgYx5tce9sjZBHefvPvNB 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RVxtoUT9CXbC1LdhztNAf9yR5ySnFnSPQh 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress R9XBrbj8iKkwy9M4erUqRaBinAiZSTXav3 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RSHdRnHHGdPtVej7fiehHBQ6dyTbEM1GHi 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RDW8EDkCkzQ1LA4xbVUoAERsBVhhYRLXCr 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RAxQTHdsy89tfSXwoce2sHeWrYXmDsMXQq 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RT2k2voy9n8jwppeTTJMQAhvaqA9pc9jHh 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RRvaVyKS59NJWhPp8Pn7mVPGhMuhJJXrdh 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RBpp98VwHx7SFv7dNbw8NY65t14XFq9fVD 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RPjUmFNcWEW9Bu275kPxzRXyWDz6bfQpPD 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RDY2CvzydimY2AtDqSjBAB1eCeogRE55DX 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RUgW6fLfVsLJ87Ng4zJTqNedJSKYQ9ToAf 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RUreYvNjhZYc1vP8cND9Cztpni1pYsigXb 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RHv3wyVnnanG2kSQmLNmjwAQeYRRAptxUy 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RLVwuTM5TitV4Gk79Rja731RwYkAzz7GWn 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RHbxwDa7JT1KJLHDKwb5n3gd8NREErqtQY 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RFDAZ1yCvKPmpqcgzg8r2qQJ8nPPgeoMrB 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RHsZesZXMfkdrsSEper3JWUBKwk29JTFfT 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RPJjzoKPb8idoUCT9XLBkNojNgysjJ5qrE 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RFQNjTfcvSAmf8D83og1NrdHj1wH2fc5X4 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RPknkGAHMwUBvfKQfvw9FyatTZzicSiN4y 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RMqbQz4NPNbG15QBwy9EFvLn4NX5Fa7w5g 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RQipE6ycbVVb9vCkhqrK8PGZs2p5YmiBtg 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RCA8H1npFPW5pnJRzycF8tFEJmn6XZhD4j 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RJD5jRidYW9Cu8qxjg9HDCsx6J3A4wQ4LU 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RQMwcDYMVBx9f4QCFfFk31px8QZP4e8uhA 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RXzsovGBQ3W97xnVC6JnWxXsV4qb7p7iBi 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RLHr8gUm2MZ3EEgDU4EmK7bdn5ZsxLYmnt 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RFTsWSzgKRd5Xa7d287w9eRFeYefKBso6Z 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress REuQ7EoxKeMYk4EGptV6EwdfV9LZXuc44g 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RX1tP6ftwe96p6scgJn4dpgNdHDgyg9R87 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RERp696QtNTeWDfBy3x3QbRwPYN2NxwxfA 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RNZKqUgoAPwWd7wNtuSKP7k1HSJAyPeH4N 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress R9jhJCwgT78pyjnkNuxgH3CE8ekxgT8iwB 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RSCQKVUhihKb13rb5VJwXsbSY6pdRPUZ6V 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RDVqM6t5xZw9jbYXEw2CJgkiSbrHBHiKR3 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RSSNgf98kiMGUxs55DvhNnumyxVudd2KQQ 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RXqdRmv7n9hygf9C7f7vj4VQyNR9RvzXss 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RE3P8D8rcWZBeKmT8DURPdezW87MU5Ho3F 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RS3v2u6d4SJ1ujLz7CHNSFLSmxn6Tx6mJp 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RREc88bQzxHCvzqErPDnTQH2Qg5yUtjbyp 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RJ9wAk3ZNrFwdso1RVbwASiqqQaDNyKjd2 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RVKtRKozg8RKvEYCumMD43fCU6f212M5RD 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RCvsbvzCwA1AaxeoYVSL9Q3BdnybEWfXaH 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RXtADsErZLmsGhNyQdW2DekHMGZ23cLrav 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RYGrWs5b8CVFFpxGpjiBaMwfYV9X5UqFaB 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RHASfhhM6bvDFakRDqkzA2wc3V4R4oNmXi 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RATaU3jjn4RwHK61YWoJ4eg7Eggk3puZW8 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RXbb9PkefXcsqq8wqiUZZUuq8e3p29mw1G 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RDY9LJZTEJ9FsvugUuD69gceA98uqan5XL 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress R9tjkpdNbzw6mNfxorb5bvTPmsuon5aLrC 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RT2JyVts5tb1prC7KYykmznrqw7VXJo1HB 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RFHRWQ5pAXNfmudHfxdxw3Wo8yFGoeDn6z 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RTw3vi3dGa9n8LLbKvk7jDAwLdt3A5ET7a 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RQeuhk4KcPM3F5hefwTBWezDdcktSGQQSq 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress R9TGdzN25MgdRkYfsYfxZWzHCLVCyWFAei 0.010000 -./komodo-cli -ac_name=REVS sendtoaddress RDYsrWBZkYSWhRDupGRrfGqrVnFtK9hJGC 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RHPGxpiwRHP4dKZXjYPdpon1nCto7qVE8s 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RLQoAcs1RaqW1xfN2NJwoZWW5twexPhuGB 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RXF3aHUaWDUY4fRRYmBNALoHWkgSQCiJ4f 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RL2SkPSCGMvcHqZ56ErfMxbQGdA4nk7MZp 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RFssbc211PJdVy1bvcvAG5X2N4ovPAoy5o 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RNoz2DKPZ2ppMxgYx5tce9sjZBHefvPvNB 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RVxtoUT9CXbC1LdhztNAf9yR5ySnFnSPQh 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress R9XBrbj8iKkwy9M4erUqRaBinAiZSTXav3 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RSHdRnHHGdPtVej7fiehHBQ6dyTbEM1GHi 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RDW8EDkCkzQ1LA4xbVUoAERsBVhhYRLXCr 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RAxQTHdsy89tfSXwoce2sHeWrYXmDsMXQq 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RT2k2voy9n8jwppeTTJMQAhvaqA9pc9jHh 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RRvaVyKS59NJWhPp8Pn7mVPGhMuhJJXrdh 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RBpp98VwHx7SFv7dNbw8NY65t14XFq9fVD 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RPjUmFNcWEW9Bu275kPxzRXyWDz6bfQpPD 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RDY2CvzydimY2AtDqSjBAB1eCeogRE55DX 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RUgW6fLfVsLJ87Ng4zJTqNedJSKYQ9ToAf 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RUreYvNjhZYc1vP8cND9Cztpni1pYsigXb 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RHv3wyVnnanG2kSQmLNmjwAQeYRRAptxUy 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RLVwuTM5TitV4Gk79Rja731RwYkAzz7GWn 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RHbxwDa7JT1KJLHDKwb5n3gd8NREErqtQY 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RFDAZ1yCvKPmpqcgzg8r2qQJ8nPPgeoMrB 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RHsZesZXMfkdrsSEper3JWUBKwk29JTFfT 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RPJjzoKPb8idoUCT9XLBkNojNgysjJ5qrE 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RFQNjTfcvSAmf8D83og1NrdHj1wH2fc5X4 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RPknkGAHMwUBvfKQfvw9FyatTZzicSiN4y 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RMqbQz4NPNbG15QBwy9EFvLn4NX5Fa7w5g 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RQipE6ycbVVb9vCkhqrK8PGZs2p5YmiBtg 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RCA8H1npFPW5pnJRzycF8tFEJmn6XZhD4j 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RJD5jRidYW9Cu8qxjg9HDCsx6J3A4wQ4LU 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RQMwcDYMVBx9f4QCFfFk31px8QZP4e8uhA 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RXzsovGBQ3W97xnVC6JnWxXsV4qb7p7iBi 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RLHr8gUm2MZ3EEgDU4EmK7bdn5ZsxLYmnt 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RFTsWSzgKRd5Xa7d287w9eRFeYefKBso6Z 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress REuQ7EoxKeMYk4EGptV6EwdfV9LZXuc44g 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RX1tP6ftwe96p6scgJn4dpgNdHDgyg9R87 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RERp696QtNTeWDfBy3x3QbRwPYN2NxwxfA 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RNZKqUgoAPwWd7wNtuSKP7k1HSJAyPeH4N 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress R9jhJCwgT78pyjnkNuxgH3CE8ekxgT8iwB 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RSCQKVUhihKb13rb5VJwXsbSY6pdRPUZ6V 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RDVqM6t5xZw9jbYXEw2CJgkiSbrHBHiKR3 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RSSNgf98kiMGUxs55DvhNnumyxVudd2KQQ 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RXqdRmv7n9hygf9C7f7vj4VQyNR9RvzXss 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RE3P8D8rcWZBeKmT8DURPdezW87MU5Ho3F 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RS3v2u6d4SJ1ujLz7CHNSFLSmxn6Tx6mJp 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RREc88bQzxHCvzqErPDnTQH2Qg5yUtjbyp 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RJ9wAk3ZNrFwdso1RVbwASiqqQaDNyKjd2 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RVKtRKozg8RKvEYCumMD43fCU6f212M5RD 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RCvsbvzCwA1AaxeoYVSL9Q3BdnybEWfXaH 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RXtADsErZLmsGhNyQdW2DekHMGZ23cLrav 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RYGrWs5b8CVFFpxGpjiBaMwfYV9X5UqFaB 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RHASfhhM6bvDFakRDqkzA2wc3V4R4oNmXi 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RATaU3jjn4RwHK61YWoJ4eg7Eggk3puZW8 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RXbb9PkefXcsqq8wqiUZZUuq8e3p29mw1G 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RDY9LJZTEJ9FsvugUuD69gceA98uqan5XL 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress R9tjkpdNbzw6mNfxorb5bvTPmsuon5aLrC 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RT2JyVts5tb1prC7KYykmznrqw7VXJo1HB 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RFHRWQ5pAXNfmudHfxdxw3Wo8yFGoeDn6z 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RTw3vi3dGa9n8LLbKvk7jDAwLdt3A5ET7a 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RQeuhk4KcPM3F5hefwTBWezDdcktSGQQSq 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress R9TGdzN25MgdRkYfsYfxZWzHCLVCyWFAei 0.010000 -./komodo-cli -ac_name=SUPERNET sendtoaddress RDYsrWBZkYSWhRDupGRrfGqrVnFtK9hJGC 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RHPGxpiwRHP4dKZXjYPdpon1nCto7qVE8s 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RLQoAcs1RaqW1xfN2NJwoZWW5twexPhuGB 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RXF3aHUaWDUY4fRRYmBNALoHWkgSQCiJ4f 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RL2SkPSCGMvcHqZ56ErfMxbQGdA4nk7MZp 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RFssbc211PJdVy1bvcvAG5X2N4ovPAoy5o 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RNoz2DKPZ2ppMxgYx5tce9sjZBHefvPvNB 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RVxtoUT9CXbC1LdhztNAf9yR5ySnFnSPQh 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress R9XBrbj8iKkwy9M4erUqRaBinAiZSTXav3 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RSHdRnHHGdPtVej7fiehHBQ6dyTbEM1GHi 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RDW8EDkCkzQ1LA4xbVUoAERsBVhhYRLXCr 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RAxQTHdsy89tfSXwoce2sHeWrYXmDsMXQq 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RT2k2voy9n8jwppeTTJMQAhvaqA9pc9jHh 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RRvaVyKS59NJWhPp8Pn7mVPGhMuhJJXrdh 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RBpp98VwHx7SFv7dNbw8NY65t14XFq9fVD 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RPjUmFNcWEW9Bu275kPxzRXyWDz6bfQpPD 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RDY2CvzydimY2AtDqSjBAB1eCeogRE55DX 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RUgW6fLfVsLJ87Ng4zJTqNedJSKYQ9ToAf 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RUreYvNjhZYc1vP8cND9Cztpni1pYsigXb 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RHv3wyVnnanG2kSQmLNmjwAQeYRRAptxUy 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RLVwuTM5TitV4Gk79Rja731RwYkAzz7GWn 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RHbxwDa7JT1KJLHDKwb5n3gd8NREErqtQY 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RFDAZ1yCvKPmpqcgzg8r2qQJ8nPPgeoMrB 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RHsZesZXMfkdrsSEper3JWUBKwk29JTFfT 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RPJjzoKPb8idoUCT9XLBkNojNgysjJ5qrE 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RFQNjTfcvSAmf8D83og1NrdHj1wH2fc5X4 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RPknkGAHMwUBvfKQfvw9FyatTZzicSiN4y 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RMqbQz4NPNbG15QBwy9EFvLn4NX5Fa7w5g 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RQipE6ycbVVb9vCkhqrK8PGZs2p5YmiBtg 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RCA8H1npFPW5pnJRzycF8tFEJmn6XZhD4j 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RJD5jRidYW9Cu8qxjg9HDCsx6J3A4wQ4LU 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RQMwcDYMVBx9f4QCFfFk31px8QZP4e8uhA 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RXzsovGBQ3W97xnVC6JnWxXsV4qb7p7iBi 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RLHr8gUm2MZ3EEgDU4EmK7bdn5ZsxLYmnt 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RFTsWSzgKRd5Xa7d287w9eRFeYefKBso6Z 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress REuQ7EoxKeMYk4EGptV6EwdfV9LZXuc44g 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RX1tP6ftwe96p6scgJn4dpgNdHDgyg9R87 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RERp696QtNTeWDfBy3x3QbRwPYN2NxwxfA 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RNZKqUgoAPwWd7wNtuSKP7k1HSJAyPeH4N 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress R9jhJCwgT78pyjnkNuxgH3CE8ekxgT8iwB 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RSCQKVUhihKb13rb5VJwXsbSY6pdRPUZ6V 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RDVqM6t5xZw9jbYXEw2CJgkiSbrHBHiKR3 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RSSNgf98kiMGUxs55DvhNnumyxVudd2KQQ 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RXqdRmv7n9hygf9C7f7vj4VQyNR9RvzXss 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RE3P8D8rcWZBeKmT8DURPdezW87MU5Ho3F 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RS3v2u6d4SJ1ujLz7CHNSFLSmxn6Tx6mJp 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RREc88bQzxHCvzqErPDnTQH2Qg5yUtjbyp 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RJ9wAk3ZNrFwdso1RVbwASiqqQaDNyKjd2 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RVKtRKozg8RKvEYCumMD43fCU6f212M5RD 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RCvsbvzCwA1AaxeoYVSL9Q3BdnybEWfXaH 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RXtADsErZLmsGhNyQdW2DekHMGZ23cLrav 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RYGrWs5b8CVFFpxGpjiBaMwfYV9X5UqFaB 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RHASfhhM6bvDFakRDqkzA2wc3V4R4oNmXi 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RATaU3jjn4RwHK61YWoJ4eg7Eggk3puZW8 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RXbb9PkefXcsqq8wqiUZZUuq8e3p29mw1G 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RDY9LJZTEJ9FsvugUuD69gceA98uqan5XL 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress R9tjkpdNbzw6mNfxorb5bvTPmsuon5aLrC 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RT2JyVts5tb1prC7KYykmznrqw7VXJo1HB 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RFHRWQ5pAXNfmudHfxdxw3Wo8yFGoeDn6z 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RTw3vi3dGa9n8LLbKvk7jDAwLdt3A5ET7a 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RQeuhk4KcPM3F5hefwTBWezDdcktSGQQSq 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress R9TGdzN25MgdRkYfsYfxZWzHCLVCyWFAei 0.010000 -./komodo-cli -ac_name=DEX sendtoaddress RDYsrWBZkYSWhRDupGRrfGqrVnFtK9hJGC 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RHPGxpiwRHP4dKZXjYPdpon1nCto7qVE8s 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RLQoAcs1RaqW1xfN2NJwoZWW5twexPhuGB 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RXF3aHUaWDUY4fRRYmBNALoHWkgSQCiJ4f 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RL2SkPSCGMvcHqZ56ErfMxbQGdA4nk7MZp 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RFssbc211PJdVy1bvcvAG5X2N4ovPAoy5o 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RNoz2DKPZ2ppMxgYx5tce9sjZBHefvPvNB 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RVxtoUT9CXbC1LdhztNAf9yR5ySnFnSPQh 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress R9XBrbj8iKkwy9M4erUqRaBinAiZSTXav3 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RSHdRnHHGdPtVej7fiehHBQ6dyTbEM1GHi 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RDW8EDkCkzQ1LA4xbVUoAERsBVhhYRLXCr 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RAxQTHdsy89tfSXwoce2sHeWrYXmDsMXQq 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RT2k2voy9n8jwppeTTJMQAhvaqA9pc9jHh 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RRvaVyKS59NJWhPp8Pn7mVPGhMuhJJXrdh 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RBpp98VwHx7SFv7dNbw8NY65t14XFq9fVD 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RPjUmFNcWEW9Bu275kPxzRXyWDz6bfQpPD 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RDY2CvzydimY2AtDqSjBAB1eCeogRE55DX 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RUgW6fLfVsLJ87Ng4zJTqNedJSKYQ9ToAf 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RUreYvNjhZYc1vP8cND9Cztpni1pYsigXb 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RHv3wyVnnanG2kSQmLNmjwAQeYRRAptxUy 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RLVwuTM5TitV4Gk79Rja731RwYkAzz7GWn 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RHbxwDa7JT1KJLHDKwb5n3gd8NREErqtQY 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RFDAZ1yCvKPmpqcgzg8r2qQJ8nPPgeoMrB 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RHsZesZXMfkdrsSEper3JWUBKwk29JTFfT 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RPJjzoKPb8idoUCT9XLBkNojNgysjJ5qrE 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RFQNjTfcvSAmf8D83og1NrdHj1wH2fc5X4 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RPknkGAHMwUBvfKQfvw9FyatTZzicSiN4y 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RMqbQz4NPNbG15QBwy9EFvLn4NX5Fa7w5g 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RQipE6ycbVVb9vCkhqrK8PGZs2p5YmiBtg 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RCA8H1npFPW5pnJRzycF8tFEJmn6XZhD4j 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RJD5jRidYW9Cu8qxjg9HDCsx6J3A4wQ4LU 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RQMwcDYMVBx9f4QCFfFk31px8QZP4e8uhA 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RXzsovGBQ3W97xnVC6JnWxXsV4qb7p7iBi 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RLHr8gUm2MZ3EEgDU4EmK7bdn5ZsxLYmnt 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RFTsWSzgKRd5Xa7d287w9eRFeYefKBso6Z 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress REuQ7EoxKeMYk4EGptV6EwdfV9LZXuc44g 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RX1tP6ftwe96p6scgJn4dpgNdHDgyg9R87 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RERp696QtNTeWDfBy3x3QbRwPYN2NxwxfA 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RNZKqUgoAPwWd7wNtuSKP7k1HSJAyPeH4N 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress R9jhJCwgT78pyjnkNuxgH3CE8ekxgT8iwB 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RSCQKVUhihKb13rb5VJwXsbSY6pdRPUZ6V 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RDVqM6t5xZw9jbYXEw2CJgkiSbrHBHiKR3 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RSSNgf98kiMGUxs55DvhNnumyxVudd2KQQ 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RXqdRmv7n9hygf9C7f7vj4VQyNR9RvzXss 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RE3P8D8rcWZBeKmT8DURPdezW87MU5Ho3F 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RS3v2u6d4SJ1ujLz7CHNSFLSmxn6Tx6mJp 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RREc88bQzxHCvzqErPDnTQH2Qg5yUtjbyp 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RJ9wAk3ZNrFwdso1RVbwASiqqQaDNyKjd2 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RVKtRKozg8RKvEYCumMD43fCU6f212M5RD 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RCvsbvzCwA1AaxeoYVSL9Q3BdnybEWfXaH 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RXtADsErZLmsGhNyQdW2DekHMGZ23cLrav 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RYGrWs5b8CVFFpxGpjiBaMwfYV9X5UqFaB 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RHASfhhM6bvDFakRDqkzA2wc3V4R4oNmXi 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RATaU3jjn4RwHK61YWoJ4eg7Eggk3puZW8 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RXbb9PkefXcsqq8wqiUZZUuq8e3p29mw1G 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RDY9LJZTEJ9FsvugUuD69gceA98uqan5XL 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress R9tjkpdNbzw6mNfxorb5bvTPmsuon5aLrC 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RT2JyVts5tb1prC7KYykmznrqw7VXJo1HB 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RFHRWQ5pAXNfmudHfxdxw3Wo8yFGoeDn6z 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RTw3vi3dGa9n8LLbKvk7jDAwLdt3A5ET7a 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RQeuhk4KcPM3F5hefwTBWezDdcktSGQQSq 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress R9TGdzN25MgdRkYfsYfxZWzHCLVCyWFAei 0.010000 -./komodo-cli -ac_name=PANGEA sendtoaddress RDYsrWBZkYSWhRDupGRrfGqrVnFtK9hJGC 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RHPGxpiwRHP4dKZXjYPdpon1nCto7qVE8s 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RLQoAcs1RaqW1xfN2NJwoZWW5twexPhuGB 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RXF3aHUaWDUY4fRRYmBNALoHWkgSQCiJ4f 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RL2SkPSCGMvcHqZ56ErfMxbQGdA4nk7MZp 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RFssbc211PJdVy1bvcvAG5X2N4ovPAoy5o 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RNoz2DKPZ2ppMxgYx5tce9sjZBHefvPvNB 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RVxtoUT9CXbC1LdhztNAf9yR5ySnFnSPQh 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress R9XBrbj8iKkwy9M4erUqRaBinAiZSTXav3 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RSHdRnHHGdPtVej7fiehHBQ6dyTbEM1GHi 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RDW8EDkCkzQ1LA4xbVUoAERsBVhhYRLXCr 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RAxQTHdsy89tfSXwoce2sHeWrYXmDsMXQq 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RT2k2voy9n8jwppeTTJMQAhvaqA9pc9jHh 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RRvaVyKS59NJWhPp8Pn7mVPGhMuhJJXrdh 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RBpp98VwHx7SFv7dNbw8NY65t14XFq9fVD 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RPjUmFNcWEW9Bu275kPxzRXyWDz6bfQpPD 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RDY2CvzydimY2AtDqSjBAB1eCeogRE55DX 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RUgW6fLfVsLJ87Ng4zJTqNedJSKYQ9ToAf 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RUreYvNjhZYc1vP8cND9Cztpni1pYsigXb 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RHv3wyVnnanG2kSQmLNmjwAQeYRRAptxUy 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RLVwuTM5TitV4Gk79Rja731RwYkAzz7GWn 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RHbxwDa7JT1KJLHDKwb5n3gd8NREErqtQY 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RFDAZ1yCvKPmpqcgzg8r2qQJ8nPPgeoMrB 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RHsZesZXMfkdrsSEper3JWUBKwk29JTFfT 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RPJjzoKPb8idoUCT9XLBkNojNgysjJ5qrE 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RFQNjTfcvSAmf8D83og1NrdHj1wH2fc5X4 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RPknkGAHMwUBvfKQfvw9FyatTZzicSiN4y 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RMqbQz4NPNbG15QBwy9EFvLn4NX5Fa7w5g 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RQipE6ycbVVb9vCkhqrK8PGZs2p5YmiBtg 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RCA8H1npFPW5pnJRzycF8tFEJmn6XZhD4j 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RJD5jRidYW9Cu8qxjg9HDCsx6J3A4wQ4LU 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RQMwcDYMVBx9f4QCFfFk31px8QZP4e8uhA 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RXzsovGBQ3W97xnVC6JnWxXsV4qb7p7iBi 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RLHr8gUm2MZ3EEgDU4EmK7bdn5ZsxLYmnt 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RFTsWSzgKRd5Xa7d287w9eRFeYefKBso6Z 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress REuQ7EoxKeMYk4EGptV6EwdfV9LZXuc44g 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RX1tP6ftwe96p6scgJn4dpgNdHDgyg9R87 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RERp696QtNTeWDfBy3x3QbRwPYN2NxwxfA 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RNZKqUgoAPwWd7wNtuSKP7k1HSJAyPeH4N 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress R9jhJCwgT78pyjnkNuxgH3CE8ekxgT8iwB 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RSCQKVUhihKb13rb5VJwXsbSY6pdRPUZ6V 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RDVqM6t5xZw9jbYXEw2CJgkiSbrHBHiKR3 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RSSNgf98kiMGUxs55DvhNnumyxVudd2KQQ 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RXqdRmv7n9hygf9C7f7vj4VQyNR9RvzXss 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RE3P8D8rcWZBeKmT8DURPdezW87MU5Ho3F 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RS3v2u6d4SJ1ujLz7CHNSFLSmxn6Tx6mJp 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RREc88bQzxHCvzqErPDnTQH2Qg5yUtjbyp 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RJ9wAk3ZNrFwdso1RVbwASiqqQaDNyKjd2 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RVKtRKozg8RKvEYCumMD43fCU6f212M5RD 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RCvsbvzCwA1AaxeoYVSL9Q3BdnybEWfXaH 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RXtADsErZLmsGhNyQdW2DekHMGZ23cLrav 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RYGrWs5b8CVFFpxGpjiBaMwfYV9X5UqFaB 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RHASfhhM6bvDFakRDqkzA2wc3V4R4oNmXi 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RATaU3jjn4RwHK61YWoJ4eg7Eggk3puZW8 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RXbb9PkefXcsqq8wqiUZZUuq8e3p29mw1G 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RDY9LJZTEJ9FsvugUuD69gceA98uqan5XL 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress R9tjkpdNbzw6mNfxorb5bvTPmsuon5aLrC 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RT2JyVts5tb1prC7KYykmznrqw7VXJo1HB 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RFHRWQ5pAXNfmudHfxdxw3Wo8yFGoeDn6z 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RTw3vi3dGa9n8LLbKvk7jDAwLdt3A5ET7a 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RQeuhk4KcPM3F5hefwTBWezDdcktSGQQSq 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress R9TGdzN25MgdRkYfsYfxZWzHCLVCyWFAei 0.010000 -./komodo-cli -ac_name=JUMBLR sendtoaddress RDYsrWBZkYSWhRDupGRrfGqrVnFtK9hJGC 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RHPGxpiwRHP4dKZXjYPdpon1nCto7qVE8s 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RLQoAcs1RaqW1xfN2NJwoZWW5twexPhuGB 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RXF3aHUaWDUY4fRRYmBNALoHWkgSQCiJ4f 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RL2SkPSCGMvcHqZ56ErfMxbQGdA4nk7MZp 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RFssbc211PJdVy1bvcvAG5X2N4ovPAoy5o 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RNoz2DKPZ2ppMxgYx5tce9sjZBHefvPvNB 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RVxtoUT9CXbC1LdhztNAf9yR5ySnFnSPQh 0.010000 -./komodo-cli -ac_name=BET sendtoaddress R9XBrbj8iKkwy9M4erUqRaBinAiZSTXav3 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RSHdRnHHGdPtVej7fiehHBQ6dyTbEM1GHi 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RDW8EDkCkzQ1LA4xbVUoAERsBVhhYRLXCr 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RAxQTHdsy89tfSXwoce2sHeWrYXmDsMXQq 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RT2k2voy9n8jwppeTTJMQAhvaqA9pc9jHh 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RRvaVyKS59NJWhPp8Pn7mVPGhMuhJJXrdh 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RBpp98VwHx7SFv7dNbw8NY65t14XFq9fVD 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RPjUmFNcWEW9Bu275kPxzRXyWDz6bfQpPD 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RDY2CvzydimY2AtDqSjBAB1eCeogRE55DX 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RUgW6fLfVsLJ87Ng4zJTqNedJSKYQ9ToAf 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RUreYvNjhZYc1vP8cND9Cztpni1pYsigXb 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RHv3wyVnnanG2kSQmLNmjwAQeYRRAptxUy 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RLVwuTM5TitV4Gk79Rja731RwYkAzz7GWn 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RHbxwDa7JT1KJLHDKwb5n3gd8NREErqtQY 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RFDAZ1yCvKPmpqcgzg8r2qQJ8nPPgeoMrB 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RHsZesZXMfkdrsSEper3JWUBKwk29JTFfT 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RPJjzoKPb8idoUCT9XLBkNojNgysjJ5qrE 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RFQNjTfcvSAmf8D83og1NrdHj1wH2fc5X4 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RPknkGAHMwUBvfKQfvw9FyatTZzicSiN4y 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RMqbQz4NPNbG15QBwy9EFvLn4NX5Fa7w5g 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RQipE6ycbVVb9vCkhqrK8PGZs2p5YmiBtg 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RCA8H1npFPW5pnJRzycF8tFEJmn6XZhD4j 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RJD5jRidYW9Cu8qxjg9HDCsx6J3A4wQ4LU 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RQMwcDYMVBx9f4QCFfFk31px8QZP4e8uhA 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RXzsovGBQ3W97xnVC6JnWxXsV4qb7p7iBi 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RLHr8gUm2MZ3EEgDU4EmK7bdn5ZsxLYmnt 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RFTsWSzgKRd5Xa7d287w9eRFeYefKBso6Z 0.010000 -./komodo-cli -ac_name=BET sendtoaddress REuQ7EoxKeMYk4EGptV6EwdfV9LZXuc44g 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RX1tP6ftwe96p6scgJn4dpgNdHDgyg9R87 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RERp696QtNTeWDfBy3x3QbRwPYN2NxwxfA 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RNZKqUgoAPwWd7wNtuSKP7k1HSJAyPeH4N 0.010000 -./komodo-cli -ac_name=BET sendtoaddress R9jhJCwgT78pyjnkNuxgH3CE8ekxgT8iwB 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RSCQKVUhihKb13rb5VJwXsbSY6pdRPUZ6V 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RDVqM6t5xZw9jbYXEw2CJgkiSbrHBHiKR3 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RSSNgf98kiMGUxs55DvhNnumyxVudd2KQQ 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RXqdRmv7n9hygf9C7f7vj4VQyNR9RvzXss 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RE3P8D8rcWZBeKmT8DURPdezW87MU5Ho3F 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RS3v2u6d4SJ1ujLz7CHNSFLSmxn6Tx6mJp 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RREc88bQzxHCvzqErPDnTQH2Qg5yUtjbyp 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RJ9wAk3ZNrFwdso1RVbwASiqqQaDNyKjd2 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RVKtRKozg8RKvEYCumMD43fCU6f212M5RD 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RCvsbvzCwA1AaxeoYVSL9Q3BdnybEWfXaH 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RXtADsErZLmsGhNyQdW2DekHMGZ23cLrav 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RYGrWs5b8CVFFpxGpjiBaMwfYV9X5UqFaB 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RHASfhhM6bvDFakRDqkzA2wc3V4R4oNmXi 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RATaU3jjn4RwHK61YWoJ4eg7Eggk3puZW8 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RXbb9PkefXcsqq8wqiUZZUuq8e3p29mw1G 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RDY9LJZTEJ9FsvugUuD69gceA98uqan5XL 0.010000 -./komodo-cli -ac_name=BET sendtoaddress R9tjkpdNbzw6mNfxorb5bvTPmsuon5aLrC 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RT2JyVts5tb1prC7KYykmznrqw7VXJo1HB 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RFHRWQ5pAXNfmudHfxdxw3Wo8yFGoeDn6z 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RTw3vi3dGa9n8LLbKvk7jDAwLdt3A5ET7a 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RQeuhk4KcPM3F5hefwTBWezDdcktSGQQSq 0.010000 -./komodo-cli -ac_name=BET sendtoaddress R9TGdzN25MgdRkYfsYfxZWzHCLVCyWFAei 0.010000 -./komodo-cli -ac_name=BET sendtoaddress RDYsrWBZkYSWhRDupGRrfGqrVnFtK9hJGC 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RHPGxpiwRHP4dKZXjYPdpon1nCto7qVE8s 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RLQoAcs1RaqW1xfN2NJwoZWW5twexPhuGB 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RXF3aHUaWDUY4fRRYmBNALoHWkgSQCiJ4f 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RL2SkPSCGMvcHqZ56ErfMxbQGdA4nk7MZp 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RFssbc211PJdVy1bvcvAG5X2N4ovPAoy5o 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RNoz2DKPZ2ppMxgYx5tce9sjZBHefvPvNB 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RVxtoUT9CXbC1LdhztNAf9yR5ySnFnSPQh 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress R9XBrbj8iKkwy9M4erUqRaBinAiZSTXav3 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RSHdRnHHGdPtVej7fiehHBQ6dyTbEM1GHi 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RDW8EDkCkzQ1LA4xbVUoAERsBVhhYRLXCr 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RAxQTHdsy89tfSXwoce2sHeWrYXmDsMXQq 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RT2k2voy9n8jwppeTTJMQAhvaqA9pc9jHh 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RRvaVyKS59NJWhPp8Pn7mVPGhMuhJJXrdh 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RBpp98VwHx7SFv7dNbw8NY65t14XFq9fVD 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RPjUmFNcWEW9Bu275kPxzRXyWDz6bfQpPD 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RDY2CvzydimY2AtDqSjBAB1eCeogRE55DX 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RUgW6fLfVsLJ87Ng4zJTqNedJSKYQ9ToAf 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RUreYvNjhZYc1vP8cND9Cztpni1pYsigXb 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RHv3wyVnnanG2kSQmLNmjwAQeYRRAptxUy 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RLVwuTM5TitV4Gk79Rja731RwYkAzz7GWn 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RHbxwDa7JT1KJLHDKwb5n3gd8NREErqtQY 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RFDAZ1yCvKPmpqcgzg8r2qQJ8nPPgeoMrB 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RHsZesZXMfkdrsSEper3JWUBKwk29JTFfT 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RPJjzoKPb8idoUCT9XLBkNojNgysjJ5qrE 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RFQNjTfcvSAmf8D83og1NrdHj1wH2fc5X4 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RPknkGAHMwUBvfKQfvw9FyatTZzicSiN4y 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RMqbQz4NPNbG15QBwy9EFvLn4NX5Fa7w5g 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RQipE6ycbVVb9vCkhqrK8PGZs2p5YmiBtg 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RCA8H1npFPW5pnJRzycF8tFEJmn6XZhD4j 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RJD5jRidYW9Cu8qxjg9HDCsx6J3A4wQ4LU 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RQMwcDYMVBx9f4QCFfFk31px8QZP4e8uhA 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RXzsovGBQ3W97xnVC6JnWxXsV4qb7p7iBi 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RLHr8gUm2MZ3EEgDU4EmK7bdn5ZsxLYmnt 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RFTsWSzgKRd5Xa7d287w9eRFeYefKBso6Z 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress REuQ7EoxKeMYk4EGptV6EwdfV9LZXuc44g 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RX1tP6ftwe96p6scgJn4dpgNdHDgyg9R87 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RERp696QtNTeWDfBy3x3QbRwPYN2NxwxfA 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RNZKqUgoAPwWd7wNtuSKP7k1HSJAyPeH4N 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress R9jhJCwgT78pyjnkNuxgH3CE8ekxgT8iwB 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RSCQKVUhihKb13rb5VJwXsbSY6pdRPUZ6V 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RDVqM6t5xZw9jbYXEw2CJgkiSbrHBHiKR3 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RSSNgf98kiMGUxs55DvhNnumyxVudd2KQQ 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RXqdRmv7n9hygf9C7f7vj4VQyNR9RvzXss 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RE3P8D8rcWZBeKmT8DURPdezW87MU5Ho3F 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RS3v2u6d4SJ1ujLz7CHNSFLSmxn6Tx6mJp 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RREc88bQzxHCvzqErPDnTQH2Qg5yUtjbyp 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RJ9wAk3ZNrFwdso1RVbwASiqqQaDNyKjd2 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RVKtRKozg8RKvEYCumMD43fCU6f212M5RD 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RCvsbvzCwA1AaxeoYVSL9Q3BdnybEWfXaH 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RXtADsErZLmsGhNyQdW2DekHMGZ23cLrav 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RYGrWs5b8CVFFpxGpjiBaMwfYV9X5UqFaB 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RHASfhhM6bvDFakRDqkzA2wc3V4R4oNmXi 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RATaU3jjn4RwHK61YWoJ4eg7Eggk3puZW8 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RXbb9PkefXcsqq8wqiUZZUuq8e3p29mw1G 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RDY9LJZTEJ9FsvugUuD69gceA98uqan5XL 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress R9tjkpdNbzw6mNfxorb5bvTPmsuon5aLrC 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RT2JyVts5tb1prC7KYykmznrqw7VXJo1HB 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RFHRWQ5pAXNfmudHfxdxw3Wo8yFGoeDn6z 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RTw3vi3dGa9n8LLbKvk7jDAwLdt3A5ET7a 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RQeuhk4KcPM3F5hefwTBWezDdcktSGQQSq 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress R9TGdzN25MgdRkYfsYfxZWzHCLVCyWFAei 0.010000 -./komodo-cli -ac_name=CRYPTO sendtoaddress RDYsrWBZkYSWhRDupGRrfGqrVnFtK9hJGC 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RHPGxpiwRHP4dKZXjYPdpon1nCto7qVE8s 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RLQoAcs1RaqW1xfN2NJwoZWW5twexPhuGB 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RXF3aHUaWDUY4fRRYmBNALoHWkgSQCiJ4f 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RL2SkPSCGMvcHqZ56ErfMxbQGdA4nk7MZp 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RFssbc211PJdVy1bvcvAG5X2N4ovPAoy5o 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RNoz2DKPZ2ppMxgYx5tce9sjZBHefvPvNB 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RVxtoUT9CXbC1LdhztNAf9yR5ySnFnSPQh 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress R9XBrbj8iKkwy9M4erUqRaBinAiZSTXav3 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RSHdRnHHGdPtVej7fiehHBQ6dyTbEM1GHi 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RDW8EDkCkzQ1LA4xbVUoAERsBVhhYRLXCr 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RAxQTHdsy89tfSXwoce2sHeWrYXmDsMXQq 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RT2k2voy9n8jwppeTTJMQAhvaqA9pc9jHh 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RRvaVyKS59NJWhPp8Pn7mVPGhMuhJJXrdh 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RBpp98VwHx7SFv7dNbw8NY65t14XFq9fVD 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RPjUmFNcWEW9Bu275kPxzRXyWDz6bfQpPD 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RDY2CvzydimY2AtDqSjBAB1eCeogRE55DX 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RUgW6fLfVsLJ87Ng4zJTqNedJSKYQ9ToAf 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RUreYvNjhZYc1vP8cND9Cztpni1pYsigXb 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RHv3wyVnnanG2kSQmLNmjwAQeYRRAptxUy 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RLVwuTM5TitV4Gk79Rja731RwYkAzz7GWn 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RHbxwDa7JT1KJLHDKwb5n3gd8NREErqtQY 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RFDAZ1yCvKPmpqcgzg8r2qQJ8nPPgeoMrB 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RHsZesZXMfkdrsSEper3JWUBKwk29JTFfT 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RPJjzoKPb8idoUCT9XLBkNojNgysjJ5qrE 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RFQNjTfcvSAmf8D83og1NrdHj1wH2fc5X4 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RPknkGAHMwUBvfKQfvw9FyatTZzicSiN4y 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RMqbQz4NPNbG15QBwy9EFvLn4NX5Fa7w5g 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RQipE6ycbVVb9vCkhqrK8PGZs2p5YmiBtg 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RCA8H1npFPW5pnJRzycF8tFEJmn6XZhD4j 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RJD5jRidYW9Cu8qxjg9HDCsx6J3A4wQ4LU 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RQMwcDYMVBx9f4QCFfFk31px8QZP4e8uhA 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RXzsovGBQ3W97xnVC6JnWxXsV4qb7p7iBi 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RLHr8gUm2MZ3EEgDU4EmK7bdn5ZsxLYmnt 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RFTsWSzgKRd5Xa7d287w9eRFeYefKBso6Z 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress REuQ7EoxKeMYk4EGptV6EwdfV9LZXuc44g 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RX1tP6ftwe96p6scgJn4dpgNdHDgyg9R87 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RERp696QtNTeWDfBy3x3QbRwPYN2NxwxfA 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RNZKqUgoAPwWd7wNtuSKP7k1HSJAyPeH4N 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress R9jhJCwgT78pyjnkNuxgH3CE8ekxgT8iwB 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RSCQKVUhihKb13rb5VJwXsbSY6pdRPUZ6V 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RDVqM6t5xZw9jbYXEw2CJgkiSbrHBHiKR3 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RSSNgf98kiMGUxs55DvhNnumyxVudd2KQQ 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RXqdRmv7n9hygf9C7f7vj4VQyNR9RvzXss 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RE3P8D8rcWZBeKmT8DURPdezW87MU5Ho3F 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RS3v2u6d4SJ1ujLz7CHNSFLSmxn6Tx6mJp 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RREc88bQzxHCvzqErPDnTQH2Qg5yUtjbyp 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RJ9wAk3ZNrFwdso1RVbwASiqqQaDNyKjd2 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RVKtRKozg8RKvEYCumMD43fCU6f212M5RD 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RCvsbvzCwA1AaxeoYVSL9Q3BdnybEWfXaH 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RXtADsErZLmsGhNyQdW2DekHMGZ23cLrav 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RYGrWs5b8CVFFpxGpjiBaMwfYV9X5UqFaB 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RHASfhhM6bvDFakRDqkzA2wc3V4R4oNmXi 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RATaU3jjn4RwHK61YWoJ4eg7Eggk3puZW8 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RXbb9PkefXcsqq8wqiUZZUuq8e3p29mw1G 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RDY9LJZTEJ9FsvugUuD69gceA98uqan5XL 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress R9tjkpdNbzw6mNfxorb5bvTPmsuon5aLrC 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RT2JyVts5tb1prC7KYykmznrqw7VXJo1HB 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RFHRWQ5pAXNfmudHfxdxw3Wo8yFGoeDn6z 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RTw3vi3dGa9n8LLbKvk7jDAwLdt3A5ET7a 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RQeuhk4KcPM3F5hefwTBWezDdcktSGQQSq 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress R9TGdzN25MgdRkYfsYfxZWzHCLVCyWFAei 0.010000 -./komodo-cli -ac_name=HODL sendtoaddress RDYsrWBZkYSWhRDupGRrfGqrVnFtK9hJGC 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RHPGxpiwRHP4dKZXjYPdpon1nCto7qVE8s 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RLQoAcs1RaqW1xfN2NJwoZWW5twexPhuGB 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RXF3aHUaWDUY4fRRYmBNALoHWkgSQCiJ4f 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RL2SkPSCGMvcHqZ56ErfMxbQGdA4nk7MZp 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RFssbc211PJdVy1bvcvAG5X2N4ovPAoy5o 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RNoz2DKPZ2ppMxgYx5tce9sjZBHefvPvNB 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RVxtoUT9CXbC1LdhztNAf9yR5ySnFnSPQh 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress R9XBrbj8iKkwy9M4erUqRaBinAiZSTXav3 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RSHdRnHHGdPtVej7fiehHBQ6dyTbEM1GHi 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RDW8EDkCkzQ1LA4xbVUoAERsBVhhYRLXCr 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RAxQTHdsy89tfSXwoce2sHeWrYXmDsMXQq 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RT2k2voy9n8jwppeTTJMQAhvaqA9pc9jHh 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RRvaVyKS59NJWhPp8Pn7mVPGhMuhJJXrdh 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RBpp98VwHx7SFv7dNbw8NY65t14XFq9fVD 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RPjUmFNcWEW9Bu275kPxzRXyWDz6bfQpPD 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RDY2CvzydimY2AtDqSjBAB1eCeogRE55DX 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RUgW6fLfVsLJ87Ng4zJTqNedJSKYQ9ToAf 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RUreYvNjhZYc1vP8cND9Cztpni1pYsigXb 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RHv3wyVnnanG2kSQmLNmjwAQeYRRAptxUy 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RLVwuTM5TitV4Gk79Rja731RwYkAzz7GWn 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RHbxwDa7JT1KJLHDKwb5n3gd8NREErqtQY 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RFDAZ1yCvKPmpqcgzg8r2qQJ8nPPgeoMrB 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RHsZesZXMfkdrsSEper3JWUBKwk29JTFfT 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RPJjzoKPb8idoUCT9XLBkNojNgysjJ5qrE 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RFQNjTfcvSAmf8D83og1NrdHj1wH2fc5X4 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RPknkGAHMwUBvfKQfvw9FyatTZzicSiN4y 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RMqbQz4NPNbG15QBwy9EFvLn4NX5Fa7w5g 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RQipE6ycbVVb9vCkhqrK8PGZs2p5YmiBtg 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RCA8H1npFPW5pnJRzycF8tFEJmn6XZhD4j 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RJD5jRidYW9Cu8qxjg9HDCsx6J3A4wQ4LU 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RQMwcDYMVBx9f4QCFfFk31px8QZP4e8uhA 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RXzsovGBQ3W97xnVC6JnWxXsV4qb7p7iBi 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RLHr8gUm2MZ3EEgDU4EmK7bdn5ZsxLYmnt 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RFTsWSzgKRd5Xa7d287w9eRFeYefKBso6Z 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress REuQ7EoxKeMYk4EGptV6EwdfV9LZXuc44g 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RX1tP6ftwe96p6scgJn4dpgNdHDgyg9R87 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RERp696QtNTeWDfBy3x3QbRwPYN2NxwxfA 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RNZKqUgoAPwWd7wNtuSKP7k1HSJAyPeH4N 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress R9jhJCwgT78pyjnkNuxgH3CE8ekxgT8iwB 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RSCQKVUhihKb13rb5VJwXsbSY6pdRPUZ6V 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RDVqM6t5xZw9jbYXEw2CJgkiSbrHBHiKR3 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RSSNgf98kiMGUxs55DvhNnumyxVudd2KQQ 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RXqdRmv7n9hygf9C7f7vj4VQyNR9RvzXss 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RE3P8D8rcWZBeKmT8DURPdezW87MU5Ho3F 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RS3v2u6d4SJ1ujLz7CHNSFLSmxn6Tx6mJp 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RREc88bQzxHCvzqErPDnTQH2Qg5yUtjbyp 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RJ9wAk3ZNrFwdso1RVbwASiqqQaDNyKjd2 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RVKtRKozg8RKvEYCumMD43fCU6f212M5RD 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RCvsbvzCwA1AaxeoYVSL9Q3BdnybEWfXaH 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RXtADsErZLmsGhNyQdW2DekHMGZ23cLrav 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RYGrWs5b8CVFFpxGpjiBaMwfYV9X5UqFaB 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RHASfhhM6bvDFakRDqkzA2wc3V4R4oNmXi 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RATaU3jjn4RwHK61YWoJ4eg7Eggk3puZW8 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RXbb9PkefXcsqq8wqiUZZUuq8e3p29mw1G 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RDY9LJZTEJ9FsvugUuD69gceA98uqan5XL 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress R9tjkpdNbzw6mNfxorb5bvTPmsuon5aLrC 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RT2JyVts5tb1prC7KYykmznrqw7VXJo1HB 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RFHRWQ5pAXNfmudHfxdxw3Wo8yFGoeDn6z 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RTw3vi3dGa9n8LLbKvk7jDAwLdt3A5ET7a 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RQeuhk4KcPM3F5hefwTBWezDdcktSGQQSq 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress R9TGdzN25MgdRkYfsYfxZWzHCLVCyWFAei 0.010000 -./komodo-cli -ac_name=SHARK sendtoaddress RDYsrWBZkYSWhRDupGRrfGqrVnFtK9hJGC 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RHPGxpiwRHP4dKZXjYPdpon1nCto7qVE8s 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RLQoAcs1RaqW1xfN2NJwoZWW5twexPhuGB 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RXF3aHUaWDUY4fRRYmBNALoHWkgSQCiJ4f 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RL2SkPSCGMvcHqZ56ErfMxbQGdA4nk7MZp 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RFssbc211PJdVy1bvcvAG5X2N4ovPAoy5o 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RNoz2DKPZ2ppMxgYx5tce9sjZBHefvPvNB 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RVxtoUT9CXbC1LdhztNAf9yR5ySnFnSPQh 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress R9XBrbj8iKkwy9M4erUqRaBinAiZSTXav3 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RSHdRnHHGdPtVej7fiehHBQ6dyTbEM1GHi 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RDW8EDkCkzQ1LA4xbVUoAERsBVhhYRLXCr 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RAxQTHdsy89tfSXwoce2sHeWrYXmDsMXQq 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RT2k2voy9n8jwppeTTJMQAhvaqA9pc9jHh 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RRvaVyKS59NJWhPp8Pn7mVPGhMuhJJXrdh 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RBpp98VwHx7SFv7dNbw8NY65t14XFq9fVD 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RPjUmFNcWEW9Bu275kPxzRXyWDz6bfQpPD 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RDY2CvzydimY2AtDqSjBAB1eCeogRE55DX 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RUgW6fLfVsLJ87Ng4zJTqNedJSKYQ9ToAf 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RUreYvNjhZYc1vP8cND9Cztpni1pYsigXb 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RHv3wyVnnanG2kSQmLNmjwAQeYRRAptxUy 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RLVwuTM5TitV4Gk79Rja731RwYkAzz7GWn 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RHbxwDa7JT1KJLHDKwb5n3gd8NREErqtQY 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RFDAZ1yCvKPmpqcgzg8r2qQJ8nPPgeoMrB 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RHsZesZXMfkdrsSEper3JWUBKwk29JTFfT 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RPJjzoKPb8idoUCT9XLBkNojNgysjJ5qrE 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RFQNjTfcvSAmf8D83og1NrdHj1wH2fc5X4 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RPknkGAHMwUBvfKQfvw9FyatTZzicSiN4y 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RMqbQz4NPNbG15QBwy9EFvLn4NX5Fa7w5g 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RQipE6ycbVVb9vCkhqrK8PGZs2p5YmiBtg 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RCA8H1npFPW5pnJRzycF8tFEJmn6XZhD4j 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RJD5jRidYW9Cu8qxjg9HDCsx6J3A4wQ4LU 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RQMwcDYMVBx9f4QCFfFk31px8QZP4e8uhA 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RXzsovGBQ3W97xnVC6JnWxXsV4qb7p7iBi 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RLHr8gUm2MZ3EEgDU4EmK7bdn5ZsxLYmnt 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RFTsWSzgKRd5Xa7d287w9eRFeYefKBso6Z 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress REuQ7EoxKeMYk4EGptV6EwdfV9LZXuc44g 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RX1tP6ftwe96p6scgJn4dpgNdHDgyg9R87 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RERp696QtNTeWDfBy3x3QbRwPYN2NxwxfA 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RNZKqUgoAPwWd7wNtuSKP7k1HSJAyPeH4N 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress R9jhJCwgT78pyjnkNuxgH3CE8ekxgT8iwB 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RSCQKVUhihKb13rb5VJwXsbSY6pdRPUZ6V 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RDVqM6t5xZw9jbYXEw2CJgkiSbrHBHiKR3 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RSSNgf98kiMGUxs55DvhNnumyxVudd2KQQ 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RXqdRmv7n9hygf9C7f7vj4VQyNR9RvzXss 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RE3P8D8rcWZBeKmT8DURPdezW87MU5Ho3F 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RS3v2u6d4SJ1ujLz7CHNSFLSmxn6Tx6mJp 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RREc88bQzxHCvzqErPDnTQH2Qg5yUtjbyp 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RJ9wAk3ZNrFwdso1RVbwASiqqQaDNyKjd2 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RVKtRKozg8RKvEYCumMD43fCU6f212M5RD 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RCvsbvzCwA1AaxeoYVSL9Q3BdnybEWfXaH 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RXtADsErZLmsGhNyQdW2DekHMGZ23cLrav 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RYGrWs5b8CVFFpxGpjiBaMwfYV9X5UqFaB 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RHASfhhM6bvDFakRDqkzA2wc3V4R4oNmXi 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RATaU3jjn4RwHK61YWoJ4eg7Eggk3puZW8 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RXbb9PkefXcsqq8wqiUZZUuq8e3p29mw1G 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RDY9LJZTEJ9FsvugUuD69gceA98uqan5XL 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress R9tjkpdNbzw6mNfxorb5bvTPmsuon5aLrC 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RT2JyVts5tb1prC7KYykmznrqw7VXJo1HB 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RFHRWQ5pAXNfmudHfxdxw3Wo8yFGoeDn6z 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RTw3vi3dGa9n8LLbKvk7jDAwLdt3A5ET7a 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RQeuhk4KcPM3F5hefwTBWezDdcktSGQQSq 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress R9TGdzN25MgdRkYfsYfxZWzHCLVCyWFAei 0.010000 -./komodo-cli -ac_name=BOTS sendtoaddress RDYsrWBZkYSWhRDupGRrfGqrVnFtK9hJGC 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RHPGxpiwRHP4dKZXjYPdpon1nCto7qVE8s 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RLQoAcs1RaqW1xfN2NJwoZWW5twexPhuGB 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RXF3aHUaWDUY4fRRYmBNALoHWkgSQCiJ4f 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RL2SkPSCGMvcHqZ56ErfMxbQGdA4nk7MZp 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RFssbc211PJdVy1bvcvAG5X2N4ovPAoy5o 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RNoz2DKPZ2ppMxgYx5tce9sjZBHefvPvNB 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RVxtoUT9CXbC1LdhztNAf9yR5ySnFnSPQh 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress R9XBrbj8iKkwy9M4erUqRaBinAiZSTXav3 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RSHdRnHHGdPtVej7fiehHBQ6dyTbEM1GHi 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RDW8EDkCkzQ1LA4xbVUoAERsBVhhYRLXCr 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RAxQTHdsy89tfSXwoce2sHeWrYXmDsMXQq 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RT2k2voy9n8jwppeTTJMQAhvaqA9pc9jHh 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RRvaVyKS59NJWhPp8Pn7mVPGhMuhJJXrdh 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RBpp98VwHx7SFv7dNbw8NY65t14XFq9fVD 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RPjUmFNcWEW9Bu275kPxzRXyWDz6bfQpPD 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RDY2CvzydimY2AtDqSjBAB1eCeogRE55DX 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RUgW6fLfVsLJ87Ng4zJTqNedJSKYQ9ToAf 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RUreYvNjhZYc1vP8cND9Cztpni1pYsigXb 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RHv3wyVnnanG2kSQmLNmjwAQeYRRAptxUy 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RLVwuTM5TitV4Gk79Rja731RwYkAzz7GWn 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RHbxwDa7JT1KJLHDKwb5n3gd8NREErqtQY 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RFDAZ1yCvKPmpqcgzg8r2qQJ8nPPgeoMrB 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RHsZesZXMfkdrsSEper3JWUBKwk29JTFfT 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RPJjzoKPb8idoUCT9XLBkNojNgysjJ5qrE 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RFQNjTfcvSAmf8D83og1NrdHj1wH2fc5X4 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RPknkGAHMwUBvfKQfvw9FyatTZzicSiN4y 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RMqbQz4NPNbG15QBwy9EFvLn4NX5Fa7w5g 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RQipE6ycbVVb9vCkhqrK8PGZs2p5YmiBtg 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RCA8H1npFPW5pnJRzycF8tFEJmn6XZhD4j 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RJD5jRidYW9Cu8qxjg9HDCsx6J3A4wQ4LU 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RQMwcDYMVBx9f4QCFfFk31px8QZP4e8uhA 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RXzsovGBQ3W97xnVC6JnWxXsV4qb7p7iBi 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RLHr8gUm2MZ3EEgDU4EmK7bdn5ZsxLYmnt 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RFTsWSzgKRd5Xa7d287w9eRFeYefKBso6Z 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress REuQ7EoxKeMYk4EGptV6EwdfV9LZXuc44g 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RX1tP6ftwe96p6scgJn4dpgNdHDgyg9R87 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RERp696QtNTeWDfBy3x3QbRwPYN2NxwxfA 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RNZKqUgoAPwWd7wNtuSKP7k1HSJAyPeH4N 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress R9jhJCwgT78pyjnkNuxgH3CE8ekxgT8iwB 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RSCQKVUhihKb13rb5VJwXsbSY6pdRPUZ6V 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RDVqM6t5xZw9jbYXEw2CJgkiSbrHBHiKR3 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RSSNgf98kiMGUxs55DvhNnumyxVudd2KQQ 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RXqdRmv7n9hygf9C7f7vj4VQyNR9RvzXss 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RE3P8D8rcWZBeKmT8DURPdezW87MU5Ho3F 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RS3v2u6d4SJ1ujLz7CHNSFLSmxn6Tx6mJp 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RREc88bQzxHCvzqErPDnTQH2Qg5yUtjbyp 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RJ9wAk3ZNrFwdso1RVbwASiqqQaDNyKjd2 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RVKtRKozg8RKvEYCumMD43fCU6f212M5RD 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RCvsbvzCwA1AaxeoYVSL9Q3BdnybEWfXaH 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RXtADsErZLmsGhNyQdW2DekHMGZ23cLrav 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RYGrWs5b8CVFFpxGpjiBaMwfYV9X5UqFaB 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RHASfhhM6bvDFakRDqkzA2wc3V4R4oNmXi 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RATaU3jjn4RwHK61YWoJ4eg7Eggk3puZW8 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RXbb9PkefXcsqq8wqiUZZUuq8e3p29mw1G 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RDY9LJZTEJ9FsvugUuD69gceA98uqan5XL 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress R9tjkpdNbzw6mNfxorb5bvTPmsuon5aLrC 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RT2JyVts5tb1prC7KYykmznrqw7VXJo1HB 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RFHRWQ5pAXNfmudHfxdxw3Wo8yFGoeDn6z 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RTw3vi3dGa9n8LLbKvk7jDAwLdt3A5ET7a 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RQeuhk4KcPM3F5hefwTBWezDdcktSGQQSq 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress R9TGdzN25MgdRkYfsYfxZWzHCLVCyWFAei 0.010000 -./komodo-cli -ac_name=MGW sendtoaddress RDYsrWBZkYSWhRDupGRrfGqrVnFtK9hJGC 0.010000 - diff --git a/src/hash.cpp b/src/hash.cpp index 9711293e3..7471da8fb 100644 --- a/src/hash.cpp +++ b/src/hash.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "hash.h" #include "crypto/common.h" #include "crypto/hmac_sha512.h" diff --git a/src/hash.h b/src/hash.h index 09f71b432..9a8edc72c 100644 --- a/src/hash.h +++ b/src/hash.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_HASH_H #define BITCOIN_HASH_H diff --git a/src/httprpc.cpp b/src/httprpc.cpp index d60770aba..799d2fbe6 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -1,3 +1,18 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "httprpc.h" #include "chainparams.h" diff --git a/src/httprpc.h b/src/httprpc.h index d35445718..6827a7063 100644 --- a/src/httprpc.h +++ b/src/httprpc.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_HTTPRPC_H #define BITCOIN_HTTPRPC_H diff --git a/src/importcoin.cpp b/src/importcoin.cpp index d36943b5d..39ff01d68 100644 --- a/src/importcoin.cpp +++ b/src/importcoin.cpp @@ -1,3 +1,18 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "crosschain.h" #include "importcoin.h" #include "cc/utils.h" @@ -5,12 +20,16 @@ #include "hash.h" #include "script/cc.h" #include "primitives/transaction.h" +#include "core_io.h" +#include "script/sign.h" +#include "wallet/wallet.h" +int32_t komodo_nextheight(); CTransaction MakeImportCoinTransaction(const TxProof proof, const CTransaction burnTx, const std::vector payouts) { std::vector payload = E_MARSHAL(ss << EVAL_IMPORTCOIN); - CMutableTransaction mtx; + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); mtx.vin.push_back(CTxIn(COutPoint(burnTx.GetHash(), 10e8), CScript() << payload)); mtx.vout = payouts; auto importData = E_MARSHAL(ss << proof; ss << burnTx); @@ -19,11 +38,13 @@ CTransaction MakeImportCoinTransaction(const TxProof proof, const CTransaction b } -CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector payouts) +CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector payouts,std::vector rawproof) { - std::vector opret = E_MARSHAL(ss << VARINT(targetCCid); - ss << targetSymbol; - ss << SerializeHash(payouts)); + std::vector opret; + opret = E_MARSHAL(ss << VARINT(targetCCid); + ss << targetSymbol; + ss << SerializeHash(payouts); + ss << rawproof); return CTxOut(value, CScript() << OP_RETURN << opret); } @@ -41,14 +62,25 @@ bool UnmarshalImportTx(const CTransaction &importTx, TxProof &proof, CTransactio } -bool UnmarshalBurnTx(const CTransaction &burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash) +bool UnmarshalBurnTx(const CTransaction &burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash,std::vector&rawproof) { - std::vector burnOpret; + std::vector burnOpret; uint32_t ccid = 0; if (burnTx.vout.size() == 0) return false; GetOpReturnData(burnTx.vout.back().scriptPubKey, burnOpret); - return E_UNMARSHAL(burnOpret, ss >> VARINT(*targetCCid); - ss >> targetSymbol; - ss >> payoutsHash); + E_UNMARSHAL(burnOpret, ss >> VARINT(ccid)); + /*if ( ccid != 0xffffffff ) + { + return E_UNMARSHAL(burnOpret, ss >> VARINT(*targetCCid); + ss >> targetSymbol; + ss >> payoutsHash); + } + else*/ + { + return E_UNMARSHAL(burnOpret, ss >> VARINT(*targetCCid); + ss >> targetSymbol; + ss >> payoutsHash; + ss >> rawproof); + } } @@ -100,9 +132,10 @@ bool VerifyCoinImport(const CScript& scriptSig, TransactionSignatureChecker& che void AddImportTombstone(const CTransaction &importTx, CCoinsViewCache &inputs, int nHeight) { uint256 burnHash = importTx.vin[0].prevout.hash; + //fprintf(stderr,"add tombstone.(%s)\n",burnHash.GetHex().c_str()); CCoinsModifier modifier = inputs.ModifyCoins(burnHash); modifier->nHeight = nHeight; - modifier->nVersion = 1; + modifier->nVersion = 4;//1; modifier->vout.push_back(CTxOut(0, CScript() << OP_0)); } @@ -110,6 +143,7 @@ void AddImportTombstone(const CTransaction &importTx, CCoinsViewCache &inputs, i void RemoveImportTombstone(const CTransaction &importTx, CCoinsViewCache &inputs) { uint256 burnHash = importTx.vin[0].prevout.hash; + //fprintf(stderr,"remove tombstone.(%s)\n",burnHash.GetHex().c_str()); inputs.ModifyCoins(burnHash)->Clear(); } @@ -117,5 +151,6 @@ void RemoveImportTombstone(const CTransaction &importTx, CCoinsViewCache &inputs int ExistsImportTombstone(const CTransaction &importTx, const CCoinsViewCache &inputs) { uint256 burnHash = importTx.vin[0].prevout.hash; + //fprintf(stderr,"check tombstone.(%s) in %s\n",burnHash.GetHex().c_str(),importTx.GetHash().GetHex().c_str()); return inputs.HaveCoins(burnHash); } diff --git a/src/importcoin.h b/src/importcoin.h index f62bb45a1..64019ac8f 100644 --- a/src/importcoin.h +++ b/src/importcoin.h @@ -1,3 +1,18 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef IMPORTCOIN_H #define IMPORTCOIN_H @@ -13,9 +28,9 @@ 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); +CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector payouts,std::vector rawproof); -bool UnmarshalBurnTx(const CTransaction &burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash); +bool UnmarshalBurnTx(const CTransaction &burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash,std::vector &rawproof); bool UnmarshalImportTx(const CTransaction &importTx, TxProof &proof, CTransaction &burnTx, std::vector &payouts); diff --git a/src/init.cpp b/src/init.cpp index a87eb6170..3dd09ac50 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #if defined(HAVE_CONFIG_H) #include "config/bitcoin-config.h" #endif @@ -76,6 +91,7 @@ using namespace std; extern void ThreadSendAlert(); extern int32_t KOMODO_LOADINGBLOCKS; extern bool VERUS_MINTBLOCKS; +extern char ASSETCHAINS_SYMBOL[]; ZCJoinSplit* pzcashParams = NULL; @@ -195,7 +211,10 @@ void Shutdown() /// for example if the data directory was found to be locked. /// Be sure that anything that writes files or flushes caches only does this if the respective /// module was initialized. - RenameThread("verus-shutoff"); + static char shutoffstr[128]; + sprintf(shutoffstr,"%s-shutoff",ASSETCHAINS_SYMBOL); + //RenameThread("verus-shutoff"); + RenameThread(shutoffstr); mempool.AddTransactionsUpdated(1); StopHTTPRPC(); @@ -1501,7 +1520,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) fReindex = true; } } - + bool clearWitnessCaches = false; bool fLoaded = false; @@ -1874,9 +1893,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) VERUS_MINTBLOCKS = GetBoolArg("-mint", false); if (pwalletMain || !GetArg("-mineraddress", "").empty()) - GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain, GetArg("-genproclimit", 0)); + GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain, GetArg("-genproclimit", -1)); #else - GenerateBitcoins(GetBoolArg("-gen", false), GetArg("-genproclimit", 0)); + GenerateBitcoins(GetBoolArg("-gen", false), GetArg("-genproclimit", -1)); #endif #endif diff --git a/src/init.h b/src/init.h index 710e43c69..108339865 100644 --- a/src/init.h +++ b/src/init.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_INIT_H #define BITCOIN_INIT_H diff --git a/src/key.cpp b/src/key.cpp index 5688b1302..3b6fed81b 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "key.h" #include "arith_uint256.h" diff --git a/src/key.h b/src/key.h index 8d64151e3..c41208003 100644 --- a/src/key.h +++ b/src/key.h @@ -4,6 +4,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_KEY_H #define BITCOIN_KEY_H diff --git a/src/keystore.cpp b/src/keystore.cpp index e1e3ae89b..34bab456c 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "keystore.h" #include "key.h" diff --git a/src/keystore.h b/src/keystore.h index bf2c9b246..bab236e24 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_KEYSTORE_H #define BITCOIN_KEYSTORE_H diff --git a/src/komodo-tx.cpp b/src/komodo-tx.cpp index 3165023e0..67ac68cd4 100644 --- a/src/komodo-tx.cpp +++ b/src/komodo-tx.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "clientversion.h" #include "coins.h" #include "consensus/consensus.h" @@ -177,6 +192,37 @@ static void RegisterLoad(const std::string& strInput) RegisterSetJson(key, valStr); } + +int32_t komodo_nextheight() +{ + return(100000000); +} + + +// Set default values of new CMutableTransaction based on consensus rules at given height. +CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight) +{ + CMutableTransaction mtx; + + bool isOverwintered = NetworkUpgradeActive(nHeight, consensusParams, Consensus::UPGRADE_OVERWINTER); + if (isOverwintered) { + mtx.fOverwintered = true; + mtx.nExpiryHeight = nHeight + 60; + + if (NetworkUpgradeActive(nHeight, consensusParams, Consensus::UPGRADE_SAPLING)) { + mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; + mtx.nVersion = SAPLING_TX_VERSION; + } else { + mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID; + mtx.nVersion = OVERWINTER_TX_VERSION; + mtx.nExpiryHeight = std::min( + mtx.nExpiryHeight, + static_cast(consensusParams.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight - 1)); + } + } + return mtx; +} + static void MutateTxVersion(CMutableTransaction& tx, const std::string& cmdVal) { int64_t newVersion = atoi64(cmdVal); diff --git a/src/komodo.h b/src/komodo.h index 4c9edee89..4a8bd7d96 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -799,6 +799,11 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block) uint64_t signedmask,voutmask; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; uint8_t scriptbuf[10001],pubkeys[64][33],rmd160[20],scriptPubKey[35]; uint256 zero,btctxid,txhash; int32_t i,j,k,numnotaries,notarized,scriptlen,isratification,nid,numvalid,specialtx,notarizedheight,notaryid,len,numvouts,numvins,height,txn_count; + if ( pindex == 0 ) + { + fprintf(stderr,"komodo_connectblock null pindex\n"); + return; + } memset(&zero,0,sizeof(zero)); komodo_init(pindex->GetHeight()); KOMODO_INITDONE = (uint32_t)time(NULL); @@ -942,12 +947,15 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block) } } } - if ( ((signedmask & 1) != 0 && numvalid >= KOMODO_MINRATIFY) || bitweight(signedmask) > (numnotaries/3) ) + if ( ASSETCHAINS_SYMBOL[0] != 0 || height < 100000 ) { - memset(&txhash,0,sizeof(txhash)); - komodo_stateupdate(height,pubkeys,numvalid,0,txhash,0,0,0,0,0,0,0,0,0,0,zero,0); - printf("RATIFIED! >>>>>>>>>> new notaries.%d newheight.%d from height.%d\n",numvalid,(((height+KOMODO_ELECTION_GAP/2)/KOMODO_ELECTION_GAP)+1)*KOMODO_ELECTION_GAP,height); - } else printf("signedmask.%llx numvalid.%d wt.%d numnotaries.%d\n",(long long)signedmask,numvalid,bitweight(signedmask),numnotaries); + if ( ((signedmask & 1) != 0 && numvalid >= KOMODO_MINRATIFY) || bitweight(signedmask) > (numnotaries/3) ) + { + memset(&txhash,0,sizeof(txhash)); + komodo_stateupdate(height,pubkeys,numvalid,0,txhash,0,0,0,0,0,0,0,0,0,0,zero,0); + printf("RATIFIED! >>>>>>>>>> new notaries.%d newheight.%d from height.%d\n",numvalid,(((height+KOMODO_ELECTION_GAP/2)/KOMODO_ELECTION_GAP)+1)*KOMODO_ELECTION_GAP,height); + } else printf("signedmask.%llx numvalid.%d wt.%d numnotaries.%d\n",(long long)signedmask,numvalid,bitweight(signedmask),numnotaries); + } } } } diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index add4f4e7f..c530db4fb 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -21,11 +21,13 @@ #include "consensus/params.h" #include "komodo_defs.h" #include "script/standard.h" +#include "cc/CCinclude.h" int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp); unsigned int lwmaGetNextPOSRequired(const CBlockIndex* pindexLast, const Consensus::Params& params); - +bool EnsureWalletIsAvailable(bool avoidException); +extern bool fRequestShutdown; //#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"curl",(char *)"http://127.0.0.1:7776",0,0,(char *)(cmdstr)) struct MemoryStruct { char *memory; size_t size; }; @@ -555,9 +557,9 @@ uint64_t komodo_seed(int32_t height) return(seed); } -uint32_t komodo_txtime(uint64_t *valuep,uint256 hash, int32_t n, char *destaddr) +uint32_t komodo_txtime(CScript &opret,uint64_t *valuep,uint256 hash, int32_t n, char *destaddr) { - CTxDestination address; CTransaction tx; uint256 hashBlock; + CTxDestination address; CTransaction tx; uint256 hashBlock; int32_t numvouts; *valuep = 0; if (!GetTransaction(hash, tx, #ifndef KOMODO_ZCASH @@ -568,10 +570,12 @@ uint32_t komodo_txtime(uint64_t *valuep,uint256 hash, int32_t n, char *destaddr) //fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); return(0); } + numvouts = tx.vout.size(); //fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); - if ( n < tx.vout.size() ) + if ( n < numvouts ) { *valuep = tx.vout[n].nValue; + opret = tx.vout[numvouts-1].scriptPubKey; if (ExtractDestination(tx.vout[n].scriptPubKey, address)) strcpy(destaddr,CBitcoinAddress(address).ToString().c_str()); } @@ -610,23 +614,63 @@ uint32_t komodo_txtime2(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr) return(txtime); } -int32_t komodo_isPoS(CBlock *pblock) +int32_t komodo_WhoStaked(CBlock *pblock, CTxDestination &addressout) { - int32_t n,vout; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid; + int32_t n,vout; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid; CScript opret; + if ( (n= pblock->vtx.size()) > 1 && pblock->vtx[n-1].vin.size() == 1 && pblock->vtx[n-1].vout.size() == 1 ) + { + txid = pblock->vtx[n-1].vin[0].prevout.hash; + vout = pblock->vtx[n-1].vin[0].prevout.n; + txtime = komodo_txtime(opret,&value,txid,vout,destaddr); + if ( ExtractDestination(pblock->vtx[n-1].vout[0].scriptPubKey,voutaddress) ) + { + strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); + if ( strcmp(destaddr,voutaddr) == 0 && pblock->vtx[n-1].vout[0].nValue == value ) + { + //fprintf(stderr,"is PoS block!\n"); + addressout = voutaddress; + return(1); + } + } + } + return(0); +} + +bool MarmaraPoScheck(char *destaddr,CScript opret,CTransaction staketx); + +int32_t komodo_isPoS(CBlock *pblock,int32_t height) +{ + int32_t n,vout,numvouts; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid; CScript opret; if ( ASSETCHAINS_STAKED != 0 ) { - if ( (n= pblock->vtx.size()) > 1 && pblock->vtx[n-1].vin.size() == 1 && pblock->vtx[n-1].vout.size() == 1 ) + n = pblock->vtx.size(); + //fprintf(stderr,"ht.%d check for PoS numtx.%d numvins.%d numvouts.%d\n",height,n,(int32_t)pblock->vtx[n-1].vin.size(),(int32_t)pblock->vtx[n-1].vout.size()); + if ( n > 1 && pblock->vtx[n-1].vin.size() == 1 && pblock->vtx[n-1].vout.size() == 1+(ASSETCHAINS_MARMARA!=0) ) { txid = pblock->vtx[n-1].vin[0].prevout.hash; vout = pblock->vtx[n-1].vin[0].prevout.n; - txtime = komodo_txtime(&value,txid,vout,destaddr); + txtime = komodo_txtime(opret,&value,txid,vout,destaddr); if ( ExtractDestination(pblock->vtx[n-1].vout[0].scriptPubKey,voutaddress) ) { strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); - if ( strcmp(destaddr,voutaddr) == 0 && pblock->vtx[n-1].vout[0].nValue == value ) + //fprintf(stderr,"voutaddr.%s vs destaddr.%s\n",voutaddr,destaddr); + if ( pblock->vtx[n-1].vout[0].nValue == value && strcmp(destaddr,voutaddr) == 0 ) { - //fprintf(stderr,"is PoS block!\n"); - return(1); + if ( ASSETCHAINS_MARMARA == 0 ) + return(1); + else + { + if ( pblock->vtx[n-1].vout[0].scriptPubKey.IsPayToCryptoCondition() != 0 && (numvouts= pblock->vtx[n-1].vout.size()) == 2 ) + { +//fprintf(stderr,"validate proper %s %s signature and unlockht preservation\n",voutaddr,destaddr); + return(MarmaraPoScheck(destaddr,opret,pblock->vtx[n-1])); + } + else + { + fprintf(stderr,"reject ht.%d PoS block\n",height); + return(strcmp(ASSETCHAINS_SYMBOL,"MTST2") == 0); // allow until MTST3 + } + } } } } @@ -1138,15 +1182,22 @@ uint64_t komodo_commission(const CBlock *pblock,int32_t height) n = pblock->vtx[i].vout.size(); for (j=0; jvtx[i].vout[j].nValue),j); if ( i != 0 || j != 1 ) total += pblock->vtx[i].vout[j].nValue; + if ( total > 1000000 * COIN ) + { + total = 1000000 * COIN; + break; + } } } - commission = ((total * ASSETCHAINS_COMMISSION) / COIN); + commission = ((total / 10000) * ASSETCHAINS_COMMISSION) / 10000; + //commission = ((total * ASSETCHAINS_COMMISSION) / COIN); } if ( commission < 10000 ) commission = 0; + //fprintf(stderr,"-> %.8f\n",(double)commission/COIN); return(commission); } @@ -1159,7 +1210,7 @@ uint32_t komodo_segid32(char *coinaddr) int8_t komodo_segid(int32_t nocache,int32_t height) { - CTxDestination voutaddress; CBlock block; CBlockIndex *pindex; uint64_t value; uint32_t txtime; char voutaddr[64],destaddr[64]; int32_t txn_count,vout; uint256 txid; int8_t segid = -1; + CTxDestination voutaddress; CBlock block; CBlockIndex *pindex; uint64_t value; uint32_t txtime; char voutaddr[64],destaddr[64]; int32_t txn_count,vout; uint256 txid; CScript opret; int8_t segid = -1; if ( height > 0 && (pindex= komodo_chainactive(height)) != 0 ) { if ( nocache == 0 && pindex->segid >= -1 ) @@ -1171,7 +1222,7 @@ int8_t komodo_segid(int32_t nocache,int32_t height) { txid = block.vtx[txn_count-1].vin[0].prevout.hash; vout = block.vtx[txn_count-1].vin[0].prevout.n; - txtime = komodo_txtime(&value,txid,vout,destaddr); + txtime = komodo_txtime(opret,&value,txid,vout,destaddr); if ( ExtractDestination(block.vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) ) { strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); @@ -1413,12 +1464,14 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_ pindex = it != mapBlockIndex.end() ? it->second : NULL; if ( pindex != 0 && pindex->segid >= -1 ) { + //fprintf(stderr,"isPoSblock segid.%d\n",pindex->segid); if ( pindex->segid == -1 ) return(0); else return(1); } txn_count = pblock->vtx.size(); - if ( txn_count > 1 && pblock->vtx[txn_count-1].vin.size() == 1 && pblock->vtx[txn_count-1].vout.size() == 1 ) + //fprintf(stderr,"checkblock n.%d vins.%d vouts.%d %.8f %.8f\n",txn_count,(int32_t)pblock->vtx[txn_count-1].vin.size(),(int32_t)pblock->vtx[txn_count-1].vout.size(),(double)pblock->vtx[txn_count-1].vout[0].nValue/COIN,(double)pblock->vtx[txn_count-1].vout[1].nValue/COIN); + if ( txn_count > 1 && pblock->vtx[txn_count-1].vin.size() == 1 && pblock->vtx[txn_count-1].vout.size() == 1 + (ASSETCHAINS_MARMARA!=0) ) { it = mapBlockIndex.find(pblock->hashPrevBlock); if ( it != mapBlockIndex.end() && (previndex = it->second) != NULL ) @@ -1428,7 +1481,7 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_ vout = pblock->vtx[txn_count-1].vin[0].prevout.n; if ( prevtime != 0 ) { - if ( komodo_isPoS(pblock) != 0 ) + if ( komodo_isPoS(pblock,height) != 0 ) { eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime+27,(char *)""); } @@ -1439,7 +1492,7 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_ if ( slowflag != 0 && pindex != 0 ) { pindex->segid = -1; - fprintf(stderr,"PoW block detected set segid.%d <- %d\n",height,pindex->segid); + //fprintf(stderr,"PoW block detected set segid.%d <- %d\n",height,pindex->segid); } } else @@ -1447,18 +1500,24 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_ isPoS = 2; // 2 means staking utxo validated if ( slowflag != 0 && height > 100 ) { - segid = -3; - if ( pindex != 0 && pindex->segid == -2 && (segid= komodo_segid(1,height)) >= 0 ) + CTxDestination voutaddress; char voutaddr[64]; + if ( ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) ) + { + strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); + segid = komodo_segid32(voutaddr) & 0x3f; + //fprintf(stderr,"komodo_segid.(%d) -> %d\n",height,segid); + } + if ( pindex != 0 && segid >= 0 ) { pindex->segid = segid; - fprintf(stderr,"B set segid.%d <- %d\n",height,pindex->segid); + //fprintf(stderr,"B set segid.%d <- %d\n",height,pindex->segid); } //else fprintf(stderr,"unexpected null pindex for slowflag set ht.%d segid.%d:%d\n",height,pindex!=0?pindex->segid:-3,segid); } } } if ( slowflag == 0 && isPoS == 0 ) // maybe previous block is not seen yet, do the best approx { - if ( komodo_isPoS(pblock) != 0 ) + if ( komodo_isPoS(pblock,height) != 0 ) isPoS = 1; } if ( slowflag != 0 && isPoS != 0 ) @@ -1669,13 +1728,19 @@ int64_t komodo_checkcommission(CBlock *pblock,int32_t height) if ( ASSETCHAINS_COMMISSION != 0 ) { checktoshis = komodo_commission(pblock,height); - //fprintf(stderr,"height.%d commission %.8f\n",height,(double)checktoshis/COIN); - /*if ( checktoshis > 10000 && pblock->vtx[0].vout.size() != 2 ) jl777: not sure why this was here + if ( checktoshis >= 10000 && pblock->vtx[0].vout.size() < 2 ) + { + //fprintf(stderr,"komodo_checkcommission vsize.%d height.%d commission %.8f\n",(int32_t)pblock->vtx[0].vout.size(),height,(double)checktoshis/COIN); return(-1); - else*/ if ( checktoshis != 0 ) + } + else if ( checktoshis != 0 ) { script = (uint8_t *)&pblock->vtx[0].vout[1].scriptPubKey[0]; scriptlen = (int32_t)pblock->vtx[0].vout[1].scriptPubKey.size(); + //int32_t i; + //for (i=0; ivtx[0].vout[1].nValue/COIN); if ( ASSETCHAINS_SCRIPTPUB.size() > 1 ) { if ( ASSETCHAINS_SCRIPTPUB.size()/2 == scriptlen && scriptlen < sizeof(scripthex) ) @@ -1691,10 +1756,7 @@ int64_t komodo_checkcommission(CBlock *pblock,int32_t height) matched = 25; if ( matched == 0 ) { - //int32_t i; - //for (i=0; i<25; i++) - // fprintf(stderr,"%02x",script[i]); - //fprintf(stderr," payment to wrong pubkey scriptlen.%d, scriptpub[%d]\n",scriptlen,(int32_t)ASSETCHAINS_SCRIPTPUB.size()/2); + fprintf(stderr," payment to wrong pubkey scriptlen.%d, scriptpub[%d] checktoshis.%llu\n",scriptlen,(int32_t)ASSETCHAINS_SCRIPTPUB.size()/2,(long long)checktoshis); return(-1); } @@ -1712,7 +1774,7 @@ 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; + uint256 hash; arith_uint256 bnTarget,bhash; bool fNegative,fOverflow; uint8_t *script,pubkey33[33],pubkeys[64][33]; int32_t i,scriptlen,possible,PoSperc,is_PoSblock=0,n,failed = 0,notaryid = -1; int64_t checktoshis,value; CBlockIndex *pprev; if ( KOMODO_TEST_ASSETCHAIN_SKIP_POW == 0 && Params().NetworkIDString() == "regtest" ) KOMODO_TEST_ASSETCHAIN_SKIP_POW = 1; if ( !CheckEquihashSolution(pblock, Params()) ) @@ -1768,6 +1830,7 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height) return(-1); } } + //fprintf(stderr,"ASSETCHAINS_STAKED.%d ht.%d\n",(int32_t)ASSETCHAINS_STAKED,height); if ( ASSETCHAINS_STAKED != 0 && height >= 2 ) // must PoS or have at least 16x better PoW { if ( (is_PoSblock= komodo_is_PoSblock(slowflag,height,pblock,bnTarget,bhash)) == 0 ) @@ -1819,7 +1882,8 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height) else { script = (uint8_t *)&pblock->vtx[0].vout[0].scriptPubKey[0]; - if ( script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 ) + scriptlen = (int32_t)pblock->vtx[0].vout[0].scriptPubKey.size(); + if ( scriptlen != 35 || script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 ) return(-1); } } @@ -1937,3 +2001,305 @@ int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height) *sproutfundsp = sproutfunds; return(supply); } +struct komodo_staking +{ + char address[64]; + uint256 txid; + arith_uint256 hashval; + uint64_t nValue; + uint32_t segid32,txtime; + int32_t vout; + CScript scriptPubKey; +}; + +struct komodo_staking *komodo_addutxo(struct komodo_staking *array,int32_t *numkp,int32_t *maxkp,uint32_t txtime,uint64_t nValue,uint256 txid,int32_t vout,char *address,uint8_t *hashbuf,CScript pk) +{ + uint256 hash; uint32_t segid32; struct komodo_staking *kp; + segid32 = komodo_stakehash(&hash,address,hashbuf,txid,vout); + if ( *numkp >= *maxkp ) + { + *maxkp += 1000; + array = (struct komodo_staking *)realloc(array,sizeof(*array) * (*maxkp)); + //fprintf(stderr,"realloc max.%d array.%p\n",*maxkp,array); + } + kp = &array[(*numkp)++]; + //fprintf(stderr,"kp.%p num.%d\n",kp,*numkp); + memset(kp,0,sizeof(*kp)); + strcpy(kp->address,address); + kp->txid = txid; + kp->vout = vout; + kp->hashval = UintToArith256(hash); + kp->txtime = txtime; + kp->segid32 = segid32; + kp->nValue = nValue; + kp->scriptPubKey = pk; + return(array); +} + +arith_uint256 _komodo_eligible(struct komodo_staking *kp,arith_uint256 ratio,uint32_t blocktime,int32_t iter,int32_t minage,int32_t segid,int32_t nHeight,uint32_t prevtime) +{ + int32_t diff; uint64_t coinage; arith_uint256 coinage256,hashval; + diff = (iter + blocktime - kp->txtime - minage); + if ( diff < 0 ) + diff = 60; + else if ( diff > 3600*24*30 ) + diff = 3600*24*30; + if ( iter > 0 ) + diff += segid*2; + coinage = ((uint64_t)kp->nValue * diff); + if ( blocktime+iter+segid*2 > prevtime+480 ) + coinage *= ((blocktime+iter+segid*2) - (prevtime+400)); + coinage256 = arith_uint256(coinage+1); + hashval = ratio * (kp->hashval / coinage256); + return(hashval); +} + +uint32_t komodo_eligible(arith_uint256 bnTarget,arith_uint256 ratio,struct komodo_staking *kp,int32_t nHeight,uint32_t blocktime,uint32_t prevtime,int32_t minage,uint8_t *hashbuf) +{ + int32_t maxiters = 600; uint256 hash; + int32_t segid,iter,diff; uint64_t coinage; arith_uint256 hashval,coinage256; + komodo_stakehash(&hash,kp->address,hashbuf,kp->txid,kp->vout); + kp->hashval = UintToArith256(hash); + segid = ((nHeight + kp->segid32) & 0x3f); + hashval = _komodo_eligible(kp,ratio,blocktime,maxiters,minage,segid,nHeight,prevtime); + /*for (int i=31; i>=16; i--) + fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]); + fprintf(stderr," vs "); + for (int i=31; i>=16; i--) + fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); + fprintf(stderr," b.%u minage.%d segid.%d ht.%d prev.%u\n",blocktime,minage,segid,nHeight,prevtime);*/ + if ( hashval <= bnTarget ) + { + for (iter=0; itertxtime+minage ) + continue; + hashval = _komodo_eligible(kp,ratio,blocktime,iter,minage,segid,nHeight,prevtime); + if ( hashval <= bnTarget ) + { + //fprintf(stderr,"winner %.8f blocktime.%u iter.%d segid.%d\n",(double)kp->nValue/COIN,blocktime,iter,segid); + blocktime += iter; + blocktime += segid * 2; + return(blocktime); + } + } + } else fprintf(stderr,"maxiters is not good enough\n"); + return(0); +} + +int32_t MarmaraSignature(uint8_t *utxosig,CMutableTransaction &txNew); +uint8_t DecodeMaramaraCoinbaseOpRet(const CScript scriptPubKey,CPubKey &pk,int32_t &height,int32_t &unlockht); + +int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig) +{ + static struct komodo_staking *array; static int32_t numkp,maxkp; static uint32_t lasttime; + set setAddress; struct komodo_staking *kp; int32_t winners,segid,minage,nHeight,counter=0,i,m,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; vector vecOutputs; uint32_t block_from_future_rejecttime,besttime,eligible,eligible2,earliest = 0; CScript best_scriptPubKey; arith_uint256 mindiff,ratio,bnTarget; CBlockIndex *tipindex,*pindex; CTxDestination address; bool fNegative,fOverflow; uint8_t hashbuf[256]; CTransaction tx; uint256 hashBlock; + if (!EnsureWalletIsAvailable(0)) + return 0; + + bnTarget.SetCompact(nBits, &fNegative, &fOverflow); + mindiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); + ratio = (mindiff / bnTarget); + assert(pwalletMain != NULL); + *utxovaluep = 0; + memset(utxotxidp,0,sizeof(*utxotxidp)); + memset(utxovoutp,0,sizeof(*utxovoutp)); + memset(utxosig,0,72); + if ( (tipindex= chainActive.Tip()) == 0 ) + return(0); + nHeight = tipindex->GetHeight() + 1; + if ( (minage= nHeight*3) > 6000 ) // about 100 blocks + minage = 6000; + komodo_segids(hashbuf,nHeight-101,100); + if ( *blocktimep < tipindex->nTime+60 ) + *blocktimep = tipindex->nTime+60; +//fprintf(stderr,"Start scan of utxo for staking %u ht.%d\n",(uint32_t)time(NULL),nHeight); + + bool resetstaker = false; + if ( array != 0 ) + { + CBlockIndex* pblockindex = chainActive[tipindex->GetHeight()]; + CBlock block; CTxDestination addressout; + if ( ASSETCHAINS_MARMARA != 0 ) + resetstaker = true; + else if( ReadBlockFromDisk(block, pblockindex, 1) && komodo_WhoStaked(&block, addressout) != 0 && IsMine(*pwalletMain,addressout) != 0 ) + { + resetstaker = true; + fprintf(stderr, "Reset ram staker after mining a block!\n"); + } + } + + if ( time(NULL) > lasttime+600 || array == 0 || resetstaker ) + { + LOCK2(cs_main, pwalletMain->cs_wallet); + pwalletMain->AvailableCoins(vecOutputs, false, NULL, true); + if ( array != 0 ) + { + free(array); + array = 0; + maxkp = numkp = 0; + lasttime = 0; + } + if ( ASSETCHAINS_MARMARA == 0 ) + { + BOOST_FOREACH(const COutput& out, vecOutputs) + { + if ( (tipindex= chainActive.Tip()) == 0 || tipindex->GetHeight()+1 > nHeight ) + { + fprintf(stderr,"chain tip changed during staking loop t.%u counter.%d\n",(uint32_t)time(NULL),counter); + return(0); + } + counter++; + if ( out.nDepth < nMinDepth || out.nDepth > nMaxDepth ) + { + fprintf(stderr,"komodo_staked invalid depth %d\n",(int32_t)out.nDepth); + continue; + } + CAmount nValue = out.tx->vout[out.i].nValue; + if ( nValue < COIN || !out.fSpendable ) + continue; + const CScript& pk = out.tx->vout[out.i].scriptPubKey; + if ( ExtractDestination(pk,address) != 0 ) + { + if ( IsMine(*pwalletMain,address) == 0 ) + continue; + if ( GetTransaction(out.tx->GetHash(),tx,hashBlock,true) != 0 && (pindex= komodo_getblockindex(hashBlock)) != 0 ) + { + array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,out.tx->GetHash(),out.i,(char *)CBitcoinAddress(address).ToString().c_str(),hashbuf,(CScript)pk); + //fprintf(stderr,"addutxo numkp.%d vs max.%d\n",numkp,maxkp); + } + } + } + } + else + { + struct CCcontract_info *cp,C; uint256 txid; int32_t vout,ht,unlockht; CAmount nValue; char coinaddr[64]; CPubKey mypk,Marmarapk,pk; + std::vector > unspentOutputs; + cp = CCinit(&C,EVAL_MARMARA); + mypk = pubkey2pk(Mypubkey()); + Marmarapk = GetUnspendable(cp,0); + GetCCaddress1of2(cp,coinaddr,Marmarapk,mypk); + SetCCunspents(unspentOutputs,coinaddr); + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) + { + txid = it->first.txhash; + vout = (int32_t)it->first.index; + if ( (nValue= it->second.satoshis) < COIN ) + continue; + if ( GetTransaction(txid,tx,hashBlock,true) != 0 && (pindex= komodo_getblockindex(hashBlock)) != 0 && myIsutxo_spentinmempool(txid,vout) == 0 ) + { + const CScript &scriptPubKey = tx.vout[vout].scriptPubKey; + if ( DecodeMaramaraCoinbaseOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,pk,ht,unlockht) != 0 && pk == mypk ) + { + array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,txid,vout,coinaddr,hashbuf,(CScript)scriptPubKey); + } + // else fprintf(stderr,"SKIP addutxo %.8f numkp.%d vs max.%d\n",(double)nValue/COIN,numkp,maxkp); + } + } + } + lasttime = (uint32_t)time(NULL); +//fprintf(stderr,"finished kp data of utxo for staking %u ht.%d numkp.%d maxkp.%d\n",(uint32_t)time(NULL),nHeight,numkp,maxkp); + } +//fprintf(stderr,"numkp.%d blocktime.%u\n",numkp,*blocktimep); + block_from_future_rejecttime = (uint32_t)GetAdjustedTime() + 57; + for (i=winners=0; iGetHeight()+1 > nHeight ) + { + fprintf(stderr,"chain tip changed during staking loop t.%u counter.%d\n",(uint32_t)time(NULL),counter); + return(0); + } + kp = &array[i]; + if ( (eligible2= komodo_eligible(bnTarget,ratio,kp,nHeight,*blocktimep,(uint32_t)tipindex->nTime+27,minage,hashbuf)) == 0 ) + continue; + eligible = komodo_stake(0,bnTarget,nHeight,kp->txid,kp->vout,0,(uint32_t)tipindex->nTime+27,kp->address); +//fprintf(stderr,"i.%d %u vs %u\n",i,eligible2,eligible); + if ( eligible > 0 ) + { + besttime = m = 0; + if ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+27,kp->address) ) + { + while ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+27,kp->address) ) + { + besttime = eligible; + eligible--; + if ( eligible < block_from_future_rejecttime ) // nothing gained by going earlier + break; + m++; +//fprintf(stderr,"m.%d ht.%d validated winning blocktime %u -> %.8f eligible.%u test prior\n",m,nHeight,*blocktimep,(double)kp->nValue/COIN,eligible); + } + } + else + { + //fprintf(stderr,"ht.%d error validating winning blocktime %u -> %.8f eligible.%u test prior\n",nHeight,*blocktimep,(double)kp->nValue/COIN,eligible); + continue; + } + eligible = besttime; + winners++; +//fprintf(stderr,"ht.%d validated winning [%d] -> %.8f eligible.%u test prior\n",nHeight,(int32_t)(eligible - tipindex->nTime),(double)kp->nValue/COIN,eligible); + if ( earliest == 0 || eligible < earliest || (eligible == earliest && (*utxovaluep == 0 || kp->nValue < *utxovaluep)) ) + { + earliest = eligible; + best_scriptPubKey = kp->scriptPubKey; //out.tx->vout[out.i].scriptPubKey; + *utxovaluep = (uint64_t)kp->nValue; + //decode_hex((uint8_t *)utxotxidp,32,(char *)out.tx->GetHash().GetHex().c_str()); + decode_hex((uint8_t *)utxotxidp,32,(char *)kp->txid.GetHex().c_str()); + *utxovoutp = kp->vout; + *txtimep = kp->txtime;//(uint32_t)out.tx->nLockTime; + fprintf(stderr,"ht.%d earliest.%u [%d].%d (%s) nValue %.8f locktime.%u counter.%d winners.%d\n",nHeight,earliest,(int32_t)(earliest - tipindex->nTime),m,kp->address,(double)kp->nValue/COIN,*txtimep,counter,winners); + } + } //else fprintf(stderr,"utxo not eligible\n"); + } + if ( numkp < 1000 && array != 0 ) + { + free(array); + array = 0; + maxkp = numkp = 0; + lasttime = 0; + } + if ( earliest != 0 ) + { + bool signSuccess; SignatureData sigdata; uint64_t txfee; uint8_t *ptr; uint256 revtxid,utxotxid; + auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); + const CKeyStore& keystore = *pwalletMain; + txNew.vin.resize(1); + txNew.vout.resize(1); + txfee = 0; + for (i=0; i<32; i++) + ((uint8_t *)&revtxid)[i] = ((uint8_t *)utxotxidp)[31 - i]; + txNew.vin[0].prevout.hash = revtxid; + txNew.vin[0].prevout.n = *utxovoutp; + txNew.vout[0].scriptPubKey = best_scriptPubKey;// CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG; + txNew.vout[0].nValue = *utxovaluep - txfee; + txNew.nLockTime = earliest; + CTransaction txNewConst(txNew); + if ( ASSETCHAINS_MARMARA == 0 ) + { + signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, *utxovaluep, SIGHASH_ALL), best_scriptPubKey, sigdata, consensusBranchId); + UpdateTransaction(txNew,0,sigdata); + ptr = (uint8_t *)&sigdata.scriptSig[0]; + siglen = sigdata.scriptSig.size(); + for (i=0; i 0 ) + signSuccess = true; + else signSuccess = false; + } + if (!signSuccess) + fprintf(stderr,"failed to create signature\n"); + else + { + //fprintf(stderr," siglen.%d\n",siglen); +//fprintf(stderr,"best %u from %u, gap %d lag.%d\n",earliest,*blocktimep,(int32_t)(earliest - *blocktimep),(int32_t)(time(NULL) - *blocktimep)); + *blocktimep = earliest; + } + } //else fprintf(stderr,"no earliest utxo for staking\n"); + //fprintf(stderr,"end scan of utxo for staking t.%u counter.%d numkp.%d winners.%d\n",(uint32_t)time(NULL),counter,numkp,winners); + return(siglen); +} diff --git a/src/komodo_cJSON.c b/src/komodo_cJSON.c index 8569b7802..10140ad02 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-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/komodo_cJSON.h b/src/komodo_cJSON.h index 2639d3c52..c104a4f79 100755 --- a/src/komodo_cJSON.h +++ b/src/komodo_cJSON.h @@ -20,6 +20,21 @@ THE SOFTWARE. */ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef komodo_cJSON__h #define komodo_cJSON__h diff --git a/src/komodo_ccdata.h b/src/komodo_ccdata.h index 012183fc7..3969532fd 100644 --- a/src/komodo_ccdata.h +++ b/src/komodo_ccdata.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/komodo_curve25519.h b/src/komodo_curve25519.h index 90d9a7e00..cba40561b 100644 --- a/src/komodo_curve25519.h +++ b/src/komodo_curve25519.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/komodo_defs.h b/src/komodo_defs.h index e604e1779..0ea97d6db 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -1,3 +1,18 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef KOMODO_DEFS_H #define KOMODO_DEFS_H @@ -13,8 +28,51 @@ #define KOMODO_FIRSTFUNGIBLEID 100 #define KOMODO_SAPLING_ACTIVATION 1544832000 // Dec 15th, 2018 #define KOMODO_SAPLING_DEADLINE 1550188800 // Feb 15th, 2019 - +#define _COINBASE_MATURITY 100 + +#define SETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] |= (1 << ((bitoffset) & 7))) +#define GETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] & (1 << ((bitoffset) & 7))) +#define CLEARBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] &= ~(1 << ((bitoffset) & 7))) + extern uint8_t ASSETCHAINS_TXPOW,ASSETCHAINS_PUBLIC; int32_t MAX_BLOCK_SIZE(int32_t height); +extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; +extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; +extern uint32_t ASSETCHAIN_INIT, ASSETCHAINS_MAGIC; +extern int32_t VERUS_BLOCK_POSUNITS, ASSETCHAINS_LWMAPOS, ASSETCHAINS_SAPLING, ASSETCHAINS_OVERWINTER; +extern uint64_t ASSETCHAINS_SUPPLY; + +extern uint64_t ASSETCHAINS_TIMELOCKGTE; +extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH,ASSETCHAINS_EQUIHASH,KOMODO_INITDONE; + +extern int32_t KOMODO_MININGTHREADS,KOMODO_LONGESTCHAIN,ASSETCHAINS_SEED,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,KOMODO_ON_DEMAND,KOMODO_PASSPORT_INITDONE; +extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_STAKED; +extern bool VERUS_MINTBLOCKS; +extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[]; +extern const char *ASSETCHAINS_ALGORITHMS[]; +extern int32_t VERUS_MIN_STAKEAGE; +extern uint32_t ASSETCHAINS_VERUSHASH, ASSETCHAINS_LASTERA, ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[]; +extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; +extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY,ASSETCHAINS_SCRIPTPUB; +extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_MARMARA; + +extern char ASSETCHAINS_SYMBOL[65]; +extern int32_t VERUS_BLOCK_POSUNITS, VERUS_CONSECUTIVE_POS_THRESHOLD, VERUS_NOPOS_THRESHHOLD; + + +extern int32_t KOMODO_CONNECTING,KOMODO_CCACTIVATE,KOMODO_DEALERNODE; +extern uint32_t ASSETCHAINS_CC; +extern char ASSETCHAINS_SYMBOL[]; +extern std::string CCerror,ASSETCHAINS_CCLIB; +extern uint8_t ASSETCHAINS_CCDISABLES[256]; + +extern int32_t USE_EXTERNAL_PUBKEY; +extern std::string NOTARY_PUBKEY; +extern int32_t KOMODO_EXCHANGEWALLET; +extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; +extern int32_t VERUS_MIN_STAKEAGE; +extern std::string DONATION_PUBKEY; +extern uint8_t ASSETCHAINS_PRIVATE; +extern int32_t USE_EXTERNAL_PUBKEY; #endif diff --git a/src/komodo_events.h b/src/komodo_events.h index d4ea17ce5..5500a341e 100644 --- a/src/komodo_events.h +++ b/src/komodo_events.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 102245723..02ab67407 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -16,6 +16,8 @@ // paxdeposit equivalent in reverse makes opreturn and KMD does the same in reverse #include "komodo_defs.h" +int32_t MarmaraValidateCoinbase(int32_t height,CTransaction tx); + int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base) { int32_t baseid; struct komodo_state *sp; int64_t netliability,maxallowed,maxval; @@ -90,7 +92,7 @@ struct pax_transaction *komodo_paxmark(int32_t height,uint256 txid,uint16_t vout pax->marked = mark; //if ( height > 214700 || pax->height > 214700 ) // printf("mark ht.%d %.8f %.8f\n",pax->height,dstr(pax->komodoshis),dstr(pax->fiatoshis)); - + } pthread_mutex_unlock(&komodo_mutex); return(pax); @@ -203,9 +205,9 @@ int32_t komodo_issued_opreturn(char *base,uint256 *txids,uint16_t *vouts,int64_t // return(0); incr = 34 + (iskomodo * (2*sizeof(fiatoshis) + 2*sizeof(height) + 20 + 4)); //41e77b91cb68dc2aa02fa88550eae6b6d44db676a7e935337b6d1392d9718f03cb0200305c90660400000000fbcbeb1f000000bde801006201000058e7945ad08ddba1eac9c9b6c8e1e97e8016a2d152 - + // 41e94d736ec69d88c08b5d238abeeca609c02357a8317e0d56c328bcb1c259be5d0200485bc80200000000404b4c000000000059470200b80b000061f22ba7d19fe29ac3baebd839af8b7127d1f9075553440046bb4cc7a3b5cd39dffe7206507a3482a00780e617f68b273cce9817ed69298d02001069ca1b0000000080f0fa02000000005b470200b90b000061f22ba7d19fe29ac3baebd839af8b7127d1f90755 - + //for (i=0; i 0 && ASSETCHAINS_MARMARA != 0 && (height & 1) == 0 ) + { + if ( MarmaraValidateCoinbase(height,block.vtx[0]) < 0 ) + { + fprintf(stderr,"MARMARA error ht.%d constrains even height blocks to pay 100%% to CC in vout0 with opreturn\n",height); + return(-1); + } + } // we don't want these checks in VRSC, leave it at the Sapling upgrade - if ( ASSETCHAINS_SYMBOL[0] == 0 || + if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_COMMISSION != 0 && height > 1) || NetworkUpgradeActive(height, Params().GetConsensus(), Consensus::UPGRADE_SAPLING) ) { @@ -740,6 +750,11 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim else if ( height > 814000 ) { script = (uint8_t *)&block.vtx[0].vout[0].scriptPubKey[0]; + //int32_t notary = komodo_electednotary(&num,script+1,height,0); + //if ( (-1 * (komodo_electednotary(&num,script+1,height,0) >= 0) * (height > 1000000)) < 0 ) + // fprintf(stderr, ">>>>>>> FAILED BLOCK.%d notary.%d insync.%d\n",height,notary,KOMODO_INSYNC); + //else + // fprintf(stderr, "<<<<<<< VALID BLOCK.%d notary.%d insync.%d\n",height,notary,KOMODO_INSYNC); return(-1 * (komodo_electednotary(&num,script+1,height,0) >= 0) * (height > 1000000)); } } @@ -774,7 +789,7 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim const char *komodo_opreturn(int32_t height,uint64_t value,uint8_t *opretbuf,int32_t opretlen,uint256 txid,uint16_t vout,char *source) { - uint8_t rmd160[20],rmd160s[64*20],addrtype,shortflag,pubkey33[33]; int32_t didstats,i,j,n,kvheight,len,tokomodo,kmdheight,otherheights[64],kmdheights[64]; int8_t baseids[64]; char base[4],coinaddr[64],destaddr[64]; uint256 txids[64]; uint16_t vouts[64]; uint64_t convtoshis,seed; int64_t fee,fiatoshis,komodoshis,checktoshis,values[64],srcvalues[64]; struct pax_transaction *pax,*pax2; struct komodo_state *basesp; double diff; + uint8_t rmd160[20],rmd160s[64*20],addrtype,shortflag,pubkey33[33]; int32_t didstats,i,j,n,kvheight,len,tokomodo,kmdheight,otherheights[64],kmdheights[64]; int8_t baseids[64]; char base[4],coinaddr[64],destaddr[64]; uint256 txids[64]; uint16_t vouts[64]; uint64_t convtoshis,seed; int64_t fee,fiatoshis,komodoshis,checktoshis,values[64],srcvalues[64]; struct pax_transaction *pax,*pax2; struct komodo_state *basesp; double diff; const char *typestr = "unknown"; if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) < 0 && opretbuf[0] != 'K' ) { @@ -1187,7 +1202,7 @@ void komodo_stateind_set(struct komodo_state *sp,uint32_t *inds,int32_t n,uint8_ printf("numR.%d numV.%d numN.%d count.%d\n",numR,numV,numN,count); /*else if ( func == 'K' ) // KMD height: stop after 1st else if ( func == 'T' ) // KMD height+timestamp: stop after 1st - + else if ( func == 'N' ) // notarization, scan backwards 1440+ blocks; else if ( func == 'V' ) // price feed: can stop after 1440+ else if ( func == 'R' ) // opreturn:*/ @@ -1373,7 +1388,7 @@ void komodo_passport_iteration() { static long lastpos[34]; static char userpass[33][1024]; static uint32_t lasttime,callcounter,lastinterest; int32_t maxseconds = 10; - FILE *fp; uint8_t *filedata; long fpos,datalen,lastfpos; int32_t baseid,limit,n,ht,isrealtime,expired,refid,blocks,longest; struct komodo_state *sp,*refsp; char *retstr,fname[512],*base,symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; uint32_t buf[3],starttime; cJSON *infoobj,*result; uint64_t RTmask = 0; //CBlockIndex *pindex; + FILE *fp; uint8_t *filedata; long fpos,datalen,lastfpos; int32_t baseid,limit,n,ht,isrealtime,expired,refid,blocks,longest; struct komodo_state *sp,*refsp; char *retstr,fname[512],*base,symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; uint32_t buf[3],starttime; uint64_t RTmask = 0; //CBlockIndex *pindex; expired = 0; while ( KOMODO_INITDONE == 0 ) { @@ -1521,4 +1536,3 @@ void komodo_passport_iteration() printf("READY for %s RPC calls at %u! done PASSPORT %s refid.%d\n",ASSETCHAINS_SYMBOL,(uint32_t)time(NULL),ASSETCHAINS_SYMBOL,refid); } } - diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 3e9b84db1..79b56cbbb 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -44,15 +44,16 @@ struct komodo_state KOMODO_STATES[34]; #define _COINBASE_MATURITY 100 int COINBASE_MATURITY = _COINBASE_MATURITY;//100; +unsigned int WITNESS_CACHE_SIZE = _COINBASE_MATURITY+10; int32_t KOMODO_MININGTHREADS = -1,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,KOMODO_CONNECTING = -1,KOMODO_DEALERNODE,KOMODO_EXTRASATOSHI,ASSETCHAINS_FOUNDERS; int32_t KOMODO_INSYNC,KOMODO_LASTMINED,prevKOMODO_LASTMINED,KOMODO_CCACTIVATE,JUMBLR_PAUSE = 1; -std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY,ASSETCHAINS_SCRIPTPUB; -uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEYHASH[20],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW; +std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY,ASSETCHAINS_SCRIPTPUB,ASSETCHAINS_SELFIMPORT,ASSETCHAINS_CCLIB; +uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEYHASH[20],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW,ASSETCHAINS_MARMARA; bool VERUS_MINTBLOCKS; char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],ASSETCHAINS_USERPASS[4096]; -uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; +uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,ASSETCHAINS_BEAMPORT,ASSETCHAINS_CODAPORT; uint32_t ASSETCHAIN_INIT,ASSETCHAINS_CC,KOMODO_STOPAT,KOMODO_DPOWCONFS = 1; uint32_t ASSETCHAINS_MAGIC = 2387029918; int64_t ASSETCHAINS_GENESISTXVAL = 5000000000; @@ -70,6 +71,7 @@ uint64_t ASSETCHAINS_TIMEUNLOCKFROM = 0, ASSETCHAINS_TIMEUNLOCKTO = 0; uint32_t ASSETCHAINS_LASTERA = 1; uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_DECAY[ASSETCHAINS_MAX_ERAS]; +uint8_t ASSETCHAINS_CCDISABLES[256]; #define _ASSETCHAINS_EQUIHASH 0 uint32_t ASSETCHAINS_NUMALGOS = 2; diff --git a/src/komodo_interest.h b/src/komodo_interest.h index b76fbbdc9..b9549d860 100644 --- a/src/komodo_interest.h +++ b/src/komodo_interest.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/komodo_jumblr.h b/src/komodo_jumblr.h index 79bd049f4..fca7395e5 100755 --- a/src/komodo_jumblr.h +++ b/src/komodo_jumblr.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -629,7 +629,7 @@ uint64_t jumblr_increment(uint8_t r,int32_t height,uint64_t total,uint64_t bigge void jumblr_iteration() { static int32_t lastheight; static uint32_t lasttime; - char *zaddr,*addr,*retstr,secretaddr[64]; cJSON *array; int32_t i,iter,height,acpublic,counter,chosen_one,n; uint64_t smallest,medium,biggest,amount=0,total=0; double fee; struct jumblr_item *ptr,*tmp; uint16_t r,s; + char *zaddr,*addr,*retstr=0,secretaddr[64]; cJSON *array; int32_t i,iter,height,acpublic,counter,chosen_one,n; uint64_t smallest,medium,biggest,amount=0,total=0; double fee; struct jumblr_item *ptr,*tmp; uint16_t r,s; acpublic = ASSETCHAINS_PUBLIC; if ( ASSETCHAINS_SYMBOL[0] == 0 && GetTime() >= KOMODO_SAPLING_DEADLINE ) acpublic = 1; @@ -648,7 +648,7 @@ void jumblr_iteration() } free_json(array); } - free(retstr); + free(retstr), retstr = 0; } } height = (int32_t)chainActive.LastTip()->GetHeight(); @@ -691,7 +691,7 @@ void jumblr_iteration() if ( amount > 0 && (retstr= jumblr_sendt_to_z(Jumblr_deposit,addr,dstr(amount))) != 0 ) { printf("sendt_to_z.(%s)\n",retstr); - free(retstr); + free(retstr), retstr = 0; } free(zaddr); } else printf("no zaddr from jumblr_zgetnewaddress\n"); @@ -723,7 +723,7 @@ void jumblr_iteration() if ( (retstr= jumblr_sendz_to_z(ptr->dest,addr,dstr(total))) != 0 ) { printf("n.%d counter.%d chosen_one.%d send z_to_z.(%s)\n",n,counter,chosen_one,retstr); - free(retstr); + free(retstr), retstr = 0; } ptr->spent = (uint32_t)time(NULL); free(zaddr); @@ -768,7 +768,7 @@ void jumblr_iteration() if ( (retstr= jumblr_sendz_to_t(ptr->dest,secretaddr,dstr(total))) != 0 ) { printf("%s send z_to_t.(%s)\n",secretaddr,retstr); - free(retstr); + free(retstr), retstr = 0; } else printf("null return from jumblr_sendz_to_t\n"); ptr->spent = (uint32_t)time(NULL); break; diff --git a/src/komodo_kv.h b/src/komodo_kv.h index 834584e44..a879340ff 100644 --- a/src/komodo_kv.h +++ b/src/komodo_kv.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/komodo_notary.h b/src/komodo_notary.h index 8c51c7924..fca7fd223 100644 --- a/src/komodo_notary.h +++ b/src/komodo_notary.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/komodo_pax.h b/src/komodo_pax.h index 6f408042e..9935f3463 100644 --- a/src/komodo_pax.h +++ b/src/komodo_pax.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/komodo_port.c b/src/komodo_port.c index 14a97e159..fd68db881 100644 --- a/src/komodo_port.c +++ b/src/komodo_port.c @@ -1,10 +1,17 @@ -// -// main.c -// spawn -// -// Created by Mac on 4/7/18. -// Copyright © 2018 SuperNET. All rights reserved. -// +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ #include #include diff --git a/src/komodo_structs.h b/src/komodo_structs.h index 8595adc76..6b7c316b6 100644 --- a/src/komodo_structs.h +++ b/src/komodo_structs.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 29ce82554..289a84d7c 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -1654,14 +1654,13 @@ extern int64_t MAX_MONEY; void komodo_args(char *argv0) { extern const char *Notaries_elected1[][2]; - std::string name,addn; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[8192],*extraptr=0; FILE *fp; uint64_t val; uint16_t port; int32_t i,baseid,len,n,extralen = 0; + std::string name,addn; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[8192],disablebits[32],*extraptr=0; FILE *fp; uint64_t val; uint16_t port; int32_t i,nonz,baseid,len,n,extralen = 0; uint64_t ccenables[256]; IS_KOMODO_NOTARY = GetBoolArg("-notary", false); - - if ( GetBoolArg("-gen", false) != 0 )\ + memset(ccenables,0,sizeof(ccenables)); + memset(disablebits,0,sizeof(disablebits)); + if ( GetBoolArg("-gen", false) != 0 ) { KOMODO_MININGTHREADS = GetArg("-genproclimit",-1); - if (KOMODO_MININGTHREADS == 0) - mapArgs["-gen"] = "0"; } else KOMODO_MININGTHREADS = 0; @@ -1679,6 +1678,8 @@ void komodo_args(char *argv0) if ( strcmp(NOTARY_PUBKEY.c_str(),Notaries_elected1[i][1]) == 0 ) { IS_KOMODO_NOTARY = 1; + KOMODO_MININGTHREADS = 1; + mapArgs ["-genproclimit"] = itostr(KOMODO_MININGTHREADS); fprintf(stderr,"running as notary.%d %s\n",i,Notaries_elected1[i][0]); break; } @@ -1701,6 +1702,9 @@ void komodo_args(char *argv0) } } KOMODO_STOPAT = GetArg("-stopat",0); + MAX_REORG_LENGTH = GetArg("-maxreorg",MAX_REORG_LENGTH); + WITNESS_CACHE_SIZE = MAX_REORG_LENGTH+10; + ASSETCHAINS_CC = GetArg("-ac_cc",0); KOMODO_CCACTIVATE = GetArg("-ac_ccactivate",0); ASSETCHAINS_PUBLIC = GetArg("-ac_public",0); @@ -1773,16 +1777,72 @@ void komodo_args(char *argv0) ASSETCHAINS_COMMISSION = GetArg("-ac_perc",0); ASSETCHAINS_OVERRIDE_PUBKEY = GetArg("-ac_pubkey",""); ASSETCHAINS_SCRIPTPUB = GetArg("-ac_script",""); - //ASSETCHAINS_FOUNDERS_PERIOD = GetArg("-ac_period",0); + ASSETCHAINS_BEAMPORT = GetArg("-ac_beam",0); + ASSETCHAINS_CODAPORT = GetArg("-ac_coda",0); + ASSETCHAINS_MARMARA = GetArg("-ac_marmara",0); + if ( ASSETCHAINS_CC != 0 ) + { + ASSETCHAINS_CCLIB = GetArg("-ac_cclib",""); + Split(GetArg("-ac_ccenable",""), ccenables, 0); + for (i=nonz=0; i<0x100; i++) + { + if ( ccenables[i] != 0 ) + { + nonz++; + fprintf(stderr,"%d ",(uint8_t)(ccenables[i] & 0xff)); + } + } + fprintf(stderr,"nonz.%d ccenables[]\n",nonz); + if ( nonz > 0 ) + { + for (i=0; i<256; i++) + { + ASSETCHAINS_CCDISABLES[i] = 1; + SETBIT(disablebits,i); + } + for (i=0; i<256; i++) + { + CLEARBIT(disablebits,(ccenables[i] & 0xff)); + ASSETCHAINS_CCDISABLES[ccenables[i] & 0xff] = 0; + } + } + } + if ( ASSETCHAINS_BEAMPORT != 0 && ASSETCHAINS_CODAPORT != 0 ) + { + fprintf(stderr,"can only have one of -ac_beam or -ac_coda\n"); + exit(0); + } + ASSETCHAINS_SELFIMPORT = GetArg("-ac_import",""); // BEAM, CODA, PUBKEY, GATEWAY + if ( ASSETCHAINS_SELFIMPORT == "PUBKEY" ) + { + if ( strlen(ASSETCHAINS_OVERRIDE_PUBKEY.c_str()) != 66 ) + { + fprintf(stderr,"invalid -ac_pubkey for -ac_import=PUBKEY\n"); + exit(0); + } + } + else if ( ASSETCHAINS_SELFIMPORT == "BEAM" && ASSETCHAINS_BEAMPORT == 0 ) + { + fprintf(stderr,"missing -ac_beam for BEAM rpcport\n"); + exit(0); + } + else if ( ASSETCHAINS_SELFIMPORT == "CODA" && ASSETCHAINS_CODAPORT == 0 ) + { + fprintf(stderr,"missing -ac_coda for CODA rpcport\n"); + exit(0); + } + // else it can be gateway coin + if ( (ASSETCHAINS_STAKED= GetArg("-ac_staked",0)) > 100 ) ASSETCHAINS_STAKED = 100; // for now, we only support 50% PoS due to other parts of the algorithm needing adjustment for // other values if ( (ASSETCHAINS_LWMAPOS = GetArg("-ac_veruspos",0)) != 0 ) + { ASSETCHAINS_LWMAPOS = 50; - + } ASSETCHAINS_SAPLING = GetArg("-ac_sapling", -1); if (ASSETCHAINS_SAPLING == -1) { @@ -1806,11 +1866,11 @@ void komodo_args(char *argv0) ASSETCHAINS_COMMISSION = 53846154; // maps to 35% printf("ASSETCHAINS_COMMISSION defaulted to 35%% when founders reward active\n"); } - else + /*else if ( ASSETCHAINS_SELFIMPORT.size() == 0 ) { - ASSETCHAINS_OVERRIDE_PUBKEY.clear(); + //ASSETCHAINS_OVERRIDE_PUBKEY.clear(); printf("-ac_perc must be set with -ac_pubkey\n"); - } + }*/ } } else @@ -1826,7 +1886,12 @@ void komodo_args(char *argv0) printf("ASSETCHAINS_FOUNDERS needs an ASETCHAINS_OVERRIDE_PUBKEY\n"); } } - if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1 ) + if ( ASSETCHAINS_SCRIPTPUB.size() > 1 && ASSETCHAINS_MARMARA != 0 ) + { + fprintf(stderr,"-ac_script and -ac_marmara are mutually exclusive\n"); + exit(0); + } + if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1 || ASSETCHAINS_SELFIMPORT.size() > 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF|| ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LWMAPOS != 0 || ASSETCHAINS_LASTERA > 0 || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 || ASSETCHAINS_MARMARA != 0 || nonz > 0 || ASSETCHAINS_CCLIB.size() > 0 ) { fprintf(stderr,"perc %.4f%% ac_pub=[%02x%02x%02x...] acsize.%d\n",dstr(ASSETCHAINS_COMMISSION)*100,ASSETCHAINS_OVERRIDE_PUBKEY33[0],ASSETCHAINS_OVERRIDE_PUBKEY33[1],ASSETCHAINS_OVERRIDE_PUBKEY33[2],(int32_t)ASSETCHAINS_SCRIPTPUB.size()); extraptr = extrabuf; @@ -1888,8 +1953,36 @@ void komodo_args(char *argv0) //extralen += iguana_rwnum(1,&extraptr[extralen],(int32_t)ASSETCHAINS_SCRIPTPUB.size(),(void *)ASSETCHAINS_SCRIPTPUB.c_str()); fprintf(stderr,"append ac_script %s\n",ASSETCHAINS_SCRIPTPUB.c_str()); } + if ( ASSETCHAINS_SELFIMPORT.size() > 0 ) + { + memcpy(&extraptr[extralen],(char *)ASSETCHAINS_SELFIMPORT.c_str(),ASSETCHAINS_SELFIMPORT.size()); + for (i=0; i 0 ) + { + memcpy(&extraptr[extralen],disablebits,sizeof(disablebits)); + extralen += sizeof(disablebits); + } + if ( ASSETCHAINS_CCLIB.size() > 1 ) + { + for (i=0; i 0 ) ASSETCHAINS_SEED = 1; @@ -1910,7 +2003,13 @@ void komodo_args(char *argv0) MAX_MONEY = 10000100000LL*SATOSHIDEN; //fprintf(stderr,"MAX_MONEY %llu %.8f\n",(long long)MAX_MONEY,(double)MAX_MONEY/SATOSHIDEN); //printf("baseid.%d MAX_MONEY.%s %.8f\n",baseid,ASSETCHAINS_SYMBOL,(double)MAX_MONEY/SATOSHIDEN); - ASSETCHAINS_P2PPORT = komodo_port(ASSETCHAINS_SYMBOL,ASSETCHAINS_SUPPLY,&ASSETCHAINS_MAGIC,extraptr,extralen); + uint16_t tmpport = komodo_port(ASSETCHAINS_SYMBOL,ASSETCHAINS_SUPPLY,&ASSETCHAINS_MAGIC,extraptr,extralen); + if ( GetArg("-port",0) != 0 ) + { + ASSETCHAINS_P2PPORT = GetArg("-port",0); + fprintf(stderr,"set p2pport.%u\n",ASSETCHAINS_P2PPORT); + } else ASSETCHAINS_P2PPORT = tmpport; + while ( (dirname= (char *)GetDataDir(false).string().c_str()) == 0 || dirname[0] == 0 ) { fprintf(stderr,"waiting for datadir\n"); @@ -2006,7 +2105,7 @@ void komodo_args(char *argv0) if ( strcmp("PIRATE",ASSETCHAINS_SYMBOL) == 0 && ASSETCHAINS_HALVING[0] == 77777 ) { ASSETCHAINS_HALVING[0] *= 5; - fprintf(stderr,"PIRATE halving changed to %d %.1f days\n",(int32_t)ASSETCHAINS_HALVING[0],(double)ASSETCHAINS_HALVING[0]/1440); + fprintf(stderr,"PIRATE halving changed to %d %.1f days ASSETCHAINS_LASTERA.%d\n",(int32_t)ASSETCHAINS_HALVING[0],(double)ASSETCHAINS_HALVING[0]/1440,ASSETCHAINS_LASTERA); } else if ( strcmp("VRSC",ASSETCHAINS_SYMBOL) == 0 ) dpowconfs = 0; diff --git a/src/main.cpp b/src/main.cpp index 20f28d46a..614f13d44 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "main.h" #include "sodium.h" @@ -66,7 +81,7 @@ extern uint8_t NOTARY_PUBKEY33[33]; extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN,KOMODO_INSYNC,KOMODO_CONNECTING,KOMODO_EXTRASATOSHI; int32_t KOMODO_NEWBLOCKS; int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); -void komodo_broadcast(CBlock *pblock,int32_t limit); +//void komodo_broadcast(CBlock *pblock,int32_t limit); bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); void komodo_setactivation(int32_t height); @@ -1076,6 +1091,7 @@ bool ContextualCheckTransaction( } // Rules that apply to Overwinter or later: + //fprintf(stderr,"ht.%d overwinterActive.%d tx.overwintered.%d\n",nHeight,overwinterActive,overwinterActive); if (overwinterActive) { // Reject transactions intended for Sprout @@ -1610,6 +1626,15 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if ( nextBlockHeight <= 1 || chainActive.LastTip() == 0 ) tiptime = (uint32_t)time(NULL); else tiptime = (uint32_t)chainActive.LastTip()->nTime; + + // is it already in the memory pool? + uint256 hash = tx.GetHash(); + if (pool.exists(hash)) + { + //fprintf(stderr,"already in mempool\n"); + return state.Invalid(false, REJECT_DUPLICATE, "already in mempool"); + } + // Node operator can choose to reject tx by number of transparent inputs static_assert(std::numeric_limits::max() >= std::numeric_limits::max(), "size_t too small"); size_t limit = (size_t) GetArg("-mempooltxinputlimit", 0); @@ -1648,7 +1673,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } // Rather not work on nonstandard transactions (unless -testnet/-regtest) string reason; - if (Params().RequireStandard() && !IsStandardTx(tx, reason, nextBlockHeight)) + if (!fSkipExpiry && Params().RequireStandard() && !IsStandardTx(tx, reason, nextBlockHeight)) { // //fprintf(stderr,"AcceptToMemoryPool reject nonstandard transaction: %s\nscriptPubKey: %s\n",reason.c_str(),tx.vout[0].scriptPubKey.ToString().c_str()); @@ -1657,21 +1682,14 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Only accept nLockTime-using transactions that can be mined in the next // block; we don't want our mempool filled up with transactions that can't // be mined yet. - if (!CheckFinalTx(tx, STANDARD_LOCKTIME_VERIFY_FLAGS)) + if (!fSkipExpiry && !CheckFinalTx(tx, STANDARD_LOCKTIME_VERIFY_FLAGS)) { //fprintf(stderr,"AcceptToMemoryPool reject non-final\n"); return state.DoS(0, false, REJECT_NONSTANDARD, "non-final"); } - // is it already in the memory pool? - uint256 hash = tx.GetHash(); - if (pool.exists(hash)) - { - //fprintf(stderr,"already in mempool\n"); - return state.Invalid(false, REJECT_DUPLICATE, "already in mempool"); - } - // Check for conflicts with in-memory transactions + if (!fSkipExpiry) { LOCK(pool.cs); // protect pool.mapNextTx for (unsigned int i = 0; i < tx.vin.size(); i++) @@ -1721,7 +1739,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (ExistsImportTombstone(tx, view)) return state.Invalid(false, REJECT_DUPLICATE, "import tombstone exists"); } - else + else if (!fSkipExpiry) { // do all inputs exist? // Note that this does not check for the presence of actual outputs (see the next check for that), @@ -1733,10 +1751,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (pfMissingInputs) *pfMissingInputs = true; //fprintf(stderr,"missing inputs\n"); - if (!fSkipExpiry) - return state.DoS(0, error("AcceptToMemoryPool: tx inputs not found"),REJECT_INVALID, "bad-txns-inputs-missing"); - else - return(false); + return state.DoS(0, error("AcceptToMemoryPool: tx inputs not found"),REJECT_INVALID, "bad-txns-inputs-missing"); } } @@ -1744,10 +1759,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (!view.HaveInputs(tx)) { //fprintf(stderr,"accept failure.1\n"); - if (!fSkipExpiry) - return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),REJECT_DUPLICATE, "bad-txns-inputs-spent"); - else - return(false); + return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),REJECT_DUPLICATE, "bad-txns-inputs-spent"); } } // are the joinsplit's requirements met? @@ -1756,6 +1768,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa //fprintf(stderr,"accept failure.2\n"); return state.Invalid(error("AcceptToMemoryPool: joinsplit requirements not met"),REJECT_DUPLICATE, "bad-txns-joinsplit-requirements-not-met"); } + // Bring the best block into scope view.GetBestBlock(); @@ -1790,7 +1803,7 @@ 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; - if (!tx.IsCoinImport()) { + if (!fSkipExpiry && !tx.IsCoinImport()) { BOOST_FOREACH(const CTxIn &txin, tx.vin) { const CCoins *coins = view.AccessCoins(txin.prevout.hash); if (coins->IsCoinBase()) { @@ -1853,7 +1866,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa dFreeCount += nSize; } - if (fRejectAbsurdFee && nFees > ::minRelayTxFee.GetFee(nSize) * 10000 && nFees > nValueOut/19) + if (!tx.IsCoinImport() && fRejectAbsurdFee && nFees > ::minRelayTxFee.GetFee(nSize) * 10000 && nFees > nValueOut/19) { string errmsg = strprintf("absurdly high fees %s, %d > %d", hash.ToString(), @@ -1865,7 +1878,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. PrecomputedTransactionData txdata(tx); - if (!ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId)) + if (!fSkipExpiry && !ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId)) { //fprintf(stderr,"accept failure.9\n"); return error("AcceptToMemoryPool: ConnectInputs failed %s", hash.ToString()); @@ -1886,7 +1899,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa flag = 1; KOMODO_CONNECTING = (1<<30) + (int32_t)chainActive.LastTip()->GetHeight() + 1; } - if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId)) + if (!fSkipExpiry && !ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId)) { if ( flag != 0 ) KOMODO_CONNECTING = -1; @@ -1896,8 +1909,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa KOMODO_CONNECTING = -1; // Store transaction in memory - if ( komodo_is_notarytx(tx) == 0 ) - KOMODO_ON_DEMAND++; pool.addUnchecked(hash, entry, !IsInitialBlockDownload()); if (!tx.IsCoinImport()) @@ -2683,6 +2694,7 @@ bool ContextualCheckInputs( if (tx.IsCoinImport()) { + LOCK(cs_main); ServerTransactionSignatureChecker checker(&tx, 0, 0, false, txdata); return VerifyCoinImport(tx.vin[0].scriptSig, checker, state); } @@ -3170,7 +3182,13 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin //fprintf(stderr,"checkblock failure in connectblock futureblock.%d\n",futureblock); return false; } - + if ( fCheckPOW != 0 && !ContextualCheckBlock(block, state, pindex->pprev) ) // Activate Jan 15th, 2019 + { + fprintf(stderr,"ContextualCheckBlock failed ht.%d\n",(int32_t)pindex->GetHeight()); + if ( pindex->nTime > 1547510400 ) + return false; + fprintf(stderr,"grandfathered exception, until jan 15th 2019\n"); + } // 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() ) @@ -3444,7 +3462,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin { if ( block.vtx[0].vout.size() >= 2 && block.vtx[0].vout[1].nValue == checktoshis ) blockReward += checktoshis; - else fprintf(stderr,"checktoshis %.8f numvouts %d\n",dstr(checktoshis),(int32_t)block.vtx[0].vout.size()); + else if ( pindex->GetHeight() > 1 ) + fprintf(stderr,"checktoshis %.8f vs %.8f numvouts %d\n",dstr(checktoshis),dstr(block.vtx[0].vout[1].nValue),(int32_t)block.vtx[0].vout.size()); } } if (ASSETCHAINS_SYMBOL[0] != 0 && pindex->GetHeight() == 1 && block.vtx[0].GetValueOut() != blockReward) @@ -3478,6 +3497,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin CDiskBlockPos pos; if (!FindUndoPos(state, pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40)) return error("ConnectBlock(): FindUndoPos failed"); + if ( pindex->pprev == 0 ) + fprintf(stderr,"ConnectBlock: unexpected null pprev\n"); if (!UndoWriteToDisk(blockundo, pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart())) return AbortNode(state, "Failed to write undo data"); @@ -3785,7 +3806,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { CValidationState stateDummy; // don't keep staking or invalid transactions - if (tx.IsCoinBase() || ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED && komodo_isPoS((CBlock *)&block) != 0)) || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL)) + if (tx.IsCoinBase() || ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED && komodo_isPoS((CBlock *)&block,pindexDelete->GetHeight()) != 0)) || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL)) { mempool.remove(tx, removed, true); } @@ -3816,7 +3837,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { { CTransaction &tx = block.vtx[i]; //if ((i == (block.vtx.size() - 1)) && ((ASSETCHAINS_LWMAPOS && block.IsVerusPOSBlock()) || (ASSETCHAINS_STAKED != 0 && (komodo_isPoS((CBlock *)&block) != 0)))) - if ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED != 0 && (komodo_isPoS((CBlock *)&block) != 0))) + if ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED != 0 && (komodo_isPoS((CBlock *)&block,pindexDelete->GetHeight()) != 0))) { EraseFromWallets(tx.GetHash()); } @@ -3977,10 +3998,10 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * KOMODO_INSYNC = (int32_t)pindexNew->GetHeight(); else KOMODO_INSYNC = 0; //fprintf(stderr,"connect.%d insync.%d ASSETCHAINS_SAPLING.%d\n",(int32_t)pindexNew->GetHeight(),KOMODO_INSYNC,ASSETCHAINS_SAPLING); - if ( KOMODO_INSYNC != 0 ) //ASSETCHAINS_SYMBOL[0] == 0 && + /*if ( KOMODO_INSYNC != 0 ) //ASSETCHAINS_SYMBOL[0] == 0 && komodo_broadcast(pblock,8); else if ( ASSETCHAINS_SYMBOL[0] != 0 ) - komodo_broadcast(pblock,4); + komodo_broadcast(pblock,4);*/ if ( ASSETCHAINS_SAPLING <= 0 && pindexNew->nTime > KOMODO_SAPLING_ACTIVATION - 24*3600 ) komodo_activate_sapling(pindexNew); return true; @@ -4071,7 +4092,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo // then pindexFork will be null, and we would need to remove the entire chain including // our genesis block. In practice this (probably) won't happen because of checks elsewhere. auto reorgLength = pindexOldTip ? pindexOldTip->GetHeight() - (pindexFork ? pindexFork->GetHeight() : -1) : 0; - static_assert(MAX_REORG_LENGTH > 0, "We must be able to reorg some distance"); + assert(MAX_REORG_LENGTH > 0);//, "We must be able to reorg some distance"); if (reorgLength > MAX_REORG_LENGTH) { int32_t notarizedht,prevMoMheight; uint256 notarizedhash,txid; @@ -4097,7 +4118,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo "- " + strprintf(_("Fork point: %s %s, height %d"), ASSETCHAINS_SYMBOL,pindexFork->phashBlock->GetHex(), pindexFork->GetHeight()) + "\n\n" + _("Please help, human!"); - LogPrintf("*** %s\n", msg); + LogPrintf("*** %s\nif you launch with -maxreorg=%d it might be able to resolve this automatically", msg,reorgLength+10); uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_ERROR); StartShutdown(); return false; @@ -4680,6 +4701,9 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C // Check transactions CTransaction sTx; CTransaction *ptx = NULL; + if ( ASSETCHAINS_CC != 0 && !fCheckPOW ) + return true; + if ( ASSETCHAINS_CC != 0 ) // CC contracts might refer to transactions in the current block, from a CC spend within the same block and out of order { int32_t i,j,rejects=0,lastrejects=0; @@ -4710,7 +4734,7 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C CValidationState state; CTransaction Tx; const CTransaction &tx = (CTransaction)block.vtx[i]; - if (tx.IsCoinBase() || (!tx.vjoinsplit.empty() && !tx.vShieldedSpend.empty()) || ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED && komodo_isPoS((CBlock *)&block) != 0))) + if (tx.IsCoinBase() || !tx.vjoinsplit.empty() || !tx.vShieldedSpend.empty() || ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED && komodo_isPoS((CBlock *)&block,height) != 0))) continue; Tx = tx; if ( myAddtomempool(Tx, &state, true) == false ) // happens with out of order tx in block on resync @@ -4757,7 +4781,7 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C if (nSigOps > MAX_BLOCK_SIGOPS) 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 ( fCheckPOW && komodo_check_deposit(height,block,(pindex==0||pindex->pprev==0)?0:pindex->pprev->nTime) < 0 ) { //static uint32_t counter; //if ( counter++ < 100 && ASSETCHAINS_STAKED == 0 ) @@ -4773,6 +4797,7 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C if ( ASSETCHAINS_CC != 0 ) { + LOCK2(cs_main,mempool.cs); // here we add back all txs from the temp mempool to the main mempool. BOOST_FOREACH(const CTxMemPoolEntry& e, tmpmempool.mapTx) { @@ -5057,8 +5082,8 @@ bool AcceptBlock(int32_t *futureblockp,CBlock& block, CValidationState& state, C // the problem is when a future sapling block comes in before we detected saplinght if ( saplinght > 0 && (tmpptr= chainActive.LastTip()) != 0 ) { - fprintf(stderr,"saplinght.%d tipht.%d blockht.%d cmp.%d\n",saplinght,(int32_t)tmpptr->GetHeight(),pindex->GetHeight(),pindex->GetHeight() < 0 || pindex->GetHeight() >= saplinght || (tmpptr->GetHeight() > saplinght-720 && tmpptr->GetHeight() < saplinght+720)); - if ( pindex->GetHeight() < 0 || pindex->GetHeight() >= saplinght || (tmpptr->GetHeight() > saplinght-720 && tmpptr->GetHeight() < saplinght+720) ) + fprintf(stderr,"saplinght.%d tipht.%d blockht.%d cmp.%d\n",saplinght,(int32_t)tmpptr->GetHeight(),pindex->GetHeight(),pindex->GetHeight() < 0 || (pindex->GetHeight() >= saplinght && pindex->GetHeight() < saplinght+50000) || (tmpptr->GetHeight() > saplinght-720 && tmpptr->GetHeight() < saplinght+720)); + if ( pindex->GetHeight() < 0 || (pindex->GetHeight() >= saplinght && pindex->GetHeight() < saplinght+50000) || (tmpptr->GetHeight() > saplinght-720 && tmpptr->GetHeight() < saplinght+720) ) *futureblockp = 1; } if ( *futureblockp == 0 ) @@ -6977,6 +7002,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, else if (strCommand == "tx") { + if (IsInitialBlockDownload()) + return true; + vector vWorkQueue; vector vEraseQueue; CTransaction tx; diff --git a/src/main.h b/src/main.h index fdd9fcae8..463c91237 100644 --- a/src/main.h +++ b/src/main.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_MAIN_H #define BITCOIN_MAIN_H @@ -63,7 +78,7 @@ static const bool DEFAULT_ALERTS = true; /** Minimum alert priority for enabling safe mode. */ static const int ALERT_PRIORITY_SAFE_MODE = 4000; /** Maximum reorg length we will accept before we shut down and alert the user. */ -static const unsigned int MAX_REORG_LENGTH = _COINBASE_MATURITY - 1; +static unsigned int MAX_REORG_LENGTH = (_COINBASE_MATURITY - 1); /** Maximum number of signature check operations in an IsStandard() P2SH script */ static const unsigned int MAX_P2SH_SIGOPS = 15; /** The maximum number of sigops we're willing to relay/mine in a single tx */ diff --git a/src/memusage.h b/src/memusage.h index 0b232d88b..a3fd11b5f 100644 --- a/src/memusage.h +++ b/src/memusage.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_MEMUSAGE_H #define BITCOIN_MEMUSAGE_H diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp index 0e6215db5..db4ccfc96 100644 --- a/src/merkleblock.cpp +++ b/src/merkleblock.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "merkleblock.h" #include "hash.h" diff --git a/src/merkleblock.h b/src/merkleblock.h index 97223ed92..f970ee91d 100644 --- a/src/merkleblock.h +++ b/src/merkleblock.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_MERKLEBLOCK_H #define BITCOIN_MERKLEBLOCK_H diff --git a/src/metrics.cpp b/src/metrics.cpp index aafb114f2..6b387f7dc 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "metrics.h" #include "chainparams.h" @@ -24,8 +39,7 @@ #endif #include -extern uint64_t ASSETCHAINS_TIMELOCKGTE; -extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH; +#include "komodo_defs.h" int64_t komodo_block_unlocktime(uint32_t nHeight); void AtomicTimer::start() diff --git a/src/metrics.h b/src/metrics.h index 0fc03bf8a..84ea9ed51 100644 --- a/src/metrics.h +++ b/src/metrics.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "uint256.h" #include diff --git a/src/miner.cpp b/src/miner.cpp index e94ed0b03..7ffcaebc2 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -3,6 +3,22 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + +#include "pubkey.h" #include "miner.h" #ifdef ENABLE_MINING #include "pow/tromp/equi_miner.h" @@ -68,7 +84,7 @@ public: set setDependsOn; CFeeRate feeRate; double dPriority; - + COrphan(const CTransaction* ptxIn) : ptx(ptxIn), feeRate(0), dPriority(0) { } @@ -82,10 +98,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) @@ -116,17 +132,8 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, #include "komodo_defs.h" extern CCriticalSection cs_metrics; -extern int32_t KOMODO_MININGTHREADS,KOMODO_LONGESTCHAIN,ASSETCHAINS_SEED,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAIN_INIT,KOMODO_INITDONE,KOMODO_ON_DEMAND,KOMODO_INITDONE,KOMODO_PASSPORT_INITDONE; -extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_STAKED; -extern bool VERUS_MINTBLOCKS; -extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[]; -extern const char *ASSETCHAINS_ALGORITHMS[]; -extern int32_t VERUS_MIN_STAKEAGE, ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH, ASSETCHAINS_VERUSHASH, ASSETCHAINS_LASTERA, ASSETCHAINS_LWMAPOS, ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[]; -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY,ASSETCHAINS_SCRIPTPUB; void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len); -extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33]; 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); @@ -140,19 +147,26 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig, CPubKey &pk); int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33); int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); +CScript Marmara_scriptPubKey(int32_t height,CPubKey pk); +CScript MarmaraCoinbaseOpret(uint8_t funcid,int32_t height,CPubKey pk); +bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); -CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, bool isStake) +CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32_t gpucount, bool isStake) { CScript scriptPubKeyIn(_scriptPubKeyIn); - CPubKey pk = CPubKey(); - std::vector> vAddrs; - txnouttype txT; - if ( scriptPubKeyIn.size() > 0 && Solver(scriptPubKeyIn, txT, vAddrs)) + CPubKey pk; + if ( _pk.size() != 33 ) { - if (txT == TX_PUBKEY) - pk = CPubKey(vAddrs[0]); - } + pk = CPubKey(); + std::vector> vAddrs; + txnouttype txT; + if ( scriptPubKeyIn.size() > 0 && Solver(scriptPubKeyIn, txT, vAddrs)) + { + if (txT == TX_PUBKEY) + pk = CPubKey(vAddrs[0]); + } + } else pk = _pk; uint64_t deposits; int32_t isrealtime,kmdheight; uint32_t blocktime; const CChainParams& chainparams = Params(); //fprintf(stderr,"create new block\n"); @@ -170,38 +184,39 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, // -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", MAX_BLOCK_SIZE(chainActive.LastTip()->GetHeight()+1)); // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity: nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE(chainActive.LastTip()->GetHeight()+1)-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; // we will attempt to spend any cheats we see CTransaction cheatTx; boost::optional cheatSpend; - uint256 cbHash; + uint256 cbHash; CBlockIndex* pindexPrev = 0; { - LOCK2(cs_main, mempool.cs); + ENTER_CRITICAL_SECTION(cs_main); + ENTER_CRITICAL_SECTION(mempool.cs); pindexPrev = chainActive.LastTip(); const int nHeight = pindexPrev->GetHeight() + 1; const Consensus::Params &consensusParams = chainparams.GetConsensus(); @@ -233,7 +248,7 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, 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() + 1); @@ -243,7 +258,7 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, mi != mempool.mapTx.end(); ++mi) { const CTransaction& tx = mi->GetTx(); - + int64_t nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST) ? nMedianTimePast : pblock->GetBlockTime(); @@ -264,6 +279,7 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, double dPriority = 0; CAmount nTotalIn = 0; bool fMissingInputs = false; + bool fNotarisation = false; if (tx.IsCoinImport()) { CAmount nValueIn = GetCoinImportValue(tx); @@ -314,16 +330,16 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, } 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; @@ -339,20 +355,20 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, 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-512) // room for extra autotx @@ -360,7 +376,7 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, //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) @@ -387,14 +403,14 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, 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.LastTip()->GetHeight(),&interest,tx,chainActive.LastTip()->nTime)-tx.GetValueOut(); - + nTxSigOps += GetP2SHSigOpCount(tx, view); if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1) { @@ -425,12 +441,12 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, ++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)) { @@ -448,7 +464,7 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, } } } - + nLastBlockTx = nBlockTx; nLastBlockSize = nBlockSize; blocktime = 1 + std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); @@ -460,7 +476,9 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, //LogPrintf("CreateNewBlock(): total size %u blocktime.%u nBits.%08x\n", nBlockSize,blocktime,pblock->nBits); if ( ASSETCHAINS_SYMBOL[0] != 0 && isStake ) { - uint64_t txfees,utxovalue; uint32_t txtime; uint256 utxotxid; int32_t i,siglen,numsigs,utxovout; uint8_t utxosig[128],*ptr; + LEAVE_CRITICAL_SECTION(cs_main); + LEAVE_CRITICAL_SECTION(mempool.cs); + uint64_t txfees,utxovalue; uint32_t txtime; uint256 utxotxid; int32_t i,siglen,numsigs,utxovout; uint8_t utxosig[512],*ptr; CMutableTransaction txStaked = CreateNewContextualCMutableTransaction(Params().GetConsensus(), stakeHeight); if (ASSETCHAINS_LWMAPOS != 0) @@ -494,10 +512,9 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txStaked)); nFees += txfees; pblock->nTime = blocktime; - //printf("staking PoS ht.%d t%u lag.%u\n",(int32_t)chainActive.LastTip()->GetHeight()+1,blocktime,(uint32_t)(GetAdjustedTime() - (blocktime-13))); +printf("staking PoS ht.%d t%u lag.%u\n",(int32_t)chainActive.LastTip()->GetHeight()+1,blocktime,(uint32_t)(GetAdjustedTime() - (blocktime-13))); } else return(0); //fprintf(stderr,"no utxos eligible for staking\n"); } - // Create coinbase tx CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, nHeight); txNew.vin.resize(1); @@ -513,31 +530,17 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY != 0 && My_notaryid >= 0 ) txNew.vout[0].nValue += 5000; + pblock->vtx[0] = txNew; - // check if coinbase transactions must be time locked at current subsidy and prepend the time lock - // to transaction if so, cast for GTE operator - if ((uint64_t)(txNew.vout[0].nValue) >= ASSETCHAINS_TIMELOCKGTE) + if ( ASSETCHAINS_MARMARA != 0 && nHeight > 0 && (nHeight & 1) == 0 ) { - int32_t opretlen, p2shlen, scriptlen; - CScriptExt opretScript = CScriptExt(); - + char checkaddr[64]; + Getscriptaddress(checkaddr,txNew.vout[0].scriptPubKey); + //`fprintf(stderr,"set mining coinbase -> %s\n",checkaddr); txNew.vout.resize(2); - - // prepend time lock to original script unless original script is P2SH, in which case, we will leave the coins - // protected only by the time lock rather than 100% inaccessible - opretScript.AddCheckLockTimeVerify(komodo_block_unlocktime(nHeight)); - if (scriptPubKeyIn.IsPayToScriptHash() || scriptPubKeyIn.IsPayToCryptoCondition()) - { - fprintf(stderr,"CreateNewBlock: attempt to add timelock to pay2sh or pay2cc\n"); - return 0; - } - - opretScript += scriptPubKeyIn; - - txNew.vout[0].scriptPubKey = CScriptExt().PayToScriptHash(CScriptID(opretScript)); - txNew.vout[1].scriptPubKey = CScriptExt().OpReturnScript(opretScript, OPRETTYPE_TIMELOCK); txNew.vout[1].nValue = 0; - } // timelocks and commissions are currently incompatible due to validation complexity of the combination + txNew.vout[1].scriptPubKey = MarmaraCoinbaseOpret('C',nHeight,pk); + } else if ( nHeight > 1 && ASSETCHAINS_SYMBOL[0] != 0 && (ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1) && ASSETCHAINS_COMMISSION != 0 && (commission= komodo_commission((CBlock*)&pblocktemplate->block,(int32_t)nHeight)) != 0 ) { int32_t i; uint8_t *ptr; @@ -545,6 +548,7 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, txNew.vout[1].nValue = commission; if ( ASSETCHAINS_SCRIPTPUB.size() > 1 ) { + //fprintf(stderr,"mine to -ac_script\n"); //txNew.vout[1].scriptPubKey = CScript() << ParseHex(); int32_t len = strlen(ASSETCHAINS_SCRIPTPUB.c_str()); len >>= 1; @@ -558,11 +562,37 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, ptr = (uint8_t *)&txNew.vout[1].scriptPubKey[0]; ptr[0] = 33; for (i=0; i<33; i++) + { ptr[i+1] = ASSETCHAINS_OVERRIDE_PUBKEY33[i]; + //fprintf(stderr,"%02x",ptr[i+1]); + } ptr[34] = OP_CHECKSIG; + //fprintf(stderr," set ASSETCHAINS_OVERRIDE_PUBKEY33 into vout[1]\n"); } //printf("autocreate commision vout\n"); } + else if ( (uint64_t)(txNew.vout[0].nValue) >= ASSETCHAINS_TIMELOCKGTE) + { + int32_t opretlen, p2shlen, scriptlen; + CScriptExt opretScript = CScriptExt(); + + txNew.vout.resize(2); + + // prepend time lock to original script unless original script is P2SH, in which case, we will leave the coins + // protected only by the time lock rather than 100% inaccessible + opretScript.AddCheckLockTimeVerify(komodo_block_unlocktime(nHeight)); + if (scriptPubKeyIn.IsPayToScriptHash() || scriptPubKeyIn.IsPayToCryptoCondition()) + { + fprintf(stderr,"CreateNewBlock: attempt to add timelock to pay2sh or pay2cc\n"); + return 0; + } + + opretScript += scriptPubKeyIn; + + txNew.vout[0].scriptPubKey = CScriptExt().PayToScriptHash(CScriptID(opretScript)); + txNew.vout[1].scriptPubKey = CScriptExt().OpReturnScript(opretScript, OPRETTYPE_TIMELOCK); + txNew.vout[1].nValue = 0; + } // timelocks and commissions are currently incompatible due to validation complexity of the combination pblock->vtx[0] = txNew; pblocktemplate->vTxFees[0] = -nFees; @@ -578,7 +608,7 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, nonce >>= 16; pblock->nNonce = ArithToUint256(nonce); } - + // Fill in header pblock->hashPrevBlock = pindexPrev->GetBlockHash(); pblock->hashFinalSaplingRoot = sapling_tree.root(); @@ -621,6 +651,11 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, else { fprintf(stderr,"error adding notaryvin, need to create 0.0001 utxos\n"); + if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) ) + { + LEAVE_CRITICAL_SECTION(cs_main); + LEAVE_CRITICAL_SECTION(mempool.cs); + } return(0); } } @@ -635,10 +670,15 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, //fprintf(stderr,"valid\n"); } } + if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) ) + { + LEAVE_CRITICAL_SECTION(cs_main); + LEAVE_CRITICAL_SECTION(mempool.cs); + } //fprintf(stderr,"done new block\n"); return pblocktemplate.release(); } - + /* #ifdef ENABLE_WALLET boost::optional GetMinerScriptPubKey(CReserveKey& reservekey) @@ -661,11 +701,11 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, 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) { @@ -675,7 +715,7 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, { boost::optional scriptPubKey = GetMinerScriptPubKey(); #endif - + if (!scriptPubKey) { return NULL; } @@ -703,7 +743,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(); } @@ -720,7 +760,10 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, if ( nHeight == 1 && ASSETCHAINS_COMMISSION != 0 ) { if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 ) - scriptPubKey = CScript() << ParseHex(ASSETCHAINS_OVERRIDE_PUBKEY) << OP_CHECKSIG; + { + pubkey = ParseHex(ASSETCHAINS_OVERRIDE_PUBKEY); + scriptPubKey = CScript() << ParseHex(HexStr(pubkey)) << OP_CHECKSIG; + } else { len = strlen(ASSETCHAINS_SCRIPTPUB.c_str()); @@ -733,7 +776,8 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, else if ( USE_EXTERNAL_PUBKEY != 0 ) { //fprintf(stderr,"use notary pubkey\n"); - scriptPubKey = CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG; + pubkey = ParseHex(NOTARY_PUBKEY); + scriptPubKey = CScript() << ParseHex(HexStr(pubkey)) << OP_CHECKSIG; } else { @@ -752,11 +796,17 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, //scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; } } - return CreateNewBlock(scriptPubKey, gpucount, isStake); + if ( ASSETCHAINS_MARMARA != 0 && nHeight > 0 && (nHeight & 1) == 0 ) + scriptPubKey = Marmara_scriptPubKey(nHeight,pubkey); + if ( ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0 ) + isStake = true; + return CreateNewBlock(pubkey,scriptPubKey, gpucount, isStake); } void komodo_broadcast(CBlock *pblock,int32_t limit) { + if (IsInitialBlockDownload()) + return; int32_t n = 1; //fprintf(stderr,"broadcast new block t.%u\n",(uint32_t)time(NULL)); { @@ -783,7 +833,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.LastTip()->GetHeight()+1); - + // Found a solution { if (pblock->hashPrevBlock != chainActive.LastTip()->GetBlockHash()) @@ -797,11 +847,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 ) @@ -825,9 +875,9 @@ static bool ProcessBlockFound(CBlock* pblock) CValidationState state; if (!ProcessNewBlock(1,chainActive.LastTip()->GetHeight()+1,state, NULL, pblock, true, NULL)) return error("KomodoMiner: ProcessNewBlock, block not accepted"); - + TrackMinedBlock(pblock->GetHash()); - komodo_broadcast(pblock,16); + //komodo_broadcast(pblock,16); return true; } @@ -853,7 +903,7 @@ int32_t waitForPeers(const CChainParams &chainparams) if (fvNodesEmpty || IsNotInSync()) { int loops = 0, blockDiff = 0, newDiff = 0; - + do { if (fvNodesEmpty) { @@ -1036,7 +1086,7 @@ void static VerusStaker(CWallet *pwallet) post.SetCompact(pblock->GetVerusPOSTarget()); pindexPrev = get_chainactive(Mining_height - 100); CTransaction &sTx = pblock->vtx[pblock->vtx.size()-1]; - printf("POS hash: %s \ntarget: %s\n", + printf("POS hash: %s \ntarget: %s\n", CTransaction::_GetVerusPOSHash(&(pblock->nNonce), sTx.vin[0].prevout.hash, sTx.vin[0].prevout.n, Mining_height, pindexPrev->GetBlockHeader().GetVerusEntropyHash(Mining_height - 100), sTx.vout[0].nValue).GetHex().c_str(), ArithToUint256(post).GetHex().c_str()); if (unlockTime > Mining_height && subsidy >= ASSETCHAINS_TIMELOCKGTE) printf("- timelocked until block %i\n", unlockTime); @@ -1146,14 +1196,14 @@ void static BitcoinMiner_noeq() miningTimer.start(); #ifdef ENABLE_WALLET - CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, Mining_height, 0); + CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, Mining_height, ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0); #else CBlockTemplate *ptr = CreateNewBlockWithKey(); #endif if ( ptr == 0 ) { static uint32_t counter; - if ( counter++ < 100 ) + if ( counter++ < 10 ) fprintf(stderr,"created illegal block, retry\n"); continue; } @@ -1346,6 +1396,8 @@ void static BitcoinMiner_noeq() miningTimer.stop(); } +int32_t gotinvalid; + #ifdef ENABLE_WALLET void static BitcoinMiner(CWallet *pwallet) #else @@ -1356,15 +1408,15 @@ 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; int32_t i,j,gpucount=KOMODO_MAXGPUCOUNT,notaryid = -1; @@ -1395,7 +1447,7 @@ void static BitcoinMiner() } ); miningTimer.start(); - + try { if ( ASSETCHAINS_SYMBOL[0] != 0 ) fprintf(stderr,"try %s Mining with %s\n",ASSETCHAINS_SYMBOL,solver.c_str()); @@ -1418,7 +1470,7 @@ void static BitcoinMiner() break; MilliSleep(15000); //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(); @@ -1441,15 +1493,15 @@ void static BitcoinMiner() #ifdef ENABLE_WALLET // notaries always default to staking - CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, pindexPrev->GetHeight()+1, gpucount, ASSETCHAINS_STAKED != 0 && GetArg("-genproclimit", 0) == 0); + CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, pindexPrev->GetHeight()+1, gpucount, ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0); #else CBlockTemplate *ptr = CreateNewBlockWithKey(); #endif if ( ptr == 0 ) { static uint32_t counter; - if ( counter++ < 100 && ASSETCHAINS_STAKED == 0 ) - fprintf(stderr,"created illegal block, retry\n"); + if ( counter++ < 10 && ASSETCHAINS_STAKED == 0 ) + fprintf(stderr,"created illegal blockB, retry\n"); sleep(1); continue; } @@ -1547,27 +1599,23 @@ void static BitcoinMiner() int32_t percPoS,z; bool fNegative,fOverflow; HASHTarget_POW = komodo_PoWtarget(&percPoS,HASHTarget,Mining_height,ASSETCHAINS_STAKED); HASHTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); - if ( ASSETCHAINS_STAKED < 100 ) + if ( ASSETCHAINS_STAKED < 100 && KOMODO_MININGTHREADS == 0 ) { for (z=31; z>=0; z--) 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); + fprintf(stderr," PoW for staked coin PoS %d%% vs target %d%% ht.%d\n",percPoS,(int32_t)ASSETCHAINS_STAKED,Mining_height); } } + gotinvalid = 0; while (true) { - /*if ( KOMODO_INSYNC == 0 ) - { - KOMODO_LONGESTCHAIN = komodo_longestchain(); - fprintf(stderr,"Mining when blockchain might not be in sync longest.%d vs %d\n",KOMODO_LONGESTCHAIN,Mining_height); - if ( KOMODO_LONGESTCHAIN != 0 && Mining_height >= KOMODO_LONGESTCHAIN ) - KOMODO_INSYNC = Mining_height; - sleep(3); - }*/ + //fprintf(stderr,"gotinvalid.%d\n",gotinvalid); + if ( gotinvalid != 0 ) + break; komodo_longestchain(); // Hash state KOMODO_CHOSEN_ONE = 0; - + crypto_generichash_blake2b_state state; EhInitialiseState(n, k, state); // I = the block header minus nonce and solution. @@ -1657,6 +1705,7 @@ void static BitcoinMiner() for (z=31; z>=0; z--) fprintf(stderr,"%02x",((uint8_t *)&h)[z]); fprintf(stderr," Invalid block mined, try again\n"); + gotinvalid = 1; return(false); } KOMODO_CHOSEN_ONE = 1; @@ -1687,13 +1736,13 @@ void static BitcoinMiner() 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; @@ -1705,7 +1754,7 @@ void static BitcoinMiner() } 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); @@ -1714,7 +1763,7 @@ void static BitcoinMiner() 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. @@ -1741,7 +1790,7 @@ void static BitcoinMiner() cancelSolver = false; } } - + // Check for stop or if block needs to be rebuilt boost::this_thread::interruption_point(); // Regtest mode doesn't require peers @@ -1811,7 +1860,7 @@ void static BitcoinMiner() miningTimer.stop(); c.disconnect(); } - + #ifdef ENABLE_WALLET void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads) #else @@ -1819,10 +1868,10 @@ void static BitcoinMiner() #endif { static boost::thread_group* minerThreads = NULL; - + if (nThreads < 0) nThreads = GetNumCores(); - + if (minerThreads != NULL) { minerThreads->interrupt_all(); @@ -1831,8 +1880,13 @@ void static BitcoinMiner() } //fprintf(stderr,"nThreads.%d fGenerate.%d\n",(int32_t)nThreads,fGenerate); - if ( nThreads == 0 && ASSETCHAINS_STAKED ) - nThreads = 1; + if ( ASSETCHAINS_STAKED > 0 && nThreads == 0 && fGenerate ) + { + if ( pwallet != NULL ) + nThreads = 1; + else + return; + } if ((nThreads == 0 || !fGenerate) && (VERUS_MINTBLOCKS == 0 || pwallet == NULL)) return; @@ -1849,17 +1903,17 @@ void static BitcoinMiner() for (int i = 0; i < nThreads; i++) { #ifdef ENABLE_WALLET - if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH) + if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH || (ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0) ) minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet)); else minerThreads->create_thread(boost::bind(&BitcoinMiner_noeq, pwallet)); #else - if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH) + if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH || (ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0) ) minerThreads->create_thread(&BitcoinMiner); else minerThreads->create_thread(&BitcoinMiner_noeq); #endif } } - + #endif // ENABLE_MINING diff --git a/src/miner.h b/src/miner.h index 71b89f320..a3bedd292 100644 --- a/src/miner.h +++ b/src/miner.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_MINER_H #define BITCOIN_MINER_H @@ -28,7 +43,7 @@ struct CBlockTemplate #define KOMODO_MAXGPUCOUNT 65 /** Generate a new block, without valid proof-of-work */ -CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, int32_t gpucount, bool isStake = false); +CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& scriptPubKeyIn, int32_t gpucount, bool isStake = false); #ifdef ENABLE_WALLET boost::optional GetMinerScriptPubKey(CReserveKey& reservekey); CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, int32_t gpucount, bool isStake = false); diff --git a/src/mini-gmp.c b/src/mini-gmp.c index 4cc08c27c..f9ee23f15 100644 --- a/src/mini-gmp.c +++ b/src/mini-gmp.c @@ -41,6 +41,21 @@ see https://www.gnu.org/licenses/. */ mpn/generic/sbpi1_div_qr.c, mpn/generic/sub_n.c, mpn/generic/submul_1.c. */ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include #include #include diff --git a/src/mini-gmp.h b/src/mini-gmp.h index 75f5a3aac..56647ee77 100644 --- a/src/mini-gmp.h +++ b/src/mini-gmp.h @@ -35,6 +35,21 @@ see https://www.gnu.org/licenses/. */ This file defines the public interface. */ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef __MINI_GMP_H__ #define __MINI_GMP_H__ diff --git a/src/mruset.h b/src/mruset.h index 398aa173b..cd3af8664 100644 --- a/src/mruset.h +++ b/src/mruset.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_MRUSET_H #define BITCOIN_MRUSET_H diff --git a/src/net.cpp b/src/net.cpp index 85bb8a13e..d403660b6 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #if defined(HAVE_CONFIG_H) #include "config/bitcoin-config.h" #endif diff --git a/src/net.h b/src/net.h index e2fbdb0bd..3f30175c3 100644 --- a/src/net.h +++ b/src/net.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_NET_H #define BITCOIN_NET_H @@ -48,7 +63,7 @@ static const unsigned int MAX_INV_SZ = 50000; /** The maximum number of new addresses to accumulate before announcing. */ static const unsigned int MAX_ADDR_TO_SEND = 1000; /** Maximum length of incoming protocol messages (no message over 2 MiB is currently acceptable). */ -static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 2 * 1024 * 1024; +static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 4 * 1024 * 1024; // depends on MAX_BLOCK_SIZE /** Maximum length of strSubVer in `version` message */ static const unsigned int MAX_SUBVERSION_LENGTH = 256; /** -listen default */ diff --git a/src/netbase.cpp b/src/netbase.cpp index 7369b0167..88439f446 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifdef HAVE_CONFIG_H #include "config/bitcoin-config.h" #endif diff --git a/src/netbase.h b/src/netbase.h index d0262eaeb..8eb40b6b7 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_NETBASE_H #define BITCOIN_NETBASE_H diff --git a/src/noui.cpp b/src/noui.cpp index 0d9207c11..5e2b28318 100644 --- a/src/noui.cpp +++ b/src/noui.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "noui.h" #include "ui_interface.h" diff --git a/src/noui.h b/src/noui.h index 15cd30a63..185d4d0ce 100644 --- a/src/noui.h +++ b/src/noui.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_NOUI_H #define BITCOIN_NOUI_H diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index e4ff99246..3d12aee15 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "policy/fees.h" #include "amount.h" diff --git a/src/policy/fees.h b/src/policy/fees.h index 6d43189be..514f17724 100644 --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -2,6 +2,22 @@ // Copyright (c) 2009-2015 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. + +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_POLICYESTIMATOR_H #define BITCOIN_POLICYESTIMATOR_H diff --git a/src/pow.cpp b/src/pow.cpp index 7e72a9e01..cc2b0b7c2 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "pow.h" #include "consensus/upgrades.h" @@ -22,9 +37,8 @@ #endif // ENABLE_RUST uint32_t komodo_chainactive_timestamp(); -extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH, ASSETCHAINS_STAKED; -extern char ASSETCHAINS_SYMBOL[65]; -extern int32_t ASSETCHAINS_LWMAPOS,VERUS_BLOCK_POSUNITS, VERUS_CONSECUTIVE_POS_THRESHOLD, VERUS_NOPOS_THRESHHOLD; +#include "komodo_defs.h" + unsigned int lwmaGetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params); unsigned int lwmaCalculateNextWorkRequired(const CBlockIndex* pindexLast, const Consensus::Params& params); diff --git a/src/pow.h b/src/pow.h index 0c6c899b8..4946cb6e8 100644 --- a/src/pow.h +++ b/src/pow.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_POW_H #define BITCOIN_POW_H diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index c34238702..bb3314760 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -3,14 +3,29 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "primitives/block.h" #include "hash.h" #include "tinyformat.h" #include "utilstrencodings.h" #include "crypto/common.h" +#include "komodo_defs.h" -extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH; // default hash algorithm for block uint256 (CBlockHeader::*CBlockHeader::hashFunction)() const = &CBlockHeader::GetSHA256DHash; diff --git a/src/primitives/block.h b/src/primitives/block.h index 053b1c80e..5cd0a72fe 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_PRIMITIVES_BLOCK_H #define BITCOIN_PRIMITIVES_BLOCK_H diff --git a/src/primitives/nonce.cpp b/src/primitives/nonce.cpp index 85cb7155a..d90a4d78c 100644 --- a/src/primitives/nonce.cpp +++ b/src/primitives/nonce.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "hash.h" #include "nonce.h" #include diff --git a/src/primitives/nonce.h b/src/primitives/nonce.h index a3da4b6b5..605564671 100644 --- a/src/primitives/nonce.h +++ b/src/primitives/nonce.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_PRIMITIVES_NONCE_H #define BITCOIN_PRIMITIVES_NONCE_H diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index fff573496..ea24f9d23 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "primitives/transaction.h" #include "hash.h" diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 0f0690b5c..d97ff03fb 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_PRIMITIVES_TRANSACTION_H #define BITCOIN_PRIMITIVES_TRANSACTION_H diff --git a/src/protocol.cpp b/src/protocol.cpp index 33b9ee773..c7d95f809 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "protocol.h" #include "util.h" diff --git a/src/protocol.h b/src/protocol.h index d908191cc..d2a3cf556 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef __cplusplus #error This header can only be compiled as C++. #endif diff --git a/src/pubkey.cpp b/src/pubkey.cpp index 53e94fbdb..c714c8671 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "pubkey.h" #include diff --git a/src/pubkey.h b/src/pubkey.h index 12f11c249..18e4dda8f 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -4,6 +4,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_PUBKEY_H #define BITCOIN_PUBKEY_H diff --git a/src/random.cpp b/src/random.cpp index 87b3f648e..e13bbd9d8 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "random.h" #include "support/cleanse.h" diff --git a/src/random.h b/src/random.h index 8cec678ef..b65c7e08a 100644 --- a/src/random.h +++ b/src/random.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_RANDOM_H #define BITCOIN_RANDOM_H diff --git a/src/rest.cpp b/src/rest.cpp index 566732ca2..1609891a3 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "primitives/block.h" #include "primitives/transaction.h" #include "main.h" diff --git a/src/reverselock.h b/src/reverselock.h index fac1ccb79..dd79cf3da 100644 --- a/src/reverselock.h +++ b/src/reverselock.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_REVERSELOCK_H #define BITCOIN_REVERSELOCK_H diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index a69a4ebb3..c210e3099 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "amount.h" #include "chain.h" #include "chainparams.h" @@ -606,6 +621,51 @@ UniValue getblockhash(const UniValue& params, bool fHelp) return pblockindex->GetBlockHash().GetHex(); } +extern uint64_t ASSETCHAINS_STAKED; + +UniValue getlastsegidstakes(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "getlastsegidstakes depth\n" + "\nReturns object containing the counts of the last X blocks staked by each segid.\n" + "\nArguments:\n" + "1. depth (numeric, required) The amount of blocks to scan back." + "\nResult:\n" + "{\n" + " \"0\" : n, (numeric) number of stakes from segid 0 in the last X blocks.\n" + " .....\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getlastsegidstakes", "1000") + + HelpExampleRpc("getlastsegidstakes", "1000") + ); + + if ( ASSETCHAINS_STAKED == 0 ) + throw runtime_error("Only applies to ac_staked chains\n"); + + LOCK(cs_main); + + int depth = params[0].get_int(); + int32_t segids[64] = {0}; + + for (int64_t i = chainActive.Height(); i > chainActive.Height()-depth; i--) + { + CBlockIndex* pblockindex = chainActive[i]; + if ( pblockindex->segid >= 0 ) + segids[pblockindex->segid] += 1; + } + + UniValue ret(UniValue::VOBJ); + for (int8_t i = 0; i < 64; i++) + { + char str[4]; + sprintf(str, "%d", i); + ret.push_back(Pair(str,segids[i])); + } + return ret; +} + /*uint256 _komodo_getblockhash(int32_t nHeight) { uint256 hash; @@ -635,7 +695,8 @@ UniValue getblockheader(const UniValue& params, bool fHelp) "\nResult (for verbose = true):\n" "{\n" " \"hash\" : \"hash\", (string) the block hash (same as provided)\n" - " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" + " \"confirmations\" : n, (numeric) The number of notarized DPoW confirmations, or -1 if the block is not on the main chain\n" + " \"rawconfirmations\" : n,(numeric) The number of raw confirmations, or -1 if the block is not on the main chain\n" " \"height\" : n, (numeric) The block height or index\n" " \"version\" : n, (numeric) The block version\n" " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" @@ -695,7 +756,8 @@ UniValue getblock(const UniValue& params, bool fHelp) "\nResult (for verbosity = 1):\n" "{\n" " \"hash\" : \"hash\", (string) the block hash (same as provided hash)\n" - " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" + " \"confirmations\" : n, (numeric) The number of notarized DPoW confirmations, or -1 if the block is not on the main chain\n" + " \"rawconfirmations\" : n,(numeric) The number of raw confirmations, or -1 if the block is not on the main chain\n" " \"size\" : n, (numeric) The block size\n" " \"height\" : n, (numeric) The block height or index (same as provided height)\n" " \"version\" : n, (numeric) The block version\n" @@ -859,7 +921,7 @@ UniValue kvsearch(const UniValue& params, bool fHelp) " \"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" + " \"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" @@ -1138,7 +1200,8 @@ UniValue gettxout(const UniValue& params, bool fHelp) "\nResult:\n" "{\n" " \"bestblock\" : \"hash\", (string) the block hash\n" - " \"confirmations\" : n, (numeric) The number of confirmations\n" + " \"confirmations\" : n, (numeric) The number of notarized DPoW confirmations\n" + " \"rawconfirmations\" : n, (numeric) The number of raw confirmations\n" " \"value\" : x.xxx, (numeric) The transaction value in " + CURRENCY_UNIT + "\n" " \"scriptPubKey\" : { (json object)\n" " \"asm\" : \"code\", (string) \n" @@ -1191,10 +1254,10 @@ UniValue gettxout(const UniValue& params, bool fHelp) BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); CBlockIndex *pindex = it->second; ret.push_back(Pair("bestblock", pindex->GetBlockHash().GetHex())); - if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT) + if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT) { ret.push_back(Pair("confirmations", 0)); - else - { + ret.push_back(Pair("rawconfirmations", 0)); + } else { ret.push_back(Pair("confirmations", komodo_dpowconfs(coins.nHeight,pindex->GetHeight() - coins.nHeight + 1))); ret.push_back(Pair("rawconfirmations", pindex->GetHeight() - coins.nHeight + 1)); } diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index c4eb16e0e..ac45cd107 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "rpc/client.h" #include "rpc/protocol.h" #include "util.h" @@ -74,6 +89,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getblockheader", 1 }, { "gettransaction", 1 }, { "getrawtransaction", 1 }, + { "getlastsegidstakes", 0 }, { "createrawtransaction", 0 }, { "createrawtransaction", 1 }, { "createrawtransaction", 2 }, diff --git a/src/rpc/client.h b/src/rpc/client.h index 8937a56f0..79527b7be 100644 --- a/src/rpc/client.h +++ b/src/rpc/client.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_RPCCLIENT_H #define BITCOIN_RPCCLIENT_H diff --git a/src/rpc/crosschain.cpp b/src/rpc/crosschain.cpp index dd604124c..a0a3b507f 100644 --- a/src/rpc/crosschain.cpp +++ b/src/rpc/crosschain.cpp @@ -1,3 +1,18 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "amount.h" #include "chain.h" #include "chainparams.h" @@ -30,6 +45,9 @@ int32_t komodo_MoM(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_ 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); +extern std::string ASSETCHAINS_SELFIMPORT; +uint256 Parseuint256(char *hexstr); +int32_t GetSelfimportProof(std::string source,CMutableTransaction &mtx,CScript &scriptPubKey,TxProof &proof,uint64_t burnAmount,std::vector rawtx,uint256 txid,std::vector rawproof); UniValue assetchainproof(const UniValue& params, bool fHelp) @@ -41,8 +59,8 @@ UniValue assetchainproof(const UniValue& params, bool fHelp) throw runtime_error("assetchainproof needs a txid"); hash = uint256S(params[0].get_str()); - - auto proof = GetAssetchainProof(hash); + CTransaction tx; + auto proof = GetAssetchainProof(hash,tx); auto proofData = E_MARSHAL(ss << proof); return HexStr(proofData); } @@ -145,6 +163,7 @@ UniValue calc_MoM(const UniValue& params, bool fHelp) UniValue migrate_converttoexport(const UniValue& params, bool fHelp) { + std::vector rawproof; uint8_t *ptr; int32_t i; uint32_t ccid = ASSETCHAINS_CC; if (fHelp || params.size() != 3) throw runtime_error( "migrate_converttoexport rawTx dest_symbol export_amount\n" @@ -180,8 +199,13 @@ UniValue migrate_converttoexport(const UniValue& params, bool fHelp) if (burnAmount < needed) throw runtime_error("export_amount too small"); } - - CTxOut burnOut = MakeBurnOutput(burnAmount, ASSETCHAINS_CC, targetSymbol, tx.vout); + //if ( ASSETCHAINS_SELFIMPORT.size() > 0 ) + // throw runtime_error("self-import chains cant be fungible"); + rawproof.resize(strlen(ASSETCHAINS_SYMBOL)); + ptr = rawproof.data(); + for (i=0; i vouts; std::vector rawtx,rawproof; CScript scriptPubKey; + if ( ASSETCHAINS_SELFIMPORT.size() == 0 ) + throw runtime_error("selfimport only works on -ac_import chains"); + if (fHelp || params.size() < 3 || params.size() > 5 ) + throw runtime_error("selfimport rawtx txid burnamount [rawproof source]\n\n" + "creates signed selfimport transaction"); + rawtx = ParseHex(params[0].get_str().c_str()); + txid = Parseuint256((char *)params[1].get_str().c_str()); // allow for txid != hash(rawtx) + burnAmount = atof(params[2].get_str().c_str()) * COIN + 0.00000000499999; + source = ASSETCHAINS_SELFIMPORT; + if ( params.size() >= 4 ) + { + rawproof = ParseHex(params[3].get_str().c_str()); + if ( params.size() == 5 ) + source = params[4].get_str(); + } + if ( GetSelfimportProof(source,mtx,scriptPubKey,proof,burnAmount,rawtx,txid,rawproof) < 0 ) + throw std::runtime_error("Failed validating selfimport"); + vouts = mtx.vout; + burnOut = MakeBurnOutput(burnAmount,0xffffffff,ASSETCHAINS_SELFIMPORT,vouts,rawproof); + mtx.vout.clear(); + mtx.vout.push_back(burnOut); + burnTx = mtx; + return HexStr(E_MARSHAL(ss << MakeImportCoinTransaction(proof,burnTx,vouts))); +} UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp) { diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 25b75c301..ff9b1b4c4 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "amount.h" #include "chainparams.h" #include "consensus/consensus.h" @@ -33,10 +48,8 @@ using namespace std; -extern int32_t ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH, ASSETCHAINS_LWMAPOS; -extern uint64_t ASSETCHAINS_STAKED; -extern int32_t KOMODO_MININGTHREADS; -extern bool VERUS_MINTBLOCKS; +#include "komodo_defs.h" + arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc); /** @@ -339,19 +352,25 @@ UniValue setgenerate(const UniValue& params, bool fHelp) //if (nGenProcLimit == 0) // fGenerate = false; } - - if (fGenerate && !nGenProcLimit) + if ( ASSETCHAINS_LWMAPOS != 0 ) { - VERUS_MINTBLOCKS = 1; - fGenerate = GetBoolArg("-gen", false); - nGenProcLimit = KOMODO_MININGTHREADS; + if (fGenerate && !nGenProcLimit) + { + VERUS_MINTBLOCKS = 1; + fGenerate = GetBoolArg("-gen", false); + KOMODO_MININGTHREADS = nGenProcLimit; + } + else if (!fGenerate) + { + VERUS_MINTBLOCKS = 0; + KOMODO_MININGTHREADS = 0; + } + else KOMODO_MININGTHREADS = (int32_t)nGenProcLimit; } - else if (!fGenerate) + else { - VERUS_MINTBLOCKS = 0; - KOMODO_MININGTHREADS = 0; + KOMODO_MININGTHREADS = (int32_t)nGenProcLimit; } - else KOMODO_MININGTHREADS = (int32_t)nGenProcLimit; mapArgs["-gen"] = (fGenerate ? "1" : "0"); mapArgs ["-genproclimit"] = itostr(KOMODO_MININGTHREADS); diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 7bfb98f7b..e6d8025b1 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "clientversion.h" #include "init.h" #include "key_io.h" @@ -13,6 +28,7 @@ #include "timedata.h" #include "txmempool.h" #include "util.h" +#include "cc/eval.h" #ifdef ENABLE_WALLET #include "wallet/wallet.h" #include "wallet/walletdb.h" @@ -56,12 +72,13 @@ extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; uint32_t komodo_segid32(char *coinaddr); int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height); int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp); -#define KOMODO_VERSION "0.3.1" +#define KOMODO_VERSION "0.3.3b" #define VERUS_VERSION "0.4.0g" extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; extern uint32_t ASSETCHAINS_CC; extern uint32_t ASSETCHAINS_MAGIC; -extern uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED,ASSETCHAINS_SUPPLY,ASSETCHAINS_LASTERA; +extern uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED,ASSETCHAINS_SUPPLY; +extern uint32_t ASSETCHAINS_LASTERA; extern int32_t ASSETCHAINS_LWMAPOS,ASSETCHAINS_SAPLING; extern uint64_t ASSETCHAINS_ENDSUBSIDY[],ASSETCHAINS_REWARD[],ASSETCHAINS_HALVING[],ASSETCHAINS_DECAY[]; extern std::string NOTARY_PUBKEY; extern uint8_t NOTARY_PUBKEY33[]; @@ -208,7 +225,7 @@ UniValue getinfo(const UniValue& params, bool fHelp) } } if (ASSETCHAINS_LASTERA > 0) - obj.push_back(Pair("eras", ASSETCHAINS_LASTERA + 1)); + obj.push_back(Pair("eras", (int64_t)(ASSETCHAINS_LASTERA + 1))); obj.push_back(Pair("reward", acReward)); obj.push_back(Pair("halving", acHalving)); obj.push_back(Pair("decay", acDecay)); @@ -1320,7 +1337,53 @@ UniValue txnotarizedconfirmed(const UniValue& params, bool fHelp) txid = uint256S((char *)params[0].get_str().c_str()); notarizedconfirmed=komodo_txnotarizedconfirmed(txid); UniValue result(UniValue::VOBJ); - result.push_back(Pair("result", notarizedconfirmed)); + result.push_back(Pair("result", notarizedconfirmed)); + return result; +} + +UniValue decodeccopret(const UniValue& params, bool fHelp) +{ + CTransaction tx; uint256 txid,hashBlock; + std::vector vopret; uint8_t *script; + UniValue result(UniValue::VOBJ); + + if (fHelp || params.size() < 1 || params.size() > 1) + { + string msg = "decodeccopret hex\n" + "\nReturns eval code and function id for CC OP RETURN data.\n" + + "\nArguments:\n" + "1. txid (string, required) Transaction id.\n" + + "\nResult:\n" + "{\n" + " eval_code, (string) Eval code name.\n" + " function, (char) Function id char.\n" + "}\n" + ; + throw runtime_error(msg); + } + txid = uint256S((char *)params[0].get_str().c_str()); + { + LOCK(cs_main); + if (!GetTransaction(txid, tx, hashBlock, true)) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction"); + } + GetOpReturnData(tx.vout[tx.vout.size()-1].scriptPubKey,vopret); + script = (uint8_t *)vopret.data(); + if ( vopret.size() > 1) + { + char func[5]; + sprintf(func,"%c",script[1]); + result.push_back(Pair("result", "success")); + result.push_back(Pair("eval_code", EvalToStr(script[0]))); + result.push_back(Pair("function", func)); + } + else + { + result.push_back(Pair("result", "error")); + result.push_back(Pair("error", "invalid or no CC opret data")); + } return result; } diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index d922daad4..e280b1a0b 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "rpc/server.h" #include "clientversion.h" diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp index 7713a54b3..2366fca14 100644 --- a/src/rpc/protocol.cpp +++ b/src/rpc/protocol.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "rpc/protocol.h" #include "random.h" diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h index 816ce9ec5..91a14c023 100644 --- a/src/rpc/protocol.h +++ b/src/rpc/protocol.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_RPCPROTOCOL_H #define BITCOIN_RPCPROTOCOL_H diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 21a6e26cd..5ab040711 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "consensus/upgrades.h" #include "consensus/validation.h" #include "core_io.h" @@ -282,6 +297,7 @@ void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue& } else { entry.push_back(Pair("height", -1)); entry.push_back(Pair("confirmations", 0)); + entry.push_back(Pair("rawconfirmations", 0)); } } @@ -364,9 +380,10 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) entry.push_back(Pair("confirmations", komodo_dpowconfs(pindex->GetHeight(),1 + chainActive.Height() - pindex->GetHeight()))); entry.push_back(Pair("time", pindex->GetBlockTime())); entry.push_back(Pair("blocktime", pindex->GetBlockTime())); - } - else + } else { entry.push_back(Pair("confirmations", 0)); + entry.push_back(Pair("rawconfirmations", 0)); + } } } } @@ -454,7 +471,8 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp) " ,...\n" " ],\n" " \"blockhash\" : \"hash\", (string) the block hash\n" - " \"confirmations\" : n, (numeric) The confirmations\n" + " \"confirmations\" : n, (numeric) The number of notarized DPoW confirmations\n" + " \"rawconfirmations\" : n, (numeric) The number of raw confirmations\n" " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT)\n" " \"blocktime\" : ttt (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" "}\n" diff --git a/src/rpc/register.h b/src/rpc/register.h index 01aa58a25..072517d88 100644 --- a/src/rpc/register.h +++ b/src/rpc/register.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_RPCREGISTER_H #define BITCOIN_RPCREGISTER_H diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 1b6856be5..82a400e71 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "rpc/server.h" #include "init.h" @@ -302,6 +317,7 @@ static const CRPCCommand vRPCCommands[] = { "blockchain", "getblockhashes", &getblockhashes, true }, { "blockchain", "getblockhash", &getblockhash, true }, { "blockchain", "getblockheader", &getblockheader, true }, + { "blockchain", "getlastsegidstakes", &getlastsegidstakes, true }, { "blockchain", "getchaintips", &getchaintips, true }, { "blockchain", "getdifficulty", &getdifficulty, true }, { "blockchain", "getmempoolinfo", &getmempoolinfo, true }, @@ -333,6 +349,7 @@ static const CRPCCommand vRPCCommands[] = { "crosschain", "migrate_converttoexport", &migrate_converttoexport, true }, { "crosschain", "migrate_createimporttransaction", &migrate_createimporttransaction, true }, { "crosschain", "migrate_completeimporttransaction", &migrate_completeimporttransaction, true }, + { "crosschain", "selfimport", &selfimport, true }, /* Mining */ { "mining", "getblocktemplate", &getblocktemplate, true }, @@ -364,16 +381,16 @@ static const CRPCCommand vRPCCommands[] = // auction { "auction", "auctionaddress", &auctionaddress, true }, - + // lotto { "lotto", "lottoaddress", &lottoaddress, true }, - + // fsm { "FSM", "FSMaddress", &FSMaddress, true }, { "FSM", "FSMcreate", &FSMcreate, true }, { "FSM", "FSMlist", &FSMlist, true }, { "FSM", "FSMinfo", &FSMinfo, true }, - + // rewards { "rewards", "rewardslist", &rewardslist, true }, { "rewards", "rewardsinfo", &rewardsinfo, true }, @@ -382,24 +399,33 @@ static const CRPCCommand vRPCCommands[] = { "rewards", "rewardslock", &rewardslock, true }, { "rewards", "rewardsunlock", &rewardsunlock, true }, { "rewards", "rewardsaddress", &rewardsaddress, true }, - + // faucet { "faucet", "faucetinfo", &faucetinfo, true }, { "faucet", "faucetfund", &faucetfund, true }, { "faucet", "faucetget", &faucetget, true }, { "faucet", "faucetaddress", &faucetaddress, true }, - // Heir - { "heir", "heiraddress", &heiraddress, true }, + // Heir + { "heir", "heiraddress", &heiraddress, true }, + { "heir", "heirfund", &heirfund, true }, + { "heir", "heiradd", &heiradd, true }, + { "heir", "heirclaim", &heirclaim, true }, +/* { "heir", "heirfundtokens", &heirfundtokens, true }, + { "heir", "heiraddtokens", &heiraddtokens, true }, + { "heir", "heirclaimtokens", &heirclaimtokens, true },*/ + { "heir", "heirinfo", &heirinfo, true }, + { "heir", "heirlist", &heirlist, true }, // Channels { "channels", "channelsaddress", &channelsaddress, true }, + { "channels", "channelslist", &channelslist, true }, { "channels", "channelsinfo", &channelsinfo, true }, { "channels", "channelsopen", &channelsopen, true }, { "channels", "channelspayment", &channelspayment, true }, { "channels", "channelsclose", &channelsclose, true }, { "channels", "channelsrefund", &channelsrefund, true }, - + // Oracles { "oracles", "oraclesaddress", &oraclesaddress, true }, { "oracles", "oracleslist", &oracleslist, true }, @@ -423,12 +449,24 @@ static const CRPCCommand vRPCCommands[] = // Pegs { "pegs", "pegsaddress", &pegsaddress, true }, - // Triggers - { "triggers", "triggersaddress", &triggersaddress, true }, + // Marmara + { "marmara", "marmaraaddress", &marmaraaddress, true }, + { "marmara", "marmarapoolpayout", &marmara_poolpayout, true }, + { "marmara", "marmarareceive", &marmara_receive, true }, + { "marmara", "marmaraissue", &marmara_issue, true }, + { "marmara", "marmaratransfer", &marmara_transfer, true }, + { "marmara", "marmarainfo", &marmara_info, true }, + { "marmara", "marmaracreditloop", &marmara_creditloop, true }, + { "marmara", "marmarasettlement", &marmara_settlement, true }, + { "marmara", "marmaralock", &marmara_lock, true }, // Payments { "payments", "paymentsaddress", &paymentsaddress, true }, + { "CClib", "cclibaddress", &cclibaddress, true }, + { "CClib", "cclibinfo", &cclibinfo, true }, + { "CClib", "cclib", &cclib, true }, + // Gateways { "gateways", "gatewaysaddress", &gatewaysaddress, true }, { "gateways", "gatewayslist", &gatewayslist, true }, @@ -454,7 +492,8 @@ static const CRPCCommand vRPCCommands[] = { "dice", "dicestatus", &dicestatus, true }, { "dice", "diceaddress", &diceaddress, true }, - // tokens + // tokens & assets + { "tokens", "assetsaddress", &assetsaddress, true }, { "tokens", "tokeninfo", &tokeninfo, true }, { "tokens", "tokenlist", &tokenlist, true }, { "tokens", "tokenorders", &tokenorders, true }, @@ -485,6 +524,7 @@ static const CRPCCommand vRPCCommands[] = { "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */ { "util", "verifymessage", &verifymessage, true }, { "util", "txnotarizedconfirmed", &txnotarizedconfirmed, true }, + { "util", "decodeccopret", &decodeccopret, true }, { "util", "estimatefee", &estimatefee, true }, { "util", "estimatepriority", &estimatepriority, true }, { "util", "z_validateaddress", &z_validateaddress, true }, /* uses wallet if enabled */ @@ -497,6 +537,9 @@ static const CRPCCommand vRPCCommands[] = { "util", "reconsiderblock", &reconsiderblock, true }, /* Not shown in help */ { "hidden", "setmocktime", &setmocktime, true }, + { "hidden", "test_ac", &test_ac, true }, + { "hidden", "test_heirmarker", &test_heirmarker, true }, + #ifdef ENABLE_WALLET /* Wallet */ { "wallet", "resendwallettransactions", &resendwallettransactions, true}, diff --git a/src/rpc/server.h b/src/rpc/server.h index 6638024b8..3edc85ebf 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_RPCSERVER_H #define BITCOIN_RPCSERVER_H @@ -227,6 +242,7 @@ extern UniValue tokeninfo(const UniValue& params, bool fHelp); extern UniValue tokenlist(const UniValue& params, bool fHelp); extern UniValue tokenorders(const UniValue& params, bool fHelp); extern UniValue tokenbalance(const UniValue& params, bool fHelp); +extern UniValue assetsaddress(const UniValue& params, bool fHelp); extern UniValue tokenaddress(const UniValue& params, bool fHelp); extern UniValue tokencreate(const UniValue& params, bool fHelp); extern UniValue tokentransfer(const UniValue& params, bool fHelp); @@ -238,6 +254,11 @@ extern UniValue tokencancelask(const UniValue& params, bool fHelp); extern UniValue tokenfillask(const UniValue& params, bool fHelp); extern UniValue tokenconvert(const UniValue& params, bool fHelp); extern UniValue heiraddress(const UniValue& params, bool fHelp); +extern UniValue heirfund(const UniValue& params, bool fHelp); +extern UniValue heiradd(const UniValue& params, bool fHelp); +extern UniValue heirclaim(const UniValue& params, bool fHelp); +extern UniValue heirinfo(const UniValue& params, bool fHelp); +extern UniValue heirlist(const UniValue& params, bool fHelp); extern UniValue channelsaddress(const UniValue& params, bool fHelp); extern UniValue oraclesaddress(const UniValue& params, bool fHelp); extern UniValue oracleslist(const UniValue& params, bool fHelp); @@ -256,8 +277,19 @@ extern UniValue pricesbet(const UniValue& params, bool fHelp); extern UniValue pricesstatus(const UniValue& params, bool fHelp); extern UniValue pricesfinish(const UniValue& params, bool fHelp); extern UniValue pegsaddress(const UniValue& params, bool fHelp); -extern UniValue triggersaddress(const UniValue& params, bool fHelp); +extern UniValue marmaraaddress(const UniValue& params, bool fHelp); +extern UniValue marmara_poolpayout(const UniValue& params, bool fHelp); +extern UniValue marmara_receive(const UniValue& params, bool fHelp); +extern UniValue marmara_issue(const UniValue& params, bool fHelp); +extern UniValue marmara_transfer(const UniValue& params, bool fHelp); +extern UniValue marmara_info(const UniValue& params, bool fHelp); +extern UniValue marmara_creditloop(const UniValue& params, bool fHelp); +extern UniValue marmara_settlement(const UniValue& params, bool fHelp); +extern UniValue marmara_lock(const UniValue& params, bool fHelp); extern UniValue paymentsaddress(const UniValue& params, bool fHelp); +extern UniValue cclibaddress(const UniValue& params, bool fHelp); +extern UniValue cclibinfo(const UniValue& params, bool fHelp); +extern UniValue cclib(const UniValue& params, bool fHelp); extern UniValue gatewaysaddress(const UniValue& params, bool fHelp); extern UniValue gatewayslist(const UniValue& params, bool fHelp); extern UniValue gatewaysinfo(const UniValue& params, bool fHelp); @@ -271,6 +303,7 @@ extern UniValue gatewaysmarkdone(const UniValue& params, bool fHelp); extern UniValue gatewayspending(const UniValue& params, bool fHelp); extern UniValue gatewaysprocessed(const UniValue& params, bool fHelp); extern UniValue gatewaysmultisig(const UniValue& params, bool fHelp); +extern UniValue channelslist(const UniValue& params, bool fHelp); extern UniValue channelsinfo(const UniValue& params, bool fHelp); extern UniValue channelsopen(const UniValue& params, bool fHelp); extern UniValue channelspayment(const UniValue& params, bool fHelp); @@ -340,6 +373,7 @@ extern UniValue walletlock(const UniValue& params, bool fHelp); extern UniValue encryptwallet(const UniValue& params, bool fHelp); extern UniValue validateaddress(const UniValue& params, bool fHelp); extern UniValue txnotarizedconfirmed(const UniValue& params, bool fHelp); +extern UniValue decodeccopret(const UniValue& params, bool fHelp); extern UniValue getinfo(const UniValue& params, bool fHelp); extern UniValue setpubkey(const UniValue& params, bool fHelp); extern UniValue getwalletinfo(const UniValue& params, bool fHelp); @@ -382,6 +416,7 @@ extern UniValue getblockhashes(const UniValue& params, bool fHelp); extern UniValue getblockdeltas(const UniValue& params, bool fHelp); extern UniValue getblockhash(const UniValue& params, bool fHelp); extern UniValue getblockheader(const UniValue& params, bool fHelp); +extern UniValue getlastsegidstakes(const UniValue& params, bool fHelp); extern UniValue getblock(const UniValue& params, bool fHelp); extern UniValue gettxoutsetinfo(const UniValue& params, bool fHelp); extern UniValue gettxout(const UniValue& params, bool fHelp); @@ -390,6 +425,7 @@ extern UniValue getchaintips(const UniValue& params, bool fHelp); extern UniValue invalidateblock(const UniValue& params, bool fHelp); extern UniValue reconsiderblock(const UniValue& params, bool fHelp); extern UniValue getspentinfo(const UniValue& params, bool fHelp); +extern UniValue selfimport(const UniValue& params, bool fHelp); extern UniValue getblocksubsidy(const UniValue& params, bool fHelp); @@ -435,4 +471,8 @@ extern UniValue paxprices(const UniValue& params, bool fHelp); extern UniValue paxdeposit(const UniValue& params, bool fHelp); extern UniValue paxwithdraw(const UniValue& params, bool fHelp); +// test rpc: +extern UniValue test_ac(const UniValue& params, bool fHelp); +extern UniValue test_heirmarker(const UniValue& params, bool fHelp); + #endif // BITCOIN_RPCSERVER_H diff --git a/src/scheduler.cpp b/src/scheduler.cpp index 8729f2a5a..e085791fc 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "scheduler.h" #include "reverselock.h" diff --git a/src/scheduler.h b/src/scheduler.h index 436659e58..af1d7a24c 100644 --- a/src/scheduler.h +++ b/src/scheduler.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_SCHEDULER_H #define BITCOIN_SCHEDULER_H diff --git a/src/script/cc.cpp b/src/script/cc.cpp index ce9262295..a0770a9b2 100644 --- a/src/script/cc.cpp +++ b/src/script/cc.cpp @@ -1,3 +1,18 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "cryptoconditions/include/cryptoconditions.h" #include "script/cc.h" diff --git a/src/script/cc.h b/src/script/cc.h index 583769a38..b3ee612a5 100644 --- a/src/script/cc.h +++ b/src/script/cc.h @@ -1,3 +1,18 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef SCRIPT_CC_H #define SCRIPT_CC_H diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index b66c07771..64d98d783 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include #include "interpreter.h" diff --git a/src/script/interpreter.h b/src/script/interpreter.h index f7a02f26d..11812b6e3 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_SCRIPT_INTERPRETER_H #define BITCOIN_SCRIPT_INTERPRETER_H diff --git a/src/script/script.cpp b/src/script/script.cpp index 8de75bb22..475acdfd5 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "script.h" #include "tinyformat.h" diff --git a/src/script/script.h b/src/script/script.h index 52d25b3d8..b1294ab25 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_SCRIPT_SCRIPT_H #define BITCOIN_SCRIPT_SCRIPT_H diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp index 41c8a24e0..199161364 100644 --- a/src/script/script_error.cpp +++ b/src/script/script_error.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "script_error.h" const char* ScriptErrorString(const ScriptError serror) diff --git a/src/script/script_error.h b/src/script/script_error.h index 35c8fbfd8..85fe1cff3 100644 --- a/src/script/script_error.h +++ b/src/script/script_error.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_SCRIPT_SCRIPT_ERROR_H #define BITCOIN_SCRIPT_SCRIPT_ERROR_H diff --git a/src/script/script_ext.cpp b/src/script/script_ext.cpp index 613b50c05..532e39d6c 100644 --- a/src/script/script_ext.cpp +++ b/src/script/script_ext.cpp @@ -4,6 +4,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "script_ext.h" using namespace std; diff --git a/src/script/script_ext.h b/src/script/script_ext.h index 187c01a5b..e14cbd1f7 100644 --- a/src/script/script_ext.h +++ b/src/script/script_ext.h @@ -4,6 +4,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_SCRIPT_SCRIPT_EXT_H #define BITCOIN_SCRIPT_SCRIPT_EXT_H diff --git a/src/script/serverchecker.cpp b/src/script/serverchecker.cpp index 469401390..9fc470e14 100644 --- a/src/script/serverchecker.cpp +++ b/src/script/serverchecker.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "serverchecker.h" #include "script/cc.h" #include "cc/eval.h" diff --git a/src/script/serverchecker.h b/src/script/serverchecker.h index 6e5bffe55..08f3acc6c 100644 --- a/src/script/serverchecker.h +++ b/src/script/serverchecker.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_SCRIPT_SERVERCHECKER_H #define BITCOIN_SCRIPT_SERVERCHECKER_H diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp index 07ec87a12..b78fc3ce3 100644 --- a/src/script/sigcache.cpp +++ b/src/script/sigcache.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "sigcache.h" #include "pubkey.h" diff --git a/src/script/sigcache.h b/src/script/sigcache.h index 134b72a2d..e9169eab6 100644 --- a/src/script/sigcache.h +++ b/src/script/sigcache.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_SCRIPT_SIGCACHE_H #define BITCOIN_SCRIPT_SIGCACHE_H diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 3bc49ef76..685018828 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "script/sign.h" #include "primitives/transaction.h" @@ -30,14 +45,14 @@ bool TransactionSignatureCreator::CreateSig(std::vector& vchSig, key = *pprivKey; else if (!keystore || !keystore->GetKey(address, key)) return false; - + uint256 hash; try { hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, consensusBranchId); } catch (logic_error ex) { return false; } - + if (scriptCode.IsPayToCryptoCondition()) { CC *cc = (CC *)extraData; @@ -60,9 +75,9 @@ bool TransactionSignatureCreator::CreateSig(std::vector& vchSig, return false; } } - + vchSig.push_back((unsigned char)nHashType); - + return true; } @@ -113,7 +128,7 @@ std::vector &GetCryptoConditions() static bool initialized = false; static std::vector vCC = std::vector(); CCcontract_info C; - + if (!initialized) { // this should initialize any desired auto-signed crypto-conditions @@ -125,7 +140,7 @@ bool GetCCByUnspendableAddress(struct CCcontract_info *cp, char *addrstr) { std::vector &vCC = GetCryptoConditions(); bool found = false; - + for (int i = 0; i < vCC.size(); i++) { if (strcmp(addrstr, vCC[i].unspendableCCaddr) == 0) @@ -142,7 +157,7 @@ bool CCinitLite(struct CCcontract_info *cp, uint8_t evalcode) { std::vector &vCC = GetCryptoConditions(); bool found = false; - + for (int i = 0; i < vCC.size(); i++) { if (vCC[i].evalcode == evalcode) @@ -157,7 +172,7 @@ bool CCinitLite(struct CCcontract_info *cp, uint8_t evalcode) bool _Getscriptaddress(char *destaddr, const CScript &scriptPubKey) { - CTxDestination address; + CTxDestination address; txnouttype whichType; std::vector> vvch = std::vector>(); if (Solver(scriptPubKey, whichType, vvch) && vvch[0].size() == 20) @@ -184,10 +199,10 @@ static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scrip vector vPK; vector vParams = vector(); COptCCParams p; - + // get information to sign with CCcontract_info C; - + scriptPubKey.IsPayToCryptoCondition(&subScript, vParams); if (vParams.empty()) { @@ -204,12 +219,12 @@ static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scrip { p = COptCCParams(vParams[0]); } - + if (p.IsValid() && p.vKeys.size() >= p.n) { bool is1of2 = (p.m == 1 && p.n == 2); CKey privKey; - + // must be a valid cc eval code if (CCinitLite(&C, p.evalCode)) { @@ -217,7 +232,7 @@ static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scrip if (!is1of2) { bool havePriv = creator.KeyStore().GetKey(p.vKeys[0].GetID(), privKey); - + // if we don't have the private key, it must be the unspendable address if (!havePriv && (p.vKeys[0] == CPubKey(ParseHex(C.CChexstr)))) { @@ -225,9 +240,9 @@ static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scrip std::vector vch(&(C.CCpriv[0]), C.CCpriv + sizeof(C.CCpriv)); privKey.Set(vch.begin(), vch.end(), false); } - + CC *cc = CCcond1(p.evalCode, p.vKeys[0]); - + if (cc) { vector vch; @@ -239,7 +254,7 @@ static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scrip { fprintf(stderr,"vin has 1of1 CC signing error with address.(%s)\n", p.vKeys[0].GetID().ToString().c_str()); } - + cc_free(cc); return ret.size() != 0; } @@ -251,7 +266,7 @@ static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scrip { if (creator.IsKeystoreValid() && creator.KeyStore().GetKey(pk.GetID(), privKey) && privKey.IsValid()) break; - + if (pk == CPubKey(ParseHex(C.CChexstr))) { privKey = CKey(); @@ -260,12 +275,12 @@ static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scrip break; } } - + if (!privKey.IsValid()) return false; - + CC *cc = CCcond1of2(p.evalCode, p.vKeys[0], p.vKeys[1]); - + if (cc) { vector vch; @@ -277,7 +292,7 @@ static bool SignStepCC(const BaseSignatureCreator& creator, const CScript& scrip { fprintf(stderr,"vin has 1of2 CC signing error with addresses.(%s)\n(%s)\n", p.vKeys[0].GetID().ToString().c_str(), p.vKeys[1].GetID().ToString().c_str()); } - + cc_free(cc); return ret.size() != 0; } @@ -299,9 +314,9 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP CScript scriptRet; uint160 h160; ret.clear(); - + vector vSolutions; - + if (!Solver(scriptPubKey, whichTypeRet, vSolutions)) { // if this is a CLTV script, solve for the destination after CLTV @@ -309,10 +324,10 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP { uint8_t pushOp = scriptPubKey[0]; uint32_t scriptStart = pushOp + 3; - + // check post CLTV script CScript postfix = CScript(scriptPubKey.size() > scriptStart ? scriptPubKey.begin() + scriptStart : scriptPubKey.end(), scriptPubKey.end()); - + // check again with only postfix subscript if (!Solver(postfix, whichTypeRet, vSolutions)) return false; @@ -320,44 +335,44 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP else return false; } - + CKeyID keyID; - + switch (whichTypeRet) { - case TX_NONSTANDARD: - case TX_NULL_DATA: - return false; - case TX_PUBKEY: - keyID = CPubKey(vSolutions[0]).GetID(); - return Sign1(keyID, creator, scriptPubKey, ret, consensusBranchId); - case TX_PUBKEYHASH: - keyID = CKeyID(uint160(vSolutions[0])); - if (!Sign1(keyID, creator, scriptPubKey, ret, consensusBranchId)) + case TX_NONSTANDARD: + case TX_NULL_DATA: return false; - else - { - CPubKey vch; - creator.KeyStore().GetPubKey(keyID, vch); - ret.push_back(ToByteVector(vch)); - } - return true; - case TX_SCRIPTHASH: - if (creator.KeyStore().GetCScript(uint160(vSolutions[0]), scriptRet)) { - ret.push_back(std::vector(scriptRet.begin(), scriptRet.end())); + case TX_PUBKEY: + keyID = CPubKey(vSolutions[0]).GetID(); + return Sign1(keyID, creator, scriptPubKey, ret, consensusBranchId); + case TX_PUBKEYHASH: + keyID = CKeyID(uint160(vSolutions[0])); + if (!Sign1(keyID, creator, scriptPubKey, ret, consensusBranchId)) + return false; + else + { + CPubKey vch; + creator.KeyStore().GetPubKey(keyID, vch); + ret.push_back(ToByteVector(vch)); + } return true; - } - return false; - - case TX_CRYPTOCONDITION: - return SignStepCC(creator, scriptPubKey, vSolutions, ret, consensusBranchId); - - case TX_MULTISIG: - ret.push_back(valtype()); // workaround CHECKMULTISIG bug - return (SignN(vSolutions, creator, scriptPubKey, ret, consensusBranchId)); - - default: - return false; + case TX_SCRIPTHASH: + if (creator.KeyStore().GetCScript(uint160(vSolutions[0]), scriptRet)) { + ret.push_back(std::vector(scriptRet.begin(), scriptRet.end())); + return true; + } + return false; + + case TX_CRYPTOCONDITION: + return SignStepCC(creator, scriptPubKey, vSolutions, ret, consensusBranchId); + + case TX_MULTISIG: + ret.push_back(valtype()); // workaround CHECKMULTISIG bug + return (SignN(vSolutions, creator, scriptPubKey, ret, consensusBranchId)); + + default: + return false; } } @@ -384,7 +399,7 @@ bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPu txnouttype whichType; solved = SignStep(creator, script, result, whichType, consensusBranchId); CScript subscript; - + if (solved && whichType == TX_SCRIPTHASH) { // Solver returns the subscript that needs to be evaluated; @@ -394,9 +409,9 @@ bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPu solved = solved && SignStep(creator, script, result, whichType, consensusBranchId) && whichType != TX_SCRIPTHASH; result.push_back(std::vector(subscript.begin(), subscript.end())); } - + sigdata.scriptSig = PushAll(result); - + // Test solution return solved && VerifyScript(sigdata.scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker(), consensusBranchId); } @@ -416,19 +431,19 @@ void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const Signatur } bool SignSignature( - const CKeyStore &keystore, - const CScript& fromPubKey, - CMutableTransaction& txTo, - unsigned int nIn, - const CAmount& amount, - int nHashType, - uint32_t consensusBranchId) + const CKeyStore &keystore, + const CScript& fromPubKey, + CMutableTransaction& txTo, + unsigned int nIn, + const CAmount& amount, + int nHashType, + uint32_t consensusBranchId) { assert(nIn < txTo.vin.size()); - + CTransaction txToConst(txTo); TransactionSignatureCreator creator(&keystore, &txToConst, nIn, amount, nHashType); - + SignatureData sigdata; bool ret = ProduceSignature(creator, fromPubKey, sigdata, consensusBranchId); UpdateTransaction(txTo, nIn, sigdata); @@ -436,24 +451,24 @@ bool SignSignature( } bool SignSignature( - const CKeyStore &keystore, - const CTransaction& txFrom, - CMutableTransaction& txTo, - unsigned int nIn, - int nHashType, - uint32_t consensusBranchId) + const CKeyStore &keystore, + const CTransaction& txFrom, + CMutableTransaction& txTo, + unsigned int nIn, + int nHashType, + uint32_t consensusBranchId) { assert(nIn < txTo.vin.size()); CTxIn& txin = txTo.vin[nIn]; assert(txin.prevout.n < txFrom.vout.size()); const CTxOut& txout = txFrom.vout[txin.prevout.n]; - + return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType, consensusBranchId); } static vector CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker, - const vector& vSolutions, - const vector& sigs1, const vector& sigs2, uint32_t consensusBranchId) + const vector& vSolutions, + const vector& sigs1, const vector& sigs2, uint32_t consensusBranchId) { // Combine all the signatures we've got: set allsigs; @@ -467,7 +482,7 @@ static vector CombineMultisig(const CScript& scriptPubKey, const BaseSi if (!v.empty()) allsigs.insert(v); } - + // Build a map of pubkey -> signature by matching sigs to pubkeys: assert(vSolutions.size() > 1); unsigned int nSigsRequired = vSolutions.front()[0]; @@ -480,7 +495,7 @@ static vector CombineMultisig(const CScript& scriptPubKey, const BaseSi const valtype& pubkey = vSolutions[i+1]; if (sigs.count(pubkey)) continue; // Already got a sig for this pubkey - + if (checker.CheckSig(sig, pubkey, scriptPubKey, consensusBranchId)) { sigs[pubkey] = sig; @@ -502,108 +517,108 @@ static vector CombineMultisig(const CScript& scriptPubKey, const BaseSi // Fill any missing with OP_0: for (unsigned int i = nSigsHave; i < nSigsRequired; i++) result.push_back(valtype()); - + return result; } namespace { -struct Stacks -{ - std::vector script; - - Stacks() {} - explicit Stacks(const std::vector& scriptSigStack_) : script(scriptSigStack_) {} - explicit Stacks(const SignatureData& data, uint32_t consensusBranchId) { - EvalScript(script, data.scriptSig, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), consensusBranchId); - } - - SignatureData Output() const { - SignatureData result; - result.scriptSig = PushAll(script); - return result; - } -}; + struct Stacks + { + std::vector script; + + Stacks() {} + explicit Stacks(const std::vector& scriptSigStack_) : script(scriptSigStack_) {} + explicit Stacks(const SignatureData& data, uint32_t consensusBranchId) { + EvalScript(script, data.scriptSig, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), consensusBranchId); + } + + SignatureData Output() const { + SignatureData result; + result.scriptSig = PushAll(script); + return result; + } + }; } static Stacks CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, - const txnouttype txType, const vector& vSolutions, - Stacks sigs1, Stacks sigs2, uint32_t consensusBranchId) + const txnouttype txType, const vector& vSolutions, + Stacks sigs1, Stacks sigs2, uint32_t consensusBranchId) { switch (txType) { - case TX_NONSTANDARD: - case TX_NULL_DATA: - // Don't know anything about this, assume bigger one is correct: - if (sigs1.script.size() >= sigs2.script.size()) - return sigs1; - return sigs2; - case TX_PUBKEY: - case TX_PUBKEYHASH: - case TX_CRYPTOCONDITION: - // Signatures are bigger than placeholders or empty scripts: - if (sigs1.script.empty() || sigs1.script[0].empty()) + case TX_NONSTANDARD: + case TX_NULL_DATA: + // Don't know anything about this, assume bigger one is correct: + if (sigs1.script.size() >= sigs2.script.size()) + return sigs1; return sigs2; - return sigs1; - case TX_SCRIPTHASH: - if (sigs1.script.empty() || sigs1.script.back().empty()) - return sigs2; - else if (sigs2.script.empty() || sigs2.script.back().empty()) + case TX_PUBKEY: + case TX_PUBKEYHASH: + case TX_CRYPTOCONDITION: + // Signatures are bigger than placeholders or empty scripts: + if (sigs1.script.empty() || sigs1.script[0].empty()) + return sigs2; return sigs1; - else - { - // Recur to combine: - valtype spk = sigs1.script.back(); - CScript pubKey2(spk.begin(), spk.end()); - - txnouttype txType2; - vector > vSolutions2; - Solver(pubKey2, txType2, vSolutions2); - sigs1.script.pop_back(); - sigs2.script.pop_back(); - Stacks result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2, consensusBranchId); - result.script.push_back(spk); - return result; - } - case TX_MULTISIG: - return Stacks(CombineMultisig(scriptPubKey, checker, vSolutions, sigs1.script, sigs2.script, consensusBranchId)); - default: - return Stacks(); + case TX_SCRIPTHASH: + if (sigs1.script.empty() || sigs1.script.back().empty()) + return sigs2; + else if (sigs2.script.empty() || sigs2.script.back().empty()) + return sigs1; + else + { + // Recur to combine: + valtype spk = sigs1.script.back(); + CScript pubKey2(spk.begin(), spk.end()); + + txnouttype txType2; + vector > vSolutions2; + Solver(pubKey2, txType2, vSolutions2); + sigs1.script.pop_back(); + sigs2.script.pop_back(); + Stacks result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2, consensusBranchId); + result.script.push_back(spk); + return result; + } + case TX_MULTISIG: + return Stacks(CombineMultisig(scriptPubKey, checker, vSolutions, sigs1.script, sigs2.script, consensusBranchId)); + default: + return Stacks(); } } SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, - const SignatureData& scriptSig1, const SignatureData& scriptSig2, - uint32_t consensusBranchId) + const SignatureData& scriptSig1, const SignatureData& scriptSig2, + uint32_t consensusBranchId) { txnouttype txType; vector > vSolutions; Solver(scriptPubKey, txType, vSolutions); - + return CombineSignatures( - scriptPubKey, checker, txType, vSolutions, - Stacks(scriptSig1, consensusBranchId), - Stacks(scriptSig2, consensusBranchId), - consensusBranchId).Output(); + scriptPubKey, checker, txType, vSolutions, + Stacks(scriptSig1, consensusBranchId), + Stacks(scriptSig2, consensusBranchId), + consensusBranchId).Output(); } namespace { -/** Dummy signature checker which accepts all signatures. */ -class DummySignatureChecker : public BaseSignatureChecker -{ -public: - DummySignatureChecker() {} - - bool CheckSig( - const std::vector& scriptSig, - const std::vector& vchPubKey, - const CScript& scriptCode, - uint32_t consensusBranchId) const + /** Dummy signature checker which accepts all signatures. */ + class DummySignatureChecker : public BaseSignatureChecker { - return true; - } -}; -const DummySignatureChecker dummyChecker; + public: + DummySignatureChecker() {} + + bool CheckSig( + const std::vector& scriptSig, + const std::vector& vchPubKey, + const CScript& scriptCode, + uint32_t consensusBranchId) const + { + return true; + } + }; + const DummySignatureChecker dummyChecker; } const BaseSignatureChecker& DummySignatureCreator::Checker() const @@ -612,12 +627,12 @@ const BaseSignatureChecker& DummySignatureCreator::Checker() const } bool DummySignatureCreator::CreateSig( - std::vector& vchSig, - const CKeyID& keyid, - const CScript& scriptCode, - uint32_t consensusBranchId, - CKey *key, - void *extraData) const + std::vector& vchSig, + const CKeyID& keyid, + const CScript& scriptCode, + uint32_t consensusBranchId, + CKey *key, + void *extraData) const { // Create a dummy signature that is a valid DER-encoding vchSig.assign(72, '\000'); @@ -632,3 +647,4 @@ bool DummySignatureCreator::CreateSig( vchSig[6 + 33 + 32] = SIGHASH_ALL; return true; } + diff --git a/src/script/sign.h b/src/script/sign.h index ac2ab6476..4455d4281 100644 --- a/src/script/sign.h +++ b/src/script/sign.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_SCRIPT_SIGN_H #define BITCOIN_SCRIPT_SIGN_H diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 3b57afd9d..2b81abdc8 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "script/standard.h" #include "pubkey.h" @@ -453,26 +468,27 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vecto if (addressRet.empty()) return false; } - else if (IsCryptoConditionsEnabled() != 0 && typeRet == TX_CRYPTOCONDITION) - { - nRequiredRet = vSolutions.front()[0]; - for (unsigned int i = 1; i < vSolutions.size()-1; i++) - { - CTxDestination address; - if (vSolutions[i].size() == 20) - { - address = CKeyID(uint160(vSolutions[i])); - } - else - { - address = CPubKey(vSolutions[i]); - } - addressRet.push_back(address); - } + // Removed to get CC address printed in getrawtransaction and decoderawtransaction + // else if (IsCryptoConditionsEnabled() != 0 && typeRet == TX_CRYPTOCONDITION) + // { + // nRequiredRet = vSolutions.front()[0]; + // for (unsigned int i = 1; i < vSolutions.size()-1; i++) + // { + // CTxDestination address; + // if (vSolutions[i].size() == 20) + // { + // address = CKeyID(uint160(vSolutions[i])); + // } + // else + // { + // address = CPubKey(vSolutions[i]); + // } + // addressRet.push_back(address); + // } - if (addressRet.empty()) - return false; - } + // if (addressRet.empty()) + // return false; + // } else { nRequiredRet = 1; diff --git a/src/script/standard.h b/src/script/standard.h index 8536b56df..ae7336e2f 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_SCRIPT_STANDARD_H #define BITCOIN_SCRIPT_STANDARD_H diff --git a/src/script/zcashconsensus.cpp b/src/script/zcashconsensus.cpp index 50d732fff..dc4ec7dc1 100644 --- a/src/script/zcashconsensus.cpp +++ b/src/script/zcashconsensus.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "zcashconsensus.h" #include "consensus/upgrades.h" diff --git a/src/script/zcashconsensus.h b/src/script/zcashconsensus.h index ff13471c6..e01a50421 100644 --- a/src/script/zcashconsensus.h +++ b/src/script/zcashconsensus.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_ZCASHCONSENSUS_H #define BITCOIN_ZCASHCONSENSUS_H diff --git a/src/sendalert.cpp b/src/sendalert.cpp index f2c2b8c0f..700146338 100644 --- a/src/sendalert.cpp +++ b/src/sendalert.cpp @@ -1,6 +1,21 @@ // Copyright (c) 2016 The Zcash developers // Original code from: https://gist.github.com/laanwj/0e689cfa37b52bcbbb44 +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + /* To set up a new alert system diff --git a/src/serialize.h b/src/serialize.h index ac2db6edd..3d9c3fae6 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_SERIALIZE_H #define BITCOIN_SERIALIZE_H diff --git a/src/streams.h b/src/streams.h index 9d4a2e39e..83c90cd39 100644 --- a/src/streams.h +++ b/src/streams.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_STREAMS_H #define BITCOIN_STREAMS_H diff --git a/src/sync.cpp b/src/sync.cpp index 1837e8d53..31c3301bd 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "sync.h" #include "util.h" diff --git a/src/sync.h b/src/sync.h index c9ba7f8b0..a8f29eb66 100644 --- a/src/sync.h +++ b/src/sync.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_SYNC_H #define BITCOIN_SYNC_H diff --git a/src/test-komodo/test_coinimport.cpp b/src/test-komodo/test_coinimport.cpp index 8c1d8b0f8..fda62c30c 100644 --- a/src/test-komodo/test_coinimport.cpp +++ b/src/test-komodo/test_coinimport.cpp @@ -26,7 +26,7 @@ static uint8_t testNum = 0; class TestCoinImport : public ::testing::Test, public Eval { public: - CMutableTransaction burnTx; + CMutableTransaction burnTx; std::vector rawproof; std::vector payouts; TxProof proof; uint256 MoMoM; @@ -37,7 +37,7 @@ public: void SetImportTx() { burnTx.vout.resize(0); - burnTx.vout.push_back(MakeBurnOutput(amount, testCcid, testSymbol, payouts)); + burnTx.vout.push_back(MakeBurnOutput(amount, testCcid, testSymbol, payouts,rawproof)); importTx = CMutableTransaction(MakeImportCoinTransaction(proof, CTransaction(burnTx), payouts)); MoMoM = burnTx.GetHash(); // TODO: an actual branch } diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 6d80fc4b7..277b726c8 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -158,7 +158,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) for (unsigned int i = 0; i < sizeof(blockinfo)/sizeof(*blockinfo); ++i) { // Simple block creation, nothing special yet: - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); CBlock *pblock = &pblocktemplate->block; // pointer for convenience pblock->nVersion = 4; @@ -273,7 +273,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) } // Just to make sure we can still make simple blocks - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); delete pblocktemplate; // block sigops > limit: 1000 CHECKMULTISIG + 1 @@ -292,7 +292,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; } - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); delete pblocktemplate; mempool.clear(); @@ -313,14 +313,14 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; } - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); delete pblocktemplate; mempool.clear(); // orphan in mempool hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Time(GetTime()).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); delete pblocktemplate; mempool.clear(); @@ -338,7 +338,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue = 49000LL; hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); delete pblocktemplate; mempool.clear(); @@ -349,7 +349,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue = 0; hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); delete pblocktemplate; mempool.clear(); @@ -367,7 +367,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue -= 10000; hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); delete pblocktemplate; mempool.clear(); @@ -381,17 +381,17 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].scriptPubKey = CScript() << OP_2; hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); delete pblocktemplate; mempool.clear(); // subsidy changing int nHeight = chainActive.Height(); chainActive.Tip()->SetHeight(209999); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); delete pblocktemplate; chainActive.Tip()->SetHeight(210000); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); delete pblocktemplate; chainActive.Tip()->SetHeight(nHeight); @@ -423,7 +423,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(true).FromTx(tx2)); BOOST_CHECK(!CheckFinalTx(tx2, LOCKTIME_MEDIAN_TIME_PAST)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); // Neither tx should have made it into the template. BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 1); @@ -438,7 +438,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) //BOOST_CHECK(CheckFinalTx(tx)); //BOOST_CHECK(CheckFinalTx(tx2)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 2); delete pblocktemplate; diff --git a/src/timedata.cpp b/src/timedata.cpp index 1dcef2de3..daeb7bae0 100644 --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "timedata.h" #include "netbase.h" diff --git a/src/txdb.cpp b/src/txdb.cpp index 63e00dcd8..164167c29 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "txdb.h" #include "chainparams.h" diff --git a/src/txdb.h b/src/txdb.h index 1370ebeee..b9bae2fe4 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_TXDB_H #define BITCOIN_TXDB_H diff --git a/src/txmempool.cpp b/src/txmempool.cpp index c9b890169..f57860c76 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "txmempool.h" #include "clientversion.h" diff --git a/src/txmempool.h b/src/txmempool.h index 8f6a8c2c0..d3e7f7b57 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_TXMEMPOOL_H #define BITCOIN_TXMEMPOOL_H diff --git a/src/uint256.cpp b/src/uint256.cpp index 25148808c..c238490b8 100644 --- a/src/uint256.cpp +++ b/src/uint256.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "uint256.h" #include "utilstrencodings.h" diff --git a/src/uint256.h b/src/uint256.h index f22a8bafa..d819dc630 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_UINT256_H #define BITCOIN_UINT256_H diff --git a/src/util.cpp b/src/util.cpp index fa67f02ee..2abbf5bef 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #if defined(HAVE_CONFIG_H) #include "config/bitcoin-config.h" #endif diff --git a/src/version.h b/src/version.h index 72ddac446..8b46fe7cf 100644 --- a/src/version.h +++ b/src/version.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_VERSION_H #define BITCOIN_VERSION_H diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index c77489381..bba44fe50 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "asyncrpcoperation_mergetoaddress.h" #include "amount.h" @@ -42,7 +57,7 @@ int mta_find_output(UniValue obj, int n) if (!outputMapValue.isArray()) { throw JSONRPCError(RPC_WALLET_ERROR, "Missing outputmap for JoinSplit operation"); } - + UniValue outputMap = outputMapValue.get_array(); assert(outputMap.size() == ZC_NUM_JS_OUTPUTS); for (size_t i = 0; i < outputMap.size(); i++) { @@ -50,7 +65,7 @@ int mta_find_output(UniValue obj, int n) return i; } } - + throw std::logic_error("n is not present in outputmap"); } @@ -69,33 +84,33 @@ saplingNoteInputs_(saplingNoteInputs), recipient_(recipient), fee_(fee), context if (fee < 0 || fee > MAX_MONEY) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Fee is out of range"); } - + if (utxoInputs.empty() && sproutNoteInputs.empty() && saplingNoteInputs.empty()) { throw JSONRPCError(RPC_INVALID_PARAMETER, "No inputs"); } - + if (std::get<0>(recipient).size() == 0) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Recipient parameter missing"); } - + if (sproutNoteInputs.size() > 0 && saplingNoteInputs.size() > 0) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot send from both Sprout and Sapling addresses using z_mergetoaddress"); } - + if (sproutNoteInputs.size() > 0 && builder) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Sprout notes are not supported by the TransactionBuilder"); } - + isUsingBuilder_ = false; if (builder) { isUsingBuilder_ = true; builder_ = builder.get(); } - + toTaddr_ = DecodeDestination(std::get<0>(recipient)); isToTaddr_ = IsValidDestination(toTaddr_); isToZaddr_ = false; - + if (!isToTaddr_) { auto address = DecodePaymentAddress(std::get<0>(recipient)); if (IsValidPaymentAddress(address)) { @@ -105,18 +120,18 @@ saplingNoteInputs_(saplingNoteInputs), recipient_(recipient), fee_(fee), context throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid recipient address"); } } - + // Log the context info i.e. the call parameters to z_mergetoaddress if (LogAcceptCategory("zrpcunsafe")) { LogPrint("zrpcunsafe", "%s: z_mergetoaddress initialized (params=%s)\n", getId(), contextInfo.write()); } else { LogPrint("zrpc", "%s: z_mergetoaddress initialized\n", getId()); } - + // Lock UTXOs lock_utxos(); lock_notes(); - + // Enable payment disclosure if requested paymentDisclosureMode = fExperimentalMode && GetBoolArg("-paymentdisclosure", true); } @@ -132,12 +147,12 @@ void AsyncRPCOperation_mergetoaddress::main() unlock_notes(); return; } - + set_state(OperationStatus::EXECUTING); start_execution_clock(); - + bool success = false; - + #ifdef ENABLE_MINING #ifdef ENABLE_WALLET GenerateBitcoins(false, NULL, 0); @@ -145,7 +160,7 @@ void AsyncRPCOperation_mergetoaddress::main() GenerateBitcoins(false, 0); #endif #endif - + try { success = main_impl(); } catch (const UniValue& objError) { @@ -166,7 +181,7 @@ void AsyncRPCOperation_mergetoaddress::main() set_error_code(-2); set_error_message("unknown error"); } - + #ifdef ENABLE_MINING #ifdef ENABLE_WALLET GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain, GetArg("-genproclimit", 1)); @@ -174,15 +189,15 @@ void AsyncRPCOperation_mergetoaddress::main() GenerateBitcoins(GetBoolArg("-gen", false), GetArg("-genproclimit", 1)); #endif #endif - + stop_execution_clock(); - + if (success) { set_state(OperationStatus::SUCCESS); } else { set_state(OperationStatus::FAILED); } - + std::string s = strprintf("%s: z_mergetoaddress finished (status=%s", getId(), getStateAsString()); if (success) { s += strprintf(", txid=%s)\n", tx_.GetHash().ToString()); @@ -190,10 +205,10 @@ void AsyncRPCOperation_mergetoaddress::main() s += strprintf(", error=%s)\n", getErrorMessage()); } LogPrintf("%s", s); - + unlock_utxos(); // clean up unlock_notes(); // clean up - + // !!! Payment disclosure START if (success && paymentDisclosureMode && paymentDisclosureData_.size() > 0) { uint256 txidhash = tx_.GetHash(); @@ -216,12 +231,12 @@ void AsyncRPCOperation_mergetoaddress::main() bool AsyncRPCOperation_mergetoaddress::main_impl() { assert(isToTaddr_ != isToZaddr_); - + bool isPureTaddrOnlyTx = (sproutNoteInputs_.empty() && saplingNoteInputs_.empty() && isToTaddr_); CAmount minersFee = fee_; - + size_t numInputs = utxoInputs_.size(); - + // Check mempooltxinputlimit to avoid creating a transaction which the local mempool rejects size_t limit = (size_t)GetArg("-mempooltxinputlimit", 0); { @@ -235,31 +250,31 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() strprintf("Number of transparent inputs %d is greater than mempooltxinputlimit of %d", numInputs, limit)); } - + CAmount t_inputs_total = 0; for (MergeToAddressInputUTXO& t : utxoInputs_) { t_inputs_total += std::get<1>(t); } - + CAmount z_inputs_total = 0; for (const MergeToAddressInputSproutNote& t : sproutNoteInputs_) { z_inputs_total += std::get<2>(t); } - + for (const MergeToAddressInputSaplingNote& t : saplingNoteInputs_) { z_inputs_total += std::get<2>(t); } - + CAmount targetAmount = z_inputs_total + t_inputs_total; - + if (targetAmount <= minersFee) { throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strprintf("Insufficient funds, have %s and miners fee is %s", FormatMoney(targetAmount), FormatMoney(minersFee))); } - + CAmount sendAmount = targetAmount - minersFee; - + // update the transaction with the UTXO inputs and output (if any) if (!isUsingBuilder_) { CMutableTransaction rawTx(tx_); @@ -274,7 +289,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() } tx_ = CTransaction(rawTx); } - + LogPrint(isPureTaddrOnlyTx ? "zrpc" : "zrpcunsafe", "%s: spending %s to send %s with fee %s\n", getId(), FormatMoney(targetAmount), FormatMoney(sendAmount), FormatMoney(minersFee)); LogPrint("zrpc", "%s: transparent input: %s\n", getId(), FormatMoney(t_inputs_total)); @@ -285,13 +300,13 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() LogPrint("zrpcunsafe", "%s: private output: %s\n", getId(), FormatMoney(sendAmount)); } LogPrint("zrpc", "%s: fee: %s\n", getId(), FormatMoney(minersFee)); - + // Grab the current consensus branch ID { LOCK(cs_main); consensusBranchId_ = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); } - + /** * SCENARIO #0 * @@ -301,15 +316,15 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() */ if (isUsingBuilder_) { builder_.SetFee(minersFee); - - + + for (const MergeToAddressInputUTXO& t : utxoInputs_) { COutPoint outPoint = std::get<0>(t); CAmount amount = std::get<1>(t); CScript scriptPubKey = std::get<2>(t); builder_.AddTransparentInput(outPoint, scriptPubKey, amount); } - + boost::optional ovk; // Select Sapling notes std::vector saplingOPs; @@ -324,7 +339,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() ovk = expsk.full_viewing_key().ovk; } } - + // Fetch Sapling anchor and witnesses uint256 anchor; std::vector> witnesses; @@ -332,7 +347,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() LOCK2(cs_main, pwalletMain->cs_wallet); pwalletMain->GetSaplingNoteWitnesses(saplingOPs, witnesses, anchor); } - + // Add Sapling spends for (size_t i = 0; i < saplingNotes.size(); i++) { if (!witnesses[i]) { @@ -340,7 +355,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() } assert(builder_.AddSaplingSpend(expsks[i], saplingNotes[i], anchor, witnesses[i].get())); } - + if (isToTaddr_) { if (!builder_.AddTransparentOutput(toTaddr_, sendAmount)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid output address, not a valid taddr."); @@ -372,15 +387,15 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() } builder_.AddSaplingOutput(ovk.get(), *saplingPaymentAddress, sendAmount, hexMemo); } - - + + // Build the transaction auto maybe_tx = builder_.Build(); if (!maybe_tx) { throw JSONRPCError(RPC_WALLET_ERROR, "Failed to build transaction."); } tx_ = maybe_tx.get(); - + // Send the transaction // TODO: Use CWallet::CommitTransaction instead of sendrawtransaction auto signedtxn = EncodeHexTx(tx_); @@ -391,9 +406,9 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() if (sendResultValue.isNull()) { throw JSONRPCError(RPC_WALLET_ERROR, "sendrawtransaction did not return an error or a txid."); } - + auto txid = sendResultValue.get_str(); - + UniValue o(UniValue::VOBJ); o.push_back(Pair("txid", txid)); set_result(o); @@ -405,14 +420,14 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() o.push_back(Pair("hex", signedtxn)); set_result(o); } - + return true; } /** * END SCENARIO #0 */ - - + + /** * SCENARIO #1 * @@ -429,16 +444,16 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() /** * END SCENARIO #1 */ - - + + // Prepare raw transaction to handle JoinSplits CMutableTransaction mtx(tx_); crypto_sign_keypair(joinSplitPubKey_.begin(), joinSplitPrivKey_); mtx.joinSplitPubKey = joinSplitPubKey_; tx_ = CTransaction(mtx); std::string hexMemo = std::get<1>(recipient_); - - + + /** * SCENARIO #2 * @@ -451,13 +466,13 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() MergeToAddressJSInfo info; info.vpub_old = sendAmount; info.vpub_new = 0; - + JSOutput jso = JSOutput(boost::get(toPaymentAddress_), sendAmount); if (hexMemo.size() > 0) { jso.memo = get_memo_from_hex_string(hexMemo); } info.vjsout.push_back(jso); - + UniValue obj(UniValue::VOBJ); obj = perform_joinsplit(info); sign_send_raw_transaction(obj); @@ -466,14 +481,14 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() /** * END SCENARIO #2 */ - - + + // Copy zinputs to more flexible containers std::deque zInputsDeque; for (const auto& o : sproutNoteInputs_) { zInputsDeque.push_back(o); } - + // When spending notes, take a snapshot of note witnesses and anchors as the treestate will // change upon arrival of new blocks which contain joinsplit transactions. This is likely // to happen as creating a chained joinsplit transaction can take longer than the block interval. @@ -488,7 +503,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() jsopWitnessAnchorMap[jso.ToString()] = MergeToAddressWitnessAnchorData{vInputWitnesses[0], inputAnchor}; } } - + /** * SCENARIO #3 * @@ -507,12 +522,12 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() int changeOutputIndex = -1; // this is updated after each joinsplit if jsChange > 0 bool vpubOldProcessed = false; // updated when vpub_old for taddr inputs is set in first joinsplit bool vpubNewProcessed = false; // updated when vpub_new for miner fee and taddr outputs is set in last joinsplit - + // At this point, we are guaranteed to have at least one input note. // Use address of first input note as the temporary change address. SproutSpendingKey changeKey = std::get<3>(zInputsDeque.front()); SproutPaymentAddress changeAddress = changeKey.address(); - + CAmount vpubOldTarget = 0; CAmount vpubNewTarget = 0; if (isToTaddr_) { @@ -524,16 +539,16 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() vpubOldTarget = t_inputs_total - minersFee; } } - + // Keep track of treestate within this transaction boost::unordered_map intermediates; std::vector previousCommitments; - + while (!vpubNewProcessed) { MergeToAddressJSInfo info; info.vpub_old = 0; info.vpub_new = 0; - + // Set vpub_old in the first joinsplit if (!vpubOldProcessed) { if (t_inputs_total < vpubOldTarget) { @@ -544,30 +559,30 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() info.vpub_old += vpubOldTarget; // funds flowing from public pool vpubOldProcessed = true; } - + CAmount jsInputValue = 0; uint256 jsAnchor; std::vector> witnesses; - + JSDescription prevJoinSplit; - + // Keep track of previous JoinSplit and its commitments if (tx_.vjoinsplit.size() > 0) { prevJoinSplit = tx_.vjoinsplit.back(); } - + // If there is no change, the chain has terminated so we can reset the tracked treestate. if (jsChange == 0 && tx_.vjoinsplit.size() > 0) { intermediates.clear(); previousCommitments.clear(); } - + // // Consume change as the first input of the JoinSplit. // if (jsChange > 0) { LOCK2(cs_main, pwalletMain->cs_wallet); - + // Update tree state with previous joinsplit SproutMerkleTree tree; auto it = intermediates.find(prevJoinSplit.anchor); @@ -576,7 +591,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() } else if (!pcoinsTip->GetSproutAnchorAt(prevJoinSplit.anchor, tree)) { throw JSONRPCError(RPC_WALLET_ERROR, "Could not find previous JoinSplit anchor"); } - + assert(changeOutputIndex != -1); boost::optional changeWitness; int n = 0; @@ -594,7 +609,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() } jsAnchor = tree.root(); intermediates.insert(std::make_pair(tree.root(), tree)); // chained js are interstitial (found in between block boundaries) - + // Decrypt the change note's ciphertext to retrieve some data we need ZCNoteDecryption decryptor(changeKey.receiving_key()); auto hSig = prevJoinSplit.h_sig(*pzcashParams, tx_.joinSplitPubKey); @@ -605,23 +620,23 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() prevJoinSplit.ephemeralKey, hSig, (unsigned char)changeOutputIndex); - + SproutNote note = plaintext.note(changeAddress); info.notes.push_back(note); info.zkeys.push_back(changeKey); - + jsInputValue += plaintext.value(); - + LogPrint("zrpcunsafe", "%s: spending change (amount=%s)\n", getId(), FormatMoney(plaintext.value())); - + } catch (const std::exception& e) { throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Error decrypting output note of previous JoinSplit: %s", e.what())); } } - - + + // // Consume spendable non-change notes // @@ -638,7 +653,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() CAmount noteFunds = std::get<2>(t); SproutSpendingKey zkey = std::get<3>(t); zInputsDeque.pop_front(); - + MergeToAddressWitnessAnchorData wad = jsopWitnessAnchorMap[jso.ToString()]; vInputWitnesses.push_back(wad.witness); if (inputAnchor.IsNull()) { @@ -646,13 +661,13 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() } else if (inputAnchor != wad.anchor) { throw JSONRPCError(RPC_WALLET_ERROR, "Selected input notes do not share the same anchor"); } - + vOutPoints.push_back(jso); vInputNotes.push_back(note); vInputZKeys.push_back(zkey); - + jsInputValue += noteFunds; - + int wtxHeight = -1; int wtxDepth = -1; { @@ -674,13 +689,13 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() wtxHeight, wtxDepth); } - + // Add history of previous commitments to witness if (vInputNotes.size() > 0) { if (vInputWitnesses.size() == 0) { throw JSONRPCError(RPC_WALLET_ERROR, "Could not find witness for note commitment"); } - + for (auto& optionalWitness : vInputWitnesses) { if (!optionalWitness) { throw JSONRPCError(RPC_WALLET_ERROR, "Witness for note commitment is null"); @@ -696,20 +711,20 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() } witnesses.push_back(w); } - + // The jsAnchor is null if this JoinSplit is at the start of a new chain if (jsAnchor.IsNull()) { jsAnchor = inputAnchor; } - + // Add spendable notes as inputs std::copy(vInputNotes.begin(), vInputNotes.end(), std::back_inserter(info.notes)); std::copy(vInputZKeys.begin(), vInputZKeys.end(), std::back_inserter(info.zkeys)); } - + // Accumulate change jsChange = jsInputValue + info.vpub_old; - + // Set vpub_new in the last joinsplit (when there are no more notes to spend) if (zInputsDeque.empty()) { assert(!vpubNewProcessed); @@ -724,10 +739,10 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() // If we are merging to a t-addr, there should be no change if (isToTaddr_) assert(jsChange == 0); } - + // create dummy output info.vjsout.push_back(JSOutput()); // dummy output while we accumulate funds into a change note for vpub_new - + // create output for any change if (jsChange > 0) { std::string outputType = "change"; @@ -741,24 +756,24 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() } } info.vjsout.push_back(jso); - + LogPrint("zrpcunsafe", "%s: generating note for %s (amount=%s)\n", getId(), outputType, FormatMoney(jsChange)); } - + obj = perform_joinsplit(info, witnesses, jsAnchor); - + if (jsChange > 0) { changeOutputIndex = mta_find_output(obj, 1); } } - + // Sanity check in case changes to code block above exits loop by invoking 'break' assert(zInputsDeque.size() == 0); assert(vpubNewProcessed); - + sign_send_raw_transaction(obj); return true; } @@ -778,7 +793,7 @@ void AsyncRPCOperation_mergetoaddress::sign_send_raw_transaction(UniValue obj) throw JSONRPCError(RPC_WALLET_ERROR, "Missing hex data for raw transaction"); } std::string rawtxn = rawtxnValue.get_str(); - + UniValue params = UniValue(UniValue::VARR); params.push_back(rawtxn); UniValue signResultValue = signrawtransaction(params, false); @@ -789,13 +804,13 @@ void AsyncRPCOperation_mergetoaddress::sign_send_raw_transaction(UniValue obj) // TODO: #1366 Maybe get "errors" and print array vErrors into a string throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Failed to sign transaction"); } - + UniValue hexValue = find_value(signResultObject, "hex"); if (hexValue.isNull()) { throw JSONRPCError(RPC_WALLET_ERROR, "Missing hex data for signed transaction"); } std::string signedtxn = hexValue.get_str(); - + // Send the signed transaction if (!testmode) { params.clear(); @@ -805,26 +820,26 @@ void AsyncRPCOperation_mergetoaddress::sign_send_raw_transaction(UniValue obj) if (sendResultValue.isNull()) { throw JSONRPCError(RPC_WALLET_ERROR, "Send raw transaction did not return an error or a txid."); } - + std::string txid = sendResultValue.get_str(); - + UniValue o(UniValue::VOBJ); o.push_back(Pair("txid", txid)); set_result(o); } else { // Test mode does not send the transaction to the network. - + CDataStream stream(ParseHex(signedtxn), SER_NETWORK, PROTOCOL_VERSION); CTransaction tx; stream >> tx; - + UniValue o(UniValue::VOBJ); o.push_back(Pair("test", 1)); o.push_back(Pair("txid", tx.GetHash().ToString())); o.push_back(Pair("hex", signedtxn)); set_result(o); } - + // Keep the signed transaction so we can hash to the same txid CDataStream stream(ParseHex(signedtxn), SER_NETWORK, PROTOCOL_VERSION); CTransaction tx; @@ -864,52 +879,52 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit( if (anchor.IsNull()) { throw std::runtime_error("anchor is null"); } - + if (witnesses.size() != info.notes.size()) { throw runtime_error("number of notes and witnesses do not match"); } - + if (info.notes.size() != info.zkeys.size()) { throw runtime_error("number of notes and spending keys do not match"); } - + for (size_t i = 0; i < witnesses.size(); i++) { if (!witnesses[i]) { throw runtime_error("joinsplit input could not be found in tree"); } info.vjsin.push_back(JSInput(*witnesses[i], info.notes[i], info.zkeys[i])); } - + // Make sure there are two inputs and two outputs while (info.vjsin.size() < ZC_NUM_JS_INPUTS) { info.vjsin.push_back(JSInput()); } - + while (info.vjsout.size() < ZC_NUM_JS_OUTPUTS) { info.vjsout.push_back(JSOutput()); } - + if (info.vjsout.size() != ZC_NUM_JS_INPUTS || info.vjsin.size() != ZC_NUM_JS_OUTPUTS) { throw runtime_error("unsupported joinsplit input/output counts"); } - + CMutableTransaction mtx(tx_); - + LogPrint("zrpcunsafe", "%s: creating joinsplit at index %d (vpub_old=%s, vpub_new=%s, in[0]=%s, in[1]=%s, out[0]=%s, out[1]=%s)\n", getId(), tx_.vjoinsplit.size(), FormatMoney(info.vpub_old), FormatMoney(info.vpub_new), FormatMoney(info.vjsin[0].note.value()), FormatMoney(info.vjsin[1].note.value()), FormatMoney(info.vjsout[0].value), FormatMoney(info.vjsout[1].value)); - + // Generate the proof, this can take over a minute. std::array inputs{info.vjsin[0], info.vjsin[1]}; std::array outputs{info.vjsout[0], info.vjsout[1]}; std::array inputMap; std::array outputMap; - + uint256 esk; // payment disclosure - secret - + JSDescription jsdesc = JSDescription::Randomized( mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION), *pzcashParams, @@ -929,34 +944,34 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit( throw std::runtime_error("error verifying joinsplit"); } } - + mtx.vjoinsplit.push_back(jsdesc); - + // Empty output script. CScript scriptCode; CTransaction signTx(mtx); uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId_); - + // Add the signature if (!(crypto_sign_detached(&mtx.joinSplitSig[0], NULL, dataToBeSigned.begin(), 32, joinSplitPrivKey_) == 0)) { throw std::runtime_error("crypto_sign_detached failed"); } - + // Sanity check if (!(crypto_sign_verify_detached(&mtx.joinSplitSig[0], dataToBeSigned.begin(), 32, mtx.joinSplitPubKey.begin()) == 0)) { throw std::runtime_error("crypto_sign_verify_detached failed"); } - + CTransaction rawTx(mtx); tx_ = rawTx; - + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << rawTx; - + std::string encryptedNote1; std::string encryptedNote2; { @@ -965,7 +980,7 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit( ss2 << jsdesc.ephemeralKey; ss2 << jsdesc.ciphertexts[0]; ss2 << jsdesc.h_sig(*pzcashParams, joinSplitPubKey_); - + encryptedNote1 = HexStr(ss2.begin(), ss2.end()); } { @@ -974,10 +989,10 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit( ss2 << jsdesc.ephemeralKey; ss2 << jsdesc.ciphertexts[1]; ss2 << jsdesc.h_sig(*pzcashParams, joinSplitPubKey_); - + encryptedNote2 = HexStr(ss2.begin(), ss2.end()); } - + UniValue arrInputMap(UniValue::VARR); UniValue arrOutputMap(UniValue::VARR); for (size_t i = 0; i < ZC_NUM_JS_INPUTS; i++) { @@ -986,8 +1001,8 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit( for (size_t i = 0; i < ZC_NUM_JS_OUTPUTS; i++) { arrOutputMap.push_back(static_cast(outputMap[i])); } - - + + // !!! Payment disclosure START unsigned char buffer[32] = {0}; memcpy(&buffer[0], &joinSplitPrivKey_[0], 32); // private key in first half of 64 byte buffer @@ -1003,11 +1018,11 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit( libzcash::SproutPaymentAddress zaddr = output.addr; // randomized output PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey, zaddr}; paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo)); - + LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), EncodePaymentAddress(zaddr)); } // !!! Payment disclosure END - + UniValue obj(UniValue::VOBJ); obj.push_back(Pair("encryptednote1", encryptedNote1)); obj.push_back(Pair("encryptednote2", encryptedNote2)); @@ -1020,19 +1035,19 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit( std::array AsyncRPCOperation_mergetoaddress::get_memo_from_hex_string(std::string s) { std::array memo = {{0x00}}; - + std::vector rawMemo = ParseHex(s.c_str()); - + // If ParseHex comes across a non-hex char, it will stop but still return results so far. size_t slen = s.length(); if (slen % 2 != 0 || (slen > 0 && rawMemo.size() != slen / 2)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Memo must be in hexadecimal format"); } - + if (rawMemo.size() > ZC_MEMO_SIZE) { throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Memo size of %d is too big, maximum allowed is %d", rawMemo.size(), ZC_MEMO_SIZE)); } - + // copy vector into boost array int lenMemo = rawMemo.size(); for (int i = 0; i < ZC_MEMO_SIZE && i < lenMemo; i++) { @@ -1050,7 +1065,7 @@ UniValue AsyncRPCOperation_mergetoaddress::getStatus() const if (contextinfo_.isNull()) { return v; } - + UniValue obj = v.get_obj(); obj.push_back(Pair("method", "z_mergetoaddress")); obj.push_back(Pair("params", contextinfo_)); diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.h b/src/wallet/asyncrpcoperation_mergetoaddress.h index f7ac81261..be49baff0 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.h +++ b/src/wallet/asyncrpcoperation_mergetoaddress.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef ASYNCRPCOPERATION_MERGETOADDRESS_H #define ASYNCRPCOPERATION_MERGETOADDRESS_H diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index 73288142a..d4c5077cc 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "asyncrpcoperation_sendmany.h" #include "asyncrpcqueue.h" #include "amount.h" @@ -169,9 +184,9 @@ void AsyncRPCOperation_sendmany::main() { #ifdef ENABLE_MINING #ifdef ENABLE_WALLET - GenerateBitcoins(GetBoolArg("-gen",false), pwalletMain, GetArg("-genproclimit", 0)); + GenerateBitcoins(GetBoolArg("-gen",false), pwalletMain, GetArg("-genproclimit", 1)); #else - GenerateBitcoins(GetBoolArg("-gen",false), GetArg("-genproclimit", 0)); + GenerateBitcoins(GetBoolArg("-gen",false), GetArg("-genproclimit", 1)); #endif #endif @@ -807,9 +822,9 @@ bool AsyncRPCOperation_sendmany::main_impl() { vOutPoints.push_back(jso); vInputNotes.push_back(note); - + jsInputValue += noteFunds; - + int wtxHeight = -1; int wtxDepth = -1; { @@ -832,14 +847,14 @@ bool AsyncRPCOperation_sendmany::main_impl() { wtxDepth ); } - + // Add history of previous commitments to witness if (vInputNotes.size() > 0) { if (vInputWitnesses.size()==0) { throw JSONRPCError(RPC_WALLET_ERROR, "Could not find witness for note commitment"); } - + for (auto & optionalWitness : vInputWitnesses) { if (!optionalWitness) { throw JSONRPCError(RPC_WALLET_ERROR, "Witness for note commitment is null"); @@ -1061,7 +1076,7 @@ bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptCoinbase=false) { continue; CAmount nValue = out.tx->vout[out.i].nValue; - + SendManyInputUTXO utxo(out.tx->GetHash(), out.i, nValue, isCoinbase, dest); t_inputs_.push_back(utxo); } @@ -1368,7 +1383,7 @@ void AsyncRPCOperation_sendmany::add_taddr_change_output_to_tx(CBitcoinAddress * std::array AsyncRPCOperation_sendmany::get_memo_from_hex_string(std::string s) { // initialize to default memo (no_memo), see section 5.5 of the protocol spec std::array memo = {{0xF6}}; - + std::vector rawMemo = ParseHex(s.c_str()); // If ParseHex comes across a non-hex char, it will stop but still return results so far. diff --git a/src/wallet/asyncrpcoperation_sendmany.h b/src/wallet/asyncrpcoperation_sendmany.h index a93925874..8e39f341a 100644 --- a/src/wallet/asyncrpcoperation_sendmany.h +++ b/src/wallet/asyncrpcoperation_sendmany.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef ASYNCRPCOPERATION_SENDMANY_H #define ASYNCRPCOPERATION_SENDMANY_H diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp index 37c771dcb..73e70a9d8 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "asyncrpcqueue.h" #include "amount.h" #include "consensus/upgrades.h" @@ -141,9 +156,9 @@ void AsyncRPCOperation_shieldcoinbase::main() { #ifdef ENABLE_MINING #ifdef ENABLE_WALLET - GenerateBitcoins(GetBoolArg("-gen",false), pwalletMain, GetArg("-genproclimit", 0)); + GenerateBitcoins(GetBoolArg("-gen",false), pwalletMain, GetArg("-genproclimit", 1)); #else - GenerateBitcoins(GetBoolArg("-gen",false), GetArg("-genproclimit", 0)); + GenerateBitcoins(GetBoolArg("-gen",false), GetArg("-genproclimit", 1)); #endif #endif diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.h b/src/wallet/asyncrpcoperation_shieldcoinbase.h index e75bb8e82..b3fef0fc1 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.h +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef ASYNCRPCOPERATION_SHIELDCOINBASE_H #define ASYNCRPCOPERATION_SHIELDCOINBASE_H diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index 05c1a6e76..38aff1a04 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "crypter.h" #include "script/script.h" diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h index 1cfefe886..f42a762af 100644 --- a/src/wallet/crypter.h +++ b/src/wallet/crypter.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_WALLET_CRYPTER_H #define BITCOIN_WALLET_CRYPTER_H diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index c6beb8a52..dd0880b75 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "db.h" #include "addrman.h" diff --git a/src/wallet/db.h b/src/wallet/db.h index 64071caa3..19b9b6079 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_WALLET_DB_H #define BITCOIN_WALLET_DB_H diff --git a/src/wallet/rpcdisclosure.cpp b/src/wallet/rpcdisclosure.cpp index 41195cfc8..19fb44d0e 100644 --- a/src/wallet/rpcdisclosure.cpp +++ b/src/wallet/rpcdisclosure.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "rpc/server.h" #include "init.h" #include "key_io.h" diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 7ec0c23c1..d233b418a 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "chain.h" #include "key_io.h" #include "rpc/server.h" diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index f8b507403..c1cf25b41 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "amount.h" #include "consensus/upgrades.h" #include "core_io.h" @@ -42,6 +57,7 @@ #include +#include "komodo_defs.h" using namespace std; @@ -52,8 +68,6 @@ const std::string ADDR_TYPE_SPROUT = "sprout"; const std::string ADDR_TYPE_SAPLING = "sapling"; extern UniValue TxJoinSplitToJSON(const CTransaction& tx); -extern uint8_t ASSETCHAINS_PRIVATE; -extern int32_t USE_EXTERNAL_PUBKEY; uint32_t komodo_segid32(char *coinaddr); int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); int32_t komodo_isnotaryvout(char *coinaddr); // from ac_private chains only @@ -1420,11 +1434,13 @@ struct tallyitem int nConf; vector txids; bool fIsWatchonly; + int nHeight; tallyitem() { nAmount = 0; nConf = std::numeric_limits::max(); fIsWatchonly = false; + nHeight = 0; } }; @@ -1470,6 +1486,7 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts) tallyitem& item = mapTally[address]; item.nAmount += txout.nValue; // komodo_interest? item.nConf = min(item.nConf, nDepth); + item.nHeight = mapBlockIndex[wtx.hashBlock]->GetHeight(); item.txids.push_back(wtx.GetHash()); if (mine & ISMINE_WATCH_ONLY) item.fIsWatchonly = true; @@ -1489,11 +1506,13 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts) CAmount nAmount = 0; int nConf = std::numeric_limits::max(); bool fIsWatchonly = false; + int nHeight=0; if (it != mapTally.end()) { nAmount = (*it).second.nAmount; nConf = (*it).second.nConf; fIsWatchonly = (*it).second.fIsWatchonly; + nHeight = (*it).second.nHeight; } if (fByAccounts) @@ -1506,12 +1525,14 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts) else { UniValue obj(UniValue::VOBJ); + if(fIsWatchonly) obj.push_back(Pair("involvesWatchonly", true)); obj.push_back(Pair("address", EncodeDestination(dest))); obj.push_back(Pair("account", strAccount)); obj.push_back(Pair("amount", ValueFromAmount(nAmount))); - obj.push_back(Pair("confirmations", (nConf == std::numeric_limits::max() ? 0 : nConf))); + obj.push_back(Pair("rawconfirmations", (nConf == std::numeric_limits::max() ? 0 : nConf))); + obj.push_back(Pair("confirmations", (nConf == std::numeric_limits::max() ? 0 : komodo_dpowconfs(nHeight, nConf)))); UniValue transactions(UniValue::VARR); if (it != mapTally.end()) { @@ -1531,12 +1552,14 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts) { CAmount nAmount = (*it).second.nAmount; int nConf = (*it).second.nConf; + int nHeight = (*it).second.nHeight; UniValue obj(UniValue::VOBJ); if((*it).second.fIsWatchonly) obj.push_back(Pair("involvesWatchonly", true)); obj.push_back(Pair("account", (*it).first)); obj.push_back(Pair("amount", ValueFromAmount(nAmount))); - obj.push_back(Pair("confirmations", (nConf == std::numeric_limits::max() ? 0 : nConf))); + obj.push_back(Pair("rawconfirmations", (nConf == std::numeric_limits::max() ? 0 : nConf))); + obj.push_back(Pair("confirmations", (nConf == std::numeric_limits::max() ? 0 : komodo_dpowconfs(nHeight, nConf)))); ret.push_back(obj); } } @@ -1674,7 +1697,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY)) entry.push_back(Pair("involvesWatchonly", true)); entry.push_back(Pair("account", account)); - + CTxDestination dest; if (CScriptExt::ExtractVoutDestination(wtx, r.vout, dest)) MaybePushAddress(entry, dest); @@ -2920,11 +2943,11 @@ UniValue z_listunspent(const UniValue& params, bool fHelp) // User did not provide zaddrs, so use default i.e. all addresses std::set sproutzaddrs = {}; pwalletMain->GetSproutPaymentAddresses(sproutzaddrs); - + // Sapling support std::set saplingzaddrs = {}; pwalletMain->GetSaplingPaymentAddresses(saplingzaddrs); - + zaddrs.insert(sproutzaddrs.begin(), sproutzaddrs.end()); zaddrs.insert(saplingzaddrs.begin(), saplingzaddrs.end()); } @@ -2936,13 +2959,32 @@ UniValue z_listunspent(const UniValue& params, bool fHelp) std::vector saplingEntries; pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs, nMinDepth, nMaxDepth, true, !fIncludeWatchonly, false); std::set> nullifierSet = pwalletMain->GetNullifiersForAddresses(zaddrs); - + for (auto & entry : sproutEntries) { UniValue obj(UniValue::VOBJ); + int nHeight = 0; + CTransaction tx; + uint256 hashBlock; + obj.push_back(Pair("txid", entry.jsop.hash.ToString())); obj.push_back(Pair("jsindex", (int)entry.jsop.js )); obj.push_back(Pair("jsoutindex", (int)entry.jsop.n)); - obj.push_back(Pair("confirmations", entry.confirmations)); + + if (!GetTransaction(entry.jsop.hash, tx, hashBlock, true)) { + // TODO: should we throw JSONRPCError ? + fprintf(stderr,"tx hash %s does not exist!\n", entry.jsop.hash.ToString().c_str() ); + } + + BlockMap::const_iterator it = mapBlockIndex.find(hashBlock); + if (it != mapBlockIndex.end()) { + nHeight = it->second->GetHeight(); + //fprintf(stderr,"blockHash %s height %d\n",hashBlock.ToString().c_str(), nHeight); + } else { + // TODO: should we throw JSONRPCError ? + fprintf(stderr,"block hash %s does not exist!\n", hashBlock.ToString().c_str() ); + } + obj.push_back(Pair("confirmations", komodo_dpowconfs(nHeight, entry.confirmations))); + obj.push_back(Pair("rawconfirmations", entry.confirmations)); bool hasSproutSpendingKey = pwalletMain->HaveSproutSpendingKey(boost::get(entry.address)); obj.push_back(Pair("spendable", hasSproutSpendingKey)); obj.push_back(Pair("address", EncodePaymentAddress(entry.address))); @@ -2954,12 +2996,29 @@ UniValue z_listunspent(const UniValue& params, bool fHelp) } results.push_back(obj); } - + for (auto & entry : saplingEntries) { UniValue obj(UniValue::VOBJ); obj.push_back(Pair("txid", entry.op.hash.ToString())); obj.push_back(Pair("outindex", (int)entry.op.n)); - obj.push_back(Pair("confirmations", entry.confirmations)); + int nHeight = 0; + CTransaction tx; + uint256 hashBlock; + if (!GetTransaction(entry.op.hash, tx, hashBlock, true)) { + // TODO: should we throw JSONRPCError ? + fprintf(stderr,"tx hash %s does not exist!\n", entry.op.hash.ToString().c_str() ); + } + + BlockMap::const_iterator it = mapBlockIndex.find(hashBlock); + if (it != mapBlockIndex.end()) { + nHeight = it->second->GetHeight(); + //fprintf(stderr,"blockHash %s height %d\n",hashBlock.ToString().c_str(), nHeight); + } else { + // TODO: should we throw JSONRPCError ? + fprintf(stderr,"block hash %s does not exist!\n", hashBlock.ToString().c_str() ); + } + obj.push_back(Pair("confirmations", komodo_dpowconfs(nHeight, entry.confirmations))); + obj.push_back(Pair("rawconfirmations", entry.confirmations)); libzcash::SaplingIncomingViewingKey ivk; libzcash::SaplingFullViewingKey fvk; pwalletMain->GetSaplingIncomingViewingKey(boost::get(entry.address), ivk); @@ -3687,7 +3746,11 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp) "{\n" " \"txid\": xxxxx, (string) the transaction id\n" " \"amount\": xxxxx, (numeric) the amount of value in the note\n" - " \"memo\": xxxxx, (string) hexademical string representation of memo field\n" + " \"memo\": xxxxx, (string) hexadecimal string representation of memo field\n" + " \"confirmations\" : n, (numeric) the number of confirmations\n" + " \"jsindex\" (sprout) : n, (numeric) the joinsplit index\n" + " \"jsoutindex\" (sprout) : n, (numeric) the output index of the joinsplit\n" + " \"outindex\" (sapling) : n, (numeric) the output index\n" " \"change\": true|false, (boolean) true if the address that received the note is also one of the sending addresses\n" "}\n" "\nExamples:\n" @@ -3732,12 +3795,30 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp) if (boost::get(&zaddr) != nullptr) { for (CSproutNotePlaintextEntry & entry : sproutEntries) { UniValue obj(UniValue::VOBJ); + int nHeight = 0; + CTransaction tx; + uint256 hashBlock; + + if (GetTransaction(entry.jsop.hash, tx, hashBlock, true)) { + BlockMap::const_iterator it = mapBlockIndex.find(hashBlock); + if (it != mapBlockIndex.end()) { + nHeight = it->second->GetHeight(); + //fprintf(stderr,"blockHash %s height %d\n",hashBlock.ToString().c_str(), nHeight); + } else { + fprintf(stderr,"block hash %s does not exist!\n", hashBlock.ToString().c_str() ); + } + } else { + fprintf(stderr,"tx hash %s does not exist!\n", entry.jsop.hash.ToString().c_str() ); + } + obj.push_back(Pair("txid", entry.jsop.hash.ToString())); obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value())))); std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end()); obj.push_back(Pair("memo", HexStr(data))); obj.push_back(Pair("jsindex", entry.jsop.js)); obj.push_back(Pair("jsoutindex", entry.jsop.n)); + obj.push_back(Pair("rawconfirmations", entry.confirmations)); + obj.push_back(Pair("confirmations", komodo_dpowconfs(nHeight, entry.confirmations))); if (hasSpendingKey) { obj.push_back(Pair("change", pwalletMain->IsNoteSproutChange(nullifierSet, entry.address, entry.jsop))); } @@ -3746,10 +3827,27 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp) } else if (boost::get(&zaddr) != nullptr) { for (SaplingNoteEntry & entry : saplingEntries) { UniValue obj(UniValue::VOBJ); + int nHeight = 0; + CTransaction tx; + uint256 hashBlock; + + if (GetTransaction(entry.op.hash, tx, hashBlock, true)) { + BlockMap::const_iterator it = mapBlockIndex.find(hashBlock); + if (it != mapBlockIndex.end()) { + nHeight = it->second->GetHeight(); + //fprintf(stderr,"blockHash %s height %d\n",hashBlock.ToString().c_str(), nHeight); + } else { + fprintf(stderr,"block hash %s does not exist!\n", hashBlock.ToString().c_str() ); + } + } else { + fprintf(stderr,"tx hash %s does not exist!\n", entry.op.hash.ToString().c_str() ); + } obj.push_back(Pair("txid", entry.op.hash.ToString())); obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.note.value())))); obj.push_back(Pair("memo", HexStr(entry.memo))); obj.push_back(Pair("outindex", (int)entry.op.n)); + obj.push_back(Pair("rawconfirmations", entry.confirmations)); + obj.push_back(Pair("confirmations", komodo_dpowconfs(nHeight, entry.confirmations))); if (hasSpendingKey) { obj.push_back(Pair("change", pwalletMain->IsNoteSaplingChange(nullifierSet, entry.address, entry.op))); } @@ -4115,7 +4213,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) } if ( toSapling && ASSETCHAINS_SYMBOL[0] == 0 ) throw JSONRPCError(RPC_INVALID_PARAMETER,"Sprout usage will expire soon"); - + // If we are sending from a shielded address, all recipient // shielded addresses must be of the same type. if ((fromSprout && toSapling) || (fromSapling && toSprout)) { @@ -4534,14 +4632,14 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) return NullUniValue; - + string enableArg = "zmergetoaddress"; auto fEnableMergeToAddress = fExperimentalMode && GetBoolArg("-" + enableArg, true); std::string strDisabledMsg = ""; if (!fEnableMergeToAddress) { strDisabledMsg = experimentalDisabledHelpMsg("z_mergetoaddress", enableArg); } - + if (fHelp || params.size() < 2 || params.size() > 6) throw runtime_error( "z_mergetoaddress [\"fromaddress\", ... ] \"toaddress\" ( fee ) ( transparent_limit ) ( shielded_limit ) ( memo )\n" @@ -4590,33 +4688,33 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) + HelpExampleCli("z_mergetoaddress", "'[\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"]' ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf") + HelpExampleRpc("z_mergetoaddress", "[\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"], \"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\"") ); - + if (!fEnableMergeToAddress) { throw JSONRPCError(RPC_WALLET_ERROR, "Error: z_mergetoaddress is disabled."); } - + LOCK2(cs_main, pwalletMain->cs_wallet); - + bool useAnyUTXO = false; bool useAnySprout = false; bool useAnySapling = false; std::set taddrs = {}; std::set zaddrs = {}; - + UniValue addresses = params[0].get_array(); if (addresses.size()==0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, fromaddresses array is empty."); - + // Keep track of addresses to spot duplicates std::set setAddress; - + // Sources for (const UniValue& o : addresses.getValues()) { if (!o.isStr()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected string"); - + std::string address = o.get_str(); - + if (address == "ANY_TADDR") { useAnyUTXO = true; } else if (address == "ANY_SPROUT") { @@ -4636,23 +4734,23 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) } } } - + if (setAddress.count(address)) throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ") + address); setAddress.insert(address); } - + if (useAnyUTXO && taddrs.size() > 0) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify specific t-addrs when using \"ANY_TADDR\""); } if ((useAnySprout || useAnySapling) && zaddrs.size() > 0) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify specific z-addrs when using \"ANY_SPROUT\" or \"ANY_SAPLING\""); } - + const int nextBlockHeight = chainActive.Height() + 1; const bool overwinterActive = NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER); const bool saplingActive = NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING); - + // Validate the destination address auto destaddress = params[1].get_str(); bool isToSproutZaddr = false; @@ -4674,7 +4772,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress ); } } - + // Convert fee from currency format to zatoshis CAmount nFee = SHIELD_COINBASE_DEFAULT_MINERS_FEE; if (params.size() > 2) { @@ -4684,7 +4782,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) nFee = AmountFromValue( params[2] ); } } - + int nUTXOLimit = MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT; if (params.size() > 3) { nUTXOLimit = params[3].get_int(); @@ -4692,7 +4790,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of UTXOs cannot be negative"); } } - + int sproutNoteLimit = MERGE_TO_ADDRESS_DEFAULT_SPROUT_LIMIT; int saplingNoteLimit = MERGE_TO_ADDRESS_DEFAULT_SAPLING_LIMIT; if (params.size() > 4) { @@ -4703,7 +4801,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) sproutNoteLimit = nNoteLimit; saplingNoteLimit = nNoteLimit; } - + std::string memo; if (params.size() > 5) { memo = params[5].get_str(); @@ -4716,9 +4814,9 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, size of memo is larger than maximum allowed %d", ZC_MEMO_SIZE )); } } - + MergeToAddressRecipient recipient(destaddress, memo); - + // Prepare to get UTXOs and notes std::vector utxoInputs; std::vector sproutNoteInputs; @@ -4732,7 +4830,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) bool maxedOutUTXOsFlag = false; bool maxedOutNotesFlag = false; size_t mempoolLimit = (nUTXOLimit != 0) ? nUTXOLimit : (overwinterActive ? 0 : (size_t)GetArg("-mempooltxinputlimit", 0)); - + unsigned int max_tx_size = saplingActive ? MAX_TX_SIZE_AFTER_SAPLING : MAX_TX_SIZE_BEFORE_SAPLING; size_t estimatedTxSize = 200; // tx overhead + wiggle room if (isToSproutZaddr) { @@ -4740,20 +4838,20 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) } else if (isToSaplingZaddr) { estimatedTxSize += OUTPUTDESCRIPTION_SIZE; } - + if (useAnyUTXO || taddrs.size() > 0) { // Get available utxos vector vecOutputs; pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, false); - + // Find unspent utxos and update estimated size for (const COutput& out : vecOutputs) { if (!out.fSpendable) { continue; } - + CScript scriptPubKey = out.tx->vout[out.i].scriptPubKey; - + CTxDestination address; if (!ExtractDestination(scriptPubKey, address)) { continue; @@ -4762,10 +4860,10 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) if (taddrs.size() > 0 && !taddrs.count(address)) { continue; } - + utxoCounter++; CAmount nValue = out.tx->vout[out.i].nValue; - + if (!maxedOutUTXOsFlag) { size_t increase = (boost::get(&address) != nullptr) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE; if (estimatedTxSize + increase >= max_tx_size || @@ -4779,19 +4877,19 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) mergedUTXOValue += nValue; } } - + if (maxedOutUTXOsFlag) { remainingUTXOValue += nValue; } } } - + if (useAnySprout || useAnySapling || zaddrs.size() > 0) { // Get available notes - std::vector sproutEntries; - std::vector saplingEntries; - pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs); - + std::vector sproutEntries,skipsprout; + std::vector saplingEntries,skipsapling; + pwalletMain->GetFilteredNotes(sproutEntries, useAnySprout == 0 ? saplingEntries : skipsapling, zaddrs); + // If Sapling is not active, do not allow sending from a sapling addresses. if (!saplingActive && saplingEntries.size() > 0) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated"); @@ -4808,12 +4906,12 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) RPC_INVALID_PARAMETER, "Cannot send between Sprout and Sapling addresses using z_mergetoaddress"); } - + // Find unspent notes and update estimated size for (const CSproutNotePlaintextEntry& entry : sproutEntries) { noteCounter++; CAmount nValue = entry.plaintext.value(); - + if (!maxedOutNotesFlag) { // If we haven't added any notes yet and the merge is to a // z-address, we have already accounted for the first JoinSplit. @@ -4831,12 +4929,12 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) mergedNoteValue += nValue; } } - + if (maxedOutNotesFlag) { remainingNoteValue += nValue; } } - + for (const SaplingNoteEntry& entry : saplingEntries) { noteCounter++; CAmount nValue = entry.note.value(); @@ -4856,20 +4954,20 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) mergedNoteValue += nValue; } } - + if (maxedOutNotesFlag) { remainingNoteValue += nValue; } } } - + size_t numUtxos = utxoInputs.size(); size_t numNotes = sproutNoteInputs.size() + saplingNoteInputs.size(); - + if (numUtxos == 0 && numNotes == 0) { throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Could not find any funds to merge."); } - + // Sanity check: Don't do anything if: // - We only have one from address // - It's equal to toaddress @@ -4877,26 +4975,26 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) if (setAddress.size() == 1 && setAddress.count(destaddress) && (numUtxos + numNotes) == 1) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Destination address is also the only source address, and all its funds are already merged."); } - + CAmount mergedValue = mergedUTXOValue + mergedNoteValue; if (mergedValue < nFee) { throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strprintf("Insufficient funds, have %s, which is less than miners fee %s", FormatMoney(mergedValue), FormatMoney(nFee))); } - + // Check that the user specified fee is sane (if too high, it can result in error -25 absurd fee) CAmount netAmount = mergedValue - nFee; if (nFee > netAmount) { throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the net amount to be shielded %s", FormatMoney(nFee), FormatMoney(netAmount))); } - + // Keep record of parameters in context object UniValue contextInfo(UniValue::VOBJ); contextInfo.push_back(Pair("fromaddresses", params[0])); contextInfo.push_back(Pair("toaddress", params[1])); contextInfo.push_back(Pair("fee", ValueFromAmount(nFee))); - + // Contextual transaction we will build on CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction( Params().GetConsensus(), @@ -4905,7 +5003,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) if (contextualTx.nVersion == 1 && isSproutShielded) { contextualTx.nVersion = 2; // Tx format should support vjoinsplit } - + // Builder (used if Sapling addresses are involved) boost::optional builder; if (isToSaplingZaddr || saplingNoteInputs.size() > 0) { @@ -4917,7 +5015,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) new AsyncRPCOperation_mergetoaddress(builder, contextualTx, utxoInputs, sproutNoteInputs, saplingNoteInputs, recipient, nFee, contextInfo) ); q->addOperation(operation); AsyncRPCOperationId operationId = operation->getId(); - + // Return continuation information UniValue o(UniValue::VOBJ); o.push_back(Pair("remainingUTXOs", static_cast(utxoCounter - numUtxos))); @@ -4995,8 +5093,8 @@ int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33) if (!EnsureWalletIsAvailable(0)) return 0; - const CKeyStore& keystore = *pwalletMain; assert(pwalletMain != NULL); + const CKeyStore& keystore = *pwalletMain; LOCK2(cs_main, pwalletMain->cs_wallet); utxovalue = 0; memset(&utxotxid,0,sizeof(utxotxid)); @@ -5066,247 +5164,6 @@ int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33) return(siglen); } -struct komodo_staking -{ - char address[64]; - uint256 txid; - arith_uint256 hashval; - uint64_t nValue; - uint32_t segid32,txtime; - int32_t vout; - CScript scriptPubKey; -}; - -struct komodo_staking *komodo_addutxo(struct komodo_staking *array,int32_t *numkp,int32_t *maxkp,uint32_t txtime,uint64_t nValue,uint256 txid,int32_t vout,char *address,uint8_t *hashbuf,CScript pk) -{ - uint256 hash; uint32_t segid32; struct komodo_staking *kp; - segid32 = komodo_stakehash(&hash,address,hashbuf,txid,vout); - if ( *numkp >= *maxkp ) - { - *maxkp += 1000; - array = (struct komodo_staking *)realloc(array,sizeof(*array) * (*maxkp)); - //fprintf(stderr,"realloc max.%d array.%p\n",*maxkp,array); - } - kp = &array[(*numkp)++]; - //fprintf(stderr,"kp.%p num.%d\n",kp,*numkp); - memset(kp,0,sizeof(*kp)); - strcpy(kp->address,address); - kp->txid = txid; - kp->vout = vout; - kp->hashval = UintToArith256(hash); - kp->txtime = txtime; - kp->segid32 = segid32; - kp->nValue = nValue; - kp->scriptPubKey = pk; - return(array); -} - -arith_uint256 _komodo_eligible(struct komodo_staking *kp,arith_uint256 ratio,uint32_t blocktime,int32_t iter,int32_t minage,int32_t segid,int32_t nHeight,uint32_t prevtime) -{ - int32_t diff; uint64_t coinage; arith_uint256 coinage256,hashval; - diff = (iter + blocktime - kp->txtime - minage); - if ( diff < 0 ) - diff = 60; - else if ( diff > 3600*24*30 ) - diff = 3600*24*30; - if ( iter > 0 ) - diff += segid*2; - coinage = ((uint64_t)kp->nValue * diff); - if ( blocktime+iter+segid*2 > prevtime+480 ) - coinage *= ((blocktime+iter+segid*2) - (prevtime+400)); - coinage256 = arith_uint256(coinage+1); - hashval = ratio * (kp->hashval / coinage256); - return(hashval); -} - -uint32_t komodo_eligible(arith_uint256 bnTarget,arith_uint256 ratio,struct komodo_staking *kp,int32_t nHeight,uint32_t blocktime,uint32_t prevtime,int32_t minage,uint8_t *hashbuf) -{ - int32_t maxiters = 600; uint256 hash; - int32_t segid,iter,diff; uint64_t coinage; arith_uint256 hashval,coinage256; - komodo_stakehash(&hash,kp->address,hashbuf,kp->txid,kp->vout); - kp->hashval = UintToArith256(hash); - segid = ((nHeight + kp->segid32) & 0x3f); - hashval = _komodo_eligible(kp,ratio,blocktime,maxiters,minage,segid,nHeight,prevtime); - //for (int i=32; i>=0; i--) - // fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]); - //fprintf(stderr," b.%u minage.%d segid.%d ht.%d prev.%u\n",blocktime,minage,segid,nHeight,prevtime); - if ( hashval <= bnTarget ) - { - for (iter=0; itertxtime+minage ) - continue; - hashval = _komodo_eligible(kp,ratio,blocktime,iter,minage,segid,nHeight,prevtime); - if ( hashval <= bnTarget ) - { - //fprintf(stderr,"winner %.8f blocktime.%u iter.%d segid.%d\n",(double)kp->nValue/COIN,blocktime,iter,segid); - blocktime += iter; - blocktime += segid * 2; - return(blocktime); - } - } - } else fprintf(stderr,"maxiters is not good enough\n"); - return(0); -} - -int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig) -{ - static struct komodo_staking *array; static int32_t numkp,maxkp; static uint32_t lasttime; - set setAddress; struct komodo_staking *kp; int32_t winners,segid,minage,nHeight,counter=0,i,m,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; vector vecOutputs; uint32_t block_from_future_rejecttime,besttime,eligible,eligible2,earliest = 0; CScript best_scriptPubKey; arith_uint256 mindiff,ratio,bnTarget; CBlockIndex *tipindex,*pindex; CTxDestination address; bool fNegative,fOverflow; uint8_t hashbuf[256]; CTransaction tx; uint256 hashBlock; - if (!EnsureWalletIsAvailable(0)) - return 0; - - bnTarget.SetCompact(nBits, &fNegative, &fOverflow); - mindiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); - ratio = (mindiff / bnTarget); - assert(pwalletMain != NULL); - LOCK2(cs_main, pwalletMain->cs_wallet); - *utxovaluep = 0; - memset(utxotxidp,0,sizeof(*utxotxidp)); - memset(utxovoutp,0,sizeof(*utxovoutp)); - memset(utxosig,0,72); - pwalletMain->AvailableCoins(vecOutputs, false, NULL, true); - if ( (tipindex= chainActive.Tip()) == 0 ) - return(0); - nHeight = tipindex->GetHeight() + 1; - if ( (minage= nHeight*3) > 6000 ) // about 100 blocks - minage = 6000; - komodo_segids(hashbuf,nHeight-101,100); - if ( *blocktimep < tipindex->nTime+60 ) - *blocktimep = tipindex->nTime+60; - //fprintf(stderr,"Start scan of utxo for staking %u ht.%d\n",(uint32_t)time(NULL),nHeight); - if ( time(NULL) > lasttime+600 || array == 0 ) - { - if ( array != 0 ) - { - free(array); - array = 0; - maxkp = numkp = 0; - lasttime = 0; - } - BOOST_FOREACH(const COutput& out, vecOutputs) - { - if ( (tipindex= chainActive.Tip()) == 0 || tipindex->GetHeight()+1 > nHeight ) - { - fprintf(stderr,"chain tip changed during staking loop t.%u counter.%d\n",(uint32_t)time(NULL),counter); - return(0); - } - counter++; - if ( out.nDepth < nMinDepth || out.nDepth > nMaxDepth ) - { - fprintf(stderr,"komodo_staked invalid depth %d\n",(int32_t)out.nDepth); - continue; - } - CAmount nValue = out.tx->vout[out.i].nValue; - if ( nValue < COIN || !out.fSpendable ) - continue; - const CScript& pk = out.tx->vout[out.i].scriptPubKey; - if ( ExtractDestination(pk,address) != 0 ) - { - if ( IsMine(*pwalletMain,address) == 0 ) - continue; - if ( GetTransaction(out.tx->GetHash(),tx,hashBlock,true) != 0 && (pindex= komodo_getblockindex(hashBlock)) != 0 ) - { - array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,out.tx->GetHash(),out.i,(char *)CBitcoinAddress(address).ToString().c_str(),hashbuf,(CScript)pk); - //fprintf(stderr,"addutxo numkp.%d vs max.%d\n",numkp,maxkp); - } - } - } - lasttime = (uint32_t)time(NULL); -//fprintf(stderr,"finished kp data of utxo for staking %u ht.%d numkp.%d maxkp.%d\n",(uint32_t)time(NULL),nHeight,numkp,maxkp); - } -//fprintf(stderr,"numkp.%d blocktime.%u\n",numkp,*blocktimep); - block_from_future_rejecttime = (uint32_t)GetAdjustedTime() + 57; - for (i=winners=0; iGetHeight()+1 > nHeight ) - { - fprintf(stderr,"chain tip changed during staking loop t.%u counter.%d\n",(uint32_t)time(NULL),counter); - return(0); - } - kp = &array[i]; - if ( (eligible2= komodo_eligible(bnTarget,ratio,kp,nHeight,*blocktimep,(uint32_t)tipindex->nTime+27,minage,hashbuf)) == 0 ) - continue; - eligible = komodo_stake(0,bnTarget,nHeight,kp->txid,kp->vout,0,(uint32_t)tipindex->nTime+27,kp->address); -//fprintf(stderr,"i.%d %u vs %u\n",i,eligible2,eligible); - if ( eligible > 0 ) - { - besttime = m = 0; - if ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+27,kp->address) ) - { - while ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+27,kp->address) ) - { - besttime = eligible; - eligible--; - if ( eligible < block_from_future_rejecttime ) // nothing gained by going earlier - break; - m++; -//fprintf(stderr,"m.%d ht.%d validated winning blocktime %u -> %.8f eligible.%u test prior\n",m,nHeight,*blocktimep,(double)kp->nValue/COIN,eligible); - } - } - else - { - fprintf(stderr,"ht.%d error validating winning blocktime %u -> %.8f eligible.%u test prior\n",nHeight,*blocktimep,(double)kp->nValue/COIN,eligible); - continue; - } - eligible = besttime; - winners++; -//fprintf(stderr,"ht.%d validated winning [%d] -> %.8f eligible.%u test prior\n",nHeight,(int32_t)(eligible - tipindex->nTime),(double)kp->nValue/COIN,eligible); - if ( earliest == 0 || eligible < earliest || (eligible == earliest && (*utxovaluep == 0 || kp->nValue < *utxovaluep)) ) - { - earliest = eligible; - best_scriptPubKey = kp->scriptPubKey; //out.tx->vout[out.i].scriptPubKey; - *utxovaluep = (uint64_t)kp->nValue; - //decode_hex((uint8_t *)utxotxidp,32,(char *)out.tx->GetHash().GetHex().c_str()); - decode_hex((uint8_t *)utxotxidp,32,(char *)kp->txid.GetHex().c_str()); - *utxovoutp = kp->vout; - *txtimep = kp->txtime;//(uint32_t)out.tx->nLockTime; - fprintf(stderr,"ht.%d earliest.%u [%d].%d (%s) nValue %.8f locktime.%u counter.%d winners.%d\n",nHeight,earliest,(int32_t)(earliest - tipindex->nTime),m,kp->address,(double)kp->nValue/COIN,*txtimep,counter,winners); - } - } //else fprintf(stderr,"utxo not eligible\n"); - } - if ( numkp < 10000 && array != 0 ) - { - free(array); - array = 0; - maxkp = numkp = 0; - lasttime = 0; - } - if ( earliest != 0 ) - { - bool signSuccess; SignatureData sigdata; uint64_t txfee; uint8_t *ptr; uint256 revtxid,utxotxid; - auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); - const CKeyStore& keystore = *pwalletMain; - txNew.vin.resize(1); - txNew.vout.resize(1); - txfee = 0; - for (i=0; i<32; i++) - ((uint8_t *)&revtxid)[i] = ((uint8_t *)utxotxidp)[31 - i]; - txNew.vin[0].prevout.hash = revtxid; - txNew.vin[0].prevout.n = *utxovoutp; - txNew.vout[0].scriptPubKey = best_scriptPubKey;// CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG; - txNew.vout[0].nValue = *utxovaluep - txfee; - txNew.nLockTime = earliest; - CTransaction txNewConst(txNew); - signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, *utxovaluep, SIGHASH_ALL), best_scriptPubKey, sigdata, consensusBranchId); - if (!signSuccess) - fprintf(stderr,"failed to create signature\n"); - else - { - UpdateTransaction(txNew,0,sigdata); - ptr = (uint8_t *)&sigdata.scriptSig[0]; - siglen = sigdata.scriptSig.size(); - for (i=0; iVerusStakeTransaction(pBlock, txNew, nBits, hashResult, utxosig, pk); @@ -5314,7 +5171,6 @@ int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits int32_t ensure_CCrequirements() { - extern uint8_t NOTARY_PUBKEY33[]; CCerror = ""; if ( NOTARY_PUBKEY33[0] == 0 ) return(-1); @@ -5337,6 +5193,7 @@ int32_t ensure_CCrequirements() #include "../cc/CCGateways.h" #include "../cc/CCPrices.h" #include "../cc/CCHeir.h" +#include "../cc/CCMarmara.h" UniValue CCaddress(struct CCcontract_info *cp,char *name,std::vector &pubkey) { @@ -5403,8 +5260,6 @@ UniValue setpubkey(const UniValue& params, bool fHelp) char Raddress[18]; uint8_t pubkey33[33]; - extern uint8_t NOTARY_PUBKEY33[]; - extern std::string NOTARY_PUBKEY; if ( NOTARY_PUBKEY33[0] == 0 ) { if (strlen(params[0].get_str().c_str()) == 66) { decode_hex(pubkey33,33,(char *)params[0].get_str().c_str()); @@ -5468,6 +5323,43 @@ UniValue channelsaddress(const UniValue& params, bool fHelp) return(result); } +UniValue cclibaddress(const UniValue& params, bool fHelp) +{ + struct CCcontract_info *cp,C; std::vector pubkey; + cp = CCinit(&C,EVAL_FIRSTUSER); + if ( fHelp || params.size() > 1 ) + throw runtime_error("cclibaddress [pubkey]\n"); + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + if ( params.size() == 1 ) + pubkey = ParseHex(params[0].get_str().c_str()); + return(CCaddress(cp,(char *)"CClib",pubkey)); +} + +UniValue cclibinfo(const UniValue& params, bool fHelp) +{ + struct CCcontract_info *cp,C; + cp = CCinit(&C,EVAL_FIRSTUSER); + if ( fHelp || params.size() > 0 ) + throw runtime_error("cclibinfo\n"); + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + return(CClib_info(cp)); +} + +UniValue cclib(const UniValue& params, bool fHelp) +{ + struct CCcontract_info *cp,C; char *method; cJSON *jsonparams; + cp = CCinit(&C,EVAL_FIRSTUSER); + if ( fHelp || params.size() > 2 ) + throw runtime_error("cclib method [JSON params]\n"); + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + method = (char *)params[0].get_str().c_str(); + jsonparams = cJSON_Parse(params[1].get_str().c_str()); + return(CClib(cp,method,jsonparams)); +} + UniValue oraclesaddress(const UniValue& params, bool fHelp) { struct CCcontract_info *cp,C; std::vector pubkey; @@ -5517,17 +5409,17 @@ UniValue pegsaddress(const UniValue& params, bool fHelp) return(CCaddress(cp,(char *)"Pegs",pubkey)); } -UniValue triggersaddress(const UniValue& params, bool fHelp) +UniValue marmaraaddress(const UniValue& params, bool fHelp) { struct CCcontract_info *cp,C; std::vector pubkey; - cp = CCinit(&C,EVAL_TRIGGERS); + cp = CCinit(&C,EVAL_MARMARA); if ( fHelp || params.size() > 1 ) - throw runtime_error("triggersaddress [pubkey]\n"); + throw runtime_error("Marmaraaddress [pubkey]\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); if ( params.size() == 1 ) pubkey = ParseHex(params[0].get_str().c_str()); - return(CCaddress(cp,(char *)"Triggers",pubkey)); + return(CCaddress(cp,(char *)"Marmara",pubkey)); } UniValue paymentsaddress(const UniValue& params, bool fHelp) @@ -5558,27 +5450,19 @@ UniValue gatewaysaddress(const UniValue& params, bool fHelp) UniValue heiraddress(const UniValue& params, bool fHelp) { - struct CCcontract_info *cp,C; std::vector destPubkey; - - cp = CCinit(&C,EVAL_HEIR); - if ( fHelp || (params.size() != 4 && params.size() != 3)) - throw runtime_error("heiraddress func txid amount [destpubkey]\n"); - if ( ensure_CCrequirements() < 0 ) - throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); - //if ( params.size() == 1 ) - // pubkey = ParseHex(params[0].get_str().c_str()); - - char funcid = ((char *)params[0].get_str().c_str())[0]; - uint256 assetid = Parseuint256((char *)params[1].get_str().c_str()); - int64_t funds = atof(params[2].get_str().c_str()) * COIN ; - if(params.size() == 4) - destPubkey = ParseHex(params[3].get_str().c_str()); - - //return HeirFundBad(funcid, assetid, funds, destPubkey); - - return(CCaddress(cp,(char *)"Heir",destPubkey)); + struct CCcontract_info *cp,C; std::vector pubkey; + cp = CCinit(&C,EVAL_HEIR); + if ( fHelp || params.size() > 1 ) + throw runtime_error("heiraddress [pubkey]\n"); + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + if ( params.size() == 1 ) + pubkey = ParseHex(params[0].get_str().c_str()); + return(CCaddress(cp,(char *)"Heir",pubkey)); } + + UniValue lottoaddress(const UniValue& params, bool fHelp) { struct CCcontract_info *cp,C; std::vector pubkey; @@ -5659,17 +5543,209 @@ UniValue rewardsaddress(const UniValue& params, bool fHelp) return(CCaddress(cp,(char *)"Rewards",pubkey)); } +UniValue assetsaddress(const UniValue& params, bool fHelp) +{ + struct CCcontract_info *cp, C; std::vector pubkey; + cp = CCinit(&C, EVAL_ASSETS); + if (fHelp || params.size() > 1) + throw runtime_error("assetsaddress [pubkey]\n"); + if (ensure_CCrequirements() < 0) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + if (params.size() == 1) + pubkey = ParseHex(params[0].get_str().c_str()); + return(CCaddress(cp, (char *)"Assets", pubkey)); +} + UniValue tokenaddress(const UniValue& params, bool fHelp) { struct CCcontract_info *cp,C; std::vector pubkey; - cp = CCinit(&C,EVAL_ASSETS); + cp = CCinit(&C,EVAL_TOKENS); if ( fHelp || params.size() > 1 ) throw runtime_error("tokenaddress [pubkey]\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); if ( params.size() == 1 ) pubkey = ParseHex(params[0].get_str().c_str()); - return(CCaddress(cp,(char *)"Assets",pubkey)); + return(CCaddress(cp,(char *)"Tokens", pubkey)); +} + +UniValue marmara_poolpayout(const UniValue& params, bool fHelp) +{ + int32_t firstheight; double perc; char *jsonstr; + if ( fHelp || params.size() != 3 ) + { + // marmarapoolpayout 0.5 2 '[["024131032ed90941e714db8e6dd176fe5a86c9d873d279edecf005c06f773da686",1000],["02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92",100]]'; + //marmarapoolpayout 0 2 '[["024131032ed90941e714db8e6dd176fe5a86c9d873d279edecf005c06f773da686",1000]]' + throw runtime_error("marmarapoolpayout perc firstheight \"[[\\\"pubkey\\\":shares], ...]\"\n"); + } + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + perc = atof(params[0].get_str().c_str()) / 100.; + firstheight = atol(params[1].get_str().c_str()); + jsonstr = (char *)params[2].get_str().c_str(); + return(MarmaraPoolPayout(0,firstheight,perc,jsonstr)); // [[pk0, shares0], [pk1, shares1], ...] +} + +UniValue marmara_receive(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); uint256 batontxid; std::vector senderpub; int64_t amount; int32_t matures; std::string currency; + if ( fHelp || (params.size() != 5 && params.size() != 4) ) + { + // automatic flag -> lsb of matures + // 1st marmarareceive 028076d42eb20efc10007fafb5ca66a2052523c0d2221e607adf958d1a332159f6 7.5 MARMARA 1440 + // after marmarareceive 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775 7.5 MARMARA 1168 d72d87aa0d50436de695c93e2bf3d7273c63c92ef6307913aa01a6ee6a16548b + throw runtime_error("marmarareceive senderpk amount currency matures batontxid\n"); + } + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + memset(&batontxid,0,sizeof(batontxid)); + senderpub = ParseHex(params[0].get_str().c_str()); + if (senderpub.size()!= 33) + { + ERR_RESULT("invalid sender pubkey"); + return result; + } + amount = atof(params[1].get_str().c_str()) * COIN + 0.00000000499999; + currency = params[2].get_str(); + if ( params.size() == 5 ) + { + matures = atol(params[3].get_str().c_str()); + batontxid = Parseuint256((char *)params[4].get_str().c_str()); + } else matures = atol(params[3].get_str().c_str()) + chainActive.LastTip()->GetHeight() + 1; + return(MarmaraReceive(0,pubkey2pk(senderpub),amount,currency,matures,batontxid,true)); +} + +UniValue marmara_issue(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); uint256 approvaltxid; std::vector receiverpub; int64_t amount; int32_t matures; std::string currency; + if ( fHelp || params.size() != 5 ) + { + // marmaraissue 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775 7.5 MARMARA 1168 32da4cb3e886ee42de90b4a15042d71169077306badf909099c5c5c692df3f27 + // marmaraissue 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775 700 MARMARA 2629 11fe8bf1de80c2ef69124d08907f259aef7f41e3a632ca2d48ad072a8c8f3078 -> 335df3a5dd6b92a3d020c9465d4d76e0d8242126106b83756dcecbad9813fdf3 + + throw runtime_error("marmaraissue receiverpk amount currency matures approvaltxid\n"); + } + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + receiverpub = ParseHex(params[0].get_str().c_str()); + if (receiverpub.size()!= 33) + { + ERR_RESULT("invalid receiverpub pubkey"); + return result; + } + amount = atof(params[1].get_str().c_str()) * COIN + 0.00000000499999; + currency = params[2].get_str(); + matures = atol(params[3].get_str().c_str()); + approvaltxid = Parseuint256((char *)params[4].get_str().c_str()); + return(MarmaraIssue(0,'I',pubkey2pk(receiverpub),amount,currency,matures,approvaltxid,zeroid)); +} + +UniValue marmara_transfer(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); uint256 approvaltxid,batontxid; std::vector receiverpub; int64_t amount; int32_t matures; std::string currency; std::vector creditloop; + if ( fHelp || params.size() != 5 ) + { + // marmaratransfer 028076d42eb20efc10007fafb5ca66a2052523c0d2221e607adf958d1a332159f6 7.5 MARMARA 1168 1506c774e4b2804a6e25260920840f4cfca8d1fb400e69fe6b74b8e593dbedc5 + throw runtime_error("marmaratransfer receiverpk amount currency matures approvaltxid\n"); + } + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + receiverpub = ParseHex(params[0].get_str().c_str()); + if (receiverpub.size()!= 33) + { + ERR_RESULT("invalid receiverpub pubkey"); + return result; + } + amount = atof(params[1].get_str().c_str()) * COIN + 0.00000000499999; + currency = params[2].get_str(); + matures = atol(params[3].get_str().c_str()); + approvaltxid = Parseuint256((char *)params[4].get_str().c_str()); + if ( MarmaraGetbatontxid(creditloop,batontxid,approvaltxid) < 0 ) + throw runtime_error("couldnt find batontxid\n"); + return(MarmaraIssue(0,'T',pubkey2pk(receiverpub),amount,currency,matures,approvaltxid,batontxid)); +} + +UniValue marmara_info(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); CPubKey issuerpk; std::vector issuerpub; int64_t minamount,maxamount; int32_t firstheight,lastheight; std::string currency; + if ( fHelp || params.size() < 4 || params.size() > 6 ) + { + throw runtime_error("marmarainfo firstheight lastheight minamount maxamount [currency issuerpk]\n"); + } + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + firstheight = atol(params[0].get_str().c_str()); + lastheight = atol(params[1].get_str().c_str()); + minamount = atof(params[2].get_str().c_str()) * COIN + 0.00000000499999; + maxamount = atof(params[3].get_str().c_str()) * COIN + 0.00000000499999; + if ( params.size() >= 5 ) + currency = params[4].get_str(); + if ( params.size() == 6 ) + { + issuerpub = ParseHex(params[5].get_str().c_str()); + if ( issuerpub.size()!= 33 ) + { + ERR_RESULT("invalid issuer pubkey"); + return result; + } + issuerpk = pubkey2pk(issuerpub); + } + result = MarmaraInfo(issuerpk,firstheight,lastheight,minamount,maxamount,currency); + return(result); +} + +UniValue marmara_creditloop(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); uint256 txid; + if ( fHelp || params.size() != 1 ) + { + // marmaracreditloop 010ff7f9256cefe3b5dee3d72c0eeae9fc6f34884e6f32ffe5b60916df54a9be + throw runtime_error("marmaracreditloop txid\n"); + } + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + txid = Parseuint256((char *)params[0].get_str().c_str()); + result = MarmaraCreditloop(txid); + return(result); +} + +UniValue marmara_settlement(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); uint256 batontxid; + if ( fHelp || params.size() != 1 ) + { + // marmarasettlement 010ff7f9256cefe3b5dee3d72c0eeae9fc6f34884e6f32ffe5b60916df54a9be + // marmarasettlement ff3e259869196f3da9b5ea3f9e088a76c4fc063cf36ab586b652e121d441a603 + throw runtime_error("marmarasettlement batontxid\n"); + } + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + batontxid = Parseuint256((char *)params[0].get_str().c_str()); + result = MarmaraSettlement(0,batontxid); + return(result); +} + +UniValue marmara_lock(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); int64_t amount; int32_t height; + if ( fHelp || params.size() > 2 || params.size() == 0 ) + { + throw runtime_error("marmaralock amount unlockht\n"); + } + amount = atof(params[0].get_str().c_str()) * COIN + 0.00000000499999; + if ( params.size() == 2 ) + height = atol(params[1].get_str().c_str()); + else height = chainActive.LastTip()->GetHeight() + 1; + return(MarmaraLock(0,amount,height)); +} + +UniValue channelslist(const UniValue& params, bool fHelp) +{ + if ( fHelp || params.size() > 0 ) + throw runtime_error("channelsinfo\n"); + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + return(ChannelsList()); } UniValue channelsinfo(const UniValue& params, bool fHelp) @@ -5688,8 +5764,10 @@ UniValue channelsinfo(const UniValue& params, bool fHelp) UniValue channelsopen(const UniValue& params, bool fHelp) { UniValue result(UniValue::VOBJ); int32_t numpayments; int64_t payment; std::vector destpub; struct CCcontract_info *cp,C; std::string hex; + uint256 tokenid=zeroid; + cp = CCinit(&C,EVAL_CHANNELS); - if ( fHelp || params.size() != 3 ) + if ( fHelp || params.size() < 3 || params.size() > 4) throw runtime_error("channelsopen destpubkey numpayments payment\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); @@ -5713,7 +5791,11 @@ UniValue channelsopen(const UniValue& params, bool fHelp) ERR_RESULT("invalid payment amount, must be greater than 0"); return result; } - hex = ChannelOpen(0,pubkey2pk(destpub),numpayments,payment); + if (params.size()==4) + { + tokenid=Parseuint256((char *)params[3].get_str().c_str()); + } + hex = ChannelOpen(0,pubkey2pk(destpub),numpayments,payment,tokenid); if ( hex.size() > 0 ) { result.push_back(Pair("result", "success")); @@ -5726,7 +5808,7 @@ UniValue channelspayment(const UniValue& params, bool fHelp) { UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C; std::string hex; uint256 opentxid,secret=zeroid; int32_t n; int64_t amount; cp = CCinit(&C,EVAL_CHANNELS); - if ( fHelp || params.size() != 2 ) + if ( fHelp || params.size() < 2 || params.size() >3 ) throw runtime_error("channelspayment opentxid amount [secret]\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); @@ -6018,7 +6100,7 @@ UniValue gatewaysbind(const UniValue& params, bool fHelp) if ( params.size() < 6+i+1 ) throw runtime_error("not enough parameters for N pubkeys\n"); pubkey = ParseHex(params[6+i].get_str().c_str()); - if (pubkey.size()!= 33) + if (pubkey.size()!= 33) throw runtime_error("invalid destination pubkey"); pubkeys.push_back(pubkey2pk(pubkey)); } @@ -6052,8 +6134,8 @@ UniValue gatewaysdeposit(const UniValue& params, bool fHelp) amount = atof((char *)params[8].get_str().c_str()) * COIN + 0.00000000499999; if ( amount <= 0 || claimvout < 0 ) throw runtime_error("invalid param: amount, numpks or claimvout\n"); - if (destpub.size()!= 33) - throw runtime_error("invalid destination pubkey"); + if (destpub.size()!= 33) + throw runtime_error("invalid destination pubkey"); hex = GatewaysDeposit(0,bindtxid,height,coin,cointxid,claimvout,deposithex,proof,pubkey2pk(destpub),amount); RETURN_IF_ERROR(CCerror); @@ -6078,9 +6160,9 @@ UniValue gatewaysclaim(const UniValue& params, bool fHelp) coin = params[1].get_str(); deposittxid = Parseuint256((char *)params[2].get_str().c_str()); destpub = ParseHex(params[3].get_str()); - amount = atof((char *)params[4].get_str().c_str()) * COIN + 0.00000000499999; - if (destpub.size()!= 33) - throw runtime_error("invalid destination pubkey"); + amount = atof((char *)params[4].get_str().c_str()) * COIN + 0.00000000499999; + if (destpub.size()!= 33) + throw runtime_error("invalid destination pubkey"); hex = GatewaysClaim(0,bindtxid,coin,deposittxid,pubkey2pk(destpub),amount); RETURN_IF_ERROR(CCerror); if ( hex.size() > 0 ) @@ -6103,9 +6185,9 @@ UniValue gatewayswithdraw(const UniValue& params, bool fHelp) bindtxid = Parseuint256((char *)params[0].get_str().c_str()); coin = params[1].get_str(); withdrawpub = ParseHex(params[2].get_str()); - amount = atof((char *)params[3].get_str().c_str()) * COIN + 0.00000000499999; - if (withdrawpub.size()!= 33) - throw runtime_error("invalid destination pubkey"); + amount = atof((char *)params[3].get_str().c_str()) * COIN + 0.00000000499999; + if (withdrawpub.size()!= 33) + throw runtime_error("invalid destination pubkey"); hex = GatewaysWithdraw(0,bindtxid,coin,pubkey2pk(withdrawpub),amount); RETURN_IF_ERROR(CCerror); if ( hex.size() > 0 ) @@ -6124,7 +6206,7 @@ UniValue gatewayspartialsign(const UniValue& params, bool fHelp) if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); const CKeyStore& keystore = *pwalletMain; - LOCK2(cs_main, pwalletMain->cs_wallet); + LOCK2(cs_main, pwalletMain->cs_wallet); txid = Parseuint256((char *)params[0].get_str().c_str()); coin = params[1].get_str(); parthex = params[2].get_str(); @@ -6169,7 +6251,7 @@ UniValue gatewaysmarkdone(const UniValue& params, bool fHelp) const CKeyStore& keystore = *pwalletMain; LOCK2(cs_main, pwalletMain->cs_wallet); completetxid = Parseuint256((char *)params[0].get_str().c_str()); - coin = params[1].get_str(); + coin = params[1].get_str(); hex = GatewaysMarkDone(0,completetxid,coin); RETURN_IF_ERROR(CCerror); if ( hex.size() > 0 ) @@ -6306,9 +6388,7 @@ UniValue oraclesdata(const UniValue& params, bool fHelp) txid = Parseuint256((char *)params[0].get_str().c_str()); data = ParseHex(params[1].get_str().c_str()); hex = OracleData(0,txid,data); - RETURN_IF_ERROR(CCerror); - if ( hex.size() > 0 ) { result.push_back(Pair("result", "success")); @@ -6344,24 +6424,6 @@ UniValue oraclescreate(const UniValue& params, bool fHelp) ERR_RESULT("oracles format must be <= 4096 characters"); return(result); } - // list of oracle valid formats from oracles.cpp -> oracle_format - const UniValue valid_formats[13] = {"s","S","d","D","c","C","t","T","i","I","l","L","h"}; - const UniValue header_type = "Ihh"; - // checking if oracle data type is valid - bool is_valid_format = false; - for ( int i = 0; i < 13; ++i ) { - if ( valid_formats[i].get_str() == format ) { - is_valid_format = true; - } - } - // additional check for special Ihh data type - if ( format == header_type.get_str() ) { - is_valid_format = true; - } - if ( !is_valid_format ) { - ERR_RESULT("oracles format not valid"); - return(result); - } hex = OracleCreate(0,name,description,format); RETURN_IF_ERROR(CCerror); if ( hex.size() > 0 ) @@ -6815,7 +6877,7 @@ UniValue tokenlist(const UniValue& params, bool fHelp) throw runtime_error("tokenlist\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); - return(AssetList()); + return(TokenList()); } UniValue tokeninfo(const UniValue& params, bool fHelp) @@ -6826,7 +6888,7 @@ UniValue tokeninfo(const UniValue& params, bool fHelp) if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); tokenid = Parseuint256((char *)params[0].get_str().c_str()); - return(AssetInfo(tokenid)); + return(TokenInfo(tokenid)); } UniValue tokenorders(const UniValue& params, bool fHelp) @@ -6836,31 +6898,51 @@ UniValue tokenorders(const UniValue& params, bool fHelp) throw runtime_error("tokenorders [tokenid]\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); - if ( params.size() == 1 ) - tokenid = Parseuint256((char *)params[0].get_str().c_str()); - else memset(&tokenid,0,sizeof(tokenid)); + if (params.size() == 1) { + tokenid = Parseuint256((char *)params[0].get_str().c_str()); + if (tokenid == zeroid) + throw runtime_error("incorrect tokenid\n"); + } + else + memset(&tokenid,0,sizeof(tokenid)); return(AssetOrders(tokenid)); } UniValue tokenbalance(const UniValue& params, bool fHelp) { - UniValue result(UniValue::VOBJ); char destaddr[64]; uint256 tokenid; uint64_t balance; std::vector pubkey; struct CCcontract_info *cp,C; - cp = CCinit(&C,EVAL_ASSETS); + UniValue result(UniValue::VOBJ); uint256 tokenid; uint64_t balance; std::vector pubkey; struct CCcontract_info *cp,C; + CCerror.clear(); + if ( fHelp || params.size() > 2 ) throw runtime_error("tokenbalance tokenid [pubkey]\n"); if ( ensure_CCrequirements() < 0 ) throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); - LOCK(cs_main); + + LOCK(cs_main); + tokenid = Parseuint256((char *)params[0].get_str().c_str()); if ( params.size() == 2 ) pubkey = ParseHex(params[1].get_str().c_str()); - else pubkey = Mypubkey(); - result.push_back(Pair("result", "success")); - if ( GetCCaddress(cp,destaddr,pubkey2pk(pubkey)) != 0 ) - result.push_back(Pair("CCaddress",destaddr)); - balance = GetAssetBalance(pubkey2pk(pubkey),tokenid); - result.push_back(Pair("tokenid", params[0].get_str())); - result.push_back(Pair("balance", (int64_t)balance)); + else + pubkey = Mypubkey(); + + balance = GetTokenBalance(pubkey2pk(pubkey),tokenid); + + if (CCerror.empty()) { + char destaddr[64]; + + result.push_back(Pair("result", "success")); + cp = CCinit(&C,EVAL_TOKENS); + if (GetCCaddress(cp, destaddr, pubkey2pk(pubkey)) != 0) + result.push_back(Pair("CCaddress", destaddr)); + + result.push_back(Pair("tokenid", params[0].get_str())); + result.push_back(Pair("balance", (int64_t)balance)); + } + else { + ERR_RESULT(CCerror); + } + return(result); } @@ -6894,7 +6976,7 @@ UniValue tokencreate(const UniValue& params, bool fHelp) return(result); } } - hex = CreateAsset(0,supply,name,description); + hex = CreateToken(0,supply,name,description); if ( hex.size() > 0 ) { result.push_back(Pair("result", "success")); @@ -6926,7 +7008,7 @@ UniValue tokentransfer(const UniValue& params, bool fHelp) ERR_RESULT("amount must be positive"); return(result); } - hex = AssetTransfer(0,tokenid,pubkey,amount); + hex = TokenTransfer(0,tokenid,pubkey,amount); if (amount > 0) { if ( hex.size() > 0 ) { @@ -6963,7 +7045,11 @@ UniValue tokenconvert(const UniValue& params, bool fHelp) ERR_RESULT("amount must be positive"); return(result); } - hex = AssetConvert(0,tokenid,pubkey,amount,evalcode); + + ERR_RESULT("deprecated"); + return(result); + +/* hex = AssetConvert(0,tokenid,pubkey,amount,evalcode); if (amount > 0) { if ( hex.size() > 0 ) { @@ -6973,7 +7059,7 @@ UniValue tokenconvert(const UniValue& params, bool fHelp) } else { ERR_RESULT("amount must be positive"); } - return(result); + return(result); */ } UniValue tokenbid(const UniValue& params, bool fHelp) @@ -7173,7 +7259,7 @@ UniValue tokenfillask(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); tokenid = Parseuint256((char *)params[0].get_str().c_str()); asktxid = Parseuint256((char *)params[1].get_str().c_str()); - //fillunits = atol(params[2].get_str().c_str()); + //fillunits = atol(params[2].get_str().c_str()); fillunits = atoll(params[2].get_str().c_str()); // dimxy changed to prevent loss of significance if ( fillunits <= 0 ) { @@ -7193,7 +7279,7 @@ UniValue tokenfillask(const UniValue& params, bool fHelp) result.push_back(Pair("result", "success")); result.push_back(Pair("hex", hex)); } else { - ERR_RESULT("couldnt fill bid"); + ERR_RESULT("couldnt fill ask"); } } else { ERR_RESULT("fillunits must be positive"); @@ -7270,6 +7356,155 @@ UniValue getbalance64(const UniValue& params, bool fHelp) return ret; } + +// heir contract functions for coins and tokens +UniValue heirfund(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); + uint256 tokenid = zeroid; + int64_t txfee; + int64_t amount; + int64_t inactivitytime; + std::string hex; + std::vector pubkey; + std::string name; + + if (!EnsureWalletIsAvailable(fHelp)) + return NullUniValue; + + if (fHelp || params.size() != 5 && params.size() != 6) + throw runtime_error("heirfund txfee funds heirname heirpubkey inactivitytime [tokenid]\n"); + if (ensure_CCrequirements() < 0) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); + + txfee = atoll(params[0].get_str().c_str()); + if (txfee < 0) + throw runtime_error("incorrect txfee param\n"); + + if(params.size() == 6) // tokens in satoshis: + amount = atoll(params[1].get_str().c_str()); + else // coins: + amount = atof(params[1].get_str().c_str()) * COIN; + + if( amount <= 0 ) + throw runtime_error("incorrect amount\n"); + + name = params[2].get_str(); + pubkey = ParseHex(params[3].get_str().c_str()); + if( !pubkey2pk(pubkey).IsValid() ) + throw runtime_error("incorrect pubkey\n"); + + inactivitytime = atoll(params[4].get_str().c_str()); + if (inactivitytime <= 0) + throw runtime_error("incorrect inactivity time param\n"); + + if (params.size() == 6) { + tokenid = Parseuint256((char*)params[5].get_str().c_str()); + if(tokenid == zeroid) + throw runtime_error("incorrect tokenid\n"); + } + + if( tokenid == zeroid ) + result = HeirFundCoinCaller(txfee, amount, name, pubkey2pk(pubkey), inactivitytime, zeroid); + else + result = HeirFundTokenCaller(txfee, amount, name, pubkey2pk(pubkey), inactivitytime, tokenid); + + return result; +} + +UniValue heiradd(const UniValue& params, bool fHelp) +{ + UniValue result; + uint256 fundingtxid; + int64_t txfee; + int64_t amount; + int64_t inactivitytime; + std::string hex; + std::vector pubkey; + std::string name; + + if (!EnsureWalletIsAvailable(fHelp)) + return NullUniValue; + + if (fHelp || params.size() != 3) + throw runtime_error("heiradd txfee funds fundingtxid\n"); + if (ensure_CCrequirements() < 0) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); + + txfee = atoll(params[0].get_str().c_str()); + if (txfee < 0) + throw runtime_error("incorrect txfee param\n"); + + fundingtxid = Parseuint256((char*)params[2].get_str().c_str()); + + result = HeirAddCaller(fundingtxid, txfee, params[1].get_str()); + return result; +} + +UniValue heirclaim(const UniValue& params, bool fHelp) +{ + UniValue result; // result(UniValue::VOBJ); + uint256 fundingtxid; + int64_t txfee; + int64_t inactivitytime; + std::string hex; + std::vector pubkey; + std::string name; + + // do we need this? + if (!EnsureWalletIsAvailable(fHelp)) + return NullUniValue; + + if (fHelp || params.size() != 3) + throw runtime_error("heirclaim txfee funds fundingtxid\n"); + if (ensure_CCrequirements() < 0) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + + const CKeyStore& keystore = *pwalletMain; + LOCK2(cs_main, pwalletMain->cs_wallet); + + txfee = atoll(params[0].get_str().c_str()); + if (txfee < 0) + throw runtime_error("incorrect txfee param\n"); + + fundingtxid = Parseuint256((char*)params[2].get_str().c_str()); + + result = HeirClaimCaller(fundingtxid, txfee, params[1].get_str()); + return result; +} + +UniValue heirinfo(const UniValue& params, bool fHelp) +{ + uint256 fundingtxid; + if (fHelp || params.size() != 1) // or 0? + throw runtime_error("heirinfo fundingtxid\n"); + // if ( ensure_CCrequirements() < 0 ) + // throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + + fundingtxid = Parseuint256((char*)params[0].get_str().c_str()); + return (HeirInfo(fundingtxid)); +} + +UniValue heirlist(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 0) // or 0? + throw runtime_error("heirlist\n"); + + // if ( ensure_CCrequirements() < 0 ) + // throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + + return (HeirList()); +} + + + + extern UniValue dumpprivkey(const UniValue& params, bool fHelp); // in rpcdump.cpp extern UniValue importprivkey(const UniValue& params, bool fHelp); extern UniValue importaddress(const UniValue& params, bool fHelp); @@ -7362,3 +7597,79 @@ void RegisterWalletRPCCommands(CRPCTable &tableRPC) for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); } + +UniValue test_ac(const UniValue& params, bool fHelp) +{ + // make fake token tx: + struct CCcontract_info *cp, C; + + if (fHelp || (params.size() != 4)) + throw runtime_error("incorrect params\n"); + if (ensure_CCrequirements() < 0) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + + std::vector pubkey1; + std::vector pubkey2; + + pubkey1 = ParseHex(params[0].get_str().c_str()); + pubkey2 = ParseHex(params[1].get_str().c_str()); + + CPubKey pk1 = pubkey2pk(pubkey1); + CPubKey pk2 = pubkey2pk(pubkey2); + + if(!pk1.IsValid() || !pk2.IsValid()) + throw runtime_error("invalid pubkey\n"); + + int64_t txfee = 10000; + int64_t amount = atoll(params[2].get_str().c_str()) * COIN; + uint256 fundingtxid = Parseuint256((char *)params[3].get_str().c_str()); + + CPubKey myPubkey = pubkey2pk(Mypubkey()); + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + + int64_t normalInputs = AddNormalinputs(mtx, myPubkey, txfee + amount, 60); + + if( normalInputs < txfee + amount) + throw runtime_error("not enough normals\n"); + + mtx.vout.push_back(MakeCC1of2vout(EVAL_HEIR, amount, pk1, pk2)); + + CScript opret; + fundingtxid = revuint256(fundingtxid); + + opret << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'A' << fundingtxid << (uint8_t)0); + + cp = CCinit(&C, EVAL_HEIR); + return(FinalizeCCTx(0, cp, mtx, myPubkey, txfee, opret)); +} + +UniValue test_heirmarker(const UniValue& params, bool fHelp) +{ + // make fake token tx: + struct CCcontract_info *cp, C; + + if (fHelp || (params.size() != 1)) + throw runtime_error("incorrect params\n"); + if (ensure_CCrequirements() < 0) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + + uint256 fundingtxid = Parseuint256((char *)params[0].get_str().c_str()); + + CPubKey myPubkey = pubkey2pk(Mypubkey()); + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + + int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60); + if (normalInputs < 10000) + throw runtime_error("not enough normals\n"); + + mtx.vin.push_back(CTxIn(fundingtxid, 1)); + mtx.vout.push_back(MakeCC1vout(EVAL_HEIR, 10000, myPubkey)); + + CScript opret; + fundingtxid = revuint256(fundingtxid); + + opret << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'C' << fundingtxid << (uint8_t)0); + + cp = CCinit(&C, EVAL_HEIR); + return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, opret)); +} \ No newline at end of file diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h index a5de7e2de..7739e94a2 100644 --- a/src/wallet/rpcwallet.h +++ b/src/wallet/rpcwallet.h @@ -2,6 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_WALLET_RPCWALLET_H #define BITCOIN_WALLET_RPCWALLET_H diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 3857f7090..d171812c4 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "wallet/wallet.h" #include "checkpoints.h" @@ -44,13 +59,7 @@ bool fSendFreeTransactions = false; bool fPayAtLeastCustomFee = true; #include "komodo_defs.h" -extern int32_t USE_EXTERNAL_PUBKEY; -extern std::string NOTARY_PUBKEY; -extern int32_t KOMODO_EXCHANGEWALLET; -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -extern int32_t VERUS_MIN_STAKEAGE; CBlockIndex *komodo_chainactive(int32_t height); -extern std::string DONATION_PUBKEY; /** * Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) @@ -1165,10 +1174,11 @@ bool DecrementNoteWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t n assert((nWitnessCacheSize - 1) >= nd->witnesses.size()); } } - assert(KOMODO_REWIND != 0 || nWitnessCacheSize > 0); + assert(KOMODO_REWIND != 0 || nWitnessCacheSize > 0 || WITNESS_CACHE_SIZE != _COINBASE_MATURITY+10); return true; } + void CWallet::DecrementNoteWitnesses(const CBlockIndex* pindex) { LOCK(cs_wallet); @@ -1178,10 +1188,17 @@ void CWallet::DecrementNoteWitnesses(const CBlockIndex* pindex) if (!::DecrementNoteWitnesses(wtxItem.second.mapSaplingNoteData, pindex->GetHeight(), nWitnessCacheSize)) needsRescan = true; } - nWitnessCacheSize -= 1; - // TODO: If nWitnessCache is zero, we need to regenerate the caches (#1302) - assert(nWitnessCacheSize > 0); - + if ( WITNESS_CACHE_SIZE == _COINBASE_MATURITY+10 ) + { + nWitnessCacheSize -= 1; + // TODO: If nWitnessCache is zero, we need to regenerate the caches (#1302) + assert(nWitnessCacheSize > 0); + } + else + { + if ( nWitnessCacheSize > 0 ) + nWitnessCacheSize--; + } // For performance reasons, we write out the witness cache in // CWallet::SetBestChain() (which also ensures that overall consistency // of the wallet.dat is maintained). diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index c5cfedda8..c8f9bcbb6 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_WALLET_WALLET_H #define BITCOIN_WALLET_WALLET_H @@ -60,8 +75,8 @@ static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000; //! Size of witness cache // Should be large enough that we can expect not to reorg beyond our cache // unless there is some exceptional network disruption. -#define _COINBASE_MATURITY 100 -static const unsigned int WITNESS_CACHE_SIZE = _COINBASE_MATURITY+10; +extern unsigned int WITNESS_CACHE_SIZE; + //! Size of HD seed in bytes static const size_t HD_WALLET_SEED_LENGTH = 32; diff --git a/src/wallet/wallet_ismine.cpp b/src/wallet/wallet_ismine.cpp index 3d8ccd0a8..692d0280d 100644 --- a/src/wallet/wallet_ismine.cpp +++ b/src/wallet/wallet_ismine.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "wallet_ismine.h" #include "key.h" diff --git a/src/wallet/wallet_ismine.h b/src/wallet/wallet_ismine.h index 2f0e1080d..409def1ef 100644 --- a/src/wallet/wallet_ismine.h +++ b/src/wallet/wallet_ismine.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_WALLET_WALLET_ISMINE_H #define BITCOIN_WALLET_WALLET_ISMINE_H diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 41c0de4b2..aae406de3 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #include "wallet/walletdb.h" #include "consensus/validation.h" @@ -24,6 +39,7 @@ using namespace std; static uint64_t nAccountingEntryNumber = 0; +static list deadTxns; // // CWalletDB @@ -469,8 +485,11 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, CValidationState state; auto verifier = libzcash::ProofVerifier::Strict(); if (!(CheckTransaction(0,wtx, state, verifier) && (wtx.GetHash() == hash) && state.IsValid())) + { + fprintf(stderr, "Removing corrupt tx from wallet.%s\n", hash.ToString().c_str()); + deadTxns.push_back(hash); return false; - + } // Undo serialize changes in 31600 if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703) { @@ -918,9 +937,6 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) { // Leave other errors alone, if we try to fix them we might make things worse. fNoncriticalErrors = true; // ... but do warn the user there is something wrong. - if (strType == "tx") - // Rescan if there is a bad transaction record: - SoftSetBoolArg("-rescan", true); } } if (!strErr.empty()) @@ -935,6 +951,24 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) result = DB_CORRUPT; } + if (!deadTxns.empty()) + { + int32_t reAdded = 0; + BOOST_FOREACH (uint256& hash, deadTxns) { + if (!EraseTx(hash)) + fprintf(stderr, "could not delete tx.%s\n",hash.ToString().c_str()); + uint256 blockhash; CTransaction tx; + if (GetTransaction(hash,tx,blockhash,true)) + { + CWalletTx wtx(pwallet,tx); + pwallet->AddToWallet(wtx, true, NULL); + reAdded++; + } + } + fprintf(stderr, "Cleared %lu corrupted transactions from wallet. Readded %i known transactions.\n",deadTxns.size(),reAdded); + deadTxns.clear(); + } + if (fNoncriticalErrors && result == DB_LOAD_OK) result = DB_NONCRITICAL_ERROR; diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index b3210bbc0..2c57ec1e8 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -3,6 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + #ifndef BITCOIN_WALLET_WALLETDB_H #define BITCOIN_WALLET_WALLETDB_H diff --git a/src/zcbenchmarks.cpp b/src/zcbenchmarks.cpp index 34e1a2b7d..6b8a910c1 100644 --- a/src/zcbenchmarks.cpp +++ b/src/zcbenchmarks.cpp @@ -63,8 +63,8 @@ void post_wallet_load(){ #ifdef ENABLE_MINING // Generate coins in the background if (pwalletMain || !GetArg("-mineraddress", "").empty()) - GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain, GetArg("-genproclimit", 0)); -#endif + GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain, GetArg("-genproclimit", 1)); +#endif } diff --git a/zcutil/build-mac.sh b/zcutil/build-mac.sh index 138508cb5..a3619111f 100755 --- a/zcutil/build-mac.sh +++ b/zcutil/build-mac.sh @@ -42,6 +42,21 @@ PREFIX="$(pwd)/depends/$TRIPLET" make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 +#BUILD CCLIB + +WD=$PWD +cd src/cc +echo $PWD + +if make "$@"; then + echo CCLIB BUILD SUCCESSFUL +else + echo CCLIB BUILD FAILED + exit 1 +fi + +cd $WD + ./autogen.sh CPPFLAGS="-I$PREFIX/include -arch x86_64" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ CXXFLAGS='-arch x86_64 -I/usr/local/Cellar/gcc\@6/6.4.0_2/include/c++/6.4.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Werror -g -Wl,-undefined -Wl,dynamic_lookup' \ diff --git a/zcutil/build.sh b/zcutil/build.sh index 08517475c..68239e16e 100755 --- a/zcutil/build.sh +++ b/zcutil/build.sh @@ -101,6 +101,21 @@ eval "$MAKE" --version as --version ld -v +#BUILD CCLIB + +WD=$PWD +cd src/cc +echo $PWD + +if make "$@"; then + echo CCLIB BUILD SUCCESSFUL +else + echo CCLIB BUILD FAILED + exit 1 +fi + +cd $WD + HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ V=1 ./autogen.sh