diff --git a/.github/workflows/ci-image.yml b/.github/workflows/ci-image.yml new file mode 100644 index 0000000..2a4a60f --- /dev/null +++ b/.github/workflows/ci-image.yml @@ -0,0 +1,39 @@ +name: CI - Release + +on: + push: + +jobs: + release-image: + permissions: + id-token: write + contents: write + runs-on: docker + steps: + - name: 'Checkout scm ${{ inputs.commitOrTag }}' + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: ${{ inputs.commitOrTag }} + + - name: Image tag + id: set-tag + run: echo "tag=$(git rev-parse --short=7 HEAD)" >> $GITHUB_OUTPUT + shell: bash + + - name: Build Docker images + run: docker build -t zilliqa/zilliqa-relayer:experimental-${{ steps.set-tag.outputs.tag }} -t zilliqa/zilliqa-relayer:latest . + shell: bash + + - name: Login to the DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_PASSWORD }} + + - name: Push Docker images to Dockerhub + if: github.actor != 'dependabot[bot]' && github.ref_name == 'main' + run: | + docker push zilliqa/zilliqa-relayer:experimental-${{ steps.set-tag.outputs.tag }} + docker push zilliqa/zilliqa-relayer:latest + shell: bash \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a7f71c6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +*~ +\#* +.\#* +zilliqa-relayer +.idea +bolt.bin +config.local.yaml +constants.xml +cross_chain_manager_admin.json +xiaohuo.wallet +zilliqa.wallet +poly.wallet +relayer.wallet +secrets +config.devnet.yaml +config.testnet.yaml +config.production.yaml +target_contracts_local.json +target_contracts_devnet.json +target_contracts_production.json +audit.log +zil_relayer +wallet.dat \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..038b8bd --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +FROM golang:1.15 AS build +WORKDIR /app/zilliqa-relayer +COPY . ./ +RUN go build +#RUN git clone https://github.com/Zilliqa/zilliqa-relayer.git && \ +# cd zilliqa-relayer && \ +# go build + +FROM ubuntu:18.04 +RUN apt-get update && apt-get install -y ca-certificates +WORKDIR /app +COPY run.sh run.sh +COPY --from=build /app/zilliqa-relayer/zilliqa-relayer zilliqa-relayer +ENTRYPOINT ["/bin/bash", "run.sh"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4e61c8d --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. 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 +them 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 prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. 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. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey 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; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + 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. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +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. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + 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 +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program 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, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU 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. But first, please read +. diff --git a/README.md b/README.md index 5274f53..ee4e691 100644 --- a/README.md +++ b/README.md @@ -1 +1,135 @@ -# zilliqa-relayer \ No newline at end of file +# zilliqa-relayer + +*This program is still under developing!* + +Zilliqa Relayer is an important character of Poly cross-chain interactive protocol which is responsible for relaying cross-chain transaction from and to Zilliqa. + +## Build From Source + +### Prerequisites + +- [Golang](https://golang.org/doc/install) version 1.14 or later + +### Build + +```shell +git clone https://github.com/polynetwork/zil-relayer.git +cd zil-relayer +./build.sh +``` + +After building the source code successfully, you should see the executable program `zilliqa-relayer`. + +### Build Docker Image + +``` +docker build -t polynetwork/zilliqa-relayer . +``` + +This command will copy config.yaml to /app/config.yaml in the image. So you need to prepare config.yaml before running this command and you should start the zilliqa-relayer in container basing on the configuration in /app/config.yaml. + + +## Run Relayer +Before you can run the relayer you will need to create a wallet file of PolyNetwork by running(build Poly CLI first): + +```shell +./poly account add -d +``` + +After creation, you need to register it as a Relayer to Poly net and get consensus nodes approving your registeration. And then you can send transaction to Poly net and start relaying. + +Before running, you need feed the configuration file `config.yaml`. + +`practice_only: true` will stop the relayer sending any actual transactions - it just prints what it would have done. +`debug: true` will produce a bunch of debug info useful when debugging ZilBridge sync. + +```yaml +practice_only: false +debug: true +zil_config: + zil_api: https://api.zilliqa.com + zil_chain_id: 111 + zil_message_version: 1 + zil_force_height: 0 + zil_monitor_interval: 10 + zil_headers_per_batch: 2 + corss_chain_manager_address: zil1tjru7m5zdn3x6k0t72nzmmpz62e5qds62nte9t + cross_chain_manager_proxy_address: zil1n7wkwr0xxslwsrhnqtjrwlus80dp5ncnlpaw93 + side_chain_id: 85 + key_store_path: zilliqa.wallet + key_store_pwd_set: + 6c89b62d65dc632e259b96f7ae2f1d68a27e3383: "" +poly_config: + poly_wallet_file: poly.wallet + poly_wallet_pwd: + poly_start_height: 0 + poly_monitor_interval: 2 + entrance_contract_address: "0300000000000000000000000000000000000000" + rest_url: http://poly.com +target_contracts: target_contracts.json +db_path: persistence +``` + +A sample keystore file could be: + +```text +{"address":"7d48043742a1103042d327111746531ca26be9be","id":"6cd445ed-8f5f-4565-af2a-cc2306a82b73","version":3,"crypto":{"cipher":"aes-128-ctr","ciphertext":"d136660a4e5664709031ebc162616556e8c812ab37d0157ea3276aa08d0a6c2d","kdf":"pbkdf2","mac":"b30dd459f1fd9d99c0b2f3452ccd2bf11414ad92d32ac70d1d7b52f17281b4e5","cipherparams":{"iv":"6a14f95c8cbafe7d1f317bec88e9d1b8"},"kdfparams":{"n":8192,"c":262144,"r":8,"p":1,"dklen":32,"salt":"c4939e7cead32935d1972a2cd06d249dd501181e6ad2d1872fa0eb397d7fea20"}}} +``` +# Relayer Container Administration +## Running the Relayer Container +### Prerequisites: +If you are running via docker-compose, you'll need to install docker-compose first via the following guide: +``` +https://docs.docker.com/compose/install/ +``` + +You need the following files and folders created:
+If persistence is already created: +``` +./persistence/bolt.bin +``` +If persistence folder is not created: +``` +create a folder named 'persistence'. The container will use that folder to store the bolt.bin file. +``` +Configuration Files: +``` +secrets/config.local.yaml +secrets/target_contracts.json +secrets/poly.wallet +secrets/zilliqa.wallet +``` +### Running Relayer via Docker Container +``` +./docker-run +``` + +### Running Relayer via Docker Compose +``` +docker-compose up -d +``` +## Stopping the Relayer +### Stopping Relayer via Docker Container +``` +docker stop zilliqa-relayer && docker rm zilliqa-relayer +``` +### Stopping Relayer via Docker Compose +``` +docker-compose down +``` +## Getting logs +``` +docker logs -f zilliqa-relayer +``` + + +## Other Resources + +- [zilliqa cross chain manager proxy](https://github.com/Zilliqa/zilliqa-contracts/blob/main/contracts/ZilCrossChainManagerProxy.scilla) +- [zilliqa cross chain manager](https://github.com/Zilliqa/zilliqa-contracts/blob/main/contracts/ZilCrossChainManager.scilla) +- [zilliqa lock proxy](https://github.com/Zilliqa/zilliqa-contracts/blob/main/contracts/LockProxy.scilla) +- [polynetwork](https://github.com/polynetwork/poly) + + + + diff --git a/build-docker.sh b/build-docker.sh new file mode 100755 index 0000000..deab546 --- /dev/null +++ b/build-docker.sh @@ -0,0 +1,2 @@ +#!/bin/sh +docker build -t polynetwork/zilliqa-relayer . diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..b972750 --- /dev/null +++ b/build.sh @@ -0,0 +1,2 @@ +#!/bin/sh +go build \ No newline at end of file diff --git a/cmd/root.go b/cmd/root.go new file mode 100644 index 0000000..506ea8f --- /dev/null +++ b/cmd/root.go @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 Zilliqa + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package cmd + +import ( + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "os" +) + +var RootCmd = &cobra.Command{ + Use: "zilliqa-relayer", + Short: "To run zilliqa relayer for poly network", + Long: `To run zilliqa relayer for poly network`, + Run: func(cmd *cobra.Command, args []string) { + }, +} + +func Execute() { + if err := RootCmd.Execute(); err != nil { + log.Error(err) + os.Exit(1) + } +} diff --git a/cmd/run.go b/cmd/run.go new file mode 100644 index 0000000..00eb5ca --- /dev/null +++ b/cmd/run.go @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2021 Zilliqa + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package cmd + +import ( + "encoding/json" + "github.com/Zilliqa/gozilliqa-sdk/provider" + poly_go_sdk "github.com/polynetwork/poly-go-sdk" + "github.com/polynetwork/zilliqa-relayer/config" + "github.com/polynetwork/zilliqa-relayer/db" + "github.com/polynetwork/zilliqa-relayer/service" + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "io/ioutil" + "os" + "path" +) + +var cfgFile string + +func init() { + cobra.OnInitialize(initConfig) + RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)") + + RootCmd.AddCommand(runCmd) + log.SetFormatter(&log.TextFormatter{ + FullTimestamp: true, + }) +} + +func initConfig() { + if cfgFile != "" { + // Use config file from the flag. + viper.SetConfigFile(cfgFile) + } else { + viper.AddConfigPath("./") + viper.SetConfigName("config.local") + } + + viper.AutomaticEnv() + + err := viper.ReadInConfig() + if err == nil { + log.Info("Using config file:", viper.ConfigFileUsed()) + } else { + log.Error(err.Error()) + } +} + +func setUpPoly(poly *poly_go_sdk.PolySdk, RpcAddr string) error { + poly.NewRpcClient().SetAddress(RpcAddr) + hdr, err := poly.GetHeaderByHeight(0) + if err != nil { + return err + } + poly.SetChainId(hdr.ChainID) + return nil +} + +func checkIfExist(dir string) bool { + _, err := os.Stat(dir) + if err != nil && !os.IsExist(err) { + return false + } + return true +} + +var runCmd = &cobra.Command{ + Use: "run", + Short: "Run zilliqa relayer", + Long: `Run zilliqa relayer`, + Run: func(cmd *cobra.Command, args []string) { + viper.SetDefault("debug", false) + viper.SetDefault("practiceOnly", false) + debugInfo := viper.GetBool("debug") + practiceOnly := viper.GetBool("practice_only") + zilConfigMap := viper.GetStringMap("zil_config") + targetContractsPath := viper.GetString("target_contracts") + dbPath := viper.GetString("db_path") + removeDb := viper.GetBool("remove_db") + bytes, e := ioutil.ReadFile(targetContractsPath) + if e != nil { + log.Errorf("read target contracts error: %s, path: %s\n", e.Error(), targetContractsPath) + return + } + var targetContract []map[string]map[string][]uint64 + e2 := json.Unmarshal(bytes, &targetContract) + if e2 != nil { + log.Errorf("unmarshal target contracts error: %s\n", e2.Error()) + return + } + log.Info(targetContract) + zilConfig := &config.ZILConfig{ + ZilApiEndpoint: zilConfigMap["zil_api"].(string), + ZilChainId: zilConfigMap["zil_chain_id"].(int), + ZilMessageVersion: zilConfigMap["zil_message_version"].(int), + ZilForceHeight: uint64(zilConfigMap["zil_force_height"].(int)), + ZilMonitorInterval: uint32(zilConfigMap["zil_monitor_interval"].(int)), + ZilHeadersPerBatch: uint32(zilConfigMap["zil_headers_per_batch"].(int)), + SideChainId: uint64(zilConfigMap["side_chain_id"].(int)), + CrossChainManagerContract: zilConfigMap["corss_chain_manager_address"].(string), + CrossChainManagerProxyContract: zilConfigMap["cross_chain_manager_proxy_address"].(string), + MaxExistTxEpoch: zilConfigMap["max_exist_tx_epoch"].(int), + KeyStorePath: zilConfigMap["key_store_path"].(string), + KeyStorePwdSet: zilConfigMap["key_store_pwd_set"].(map[string]interface{}), + } + + polyConfigMap := viper.GetStringMap("poly_config") + + polyConfig := &config.POLYConfig{ + PolyWalletFile: polyConfigMap["poly_wallet_file"].(string), + PolyWalletPassword: polyConfigMap["poly_wallet_pwd"].(string), + PolyStartHeight: uint32(polyConfigMap["poly_start_height"].(int)), + PolyMonitorInterval: uint32(polyConfigMap["poly_monitor_interval"].(int)), + EntranceContractAddress: polyConfigMap["entrance_contract_address"].(string), + RestUrl: polyConfigMap["rest_url"].(string), + } + + cfg := &config.Config{ + ZilConfig: zilConfig, + PolyConfig: polyConfig, + TargetContracts: targetContract, + Path: dbPath, + RemoveDB: removeDb, + } + + cfgStr, _ := json.Marshal(cfg) + log.Infof("config file: %s\n", cfgStr) + + zilSdk := provider.NewProvider(cfg.ZilConfig.ZilApiEndpoint) + polySdk := poly_go_sdk.NewPolySdk() + err1 := setUpPoly(polySdk, cfg.PolyConfig.RestUrl) + if err1 != nil { + log.Errorf("init poly sdk error: %s\n", err1.Error()) + return + } + + if cfg.RemoveDB { + os.Remove(path.Join(cfg.Path, "bolt.bin")) + } + + if !checkIfExist(cfg.Path) { + os.Mkdir(cfg.Path, os.ModePerm) + } + boltDB, err2 := db.NewBoltDB(cfg.Path) + if err2 != nil { + log.Errorf("cannot init bolt db: %s\n", err2.Error()) + return + } + + // zil to poly + zilliqaManager, err := service.NewZilliqaSyncManager(cfg, zilSdk, polySdk, boltDB, debugInfo, practiceOnly) + if err != nil { + log.Errorf("init zilliqamanger error: %s\n", err.Error()) + return + } + // poly to zil + polyManager, err1 := service.NewPolySyncManager(cfg, zilSdk, polySdk, boltDB, cfg.ZilConfig.CrossChainManagerContract, cfg.ZilConfig.CrossChainManagerProxyContract) + if err1 != nil { + log.Errorf("init polymanager error: %s\n", err1.Error()) + return + } + + zilliqaManager.Run(true) + polyManager.Run(true) + + service.WaitToExit() + + }, +} diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..b4660a1 --- /dev/null +++ b/config.yaml @@ -0,0 +1,23 @@ +zil_config: + zil_api: https://api.zilliqa.com + zil_chain_id: 111 + zil_message_version: 1 + zil_force_height: 0 + zil_monitor_interval: 10 + zil_headers_per_batch: 2 + corss_chain_manager_address: zil1tjru7m5zdn3x6k0t72nzmmpz62e5qds62nte9t + cross_chain_manager_proxy_address: zil1n7wkwr0xxslwsrhnqtjrwlus80dp5ncnlpaw93 + side_chain_id: 85 + key_store_path: zilliqa.wallet + max_exist_tx_epoch: 5 + key_store_pwd_set: + 6c89b62d65dc632e259b96f7ae2f1d68a27e3383: "" +poly_config: + poly_wallet_file: poly.wallet + poly_wallet_pwd: + poly_start_height: 0 + poly_monitor_interval: 2 + entrance_contract_address: "0300000000000000000000000000000000000000" + rest_url: http://poly.com +target_contracts: target_contracts.json +remove_db: false \ No newline at end of file diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..511c930 --- /dev/null +++ b/config/config.go @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2021 Zilliqa + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package config + +const ( + OntUsefulBlockNum = 1 +) + +type Config struct { + ZilConfig *ZILConfig + PolyConfig *POLYConfig + Path string + RemoveDB bool + TargetContracts []map[string]map[string][]uint64 +} + +type ZILConfig struct { + ZilApiEndpoint string + ZilChainId int + ZilMessageVersion int + ZilMonitorInterval uint32 + ZilHeadersPerBatch uint32 + ZilForceHeight uint64 + SideChainId uint64 + CrossChainManagerContract string + CrossChainManagerProxyContract string + MaxExistTxEpoch int + KeyStorePath string + KeyStorePwdSet map[string]interface{} +} + +type POLYConfig struct { + PolyWalletFile string + PolyWalletPassword string + PolyStartHeight uint32 + PolyMonitorInterval uint32 + EntranceContractAddress string + RestUrl string +} diff --git a/db/db.go b/db/db.go new file mode 100644 index 0000000..e21d1cf --- /dev/null +++ b/db/db.go @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2021 Zilliqa + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package db + +import ( + "encoding/binary" + "encoding/hex" + "fmt" + "github.com/boltdb/bolt" + "path" + "strings" + "sync" +) + +const MAX_NUM = 1000 + +type BoltDB struct { + rwLock *sync.RWMutex + db *bolt.DB + filePath string +} + +var ( + BKTCheck = []byte("Check") + BKTRetry = []byte("Retry") + BKTHeight = []byte("Height") +) + +func NewBoltDB(filePath string) (*BoltDB, error) { + if !strings.Contains(filePath, ".bin") { + filePath = path.Join(filePath, "bolt.bin") + } + + w := new(BoltDB) + db, err := bolt.Open(filePath, 0644, &bolt.Options{InitialMmapSize: 500000}) + if err != nil { + return nil, err + } + + w.db = db + w.rwLock = new(sync.RWMutex) + w.filePath = filePath + + // poly check + if err = db.Update(func(btx *bolt.Tx) error { + _, err := btx.CreateBucketIfNotExists(BKTCheck) + if err != nil { + return err + } + return nil + }); err != nil { + return nil, err + } + + // poly retry + if err = db.Update(func(btx *bolt.Tx) error { + _, err := btx.CreateBucketIfNotExists(BKTRetry) + if err != nil { + return err + } + return nil + }); err != nil { + return nil, err + } + + // poly check + if err = db.Update(func(btx *bolt.Tx) error { + _, err := btx.CreateBucketIfNotExists(BKTHeight) + if err != nil { + return err + } + return nil + }); err != nil { + return nil, err + } + + return w, nil +} + +func (w *BoltDB) PutRetry(k []byte) error { + w.rwLock.Lock() + defer w.rwLock.Unlock() + + return w.db.Update(func(btx *bolt.Tx) error { + bucket := btx.Bucket(BKTRetry) + err := bucket.Put(k, []byte{0x00}) + if err != nil { + return err + } + + return nil + }) +} + +func (w *BoltDB) DeleteRetry(k []byte) error { + w.rwLock.Lock() + defer w.rwLock.Unlock() + + return w.db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket(BKTRetry) + err := bucket.Delete(k) + if err != nil { + return err + } + return nil + }) +} + +func (w *BoltDB) PutCheck(txHash string, v []byte) error { + w.rwLock.Lock() + defer w.rwLock.Unlock() + + k, err := hex.DecodeString(txHash) + if err != nil { + return err + } + return w.db.Update(func(btx *bolt.Tx) error { + bucket := btx.Bucket(BKTCheck) + err := bucket.Put(k, v) + if err != nil { + return err + } + + return nil + }) +} + +func (w *BoltDB) GetAllRetry() ([][]byte, error) { + w.rwLock.Lock() + defer w.rwLock.Unlock() + + retryList := make([][]byte, 0) + err := w.db.Update(func(tx *bolt.Tx) error { + bw := tx.Bucket(BKTRetry) + bw.ForEach(func(k, _ []byte) error { + _k := make([]byte, len(k)) + copy(_k, k) + retryList = append(retryList, _k) + if len(retryList) >= MAX_NUM { + return fmt.Errorf("max num") + } + return nil + }) + return nil + }) + if err != nil { + return nil, err + } + return retryList, nil +} + +func (w *BoltDB) UpdatePolyHeight(h uint32) error { + w.rwLock.Lock() + defer w.rwLock.Unlock() + + raw := make([]byte, 4) + binary.LittleEndian.PutUint32(raw, h) + + return w.db.Update(func(tx *bolt.Tx) error { + bkt := tx.Bucket(BKTHeight) + return bkt.Put([]byte("poly_height"), raw) + }) +} + +func (w *BoltDB) GetPolyHeight() uint32 { + w.rwLock.RLock() + defer w.rwLock.RUnlock() + + var h uint32 + _ = w.db.View(func(tx *bolt.Tx) error { + bkt := tx.Bucket(BKTHeight) + raw := bkt.Get([]byte("poly_height")) + if len(raw) == 0 { + h = 0 + return nil + } + h = binary.LittleEndian.Uint32(raw) + return nil + }) + return h +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..157d6e4 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,11 @@ +version: "3.9" +services: + zilliqa-relayer: + container_name: zilliqa-relayer + build: . + volumes: + - ./persistence:/app/persistence + - ./secrets/config.local.yaml:/app/config.local.yaml + - ./secrets/target_contracts.json:/app/target_contracts.json + - ./secrets/poly.wallet:/app/poly.wallet + - ./secrets/zilliqa.wallet:/app/zilliqa.wallet diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..ed342e2 --- /dev/null +++ b/go.mod @@ -0,0 +1,21 @@ +module github.com/polynetwork/zilliqa-relayer + +go 1.15 + +require ( + github.com/Zilliqa/gozilliqa-sdk v1.2.1-0.20210927032600-4c733f2cb879 + github.com/boltdb/bolt v1.3.1 + github.com/btcsuite/btcd v0.20.1-beta + github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/ethereum/go-ethereum v1.9.24 // indirect + github.com/magiconair/properties v1.8.1 + github.com/ontio/ontology v1.11.0 + github.com/ontio/ontology-crypto v1.0.9 + github.com/polynetwork/poly v0.0.0-20200715030435-4f1d1a0adb44 + github.com/polynetwork/poly-go-sdk v0.0.0-20200817120957-365691ad3493 + github.com/sirupsen/logrus v1.7.0 + github.com/spf13/cobra v1.1.1 + github.com/spf13/viper v1.7.0 + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 + launchpad.net/gocheck v0.0.0-20140225173054-000000000087 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..08f2f03 --- /dev/null +++ b/go.sum @@ -0,0 +1,900 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/99designs/keyring v1.1.3/go.mod h1:657DQuMrBZRtuL/voxVyiyb6zpMehlm5vLB9Qwrv904= +github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= +github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= +github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/ChainSafe/go-schnorrkel v0.0.0-20200102211924-4bcbc698314f h1:4O1om+UVU+Hfcihr1timk8YNXHxzZWgCo7ofnrZRApw= +github.com/ChainSafe/go-schnorrkel v0.0.0-20200102211924-4bcbc698314f/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/JohnCGriffin/overflow v0.0.0-20170615021017-4d914c927216 h1:2ZboyJ8vl75fGesnG9NpMTD2DyQI3FzMXy4x752rGF0= +github.com/JohnCGriffin/overflow v0.0.0-20170615021017-4d914c927216/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= +github.com/OpenBazaar/jsonpb v0.0.0-20171123000858-37d32ddf4eef/go.mod h1:55mCznBcN9WQgrtgaAkv+p2LxeW/tQRdidyyE9D0I5k= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/VictoriaMetrics/fastcache v1.5.3/go.mod h1:+jv9Ckb+za/P1ZRg/sulP5Ni1v49daAVERr0H3CuscE= +github.com/VictoriaMetrics/fastcache v1.5.7 h1:4y6y0G8PRzszQUYIQHHssv/jgPHAb5qQuuDNdCbyAgw= +github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= +github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= +github.com/Workiva/go-datastructures v1.0.52 h1:PLSK6pwn8mYdaoaCZEMsXBpBotr4HHn9abU0yMQt0NI= +github.com/Workiva/go-datastructures v1.0.52/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= +github.com/Zilliqa/gozilliqa-sdk v1.2.1-0.20210927032600-4c733f2cb879 h1:/OXqInjRm8CEd81EEFCGJ5Q24TTlY1/qu6DQ0D91WPA= +github.com/Zilliqa/gozilliqa-sdk v1.2.1-0.20210927032600-4c733f2cb879/go.mod h1:XLd05IRvH+nQt2lLvW6I2pfWBtRYE4i8Tpx45xBrlUE= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 h1:rtI0fD4oG/8eVokGVPYJEW1F88p1ZNgXiEIs9thEE4A= +github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d/go.mod h1:icNx/6QdFblhsEjZehARqbNumymUT/ydwlLojFdv7Sk= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= +github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0= +github.com/btcsuite/btcd v0.0.0-20190315201642-aa6e0f35703c/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= +github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= +github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0 h1:Tvd0BfvqX9o823q1j2UZ/epQo09eJh6dTcRp79ilIN4= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0 h1:ZxaA6lo2EpxGddsA8JwWOcxlzRybb444sgmeJQMJGQE= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.0.1-0.20190104013014-3767db7a7e18/go.mod h1:HD5P3vAIAh+Y2GAxg0PrPN1P8WkepXGpjbUPDHJqqKM= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cosmos/cosmos-sdk v0.38.4 h1:jPZOvhMQkm7wwwzcLxuluhVpKfuIgddNGt999pAiz/Y= +github.com/cosmos/cosmos-sdk v0.38.4/go.mod h1:rzWOofbKfRt3wxiylmYWEFHnxxGj0coyqgWl2I9obAw= +github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d h1:49RLWk1j44Xu4fjHb6JFYmeUnDORVwHNkDxaQ0ctCVU= +github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= +github.com/cosmos/ledger-cosmos-go v0.11.1/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY= +github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/danieljoos/wincred v1.0.2/go.mod h1:SnuYRW9lp1oJrZX/dXJqr0cPK5gYXqx3EJbmjhLdK9U= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dchest/siphash v1.2.1 h1:4cLinnzVJDKxTCl9B01807Yiy+W7ZzVHj/KIroQRvT4= +github.com/dchest/siphash v1.2.1/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= +github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0= +github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/dop251/goja v0.0.0-20200219165308-d1232e640a87/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= +github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dvsekhvalnov/jose2go v0.0.0-20180829124132-7f401d37b68a/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM= +github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs= +github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= +github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/etcd-io/bbolt v1.3.3 h1:gSJmxrs37LgTqR/oyJBWok6k6SvXEUerFTbltIhXkBM= +github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/ethereum/go-ethereum v1.9.13/go.mod h1:qwN9d1GLyDh0N7Ab8bMGd0H9knaji2jOBm2RrMGjXls= +github.com/ethereum/go-ethereum v1.9.15/go.mod h1:slT8bPPRhXsyNTwHQxrOnjuTZ1sDXRajW11EkJ84QJ0= +github.com/ethereum/go-ethereum v1.9.24 h1:6AK+ORt3EMDO+FTjzXy/AQwHMbu52J2nYHIjyQX9azQ= +github.com/ethereum/go-ethereum v1.9.24/go.mod h1:JIfVb6esrqALTExdz9hRYvrP0xBDf6wCncIu1hNwHpM= +github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= +github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= +github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQDg5gKsWoLBOB0n+ZW8s599zru8FJ2/Y= +github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= +github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI= +github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gcash/bchd v0.14.7/go.mod h1:Gk/O1ktRVW5Kao0RsnVXp3bWxeYQadqawZ1Im9HE78M= +github.com/gcash/bchd v0.15.2/go.mod h1:k9wIjgwnhbrAw+ruIPZ2tHZMzfFNdyUnORZZX7lqXGY= +github.com/gcash/bchd v0.16.4 h1:+aq3sk3MDTLLwfDldvJaQBbpALCiDMH1bT32qIeHYos= +github.com/gcash/bchd v0.16.4/go.mod h1:gR67ljCexTNwbKYN3wjbRHi9lYLp4rMomy1UQ3E1USA= +github.com/gcash/bchlog v0.0.0-20180913005452-b4f036f92fa6 h1:3pZvWJ8MSfWstGrb8Hfh4ZpLyZNcXypcGx2Ju4ZibVM= +github.com/gcash/bchlog v0.0.0-20180913005452-b4f036f92fa6/go.mod h1:PpfmXTLfjRp7Tf6v/DCGTRXHz+VFbiRcsoUxi7HvwlQ= +github.com/gcash/bchutil v0.0.0-20190625002603-800e62fe9aff/go.mod h1:zXSP0Fg2L52wpSEDApQDQMiSygnQiK5HDquDl0a5BHg= +github.com/gcash/bchutil v0.0.0-20191012211144-98e73ec336ba/go.mod h1:nUIrcbbtEQdCsRwcp+j/CndDKMQE9Fi8p2F8cIZmIqI= +github.com/gcash/bchutil v0.0.0-20200229194731-128fc9884722/go.mod h1:wB++2ZcHUvGLN1OgO9swBmJK1vmyshJLW9SNS+apXwc= +github.com/gcash/bchutil v0.0.0-20200506001747-c2894cd54b33 h1:HNO6rKAfeYm6hE+0KXMfRomDZ8cQNlBmWirH8PSk9MY= +github.com/gcash/bchutil v0.0.0-20200506001747-c2894cd54b33/go.mod h1:wB++2ZcHUvGLN1OgO9swBmJK1vmyshJLW9SNS+apXwc= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2-0.20190517061210-b285ee9cfc6c/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.2-0.20200707131729-196ae77b8a26 h1:lMm2hD9Fy0ynom5+85/pbdkiYcBqM1JWmhpAXLmy0fw= +github.com/golang/snappy v0.0.2-0.20200707131729-196ae77b8a26/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64= +github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gosuri/uilive v0.0.3/go.mod h1:qkLSc0A5EXSP6B04TrN4oQoxqFI7A8XvoXSlJi8cwk8= +github.com/gosuri/uilive v0.0.4/go.mod h1:V/epo5LjjlDE5RJUcqx8dbw+zc93y5Ya3yg8tfZ74VI= +github.com/gosuri/uiprogress v0.0.1/go.mod h1:C1RTYn4Sc7iEyf6j8ft5dyoZ4212h8G1ol9QQluh5+0= +github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= +github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f h1:8N8XWLZelZNibkhM1FuF+3Ad3YIbgirjdMiVA0eUkaM= +github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= +github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= +github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/holiman/uint256 v1.1.1 h1:4JywC80b+/hSfljFlEBLHrrh+CIONLDz9NuFl0af4Mw= +github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag= +github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= +github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= +github.com/improbable-eng/grpc-web v0.9.1/go.mod h1:6hRR09jOEG81ADP5wCQju1z71g6OL4eEvELdran/3cs= +github.com/improbable-eng/grpc-web v0.12.0/go.mod h1:6hRR09jOEG81ADP5wCQju1z71g6OL4eEvELdran/3cs= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/itchyny/base58-go v0.1.0 h1:zF5spLDo956exUAD17o+7GamZTRkXOZlqJjRciZwd1I= +github.com/itchyny/base58-go v0.1.0/go.mod h1:SrMWPE3DFuJJp1M/RUhu4fccp/y9AlB8AL3o3duPToU= +github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v0.0.0-20181221193153-c0795c8afcf4/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= +github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= +github.com/joeqian10/neo-gogogo v0.0.0-20200611102831-c17de5e1f0f8 h1:C+PIS6p7oQ4DwT+1IJkIvS+BMLn9TodglcqcGzhE+fQ= +github.com/joeqian10/neo-gogogo v0.0.0-20200611102831-c17de5e1f0f8/go.mod h1:1fVDp4U1ROZQBRIooecbGNHHJpfs3bG9528sqlZ096g= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d/go.mod h1:JJNrCn9otv/2QP4D7SMJBgaleKpOf66PnW6F5WGNRIc= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= +github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0= +github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= +github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c h1:1RHs3tNxjXGHeul8z2t6H2N2TlAqpKe5yryJztRx4Jk= +github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/ontio/go-bip32 v0.0.0-20190520025953-d3cea6894a2b h1:UQDN12BzdWhXQL0t2QcRixHqAIG+JKNvQ20DhrIODtU= +github.com/ontio/go-bip32 v0.0.0-20190520025953-d3cea6894a2b/go.mod h1:J0eVc7BEMmVVXbGv9PHoxjRSEwOwLr0qfzPk8Rdl5iw= +github.com/ontio/ontology v1.11.0 h1:0T/hxFDHQqRcs1+yEdgaym5YIvGx5yebOsHYdKVWgHI= +github.com/ontio/ontology v1.11.0/go.mod h1:Qw74bfTBlIQka+jQX4nXuWvyOYGGt368/V7XFxaf4tY= +github.com/ontio/ontology-crypto v1.0.9 h1:6fxBsz3W4CcdJk4/9QO7j0Qq7NdlP2ixPrViu8XpzzM= +github.com/ontio/ontology-crypto v1.0.9/go.mod h1:h/jeqqb9Ma/Leszxqh6zY3eTF2yks44hyRKikMni+YQ= +github.com/ontio/ontology-eventbus v0.9.1 h1:nt3AXWx3gOyqtLiU4EwI92Yc4ik/pWHu9xRK15uHSOs= +github.com/ontio/ontology-eventbus v0.9.1/go.mod h1:hCQIlbdPckcfykMeVUdWrqHZ8d30TBdmLfXCVWGkYhM= +github.com/ontio/wagon v0.4.1/go.mod h1:oTPdgWT7WfPlEyzVaHSn1vQPMSbOpQPv+WphxibWlhg= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6 h1:lNCW6THrCKBiJBpz8kbVGjC7MgdCGKwuvBgc7LoD6sw= +github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CFcDWnWD9XkenwhI= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.6.0 h1:aetoXYr0Tv7xRU/V4B4IZJ2QcbtMUFoNb3ORp7TzIK4= +github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/polynetwork/poly v0.0.0-20200715030435-4f1d1a0adb44 h1:QXznsPhBBa1vY6Fhav8S9+qoHBi8iGy6g1VeIMdYglI= +github.com/polynetwork/poly v0.0.0-20200715030435-4f1d1a0adb44/go.mod h1:UzlGEWk0eCGsuMJOZfBoZjRbmu4Yw/SudKAIFe1gPnY= +github.com/polynetwork/poly-go-sdk v0.0.0-20200817120957-365691ad3493 h1:wob4aH5NxiDFIOWlpKbmoIb88QOccDNa1+rl93czjr8= +github.com/polynetwork/poly-go-sdk v0.0.0-20200817120957-365691ad3493/go.mod h1:a1wMo/VFoUAKX2yVjipvFug6Yu5BPhf/2tP5xywqfIc= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.5.0 h1:Ctq0iGpCmr3jeP77kbF2UxgvRwzWWz+4Bh9/vJTyg1A= +github.com/prometheus/client_golang v1.5.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rakyll/statik v0.1.6/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/scylladb/go-set v1.0.2/go.mod h1:DkpGd78rljTxKAnTDPFqXSGxvETQnJyuSOQwsHycqfs= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shirou/gopsutil v2.20.5-0.20200531151128-663af789c085+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v2.20.5+incompatible h1:tYH07UPoQt0OCQdgWWMgYHy3/a9bcxNpBIysykNIP7I= +github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa/go.mod h1:oJyF+mSPHbB5mVY2iO9KV3pTt/QbIkGaO8gQ2WrDbP4= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.0.1-0.20190317074736-539464a789e9/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.2.1 h1:qgMbHoJbPbw579P+1zVY+6n4nIFuIchaIjzZ/I/Yq8M= +github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4= +github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= +github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE= +github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= +github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM= +github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= +github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca h1:Ld/zXl5t4+D69SiV4JoN7kkfvJdOWlPpfxrzxpLMoUk= +github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= +github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= +github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= +github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U= +github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk= +github.com/tendermint/go-amino v0.14.1/go.mod h1:i/UKE5Uocn+argJJBb12qTZsCDBcAYMbR92AaJVmKso= +github.com/tendermint/go-amino v0.15.1 h1:D2uk35eT4iTsvJd9jWIetzthE5C0/k2QmMFkCN+4JgQ= +github.com/tendermint/go-amino v0.15.1/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= +github.com/tendermint/iavl v0.13.2 h1:O1m08/Ciy53l9IYmf75uIRVvrNsfjEbre8u/yCu/oqk= +github.com/tendermint/iavl v0.13.2/go.mod h1:vE1u0XAGXYjHykd4BLp8p/yivrw2PF1TuoljBcsQoGA= +github.com/tendermint/tendermint v0.33.2/go.mod h1:25DqB7YvV1tN3tHsjWoc2vFtlwICfrub9XO6UBO+4xk= +github.com/tendermint/tendermint v0.33.3 h1:6lMqjEoCGejCzAghbvfQgmw87snGSqEhDTo/jw+W8CI= +github.com/tendermint/tendermint v0.33.3/go.mod h1:25DqB7YvV1tN3tHsjWoc2vFtlwICfrub9XO6UBO+4xk= +github.com/tendermint/tm-db v0.4.1/go.mod h1:JsJ6qzYkCGiGwm5GHl/H5GLI9XLb6qZX7PRe425dHAY= +github.com/tendermint/tm-db v0.5.0 h1:qtM5UTr1dlRnHtDY6y7MZO5Di8XAE2j3lc/pCnKJ5hQ= +github.com/tendermint/tm-db v0.5.0/go.mod h1:lSq7q5WRR/njf1LnhiZ/lIJHk2S8Y1Zyq5oP/3o9C2U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tyler-smith/go-bip39 v1.0.2 h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1OlOT8= +github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/ybbus/jsonrpc v2.1.2+incompatible h1:V4mkE9qhbDQ92/MLMIhlhMSbz8jNXdagC3xBR5NDwaQ= +github.com/ybbus/jsonrpc v2.1.2+incompatible/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE= +github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zquestz/grab v0.0.0-20190224022517-abcee96e61b1 h1:1qKTeMTSIEvRIjvVYzgcRp0xVp0eoiRTTiHSncb5gD8= +github.com/zquestz/grab v0.0.0-20190224022517-abcee96e61b1/go.mod h1:bslhAiUxakrA6z6CHmVyvkfpnxx18RJBwVyx2TluJWw= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mobile v0.0.0-20200801112145-973feb4309de/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8 h1:AvbQYmiaaaza3cW3QXRyPo5kYgpFIzOAfeAAN7m3qQ4= +golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84 h1:pSLkPbrjnPyLDYUO2VM9mDLqo2V6CFBY84lFSZAfoi4= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= +gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200316214253-d7b0ff38cac9/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= +gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200603215123-a4a8cb9d2cbc/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= +gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/hooks/post_push b/hooks/post_push new file mode 100644 index 0000000..4575c25 --- /dev/null +++ b/hooks/post_push @@ -0,0 +1,6 @@ +#!/bin/bash + +if [ $SOURCE_BRANCH == "main" ]; then + docker tag $IMAGE_NAME $DOCKER_REPO:experimental-${SOURCE_COMMIT:0:7} + docker push $DOCKER_REPO:experimental-${SOURCE_COMMIT:0:7} +fi diff --git a/main.go b/main.go new file mode 100644 index 0000000..56deda4 --- /dev/null +++ b/main.go @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2021 Zilliqa + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package main + +import "github.com/polynetwork/zilliqa-relayer/cmd" + +func main() { + cmd.Execute() +} diff --git a/run-docker.sh b/run-docker.sh new file mode 100755 index 0000000..9a53340 --- /dev/null +++ b/run-docker.sh @@ -0,0 +1,11 @@ +#!/bin/sh +docker stop zilliqa-relayer +docker rm zilliqa-relayer + +docker run -d \ +-v $(pwd)/persistence:/app/persistence \ +-v $(pwd)/secrets/config.local.yaml:/app/config.local.yaml \ +-v $(pwd)/secrets/target_contracts.json:/app/target_contracts.json \ +-v $(pwd)/secrets/poly.wallet:/app/poly.wallet \ +-v $(pwd)/secrets/zilliqa.wallet:/app/zilliqa.wallet \ +--name zilliqa-relayer polynetwork/zilliqa-relayer diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..052a2ce --- /dev/null +++ b/run.sh @@ -0,0 +1,2 @@ +#!/bin/sh +./zilliqa-relayer run \ No newline at end of file diff --git a/service/common.go b/service/common.go new file mode 100644 index 0000000..47be13e --- /dev/null +++ b/service/common.go @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 Zilliqa + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package service + +import ( + log "github.com/sirupsen/logrus" + "os" + "os/signal" + "syscall" +) + +func WaitToExit() { + exit := make(chan bool, 0) + sc := make(chan os.Signal, 1) + signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP) + go func() { + for sig := range sc { + log.Infof("Zilliqa Relayer received exit signal: %v.", sig.String()) + close(exit) + break + } + }() + <-exit +} diff --git a/service/nonce_manager.go b/service/nonce_manager.go new file mode 100644 index 0000000..d714ac6 --- /dev/null +++ b/service/nonce_manager.go @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2021 Zilliqa + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package service + +import ( + "encoding/json" + "github.com/Zilliqa/gozilliqa-sdk/keytools" + "github.com/Zilliqa/gozilliqa-sdk/provider" + "github.com/Zilliqa/gozilliqa-sdk/transaction" + "github.com/Zilliqa/gozilliqa-sdk/util" + polytypes "github.com/polynetwork/poly/core/types" + common2 "github.com/polynetwork/poly/native/service/cross_chain_manager/common" + "github.com/polynetwork/zilliqa-relayer/config" + "github.com/polynetwork/zilliqa-relayer/tools" + log "github.com/sirupsen/logrus" + "math" + "strconv" + "sync" + "time" +) + +const AuditLogFile = "audit.log" + +type NonceAndSender struct { + Sender *ZilSender + LocalNonce int64 +} + +type TransactionWithAge struct { + Txn *transaction.Transaction + StartTxBlock uint64 + Age int +} + +type NonceManager struct { + UpdateInterval int64 + ZilClient *provider.Provider + // address => hash => transaction + SentTransactions map[string]map[string]TransactionWithAge + LockSentTransaction sync.Mutex + // address => list of transaction hash + ConfirmedTransactions map[string][]string + // private key => nonce and sender + ZilSenderMap map[string]*NonceAndSender + SenderPrivateKeys []string + CurrentIndex int + Cfg *config.Config +} + +func (nm *NonceManager) Run() { + log.Infof("starting nonce manager...") + for { + time.Sleep(time.Second * time.Duration(nm.UpdateInterval)) + nm.stat() + } +} + +func (nm *NonceManager) commitHeader(hdr *polytypes.Header) bool { + nm.LockSentTransaction.Lock() + defer nm.LockSentTransaction.Unlock() + currentSenderPrivateKey := nm.SenderPrivateKeys[nm.CurrentIndex] + nm.CurrentIndex++ + if nm.CurrentIndex > len(nm.SenderPrivateKeys)-1 { + nm.CurrentIndex = 0 + } + currentSender := nm.ZilSenderMap[currentSenderPrivateKey].Sender + log.Infof("NonceManager - commitHeader use sender %s", currentSender.address) + nonce := strconv.FormatUint(uint64(nm.ZilSenderMap[currentSenderPrivateKey].LocalNonce+1), 10) + txn, err := currentSender.commitHeaderWithNonce(hdr, nonce) + if err != nil { + log.Warnf("NonceManager - commitHeader error %s", err.Error()) + return false + } + + hash, _ := txn.Hash() + + // handle nonce + nm.ZilSenderMap[currentSenderPrivateKey] = &NonceAndSender{ + Sender: nm.ZilSenderMap[currentSenderPrivateKey].Sender, + LocalNonce: nm.ZilSenderMap[currentSenderPrivateKey].LocalNonce + 1, + } + + outerMap := nm.SentTransactions[currentSender.address] + if outerMap == nil { + outerMap = make(map[string]TransactionWithAge) + } + outerMap[util.EncodeHex(hash)] = TransactionWithAge{ + Txn: txn, + Age: 0, + } + nm.SentTransactions[currentSender.address] = outerMap + return true +} + +type TransactionAuditLog struct { + Time time.Time + PayLoad string + Error string +} + +func (nm *NonceManager) commitDepositEventsWithHeader(header *polytypes.Header, param *common2.ToMerkleValue, headerProof string, anchorHeader *polytypes.Header, polyTxHash string, rawAuditPath []byte) bool { + nm.LockSentTransaction.Lock() + defer nm.LockSentTransaction.Unlock() + currentSenderPrivateKey := nm.SenderPrivateKeys[nm.CurrentIndex] + nm.CurrentIndex++ + if nm.CurrentIndex > len(nm.SenderPrivateKeys)-1 { + nm.CurrentIndex = 0 + } + + currentSender := nm.ZilSenderMap[currentSenderPrivateKey].Sender + log.Infof("NonceManager - commitDepositEventsWithHeader use sender %s", currentSender.address) + nonce := strconv.FormatUint(uint64(nm.ZilSenderMap[currentSenderPrivateKey].LocalNonce+1), 10) + txn, err := currentSender.commitDepositEventsWithHeaderWithNonce(header, param, headerProof, anchorHeader, polyTxHash, rawAuditPath, nonce) + var auditLog TransactionAuditLog + if err != nil { + auditLog = TransactionAuditLog{ + Time: time.Now(), + Error: err.Error(), + } + } else { + transactionRaw, _ := json.Marshal(txn) + auditLog = TransactionAuditLog{ + Time: time.Now(), + PayLoad: string(transactionRaw), + } + } + + auditLogRaw, _ := json.Marshal(auditLog) + tools.AppendToFile(AuditLogFile, string(auditLogRaw)) + + if err != nil { + log.Warnf("NonceManager - commitDepositEventsWithHeaderWithNonc e error %s", err.Error()) + return false + } + + hash, _ := txn.Hash() + + // handle nonce + nm.ZilSenderMap[currentSenderPrivateKey] = &NonceAndSender{ + Sender: nm.ZilSenderMap[currentSenderPrivateKey].Sender, + LocalNonce: nm.ZilSenderMap[currentSenderPrivateKey].LocalNonce + 1, + } + + outerMap := nm.SentTransactions[currentSender.address] + if outerMap == nil { + outerMap = make(map[string]TransactionWithAge) + } + outerMap[util.EncodeHex(hash)] = TransactionWithAge{ + Txn: txn, + Age: 0, + } + nm.SentTransactions[currentSender.address] = outerMap + return true +} + +func (nm *NonceManager) stat() { + txBlock, err := nm.ZilClient.GetLatestTxBlock() + if err != nil { + log.Warnf("NonceManager - get current tx block number error: %s", err.Error()) + return + } + currentTxEpoch, _ := strconv.ParseUint(txBlock.Header.BlockNum, 10, 64) + log.Infof("NonceManager - current tx block number is: %s", txBlock.Header.BlockNum) + nm.LockSentTransaction.Lock() + defer nm.LockSentTransaction.Unlock() + for _, key := range nm.SenderPrivateKeys { + addr := keytools.GetAddressFromPrivateKey(util.DecodeHex(key)) + balAndNonce, err := nm.ZilClient.GetBalance(addr) + if err != nil { + log.Warnf("NonceManager - get nonce for address %s error %s", addr, err.Error()) + continue + } + + // print some stat info about this address + log.Infof("NonceManager - address %s, local nonce = %d, remote nonce = %d", addr, nm.ZilSenderMap[key].LocalNonce, balAndNonce.Nonce) + log.Infof("NonceManager - sent transactions: %+v", nm.SentTransactions[addr]) + log.Infof("NonceManager - confimred transactions: %+v", len(nm.ConfirmedTransactions[addr])) + + // check sent transactions + log.Infof("NonceManager - check sent transactions") + var confirmedTxn []string + + sentTransactionMap := nm.SentTransactions[addr] + for hash, txn := range sentTransactionMap { + log.Infof("NonceManager - check transaction %s", hash) + _, err := nm.ZilClient.GetTransaction(hash) + + if err == nil { + log.Infof("NonceManager - transaction %s confirmed", hash) + confirmedTxn = append(confirmedTxn, hash) + } else { + // if start block is 0, try to give it a number first + if sentTransactionMap[hash].StartTxBlock == 0 { + log.Infof("NonceManager - stat try to determine start tx block for hash: %s", hash) + sentTransactionMap[hash] = TransactionWithAge{ + Txn: txn.Txn, + StartTxBlock: currentTxEpoch, + Age: 0, + } + } else { + log.Warnf("NonceManager - stat already has inserted epoch, update age, hash is %s", hash) + age := 0 + if currentTxEpoch > sentTransactionMap[hash].StartTxBlock { + age = int(currentTxEpoch - sentTransactionMap[hash].StartTxBlock) + } + sentTransactionMap[hash] = TransactionWithAge{ + Txn: txn.Txn, + StartTxBlock: txn.StartTxBlock, + Age: age, + } + } + } + + } + + for _, hash := range confirmedTxn { + delete(sentTransactionMap, hash) + nm.ConfirmedTransactions[addr] = append(nm.ConfirmedTransactions[addr], hash) + } + nm.SentTransactions[addr] = sentTransactionMap + + // print some stat info about this address again + log.Infof("NonceManager - sent transactions: %+v", nm.SentTransactions[addr]) + log.Infof("NonceManager - confimred transactions: %+v", len(nm.ConfirmedTransactions[addr])) + + // detect dead transactions + log.Infof("NonceManager - stat start to detect dead transactions") + currentNonce := uint64(math.MaxUint64) + for hash, txn := range nm.SentTransactions[addr] { + if txn.Age > nm.Cfg.ZilConfig.MaxExistTxEpoch { + log.Warnf("NonceManager - stat found dead transaction, hash: %s, nonce is %s", hash, txn.Txn.Nonce) + log.Warnf("NonceManager - stat current nonce is: %d", currentNonce) + nonce, _ := strconv.ParseUint(txn.Txn.Nonce, 10, 64) + if currentNonce > nonce { + log.Warnf("NonceManager - stat replace current nonce with it") + currentNonce = nonce + } + } + } + + if currentNonce == math.MaxUint64 { + log.Infof("NonceManager - stat no dead found") + } else { + log.Infof("NonceManager - stat dead transaction, bad nonce is: %d, start to resend transactions", currentNonce) + for hash, txn := range nm.SentTransactions[addr] { + nonce, _ := strconv.ParseUint(txn.Txn.Nonce, 10, 64) + if nonce >= currentNonce { + log.Infof("NonceManager - stat start to resend transaction %s, nonce %d", hash, nonce) + // todo handle error + nm.ZilClient.CreateTransaction(txn.Txn.ToTransactionPayload()) + nm.SentTransactions[addr][hash] = TransactionWithAge{ + Txn: txn.Txn, + StartTxBlock: currentTxEpoch, + Age: 0, + } + } + } + + } + } +} diff --git a/service/poly2zil.go b/service/poly2zil.go new file mode 100644 index 0000000..4cbd4bc --- /dev/null +++ b/service/poly2zil.go @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2021 Zilliqa + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package service + +import ( + "encoding/hex" + "encoding/json" + "github.com/Zilliqa/gozilliqa-sdk/bech32" + "github.com/Zilliqa/gozilliqa-sdk/util" + "github.com/polynetwork/poly/common" + "github.com/polynetwork/poly/consensus/vbft/config" + polytypes "github.com/polynetwork/poly/core/types" + common2 "github.com/polynetwork/poly/native/service/cross_chain_manager/common" + "github.com/polynetwork/zilliqa-relayer/config" + "github.com/polynetwork/zilliqa-relayer/tools" + log "github.com/sirupsen/logrus" + "strconv" + "time" +) + +func (p *PolySyncManager) MonitorChain() { + if !p.init() { + log.Errorf("PolySyncManager MonitorChain - init error\n") + return + } + + log.Infof("PolySyncManager MonitorChain - start scan block at height: %d\n", p.currentHeight) + monitorTicker := time.NewTicker(time.Duration(p.cfg.PolyConfig.PolyMonitorInterval) * time.Second) + var blockHandleResult bool + for { + start: + log.Infof("PolySyncManager MonitorChain - current height: %d\n", p.currentHeight) + select { + case <-monitorTicker.C: + latestHeight, err := p.polySdk.GetCurrentBlockHeight() + if err != nil { + log.Errorf("PolySyncManager MonitorChain - cannot get node hight, err: %s\n", err.Error()) + continue + } + latestHeight-- + if latestHeight-p.currentHeight < config.OntUsefulBlockNum { + log.Infof("PolySyncManager MonitorChain - poly chain skip current height: %d", latestHeight) + continue + } + log.Infof("PolySyncManager MonitorChain - poly chain current height: %d", latestHeight) + blockHandleResult = true + for p.currentHeight <= latestHeight-config.OntUsefulBlockNum { + blockHandleResult = p.handleDepositEvents(p.currentHeight, latestHeight) + if blockHandleResult { + p.currentHeight++ + if err = p.db.UpdatePolyHeight(p.currentHeight - 1); err != nil { + log.Errorf("PolySyncManager MonitorChain - failed to save height of poly: %v", err) + } + } else { + goto start + } + } + + case <-p.exitChan: + return + + } + } +} + +func (p *PolySyncManager) handleDepositEvents(height, latest uint32) bool { + log.Infof("PolySyncManager handleDepositEvents at height %d, latest height %d\n", height, latest) + lastEpoch := p.findLatestHeight() + hdr, err := p.polySdk.GetHeaderByHeight(height + 1) + if err != nil { + log.Errorf("PolySyncManager handleBlockHeader - GetNodeHeader on height :%d failed", height) + return false + } + isCurr := lastEpoch < height+1 + info := &vconfig.VbftBlockInfo{} + if err := json.Unmarshal(hdr.ConsensusPayload, info); err != nil { + log.Errorf("PolySyncManager failed to unmarshal ConsensusPayload for height %d: %v", height+1, err) + return false + } + isEpoch := hdr.NextBookkeeper != common.ADDRESS_EMPTY && info.NewChainConfig != nil + var ( + anchor *polytypes.Header + hp string + ) + if !isCurr { + anchor, _ = p.polySdk.GetHeaderByHeight(lastEpoch + 1) + proof, _ := p.polySdk.GetMerkleProof(height+1, lastEpoch+1) + hp = proof.AuditPath + } else if isEpoch { + anchor, _ = p.polySdk.GetHeaderByHeight(height + 2) + proof, _ := p.polySdk.GetMerkleProof(height+1, height+2) + hp = proof.AuditPath + } + + cnt := 0 + events, err := p.polySdk.GetSmartContractEventByBlock(height) + for err != nil { + log.Errorf("PolySyncManager handleDepositEvents - get block event at height:%d error: %s", height, err.Error()) + return false + } + for _, event := range events { + for _, notify := range event.Notify { + log.Infof("PolySyncManager handleDepositEvents get notify address: %s\n", notify.ContractAddress) + if notify.ContractAddress == p.cfg.PolyConfig.EntranceContractAddress { + states := notify.States.([]interface{}) + method, _ := states[0].(string) + if method != "makeProof" { + continue + } + if uint64(states[2].(float64)) != p.cfg.ZilConfig.SideChainId { + continue + } + proof, err := p.polySdk.GetCrossStatesProof(hdr.Height-1, states[5].(string)) + if err != nil { + log.Errorf("handleDepositEvents - failed to get proof for key %s: %v", states[5].(string), err) + continue + } + auditpath, _ := hex.DecodeString(proof.AuditPath) + value, _, _, _ := tools.ParseAuditpath(auditpath) + param := &common2.ToMerkleValue{} + if err := param.Deserialization(common.NewZeroCopySource(value)); err != nil { + log.Errorf("handleDepositEvents - failed to deserialize MakeTxParam (value: %x, err: %v)", value, err) + continue + } + var isTarget bool + if len(p.cfg.TargetContracts) > 0 { + // target address configuration should include those contracts are allowed to be triggered by + // cross chain transactions. e.g LockProxy + toContractStr, _ := bech32.ToBech32Address(util.EncodeHex(param.MakeTxParam.ToContractAddress)) + for _, v := range p.cfg.TargetContracts { + toChainIdArr, ok := v[toContractStr] + if ok { + if len(toChainIdArr["inbound"]) == 0 { + isTarget = true + break + } + for _, id := range toChainIdArr["inbound"] { + if id == param.FromChainID { + isTarget = true + break + } + } + if isTarget { + break + } + } + } + if !isTarget { + continue + } + } + cnt++ + p.nonceManager.commitDepositEventsWithHeader(hdr, param, hp, anchor, event.TxHash, auditpath) + } + } + } + + if cnt == 0 && isEpoch && isCurr { + return p.nonceManager.commitHeader(hdr) + } + + return true +} + +func (p *PolySyncManager) selectSender() *ZilSender { +S: + log.Info("start select sender") + for _, sender := range p.senders { + sender.mu.Lock() + if !sender.inUse { + sender.inUse = true + sender.mu.Unlock() + log.Infof("sender %s selected", sender.address) + return sender + } + sender.mu.Unlock() + } + log.Warn("Current no zilliqa sender can use, sleep 10 seconds and reselect") + time.Sleep(time.Second * 10) + goto S +} + +type EpochStartHeight struct { + CurEpochStartHeight string `json:"curEpochStartHeight"` +} + +type EpochStartHeightRep struct { + Id string `json:"id"` + JsonRpc string `json:"jsonrpc"` + Result EpochStartHeight `json:"result"` +} + +type FromChainTxExist struct { + FromChainTxExist map[string]interface{} `json:"fromChainTxExist"` +} + +type FromChainTxExistRsp struct { + Id string `json:"id"` + JsonRpc string `json:"jsonrpc"` + Result *FromChainTxExist `json:"result"` +} + +// ZilCrossChainManager.scilla +// check fromChainTxExist map +func (z *ZilSender) checkIfFromChainTxExist(fromChainId uint64, fromTx string) bool { + ccm, err := bech32.FromBech32Addr(z.cfg.ZilConfig.CrossChainManagerContract) + if err != nil { + log.Errorf("PolySyncManager checkIfFromChainTxExist - failed to convert cross chain manager contract address: %s\n", err.Error()) + return false + } + + state, err1 := z.zilSdk.GetSmartContractSubState(ccm, "fromChainTxExist", []interface{}{strconv.FormatUint(fromChainId, 10), fromTx}) + if err1 != nil { + log.Errorf("PolySyncManager checkIfFromChainTxExist - failed to get state of fromChainTxExist: %s\n", err1.Error()) + return false + } + + var fromChainTxExistRsp FromChainTxExistRsp + err2 := json.Unmarshal([]byte(state), &fromChainTxExistRsp) + if err2 != nil { + log.Errorf("PolySyncManager checkIfFromChainTxExist - failed to parse fromChainTxExistRsp: %s\n", err2.Error()) + return false + } + + if fromChainTxExistRsp.Result == nil { + return false + } else { + return true + } +} + +// ZilCrossChainManager.scilla +// curEpochStartHeight +func (p *PolySyncManager) findLatestHeight() uint32 { + ccm, err := bech32.FromBech32Addr(p.cfg.ZilConfig.CrossChainManagerContract) + if err != nil { + log.Errorf("PolySyncManager FindLatestHeight - failed to convert cross chain manager contract address: %s\n", err.Error()) + return 0 + } + curEpochStartHeight, err1 := p.zilSdk.GetSmartContractSubState(ccm, "curEpochStartHeight", []interface{}{}) + if err1 != nil { + log.Errorf("PolySyncManager FindLatestHeight - faild to get current epoch start height: %s\n", err1.Error()) + return 0 + } + + var epochStartHeightRep EpochStartHeightRep + err3 := json.Unmarshal([]byte(curEpochStartHeight), &epochStartHeightRep) + if err3 != nil { + log.Errorf("PolySyncManager FindLatestHeight - faild to unmarshal current epoch start height: %s\n", err3.Error()) + return 0 + } + + height, err2 := strconv.ParseUint(epochStartHeightRep.Result.CurEpochStartHeight, 10, 32) + if err2 != nil { + log.Errorf("PolySyncManager FindLatestHeight - failed to parse epoch start height: %s\n", err2.Error()) + return 0 + } + return uint32(height) +} diff --git a/service/poly2zil_test.go b/service/poly2zil_test.go new file mode 100644 index 0000000..25f8ff0 --- /dev/null +++ b/service/poly2zil_test.go @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2021 Zilliqa + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package service + +import ( + "fmt" + "github.com/Zilliqa/gozilliqa-sdk/provider" + "github.com/magiconair/properties/assert" + "github.com/polynetwork/zilliqa-relayer/config" + "testing" +) + +var p *PolySyncManager +var s *ZilSender + +func init() { + zilSdk := provider.NewProvider("https://polynetworkcc3dcb2-5-api.dev.z7a.xyz") + p = &PolySyncManager{ + zilSdk: zilSdk, + cfg: &config.Config{ZilConfig: &config.ZILConfig{ + CrossChainManagerContract: "zil1ur4vwcmcz3jqypksgq7qeju2sk5jrskzaadau5", + }}, + } + s = &ZilSender{ + cfg: &config.Config{ZilConfig: &config.ZILConfig{ + CrossChainManagerContract: "zil1ur4vwcmcz3jqypksgq7qeju2sk5jrskzaadau5", + }}, + zilSdk: zilSdk, + address: "zil1ur4vwcmcz3jqypksgq7qeju2sk5jrskzaadau5", + } +} + +func TestPolySyncManager_FindLatestHeight(t *testing.T) { + fmt.Println(p.findLatestHeight()) +} + +func TestZilSender_CheckIfFromChainTxExist(t *testing.T) { + exist := s.checkIfFromChainTxExist(3, "0x00ca93f8738111a063d8ab7221f47c70a4cade0ca4a2829df494cd4b5e231bd6") + assert.Equal(t, exist, true) + + exist = s.checkIfFromChainTxExist(3, "0x00ca93f8738111a063d8ab7221f47c70a4cade0ca4a2829df494cd4b5e231bd7") + assert.Equal(t, exist, false) + +} diff --git a/service/polymanager.go b/service/polymanager.go new file mode 100644 index 0000000..dd95463 --- /dev/null +++ b/service/polymanager.go @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2021 Zilliqa + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package service + +import ( + "encoding/json" + "errors" + "github.com/Zilliqa/gozilliqa-sdk/account" + "github.com/Zilliqa/gozilliqa-sdk/crosschain/polynetwork" + "github.com/Zilliqa/gozilliqa-sdk/crypto" + "github.com/Zilliqa/gozilliqa-sdk/provider" + "github.com/ontio/ontology/common/log" + "github.com/polynetwork/poly-go-sdk" + "github.com/polynetwork/zilliqa-relayer/config" + "github.com/polynetwork/zilliqa-relayer/db" + "github.com/polynetwork/zilliqa-relayer/tools" + "strings" +) + +type PolySyncManager struct { + currentHeight uint32 + polySdk *poly_go_sdk.PolySdk + exitChan chan int + cfg *config.Config + db *db.BoltDB + + zilSdk *provider.Provider + crossChainManager string + crossChainManagerProxy string + senders []*ZilSender + nonceManager *NonceManager +} + +func (p *PolySyncManager) init() bool { + if p.currentHeight > 0 { + log.Infof("PolySyncManager init - start height from flag: %d", p.currentHeight) + return true + } + + p.currentHeight = p.db.GetPolyHeight() + log.Infof("PolySyncManager init - get poly height from local storage: %d", p.currentHeight) + latestHeight := p.findLatestHeight() + log.Infof("PolySyncManager init - get poly height from cross chain manager contract: %d", latestHeight) + if latestHeight > p.currentHeight { + p.currentHeight = latestHeight + return true + } + log.Infof("PolySyncManager init - start height from flag: %d", p.currentHeight) + return true +} + +func (p *PolySyncManager) Run(enable bool) { + if enable { + go p.MonitorChain() + go p.nonceManager.Run() + } +} + +func NewPolySyncManager(cfg *config.Config, zilSdk *provider.Provider, polySdk *poly_go_sdk.PolySdk, boltDB *db.BoltDB, crossChainManager, crossChainManagerProxy string) (*PolySyncManager, error) { + keystores, err := tools.ReadLine(cfg.ZilConfig.KeyStorePath) + keystorepwdset := cfg.ZilConfig.KeyStorePwdSet + if err != nil { + return nil, err + } + descryptor := crypto.NewDefaultKeystore() + + var senders []*ZilSender + var privateKeys []string + zilSenderMap := make(map[string]*NonceAndSender, 0) + + for _, keystore := range keystores { + var ks crypto.KeystoreV3 + err1 := json.Unmarshal([]byte(keystore), &ks) + if err1 != nil { + return nil, err1 + } + pwd := keystorepwdset[strings.ToLower(ks.Address)] + if pwd == nil { + return nil, errors.New("NewPolySyncManager - there is no password for zilliqa.wallet: " + ks.Address) + } + privateKey, err2 := descryptor.DecryptPrivateKey(keystore, pwd.(string)) + if err2 != nil { + return nil, errors.New("NewPolySyncManager - descrypt zilliqa.wallet error: " + err2.Error()) + } + + // init cross chain smart contract proxy + wallet := account.NewWallet() + wallet.AddByPrivateKey(privateKey) + log.Infof("NewPolySyncManager get zilliqa wallet: %s", wallet.DefaultAccount.Address) + proxy := &polynetwork.Proxy{ + ProxyAddr: crossChainManagerProxy, + ImplAddr: crossChainManager, + Wallet: wallet, + Client: zilSdk, + ChainId: cfg.ZilConfig.ZilChainId, + MsgVersion: cfg.ZilConfig.ZilMessageVersion, + } + + addr := strings.Replace(ks.Address, "0x", "", 1) + sender := &ZilSender{ + cfg: cfg, + zilSdk: zilSdk, + address: addr, + privateKey: privateKey, + polySdk: polySdk, + crossChainProxy: proxy, + inUse: false, + } + + senders = append(senders, sender) + + balAndNonce, err3 := zilSdk.GetBalance(addr) + if err3 != nil { + log.Infof("NewPolySyncManager get address %s nonce error %s", addr, err3.Error()) + continue + } + + privateKeyAndNonce := &NonceAndSender{ + Sender: sender, + LocalNonce: balAndNonce.Nonce, + } + + privateKeys = append(privateKeys, privateKey) + zilSenderMap[privateKey] = privateKeyAndNonce + } + + nonceManager := &NonceManager{ + UpdateInterval: 30, + ZilClient: zilSdk, + SentTransactions: make(map[string]map[string]TransactionWithAge), + ConfirmedTransactions: make(map[string][]string), + SenderPrivateKeys: privateKeys, + ZilSenderMap: zilSenderMap, + CurrentIndex: 0, + Cfg: cfg, + } + + return &PolySyncManager{ + currentHeight: cfg.PolyConfig.PolyStartHeight, + polySdk: polySdk, + exitChan: make(chan int), + cfg: cfg, + db: boltDB, + zilSdk: zilSdk, + crossChainManager: crossChainManager, + crossChainManagerProxy: crossChainManagerProxy, + senders: senders, + nonceManager: nonceManager, + }, nil +} diff --git a/service/zil2poly.go b/service/zil2poly.go new file mode 100644 index 0000000..d617ecb --- /dev/null +++ b/service/zil2poly.go @@ -0,0 +1,549 @@ +/* + * Copyright (C) 2021 Zilliqa + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package service + +import ( + "bytes" + "encoding/json" + "fmt" + "math/big" + "strconv" + "strings" + "time" + + "github.com/Zilliqa/gozilliqa-sdk/bech32" + "github.com/Zilliqa/gozilliqa-sdk/core" + "github.com/Zilliqa/gozilliqa-sdk/util" + "github.com/polynetwork/poly/common" + scom "github.com/polynetwork/poly/native/service/header_sync/common" + autils "github.com/polynetwork/poly/native/service/utils" + "github.com/polynetwork/zilliqa-relayer/tools" + log "github.com/sirupsen/logrus" +) + +/** + * handle new block: + * 1. commit tx block and ds block + * 2. filter deposit event, put into local database + * 3. from database, handle deposit event, get proof and commit to poly + */ + +func (s *ZilliqaSyncManager) MonitorChain() { + log.Infof("ZilliqaSyncManager MonitorChain - start scan block at height: %d\n", s.currentHeight) + fetchBlockTicker := time.NewTicker(time.Duration(s.cfg.ZilConfig.ZilMonitorInterval) * time.Second) + var blockHandleResult bool + for { + select { + case <-fetchBlockTicker.C: + txBlock, err := s.zilSdk.GetLatestTxBlock() + if err != nil { + log.Errorf("ZilliqaSyncManager MonitorChain - cannot get node hight, err: %s\n", err.Error()) + continue + } + log.Infof("ZilliqaSyncManager MonitorChain - current tx block height: %s\n", txBlock.Header.BlockNum) + blockNumber, err2 := strconv.ParseUint(txBlock.Header.BlockNum, 10, 32) + if err2 != nil { + log.Errorf("ZilliqaSyncManager MonitorChain - cannot parse block height, err: %s\n", err2.Error()) + } + if s.currentHeight >= blockNumber { + log.Infof("ZilliqaSyncManager MonitorChain - current height is not changed, skip") + continue + } + + blockHandleResult = true + for s.currentHeight < blockNumber { + if s.debugInfo { + s.dumpPendingHeaders() + } + if !s.handleNewBlock(s.currentHeight + 1) { + break + } + s.currentHeight++ + + if uint32(len(s.header4sync)) > s.cfg.ZilConfig.ZilHeadersPerBatch { + log.Infof("ZilliqaSyncManager MonitorChain - commit header") + if s.debugInfo { + s.dumpPendingHeaders() + } + if res := s.commitHeader(); res != 0 { + log.Errorf("ZilliqaSyncManager MonitorChain -- commit header error, result %d", res) + blockHandleResult = false + break + } + } + } + + if blockHandleResult && len(s.header4sync) > 0 { + s.commitHeader() + } + + case <-s.exitChan: + return + } + } +} + +func (s *ZilliqaSyncManager) handleNewBlock(height uint64) bool { + log.Infof("ZilliqaSyncManager handle new block: %d\n", height) + ret := s.handleBlockHeader(height) + if !ret { + log.Infof("ZilliqaSyncManager handleNewBlock - handleBlockHeader on height :%d failed\n", height) + return false + } + ret = s.fetchLockDepositEvents(height) + if !ret { + log.Infof("ZilliqaSyncManager handleNewBlock - fetchLockDepositEvents on height :%d failed\n", height) + return false + } + return true +} + +func (s *ZilliqaSyncManager) handleBlockHeader(height uint64) bool { + log.Infof("ZilliqaSyncManager handle new block header height is: %d\n", height) +T: + txBlockT, err := s.zilSdk.GetTxBlockVerbose(strconv.FormatUint(height, 10)) + if err != nil { + log.Errorf("ZilliqaSyncManager - handleBlockHeader error: %s", err) + return false + } + txBlock := core.NewTxBlockFromTxBlockT(txBlockT) + if txBlock.BlockHeader.DSBlockNum == 18446744073709551615 { + log.Infof("ZilliqaSyncManager - handleBlockHeader query ds block: ds block not ready") + time.Sleep(time.Second * 2) + goto T + } + if txBlock.BlockHeader.DSBlockNum > s.currentDsBlockNum { + // as we can't control the order how the header4sync on the poly + // nodes after we sent it across, + // this will ensure that all the TXBlock for a given DSBlock are synced before + // we proceed with the next dsblock. + log.Infof("ZilliqaSyncManager - new DsBlock %d", txBlock.BlockHeader.DSBlockNum) + log.Infof("ZilliqaSyncManager - sync all the txblock for %d", s.currentDsBlockNum) + if res := s.commitHeader(); res != 0 { + log.Errorf("ZilliqaSyncManager MonitorChain -- commit header error, result %d", res) + return false + } + + log.Infof("ZilliqaSyncManager - handleBlockHeader query ds block: %d\n", txBlock.BlockHeader.DSBlockNum) + dsBlock, err := s.zilSdk.GetDsBlockVerbose(strconv.FormatUint(txBlock.BlockHeader.DSBlockNum, 10)) + if err != nil { + log.Errorf("ZilliqaSyncManager - handleBlockHeader get ds block error: %s", err) + return false + } + txBlockOrDsBlock := core.TxBlockOrDsBlock{ + DsBlock: core.NewDsBlockFromDsBlockT(dsBlock), + } + rawBlock, _ := json.Marshal(txBlockOrDsBlock) + log.Infof("ZilliqaSyncManager handle new block header: %s\n", rawBlock) + s.header4sync = append(s.header4sync, rawBlock) + s.currentDsBlockNum++ + } + + txBlockOrDsBlock := core.TxBlockOrDsBlock{ + TxBlock: txBlock, + } + rawBlock, err2 := json.Marshal(txBlockOrDsBlock) + if err2 != nil { + log.Errorf("ZilliqaSyncManager - handleBlockHeader marshal block error: %s", err2) + return false + } + log.Debugf("ZilliqaSyncManager handle new block header: %s\n", rawBlock) + blockHash := txBlock.BlockHash[:] + log.Infof("ZilliqaSyncManager handleBlockHeader - header hash: %s\n", util.EncodeHex(blockHash)) + raw, _ := s.polySdk.GetStorage(autils.HeaderSyncContractAddress.ToHexString(), + append(append([]byte(scom.MAIN_CHAIN), autils.GetUint64Bytes(s.cfg.ZilConfig.SideChainId)...), autils.GetUint64Bytes(height)...)) + if len(raw) == 0 || !bytes.Equal(raw, blockHash) { + s.header4sync = append(s.header4sync, rawBlock) + } + if s.debugInfo { + s.dumpPendingHeaders() + } + return true +} + +// the workflow is: user -> LockProxy on zilliqa -> Cross Chain Manager -> emit event +// so here we need to filter out those transactions related to cross chain manager +// and parse the events, store them to local db, and commit them to the polynetwork +func (s *ZilliqaSyncManager) fetchLockDepositEvents(height uint64) bool { + transactions, err := s.zilSdk.GetTxnBodiesForTxBlock(strconv.FormatUint(height, 10)) + if err != nil { + if strings.Contains(err.Error(), "TxBlock has no transactions") { + log.Infof("ZilliqaSyncManager no transaction in block %d\n", height) + return true + } else { + log.Infof("ZilliqaSyncManager get transactions for tx block %d failed: %s\n", height, err.Error()) + return false + } + } + + for _, transaction := range transactions { + if !transaction.Receipt.Success { + continue + } + events := transaction.Receipt.EventLogs + for _, event := range events { + // 1. contract address should be cross chain manager + // 2. event name should be CrossChainEvent + toAddr, _ := bech32.ToBech32Address(event.Address) + if toAddr == s.crossChainManagerAddress { + if event.EventName != "CrossChainEvent" { + continue + } + log.Infof("ZilliqaSyncManager found event on cross chain manager: %+v\n", event) + // todo parse event to struct CrossTransfer + crossTx := &CrossTransfer{} + for _, param := range event.Params { + switch param.VName { + case "txId": + index := big.NewInt(0) + index.SetBytes(util.DecodeHex(param.Value.(string))) + crossTx.txIndex = tools.EncodeBigInt(index) + case "toChainId": + toChainId, _ := strconv.ParseUint(param.Value.(string), 10, 32) + crossTx.toChain = uint32(toChainId) + case "rawdata": + crossTx.value = util.DecodeHex(param.Value.(string)) + } + } + crossTx.height = height + crossTx.txId = util.DecodeHex(transaction.ID) + log.Infof("ZilliqaSyncManager parsed cross tx is: %+v\n", crossTx) + sink := common.NewZeroCopySink(nil) + crossTx.Serialization(sink) + err1 := s.db.PutRetry(sink.Bytes()) + if err1 != nil { + log.Errorf("ZilliqaSyncManager fetchLockDepositEvents - this.db.PutRetry error: %s", err) + } + log.Infof("ZilliqaSyncManager fetchLockDepositEvent - height: %d", height) + } else { + log.Infof("ZilliqaSyncManager found event but not on cross chain manager, ignore: %+v\n", event) + } + } + } + + return true +} + +func (s *ZilliqaSyncManager) handleLockDepositEvents(height uint64) error { + if s.practiceOnly { + return nil + } + log.Infof("ZilliqaSyncManager handleLockDepositEvents - height is %d", height) + retryList, err := s.db.GetAllRetry() + if err != nil { + return fmt.Errorf("ZilliqaSyncManager - handleLockDepositEvents - this.db.GetAllRetry error: %s", err) + } + for _, v := range retryList { + time.Sleep(time.Second * 1) + crosstx := new(CrossTransfer) + err := crosstx.Deserialization(common.NewZeroCopySource(v)) + if err != nil { + log.Errorf("ZilliqaSyncManager - handleLockDepositEvents - retry.Deserialization error: %s", err) + continue + } + heightString := new(string) + *heightString = strconv.FormatUint(height, 10) + ccmc, _ := bech32.FromBech32Addr(s.cfg.ZilConfig.CrossChainManagerContract) + ccmc = strings.ToLower(ccmc) + txIndexBigInt, _ := new(big.Int).SetString(crosstx.txIndex, 16) + txIndexDecimal := txIndexBigInt.String() + storageKey := core.GenerateStorageKey(ccmc, "zilToPolyTxHashMap", []string{txIndexDecimal}) + hashedStorageKey := util.Sha256(storageKey) + log.Infof("ZilliqaSyncManager - handleLockDepositEvents start get proof on address %s, hashed key is: %s, height is %s", ccmc, util.EncodeHex(hashedStorageKey), *heightString) + proof, err := s.zilSdk.GetStateProof(ccmc, util.EncodeHex(hashedStorageKey), heightString) + if err != nil { + return fmt.Errorf("ZilliqaSyncManager - handleLockDepositEvents - get proof from api error: %s", err) + } + + if proof == nil { + log.Warnf("ZilliqaSyncManager - handleLockDepositEvents - get proof from api error: %s", "proof is nil") + return fmt.Errorf("ZilliqaSyncManager - handleLockDepositEvents - get proof from api error: %s", "proof is nil") + } + + log.Infof("ZilliqaSyncManager - handleLockDepositEvents get proof from zilliqa api endpoint: %+v, height is: %d\n", proof, height) + + zilProof := &ZILProof{ + AccountProof: proof.AccountProof, + } + + hexskey := util.EncodeHex(storageKey) + storageProof := StorageProof{ + Key: []byte(hexskey), + Value: crosstx.value, + Proof: proof.StateProof, + } + + zilProof.StorageProofs = []StorageProof{storageProof} + proofRaw, _ := json.Marshal(zilProof) + + // commit proof + proofString, _ := json.Marshal(proof) + log.Infof("ZilliqaSyncManager - handleLockDepositEvents commit proof, height: %d, proof: %s, value: %s, txhash: %s\n", height, proofString, util.EncodeHex(crosstx.value), util.EncodeHex(crosstx.txId)) + tx, err := s.polySdk.Native.Ccm.ImportOuterTransfer( + s.cfg.ZilConfig.SideChainId, + crosstx.value, + uint32(height), + proofRaw, + util.DecodeHex(s.polySigner.Address.ToHexString()), + []byte{}, + s.polySigner) + + if err != nil { + if strings.Contains(err.Error(), "ZilliqaSyncManager - handleLockDepositEvents chooseUtxos, current utxo is not enough") { + log.Infof("ZilliqaSyncManager - handleLockDepositEvents handleLockDepositEvents - invokeNativeContract error: %s", err) + continue + } else { + if err := s.db.DeleteRetry(v); err != nil { + log.Errorf("ZilliqaSyncManager - handleLockDepositEvents handleLockDepositEvents handleLockDepositEvents - this.db.DeleteRetry error: %s", err) + } + if strings.Contains(err.Error(), "tx already done") { + log.Debugf("ZilliqaSyncManager - handleLockDepositEvents handleLockDepositEvents handleLockDepositEvents - eth_tx %s already on poly", util.EncodeHex(crosstx.txId)) + } else { + log.Errorf("ZilliqaSyncManager handleLockDepositEvents invokeNativeContract error for zil_tx %s: %s", util.EncodeHex(crosstx.txId), err) + } + continue + } + } else { + log.Infof("ZilliqaSyncManager - handleLockDepositEvents commitProof - send transaction to poly chain: ( poly_txhash: %s, zil_txhash: %s, height: %d )", + tx.ToHexString(), util.EncodeHex(crosstx.txId), height) + txHash := tx.ToHexString() + err = s.db.PutCheck(txHash, v) + err = s.db.PutCheck(txHash, v) + if err != nil { + log.Errorf("ZilliqaSyncManager handleLockDepositEvents - this.db.PutCheck error: %s", err) + } + err = s.db.DeleteRetry(v) + if err != nil { + log.Errorf("ZilliqaSyncManager handleLockDepositEvents - this.db.PutCheck error: %s", err) + } + log.Infof("ZilliqaSyncManager handleLockDepositEvents - syncProofToAlia txHash is %s", txHash) + } + } + + return nil +} + +// should be the same as relayer side +type ZILProof struct { + AccountProof []string `json:"accountProof"` + StorageProofs []StorageProof `json:"storageProof"` +} + +// key should be storage key (in zilliqa) +type StorageProof struct { + Key []byte `json:"key"` + Value []byte `json:"value"` + Proof []string `json:"proof"` +} + +type CrossTransfer struct { + txIndex string + txId []byte + value []byte + toChain uint32 + height uint64 +} + +func (this *CrossTransfer) Serialization(sink *common.ZeroCopySink) { + sink.WriteString(this.txIndex) + sink.WriteVarBytes(this.txId) + sink.WriteVarBytes(this.value) + sink.WriteUint32(this.toChain) + sink.WriteUint64(this.height) +} + +func (this *CrossTransfer) Deserialization(source *common.ZeroCopySource) error { + txIndex, eof := source.NextString() + if eof { + return fmt.Errorf("Waiting deserialize txIndex error") + } + txId, eof := source.NextVarBytes() + if eof { + return fmt.Errorf("Waiting deserialize txId error") + } + value, eof := source.NextVarBytes() + if eof { + return fmt.Errorf("Waiting deserialize value error") + } + toChain, eof := source.NextUint32() + if eof { + return fmt.Errorf("Waiting deserialize toChain error") + } + height, eof := source.NextUint64() + if eof { + return fmt.Errorf("Waiting deserialize height error") + } + this.txIndex = txIndex + this.txId = txId + this.value = value + this.toChain = toChain + this.height = height + return nil +} + +func (s *ZilliqaSyncManager) dumpPendingHeaders() { + log.Infof("ZilliqaSyncManager pending headers ------**-*") + for _, raw := range s.header4sync { + var block core.TxBlockOrDsBlock + _ = json.Unmarshal(raw, &block) + if block.TxBlock != nil { + log.Infof("ZilliqaSyncManager txBlk %d", block.TxBlock.BlockHeader.BlockNum) + } + if block.DsBlock != nil { + log.Infof("ZilliqaSyncManager dsBlk %d", block.DsBlock.BlockHeader.BlockNum) + } + } + log.Infof("ZilliqaSyncManager pending headers ======**=*") +} + +func (s *ZilliqaSyncManager) commitHeader() int { + // maybe delete this after it is stable + for _, raw := range s.header4sync { + var block core.TxBlockOrDsBlock + _ = json.Unmarshal(raw, &block) + if block.TxBlock != nil { + log.Infof("ZilliqaSyncManager commitHeader - about to commit tx block: %d from DS %d \n", block.TxBlock.BlockHeader.BlockNum, + block.TxBlock.BlockHeader.DSBlockNum) + if s.debugInfo { + log.Infof("000 Check if DS block is in storage") + s.checkDSBlockInStorage(block.TxBlock.BlockHeader.DSBlockNum) + log.Infof("Check header index") + s.getHeaderIndex(block.TxBlock.BlockHeader.BlockNum, block.TxBlock.BlockHash[:]) + log.Infof("Check main chain") + s.getMainChain(block.TxBlock.BlockHeader.BlockNum) + } + } + + if block.DsBlock != nil { + log.Infof("ZilliqaSyncManager commitHeader - about to commit ds block: %d\n", block.DsBlock.BlockHeader.BlockNum) + if s.debugInfo { + s.checkDSBlockInStorage(block.DsBlock.BlockHeader.BlockNum) + log.Infof("000 check ds block hash") + s.getDsBlockHeader(block.DsBlock.BlockHeader.BlockNum, block.DsBlock.BlockHash[:]) + } + } + } + + if s.practiceOnly { + log.Infof("ZilliqaSyncManager commitHeader - exit without sync") + return 1 + } + tx, err := s.polySdk.Native.Hs.SyncBlockHeader( + s.cfg.ZilConfig.SideChainId, + s.polySigner.Address, + s.header4sync, + s.polySigner, + ) + + if err != nil { + errDesc := err.Error() + if strings.Contains(errDesc, "get the parent block failed") || strings.Contains(errDesc, "missing required field") { + log.Warnf("ZilliqaSyncManager commitHeader - send transaction to poly chain err: %s", errDesc) + s.rollBackToCommAncestor() + return 0 + } else { + log.Errorf("ZilliqaSyncManager commitHeader - send transaction to poly chain err: %s", errDesc) + if s.debugInfo { + log.Info("ZilliqaSyncManager - Raw data ****** ") + for _, raw := range s.header4sync { + log.Infof(string(raw[:])) + } + log.Infof("ZilliqaSyncManager - Raw data ends ====== ") + } + return 1 + } + } + + tick := time.NewTicker(100 * time.Millisecond) + retries := 0 + var h uint32 + for range tick.C { + if retries > 5000 { + return 1 + } else { + retries++ + } + h, err = s.polySdk.GetBlockHeightByTxHash(tx.ToHexString()) + + if err != nil { + if strings.Contains(err.Error(), "JsonRpcResponse error code:42002 desc:INVALID PARAMS") { + log.Infof("ZilliqaSyncManager commitHeader - wait for confirmation") + } else { + log.Warnf("ZilliqaSyncManager commitHeader get block height by hash, hash: %s error: %s", tx.ToHexString(), err.Error()) + } + } + curr, err2 := s.polySdk.GetCurrentBlockHeight() + if err2 != nil { + log.Warnf("ZilliqaSyncManager commitHeader get current block height error: %s", err2.Error()) + } + if h > 0 && curr > h { + log.Infof("ZilliqaSyncManager commitHeader h > 0 or curr > h") + break + } + } + + log.Infof("ZilliqaSyncManager commitHeader - send transaction %s to poly chain and confirmed on height %d", tx.ToHexString(), h) + s.header4sync = make([][]byte, 0) + + s.handleLockDepositEvents(s.currentHeight) + return 0 +} + +func (s *ZilliqaSyncManager) rollBackToCommAncestor() { + for ; ; s.currentHeight-- { + raw, err := s.polySdk.GetStorage(autils.HeaderSyncContractAddress.ToHexString(), + append(append([]byte(scom.MAIN_CHAIN), autils.GetUint64Bytes(s.cfg.ZilConfig.SideChainId)...), autils.GetUint64Bytes(s.currentHeight)...)) + if len(raw) == 0 || err != nil { + continue + } + txBlockT, err2 := s.zilSdk.GetTxBlockVerbose(strconv.FormatUint(s.currentHeight, 10)) + if err2 != nil { + log.Errorf("rollBackToCommAncestor - failed to get header by number, so we wait for one second to retry: %v", err2) + time.Sleep(time.Second) + s.currentHeight++ + continue + } + blockHeader := core.NewTxBlockFromTxBlockT(txBlockT).BlockHeader + if bytes.Equal(util.Sha256(blockHeader.Serialize()), raw) { + bs, _ := json.Marshal(blockHeader) + log.Infof("ZilliqaSyncManager rollBackToCommAncestor - find the common ancestor: %s(number: %d)", bs, s.currentHeight) + break + } + } + + s.header4sync = make([][]byte, 0) + txBlock, err := s.zilSdk.GetTxBlock(strconv.FormatUint(s.currentHeight, 10)) + if err != nil { + log.Warnf("rollBackToCommAncestor, fail to get tx block, err: %s\n", err) + } + + dsNum, err2 := strconv.ParseUint(txBlock.Header.DSBlockNum, 10, 64) + if err2 != nil { + log.Warnf("rollBackToCommAncestor, fail to parse ds num, err: %s\n", err2) + } + + a, _ := s.zilSdk.GetDsBlockVerbose(txBlock.Header.DSBlockNum) + b := core.NewDsBlockFromDsBlockT(a) + txBlockOrDsBlock := core.TxBlockOrDsBlock{ + DsBlock: b, + } + rawBlock, _ := json.Marshal(txBlockOrDsBlock) + s.header4sync = append(s.header4sync, rawBlock) + s.currentDsBlockNum = dsNum + +} diff --git a/service/zil_sender.go b/service/zil_sender.go new file mode 100644 index 0000000..8caa5c6 --- /dev/null +++ b/service/zil_sender.go @@ -0,0 +1,233 @@ +/* + * Copyright (C) 2021 Zilliqa + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package service + +import ( + "encoding/hex" + "encoding/json" + "errors" + "github.com/Zilliqa/gozilliqa-sdk/crosschain/polynetwork" + "github.com/Zilliqa/gozilliqa-sdk/provider" + "github.com/Zilliqa/gozilliqa-sdk/transaction" + "github.com/Zilliqa/gozilliqa-sdk/util" + "github.com/ontio/ontology-crypto/keypair" + "github.com/ontio/ontology-crypto/signature" + poly_go_sdk "github.com/polynetwork/poly-go-sdk" + vconfig "github.com/polynetwork/poly/consensus/vbft/config" + polytypes "github.com/polynetwork/poly/core/types" + common2 "github.com/polynetwork/poly/native/service/cross_chain_manager/common" + "github.com/polynetwork/zilliqa-relayer/config" + "github.com/polynetwork/zilliqa-relayer/tools" + log "github.com/sirupsen/logrus" + "sync" +) + +type ZilSender struct { + cfg *config.Config + zilSdk *provider.Provider + //non-bech32 address + address string + privateKey string + + polySdk *poly_go_sdk.PolySdk + crossChainProxy *polynetwork.Proxy + inUse bool + mu sync.Mutex +} + +func (sender *ZilSender) commitDepositEventsWithHeaderWithNonce(header *polytypes.Header, param *common2.ToMerkleValue, headerProof string, anchorHeader *polytypes.Header, polyTxHash string, rawAuditPath []byte, nonce string) (*transaction.Transaction, error) { + // verifyHeaderAndExecuteTx + var ( + sigs []byte + headerData []byte + ) + if anchorHeader != nil && headerProof != "" { + for _, sig := range anchorHeader.SigData { + temp := make([]byte, len(sig)) + copy(temp, sig) + newsig, _ := signature.ConvertToEthCompatible(temp) + sigs = append(sigs, newsig...) + } + } else { + for _, sig := range header.SigData { + temp := make([]byte, len(sig)) + copy(temp, sig) + newsig, _ := signature.ConvertToEthCompatible(temp) + sigs = append(sigs, newsig...) + } + } + + exist := sender.checkIfFromChainTxExist(param.FromChainID, util.EncodeHex(param.TxHash)) + if exist { + log.Infof("ZilSender commitDepositEventsWithHeader - already relayed to zil: (from_chain_id: %d, from_txhash: %x, param.TxHash: %x\n)", param.FromChainID, param.TxHash, param.MakeTxParam.TxHash) + return nil, errors.New("ZilSender commitDepositEventsWithHeader - already relayed to zil") + } + + var rawAnchor []byte + if anchorHeader != nil { + rawAnchor = anchorHeader.GetMessage() + } + headerData = header.GetMessage() + + pe := polynetwork.DeserializeProof(util.EncodeHex(rawAuditPath), 0) + rawHeader := "0x" + util.EncodeHex(headerData) + hpe := polynetwork.DeserializeProof(headerProof, 0) + curRawHeader := "0x" + util.EncodeHex(rawAnchor) + signatures, _ := polynetwork.SplitSignature(util.EncodeHex(sigs)) + + return sender.crossChainProxy.VerifyHeaderAndExecuteTxWithNonce(pe, rawHeader, hpe, curRawHeader, signatures, nonce) +} + +func (sender *ZilSender) commitDepositEventsWithHeader(header *polytypes.Header, param *common2.ToMerkleValue, headerProof string, anchorHeader *polytypes.Header, polyTxHash string, rawAuditPath []byte) bool { + // verifyHeaderAndExecuteTx + var ( + sigs []byte + headerData []byte + ) + if anchorHeader != nil && headerProof != "" { + for _, sig := range anchorHeader.SigData { + temp := make([]byte, len(sig)) + copy(temp, sig) + newsig, _ := signature.ConvertToEthCompatible(temp) + sigs = append(sigs, newsig...) + } + } else { + for _, sig := range header.SigData { + temp := make([]byte, len(sig)) + copy(temp, sig) + newsig, _ := signature.ConvertToEthCompatible(temp) + sigs = append(sigs, newsig...) + } + } + + exist := sender.checkIfFromChainTxExist(param.FromChainID, util.EncodeHex(param.TxHash)) + if exist { + log.Infof("ZilSender commitDepositEventsWithHeader - already relayed to zil: (from_chain_id: %d, from_txhash: %x, param.TxHash: %x\n)", param.FromChainID, param.TxHash, param.MakeTxParam.TxHash) + return true + } + + var rawAnchor []byte + if anchorHeader != nil { + rawAnchor = anchorHeader.GetMessage() + } + headerData = header.GetMessage() + + pe := polynetwork.DeserializeProof(util.EncodeHex(rawAuditPath), 0) + rawHeader := "0x" + util.EncodeHex(headerData) + hpe := polynetwork.DeserializeProof(headerProof, 0) + curRawHeader := "0x" + util.EncodeHex(rawAnchor) + signatures, _ := polynetwork.SplitSignature(util.EncodeHex(sigs)) + + transaction, err := sender.crossChainProxy.VerifyHeaderAndExecuteTx(pe, rawHeader, hpe, curRawHeader, signatures) + sender.inUse = false + if err != nil { + log.Errorf("ZilSender commitDepositEventsWithHeader - failed to call VerifyHeaderAndExecuteTx: %s\n", err.Error()) + return false + } + + log.Infof("ZilSender commitDepositEventsWithHeader - confirmed transaction: %s\n", transaction.ID) + return true + +} + +func (sender *ZilSender) commitHeader(hdr *polytypes.Header) bool { + log.Infof("ZilSender commitHeader - height: %d\n", hdr.Height) + headerdata := hdr.GetMessage() + var ( + bookkeepers []keypair.PublicKey + sigs []byte + ) + + for _, sig := range hdr.SigData { + temp := make([]byte, len(sig)) + copy(temp, sig) + newsig, _ := signature.ConvertToEthCompatible(temp) + sigs = append(sigs, newsig...) + } + + blkInfo := &vconfig.VbftBlockInfo{} + if err := json.Unmarshal(hdr.ConsensusPayload, blkInfo); err != nil { + log.Errorf("commitHeader - unmarshal blockInfo error: %s", err) + return false + } + + for _, peer := range blkInfo.NewChainConfig.Peers { + keystr, _ := hex.DecodeString(peer.ID) + key, _ := keypair.DeserializePublicKey(keystr) + bookkeepers = append(bookkeepers, key) + } + + bookkeepers = keypair.SortPublicKeys(bookkeepers) + publickeys := make([]byte, 0) + for _, key := range bookkeepers { + publickeys = append(publickeys, tools.GetNoCompresskey(key)...) + } + + rawHeader := "0x" + util.EncodeHex(headerdata) + PubKeys, _ := polynetwork.SplitPubKeys(util.EncodeHex(publickeys)) + signatures, _ := polynetwork.SplitSignature(util.EncodeHex(sigs)) + transaction, err := sender.crossChainProxy.ChangeBookKeeper(rawHeader, PubKeys, signatures) + sender.inUse = false + if err != nil { + log.Errorf("ZilSender commitHeader - failed to call VerifyHeaderAndExecuteTx: %s\n", err.Error()) + return false + } + + log.Infof("ZilSender commitHeader - confirmed transaction: %s\n", transaction.ID) + + return true + +} + +func (sender *ZilSender) commitHeaderWithNonce(hdr *polytypes.Header, nonce string) (*transaction.Transaction, error) { + log.Infof("ZilSender commitHeader - height: %d\n", hdr.Height) + headerdata := hdr.GetMessage() + var ( + bookkeepers []keypair.PublicKey + sigs []byte + ) + + for _, sig := range hdr.SigData { + temp := make([]byte, len(sig)) + copy(temp, sig) + newsig, _ := signature.ConvertToEthCompatible(temp) + sigs = append(sigs, newsig...) + } + + blkInfo := &vconfig.VbftBlockInfo{} + if err := json.Unmarshal(hdr.ConsensusPayload, blkInfo); err != nil { + return nil, err + } + + for _, peer := range blkInfo.NewChainConfig.Peers { + keystr, _ := hex.DecodeString(peer.ID) + key, _ := keypair.DeserializePublicKey(keystr) + bookkeepers = append(bookkeepers, key) + } + + bookkeepers = keypair.SortPublicKeys(bookkeepers) + publickeys := make([]byte, 0) + for _, key := range bookkeepers { + publickeys = append(publickeys, tools.GetNoCompresskey(key)...) + } + + rawHeader := "0x" + util.EncodeHex(headerdata) + PubKeys, _ := polynetwork.SplitPubKeys(util.EncodeHex(publickeys)) + signatures, _ := polynetwork.SplitSignature(util.EncodeHex(sigs)) + return sender.crossChainProxy.ChangeBookKeeperWithNonce(rawHeader, PubKeys, signatures, nonce) +} diff --git a/service/zilliqamanager.go b/service/zilliqamanager.go new file mode 100644 index 0000000..354f1b6 --- /dev/null +++ b/service/zilliqamanager.go @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2021 Zilliqa + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package service + +import ( + "encoding/binary" + "encoding/json" + "fmt" + "github.com/Zilliqa/gozilliqa-sdk/account" + "github.com/Zilliqa/gozilliqa-sdk/core" + "github.com/Zilliqa/gozilliqa-sdk/provider" + poly "github.com/polynetwork/poly-go-sdk" + sdk "github.com/polynetwork/poly-go-sdk" + "github.com/polynetwork/poly/common" + scom "github.com/polynetwork/poly/native/service/header_sync/common" + autils "github.com/polynetwork/poly/native/service/utils" + "github.com/polynetwork/zilliqa-relayer/config" + "github.com/polynetwork/zilliqa-relayer/db" + log "github.com/sirupsen/logrus" + "strconv" +) + +/** + * currentHeight's source is either from poly remote storage or forceHeight + */ +type ZilliqaSyncManager struct { + polySigner *poly.Account + polySdk *poly.PolySdk + relaySyncHeight uint32 + zilAccount *account.Account + currentHeight uint64 + currentDsBlockNum uint64 + forceHeight uint64 + zilSdk *provider.Provider + crossChainManagerAddress string + cfg *config.Config + db *db.BoltDB + exitChan chan int + header4sync [][]byte + debugInfo bool + practiceOnly bool +} + +func NewZilliqaSyncManager(cfg *config.Config, zilSdk *provider.Provider, polysdk *sdk.PolySdk, boltDB *db.BoltDB, debugInfo bool, practiceOnly bool) (*ZilliqaSyncManager, error) { + var wallet *sdk.Wallet + var err error + if !common.FileExisted(cfg.PolyConfig.PolyWalletFile) { + wallet, err = polysdk.OpenWallet(cfg.PolyConfig.PolyWalletFile) + if err != nil { + return nil, err + } + } else { + wallet, err = polysdk.OpenWallet(cfg.PolyConfig.PolyWalletFile) + if err != nil { + log.Errorf("NewZilliqaSyncManager - wallet open error: %s", err.Error()) + return nil, err + } + } + signer, err := wallet.GetDefaultAccount([]byte(cfg.PolyConfig.PolyWalletPassword)) + if err != nil || signer == nil { + signer, err = wallet.NewDefaultSettingAccount([]byte(cfg.PolyConfig.PolyWalletPassword)) + if err != nil { + log.Errorf("NewETHManager - wallet password error") + return nil, err + } + + err = wallet.Save() + if err != nil { + return nil, err + } + } + log.Infof("NewZilliqaSyncManager - poly address: %s", signer.Address.ToBase58()) + zilliqaSyncManager := &ZilliqaSyncManager{ + db: boltDB, + cfg: cfg, + exitChan: make(chan int), + zilSdk: zilSdk, + forceHeight: cfg.ZilConfig.ZilForceHeight, + crossChainManagerAddress: cfg.ZilConfig.CrossChainManagerContract, + polySigner: signer, + polySdk: polysdk, + debugInfo: debugInfo, + practiceOnly: practiceOnly, + } + + err = zilliqaSyncManager.init() + if err != nil { + return nil, err + } else { + return zilliqaSyncManager, nil + } +} + +func (s *ZilliqaSyncManager) Run(enable bool) { + if enable { + go s.MonitorChain() + } +} + +func (s *ZilliqaSyncManager) init() error { + // get latest tx block from remote poly storage, thus we can know current tx block num and ds block num + latestHeight := s.findLatestTxBlockHeight() + log.Infof("ZilliqaSyncManager init - get latest tx block from poly, tx block height is: %d\n", latestHeight) + + if latestHeight == 0 { + return fmt.Errorf("ZilliqaSyncManager init - the genesis block has not synced!") + } + + if s.forceHeight > 0 && s.forceHeight < latestHeight { + s.currentHeight = s.forceHeight + } else { + s.currentHeight = latestHeight + } + log.Infof("ZilliqaSyncManager init - start height: %d", s.currentHeight) + if s.debugInfo { + s.getGenesisHeader() + s.getMainChain(latestHeight) + } + txBlockT, err := s.zilSdk.GetTxBlockVerbose(strconv.FormatUint(s.currentHeight, 10)) + if err != nil { + return fmt.Errorf("ZilliqaSyncManager init - get tx block error: %s", err.Error()) + } + dsBlockNum, _ := strconv.ParseUint(txBlockT.Header.DSBlockNum, 10, 64) + s.currentDsBlockNum = dsBlockNum + log.Infof("ZilliqaSyncManager init - current ds block height is: %d\n", s.currentDsBlockNum) + return nil +} + +func (s *ZilliqaSyncManager) getGenesisHeader() { + var sideChainIdBytes [8]byte + binary.LittleEndian.PutUint64(sideChainIdBytes[:], s.cfg.ZilConfig.SideChainId) + key := append([]byte(scom.GENESIS_HEADER), sideChainIdBytes[:]...) + contractAddress := autils.HeaderSyncContractAddress + result, err := s.polySdk.GetStorage(contractAddress.ToHexString(), key) + if err != nil { + log.Infof("cannot obtain latest genesis header\n") + } + if result == nil || len(result) == 0 { + log.Infof("0-length result from gensis header query\n") + } + // Turns out the genesis header is a string. + block := new(core.TxBlock) + genesisString := string(result[:]) + log.Infof("----- GENESIS HEADER ----- \n") + log.Infof("%s", genesisString) + log.Infof("====== END GENESIS HEADER ===== \n") + err = json.Unmarshal(result, block) + if err != nil { + log.Infof("!!!!! Could not unmarshal genesis - %s", err) + } else { + log.Infof("Get main chain for %d", block.BlockHeader.BlockNum) + s.getMainChain(block.BlockHeader.BlockNum) + log.Infof("GetHeaderIndex for %d:%x", block.BlockHeader.BlockNum, block.BlockHash) + s.getHeaderIndex(block.BlockHeader.BlockNum, block.BlockHash[:]) + dsBlockNum := block.BlockHeader.DSBlockNum + log.Infof("Get DsComm %d from polynet", dsBlockNum) + s.checkDSBlockInStorage(dsBlockNum) + log.Infof("Get DS Block %d from chain", dsBlockNum) + dsb, err := s.zilSdk.GetDsBlockVerbose(strconv.FormatUint(dsBlockNum, 10)) + if err != nil { + log.Infof("Could not get DS Block - %s", err) + } else { + if dsb == nil { + log.Infof("nil DS Block %s", strconv.Itoa(int(dsBlockNum))) + } else { + dsbval := core.NewDsBlockFromDsBlockT(dsb) + log.Infof("getDsBlockHeader %x", dsbval.BlockHash) + s.getDsBlockHeader(dsBlockNum, dsbval.BlockHash[:]) + } + } + log.Infof("XXX Done") + s.scanForDsCommittees(dsBlockNum) + } +} + +func (s *ZilliqaSyncManager) scanForDsCommittees(seedBlk uint64) { + for i := -32; i < 32; i += 1 { + toSearch := int(seedBlk) + i + log.Infof("==== Is there a DSC for %d? ", toSearch) + s.checkDSBlockInStorage(uint64(toSearch)) + log.Infof("---- NEXT DSC") + } +} + +// Get the DS Block Header +func (s *ZilliqaSyncManager) getDsBlockHeader(dsBlkNum uint64, hash []byte) { + var sideChainIdBytes [8]byte + binary.LittleEndian.PutUint64(sideChainIdBytes[:], s.cfg.ZilConfig.SideChainId) + key := append([]byte(scom.HEADER_INDEX), sideChainIdBytes[:]...) + key = append(key, hash...) + contractAddress := autils.HeaderSyncContractAddress + result, err := s.polySdk.GetStorage(contractAddress.ToHexString(), key) + log.Infof("---- DS Header hash with blknum %d hash %x", dsBlkNum, hash) + if err != nil { + log.Infof("==== FAILED %s", err) + } + if result == nil || len(result) == 0 { + log.Infof("==== 0-length or empty result") + } else { + log.Infof("==== Retrieved: %x", result) + } + +} + +// Given a tx block number, try to obtain MAIN_CHAIN +func (s *ZilliqaSyncManager) getMainChain(blknum uint64) { + var sideChainIdBytes [8]byte + binary.LittleEndian.PutUint64(sideChainIdBytes[:], s.cfg.ZilConfig.SideChainId) + key := append([]byte(scom.MAIN_CHAIN), sideChainIdBytes[:]...) + var blkNumBytes [8]byte + binary.LittleEndian.PutUint64(blkNumBytes[:], blknum) + key = append(key, blkNumBytes[:]...) + contractAddress := autils.HeaderSyncContractAddress + result, err := s.polySdk.GetStorage(contractAddress.ToHexString(), key) + log.Infof("---- MAIN_CHAIN with blknum %d", blknum) + if err != nil { + log.Infof("==== FAILED %s", err) + } + if result == nil || len(result) == 0 { + log.Infof("==== 0-length or empty result") + } else { + log.Infof("==== Retrieved: %x", result) + } +} + +// Given a tx block hash, see if the header index is in storage. +func (s *ZilliqaSyncManager) getHeaderIndex(blknum uint64, hash []byte) { + var sideChainIdBytes [8]byte + binary.LittleEndian.PutUint64(sideChainIdBytes[:], s.cfg.ZilConfig.SideChainId) + key := append([]byte(scom.HEADER_INDEX), sideChainIdBytes[:]...) + key = append(key, hash...) + contractAddress := autils.HeaderSyncContractAddress + result, err := s.polySdk.GetStorage(contractAddress.ToHexString(), key) + log.Infof("---- Header hash with blknum %d hash %x", blknum, hash) + if err != nil { + log.Infof("==== FAILED %s", err) + } + if result == nil || len(result) == 0 { + log.Infof("==== 0-length or empty result") + } else { + log.Infof("==== Retrieved: %x", result) + } +} + +func (s *ZilliqaSyncManager) checkDSBlockInStorage(blk uint64) { + var sideChainIdBytes [8]byte + binary.LittleEndian.PutUint64(sideChainIdBytes[:], s.cfg.ZilConfig.SideChainId) + var blkc [8]byte + binary.LittleEndian.PutUint64(blkc[:], blk) + key := append(sideChainIdBytes[:], []byte("dsComm")...) + key = append(key, blkc[:]...) + result, err := s.polySdk.GetStorage(autils.HeaderSyncContractAddress.ToHexString(), key) + if err != nil { + log.Infof("XXXX Couldn't retrieve polynet storage for DS Block %d: %s", blk, err.Error()) + } + if result == nil || len(result) == 0 { + log.Infof("XXXX no DSC stored for ds block %d", blk) + } else { + log.Infof("==== DSC for DS block %d is %x", blk, result) + } +} + +func (s *ZilliqaSyncManager) findLatestTxBlockHeight() uint64 { + // try to get key + var sideChainIdBytes [8]byte + binary.LittleEndian.PutUint64(sideChainIdBytes[:], s.cfg.ZilConfig.SideChainId) + contractAddress := autils.HeaderSyncContractAddress + key := append([]byte(scom.CURRENT_HEADER_HEIGHT), sideChainIdBytes[:]...) + // try to get storage + result, err := s.polySdk.GetStorage(contractAddress.ToHexString(), key) + if err != nil { + log.Infof("get latest tx block from poly failed,err: %s\n", err.Error()) + return 0 + } + if result == nil || len(result) == 0 { + return 0 + } else { + return binary.LittleEndian.Uint64(result) + } +} diff --git a/target_contracts.json b/target_contracts.json new file mode 100644 index 0000000..f755f41 --- /dev/null +++ b/target_contracts.json @@ -0,0 +1,8 @@ +[ + { + "zil1v4v858qjqd5s88vvsj3qsn89nndeldkpwd9l2c": { + "inbound": [202], + "outbound": [202] + } + } +] \ No newline at end of file diff --git a/tools/utils.go b/tools/utils.go new file mode 100644 index 0000000..5313566 --- /dev/null +++ b/tools/utils.go @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2021 Zilliqa + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package tools + +import ( + "bufio" + "bytes" + "crypto/elliptic" + "encoding/hex" + "github.com/btcsuite/btcd/btcec" + "github.com/ontio/ontology-crypto/ec" + "github.com/ontio/ontology-crypto/keypair" + "github.com/ontio/ontology-crypto/sm2" + "github.com/polynetwork/poly/common" + "golang.org/x/crypto/ed25519" + "math/big" + "os" + "strings" +) + +func EncodeBigInt(b *big.Int) string { + if b.Uint64() == 0 { + return "00" + } + return hex.EncodeToString(b.Bytes()) +} + +func ParseAuditpath(path []byte) ([]byte, []byte, [][32]byte, error) { + source := common.NewZeroCopySource(path) + /* + l, eof := source.NextUint64() + if eof { + return nil, nil, nil, nil + } + */ + value, eof := source.NextVarBytes() + if eof { + return nil, nil, nil, nil + } + size := int((source.Size() - source.Pos()) / common.UINT256_SIZE) + pos := make([]byte, 0) + hashs := make([][32]byte, 0) + for i := 0; i < size; i++ { + f, eof := source.NextByte() + if eof { + return nil, nil, nil, nil + } + pos = append(pos, f) + + v, eof := source.NextHash() + if eof { + return nil, nil, nil, nil + } + var onehash [32]byte + copy(onehash[:], (v.ToArray())[0:32]) + hashs = append(hashs, onehash) + } + + return value, pos, hashs, nil +} + +func ReadLine(path string) ([]string, error) { + var lines []string + file, err := os.Open(path) + if err != nil { + return lines, err + } + defer file.Close() + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + lines = append(lines, scanner.Text()) + } + + if err1 := scanner.Err(); err1 != nil { + return lines, err1 + } + + return lines, nil +} + +func GetCurveLabel(name string) (byte, error) { + switch strings.ToUpper(name) { + case strings.ToUpper(elliptic.P224().Params().Name): + return 1, nil + case strings.ToUpper(elliptic.P256().Params().Name): + return 2, nil + case strings.ToUpper(elliptic.P384().Params().Name): + return 3, nil + case strings.ToUpper(elliptic.P521().Params().Name): + return 4, nil + case strings.ToUpper(sm2.SM2P256V1().Params().Name): + return 20, nil + case strings.ToUpper(btcec.S256().Name): + return 5, nil + default: + panic("err") + } +} + +func GetNoCompresskey(key keypair.PublicKey) []byte { + var buf bytes.Buffer + switch t := key.(type) { + case *ec.PublicKey: + switch t.Algorithm { + case ec.ECDSA: + // Take P-256 as a special case + if t.Params().Name == elliptic.P256().Params().Name { + return ec.EncodePublicKey(t.PublicKey, false) + } + buf.WriteByte(byte(0x12)) + case ec.SM2: + buf.WriteByte(byte(0x13)) + } + label, err := GetCurveLabel(t.Curve.Params().Name) + if err != nil { + panic(err) + } + buf.WriteByte(label) + buf.Write(ec.EncodePublicKey(t.PublicKey, false)) + case ed25519.PublicKey: + panic("err") + default: + panic("err") + } + return buf.Bytes() +} + +func AppendToFile(fileName string, context string) { + f, err := os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) + if err != nil { + panic(err) + } + + defer f.Close() + + if _, err = f.WriteString(context); err != nil { + panic(err) + } +}