diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..beb15a5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.idea/ +.idea/workspace.xml +capital* +db/bolt.bin +wallet.dat +config-debug.json +log/20* +UTC--* +Log \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f288702 --- /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 0bf26bc..4a48f01 100644 --- a/README.md +++ b/README.md @@ -1 +1,70 @@ -# kai-relayer \ No newline at end of file +

Kai Relayer

+ +Kai(Kardiachain) Relayer is an important character of Poly cross-chain interactive protocol which is responsible for relaying cross-chain transaction from and to Kardiachain. + +## Build From Source + +### Prerequisites + +- [Golang](https://golang.org/doc/install) version 1.14 or later + +### Build + +```shell +git clone https://github.com/polynetwork/kai-relayer.git +cd kai_relayer +go build -o kai_relayer main.go +``` + +After building the source code successfully, you should see the executable program `kai_relayer`. + +### Build Docker Image + +``` +docker build -t polynetwork/kai_relayer -f Dockerfile ./ +``` + +This command will copy ./config.json to /app/config.json in the image. So you need to prepare config.json before running this command and you should start the kai-relayer in container basing on the configuration in /app/config.json. + +## Run Relayer + +Before you can run the relayer you will need to create a wallet file of PolyNetwork. 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.json`. + +``` +{ + "MultiChainConfig":{ + "RestURL":"http://poly_ip:20336", // address of Poly + "EntranceContractAddress":"0300000000000000000000000000000000000000", // CrossChainManagerContractAddress on Poly. No need to change + "WalletFile":"./wallet.dat", // your poly wallet + "WalletPwd":"pwd" //password + }, + "KaiConfig":{ + "SideChainId": 2, // kai side chainID registered on poly + "RestURL":"https://dev-1@kardiachain.io", // your kai node + "ECCMContractAddress":"kai_cross_chain_contract", + "ECCDContractAddress":"kai_cross_chain_data_contract", + "KeyStorePath": "./keystore", // path to store your kai(ethereum) wallet + "KeyStorePwdSet": { // password to protect your kai(ethereum) wallet + "0xd12e...54ccacf91ca364d": "pwd1", // password for address "0xd12e...54ccacf91ca364d" + "0xabb4...0aba7cf3ee3b953": "pwd2" // password for address "0xabb4...0aba7cf3ee3b953" + }, + "BlockConfig": 20, // blocks to confirm a kai tx + "HeadersPerBatch": 500, // number of kai headers commited to poly in one transaction at most + "MonitorInterval": 3, // seconds of ticker to monitor kai chain + "EnableChangeBookKeeper": false // normally speaking, set this value as false + }, + "BoltDbPath": "./db", // DB path + "RoutineNum": 64, + "TargetContracts": [ + { + "0xD8aE73e06552E...bcAbf9277a1aac99": { // your lockproxy hash on kai chain + "inbound": [6], // from which chain allowed + "outbound": [6] // to which chain allowed + } + } + ] +} +``` + diff --git a/cmd/flags.go b/cmd/flags.go new file mode 100644 index 0000000..7c956e8 --- /dev/null +++ b/cmd/flags.go @@ -0,0 +1,95 @@ +/* +* Copyright (C) 2020 The poly network Authors +* This file is part of The poly network library. +* +* The poly network is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* The poly network 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 Lesser General Public License for more details. +* You should have received a copy of the GNU Lesser General Public License +* along with The poly network . If not, see . + */ +package cmd + +import ( + "strings" + + "github.com/polynetwork/kai-relayer/config" + "github.com/urfave/cli" +) + +var ( + LogLevelFlag = cli.UintFlag{ + Name: "loglevel", + Usage: "Set the log level to `` (0~6). 0:Trace 1:Debug 2:Info 3:Warn 4:Error 5:Fatal 6:MaxLevel", + Value: config.DEFAULT_LOG_LEVEL, + } + + //CliWalletDirFlag = cli.StringFlag{ + // Name: "walletdir", + // Usage: "Wallet data ``", + // Value: config.DEFAULT_WALLET_PATH, + //} + + //CliAddressFlag = cli.StringFlag{ + // Name: "cliaddress", + // Usage: "Rpc bind `
`", + // Value: config.DEFUALT_CLI_RPC_ADDRESS, + //} + + //CliRpcPortFlag = cli.UintFlag{ + // Name: "cliport", + // Usage: "Rpc bind port ``", + // Value: config.DEFAULT_CLI_RPC_PORT, + //} + + ConfigPathFlag = cli.StringFlag{ + Name: "cliconfig", + Usage: "Server config file ``", + Value: config.DEFAULT_CONFIG_FILE_NAME, + } + + KaiStartFlag = cli.Uint64Flag{ + Name: "kardiachain", + Usage: "kai start block height ", + Value: uint64(0), + } + + KaiStartForceFlag = cli.Uint64Flag{ + Name: "kardiachainforce", + Usage: "kai start block height ", + Value: uint64(0), + } + + PolyStartFlag = cli.Uint64Flag{ + Name: "poly", + Usage: "poly start block height ", + Value: uint64(0), + } + + LogDir = cli.StringFlag{ + Name: "logdir", + Usage: "log directory", + Value: "./Log/", + } + + //EncryptFlag = cli.StringFlag{ + // Name: "encrypt", + // Usage: "encrypt string `pwd`", + // Value: "", + //} +) + +//GetFlagName deal with short flag, and return the flag name whether flag name have short name +func GetFlagName(flag cli.Flag) string { + name := flag.GetName() + if name == "" { + return "" + } + return strings.TrimSpace(strings.Split(name, ",")[0]) +} diff --git a/config.json b/config.json new file mode 100644 index 0000000..3de4aa6 --- /dev/null +++ b/config.json @@ -0,0 +1,26 @@ +{ + "PolyConfig":{ + "RestURL":"http://138.91.6.226:40336", + "EntranceContractAddress":"0300000000000000000000000000000000000000", + "WalletFile":"/home/thangn/go/pkg/github.com/polynetwork/poly/wallet.dat", + "WalletPwd":"123456" + }, + "KaiConfig":{ + "SideChainId": 141, + "RestURL":"https://dev-1.kardiachain.io", + "ECCMContractAddress":"0x14E8226B63C77c6fdCB3830e1bde2b6981F01AAe", + "ECCDContractAddress":"0xad8673ba653c75494EF43F3431b67aD597B21314", + "KeyStorePath": "/home/thangn/snap/geth/477/.ethereum/keystore", + "KeyStorePwdSet": { + "0x2290ddc3874523ffd48c948c8b9379425bDe8BeC": "123456" + }, + "BlockConfig": 2, + "HeadersPerBatch": 500, + "MonitorInterval": 3, + "EnableChangeBookKeeper": false + }, + "BoltDbPath": "./db", + "RoutineNum": 64, + "TargetContracts": [ + ] +} \ No newline at end of file diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..5e47b50 --- /dev/null +++ b/config/config.go @@ -0,0 +1,113 @@ +/* +* Copyright (C) 2020 The poly network Authors +* This file is part of The poly network library. +* +* The poly network is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* The poly network 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 Lesser General Public License for more details. +* You should have received a copy of the GNU Lesser General Public License +* along with The poly network . If not, see . + */ +package config + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "os" + "strings" + "time" + + "github.com/polynetwork/kai-relayer/log" +) + +const ( + KAI_MONITOR_INTERVAL = 3 * time.Second + ONT_MONITOR_INTERVAL = 3 * time.Second + KEY_UNLOCK_TIME = 30 * time.Second + + KAI_USEFUL_BLOCK_NUM = 3 + KAI_PROOF_USERFUL_BLOCK = 12 + ONT_USEFUL_BLOCK_NUM = 1 + DEFAULT_CONFIG_FILE_NAME = "./config.json" + Version = "1.0" + + DEFAULT_LOG_LEVEL = log.InfoLog +) + +//type ETH struct { +// Chain string // eth or etc +// ChainId uint64 +// RpcAddress string +// ConfirmedBlockNum uint +// //Tokens []*Token +//} + +type ServiceConfig struct { + PolyConfig *PolyConfig + KAIConfig *KAIConfig + BoltDbPath string + RoutineNum int64 +} + +type PolyConfig struct { + RestURL string + EntranceContractAddress string + WalletFile string + WalletPwd string +} + +type KAIConfig struct { + RestURL string + ECCMContractAddress string + ECCDContractAddress string + KeyStorePath string + KeyStorePwdSet map[string]string + BlockConfig uint64 + SideChainId uint64 +} + +func ReadFile(fileName string) ([]byte, error) { + file, err := os.OpenFile(fileName, os.O_RDONLY, 0666) + if err != nil { + return nil, fmt.Errorf("ReadFile: open file %s error %s", fileName, err) + } + defer func() { + err := file.Close() + if err != nil { + log.Errorf("ReadFile: File %s close error %s", fileName, err) + } + }() + data, err := ioutil.ReadAll(file) + if err != nil { + return nil, fmt.Errorf("ReadFile: ioutil.ReadAll %s error %s", fileName, err) + } + return data, nil +} + +func NewServiceConfig(configFilePath string) *ServiceConfig { + fileContent, err := ReadFile(configFilePath) + if err != nil { + log.Errorf("NewServiceConfig: failed, err: %s", err) + return nil + } + servConfig := &ServiceConfig{} + err = json.Unmarshal(fileContent, servConfig) + if err != nil { + log.Errorf("NewServiceConfig: failed, err: %s", err) + return nil + } + + for k, v := range servConfig.KAIConfig.KeyStorePwdSet { + delete(servConfig.KAIConfig.KeyStorePwdSet, k) + servConfig.KAIConfig.KeyStorePwdSet[strings.ToLower(k)] = v + } + + return servConfig +} diff --git a/db/db.go b/db/db.go new file mode 100644 index 0000000..f6a1b42 --- /dev/null +++ b/db/db.go @@ -0,0 +1,244 @@ +/* +* Copyright (C) 2020 The poly network Authors +* This file is part of The poly network library. +* +* The poly network is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* The poly network 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 Lesser General Public License for more details. +* You should have received a copy of the GNU Lesser General Public License +* along with The poly network . If not, see . + */ +package db + +import ( + "encoding/binary" + "encoding/hex" + "fmt" + "path" + "strings" + "sync" + + "github.com/boltdb/bolt" +) + +const MAX_NUM = 1000 + +var ( + BKTCheck = []byte("Check") + BKTRetry = []byte("Retry") + BKTHeight = []byte("Height") +) + +type BoltDB struct { + rwlock *sync.RWMutex + db *bolt.DB + filePath string +} + +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 + + 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 + } + + 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 + } + + 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) 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) DeleteCheck(txHash string) error { + w.rwlock.Lock() + defer w.rwlock.Unlock() + + k, err := hex.DecodeString(txHash) + if err != nil { + return err + } + return w.db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket(BKTCheck) + err := bucket.Delete(k) + if err != nil { + return err + } + return 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) GetAllCheck() (map[string][]byte, error) { + w.rwlock.Lock() + defer w.rwlock.Unlock() + + checkMap := make(map[string][]byte) + err := w.db.Update(func(tx *bolt.Tx) error { + bw := tx.Bucket(BKTCheck) + bw.ForEach(func(k, v []byte) error { + _k := make([]byte, len(k)) + _v := make([]byte, len(v)) + copy(_k, k) + copy(_v, v) + checkMap[hex.EncodeToString(_k)] = _v + if len(checkMap) >= MAX_NUM { + return fmt.Errorf("max num") + } + return nil + }) + return nil + }) + if err != nil { + return nil, err + } + return checkMap, 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 +} + +func (w *BoltDB) Close() { + w.rwlock.Lock() + w.db.Close() + w.rwlock.Unlock() +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..3a81ed8 --- /dev/null +++ b/go.mod @@ -0,0 +1,18 @@ +module github.com/polynetwork/kai-relayer + +go 1.14 + +require ( + github.com/boltdb/bolt v1.3.1 + github.com/btcsuite/btcd v0.21.0-beta + github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/ethereum/go-ethereum v1.9.18 + github.com/kardiachain/go-kardia v1.1.1-0.20210518091640-d13a5b7f7c4c + github.com/ontio/ontology-crypto v1.0.9 + github.com/polynetwork/eth-contracts v0.0.0-20200814062128-70f58e22b014 + github.com/polynetwork/poly v0.0.0-20200722075529-eea88acb37b2 + github.com/polynetwork/poly-go-sdk v0.0.0-20200729103825-af447ef53ef0 + github.com/stretchr/testify v1.7.0 + github.com/urfave/cli v1.22.4 + launchpad.net/gocheck v0.0.0-20140225173054-000000000087 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..1d09c83 --- /dev/null +++ b/go.sum @@ -0,0 +1,904 @@ +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= +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/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/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/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= +github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/antlr/antlr4 v0.0.0-20190819145818-b43a4c3a8015/go.mod h1:T7PbCXFs94rrTttyxjbyT5+/1V8T2TYDejxUfHJjw1Y= +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/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= +github.com/aristanetworks/goarista v0.0.0-20190712234253-ed1100a1c015 h1:7ABPr1+uJdqESAdlVevnc/2FJGiC/K3uMg1JiELeF+0= +github.com/aristanetworks/goarista v0.0.0-20190712234253-ed1100a1c015/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/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.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.21.0-beta h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M= +github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= +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-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/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= +github.com/cespare/cp v1.1.1/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/go-semver v0.2.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 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= +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/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ= +github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +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/docker/docker v17.12.0-ce-rc1.0.20200531234253-77e06fda0c94+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/dop251/goja v0.0.0-20200219165308-d1232e640a87/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/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/ebuchman/fail-test v0.0.0-20170303061230-95f809107225 h1:7TXT8REobzZUI9GzsRtAD29efTY/HgKRU2xYnV1zlaM= +github.com/ebuchman/fail-test v0.0.0-20170303061230-95f809107225/go.mod h1:OFTBW14UVJS8P0shpX7OdPY0qpkTdA7AWGYFacMC2D8= +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.18 h1:+vzvufVD7+OfQa07IJP20Z7AGZsJaw0M6JIA/WQcqy8= +github.com/ethereum/go-ethereum v1.9.18/go.mod h1:JSSTypSMTkGZtAdAChH2wP5dZEvPGh3nUTuDpH+hNrg= +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/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/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 h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= +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-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/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +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.3.1-0.20190508161146-9fa652df1129/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/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= +github.com/golang/protobuf v1.4.3/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/cel-go v0.3.2/go.mod h1:DoRSdzaJzNiP1lVuWhp/RjSnHLDQr/aNPlyqSBasBqA= +github.com/google/cel-spec v0.3.0/go.mod h1:MjQm800JAGhOZXI7vatnVpmIaFTR6L8FHcKk+piiKpI= +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/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/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 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= +github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= +github.com/gtank/merlin v0.1.1/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.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +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 h1:aY2hhxLhjEAbfXOx2nRJxCXezC6CO2V/yN+OCr1srtk= +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 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo= +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 h1:6OvNmYgJyexcZ3pYbTI9jWx5tHo1Dee/tWbLMfPe2TA= +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/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +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/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +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/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356 h1:I/yrLt2WilKxlQKCM52clh5rGzTKpVctGT1lH4Dc8Jw= +github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/kardiachain/go-kardia v1.1.1-0.20210518091640-d13a5b7f7c4c h1:xjhQZf1wiA+ebCz/oNZ7xaZZY/mi/FNoNnMP3iSV/GQ= +github.com/kardiachain/go-kardia v1.1.1-0.20210518091640-d13a5b7f7c4c/go.mod h1:dIcZ5VO21q0HAjL9LiHqJ8bKMDkoE3T/4H0vy8urggs= +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/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +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/konsorten/go-windows-terminal-sequences v1.0.3/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/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-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +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.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +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/minio/highwayhash v1.0.1 h1:dZ6IIu8Z14VlC0VpfKofAhCy74wu/Qb5gcn52yWoz/0= +github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= +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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +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 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pebbe/zmq4 v1.0.0/go.mod h1:7N4y5R18zBiu3l0vajMUWQgZyjv464prE8RCyBcmnZM= +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 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= +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/eth-contracts v0.0.0-20200814062128-70f58e22b014 h1:fbVjTnsS7nZwsTtRdbv+2162e/odNN1rqfLf/gBmhAM= +github.com/polynetwork/eth-contracts v0.0.0-20200814062128-70f58e22b014/go.mod h1:TeePrYZfWJAwuksPlie7RPequ51Ujp5l/JY6TcutsFc= +github.com/polynetwork/poly v0.0.0-20200715030435-4f1d1a0adb44/go.mod h1:UzlGEWk0eCGsuMJOZfBoZjRbmu4Yw/SudKAIFe1gPnY= +github.com/polynetwork/poly v0.0.0-20200722075529-eea88acb37b2 h1:t4zDeTSvzn8Mo2jxUwg8WImqih3ZZWoytTFcnbpGZuU= +github.com/polynetwork/poly v0.0.0-20200722075529-eea88acb37b2/go.mod h1:UzlGEWk0eCGsuMJOZfBoZjRbmu4Yw/SudKAIFe1gPnY= +github.com/polynetwork/poly-go-sdk v0.0.0-20200729103825-af447ef53ef0 h1:pWDLHm20+92Oa3kIDSKPJBtZeLe1/ZcKfcSDrw2fpZQ= +github.com/polynetwork/poly-go-sdk v0.0.0-20200729103825-af447ef53ef0/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/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.8.0 h1:zvJNkoCFAnYFNC24FV8nW4JdRJ3GIFcLbg65lL/JDcw= +github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM= +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/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.14.0 h1:RHRyE8UocrbjU+6UvRzwi6HjiDfxrrBU91TtbKzkGp4= +github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +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/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= +github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= +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/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= +github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= +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 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= +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 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= +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/sasha-s/go-deadlock v0.2.0 h1:lMqc+fUb7RrFS3gQLtoQsJ7/6TV/pAIFvBsqX73DK8Y= +github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10= +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 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +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.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +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 h1:breEStsVwemnKh2/s6gMvSdMEkwW0sK8vGStnlVBMCs= +github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +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 h1:7aKfF+e8/k68gda3LOjo5RxiUqddoFxVq4BKBPrxk5E= +github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48 h1:ju5UTwk5Odtm4trrY+4Ca4RMj5OyXbmVeDAVad2T0Jw= +github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48/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/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +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 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA= +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 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk= +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/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +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.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-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-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9 h1:phUcVbl53swtrUN8kQEXFhUxPlIlWyBfKmidCu7P95o= +golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +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-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/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-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-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +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-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +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/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/sync v0.0.0-20201020160332-67f06af15bc9/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-20180926160741-c2ed4eda69e7/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-20190130150945-aca44879d564/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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +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-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-20200106162015-b016eb3dc98e/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-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 h1:9UQO31fZ+0aKQOFldThf7BKPMJTiBfWycGh/u3UoO88= +golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/text v0.3.0/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-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-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-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +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-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-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +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/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/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-20190425155659-357c62f0e4bb/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-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20201111145450-ac7456db90a6 h1:iRN4+t0lvZX/l9gH14ARF9i58tsVa5a97k6aH95rC3Y= +google.golang.org/genproto v0.0.0-20201111145450-ac7456db90a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +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.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/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/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 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= +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= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +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-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= +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/kaiclient/client.go b/kaiclient/client.go new file mode 100644 index 0000000..e7b95d7 --- /dev/null +++ b/kaiclient/client.go @@ -0,0 +1,133 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Package kaiclient provides a client for the KardiaChain RPC API. +package kaiclient + +import ( + "context" + "math" + "math/big" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/rpc" + + kai "github.com/kardiachain/go-kardia/mainchain" + ktypes "github.com/kardiachain/go-kardia/types" +) + +// Client defines typed wrappers for the Ethereum RPC API. +type Client struct { + c *rpc.Client +} + +// Dial connects a client to the given URL. +func Dial(rawurl string) (*Client, error) { + return DialContext(context.Background(), rawurl) +} + +func DialContext(ctx context.Context, rawurl string) (*Client, error) { + c, err := rpc.DialContext(ctx, rawurl) + if err != nil { + return nil, err + } + return NewClient(c), nil +} + +// NewClient creates a client that uses the given RPC client. +func NewClient(c *rpc.Client) *Client { + return &Client{c} +} + +func (ec *Client) Close() { + ec.c.Close() +} + +// HeaderByNumber returns a block header from the current canonical chain. If number is +// nil, the latest known header is returned. +func (ec *Client) HeaderByNumber(ctx context.Context, number *big.Int) (*ktypes.Header, error) { + var head *ktypes.Header + err := ec.c.CallContext(ctx, &head, "kai_getBlockHeaderByNumber", toBlockNumArg(number)) + if err == nil && head == nil { + err = ethereum.NotFound + } + return head, err +} + +type KaiHeader struct { + Header *ktypes.Header + Commit *ktypes.Commit + ValidatorSet *ktypes.ValidatorSet +} + +func (ec *Client) FullHeaderByNumber(ctx context.Context, number *big.Int) (*KaiHeader, error) { + header, err := ec.HeaderByNumber(ctx, number) + if err != nil { + return nil, err + } + validators, err := ec.GetValidators(ctx, number) + if err != nil { + return nil, err + } + + commit, err := ec.GetCommit(ctx, number.Sub(number, big.NewInt(1))) + if err != nil { + return nil, err + } + return &KaiHeader{ + Header: header, + ValidatorSet: validators, + Commit: commit, + }, nil +} + +func (ec *Client) GetValidators(ctx context.Context, number *big.Int) (*ktypes.ValidatorSet, error) { + var valSet *ktypes.ValidatorSet + err := ec.c.CallContext(ctx, &valSet, "kai_getValidatorSet", toBlockNumArg(number)) + if err == nil && valSet == nil { + err = ethereum.NotFound + } + return valSet, err +} + +func (ec *Client) GetCommit(ctx context.Context, number *big.Int) (*ktypes.Commit, error) { + var commit *ktypes.Commit + err := ec.c.CallContext(ctx, &commit, "kai_getCommit", toBlockNumArg(number)) + if err == nil && commit == nil { + err = ethereum.NotFound + } + return commit, err +} + +func (ec *Client) GetProof(ctx context.Context, address common.Address, storageKeys []string, number *big.Int) (*kai.AccountResult, error) { + var accountR *kai.AccountResult + err := ec.c.CallContext(ctx, &accountR, "kai_getProof", address, storageKeys, toBlockNumArg(number), false) + if err == nil && accountR == nil { + err = ethereum.NotFound + } + return accountR, err +} +func toBlockNumArg(number *big.Int) string { + if number == nil { + return "latest" + } + pending := new(big.Int).SetUint64(math.MaxUint64 - 1) + if number.Cmp(pending) == 0 { + return "pending" + } + return number.String() +} diff --git a/kaiclient/kaiclient_test.go b/kaiclient/kaiclient_test.go new file mode 100644 index 0000000..0fb2d4e --- /dev/null +++ b/kaiclient/kaiclient_test.go @@ -0,0 +1,370 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package kaiclient + +import ( + "context" + "math/big" + "testing" + + "github.com/stretchr/testify/assert" +) + +const kaiRawRPC = "https://dev-1.kardiachain.io" + +func TestGetFullHeader(t *testing.T) { + cli, err := Dial(kaiRawRPC) + assert.NoError(t, err) + ctx := context.Background() + header, err := cli.FullHeaderByNumber(ctx, big.NewInt(3)) + assert.NoError(t, err) + assert.Equal(t, header.Commit.Hash().Hex(), header.Header.LastCommitHash.Hex()) + assert.Equal(t, header.ValidatorSet.Hash().Hex(), header.Header.ValidatorsHash.Hex()) +} + +// func TestGetTransaction(t *testing.T) { +// cli, err := Dial(kaiRawRPC) +// assert.NoError(t, err) +// ctx := context.Background() +// tx, isPending, err := cli.TransactionByHash(ctx, common.HexToHash("0xd84e553e62c61f3c3343d7d215c72616907e50bac9235460ba55e878a59d2399")) +// t.Logf("tx %+v isPending %v err %v", tx, isPending, err) +// assert.NoError(t, err) +// } + +// func TestGetTransactionReceipt(t *testing.T) { +// cli, err := Dial(kaiRawRPC) +// assert.NoError(t, err) +// ctx := context.Background() +// receipt, err := cli.TransactionReceipt(ctx, common.HexToHash("0xd84e553e62c61f3c3343d7d215c72616907e50bac9235460ba55e878a59d2399")) +// t.Logf("receipt %+v err %v", receipt, err) +// assert.NoError(t, err) +// } + +// // Verify that Client implements the ethereum interfaces. +// var ( +// _ = ethereum.ChainReader(&Client{}) +// _ = ethereum.TransactionReader(&Client{}) +// _ = ethereum.ChainStateReader(&Client{}) +// _ = ethereum.ChainSyncReader(&Client{}) +// _ = ethereum.ContractCaller(&Client{}) +// _ = ethereum.GasEstimator(&Client{}) +// _ = ethereum.GasPricer(&Client{}) +// _ = ethereum.LogFilterer(&Client{}) +// _ = ethereum.PendingStateReader(&Client{}) +// // _ = ethereum.PendingStateEventer(&Client{}) +// _ = ethereum.PendingContractCaller(&Client{}) +// ) + +// func TestToFilterArg(t *testing.T) { +// blockHashErr := fmt.Errorf("cannot specify both BlockHash and FromBlock/ToBlock") +// addresses := []common.Address{ +// common.HexToAddress("0xD36722ADeC3EdCB29c8e7b5a47f352D701393462"), +// } +// blockHash := common.HexToHash( +// "0xeb94bb7d78b73657a9d7a99792413f50c0a45c51fc62bdcb08a53f18e9a2b4eb", +// ) + +// for _, testCase := range []struct { +// name string +// input ethereum.FilterQuery +// output interface{} +// err error +// }{ +// { +// "without BlockHash", +// ethereum.FilterQuery{ +// Addresses: addresses, +// FromBlock: big.NewInt(1), +// ToBlock: big.NewInt(2), +// Topics: [][]common.Hash{}, +// }, +// map[string]interface{}{ +// "address": addresses, +// "fromBlock": "0x1", +// "toBlock": "0x2", +// "topics": [][]common.Hash{}, +// }, +// nil, +// }, +// { +// "with nil fromBlock and nil toBlock", +// ethereum.FilterQuery{ +// Addresses: addresses, +// Topics: [][]common.Hash{}, +// }, +// map[string]interface{}{ +// "address": addresses, +// "fromBlock": "0x0", +// "toBlock": "latest", +// "topics": [][]common.Hash{}, +// }, +// nil, +// }, +// { +// "with negative fromBlock and negative toBlock", +// ethereum.FilterQuery{ +// Addresses: addresses, +// FromBlock: big.NewInt(-1), +// ToBlock: big.NewInt(-1), +// Topics: [][]common.Hash{}, +// }, +// map[string]interface{}{ +// "address": addresses, +// "fromBlock": "pending", +// "toBlock": "pending", +// "topics": [][]common.Hash{}, +// }, +// nil, +// }, +// { +// "with blockhash", +// ethereum.FilterQuery{ +// Addresses: addresses, +// BlockHash: &blockHash, +// Topics: [][]common.Hash{}, +// }, +// map[string]interface{}{ +// "address": addresses, +// "blockHash": blockHash, +// "topics": [][]common.Hash{}, +// }, +// nil, +// }, +// { +// "with blockhash and from block", +// ethereum.FilterQuery{ +// Addresses: addresses, +// BlockHash: &blockHash, +// FromBlock: big.NewInt(1), +// Topics: [][]common.Hash{}, +// }, +// nil, +// blockHashErr, +// }, +// { +// "with blockhash and to block", +// ethereum.FilterQuery{ +// Addresses: addresses, +// BlockHash: &blockHash, +// ToBlock: big.NewInt(1), +// Topics: [][]common.Hash{}, +// }, +// nil, +// blockHashErr, +// }, +// { +// "with blockhash and both from / to block", +// ethereum.FilterQuery{ +// Addresses: addresses, +// BlockHash: &blockHash, +// FromBlock: big.NewInt(1), +// ToBlock: big.NewInt(2), +// Topics: [][]common.Hash{}, +// }, +// nil, +// blockHashErr, +// }, +// } { +// t.Run(testCase.name, func(t *testing.T) { +// output, err := toFilterArg(testCase.input) +// if (testCase.err == nil) != (err == nil) { +// t.Fatalf("expected error %v but got %v", testCase.err, err) +// } +// if testCase.err != nil { +// if testCase.err.Error() != err.Error() { +// t.Fatalf("expected error %v but got %v", testCase.err, err) +// } +// } else if !reflect.DeepEqual(testCase.output, output) { +// t.Fatalf("expected filter arg %v but got %v", testCase.output, output) +// } +// }) +// } +// } + +// var ( +// testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") +// testAddr = crypto.PubkeyToAddress(testKey.PublicKey) +// testBalance = big.NewInt(2e10) +// ) + +// func newTestBackend(t *testing.T) (*node.Node, []*types.Block) { +// // Generate test chain. +// genesis, blocks := generateTestChain() + +// // Start Ethereum service. +// var ethservice *eth.Ethereum +// n, err := node.New(&node.Config{}) +// n.Register(func(ctx *node.ServiceContext) (node.Service, error) { +// config := ð.Config{Genesis: genesis} +// config.Ethash.PowMode = ethash.ModeFake +// ethservice, err = eth.New(ctx, config) +// return ethservice, err +// }) + +// // Import the test chain. +// if err := n.Start(); err != nil { +// t.Fatalf("can't start test node: %v", err) +// } +// if _, err := ethservice.BlockChain().InsertChain(blocks[1:]); err != nil { +// t.Fatalf("can't import test blocks: %v", err) +// } +// return n, blocks +// } + +// func generateTestChain() (*core.Genesis, []*types.Block) { +// db := rawdb.NewMemoryDatabase() +// config := params.AllEthashProtocolChanges +// genesis := &core.Genesis{ +// Config: config, +// Alloc: core.GenesisAlloc{testAddr: {Balance: testBalance}}, +// ExtraData: []byte("test genesis"), +// Timestamp: 9000, +// } +// generate := func(i int, g *core.BlockGen) { +// g.OffsetTime(5) +// g.SetExtra([]byte("test")) +// } +// gblock := genesis.ToBlock(db) +// engine := ethash.NewFaker() +// blocks, _ := core.GenerateChain(config, gblock, engine, db, 1, generate) +// blocks = append([]*types.Block{gblock}, blocks...) +// return genesis, blocks +// } + +// func TestHeader(t *testing.T) { +// backend, chain := newTestBackend(t) +// client, _ := backend.Attach() +// defer backend.Stop() +// defer client.Close() + +// tests := map[string]struct { +// block *big.Int +// want *types.Header +// wantErr error +// }{ +// "genesis": { +// block: big.NewInt(0), +// want: chain[0].Header(), +// }, +// "first_block": { +// block: big.NewInt(1), +// want: chain[1].Header(), +// }, +// "future_block": { +// block: big.NewInt(1000000000), +// want: nil, +// }, +// } +// for name, tt := range tests { +// t.Run(name, func(t *testing.T) { +// ec := NewClient(client) +// ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) +// defer cancel() + +// got, err := ec.HeaderByNumber(ctx, tt.block) +// if tt.wantErr != nil && (err == nil || err.Error() != tt.wantErr.Error()) { +// t.Fatalf("HeaderByNumber(%v) error = %q, want %q", tt.block, err, tt.wantErr) +// } +// if got != nil && got.Number.Sign() == 0 { +// got.Number = big.NewInt(0) // hack to make DeepEqual work +// } +// if !reflect.DeepEqual(got, tt.want) { +// t.Fatalf("HeaderByNumber(%v)\n = %v\nwant %v", tt.block, got, tt.want) +// } +// }) +// } +// } + +// func TestBalanceAt(t *testing.T) { +// backend, _ := newTestBackend(t) +// client, _ := backend.Attach() +// defer backend.Stop() +// defer client.Close() + +// tests := map[string]struct { +// account common.Address +// block *big.Int +// want *big.Int +// wantErr error +// }{ +// "valid_account": { +// account: testAddr, +// block: big.NewInt(1), +// want: testBalance, +// }, +// "non_existent_account": { +// account: common.Address{1}, +// block: big.NewInt(1), +// want: big.NewInt(0), +// }, +// "future_block": { +// account: testAddr, +// block: big.NewInt(1000000000), +// want: big.NewInt(0), +// wantErr: errors.New("header not found"), +// }, +// } +// for name, tt := range tests { +// t.Run(name, func(t *testing.T) { +// ec := NewClient(client) +// ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) +// defer cancel() + +// got, err := ec.BalanceAt(ctx, tt.account, tt.block) +// if tt.wantErr != nil && (err == nil || err.Error() != tt.wantErr.Error()) { +// t.Fatalf("BalanceAt(%x, %v) error = %q, want %q", tt.account, tt.block, err, tt.wantErr) +// } +// if got.Cmp(tt.want) != 0 { +// t.Fatalf("BalanceAt(%x, %v) = %v, want %v", tt.account, tt.block, got, tt.want) +// } +// }) +// } +// } + +// func TestTransactionInBlockInterrupted(t *testing.T) { +// backend, _ := newTestBackend(t) +// client, _ := backend.Attach() +// defer backend.Stop() +// defer client.Close() + +// ec := NewClient(client) +// ctx, cancel := context.WithCancel(context.Background()) +// cancel() +// tx, err := ec.TransactionInBlock(ctx, common.Hash{1}, 1) +// if tx != nil { +// t.Fatal("transaction should be nil") +// } +// if err == nil { +// t.Fatal("error should not be nil") +// } +// } + +// func TestChainID(t *testing.T) { +// backend, _ := newTestBackend(t) +// client, _ := backend.Attach() +// defer backend.Stop() +// defer client.Close() +// ec := NewClient(client) + +// id, err := ec.ChainID(context.Background()) +// if err != nil { +// t.Fatalf("unexpected error: %v", err) +// } +// if id == nil || id.Cmp(params.AllEthashProtocolChanges.ChainID) != 0 { +// t.Fatalf("ChainID returned wrong number: %+v", id) +// } +// } diff --git a/log/log.go b/log/log.go new file mode 100644 index 0000000..2c2a7c7 --- /dev/null +++ b/log/log.go @@ -0,0 +1,405 @@ +/* + * Copyright (C) 2018 The ontology Authors + * This file is part of The ontology library. + * + * The ontology is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ontology 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with The ontology. If not, see . + */ + +package log + +import ( + "bytes" + "errors" + "fmt" + "io" + "io/ioutil" + "log" + "os" + "path/filepath" + "runtime" + "strconv" + "strings" + "time" +) + +const ( + Blue = "0;34" + Red = "0;31" + Green = "0;32" + Yellow = "0;33" + Cyan = "0;36" + Pink = "1;35" +) + +func Color(code, msg string) string { + return fmt.Sprintf("\033[%sm%s\033[m", code, msg) +} + +const ( + TraceLog = iota + DebugLog + InfoLog + WarnLog + ErrorLog + FatalLog + MaxLevelLog +) + +var ( + levels = map[int]string{ + DebugLog: Color(Green, "[DEBUG]"), + InfoLog: Color(Cyan, "[INFO ]"), + WarnLog: Color(Yellow, "[WARN ]"), + ErrorLog: Color(Red, "[ERROR]"), + FatalLog: Color(Red, "[FATAL]"), + TraceLog: Color(Pink, "[TRACE]"), + } + Stdout = os.Stdout +) + +const ( + NAME_PREFIX = "LEVEL" + CALL_DEPTH = 2 + DEFAULT_MAX_LOG_SIZE = 20 + BYTE_TO_MB = 1024 * 1024 + PATH = "./logoutput/" +) + +func GetGID() uint64 { + var buf [64]byte + b := buf[:runtime.Stack(buf[:], false)] + b = bytes.TrimPrefix(b, []byte("goroutine ")) + b = b[:bytes.IndexByte(b, ' ')] + n, _ := strconv.ParseUint(string(b), 10, 64) + return n +} + +var Log *Logger + +func init() { + //Default print to console + InitLog(InfoLog, Stdout) +} + +func LevelName(level int) string { + if name, ok := levels[level]; ok { + return name + } + return NAME_PREFIX + strconv.Itoa(level) +} + +func NameLevel(name string) int { + for k, v := range levels { + if v == name { + return k + } + } + var level int + if strings.HasPrefix(name, NAME_PREFIX) { + level, _ = strconv.Atoi(name[len(NAME_PREFIX):]) + } + return level +} + +type Logger struct { + level int + logger *log.Logger + logFile *os.File +} + +func New(out io.Writer, prefix string, flag, level int, file *os.File) *Logger { + return &Logger{ + level: level, + logger: log.New(out, prefix, flag), + logFile: file, + } +} + +func (l *Logger) SetDebugLevel(level int) error { + if level > MaxLevelLog || level < 0 { + return errors.New("Invalid Debug Level") + } + + l.level = level + return nil +} + +func (l *Logger) Output(level int, a ...interface{}) error { + if level >= l.level { + gid := GetGID() + gidStr := strconv.FormatUint(gid, 10) + + a = append([]interface{}{LevelName(level), "GID", + gidStr + ","}, a...) + + return l.logger.Output(CALL_DEPTH, fmt.Sprintln(a...)) + } + return nil +} + +func (l *Logger) Outputf(level int, format string, v ...interface{}) error { + if level >= l.level { + gid := GetGID() + v = append([]interface{}{LevelName(level), "GID", + gid}, v...) + + return l.logger.Output(CALL_DEPTH, fmt.Sprintf("%s %s %d, "+format+"\n", v...)) + } + return nil +} + +func (l *Logger) Trace(a ...interface{}) { + l.Output(TraceLog, a...) +} + +func (l *Logger) Tracef(format string, a ...interface{}) { + l.Outputf(TraceLog, format, a...) +} + +func (l *Logger) Debug(a ...interface{}) { + l.Output(DebugLog, a...) +} + +func (l *Logger) Debugf(format string, a ...interface{}) { + l.Outputf(DebugLog, format, a...) +} + +func (l *Logger) Info(a ...interface{}) { + l.Output(InfoLog, a...) +} + +func (l *Logger) Infof(format string, a ...interface{}) { + l.Outputf(InfoLog, format, a...) +} + +func (l *Logger) Warn(a ...interface{}) { + l.Output(WarnLog, a...) +} + +func (l *Logger) Warnf(format string, a ...interface{}) { + l.Outputf(WarnLog, format, a...) +} + +func (l *Logger) Error(a ...interface{}) { + l.Output(ErrorLog, a...) +} + +func (l *Logger) Errorf(format string, a ...interface{}) { + l.Outputf(ErrorLog, format, a...) +} + +func (l *Logger) Fatal(a ...interface{}) { + l.Output(FatalLog, a...) +} + +func (l *Logger) Fatalf(format string, a ...interface{}) { + l.Outputf(FatalLog, format, a...) +} + +func Trace(a ...interface{}) { + if TraceLog < Log.level { + return + } + + pc := make([]uintptr, 10) + runtime.Callers(2, pc) + f := runtime.FuncForPC(pc[0]) + file, line := f.FileLine(pc[0]) + fileName := filepath.Base(file) + + nameFull := f.Name() + nameEnd := filepath.Ext(nameFull) + funcName := strings.TrimPrefix(nameEnd, ".") + + a = append([]interface{}{funcName + "()", fileName + ":" + strconv.Itoa(line)}, a...) + + Log.Trace(a...) +} + +func Tracef(format string, a ...interface{}) { + if TraceLog < Log.level { + return + } + + pc := make([]uintptr, 10) + runtime.Callers(2, pc) + f := runtime.FuncForPC(pc[0]) + file, line := f.FileLine(pc[0]) + fileName := filepath.Base(file) + + nameFull := f.Name() + nameEnd := filepath.Ext(nameFull) + funcName := strings.TrimPrefix(nameEnd, ".") + + a = append([]interface{}{funcName, fileName, line}, a...) + + Log.Tracef("%s() %s:%d "+format, a...) +} + +func Debug(a ...interface{}) { + if DebugLog < Log.level { + return + } + + pc := make([]uintptr, 10) + runtime.Callers(2, pc) + f := runtime.FuncForPC(pc[0]) + file, line := f.FileLine(pc[0]) + fileName := filepath.Base(file) + + a = append([]interface{}{f.Name(), fileName + ":" + strconv.Itoa(line)}, a...) + + Log.Debug(a...) +} + +func Debugf(format string, a ...interface{}) { + if DebugLog < Log.level { + return + } + + pc := make([]uintptr, 10) + runtime.Callers(2, pc) + f := runtime.FuncForPC(pc[0]) + file, line := f.FileLine(pc[0]) + fileName := filepath.Base(file) + + a = append([]interface{}{f.Name(), fileName, line}, a...) + + Log.Debugf("%s %s:%d "+format, a...) +} + +func Info(a ...interface{}) { + Log.Info(a...) +} + +func Warn(a ...interface{}) { + Log.Warn(a...) +} + +func Error(a ...interface{}) { + Log.Error(a...) +} + +func Fatal(a ...interface{}) { + Log.Fatal(a...) +} + +func Infof(format string, a ...interface{}) { + Log.Infof(format, a...) +} + +func Warnf(format string, a ...interface{}) { + Log.Warnf(format, a...) +} + +func Errorf(format string, a ...interface{}) { + Log.Errorf(format, a...) +} + +func Fatalf(format string, a ...interface{}) { + Log.Fatalf(format, a...) +} + +func FileOpen(path string) (*os.File, error) { + if fi, err := os.Stat(path); err == nil { + if !fi.IsDir() { + return nil, fmt.Errorf("open %s: not a directory", path) + } + } else if os.IsNotExist(err) { + if err := os.MkdirAll(path, 0766); err != nil { + return nil, err + } + } else { + return nil, err + } + + var currenttime = time.Now().Format("2006-01-02_15.04.05") + + logfile, err := os.OpenFile(path+currenttime+"_LOG.log", os.O_RDWR|os.O_CREATE, 0666) + if err != nil { + return nil, err + } + return logfile, nil +} + +//Init deprecated, use InitLog instead +func Init(a ...interface{}) { + os.Stderr.WriteString("warning: use of deprecated Init. Use InitLog instead\n") + InitLog(InfoLog, a...) +} + +func InitLog(logLevel int, a ...interface{}) { + writers := []io.Writer{} + var logFile *os.File + var err error + if len(a) == 0 { + writers = append(writers, ioutil.Discard) + } else { + for _, o := range a { + switch o.(type) { + case string: + logFile, err = FileOpen(o.(string)) + if err != nil { + fmt.Println("error: open log file failed") + os.Exit(1) + } + writers = append(writers, logFile) + case *os.File: + writers = append(writers, o.(*os.File)) + default: + fmt.Println("error: invalid log location") + os.Exit(1) + } + } + } + fileAndStdoutWrite := io.MultiWriter(writers...) + Log = New(fileAndStdoutWrite, "", log.Ldate|log.Lmicroseconds, logLevel, logFile) +} + +func GetLogFileSize() (int64, error) { + f, e := Log.logFile.Stat() + if e != nil { + return 0, e + } + return f.Size(), nil +} + +func GetMaxLogChangeInterval(maxLogSize int64) int64 { + if maxLogSize != 0 { + return (maxLogSize * BYTE_TO_MB) + } else { + return (DEFAULT_MAX_LOG_SIZE * BYTE_TO_MB) + } +} + +func CheckIfNeedNewFile() bool { + logFileSize, err := GetLogFileSize() + maxLogFileSize := GetMaxLogChangeInterval(0) + if err != nil { + return false + } + if logFileSize > maxLogFileSize { + return true + } else { + return false + } +} + +func ClosePrintLog() error { + var err error + if Log.logFile != nil { + err = Log.logFile.Close() + } + return err +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..e60ab34 --- /dev/null +++ b/main.go @@ -0,0 +1,188 @@ +/* +* Copyright (C) 2020 The poly network Authors +* This file is part of The poly network library. +* +* The poly network is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* The poly network 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 Lesser General Public License for more details. +* You should have received a copy of the GNU Lesser General Public License +* along with The poly network . If not, see . + */ +package main + +import ( + "fmt" + "os" + "os/signal" + "runtime" + "syscall" + + "github.com/ethereum/go-ethereum/ethclient" + "github.com/polynetwork/kai-relayer/cmd" + "github.com/polynetwork/kai-relayer/config" + "github.com/polynetwork/kai-relayer/db" + "github.com/polynetwork/kai-relayer/kaiclient" + "github.com/polynetwork/kai-relayer/log" + "github.com/polynetwork/kai-relayer/manager" + sdk "github.com/polynetwork/poly-go-sdk" + "github.com/urfave/cli" +) + +var ConfigPath string +var LogDir string +var StartHeight uint64 +var PolyStartHeight uint64 +var StartForceHeight uint64 + +func setupApp() *cli.App { + app := cli.NewApp() + app.Usage = "Kai relayer Service" + app.Action = startServer + app.Version = config.Version + app.Copyright = "Copyright in 2019 The Ontology Authors" + app.Flags = []cli.Flag{ + cmd.LogLevelFlag, + cmd.ConfigPathFlag, + cmd.KaiStartFlag, + cmd.KaiStartForceFlag, + cmd.PolyStartFlag, + cmd.LogDir, + } + app.Commands = []cli.Command{} + app.Before = func(context *cli.Context) error { + runtime.GOMAXPROCS(runtime.NumCPU()) + return nil + } + return app +} + +func startServer(ctx *cli.Context) { + // get all cmd flag + logLevel := ctx.GlobalInt(cmd.GetFlagName(cmd.LogLevelFlag)) + + ld := ctx.GlobalString(cmd.GetFlagName(cmd.LogDir)) + if ld == "" { + log.InitLog(logLevel, "./Log/", log.Stdout) + } else { + log.InitLog(logLevel, ld, log.Stdout) + } + + configPath := ctx.GlobalString(cmd.GetFlagName(cmd.ConfigPathFlag)) + if configPath != "" { + ConfigPath = configPath + } + kaistart := ctx.GlobalUint64(cmd.GetFlagName(cmd.KaiStartFlag)) + if kaistart > 0 { + StartHeight = kaistart + } + + StartForceHeight = 0 + kaistartforce := ctx.GlobalUint64(cmd.GetFlagName(cmd.KaiStartForceFlag)) + if kaistartforce > 0 { + StartForceHeight = kaistartforce + } + polyStart := ctx.GlobalUint64(cmd.GetFlagName(cmd.PolyStartFlag)) + if polyStart > 0 { + PolyStartHeight = polyStart + } + + // read config + servConfig := config.NewServiceConfig(ConfigPath) + if servConfig == nil { + log.Errorf("startServer - create config failed!") + return + } + + // create poly sdk + polySdk := sdk.NewPolySdk() + err := setUpPoly(polySdk, servConfig.PolyConfig.RestURL) + if err != nil { + log.Errorf("startServer - failed to setup poly sdk: %v", err) + return + } + + // create kai sdk + kclient, err := kaiclient.Dial(servConfig.KAIConfig.RestURL) + if err != nil { + log.Errorf("startServer - cannot dial sync node, err: %s", err) + return + } + + ethclient, err := ethclient.Dial(servConfig.KAIConfig.RestURL) + if err != nil { + log.Errorf("startServer - cannot dial sync node ethclient, err: %s", err) + return + } + var boltDB *db.BoltDB + if servConfig.BoltDbPath == "" { + boltDB, err = db.NewBoltDB("boltdb") + } else { + boltDB, err = db.NewBoltDB(servConfig.BoltDbPath) + } + if err != nil { + log.Fatalf("db.NewWaitingDB error:%s", err) + return + } + + initKaiServer(servConfig, polySdk, ethclient, kclient, boltDB) + initPolyServer(servConfig, polySdk, ethclient, kclient, boltDB) + waitToExit() +} + +func setUpPoly(poly *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 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("waitToExit - KAI relayer received exit signal:%v.", sig.String()) + close(exit) + break + } + }() + <-exit +} + +func initKaiServer(servConfig *config.ServiceConfig, polysdk *sdk.PolySdk, ethclient *ethclient.Client, kclient *kaiclient.Client, boltDB *db.BoltDB) { + mgr, err := manager.NewKardiaManager(servConfig, StartHeight, StartForceHeight, polysdk, ethclient, kclient, boltDB) + if err != nil { + log.Error("initKAIServer - KAI service start err: %s", err.Error()) + return + } + go mgr.MonitorChain() + go mgr.MonitorDeposit() + go mgr.CheckDeposit() +} + +func initPolyServer(servConfig *config.ServiceConfig, polysdk *sdk.PolySdk, ethclient *ethclient.Client, kclient *kaiclient.Client, boltDB *db.BoltDB) { + mgr, err := manager.NewPolyManager(servConfig, uint32(PolyStartHeight), polysdk, ethclient, kclient, boltDB) + if err != nil { + log.Error("initPolyServer - PolyServer service start failed") + return + } + go mgr.MonitorChain() +} + +func main() { + log.Infof("main - KAI relayer starting...") + if err := setupApp().Run(os.Args); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} diff --git a/manager/kardiachainmanager.go b/manager/kardiachainmanager.go new file mode 100644 index 0000000..62837b4 --- /dev/null +++ b/manager/kardiachainmanager.go @@ -0,0 +1,529 @@ +/* +* Copyright (C) 2020 The poly network Authors +* This file is part of The poly network library. +* +* The poly network is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* The poly network 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 Lesser General Public License for more details. +* You should have received a copy of the GNU Lesser General Public License +* along with The poly network . If not, see . + */ +package manager + +import ( + "encoding/binary" + "encoding/hex" + "encoding/json" + "fmt" + "math/big" + "strings" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/polynetwork/eth-contracts/go_abi/eccm_abi" + "github.com/polynetwork/kai-relayer/config" + "github.com/polynetwork/kai-relayer/db" + "github.com/polynetwork/kai-relayer/kaiclient" + + "context" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/polynetwork/kai-relayer/log" + "github.com/polynetwork/kai-relayer/tools" + sdk "github.com/polynetwork/poly-go-sdk" + "github.com/polynetwork/poly/common" + "github.com/polynetwork/poly/native/service/cross_chain_manager/eth" + scom "github.com/polynetwork/poly/native/service/header_sync/common" + "github.com/polynetwork/poly/native/service/utils" + autils "github.com/polynetwork/poly/native/service/utils" +) + +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 +} + +type KardiaManager struct { + config *config.ServiceConfig + restClient *tools.RestClient + client *ethclient.Client + kaiclient *kaiclient.Client + currentHeight uint64 + forceHeight uint64 + lockerContract *bind.BoundContract + polySdk *sdk.PolySdk + polySigner *sdk.Account + exitChan chan int + header4sync [][]byte + crosstx4sync []*CrossTransfer + db *db.BoltDB +} + +func NewKardiaManager(servconfig *config.ServiceConfig, startheight uint64, startforceheight uint64, ontsdk *sdk.PolySdk, ethclient *ethclient.Client, client *kaiclient.Client, boltDB *db.BoltDB) (*KardiaManager, error) { + var wallet *sdk.Wallet + var err error + + if !common.FileExisted(servconfig.PolyConfig.WalletFile) { + wallet, err = ontsdk.CreateWallet(servconfig.PolyConfig.WalletFile) + if err != nil { + return nil, err + } + } else { + wallet, err = ontsdk.OpenWallet(servconfig.PolyConfig.WalletFile) + if err != nil { + log.Errorf("NewKaiManager - wallet open error: %s", err.Error()) + return nil, err + } + } + signer, err := wallet.GetDefaultAccount([]byte(servconfig.PolyConfig.WalletPwd)) + if err != nil || signer == nil { + signer, err = wallet.NewDefaultSettingAccount([]byte(servconfig.PolyConfig.WalletPwd)) + if err != nil { + log.Errorf("NewKaiManager - wallet password error") + return nil, err + } + + err = wallet.Save() + if err != nil { + return nil, err + } + } + log.Infof("NewKaiManager - poly address: %s", signer.Address.ToBase58()) + + mgr := &KardiaManager{ + config: servconfig, + exitChan: make(chan int), + currentHeight: startheight, + forceHeight: startforceheight, + restClient: tools.NewRestClient(), + client: ethclient, + kaiclient: client, + polySdk: ontsdk, + polySigner: signer, + header4sync: make([][]byte, 0), + crosstx4sync: make([]*CrossTransfer, 0), + db: boltDB, + } + err = mgr.init() + if err != nil { + return nil, err + } else { + return mgr, nil + } +} + +func (this *KardiaManager) MonitorChain() { + fetchBlockTicker := time.NewTicker(config.KAI_MONITOR_INTERVAL) + var blockHandleResult bool + backtrace := uint64(1) + for { + select { + case <-fetchBlockTicker.C: + height, err := tools.GetNodeHeight(this.config.KAIConfig.RestURL, this.restClient) + if err != nil { + log.Infof("MonitorChain - cannot get node height, err: %s", err) + continue + } + if height-this.currentHeight <= config.KAI_USEFUL_BLOCK_NUM { + continue + } + log.Infof("MonitorChain - kai height is %d", height) + blockHandleResult = true + for this.currentHeight < height-config.KAI_USEFUL_BLOCK_NUM { + blockHandleResult = this.handleNewBlock(this.currentHeight + 1) + if !blockHandleResult { + break + } + this.currentHeight++ + // try to commit header if more than 50 headers needed to be syned + if len(this.header4sync) > 0 { + if this.commitHeader() != 0 { + log.Error("MonitorChain - commit header failed.", "height", this.currentHeight) + blockHandleResult = false + break + } + this.header4sync = make([][]byte, 0) + } + } + if !blockHandleResult { + continue + } + + if len(this.header4sync) > 0 { + // try to commit lastest header when we are at latest height + commitHeaderResult := this.commitHeader() + if commitHeaderResult > 0 { + log.Error("MonitorChain - commit header failed.", "height", this.currentHeight) + continue + } else if commitHeaderResult == 0 { + backtrace = 1 + this.header4sync = make([][]byte, 0) + continue + } else { + latestHeight := this.findLastestHeight() + if latestHeight == 0 { + continue + } + this.currentHeight = latestHeight - backtrace + backtrace++ + log.Errorf("MonitorChain - back to height: %d", this.currentHeight) + this.header4sync = make([][]byte, 0) + } + } + case <-this.exitChan: + return + } + } +} +func (this *KardiaManager) init() error { + // get latest height + latestHeight := this.findLastestHeight() + if latestHeight == 0 { + return fmt.Errorf("init - the genesis block has not synced!") + } + log.Infof("init - latest synced height: %d", latestHeight) + if this.forceHeight > 0 && this.forceHeight < latestHeight { + this.currentHeight = this.forceHeight + } else { + this.currentHeight = latestHeight + } + // this.currentHeight = 760565 + return nil +} + +func (this *KardiaManager) findLastestHeight() uint64 { + // try to get key + contractAddress := autils.HeaderSyncContractAddress + key := append([]byte(scom.EPOCH_SWITCH), utils.GetUint64Bytes(this.config.KAIConfig.SideChainId)...) + // try to get storage + result, err := this.polySdk.GetStorage(contractAddress.ToHexString(), key) + if err != nil { + return 0 + } + + if len(result) == 0 { + return 0 + } else { + return binary.LittleEndian.Uint64(result) + } +} + +func (this *KardiaManager) handleNewBlock(height uint64) bool { + ret := this.handleBlockHeader(height) + if !ret { + log.Errorf("handleNewBlock - handleBlockHeader on height :%d failed", height) + return false + } + ret = this.fetchLockDepositEvents(height-1, this.client) + if !ret { + log.Errorf("handleNewBlock - fetchLockDepositEvents on height :%d failed", height) + } + return true +} + +func (this *KardiaManager) handleBlockHeader(height uint64) bool { + ctx := context.Background() + number := big.NewInt(int64(height)) + header, err := this.kaiclient.HeaderByNumber(ctx, number) + if err != nil { + log.Error("handleBlockHeader - GetNodeHeader on height :%d failed", height, "err", err) + return false + } + + if header.ValidatorsHash.Equal(header.NextValidatorsHash) { + return true + } + + val, _ := this.polySdk.GetStorage(utils.CrossChainManagerContractAddress.ToHexString(), + append(append([]byte(scom.EPOCH_SWITCH), utils.GetUint64Bytes(this.config.KAIConfig.SideChainId)...), + utils.GetUint64Bytes(uint64(header.Height))...)) + // check if this header is not committed on Poly + if len(val) > 0 { + return true + } + + validators, err := this.kaiclient.GetValidators(ctx, number) + if err != nil { + log.Error("handleBlockHeader - GetValidators on height :%d failed", height, "err", err) + return false + } + + commit, err := this.kaiclient.GetCommit(ctx, number.Sub(number, big.NewInt(1))) + if err != nil { + log.Error("handleBlockHeader - GetCommit on height :%d failed", height, "err", err) + return false + } + + fullHeader := &kaiclient.KaiHeader{ + Header: header, + ValidatorSet: validators, + Commit: commit, + } + headerBytes, err := json.Marshal(fullHeader) + if err != nil { + log.Errorf("marshal header on height :%d failed err %s", height, err) + return false + } + this.header4sync = append(this.header4sync, headerBytes) + return true +} + +func (this *KardiaManager) fetchLockDepositEvents(height uint64, client *ethclient.Client) bool { + lockAddress := ethcommon.HexToAddress(this.config.KAIConfig.ECCMContractAddress) + lockContract, err := eccm_abi.NewEthCrossChainManager(lockAddress, client) + if err != nil { + return false + } + opt := &bind.FilterOpts{ + Start: height, + End: &height, + Context: context.Background(), + } + events, err := lockContract.FilterCrossChainEvent(opt, nil) + if err != nil { + log.Errorf("fetchLockDepositEvents - FilterCrossChainEvent error :%s", err.Error()) + return false + } + if events == nil { + log.Infof("fetchLockDepositEvents - no events found on FilterCrossChainEvent") + return false + } + for events.Next() { + evt := events.Event + index := big.NewInt(0) + index.SetBytes(evt.TxId) + crossTx := &CrossTransfer{ + txIndex: tools.EncodeBigInt(index), + txId: evt.Raw.TxHash.Bytes(), + toChain: uint32(evt.ToChainId), + value: []byte(evt.Rawdata), + height: height, + } + sink := common.NewZeroCopySink(nil) + crossTx.Serialization(sink) + err = this.db.PutRetry(sink.Bytes()) + if err != nil { + log.Errorf("fetchLockDepositEvents - this.db.PutRetry error: %s", err) + } + log.Infof("fetchLockDepositEvent - height: %d", height) + } + return true +} + +func (this *KardiaManager) commitHeader() int { + tx, err := this.polySdk.Native.Hs.SyncBlockHeader( + this.config.KAIConfig.SideChainId, + this.polySigner.Address, + this.header4sync, + this.polySigner, + ) + if err != nil { + log.Warnf("commitHeader - send transaction to poly chain err: %s!", err.Error()) + errDesc := err.Error() + if strings.Contains(errDesc, "get the parent block failed") || strings.Contains(errDesc, "missing required field") { + return -1 + } else { + return 1 + } + } + tick := time.NewTicker(100 * time.Millisecond) + var h uint32 + for range tick.C { + h, _ = this.polySdk.GetBlockHeightByTxHash(tx.ToHexString()) + curr, _ := this.polySdk.GetCurrentBlockHeight() + if h > 0 && curr > h { + break + } + } + log.Infof("commitHeader - send transaction %s to poly chain and confirmed on height %d", tx.ToHexString(), h) + return 0 +} +func (this *KardiaManager) MonitorDeposit() { + monitorTicker := time.NewTicker(config.KAI_MONITOR_INTERVAL) + for { + select { + case <-monitorTicker.C: + if err := this.handleLockDepositEvents(); err != nil { + log.Errorf("MonitorChain - handleLockDepositEvents, err: %s", err) + } + case <-this.exitChan: + return + } + } +} +func (this *KardiaManager) handleLockDepositEvents() error { + retryList, err := this.db.GetAllRetry() + if err != nil { + return fmt.Errorf("handleLockDepositEvents - this.db.GetAllRetry error: %s", err) + } + fmt.Println("----------------->", len(retryList)) + for _, v := range retryList { + time.Sleep(time.Second * 1) + crosstx := new(CrossTransfer) + err := crosstx.Deserialization(common.NewZeroCopySource(v)) + if err != nil { + log.Errorf("handleLockDepositEvents - retry.Deserialization error: %s", err) + continue + } + //1. decode events + key := crosstx.txIndex + keyBytes, err := eth.MappingKeyAt(key, "01") + if err != nil { + log.Errorf("handleLockDepositEvents - MappingKeyAt error:%s\n", err.Error()) + continue + } + + heightHex := hexutil.EncodeBig(big.NewInt(int64(crosstx.height + 1))) + proofKey := hexutil.Encode(keyBytes) + //2. get proof + proof, err := tools.GetProof(this.config.KAIConfig.RestURL, this.config.KAIConfig.ECCDContractAddress, proofKey, heightHex, this.restClient) + if err != nil { + log.Errorf("handleLockDepositEvents - error :%s\n", err.Error()) + continue + } + //3. commit proof to poly + txHash, err := this.commitProof(uint32(crosstx.height+1), proof, crosstx.value, crosstx.txId) + if err != nil { + if strings.Contains(err.Error(), "chooseUtxos, current utxo is not enough") { + log.Infof("handleLockDepositEvents - invokeNativeContract error: %s", err) + continue + } else { + if err := this.db.DeleteRetry(v); err != nil { + log.Errorf("handleLockDepositEvents - this.db.DeleteRetry error: %s", err) + } + log.Errorf("handleLockDepositEvents - invokeNativeContract error: %s", err) + continue + } + } + //4. put to check db for checking + err = this.db.PutCheck(txHash, v) + if err != nil { + log.Errorf("handleLockDepositEvents - this.db.PutCheck error: %s", err) + } + err = this.db.DeleteRetry(v) + if err != nil { + log.Errorf("handleLockDepositEvents - this.db.PutCheck error: %s", err) + } + log.Infof("handleLockDepositEvents - syncProofToAlia txHash is %s", txHash) + } + return nil +} +func (this *KardiaManager) commitProof(height uint32, proof []byte, value []byte, txhash []byte) (string, error) { + ctx := context.Background() + header, err := this.kaiclient.FullHeaderByNumber(ctx, big.NewInt(int64(height))) + if err != nil { + return "", err + } + + headerBytes, err := json.Marshal(header) + if err != nil { + return "", err + } + + log.Infof("commit proof, height: %d, proof: %s, value: %s, txhash: %s", height, string(proof), hex.EncodeToString(value), hex.EncodeToString(txhash)) + tx, err := this.polySdk.Native.Ccm.ImportOuterTransfer( + this.config.KAIConfig.SideChainId, + value, + height, + proof, + ethcommon.Hex2Bytes(this.polySigner.Address.ToHexString()), + headerBytes, + this.polySigner) + if err != nil { + return "", err + } else { + log.Infof("commitProof - send transaction to poly chain: %s, height: %d", tx.ToHexString(), height) + return tx.ToHexString(), nil + } +} + +func (this *KardiaManager) CheckDeposit() { + checkTicker := time.NewTicker(config.KAI_MONITOR_INTERVAL) + for { + select { + case <-checkTicker.C: + // try to check deposit + _ = this.checkLockDepositEvents() + case <-this.exitChan: + return + } + } +} +func (this *KardiaManager) checkLockDepositEvents() error { + checkMap, err := this.db.GetAllCheck() + if err != nil { + return fmt.Errorf("checkLockDepositEvents - this.db.GetAllCheck error: %s", err) + } + for k, v := range checkMap { + time.Sleep(time.Second * 1) + event, err := this.polySdk.GetSmartContractEvent(k) + if err != nil { + return fmt.Errorf("checkLockDepositEvents - this.aliaSdk.GetSmartContractEvent error: %s", err) + } + if event == nil { + log.Infof("checkLockDepositEvents - can not find event of hash %s", k) + continue + } + if event.State != 1 { + log.Infof("checkLockDepositEvents - state of tx %s is not success", k) + err := this.db.PutRetry(v) + if err != nil { + log.Errorf("checkLockDepositEvents - this.db.PutRetry error:%s", err) + } + } else { + err := this.db.DeleteCheck(k) + if err != nil { + log.Errorf("checkLockDepositEvents - this.db.DeleteRetry error:%s", err) + } + } + } + return nil +} diff --git a/manager/polymanager.go b/manager/polymanager.go new file mode 100644 index 0000000..44cdcdb --- /dev/null +++ b/manager/polymanager.go @@ -0,0 +1,549 @@ +/* +* Copyright (C) 2020 The poly network Authors +* This file is part of The poly network library. +* +* The poly network is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* The poly network 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 Lesser General Public License for more details. +* You should have received a copy of the GNU Lesser General Public License +* along with The poly network . If not, see . + */ +package manager + +import ( + "context" + "encoding/hex" + "encoding/json" + "fmt" + "math/rand" + "strconv" + "strings" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/abi" + ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ontio/ontology-crypto/keypair" + "github.com/ontio/ontology-crypto/signature" + "github.com/polynetwork/eth-contracts/go_abi/eccd_abi" + "github.com/polynetwork/eth-contracts/go_abi/eccm_abi" + "github.com/polynetwork/kai-relayer/config" + "github.com/polynetwork/kai-relayer/db" + "github.com/polynetwork/kai-relayer/kaiclient" + "github.com/polynetwork/kai-relayer/log" + sdk "github.com/polynetwork/poly-go-sdk" + "github.com/polynetwork/poly/common" + "github.com/polynetwork/poly/common/password" + vconfig "github.com/polynetwork/poly/consensus/vbft/config" + common2 "github.com/polynetwork/poly/native/service/cross_chain_manager/common" + + "math/big" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/polynetwork/kai-relayer/tools" + + polytypes "github.com/polynetwork/poly/core/types" +) + +const ( + ChanLen = 64 +) + +type PolyManager struct { + config *config.ServiceConfig + polySdk *sdk.PolySdk + currentHeight uint32 + contractAbi *abi.ABI + exitChan chan int + db *db.BoltDB + ethClient *ethclient.Client + senders []*EthSender +} + +func NewPolyManager(servCfg *config.ServiceConfig, startblockHeight uint32, polySdk *sdk.PolySdk, ethclient *ethclient.Client, kaiclient *kaiclient.Client, boltDB *db.BoltDB) (*PolyManager, error) { + contractabi, err := abi.JSON(strings.NewReader(eccm_abi.EthCrossChainManagerABI)) + if err != nil { + return nil, err + } + ks := tools.NewKaiKeyStore(servCfg.KAIConfig) + accArr := ks.GetAccounts() + + if len(servCfg.KAIConfig.KeyStorePwdSet) == 0 { + fmt.Println("please input the passwords for ethereum keystore: ") + for _, v := range accArr { + fmt.Printf("For address %s. ", v.Address.String()) + raw, err := password.GetPassword() + if err != nil { + log.Fatalf("failed to input password: %v", err) + panic(err) + } + servCfg.KAIConfig.KeyStorePwdSet[strings.ToLower(v.Address.String())] = string(raw) + } + } + + senders := make([]*EthSender, len(accArr)) + for i, v := range senders { + v = &EthSender{} + v.acc = accArr[i] + pwd, ok := servCfg.KAIConfig.KeyStorePwdSet[strings.ToLower(v.acc.Address.String())] + if !ok { + fmt.Printf("Password for address %s is not found in configuration, please input ", v.acc.Address.String()) + raw, err := password.GetPassword() + if err != nil { + log.Fatalf("failed to input password: %v", err) + panic(err) + } + pwd = string(raw) + } + + if err := ks.TestPwd(v.acc, pwd); err != nil { + log.Fatalf("your password %s for account %s is not working: %v", pwd, v.acc.Address.String(), err) + panic(err) + } + + v.ethClient = ethclient + v.keyStore = ks + v.pwd = pwd + v.config = servCfg + v.polySdk = polySdk + v.contractAbi = &contractabi + v.nonceManager = tools.NewNonceManager(ethclient) + v.cmap = make(map[string]chan *EthTxInfo) + + senders[i] = v + } + return &PolyManager{ + exitChan: make(chan int), + config: servCfg, + polySdk: polySdk, + currentHeight: startblockHeight, + contractAbi: &contractabi, + db: boltDB, + ethClient: ethclient, + senders: senders, + }, nil +} + +func (this *PolyManager) findLatestHeight() uint32 { + address := ethcommon.HexToAddress(this.config.KAIConfig.ECCDContractAddress) + instance, err := eccd_abi.NewEthCrossChainData(address, this.ethClient) + if err != nil { + log.Errorf("findLatestHeight - new eth cross chain failed: %s", err.Error()) + return 0 + } + height, err := instance.GetCurEpochStartHeight(nil) + if err != nil { + log.Errorf("findLatestHeight - GetLatestHeight failed: %s", err.Error()) + return 0 + } + return uint32(height) +} + +func (this *PolyManager) init() bool { + if this.currentHeight > 0 { + log.Infof("PolyManager init - start height from flag: %d", this.currentHeight) + return true + } + this.currentHeight = this.db.GetPolyHeight() + latestHeight := this.findLatestHeight() + if latestHeight > this.currentHeight { + this.currentHeight = latestHeight + log.Infof("PolyManager init - latest height from ECCM: %d", this.currentHeight) + return true + } + log.Infof("PolyManager init - latest height from DB: %d", this.currentHeight) + + return true +} + +func (this *PolyManager) MonitorChain() { + ret := this.init() + if ret == false { + log.Errorf("MonitorChain - init failed\n") + } + monitorTicker := time.NewTicker(config.ONT_MONITOR_INTERVAL) + var blockHandleResult bool + for { + select { + case <-monitorTicker.C: + latestheight, err := this.polySdk.GetCurrentBlockHeight() + if err != nil { + log.Errorf("MonitorChain - get poly chain block height error: %s", err) + continue + } + latestheight-- + if latestheight-this.currentHeight < config.ONT_USEFUL_BLOCK_NUM { + continue + } + log.Infof("MonitorChain - poly chain current height: %d", latestheight) + blockHandleResult = true + for this.currentHeight <= latestheight-config.ONT_USEFUL_BLOCK_NUM { + blockHandleResult = this.handleDepositEvents(this.currentHeight) + if blockHandleResult == false { + break + } + this.currentHeight++ + } + if err = this.db.UpdatePolyHeight(this.currentHeight - 1); err != nil { + log.Errorf("MonitorChain - failed to save height of poly: %v", err) + } + case <-this.exitChan: + return + } + } +} + +func (this *PolyManager) handleDepositEvents(height uint32) bool { + lastEpoch := this.findLatestHeight() + hdr, err := this.polySdk.GetHeaderByHeight(height + 1) + if err != nil { + log.Errorf("handleBlockHeader - GetNodeHeader on height :%d failed", height) + return false + } + isCurr := lastEpoch < height+1 + isEpoch := hdr.NextBookkeeper != common.ADDRESS_EMPTY + var ( + anchor *polytypes.Header + hp string + ) + if !isCurr { + anchor, _ = this.polySdk.GetHeaderByHeight(lastEpoch + 1) + proof, _ := this.polySdk.GetMerkleProof(height+1, lastEpoch+1) + hp = proof.AuditPath + } else if isEpoch { + anchor, _ = this.polySdk.GetHeaderByHeight(height + 2) + proof, _ := this.polySdk.GetMerkleProof(height+1, height+2) + hp = proof.AuditPath + } + + cnt := 0 + events, err := this.polySdk.GetSmartContractEventByBlock(height) + for err != nil { + log.Errorf("handleDepositEvents - get block event at height:%d error: %s", height, err.Error()) + return false + } + for _, event := range events { + for _, notify := range event.Notify { + if notify.ContractAddress == this.config.PolyConfig.EntranceContractAddress { + states := notify.States.([]interface{}) + method, _ := states[0].(string) + if method != "makeProof" { + continue + } + tchainid := uint32(states[2].(float64)) + if tchainid != 2 { + continue + } + cnt++ + sender := this.selectSender() + log.Infof("sender %s is handling poly tx ( hash: %s, height: %d )", + sender.acc.Address.String(), event.TxHash, height) + if !sender.commitDepositEventsWithHeader(hdr, []byte(states[5].(string)), hp, anchor, event.TxHash) { + return false + } + } + } + } + if cnt == 0 && isEpoch && isCurr { + sender := this.selectSender() + return sender.commitHeader(hdr) + } + + return true +} + +func (this *PolyManager) selectSender() *EthSender { + sum := big.NewInt(0) + balArr := make([]*big.Int, len(this.senders)) + for i, v := range this.senders { + RETRY: + bal, err := v.Balance() + if err != nil { + log.Errorf("failed to get balance for %s: %v", v.acc.Address.String(), err) + time.Sleep(time.Second) + goto RETRY + } + sum.Add(sum, bal) + balArr[i] = big.NewInt(sum.Int64()) + } + sum.Rand(rand.New(rand.NewSource(time.Now().Unix())), sum) + for i, v := range balArr { + res := v.Cmp(sum) + if res == 1 || res == 0 { + return this.senders[i] + } + } + return this.senders[0] +} + +func (this *PolyManager) Stop() { + this.exitChan <- 1 + close(this.exitChan) + log.Infof("poly chain manager exit.") +} + +type EthSender struct { + pwd string + acc accounts.Account + keyStore *tools.KaiKeyStore + cmap map[string]chan *EthTxInfo + nonceManager *tools.NonceManager + ethClient *ethclient.Client + polySdk *sdk.PolySdk + config *config.ServiceConfig + contractAbi *abi.ABI +} + +func (this *EthSender) sendTxToEth(info *EthTxInfo) error { + nonce := this.nonceManager.GetAddressNonce(this.acc.Address) + tx := types.NewTransaction(nonce, info.contractAddr, big.NewInt(0), info.gasLimit, info.gasPrice, info.txData) + signedtx, err := this.keyStore.SignTransaction(tx, this.acc, this.pwd) + if err != nil { + this.nonceManager.ReturnNonce(this.acc.Address, nonce) + return fmt.Errorf("commitDepositEventsWithHeader - sign raw tx error and return nonce %d: %v", nonce, err) + } + err = this.ethClient.SendTransaction(context.Background(), signedtx) + if err != nil { + this.nonceManager.ReturnNonce(this.acc.Address, nonce) + return fmt.Errorf("commitDepositEventsWithHeader - send transaction error and return nonce %d: %v\n", nonce, err) + } + hash := signedtx.Hash() + isSuccess := this.waitTransactionConfirm(hash) + if isSuccess { + log.Infof("successful to relay tx to ethereum: (eth_hash: %s, nonce: %d, poly_hash: %s)", + hash.String(), nonce, info.polyTxHash) + } else { + log.Errorf("failed to relay tx to ethereum: (eth_hash: %s, nonce: %d, poly_hash: %s)", + hash.String(), nonce, info.polyTxHash) + } + return nil +} + +func (this *EthSender) commitDepositEventsWithHeader(header *polytypes.Header, key []byte, headerProof string, anchorHeader *polytypes.Header, polyTxHash string) bool { + var ( + sigs []byte + auditpath []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...) + } + } + proof, err := this.polySdk.GetCrossStatesProof(header.Height-1, string(key)) + if err != nil { + log.Errorf("commitDepositEventsWithHeader - err: %v", err) + return false + } + auditpath, _ = hex.DecodeString(proof.AuditPath) + value, _, _, _ := tools.ParseAuditpath(auditpath) + param := &common2.ToMerkleValue{} + if err := param.Deserialization(common.NewZeroCopySource(value)); err != nil { + log.Errorf("commitDepositEventsWithHeader - failed to deserialize MakeTxParam: %v", err) + return false + } + + eccdAddr := ethcommon.HexToAddress(this.config.KAIConfig.ECCDContractAddress) + eccd, err := eccd_abi.NewEthCrossChainData(eccdAddr, this.ethClient) + if err != nil { + panic(fmt.Errorf("failed to new eccm: %v", err)) + } + fromTx := [32]byte{} + copy(fromTx[:], param.TxHash[:32]) + res, _ := eccd.CheckIfFromChainTxExist(nil, param.FromChainID, fromTx) + if res { + log.Debugf("already relayed to eth: ( from_chain_id: %d, from_txhash: %x, param.Txhash: %x)", + param.FromChainID, param.TxHash, param.MakeTxParam.TxHash) + return true + } + log.Infof("poly proof with header, height: %d, key: %s, proof: %s", header.Height-1, string(key), proof.AuditPath) + + rawProof, _ := hex.DecodeString(headerProof) + var rawAnchor []byte + if anchorHeader != nil { + rawAnchor = anchorHeader.ToArray() + } + headerData = header.GetMessage() + txData, err := this.contractAbi.Pack("verifyHeaderAndExecuteTx", auditpath, headerData, rawProof, rawAnchor, sigs) + if err != nil { + log.Errorf("commitDepositEventsWithHeader - err:" + err.Error()) + return false + } + + gasPrice, err := this.ethClient.SuggestGasPrice(context.Background()) + if err != nil { + log.Errorf("commitDepositEventsWithHeader - get suggest sas price failed error: %s", err.Error()) + return false + } + contractaddr := ethcommon.HexToAddress(this.config.KAIConfig.ECCMContractAddress) + callMsg := ethereum.CallMsg{ + From: this.acc.Address, To: &contractaddr, Gas: 0, GasPrice: gasPrice, + Value: big.NewInt(0), Data: txData, + } + gasLimit, err := this.ethClient.EstimateGas(context.Background(), callMsg) + if err != nil { + log.Errorf("commitDepositEventsWithHeader - estimate gas limit error: %s", err.Error()) + return false + } + + k := this.getRouter() + c, ok := this.cmap[k] + if !ok { + c = make(chan *EthTxInfo, ChanLen) + this.cmap[k] = c + go func() { + for v := range c { + if err = this.sendTxToEth(v); err != nil { + log.Errorf("failed to send tx to ethereum: error: %v, txData: %s", err, hex.EncodeToString(v.txData)) + } + } + }() + } + //TODO: could be blocked + c <- &EthTxInfo{ + txData: txData, + contractAddr: contractaddr, + gasPrice: gasPrice, + gasLimit: gasLimit, + polyTxHash: polyTxHash, + } + return true +} + +func (this *EthSender) commitHeader(header *polytypes.Header) bool { + headerdata := header.GetMessage() + var ( + txData []byte + txErr error + bookkeepers []keypair.PublicKey + sigs []byte + ) + gasPrice, err := this.ethClient.SuggestGasPrice(context.Background()) + if err != nil { + log.Errorf("commitHeader - get suggest sas price failed error: %s", err.Error()) + return false + } + for _, sig := range header.SigData { + temp := make([]byte, len(sig)) + copy(temp, sig) + newsig, _ := signature.ConvertToEthCompatible(temp) + sigs = append(sigs, newsig...) + } + + blkInfo := &vconfig.VbftBlockInfo{} + if err := json.Unmarshal(header.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)...) + } + txData, txErr = this.contractAbi.Pack("changeBookKeeper", headerdata, publickeys, sigs) + if txErr != nil { + log.Errorf("commitHeader - err:" + err.Error()) + return false + } + + contractaddr := ethcommon.HexToAddress(this.config.KAIConfig.ECCMContractAddress) + callMsg := ethereum.CallMsg{ + From: this.acc.Address, To: &contractaddr, Gas: 0, GasPrice: gasPrice, + Value: big.NewInt(0), Data: txData, + } + + gasLimit, err := this.ethClient.EstimateGas(context.Background(), callMsg) + if err != nil { + log.Errorf("commitHeader - estimate gas limit error: %s", err.Error()) + return false + } + + nonce := this.nonceManager.GetAddressNonce(this.acc.Address) + tx := types.NewTransaction(nonce, contractaddr, big.NewInt(0), gasLimit, gasPrice, txData) + signedtx, err := this.keyStore.SignTransaction(tx, this.acc, this.pwd) + if err != nil { + log.Errorf("commitHeader - sign raw tx error: %s", err.Error()) + return false + } + if err = this.ethClient.SendTransaction(context.Background(), signedtx); err != nil { + log.Errorf("commitHeader - send transaction error:%s\n", err.Error()) + return false + } + + hash := header.Hash() + txhash := signedtx.Hash() + isSuccess := this.waitTransactionConfirm(txhash) + if isSuccess { + log.Infof("successful to relay poly header to ethereum: (header_hash: %s, height: %d, eth_txhash: %s, nonce: %d)", + hash.ToHexString(), header.Height, txhash.String(), nonce) + } else { + log.Errorf("failed to relay poly header to ethereum: (header_hash: %s, height: %d, eth_txhash: %s, nonce: %d)", + hash.ToHexString(), header.Height, txhash.String(), nonce) + } + return true +} + +func (this *EthSender) getRouter() string { + return strconv.FormatInt(rand.Int63n(this.config.RoutineNum), 10) +} + +func (this *EthSender) Balance() (*big.Int, error) { + balance, err := this.ethClient.BalanceAt(context.Background(), this.acc.Address, nil) + if err != nil { + return nil, err + } + return balance, nil +} + +// TODO: check the status of tx +func (this *EthSender) waitTransactionConfirm(hash ethcommon.Hash) bool { + for { + time.Sleep(time.Second * 1) + _, ispending, err := this.ethClient.TransactionByHash(context.Background(), hash) + if err != nil { + continue + } + log.Debugf("transaction %s is pending: %b\n", hash.String(), ispending) + if ispending == true { + continue + } else { + receipt, err := this.ethClient.TransactionReceipt(context.Background(), hash) + if err != nil { + continue + } + return receipt.Status == types.ReceiptStatusSuccessful + } + } +} + +type EthTxInfo struct { + txData []byte + gasLimit uint64 + gasPrice *big.Int + contractAddr ethcommon.Address + polyTxHash string +} diff --git a/tools/kaikeystore.go b/tools/kaikeystore.go new file mode 100644 index 0000000..e01f9d6 --- /dev/null +++ b/tools/kaikeystore.go @@ -0,0 +1,71 @@ +/* +* Copyright (C) 2020 The poly network Authors +* This file is part of The poly network library. +* +* The poly network is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* The poly network 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 Lesser General Public License for more details. +* You should have received a copy of the GNU Lesser General Public License +* along with The poly network . If not, see . + */ +package tools + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/core/types" + "github.com/polynetwork/kai-relayer/config" + "github.com/polynetwork/kai-relayer/log" +) + +type KaiKeyStore struct { + ks *keystore.KeyStore +} + +func NewKaiKeyStore(sigConfig *config.KAIConfig) *KaiKeyStore { + service := &KaiKeyStore{} + capitalKeyStore := keystore.NewKeyStore(sigConfig.KeyStorePath, keystore.StandardScryptN, + keystore.StandardScryptP) + + accArr := capitalKeyStore.Accounts() + if len(accArr) == 0 { + log.Fatal("relayer has no account") + panic(fmt.Errorf("relayer has no account")) + } + str := "" + for i, v := range accArr { + str += fmt.Sprintf("(no.%d acc: %s), ", i+1, v.Address.String()) + } + log.Infof("relayer are using accounts: [ %s ]", str) + + service.ks = capitalKeyStore + return service +} + +func (this *KaiKeyStore) SignTransaction(tx *types.Transaction, acc accounts.Account, pwd string) (*types.Transaction, error) { + tx, err := this.ks.SignTxWithPassphrase(acc, pwd, tx, nil) + if err != nil { + return nil, err + } + return tx, nil +} + +func (this *KaiKeyStore) GetAccounts() []accounts.Account { + return this.ks.Accounts() +} + +func (this *KaiKeyStore) TestPwd(acc accounts.Account, pwd string) error { + if err := this.ks.Unlock(acc, pwd); err != nil { + return err + } + _ = this.ks.Lock(acc.Address) + return nil +} diff --git a/tools/kaikeystore_test.go b/tools/kaikeystore_test.go new file mode 100644 index 0000000..ab4c683 --- /dev/null +++ b/tools/kaikeystore_test.go @@ -0,0 +1,35 @@ +/* +* Copyright (C) 2020 The poly network Authors +* This file is part of The poly network library. +* +* The poly network is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* The poly network 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 Lesser General Public License for more details. +* You should have received a copy of the GNU Lesser General Public License +* along with The poly network . If not, see . + */ +package tools + +import ( + "testing" +) + +func TestETHSigner_SignTransaction(t *testing.T) { + // cfg := config.NewServiceConfig("./config-debug.json") + // ethsigner := NewKaiKeyStore(cfg.KAIConfig) + // tx := &types.Transaction{} + // tx, err := ethsigner.SignTransaction(tx) + // if err != nil { + // t.Fatal(err) + // } + // v, r, s := tx.RawSignatureValues() + // if v.BitLen()+r.BitLen()+s.BitLen() <= 0 { + // t.Fatal("failed to sign") + // } +} diff --git a/tools/nouncmanager.go b/tools/nouncmanager.go new file mode 100644 index 0000000..04b52e3 --- /dev/null +++ b/tools/nouncmanager.go @@ -0,0 +1,118 @@ +/* +* Copyright (C) 2020 The poly network Authors +* This file is part of The poly network library. +* +* The poly network is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* The poly network 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 Lesser General Public License for more details. +* You should have received a copy of the GNU Lesser General Public License +* along with The poly network . If not, see . + */ +package tools + +import ( + "context" + "sort" + "sync" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/polynetwork/kai-relayer/log" +) + +const clear_nonce_interval = 10 * time.Minute + +type NonceManager struct { + addressNonce map[common.Address]uint64 + returnedNonce map[common.Address]SortedNonceArr + kaiCli *ethclient.Client + lock sync.Mutex +} + +func NewNonceManager(kaiCli *ethclient.Client) *NonceManager { + nonceManager := &NonceManager{ + addressNonce: make(map[common.Address]uint64), + kaiCli: kaiCli, + returnedNonce: make(map[common.Address]SortedNonceArr), + } + go nonceManager.clearNonce() + return nonceManager +} + +// return account nonce, and than nonce++ +func (this *NonceManager) GetAddressNonce(address common.Address) uint64 { + this.lock.Lock() + defer this.lock.Unlock() + + if this.returnedNonce[address].Len() > 0 { + nonce := this.returnedNonce[address][0] + this.returnedNonce[address] = this.returnedNonce[address][1:] + return nonce + } + + // return a new point + nonce, ok := this.addressNonce[address] + if !ok { + // get nonce from eth network + uintNonce, err := this.kaiCli.PendingNonceAt(context.Background(), address) + if err != nil { + log.Errorf("GetAddressNonce: cannot get account %s nonce, err: %s, set it to nil!", + address, err) + } + this.addressNonce[address] = uintNonce + nonce = uintNonce + } + // increase record + this.addressNonce[address]++ + return nonce +} + +func (this *NonceManager) ReturnNonce(addr common.Address, nonce uint64) { + arr, ok := this.returnedNonce[addr] + if !ok { + arr = make([]uint64, 0) + } + arr = append(arr, nonce) + sort.Sort(arr) + this.returnedNonce[addr] = arr +} + +func (this *NonceManager) DecreaseAddressNonce(address common.Address) { + this.lock.Lock() + defer this.lock.Unlock() + + nonce, ok := this.addressNonce[address] + if ok && nonce > 0 { + this.addressNonce[address]-- + } +} + +// clear nonce per +func (this *NonceManager) clearNonce() { + for { + <-time.After(clear_nonce_interval) + this.lock.Lock() + for addr, _ := range this.addressNonce { + delete(this.addressNonce, addr) + } + this.lock.Unlock() + //log.Infof("clearNonce: clear all cache nonce") + } +} + +type SortedNonceArr []uint64 + +func (arr SortedNonceArr) Less(i, j int) bool { + return arr[i] < arr[j] +} + +func (arr SortedNonceArr) Len() int { return len(arr) } + +func (arr SortedNonceArr) Swap(i, j int) { arr[i], arr[j] = arr[j], arr[i] } diff --git a/tools/rest_client.go b/tools/rest_client.go new file mode 100644 index 0000000..ba5989b --- /dev/null +++ b/tools/rest_client.go @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2018 The ontology Authors + * This file is part of The ontology library. + * + * The ontology is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ontology 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with The ontology. If not, see . + */ + +/* +* Copyright (C) 2020 The poly network Authors +* This file is part of The poly network library. +* +* The poly network is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* The poly network 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 Lesser General Public License for more details. +* You should have received a copy of the GNU Lesser General Public License +* along with The poly network . If not, see . + */ +package tools + +import ( + "crypto/tls" + "fmt" + "io/ioutil" + "net/http" + "strings" + "time" +) + +type RestClient struct { + Addr string + restClient *http.Client +} + +func NewRestClient() *RestClient { + return &RestClient{ + restClient: &http.Client{ + Transport: &http.Transport{ + MaxIdleConnsPerHost: 5, + DisableKeepAlives: false, + IdleConnTimeout: time.Second * 300, + ResponseHeaderTimeout: time.Second * 300, + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + }, + Timeout: time.Second * 300, + }, + } +} + +func (self *RestClient) SetAddr(addr string) *RestClient { + self.Addr = addr + return self +} + +func (self *RestClient) SetRestClient(restClient *http.Client) *RestClient { + self.restClient = restClient + return self +} + +func (self *RestClient) SendRestRequest(addr string, data []byte) ([]byte, error) { + resp, err := self.restClient.Post(addr, "application/json", strings.NewReader(string(data))) + if err != nil { + return nil, fmt.Errorf("http post request:%s error:%s", data, err) + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("read rest response body error:%s", err) + } + return body, nil +} diff --git a/tools/rest_client_test.go b/tools/rest_client_test.go new file mode 100644 index 0000000..bf4ebe1 --- /dev/null +++ b/tools/rest_client_test.go @@ -0,0 +1,33 @@ +/* +* Copyright (C) 2020 The poly network Authors +* This file is part of The poly network library. +* +* The poly network is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* The poly network 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 Lesser General Public License for more details. +* You should have received a copy of the GNU Lesser General Public License +* along with The poly network . If not, see . + */ +package tools + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRestClient(t *testing.T) { + client := NewRestClient() + assert.NotNil(t, client) + assert.NotNil(t, client.restClient) + + addr := "ahgakgkajn" + client.SetAddr(addr) + assert.Equal(t, addr, client.Addr) +} diff --git a/tools/util.go b/tools/util.go new file mode 100644 index 0000000..c9c5852 --- /dev/null +++ b/tools/util.go @@ -0,0 +1,286 @@ +/* +* Copyright (C) 2020 The poly network Authors +* This file is part of The poly network library. +* +* The poly network is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* The poly network 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 Lesser General Public License for more details. +* You should have received a copy of the GNU Lesser General Public License +* along with The poly network . If not, see . + */ +package tools + +import ( + "bytes" + "crypto/ed25519" + "crypto/elliptic" + "encoding/hex" + "encoding/json" + "fmt" + "math/big" + "strings" + + "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" + + ktypes "github.com/kardiachain/go-kardia/types" +) + +type jsonError struct { + Code int `json:"code"` + Message string `json:"message"` + Data interface{} `json:"data,omitempty"` +} + +type heightReq struct { + JsonRpc string `json:"jsonrpc"` + Method string `json:"method"` + Params []string `json:"params"` + Id uint `json:"id"` +} + +type heightRsp struct { + JsonRpc string `json:"jsonrpc"` + Result uint64 `json:"result,omitempty"` + Error *jsonError `json:"error,omitempty"` + Id uint `json:"id"` +} + +type proofReq struct { + JsonRPC string `json:"jsonrpc"` + Method string `json:"method"` + Params []interface{} `json:"params"` + Id uint `json:"id"` +} + +type proofRsp struct { + JsonRPC string `json:"jsonrpc"` + Result KAIProof `json:"result,omitempty"` + Error *jsonError `json:"error,omitempty"` + Id uint `json:"id"` +} + +type KAIProof struct { + Address string `json:"address"` + Balance string `json:"balance"` + CodeHash string `json:"codeHash"` + Nonce string `json:"nonce"` + StorageHash string `json:"storageHash"` + AccountProof []string `json:"accountProof"` + StorageProofs []StorageProof `json:"storageProof"` +} + +type StorageProof struct { + Key string `json:"key"` + Value string `json:"value"` + Proof []string `json:"proof"` +} + +type blockReq struct { + JsonRpc string `json:"jsonrpc"` + Method string `json:"method"` + Params []interface{} `json:"params"` + Id uint `json:"id"` +} + +type blockRsp struct { + JsonRPC string `json:"jsonrpc"` + Result *ktypes.Header `json:"result,omitempty"` + Error *jsonError `json:"error,omitempty"` + Id uint `json:"id"` +} + +type valSetRsp struct { + JsonRPC string `json:"jsonrpc"` + Result []*ktypes.Validator `json:"result,omitempty"` + Error *jsonError `json:"error,omitempty"` + Id uint `json:"id"` +} + +type commitRsp struct { + JsonRPC string `json:"jsonrpc"` + Result *ktypes.Commit `json:"result,omitempty"` + Error *jsonError `json:"error,omitempty"` + Id uint `json:"id"` +} + +func GetNodeHeader(url string, restClient *RestClient, height uint64) ([]byte, error) { + params := []interface{}{fmt.Sprintf("0x%x", height), true} + req := &blockReq{ + JsonRpc: "2.0", + Method: "kai_getBlockByNumber", + Params: params, + Id: 1, + } + reqdata, err := json.Marshal(req) + if err != nil { + return nil, fmt.Errorf("GetNodeHeight: marshal req err: %s", err) + } + rspdata, err := restClient.SendRestRequest(url, reqdata) + if err != nil { + return nil, fmt.Errorf("GetNodeHeight err: %s", err) + } + rsp := &blockRsp{} + err = json.Unmarshal(rspdata, rsp) + if err != nil { + return nil, fmt.Errorf("GetNodeHeight, unmarshal resp err: %s", err) + } + if rsp.Error != nil { + return nil, fmt.Errorf("GetNodeHeight, unmarshal resp err: %s", rsp.Error.Message) + } + return json.Marshal(rsp.Result) +} + +func GetNodeHeight(url string, restClient *RestClient) (uint64, error) { + req := &heightReq{ + JsonRpc: "2.0", + Method: "kai_blockNumber", + Params: make([]string, 0), + Id: 1, + } + reqData, err := json.Marshal(req) + if err != nil { + return 0, fmt.Errorf("GetNodeHeight: marshal req err: %s", err) + } + rspData, err := restClient.SendRestRequest(url, reqData) + if err != nil { + return 0, fmt.Errorf("GetNodeHeight err: %s", err) + } + rsp := &heightRsp{} + err = json.Unmarshal(rspData, rsp) + if err != nil { + return 0, fmt.Errorf("GetNodeHeight, unmarshal resp err: %s", err) + } + if rsp.Error != nil { + return 0, fmt.Errorf("GetNodeHeight, unmarshal resp err: %s", rsp.Error.Message) + } + return rsp.Result, nil +} + +func GetProof(url string, contractAddress string, key string, blockheight string, restClient *RestClient) ([]byte, error) { + req := &proofReq{ + JsonRPC: "2.0", + Method: "eth_getProof", + Params: []interface{}{contractAddress, []string{key}, blockheight}, + Id: 1, + } + reqdata, err := json.Marshal(req) + if err != nil { + return nil, fmt.Errorf("eth_kaiProof: marshal req err: %s", err) + } + rspdata, err := restClient.SendRestRequest(url, reqdata) + if err != nil { + return nil, fmt.Errorf("GetProof: send request err: %s", err) + } + rsp := &proofRsp{} + err = json.Unmarshal(rspdata, rsp) + if err != nil { + return nil, fmt.Errorf("GetProof, unmarshal resp err: %s", err) + } + if rsp.Error != nil { + return nil, fmt.Errorf("GetNodeHeight, unmarshal resp err: %s", rsp.Error.Message) + } + result, err := json.Marshal(rsp.Result) + if err != nil { + return nil, fmt.Errorf("GetProof, Marshal result err: %s", err) + } + //fmt.Printf("proof res is:%s\n", string(result)) + return result, nil +} + +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 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 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") + } +} diff --git a/tools/util_test.go b/tools/util_test.go new file mode 100644 index 0000000..ab5366f --- /dev/null +++ b/tools/util_test.go @@ -0,0 +1,36 @@ +/* +* Copyright (C) 2020 The poly network Authors +* This file is part of The poly network library. +* +* The poly network is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* The poly network 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 Lesser General Public License for more details. +* You should have received a copy of the GNU Lesser General Public License +* along with The poly network . If not, see . + */ +package tools + +import ( + "fmt" + "testing" +) + +func TestGetProof(t *testing.T) { + client := NewRestClient() + res, err := GetProof("http://139.219.131.74:10331", + "0xf6dc652e2f7ab7a20d1cc4156d5a7122a9e966a5", + "0xada5013122d395ba3c54772283fb069b10426056ef8ca54750cb9bb552a59e7d", + "0x5e852e", + client) + if err != nil { + fmt.Printf("err:%s\n", err) + return + } + fmt.Printf("res is :%s\n", res) +}