91
.travis.yml
91
.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"
|
||||
|
||||
344
COPYING
344
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.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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.
|
||||
|
||||
<signature of Ty Coon>, 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.
|
||||
|
||||
|
||||
@@ -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=
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
2
src/ac/ksb
Executable file
2
src/ac/ksb
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
./komodo-cli -ac_name=KSB $1 $2 $3 $4 $5 $6
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
15
src/alert.h
15
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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
15
src/amount.h
15
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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -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 &
|
||||
|
||||
@@ -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 <boost/uuid/uuid.hpp>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<size_t> workerCounter(0);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 <hash.h>
|
||||
|
||||
15
src/base58.h
15
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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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"
|
||||
|
||||
15
src/bloom.h
15
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
|
||||
|
||||
|
||||
15
src/cJSON.c
15
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. */
|
||||
|
||||
|
||||
15
src/cJSON.h
15
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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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
|
||||
|
||||
46
src/cc/CCMarmara.h
Normal file
46
src/cc/CCMarmara.h
Normal file
@@ -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<uint256> &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
|
||||
@@ -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 *
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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
|
||||
@@ -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<uint8_t> origpubkey,std::string name,std::string description);
|
||||
CScript EncodeAssetOpRet(uint8_t funcid,uint256 assetid,uint256 assetid2,int64_t price,std::vector<uint8_t> origpubkey);
|
||||
bool DecodeAssetCreateOpRet(const CScript &scriptPubKey,std::vector<uint8_t> &origpubkey,std::string &name,std::string &description);
|
||||
uint8_t DecodeAssetOpRet(const CScript &scriptPubKey,uint256 &assetid,uint256 &assetid2,int64_t &price,std::vector<uint8_t> &origpubkey);
|
||||
//CScript EncodeAssetCreateOpRet(uint8_t funcid,std::vector<uint8_t> origpubkey,std::string name,std::string description);
|
||||
//CScript EncodeAssetOpRet(uint8_t assetFuncId, uint256 tokenid, uint256 assetid2, int64_t price, std::vector<uint8_t> origpubkey);
|
||||
//bool DecodeAssetCreateOpRet(const CScript &scriptPubKey,std::vector<uint8_t> &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<uint8_t> &origpubkey);
|
||||
bool SetAssetOrigpubkey(std::vector<uint8_t> &origpubkey,int64_t &price,const CTransaction &tx);
|
||||
int64_t IsAssetvout(int32_t maxAssetExactAmountDepth, struct CCcontract_info *cp, Eval* eval, int64_t &price,std::vector<uint8_t> &origpubkey,const CTransaction& tx,int32_t v,uint256 refassetid);
|
||||
int64_t IsAssetvout(struct CCcontract_info *cp, int64_t &price, std::vector<uint8_t> &origpubkey, const CTransaction& tx, int32_t v, uint256 refassetid);
|
||||
bool ValidateBidRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice);
|
||||
bool ValidateAskRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice);
|
||||
bool ValidateSwapRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice);
|
||||
@@ -44,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<uint8_t> &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 refassetid);
|
||||
int64_t AssetValidateSellvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpprice,std::vector<uint8_t> &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 assetid);
|
||||
bool AssetExactAmounts(int32_t maxDepth, struct CCcontract_info *cp,int64_t &inputs,int32_t starti,int64_t &outputs,Eval* eval,const CTransaction &tx,uint256 assetid);
|
||||
//bool AssetExactAmounts(bool doValidateTx, struct CCcontract_info *cp, int64_t &inputs, int32_t starti, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 assetid, std::vector<CTransaction> &ccVinsTxs);
|
||||
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<uint8_t> destpubkey,int64_t total);
|
||||
std::string AssetConvert(int64_t txfee,uint256 assetid,std::vector<uint8_t> 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<uint8_t> destpubkey,int64_t total);
|
||||
//std::string AssetConvert(int64_t txfee,uint256 assetid,std::vector<uint8_t> 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);
|
||||
|
||||
@@ -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<uint8_t> 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<uint8_t> origpubkey)
|
||||
CScript EncodeAssetOpRet(uint8_t assetFuncId, uint256 assetid2, int64_t price, std::vector<uint8_t> 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<uint8_t> &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<uint8_t> &origpubkey, std::string &name, std::string &description)
|
||||
{
|
||||
std::vector<uint8_t> vopret; uint8_t evalcode,funcid,*script;
|
||||
GetOpReturnData(scriptPubKey, vopret);
|
||||
@@ -272,173 +277,187 @@ bool DecodeAssetCreateOpRet(const CScript &scriptPubKey,std::vector<uint8_t> &or
|
||||
return(true);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
} */
|
||||
|
||||
uint8_t DecodeAssetOpRet(const CScript &scriptPubKey,uint256 &assetid,uint256 &assetid2,int64_t &price,std::vector<uint8_t> &origpubkey)
|
||||
uint8_t DecodeAssetTokenOpRet(const CScript &scriptPubKey, uint8_t &evalCodeInOpret, uint256 &tokenid, uint256 &assetid2, int64_t &price, std::vector<uint8_t> &origpubkey)
|
||||
{
|
||||
std::vector<uint8_t> vopret; uint8_t funcid=0,*script,e,f;
|
||||
GetOpReturnData(scriptPubKey, vopret);
|
||||
std::vector<uint8_t> vopretExtra, vopretStripped;
|
||||
uint8_t *script, funcId = 0, assetFuncId = 0, dummyEvalCode, dummyAssetFuncId;
|
||||
uint256 dummyTokenid;
|
||||
std::vector<CPubKey> 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<uint8_t> &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<uint8_t> origpubkey; CScript script;
|
||||
uint256 assetid,assetid2; int64_t price,nValue=0; int32_t n; uint8_t funcid;
|
||||
std::vector<uint8_t> 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<uint8_t> &origpubkey,const CTransaction& tx,int32_t v,uint256 refassetid)
|
||||
{
|
||||
uint256 assetid,assetid2; int64_t nValue=0; int32_t n; uint8_t funcid;
|
||||
|
||||
if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) // maybe check address too?
|
||||
{
|
||||
|
||||
if (maxAssetExactAmountDepth > 0) {
|
||||
//validate all tx
|
||||
int64_t myCCVinsAmount = 0, myCCVoutsAmount = 0;
|
||||
std::vector<CTransaction> ccVinsTxs;
|
||||
|
||||
//std::cerr << "IsAssetvout() validate=yes" << std::endl;
|
||||
const bool validateVinTxs = false;
|
||||
bool isEqualAmounts = AssetExactAmounts(maxAssetExactAmountDepth, cp, myCCVinsAmount, 0, myCCVoutsAmount, eval, tx, refassetid);
|
||||
|
||||
// if ccInputs != ccOutputs and it is not the tokenbase tx means it is possibly fake tx (dimxy):
|
||||
if (!isEqualAmounts && refassetid != tx.GetHash()) { // checking that this is the true tokenbase tx, by verifying that funcid=c, is done further in this function (dimxy)
|
||||
std::cerr << "IsAssetvout() detected bad tx=" << tx.GetHash().GetHex() << ": cc inputs != cc outputs and not the 'tokenbase' tx" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
n = tx.vout.size();
|
||||
if (v >= n - 1) { // just moved this up (dimxy)
|
||||
std::cerr << "isAssetVout() internal err: (v >= n - 1), returning 0" << std::endl;
|
||||
return(0);
|
||||
}
|
||||
nValue = tx.vout[v].nValue;
|
||||
|
||||
// fprintf(stderr,"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<uint8_t> 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<uint8_t> 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<uint8_t> &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<uint8_t> &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<uint8_t> &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<uint8_t> &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<uint8_t> 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; i<numvins; i++)
|
||||
{
|
||||
if ( (*cp->ismyvin)(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<uint8_t> tmporigpubkey; int64_t tmpprice;
|
||||
int32_t numvins = tx.vin.size();
|
||||
int32_t numvouts = tx.vout.size();
|
||||
inputs = outputs = 0;
|
||||
|
||||
for (i=0; i<numvouts; i++)
|
||||
{ // 'false' means 'dont go deep' -- dimxy
|
||||
if ( (assetoshis= IsAssetvout(maxDepth, cp, eval, tmpprice,tmporigpubkey,tx,i,assetid)) != 0 )
|
||||
{
|
||||
fprintf(stderr,"AssetExactAmounts() vout%d assetoshis=%llu, ",i,(long long)assetoshis);
|
||||
outputs += assetoshis;
|
||||
}
|
||||
// Note: account it only if this is 'transfer' tx -- dimxy
|
||||
else if ( flag != 0 && tx.vout[i].scriptPubKey.IsPayToCryptoCondition() != 0 )
|
||||
{
|
||||
assetoshis = tx.vout[i].nValue;
|
||||
fprintf(stderr,"AssetExactAmounts() vout%d assetoshis=%llu special case, ",i,(long long)assetoshis);
|
||||
outputs += assetoshis;
|
||||
}
|
||||
}
|
||||
struct CCcontract_info *cpTokens, C;
|
||||
|
||||
//std::cerr << "AssetExactAmounts() inputs=" << inputs << " outputs=" << outputs << " for txid=" << tx.GetHash().GetHex() << std::endl;
|
||||
cpTokens = CCinit(&C, EVAL_TOKENS);
|
||||
|
||||
if ( inputs != outputs )
|
||||
{
|
||||
std::cerr << "AssetExactAmounts() incorrect inputs=" << (double)inputs / COIN << " vs outputs=" << (double)outputs/COIN << " for txid=" << tx.GetHash().GetHex() << std::endl;
|
||||
return(false);
|
||||
}
|
||||
else return(true);
|
||||
for (int32_t i = 0; i<numvins; i++)
|
||||
{ // only tokens are relevant!!
|
||||
if (/*(*cpAssets->ismyvin)(tx.vin[i].scriptSig)*/ (*cpTokens->ismyvin)(tx.vin[i].scriptSig) ) // || IsVinAllowed(tx.vin[i].scriptSig) != 0)
|
||||
{
|
||||
//std::cerr << indentStr << "AssetExactAmounts() 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 << "AssetCalcAmounts() cannot read vintx for i." << i << " numvins." << numvins << std::endl;
|
||||
return (!eval) ? false : eval->Invalid("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<uint8_t> vopretExtra;
|
||||
std::vector<CPubKey> 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<CTransaction> ccVinsTxs;
|
||||
|
||||
return AssetExactAmounts(true, cp, inputs, starti, outputs, eval, tx, assetid);
|
||||
}*/
|
||||
@@ -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<std::pair<CAddressUnspentKey, CAddressUnspentValue> > 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<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
{
|
||||
txid = it->first.txhash;
|
||||
vout = (int32_t)it->first.index;
|
||||
if ( it->second.satoshis < threshold )
|
||||
|
||||
if (it->second.satoshis < threshold)
|
||||
continue;
|
||||
|
||||
for (j=0; j<mtx.vin.size(); j++)
|
||||
if ( txid == mtx.vin[j].prevout.hash && vout == mtx.vin[j].prevout.n )
|
||||
if (txid == mtx.vin[j].prevout.hash && vout == mtx.vin[j].prevout.n)
|
||||
break;
|
||||
if ( j != mtx.vin.size() )
|
||||
|
||||
if( j != mtx.vin.size() )
|
||||
continue;
|
||||
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
|
||||
|
||||
if( GetTransaction(txid,vintx,hashBlock,false) != 0 )
|
||||
{
|
||||
Getscriptaddress(destaddr,vintx.vout[vout].scriptPubKey);
|
||||
if ( strcmp(destaddr,coinaddr) != 0 && strcmp(destaddr,cp->unspendableCCaddr) != 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<uint8_t> 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<std::pair<CAddressIndexKey, CAmount> > addressIndex; struct CCcontract_info *cp,C; uint256 txid,hashBlock; CTransaction vintx; std::vector<uint8_t> origpubkey; std::string name,description; char str[65];
|
||||
cp = CCinit(&C,EVAL_ASSETS);
|
||||
SetCCtxids(addressIndex,cp->normaladdr);
|
||||
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::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<uint8_t> origpubkey; CTransaction vintx; UniValue result(UniValue::VARR); std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > 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<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
{
|
||||
UniValue result(UniValue::VARR);
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > 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<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it)
|
||||
{
|
||||
uint256 txid, hashBlock, assetid, assetid2;
|
||||
int64_t price;
|
||||
std::vector<uint8_t> 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<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator itTokens = unspentOutputsTokens.begin();
|
||||
itTokens != unspentOutputsTokens.end();
|
||||
itTokens++)
|
||||
addOrders(cpTokens, itTokens);
|
||||
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::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<uint8_t> destpubkey,int64_t total)
|
||||
} */
|
||||
|
||||
// not used (use TokenTransfer instead)
|
||||
/* std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector<uint8_t> 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<uint8_t> des
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 )
|
||||
{
|
||||
/*n = outputs.size();
|
||||
if ( n == amounts.size() )
|
||||
{
|
||||
for (i=0; i<n; i++)
|
||||
total += amounts[i];*/
|
||||
//n = outputs.size();
|
||||
//if ( n == amounts.size() )
|
||||
//{
|
||||
// for (i=0; i<n; i++)
|
||||
// total += amounts[i];
|
||||
mask = ~((1LL << mtx.vin.size()) - 1);
|
||||
if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,total,60)) > 0 )
|
||||
{
|
||||
@@ -254,9 +253,10 @@ std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector<uint8_t> 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<uint8_t> destpubkey,int64_t total,int32_t evalcode)
|
||||
// deprecated
|
||||
/* std::string AssetConvert(int64_t txfee,uint256 assetid,std::vector<uint8_t> 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<uint8_t> 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<uint8_t> origpubkey; std::string name,description;
|
||||
if ( bidamount < 0 || pricetotal < 0 )
|
||||
CPubKey mypk;
|
||||
struct CCcontract_info *cpAssets, C;
|
||||
uint256 hashBlock;
|
||||
CTransaction vintx;
|
||||
std::vector<uint8_t> 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<CPubKey> 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<CPubKey> 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<CPubKey> 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<uint8_t> 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<CPubKey> 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<uint8_t> 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<CPubKey> 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<uint8_t> origpubkey; int32_t bidvout=0; uint64_t mask; int64_t origprice,bidamount,paid_amount,remaining_required,inputs,CCchange=0; struct CCcontract_info *cp,C;
|
||||
if ( fillamount < 0 )
|
||||
CTransaction vintx;
|
||||
uint256 hashBlock;
|
||||
CPubKey mypk;
|
||||
std::vector<uint8_t> origpubkey;
|
||||
int32_t bidvout=0;
|
||||
uint64_t mask;
|
||||
int64_t origprice, bidamount, paid_amount, remaining_required, inputs, CCchange=0;
|
||||
struct CCcontract_info *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<CPubKey> 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<uint8_t> origpubkey; double dprice; uint64_t mask; int32_t askvout=0; int64_t received_assetoshis,total_nValue,orig_assetoshis,paid_nValue,remaining_nValue,inputs,CCchange=0; struct CCcontract_info *cp,C;
|
||||
if ( fillunits < 0 )
|
||||
CTransaction vintx,filltx;
|
||||
uint256 hashBlock;
|
||||
CPubKey mypk;
|
||||
std::vector<uint8_t> 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<CPubKey> 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());
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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<std::pair<CAddressUnspentKey,CAddressUnspentValue> > &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::vector<struct oracle_merklepair>publishers);
|
||||
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<uint8_t> &origpubkey,std::string &name,std::string &description);
|
||||
uint8_t DecodeAssetOpRet(const CScript &scriptPubKey,uint256 &assetid,uint256 &assetid2,int64_t &price,std::vector<uint8_t> &origpubkey);
|
||||
CScript EncodeAssetOpRet(uint8_t assetFuncId, uint256 assetid2, int64_t price, std::vector<uint8_t> origpubkey);
|
||||
//bool DecodeAssetCreateOpRet(const CScript &scriptPubKey, std::vector<uint8_t> &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<uint8_t> &origpubkey);
|
||||
|
||||
CScript EncodeTokenOpRet(uint256 tokenid, std::vector<CPubKey> voutPubkeys, CScript payload);
|
||||
CScript EncodeTokenOpRet(uint8_t tokenFuncId, uint8_t evalCodeInOpret, uint256 tokenid, std::vector<CPubKey> voutPubkeys, CScript payload);
|
||||
uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey, std::vector<uint8_t> &origpubkey, std::string &name, std::string &description);
|
||||
uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCode, uint256 &tokenid, std::vector<CPubKey> &voutPubkeys, std::vector<uint8_t> &vopretExtra);
|
||||
|
||||
uint8_t DecodeOraclesData(const CScript &scriptPubKey,uint256 &oracletxid,uint256 &batontxid,CPubKey &pk,std::vector <uint8_t>&data);
|
||||
int32_t oracle_format(uint256 *hashp,int64_t *valp,char *str,uint8_t fmt,uint8_t *data,int32_t offset,int32_t datalen);
|
||||
CScript EncodeAssetOpRet(uint8_t funcid,uint256 assetid,uint256 assetid2,int64_t price,std::vector<uint8_t> 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<uint8_t> 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<CPubKey> NULL_pubkeys;
|
||||
std::string FinalizeCCTx(uint64_t skipmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret,std::vector<CPubKey> pubkeys = NULL_pubkeys);
|
||||
void SetCCunspents(std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs,char *coinaddr);
|
||||
void SetCCtxids(std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex,char *coinaddr);
|
||||
int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs);
|
||||
@@ -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
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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 *
|
||||
|
||||
768
src/cc/CCtokens.cpp
Normal file
768
src/cc/CCtokens.cpp
Normal file
@@ -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<uint8_t> 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<CPubKey> 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<uint8_t> 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<CPubKey> voutPubkeys, CScript payload)
|
||||
{
|
||||
return EncodeTokenOpRet(tokenid, voutPubkeys, payload);
|
||||
}
|
||||
|
||||
uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey,std::vector<uint8_t> &origpubkey,std::string &name,std::string &description)
|
||||
{
|
||||
std::vector<uint8_t> 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<CPubKey> &voutPubkeys, std::vector<uint8_t> &vopretExtra)
|
||||
{
|
||||
std::vector<uint8_t> 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<uint8_t>(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<uint8_t> vopretExtra, tmporigpubkey, ignorepubkey;
|
||||
uint8_t funcid, evalCodeInOpret;
|
||||
char destaddr[64], origaddr[64], CCaddr[64];
|
||||
std::vector<CPubKey> 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' <tokenname> <description>
|
||||
//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 <other evalcode> 't' tokenid <other contract payload>
|
||||
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<CPubKey> &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<CPubKey> &voutPubkeys, std::vector<uint8_t> &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<CPubKey> voutPubkeys;
|
||||
std::vector<uint8_t> 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<CPubKey> vinPubkeys;
|
||||
ExtractTokensVinPubkeys(tx, vinPubkeys);
|
||||
|
||||
for(std::vector<CPubKey>::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; i<numvins; i++)
|
||||
{ // check for additional contracts which may send tokens to the Tokens contract
|
||||
if ((*cpTokens->ismyvin)(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; i<numvouts; i++)
|
||||
{
|
||||
tokenValIndentSize++;
|
||||
// Note: we pass in here 'false' because we don't need to call TokenExactAmounts() recursively from IsTokensvout
|
||||
// indeed, in this case we'll be checking this tx again
|
||||
//std::cerr << indentStr << "TokenExactAmounts() check vout i=" << i << " nValue=" << tx.vout[i].nValue << std::endl;
|
||||
tokenoshis = IsTokensvout(false, true /*<--exclude non-tokens vouts*/, cpTokens, eval, tx, i, tokenid);
|
||||
tokenValIndentSize--;
|
||||
|
||||
if (tokenoshis != 0)
|
||||
{
|
||||
std::cerr << indentStr << "TokensExactAmounts() vout i=" << i << " tokenoshis=" << tokenoshis << std::endl;
|
||||
outputs += tokenoshis;
|
||||
}
|
||||
}
|
||||
|
||||
//std::cerr << indentStr << "TokensExactAmounts() inputs=" << inputs << " outputs=" << outputs << " for txid=" << tx.GetHash().GetHex() << std::endl;
|
||||
|
||||
if (inputs != outputs) {
|
||||
if (tx.GetHash() != tokenid)
|
||||
std::cerr << indentStr << "TokenExactAmounts() found unequal token cc inputs=" << inputs << " vs cc outputs=" << outputs << " for txid=" << tx.GetHash().GetHex() << " and this is not the create tx" << std::endl;
|
||||
return false; // do not call eval->Invalid() 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<uint8_t> vopretExtra;
|
||||
CTransaction vintx;
|
||||
int32_t j, vout, n = 0;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > 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<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++)
|
||||
{
|
||||
txid = it->first.txhash;
|
||||
vout = (int32_t)it->first.index;
|
||||
if (it->second.satoshis < threshold)
|
||||
continue;
|
||||
for (j = 0; j<mtx.vin.size(); j++)
|
||||
if (txid == mtx.vin[j].prevout.hash && vout == mtx.vin[j].prevout.n)
|
||||
break;
|
||||
if (j != mtx.vin.size())
|
||||
continue;
|
||||
|
||||
if (GetTransaction(txid, vintx, hashBlock, false) != 0)
|
||||
{
|
||||
Getscriptaddress(destaddr, vintx.vout[vout].scriptPubKey);
|
||||
if (strcmp(destaddr, tokenaddr) != 0 && strcmp(destaddr, cp->unspendableCCaddr) != 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<CPubKey> 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<uint8_t> 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<uint8_t> 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<n; i++)
|
||||
// total += amounts[i];
|
||||
mask = ~((1LL << mtx.vin.size()) - 1);
|
||||
if ((inputs = AddTokenCCInputs(cp, mtx, mypk, assetid, total, 60)) > 0)
|
||||
{
|
||||
|
||||
if (inputs < total) { //added dimxy
|
||||
std::cerr << "AssetTransfer(): insufficient funds" << std::endl;
|
||||
return ("");
|
||||
}
|
||||
if (inputs > total)
|
||||
CCchange = (inputs - total);
|
||||
//for (i=0; i<n; i++)
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, total, pubkey2pk(destpubkey))); // TODO: or MakeTokensCC1vout??
|
||||
if (CCchange != 0)
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, CCchange, mypk));
|
||||
|
||||
std::vector<CPubKey> 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<uint8_t> 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<std::pair<CAddressIndexKey, CAmount> > addressIndex;
|
||||
struct CCcontract_info *cp, C; uint256 txid, hashBlock;
|
||||
CTransaction vintx; std::vector<uint8_t> origpubkey;
|
||||
std::string name, description; char str[65];
|
||||
|
||||
cp = CCinit(&C, EVAL_TOKENS);
|
||||
SetCCtxids(addressIndex, cp->normaladdr);
|
||||
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::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);
|
||||
}
|
||||
44
src/cc/CCtokens.h
Normal file
44
src/cc/CCtokens.h
Normal file
@@ -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<uint8_t> &origpubkey, const CTransaction& tx, int32_t v, uint256 reftokenid, std::vector<CPubKey> 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<uint8_t> 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<uint8_t> &origpubkey,std::string &name,std::string &description);
|
||||
|
||||
|
||||
#endif
|
||||
175
src/cc/CCtx.cpp
175
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<CPubKey> 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<CPubKey> 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<n; i++)
|
||||
{
|
||||
@@ -52,17 +59,37 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
|
||||
normaloutputs += mtx.vout[i].nValue;
|
||||
totaloutputs += mtx.vout[i].nValue;
|
||||
}
|
||||
if ( (n= mtx.vin.size()) > 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<n; i++)
|
||||
@@ -127,41 +154,96 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
|
||||
else
|
||||
{
|
||||
Getscriptaddress(destaddr,vintx.vout[utxovout].scriptPubKey);
|
||||
//fprintf(stderr,"vin.%d is CC %.8f -> (%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<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
@@ -263,7 +382,7 @@ int64_t CCfullsupply(uint256 tokenid)
|
||||
uint256 hashBlock; int32_t numvouts; CTransaction tx; std::vector<uint8_t> 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<uint8_t> origpubkey;
|
||||
int64_t price,sum = 0; int32_t numvouts; CTransaction tx; uint256 assetid,assetid2,txid,hashBlock;
|
||||
std::vector<uint8_t> vopretExtra;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
uint8_t evalCode;
|
||||
|
||||
SetCCunspents(unspentOutputs,coinaddr);
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::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<CPubKey> 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<COutput> 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));
|
||||
|
||||
@@ -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<CC*> pks;
|
||||
pks.push_back(CCNewSecp256k1(pk1));
|
||||
pks.push_back(CCNewSecp256k1(pk2));
|
||||
|
||||
std::vector<CC*> 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<CC*> pks;
|
||||
pks.push_back(CCNewSecp256k1(pk));
|
||||
|
||||
std::vector<CC*> 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<uint8_t> paramsNull,const CTransaction &ctx, unsigned int nIn)
|
||||
void CCclearvars(struct CCcontract_info *cp)
|
||||
{
|
||||
CTransaction createTx; uint256 assetid,assetid2,hashBlock; uint8_t funcid; int32_t height,i,n,from_mempool = 0; int64_t amount; std::vector<uint8_t> origpubkey;
|
||||
height = KOMODO_CONNECTING;
|
||||
if ( KOMODO_CONNECTING < 0 ) // always comes back with > 0 for final confirmation
|
||||
return(true);
|
||||
if ( ASSETCHAINS_CC == 0 || (height & ~(1<<30)) < KOMODO_CCACTIVATE )
|
||||
return eval->Invalid("CC are disabled or not active yet");
|
||||
if ( (KOMODO_CONNECTING & (1<<30)) != 0 )
|
||||
{
|
||||
from_mempool = 1;
|
||||
height &= ((1<<30) - 1);
|
||||
}
|
||||
//fprintf(stderr,"KOMODO_CONNECTING.%d mempool.%d vs CCactive.%d\n",height,from_mempool,KOMODO_CCACTIVATE);
|
||||
// there is a chance CC tx is valid in mempool, but invalid when in block, so we cant filter duplicate requests. if any of the vins are spent, for example
|
||||
//txid = ctx.GetHash();
|
||||
//if ( txid == cp->prevtxid )
|
||||
// return(true);
|
||||
//fprintf(stderr,"process CC %02x\n",cp->evalcode);
|
||||
cp->evalcode2 = cp->evalcode3 = 0;
|
||||
cp->unspendableaddr2[0] = cp->unspendableaddr3[0] = 0;
|
||||
if ( paramsNull.size() != 0 ) // Don't expect params
|
||||
return eval->Invalid("Cannot have params");
|
||||
//else if ( ctx.vout.size() == 0 ) // spend can go to z-addresses
|
||||
// return eval->Invalid("no-vouts");
|
||||
else if ( (*cp->validate)(cp,eval,ctx,nIn) != 0 )
|
||||
{
|
||||
//fprintf(stderr,"done CC %02x\n",cp->evalcode);
|
||||
//cp->prevtxid = txid;
|
||||
return(true);
|
||||
}
|
||||
//fprintf(stderr,"invalid CC %02x\n",cp->evalcode);
|
||||
return(false);
|
||||
}
|
||||
|
||||
int64_t CCduration(int32_t &numblocks,uint256 txid)
|
||||
@@ -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<uint8_t> paramsNull,const CTransaction &ctx, unsigned int nIn)
|
||||
{
|
||||
CTransaction createTx; uint256 assetid,assetid2,hashBlock; uint8_t funcid; int32_t height,i,n,from_mempool = 0; int64_t amount; std::vector<uint8_t> origpubkey;
|
||||
height = KOMODO_CONNECTING;
|
||||
if ( KOMODO_CONNECTING < 0 ) // always comes back with > 0 for final confirmation
|
||||
return(true);
|
||||
if ( ASSETCHAINS_CC == 0 || (height & ~(1<<30)) < KOMODO_CCACTIVATE )
|
||||
return eval->Invalid("CC are disabled or not active yet");
|
||||
if ( (KOMODO_CONNECTING & (1<<30)) != 0 )
|
||||
{
|
||||
from_mempool = 1;
|
||||
height &= ((1<<30) - 1);
|
||||
}
|
||||
//fprintf(stderr,"KOMODO_CONNECTING.%d mempool.%d vs CCactive.%d\n",height,from_mempool,KOMODO_CCACTIVATE);
|
||||
// there is a chance CC tx is valid in mempool, but invalid when in block, so we cant filter duplicate requests. if any of the vins are spent, for example
|
||||
//txid = ctx.GetHash();
|
||||
//if ( txid == cp->prevtxid )
|
||||
// return(true);
|
||||
//fprintf(stderr,"process CC %02x\n",cp->evalcode);
|
||||
CCclearvars(cp);
|
||||
if ( paramsNull.size() != 0 ) // Don't expect params
|
||||
return eval->Invalid("Cannot have params");
|
||||
//else if ( ctx.vout.size() == 0 ) // spend can go to z-addresses
|
||||
// return eval->Invalid("no-vouts");
|
||||
else if ( (*cp->validate)(cp,eval,ctx,nIn) != 0 )
|
||||
{
|
||||
//fprintf(stderr,"done CC %02x\n",cp->evalcode);
|
||||
//cp->prevtxid = txid;
|
||||
return(true);
|
||||
}
|
||||
//fprintf(stderr,"invalid CC %02x\n",cp->evalcode);
|
||||
return(false);
|
||||
}
|
||||
|
||||
extern struct CCcontract_info CCinfos[0x100];
|
||||
extern std::string MYCCLIBNAME;
|
||||
bool CClib_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx,unsigned int nIn);
|
||||
|
||||
bool CClib_Dispatch(const CC *cond,Eval *eval,std::vector<uint8_t> paramsNull,const CTransaction &txTo,unsigned int nIn)
|
||||
{
|
||||
uint8_t evalcode; int32_t height,from_mempool; struct CCcontract_info *cp;
|
||||
if ( ASSETCHAINS_CCLIB != MYCCLIBNAME )
|
||||
{
|
||||
fprintf(stderr,"-ac_cclib=%s vs myname %s\n",ASSETCHAINS_CCLIB.c_str(),MYCCLIBNAME.c_str());
|
||||
return eval->Invalid("-ac_cclib name mismatches myname");
|
||||
}
|
||||
height = KOMODO_CONNECTING;
|
||||
if ( KOMODO_CONNECTING < 0 ) // always comes back with > 0 for final confirmation
|
||||
return(true);
|
||||
if ( ASSETCHAINS_CC == 0 || (height & ~(1<<30)) < KOMODO_CCACTIVATE )
|
||||
return eval->Invalid("CC are disabled or not active yet");
|
||||
if ( (KOMODO_CONNECTING & (1<<30)) != 0 )
|
||||
{
|
||||
from_mempool = 1;
|
||||
height &= ((1<<30) - 1);
|
||||
}
|
||||
evalcode = cond->code[0];
|
||||
if ( evalcode >= EVAL_FIRSTUSER && evalcode <= EVAL_LASTUSER )
|
||||
{
|
||||
cp = &CCinfos[(int32_t)evalcode];
|
||||
if ( cp->didinit == 0 )
|
||||
{
|
||||
if ( CClib_initcp(cp,evalcode) == 0 )
|
||||
cp->didinit = 1;
|
||||
else return eval->Invalid("unsupported CClib evalcode");
|
||||
}
|
||||
CCclearvars(cp);
|
||||
if ( paramsNull.size() != 0 ) // Don't expect params
|
||||
return eval->Invalid("Cannot have params");
|
||||
else if ( CClib_validate(cp,height,eval,txTo,nIn) != 0 )
|
||||
return(true);
|
||||
return(false); //eval->Invalid("error in CClib_validate");
|
||||
}
|
||||
return eval->Invalid("cclib CC must have evalcode between 16 and 127");
|
||||
}
|
||||
|
||||
34
src/cc/Makefile
Normal file
34
src/cc/Makefile
Normal file
@@ -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)
|
||||
7
src/cc/README.md
Normal file
7
src/cc/README.md
Normal file
@@ -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
|
||||
```
|
||||
@@ -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] "<assetname>" "<description>"
|
||||
|
||||
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<uint8_t> 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<uint8_t> 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'] [{"<assetname>":"<description>"}]
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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 *
|
||||
|
||||
317
src/cc/cclib.cpp
Normal file
317
src/cc/cclib.cpp
Normal file
@@ -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 <assert.h>
|
||||
#include <cryptoconditions.h>
|
||||
|
||||
#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 *)"<no args>", 0, 0, 'G' },
|
||||
};
|
||||
|
||||
std::string MYCCLIBNAME = (char *)"faucet2";
|
||||
|
||||
char *CClib_name() { return((char *)MYCCLIBNAME.c_str()); }
|
||||
|
||||
std::string CClib_rawtxgen(struct CCcontract_info *cp,uint8_t funcid,cJSON *params);
|
||||
|
||||
UniValue CClib_info(struct CCcontract_info *cp)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ),a(UniValue::VARR); int32_t i; char str[2];
|
||||
result.push_back(Pair("result","success"));
|
||||
result.push_back(Pair("CClib",CClib_name()));
|
||||
for (i=0; i<sizeof(CClib_methods)/sizeof(*CClib_methods); i++)
|
||||
{
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
if ( CClib_methods[i].funcid < ' ' || CClib_methods[i].funcid >= 128 )
|
||||
obj.push_back(Pair("funcid",CClib_methods[i].funcid));
|
||||
else
|
||||
{
|
||||
str[0] = CClib_methods[i].funcid;
|
||||
str[1] = 0;
|
||||
obj.push_back(Pair("funcid",str));
|
||||
}
|
||||
obj.push_back(Pair("name",CClib_methods[i].method));
|
||||
obj.push_back(Pair("help",CClib_methods[i].help));
|
||||
obj.push_back(Pair("params_required",CClib_methods[i].numrequiredargs));
|
||||
obj.push_back(Pair("params_max",CClib_methods[i].maxargs));
|
||||
a.push_back(obj);
|
||||
}
|
||||
result.push_back(Pair("methods",a));
|
||||
return(result);
|
||||
}
|
||||
|
||||
UniValue CClib(struct CCcontract_info *cp,char *method,cJSON *params)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ); int32_t i; std::string rawtx;
|
||||
for (i=0; i<sizeof(CClib_methods)/sizeof(*CClib_methods); i++)
|
||||
{
|
||||
if ( strcmp(method,CClib_methods[i].method) == 0 )
|
||||
{
|
||||
result.push_back(Pair("result","success"));
|
||||
result.push_back(Pair("method",CClib_methods[i].method));
|
||||
rawtx = CClib_rawtxgen(cp,CClib_methods[i].funcid,params);
|
||||
result.push_back(Pair("rawtx",rawtx));
|
||||
return(result);
|
||||
}
|
||||
}
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("method",CClib_methods[i].method));
|
||||
result.push_back(Pair("error","method not found"));
|
||||
return(result);
|
||||
}
|
||||
|
||||
int64_t IsCClibvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v)
|
||||
{
|
||||
char destaddr[64];
|
||||
if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 )
|
||||
{
|
||||
if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 )
|
||||
return(tx.vout[v].nValue);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
bool CClibExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee)
|
||||
{
|
||||
static uint256 zerohash;
|
||||
CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis;
|
||||
numvins = tx.vin.size();
|
||||
numvouts = tx.vout.size();
|
||||
for (i=0; i<numvins; i++)
|
||||
{
|
||||
//fprintf(stderr,"vini.%d\n",i);
|
||||
if ( (*cp->ismyvin)(tx.vin[i].scriptSig) != 0 )
|
||||
{
|
||||
//fprintf(stderr,"vini.%d check mempool\n",i);
|
||||
if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 )
|
||||
return eval->Invalid("cant find vinTx");
|
||||
else
|
||||
{
|
||||
//fprintf(stderr,"vini.%d check hash and vout\n",i);
|
||||
if ( hashBlock == zerohash )
|
||||
return eval->Invalid("cant faucet2 from mempool");
|
||||
if ( (assetoshis= IsCClibvout(cp,vinTx,tx.vin[i].prevout.n)) != 0 )
|
||||
inputs += assetoshis;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i=0; i<numvouts; i++)
|
||||
{
|
||||
//fprintf(stderr,"i.%d of numvouts.%d\n",i,numvouts);
|
||||
if ( (assetoshis= IsCClibvout(cp,tx,i)) != 0 )
|
||||
outputs += assetoshis;
|
||||
}
|
||||
if ( inputs != outputs+FAUCET2SIZE+txfee )
|
||||
{
|
||||
fprintf(stderr,"inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs);
|
||||
return eval->Invalid("mismatched inputs != outputs + FAUCET2SIZE + txfee");
|
||||
}
|
||||
else return(true);
|
||||
}
|
||||
|
||||
bool CClib_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx,unsigned int nIn)
|
||||
{
|
||||
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64];
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > txids;
|
||||
numvins = tx.vin.size();
|
||||
numvouts = tx.vout.size();
|
||||
preventCCvins = preventCCvouts = -1;
|
||||
if ( numvouts < 1 )
|
||||
return eval->Invalid("no vouts");
|
||||
else
|
||||
{
|
||||
for (i=0; i<numvins; i++)
|
||||
{
|
||||
if ( IsCCInput(tx.vin[0].scriptSig) == 0 )
|
||||
{
|
||||
fprintf(stderr,"faucetget invalid vini\n");
|
||||
return eval->Invalid("illegal normal vini");
|
||||
}
|
||||
}
|
||||
//fprintf(stderr,"check amounts\n");
|
||||
if ( CClibExactAmounts(cp,eval,tx,1,10000) == false )
|
||||
{
|
||||
fprintf(stderr,"faucetget invalid amount\n");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
preventCCvouts = 1;
|
||||
if ( IsCClibvout(cp,tx,0) != 0 )
|
||||
{
|
||||
preventCCvouts++;
|
||||
i = 1;
|
||||
} else i = 0;
|
||||
txid = tx.GetHash();
|
||||
memcpy(hash,&txid,sizeof(hash));
|
||||
fprintf(stderr,"check faucetget txid %s %02x/%02x\n",uint256_str(str,txid),hash[0],hash[31]);
|
||||
if ( tx.vout[i].nValue != FAUCET2SIZE )
|
||||
return eval->Invalid("invalid faucet output");
|
||||
else if ( (hash[0] & 0xff) != 0 || (hash[31] & 0xff) != 0 )
|
||||
return eval->Invalid("invalid faucetget txid");
|
||||
Getscriptaddress(destaddr,tx.vout[i].scriptPubKey);
|
||||
SetCCtxids(txids,destaddr);
|
||||
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=txids.begin(); it!=txids.end(); it++)
|
||||
{
|
||||
//int height = it->first.blockHeight;
|
||||
if ( CCduration(numblocks,it->first.txhash) > 0 && numblocks > 3 )
|
||||
{
|
||||
//fprintf(stderr,"would return error %s numblocks.%d ago\n",uint256_str(str,it->first.txhash),numblocks);
|
||||
return eval->Invalid("faucet2 is only for brand new addresses");
|
||||
}
|
||||
}
|
||||
retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts);
|
||||
if ( retval != 0 )
|
||||
fprintf(stderr,"faucet2get validated\n");
|
||||
else fprintf(stderr,"faucet2get invalid\n");
|
||||
return(retval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int64_t AddCClibInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs)
|
||||
{
|
||||
char coinaddr[64]; int64_t threshold,nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector<uint8_t> origpubkey; CTransaction vintx; int32_t vout,n = 0;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
GetCCaddress(cp,coinaddr,pk);
|
||||
SetCCunspents(unspentOutputs,coinaddr);
|
||||
threshold = total/(maxinputs+1);
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
{
|
||||
txid = it->first.txhash;
|
||||
vout = (int32_t)it->first.index;
|
||||
if ( it->second.satoshis < threshold )
|
||||
continue;
|
||||
//char str[65]; fprintf(stderr,"check %s/v%d %.8f`\n",uint256_str(str,txid),vout,(double)it->second.satoshis/COIN);
|
||||
// no need to prevent dup
|
||||
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
|
||||
{
|
||||
if ( (nValue= IsCClibvout(cp,vintx,vout)) > 1000000 && myIsutxo_spentinmempool(txid,vout) == 0 )
|
||||
{
|
||||
if ( total != 0 && maxinputs != 0 )
|
||||
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
|
||||
nValue = it->second.satoshis;
|
||||
totalinputs += nValue;
|
||||
n++;
|
||||
if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) )
|
||||
break;
|
||||
} else fprintf(stderr,"nValue too small or already spent in mempool\n");
|
||||
} else fprintf(stderr,"couldnt get tx\n");
|
||||
}
|
||||
return(totalinputs);
|
||||
}
|
||||
|
||||
|
||||
std::string Faucet2Fund(struct CCcontract_info *cp,uint64_t txfee,int64_t funds)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
CPubKey mypk,cclibpk; CScript opret;
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
cclibpk = GetUnspendable(cp,0);
|
||||
if ( AddNormalinputs(mtx,mypk,funds+txfee,64) > 0 )
|
||||
{
|
||||
mtx.vout.push_back(MakeCC1vout(cp->evalcode,funds,cclibpk));
|
||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret));
|
||||
}
|
||||
return("");
|
||||
}
|
||||
|
||||
/*UniValue FaucetInfo()
|
||||
{
|
||||
UniValue result(UniValue::VOBJ); char numstr[64];
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
CPubKey faucetpk; struct CCcontract_info *cp,C; int64_t funding;
|
||||
result.push_back(Pair("result","success"));
|
||||
result.push_back(Pair("name","Faucet"));
|
||||
cp = CCinit(&C,EVAL_FAUCET);
|
||||
faucetpk = GetUnspendable(cp,0);
|
||||
funding = AddFaucetInputs(cp,mtx,faucetpk,0,0);
|
||||
sprintf(numstr,"%.8f",(double)funding/COIN);
|
||||
result.push_back(Pair("funding",numstr));
|
||||
return(result);
|
||||
}*/
|
||||
|
||||
std::string CClib_rawtxgen(struct CCcontract_info *cp,uint8_t funcid,cJSON *params)
|
||||
{
|
||||
CMutableTransaction tmpmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
CPubKey mypk,cclibpk; int64_t funds,txfee=0,inputs,CCchange=0,nValue=FAUCET2SIZE; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash;
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
if ( funcid == 'F' )
|
||||
{
|
||||
if ( cJSON_GetArraySize(params) > 0 )
|
||||
{
|
||||
funds = (int64_t)jdouble(jitem(params,0),0)*COIN + 0.0000000049;
|
||||
return(Faucet2Fund(cp,0,funds));
|
||||
} else return("");
|
||||
}
|
||||
else if ( funcid != 'G' )
|
||||
return("");
|
||||
cclibpk = GetUnspendable(cp,0);
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
if ( (inputs= AddCClibInputs(cp,mtx,cclibpk,nValue+txfee,60)) > 0 )
|
||||
{
|
||||
if ( inputs > nValue )
|
||||
CCchange = (inputs - nValue - txfee);
|
||||
if ( CCchange != 0 )
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_FIRSTUSER,CCchange,cclibpk));
|
||||
mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
|
||||
fprintf(stderr,"start at %u\n",(uint32_t)time(NULL));
|
||||
j = rand() & 0xfffffff;
|
||||
for (i=0; i<1000000; i++,j++)
|
||||
{
|
||||
tmpmtx = mtx;
|
||||
rawhex = FinalizeCCTx(-1LL,cp,tmpmtx,mypk,txfee,CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_FIRSTUSER << (uint8_t)'G' << j));
|
||||
if ( (len= (int32_t)rawhex.size()) > 0 && len < 65536 )
|
||||
{
|
||||
len >>= 1;
|
||||
decode_hex(buf,len,(char *)rawhex.c_str());
|
||||
hash = bits256_doublesha256(0,buf,len);
|
||||
if ( (hash.bytes[0] & 0xff) == 0 && (hash.bytes[31] & 0xff) == 0 )
|
||||
{
|
||||
fprintf(stderr,"found valid txid after %d iterations %u\n",i,(uint32_t)time(NULL));
|
||||
return(rawhex);
|
||||
}
|
||||
//fprintf(stderr,"%02x%02x ",hash.bytes[0],hash.bytes[31]);
|
||||
}
|
||||
}
|
||||
fprintf(stderr,"couldnt generate valid txid %u\n",(uint32_t)time(NULL));
|
||||
return("");
|
||||
} else fprintf(stderr,"cant find faucet inputs\n");
|
||||
return("");
|
||||
}
|
||||
@@ -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<CPubKey> 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<uint8_t> vopret; uint8_t *script,e,f;
|
||||
GetOpReturnData(scriptPubKey, vopret);
|
||||
std::vector<uint8_t> vopret; uint8_t *script,e,f,tokenevalcode;
|
||||
std::vector<CPubKey> pubkeys; std::vector<uint8_t> 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<numvins; i++)
|
||||
if ((numvouts=tx.vout.size()) > 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; i<numvouts; i++)
|
||||
{
|
||||
outputs += tx.vout[i].nValue;
|
||||
}
|
||||
if ( inputs != outputs+txfee )
|
||||
{
|
||||
fprintf(stderr,"inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs);
|
||||
return eval->Invalid("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<std::pair<CAddressUnspentKey, CAddressUnspentValue> > 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<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::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<payment)
|
||||
{
|
||||
CCerror = strprintf("invalid amount, not a magnitude of payment size");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return ("");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CCerror = strprintf("invalid channel open tx");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return ("");
|
||||
}
|
||||
if (AddNormalinputs(mtx,mypk,2*txfee,3) > 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<payment)
|
||||
CCerror = strprintf("not enough funds in channel for that amount");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return ("");
|
||||
} else if (numpayments == 0)
|
||||
{
|
||||
fprintf(stderr,"invalid amount, not a magnitude of payment size\n");
|
||||
CCerror = strprintf("invalid amount");
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return ("");
|
||||
}
|
||||
numpayments=amount/payment;
|
||||
if (GetTransaction(prevtxid,prevTx,hashblock,false) != 0 && (numvouts=prevTx.vout.size()) > 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<std::pair<CAddressIndexKey, CAmount> > txids;
|
||||
UniValue result(UniValue::VOBJ); std::vector<std::pair<CAddressIndexKey, CAmount> > 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<std::pair<CAddressIndexKey, CAmount> >::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<std::pair<CAddressIndexKey, CAmount> >::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<std::pair<CAddressIndexKey, CAmount> >::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<std::pair<CAddressIndexKey, CAmount> > addressIndex; std::vector<uint256> 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<std::pair<CAddressIndexKey, CAmount> >::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<uint256>::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);
|
||||
}
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<n; i++)
|
||||
{
|
||||
item = jitem(array,i);
|
||||
if (is_cJSON_False(jobj(item, "spendable")) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ( (addr= jstr(item,"address")) != 0 )
|
||||
{
|
||||
strcpy(coinaddr,addr);
|
||||
@@ -732,7 +772,7 @@ void importaddress(char *refcoin,char *acname,char *depositaddr)
|
||||
|
||||
int32_t z_sendmany(char *opidstr,char *coinstr,char *acname,char *srcaddr,char *destaddr,int64_t amount)
|
||||
{
|
||||
cJSON *retjson; char *retstr,params[1024],addr[128];
|
||||
cJSON *retjson; char *retstr,params[1024],addr[128]; int32_t retval = -1;
|
||||
sprintf(params,"'[{\"address\":\"%s\",\"amount\":%.8f}]'",destaddr,dstr(amount));
|
||||
sprintf(addr,"\"%s\"",srcaddr);
|
||||
printf("z_sendmany from.(%s) -> %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;
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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.h>
|
||||
|
||||
#include "hash.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 *
|
||||
@@ -27,6 +27,8 @@
|
||||
#include "core_io.h"
|
||||
#include "crosschain.h"
|
||||
|
||||
bool CClib_Dispatch(const CC *cond,Eval *eval,std::vector<uint8_t> 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<uint8_t> 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<uint8_t> vparams(cond->code+1, cond->code+cond->codeLength);
|
||||
switch ( ecode )
|
||||
{
|
||||
case EVAL_IMPORTPAYOUT:
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint256> txids; std::vector<CPubKey> pubkeys,publishers,tmppublishers; std::vector<uint8_t> 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<uint8_t> origpubkey; std::vector<uint8_t> 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<uint8_t> origpubkey; std::vector<uint8_t> vopret; CTransaction vintx; int32_t j,vout,n = 0; uint8_t evalcode,funcid;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > 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<CPubKey> msigpubkeys,publishers; int64_t totalsupply,depositamount,tmpamount,inputs,CCchange=0;
|
||||
int32_t numvouts,claimvout,height; std::vector<uint8_t> proof;
|
||||
uint256 hashBlock,assetid,oracletxid,tmptxid,cointxid; char str[65],depositaddr[64],coinaddr[64],destaddr[64]; std::vector<uint256> txids;
|
||||
uint256 hashBlock,tokenid,oracletxid,tmptxid,cointxid; char str[65],depositaddr[64],coinaddr[64],destaddr[64]; std::vector<uint256> 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<CPubKey> 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<CPubKey> 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<CPubKey> 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<CPubKey> 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<std::pair<CAddressUnspentKey, CAddressUnspentValue> > 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<CPubKey> 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<std::pair<CAddressUnspentKey, CAddressUnspentValue> > 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)));
|
||||
|
||||
1408
src/cc/heir.cpp
1408
src/cc/heir.cpp
File diff suppressed because it is too large
Load Diff
667
src/cc/heir_validate.h
Normal file
667
src/cc/heir_validate.h
Normal file
@@ -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<CPubKey> 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<CPubKey> dummyPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan) {
|
||||
return EncodeHeirOpRet((uint8_t)'A', fundingtxid, isHeirSpendingBegan);
|
||||
}
|
||||
static CScript makeClaimOpRet(uint256 dummyid, std::vector<CPubKey> 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<CPubKey> 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<CPubKey> voutTokenPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan) {
|
||||
return EncodeTokenOpRet(tokenid, voutTokenPubkeys,
|
||||
EncodeHeirOpRet((uint8_t)'A', fundingtxid, isHeirSpendingBegan));
|
||||
}
|
||||
static CScript makeClaimOpRet(uint256 tokenid, std::vector<CPubKey> 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<CTxOut> 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 <typename TValidatorBase>
|
||||
class CInputValidationPlan
|
||||
{
|
||||
using ValidatorsRow = std::vector<TValidatorBase*>;
|
||||
|
||||
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 <typename TValidatorBaseX, typename... ARGS>
|
||||
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 = "<empty>";
|
||||
//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<CInputIdentifierBase*, ValidatorsRow> m_arrayValidators;
|
||||
std::vector< std::pair<CInputIdentifierBase*, ValidatorsRow> > 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 <typename TValidatorBase>
|
||||
class COutputValidationPlan
|
||||
{
|
||||
using ValidatorsRow = std::vector<TValidatorBase*>;
|
||||
|
||||
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 <typename TValidatorBaseX, typename... ARGS>
|
||||
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 = "<empty>";
|
||||
//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<int32_t, ValidatorsRow> m_mapValidators;
|
||||
std::vector< std::pair<int32_t, ValidatorsRow> > 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 Helper> 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<CTxOut> 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 Helper> 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<CTxOut> 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 Helper> 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<CTxOut> 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 Helper> 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<CTxOut> 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 Helper> 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<CTxOut> 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 Helper> 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<CTxOut> prevVout, int32_t prevN, std::string& message) const { return true; }
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -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<uint8_t> 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<uint8_t> rawtx,uint256 txid,std::vector<uint8_t> 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<uint8_t> rawproof,CTransaction burnTx,std::vector<CTxOut> payouts)
|
||||
{
|
||||
// check with dual-BEAM daemon via ASSETCHAINS_BEAMPORT for validity of burnTx
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int32_t CheckCODAimport(TxProof proof,std::vector<uint8_t> rawproof,CTransaction burnTx,std::vector<CTxOut> payouts)
|
||||
{
|
||||
// check with dual-CODA daemon via ASSETCHAINS_CODAPORT for validity of burnTx
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int32_t CheckGATEWAYimport(TxProof proof,std::vector<uint8_t> rawproof,CTransaction burnTx,std::vector<CTxOut> 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<uint8_t> rawproof,CTransaction burnTx,std::vector<CTxOut> 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<uint8_t> params,const CTransaction &importTx,unsigned int nIn)
|
||||
{
|
||||
TxProof proof; CTransaction burnTx; std::vector<CTxOut> payouts; uint64_t txfee = 10000;
|
||||
uint32_t targetCcid; std::string targetSymbol; uint256 payoutsHash; std::vector<uint8_t> rawproof;
|
||||
if ( importTx.vout.size() < 2 )
|
||||
return Invalid("too-few-vouts");
|
||||
|
||||
// params
|
||||
TxProof proof;
|
||||
CTransaction burnTx;
|
||||
std::vector<CTxOut> 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<uint8_t> params, const CTransaction &imp
|
||||
uint64_t totalOut = 0;
|
||||
for (int i=0; i<importTx.vout.size(); i++)
|
||||
totalOut += importTx.vout[i].nValue;
|
||||
if (totalOut > 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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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.h>
|
||||
|
||||
#include "main.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
|
||||
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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 <stdint.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 *
|
||||
@@ -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;
|
||||
|
||||
1
src/cc/makecclib
Executable file
1
src/cc/makecclib
Executable file
@@ -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
|
||||
1097
src/cc/marmara.cpp
Normal file
1097
src/cc/marmara.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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 *
|
||||
@@ -108,7 +108,7 @@ uint8_t DecodeOraclesCreateOpRet(const CScript &scriptPubKey,std::string &name,s
|
||||
std::vector<uint8_t> 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<uint8_t> 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<uint8_t> 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<dlen; i++)
|
||||
sprintf(&str[i<<1],"%02x",data[offset++]);
|
||||
str[i] = 0;
|
||||
str[i<<1] = 0;
|
||||
} else return(-1);
|
||||
}
|
||||
}
|
||||
@@ -416,6 +416,42 @@ int32_t oracle_format(uint256 *hashp,int64_t *valp,char *str,uint8_t fmt,uint8_t
|
||||
return(offset);
|
||||
}
|
||||
|
||||
int32_t oracle_parse_data_format(std::vector<uint8_t> data,std::string format)
|
||||
{
|
||||
int64_t offset=0,len=0; char fmt;
|
||||
|
||||
for (int i=0; i<format.size();i++)
|
||||
{
|
||||
fmt=format[i];
|
||||
switch (fmt)
|
||||
{
|
||||
case 's': len = data[offset++]; break;
|
||||
case 'S': len = data[offset++]; len |= ((int32_t)data[offset++] << 8); break;
|
||||
case 'd': len = data[offset++]; break;
|
||||
case 'D': len = data[offset++]; len |= ((int32_t)data[offset++] << 8); break;
|
||||
case 'c': len = 1; break;
|
||||
case 'C': len = 1; break;
|
||||
case 't': len = 2; break;
|
||||
case 'T': len = 2; break;
|
||||
case 'i': len = 4; break;
|
||||
case 'I': len = 4; break;
|
||||
case 'l': len = 8; break;
|
||||
case 'L': len = 8; break;
|
||||
case 'h': len = 32; break;
|
||||
default: return(0); break;
|
||||
}
|
||||
if (len>data.size()-offset) return (0);
|
||||
if (fmt=='S' || fmt=='s')
|
||||
{
|
||||
for (int j=offset;j<offset+len;j++)
|
||||
if (data[j]<32 || data[j]>127) 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 <uint8_t> 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 <uint8_t> 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 <uint8_t> 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 <uint8_t> 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 <uint8_t> 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<uint8_t> 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<uint8_t> data; char *formatstr = 0;
|
||||
|
||||
result.push_back(Pair("result","success"));
|
||||
if ( GetTransaction(reforacletxid,oracletx,hashBlock,false) != 0 && (numvouts=oracletx.vout.size()) > 0 )
|
||||
{
|
||||
|
||||
@@ -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<std::pair<CAddressIndexKey, CAmount> > txids;
|
||||
numvins = tx.vin.size();
|
||||
numvouts = tx.vout.size();
|
||||
|
||||
@@ -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<std::pair<CAddressIndexKey, CAmount> > txids;
|
||||
numvins = tx.vin.size();
|
||||
numvouts = tx.vout.size();
|
||||
|
||||
@@ -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<std::pair<CAddressIndexKey, CAmount> > 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<CPubKey> voutTokenPubkeysEmpty; //TODO: add token vout pubkeys
|
||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,
|
||||
EncodeTokenOpRet(bettoken, voutTokenPubkeysEmpty,
|
||||
EncodeAssetOpRet('t',/*bettoken,*/zeroid, 0, Mypubkey()))));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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; i<numvins; i++)
|
||||
{
|
||||
//fprintf(stderr,"vini.%d\n",i);
|
||||
if ( (*cp->ismyvin)(tx.vin[i].scriptSig) != 0 )
|
||||
{
|
||||
//fprintf(stderr,"vini.%d check mempool\n",i);
|
||||
if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 )
|
||||
return eval->Invalid("cant find vinTx");
|
||||
else
|
||||
{
|
||||
//fprintf(stderr,"vini.%d check hash and vout\n",i);
|
||||
if ( hashBlock == zerohash )
|
||||
return eval->Invalid("cant Triggers from mempool");
|
||||
if ( (assetoshis= IsTriggersvout(cp,vinTx,tx.vin[i].prevout.n)) != 0 )
|
||||
inputs += assetoshis;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i=0; i<numvouts; i++)
|
||||
{
|
||||
//fprintf(stderr,"i.%d of numvouts.%d\n",i,numvouts);
|
||||
if ( (assetoshis= IsTriggersvout(cp,tx,i)) != 0 )
|
||||
outputs += assetoshis;
|
||||
}
|
||||
if ( inputs != outputs+txfee )
|
||||
{
|
||||
fprintf(stderr,"inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs);
|
||||
return eval->Invalid("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<std::pair<CAddressIndexKey, CAmount> > txids;
|
||||
numvins = tx.vin.size();
|
||||
numvouts = tx.vout.size();
|
||||
preventCCvins = preventCCvouts = -1;
|
||||
if ( numvouts < 1 )
|
||||
return eval->Invalid("no vouts");
|
||||
else
|
||||
{
|
||||
for (i=0; i<numvins; i++)
|
||||
{
|
||||
if ( IsCCInput(tx.vin[0].scriptSig) == 0 )
|
||||
{
|
||||
return eval->Invalid("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<uint8_t> origpubkey; CTransaction vintx; int32_t vout,n = 0;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
GetCCaddress(cp,coinaddr,pk);
|
||||
SetCCunspents(unspentOutputs,coinaddr);
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
{
|
||||
txid = it->first.txhash;
|
||||
vout = (int32_t)it->first.index;
|
||||
// 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);
|
||||
}
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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;
|
||||
|
||||
15
src/chain.h
15
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
|
||||
|
||||
|
||||
@@ -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) )
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
/**
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user