Merge branch 'master' into disk-db

This commit is contained in:
Paul Hauner 2019-04-30 16:02:23 +10:00
commit 05df7702d3
No known key found for this signature in database
GPG Key ID: D362883A9218FCC6
205 changed files with 19475 additions and 2247 deletions

2
.gitignore vendored
View File

@ -4,3 +4,5 @@ Cargo.lock
*.pk *.pk
*.sk *.sk
*.raw_keypairs *.raw_keypairs
flamegraph.svg
perf.data*

View File

@ -1,4 +1,9 @@
language: rust language: rust
cache:
directories:
- /home/travis/.cargo
before_cache:
- rm -rf /home/travis/.cargo/registry
before_install: before_install:
- curl -OL https://github.com/google/protobuf/releases/download/v3.4.0/protoc-3.4.0-linux-x86_64.zip - curl -OL https://github.com/google/protobuf/releases/download/v3.4.0/protoc-3.4.0-linux-x86_64.zip
- unzip protoc-3.4.0-linux-x86_64.zip -d protoc3 - unzip protoc-3.4.0-linux-x86_64.zip -d protoc3
@ -6,12 +11,16 @@ before_install:
- sudo mv protoc3/include/* /usr/local/include/ - sudo mv protoc3/include/* /usr/local/include/
- sudo chown $USER /usr/local/bin/protoc - sudo chown $USER /usr/local/bin/protoc
- sudo chown -R $USER /usr/local/include/google - sudo chown -R $USER /usr/local/include/google
env:
- BUILD=--all
- BUILD=--release --all
- BUILD= --manifest-path eth2/state_processing/Cargo.toml --release --features fake_crypto
script: script:
- cargo build --verbose --all - cargo build --verbose $BUILD
- cargo build --verbose --release --all - cargo test --verbose $BUILD
- cargo test --verbose --all
- cargo test --verbose --release --all
- cargo fmt --all -- --check - cargo fmt --all -- --check
# No clippy until later...
#- cargo clippy
rust: rust:
- stable - stable
- beta - beta
@ -20,5 +29,15 @@ matrix:
allow_failures: allow_failures:
- rust: nightly - rust: nightly
fast_finish: true fast_finish: true
exclude:
- rust: beta
env: BUILD=--release --all
- rust: beta
env: BUILD= --manifest-path eth2/state_processing/Cargo.toml --release --features fake_crypto
- rust: nightly
env: BUILD=--release --all
- rust: nightly
env: BUILD= --manifest-path eth2/state_processing/Cargo.toml --release --features fake_crypto
install: install:
- rustup component add rustfmt - rustup component add rustfmt
- rustup component add clippy

View File

@ -5,9 +5,11 @@ members = [
"eth2/fork_choice", "eth2/fork_choice",
"eth2/operation_pool", "eth2/operation_pool",
"eth2/state_processing", "eth2/state_processing",
"eth2/state_processing/yaml_utils",
"eth2/types", "eth2/types",
"eth2/utils/bls", "eth2/utils/bls",
"eth2/utils/boolean-bitfield", "eth2/utils/boolean-bitfield",
"eth2/utils/cached_tree_hash",
"eth2/utils/hashing", "eth2/utils/hashing",
"eth2/utils/honey-badger-split", "eth2/utils/honey-badger-split",
"eth2/utils/merkle_proof", "eth2/utils/merkle_proof",
@ -17,6 +19,8 @@ members = [
"eth2/utils/ssz", "eth2/utils/ssz",
"eth2/utils/ssz_derive", "eth2/utils/ssz_derive",
"eth2/utils/swap_or_not_shuffle", "eth2/utils/swap_or_not_shuffle",
"eth2/utils/tree_hash",
"eth2/utils/tree_hash_derive",
"eth2/utils/fisher_yates_shuffle", "eth2/utils/fisher_yates_shuffle",
"eth2/utils/test_random_derive", "eth2/utils/test_random_derive",
"beacon_node", "beacon_node",

View File

@ -15,3 +15,7 @@ RUN git clone https://github.com/google/protobuf.git && \
RUN mkdir /cargocache && chmod -R ugo+rwX /cargocache RUN mkdir /cargocache && chmod -R ugo+rwX /cargocache
ENV CARGO_HOME /cargocache
RUN rustup component add rustfmt clippy

12
Jenkinsfile vendored
View File

@ -12,10 +12,22 @@ pipeline {
sh 'cargo build --verbose --all --release' sh 'cargo build --verbose --all --release'
} }
} }
stage('Check') {
steps {
sh 'cargo fmt --all -- --check'
// No clippy until later...
//sh 'cargo clippy'
}
}
stage('Test') { stage('Test') {
steps { steps {
sh 'cargo test --verbose --all' sh 'cargo test --verbose --all'
sh 'cargo test --verbose --all --release' sh 'cargo test --verbose --all --release'
sh 'cargo test --manifest-path eth2/state_processing/Cargo.toml --verbose \
--release --features fake_crypto'
sh 'cargo test --manifest-path eth2/state_processing/Cargo.toml --verbose \
--release --features fake_crypto -- --ignored'
} }
} }
} }

476
LICENSE
View File

@ -1,339 +1,201 @@
GNU GENERAL PUBLIC LICENSE Apache License
Version 2, June 1991 Version 2.0, January 2004
http://www.apache.org/licenses/
Copyright (C) 1989, 1991 Free Software Foundation, Inc., TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble 1. Definitions.
The licenses for most software are designed to take away your "License" shall mean the terms and conditions for use, reproduction,
freedom to share and change it. By contrast, the GNU General Public and distribution as defined by Sections 1 through 9 of this document.
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not "Licensor" shall mean the copyright owner or entity authorized by
price. Our General Public Licenses are designed to make sure that you the copyright owner that is granting the License.
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid "Legal Entity" shall mean the union of the acting entity and all
anyone to deny you these rights or to ask you to surrender the rights. other entities that control, are controlled by, or are under common
These restrictions translate to certain responsibilities for you if you control with that entity. For the purposes of this definition,
distribute copies of the software, or if you modify it. "control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
For example, if you distribute copies of such a program, whether "You" (or "Your") shall mean an individual or Legal Entity
gratis or for a fee, you must give the recipients all the rights that exercising permissions granted by this License.
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and "Source" form shall mean the preferred form for making modifications,
(2) offer you this license which gives you legal permission to copy, including but not limited to software source code, documentation
distribute and/or modify the software. source, and configuration files.
Also, for each author's protection and ours, we want to make certain "Object" form shall mean any form resulting from mechanical
that everyone understands that there is no warranty for this free transformation or translation of a Source form, including but
software. If the software is modified by someone else and passed on, we not limited to compiled object code, generated documentation,
want its recipients to know that what they have is not the original, so and conversions to other media types.
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software "Work" shall mean the work of authorship, whether in Source or
patents. We wish to avoid the danger that redistributors of a free Object form, made available under the License, as indicated by a
program will individually obtain patent licenses, in effect making the copyright notice that is included in or attached to the work
program proprietary. To prevent this, we have made it clear that any (an example is provided in the Appendix below).
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and "Derivative Works" shall mean any work, whether in Source or Object
modification follow. form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
GNU GENERAL PUBLIC LICENSE "Contribution" shall mean any work of authorship, including
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
0. This License applies to any program or other work which contains "Contributor" shall mean Licensor and any individual or Legal Entity
a notice placed by the copyright holder saying it may be distributed on behalf of whom a Contribution has been received by Licensor and
under the terms of this General Public License. The "Program", below, subsequently incorporated within the Work.
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not 2. Grant of Copyright License. Subject to the terms and conditions of
covered by this License; they are outside its scope. The act of this License, each Contributor hereby grants to You a perpetual,
running the Program is not restricted, and the output from the Program worldwide, non-exclusive, no-charge, royalty-free, irrevocable
is covered only if its contents constitute a work based on the copyright license to reproduce, prepare Derivative Works of,
Program (independent of having been made by running the Program). publicly display, publicly perform, sublicense, and distribute the
Whether that is true depends on what the Program does. Work and such Derivative Works in Source or Object form.
1. You may copy and distribute verbatim copies of the Program's 3. Grant of Patent License. Subject to the terms and conditions of
source code as you receive it, in any medium, provided that you this License, each Contributor hereby grants to You a perpetual,
conspicuously and appropriately publish on each copy an appropriate worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright notice and disclaimer of warranty; keep intact all the (except as stated in this section) patent license to make, have made,
notices that refer to this License and to the absence of any warranty; use, offer to sell, sell, import, and otherwise transfer the Work,
and give any other recipients of the Program a copy of this License where such license applies only to those patent claims licensable
along with the Program. by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
You may charge a fee for the physical act of transferring a copy, and 4. Redistribution. You may reproduce and distribute copies of the
you may at your option offer warranty protection in exchange for a fee. Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
2. You may modify your copy or copies of the Program or any portion (a) You must give any other recipients of the Work or
of it, thus forming a work based on the Program, and copy and Derivative Works a copy of this License; and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices (b) You must cause any modified files to carry prominent notices
stating that you changed the files and the date of any change. stating that You changed the files; and
b) You must cause any work that you distribute or publish, that in (c) You must retain, in the Source form of any Derivative Works
whole or in part contains or is derived from the Program or any that You distribute, all copyright, patent, trademark, and
part thereof, to be licensed as a whole at no charge to all third attribution notices from the Source form of the Work,
parties under the terms of this License. excluding those notices that do not pertain to any part of
the Derivative Works; and
c) If the modified program normally reads commands interactively (d) If the Work includes a "NOTICE" text file as part of its
when run, you must cause it, when started running for such distribution, then any Derivative Works that You distribute must
interactive use in the most ordinary way, to print or display an include a readable copy of the attribution notices contained
announcement including an appropriate copyright notice and a within such NOTICE file, excluding those notices that do not
notice that there is no warranty (or else, saying that you provide pertain to any part of the Derivative Works, in at least one
a warranty) and that users may redistribute the program under of the following places: within a NOTICE text file distributed
these conditions, and telling the user how to view a copy of this as part of the Derivative Works; within the Source form or
License. (Exception: if the Program itself is interactive but documentation, if provided along with the Derivative Works; or,
does not normally print such an announcement, your work based on within a display generated by the Derivative Works, if and
the Program is not required to print an announcement.) wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
These requirements apply to the modified work as a whole. If You may add Your own copyright statement to Your modifications and
identifiable sections of that work are not derived from the Program, may provide additional or different license terms and conditions
and can be reasonably considered independent and separate works in for use, reproduction, or distribution of Your modifications, or
themselves, then this License, and its terms, do not apply to those for any such Derivative Works as a whole, provided Your use,
sections when you distribute them as separate works. But when you reproduction, and distribution of the Work otherwise complies with
distribute the same sections as part of a whole which is a work based the conditions stated in this License.
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest 5. Submission of Contributions. Unless You explicitly state otherwise,
your rights to work written entirely by you; rather, the intent is to any Contribution intentionally submitted for inclusion in the Work
exercise the right to control the distribution of derivative or by You to the Licensor shall be under the terms and conditions of
collective works based on the Program. this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
In addition, mere aggregation of another work not based on the Program 6. Trademarks. This License does not grant permission to use the trade
with the Program (or with a work based on the Program) on a volume of names, trademarks, service marks, or product names of the Licensor,
a storage or distribution medium does not bring the other work under except as required for reasonable and customary use in describing the
the scope of this License. origin of the Work and reproducing the content of the NOTICE file.
3. You may copy and distribute the Program (or a work based on it, 7. Disclaimer of Warranty. Unless required by applicable law or
under Section 2) in object code or executable form under the terms of agreed to in writing, Licensor provides the Work (and each
Sections 1 and 2 above provided that you also do one of the following: Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
a) Accompany it with the complete corresponding machine-readable 8. Limitation of Liability. In no event and under no legal theory,
source code, which must be distributed under the terms of Sections whether in tort (including negligence), contract, or otherwise,
1 and 2 above on a medium customarily used for software interchange; or, unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
b) Accompany it with a written offer, valid for at least three 9. Accepting Warranty or Additional Liability. While redistributing
years, to give any third party, for a charge no more than your the Work or Derivative Works thereof, You may choose to offer,
cost of physically performing source distribution, a complete and charge a fee for, acceptance of support, warranty, indemnity,
machine-readable copy of the corresponding source code, to be or other liability obligations and/or rights consistent with this
distributed under the terms of Sections 1 and 2 above on a medium License. However, in accepting such obligations, You may act only
customarily used for software interchange; or, on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
c) Accompany it with the information you received as to the offer END OF TERMS AND CONDITIONS
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for APPENDIX: How to apply the Apache License to your work.
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering To apply the Apache License to your work, attach the following
access to copy from a designated place, then offering equivalent boilerplate notice, with the fields enclosed by brackets "[]"
access to copy the source code from the same place counts as replaced with your own identifying information. (Don't include
distribution of the source code, even though third parties are not the brackets!) The text should be enclosed in the appropriate
compelled to copy the source along with the object code. comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
4. You may not copy, modify, sublicense, or distribute the Program Copyright 2018 Sigma Prime Pty Ltd
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not Licensed under the Apache License, Version 2.0 (the "License");
signed it. However, nothing else grants you permission to modify or you may not use this file except in compliance with the License.
distribute the Program or its derivative works. These actions are You may obtain a copy of the License at
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the http://www.apache.org/licenses/LICENSE-2.0
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent Unless required by applicable law or agreed to in writing, software
infringement or for any other reason (not limited to patent issues), distributed under the License is distributed on an "AS IS" BASIS,
conditions are imposed on you (whether by court order, agreement or WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
otherwise) that contradict the conditions of this License, they do not See the License for the specific language governing permissions and
excuse you from the conditions of this License. If you cannot limitations under the License.
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -112,6 +112,7 @@ A few basic steps are needed to get set up:
5. Install build dependencies (Arch packages are listed here, your distribution will likely be similar): 5. Install build dependencies (Arch packages are listed here, your distribution will likely be similar):
- `clang`: required by RocksDB. - `clang`: required by RocksDB.
- `protobuf`: required for protobuf serialization (gRPC). - `protobuf`: required for protobuf serialization (gRPC).
- `cmake`: required for building protobuf
6. Navigate to the working directory. 6. Navigate to the working directory.
7. Run the test by using command `cargo test --all`. By running, it will pass all the required test cases. 7. Run the test by using command `cargo test --all`. By running, it will pass all the required test cases.
If you are doing it for the first time, then you can grab a coffee in the meantime. Usually, it takes time If you are doing it for the first time, then you can grab a coffee in the meantime. Usually, it takes time

View File

@ -23,4 +23,5 @@ serde_json = "1.0"
slot_clock = { path = "../../eth2/utils/slot_clock" } slot_clock = { path = "../../eth2/utils/slot_clock" }
ssz = { path = "../../eth2/utils/ssz" } ssz = { path = "../../eth2/utils/ssz" }
state_processing = { path = "../../eth2/state_processing" } state_processing = { path = "../../eth2/state_processing" }
tree_hash = { path = "../../eth2/utils/tree_hash" }
types = { path = "../../eth2/types" } types = { path = "../../eth2/types" }

View File

@ -303,8 +303,6 @@ where
/// then having it iteratively updated -- in such a case it's possible for another thread to /// then having it iteratively updated -- in such a case it's possible for another thread to
/// find the state at an old slot. /// find the state at an old slot.
pub fn update_state(&self, mut state: BeaconState) -> Result<(), Error> { pub fn update_state(&self, mut state: BeaconState) -> Result<(), Error> {
let latest_block_header = self.head().beacon_block.block_header();
let present_slot = match self.slot_clock.present_slot() { let present_slot = match self.slot_clock.present_slot() {
Ok(Some(slot)) => slot, Ok(Some(slot)) => slot,
_ => return Err(Error::UnableToReadSlot), _ => return Err(Error::UnableToReadSlot),
@ -312,7 +310,7 @@ where
// If required, transition the new state to the present slot. // If required, transition the new state to the present slot.
for _ in state.slot.as_u64()..present_slot.as_u64() { for _ in state.slot.as_u64()..present_slot.as_u64() {
per_slot_processing(&mut state, &latest_block_header, &self.spec)?; per_slot_processing(&mut state, &self.spec)?;
} }
state.build_all_caches(&self.spec)?; state.build_all_caches(&self.spec)?;
@ -324,8 +322,6 @@ where
/// Ensures the current canonical `BeaconState` has been transitioned to match the `slot_clock`. /// Ensures the current canonical `BeaconState` has been transitioned to match the `slot_clock`.
pub fn catchup_state(&self) -> Result<(), Error> { pub fn catchup_state(&self) -> Result<(), Error> {
let latest_block_header = self.head().beacon_block.block_header();
let present_slot = match self.slot_clock.present_slot() { let present_slot = match self.slot_clock.present_slot() {
Ok(Some(slot)) => slot, Ok(Some(slot)) => slot,
_ => return Err(Error::UnableToReadSlot), _ => return Err(Error::UnableToReadSlot),
@ -339,7 +335,7 @@ where
state.build_epoch_cache(RelativeEpoch::NextWithoutRegistryChange, &self.spec)?; state.build_epoch_cache(RelativeEpoch::NextWithoutRegistryChange, &self.spec)?;
state.build_epoch_cache(RelativeEpoch::NextWithRegistryChange, &self.spec)?; state.build_epoch_cache(RelativeEpoch::NextWithRegistryChange, &self.spec)?;
per_slot_processing(&mut *state, &latest_block_header, &self.spec)?; per_slot_processing(&mut *state, &self.spec)?;
} }
state.build_all_caches(&self.spec)?; state.build_all_caches(&self.spec)?;
@ -497,21 +493,17 @@ where
} else { } else {
// If the current head block is not from this slot, use the slot from the previous // If the current head block is not from this slot, use the slot from the previous
// epoch. // epoch.
let root = *self.state.read().get_block_root( *self.state.read().get_block_root(
current_epoch_start_slot - self.spec.slots_per_epoch, current_epoch_start_slot - self.spec.slots_per_epoch,
&self.spec, &self.spec,
)?; )?
root
} }
} else { } else {
// If we're not on the first slot of the epoch. // If we're not on the first slot of the epoch.
let root = *self *self
.state .state
.read() .read()
.get_block_root(current_epoch_start_slot, &self.spec)?; .get_block_root(current_epoch_start_slot, &self.spec)?
root
}; };
Ok(AttestationData { Ok(AttestationData {
@ -621,9 +613,8 @@ where
// Transition the parent state to the block slot. // Transition the parent state to the block slot.
let mut state = parent_state; let mut state = parent_state;
let previous_block_header = parent_block.block_header();
for _ in state.slot.as_u64()..block.slot.as_u64() { for _ in state.slot.as_u64()..block.slot.as_u64() {
if let Err(e) = per_slot_processing(&mut state, &previous_block_header, &self.spec) { if let Err(e) = per_slot_processing(&mut state, &self.spec) {
return Ok(BlockProcessingOutcome::InvalidBlock( return Ok(BlockProcessingOutcome::InvalidBlock(
InvalidBlock::SlotProcessingError(e), InvalidBlock::SlotProcessingError(e),
)); ));

View File

@ -7,9 +7,9 @@ use db::stores::{BeaconBlockStore, BeaconStateStore};
use db::{DiskDB, MemoryDB}; use db::{DiskDB, MemoryDB};
use fork_choice::BitwiseLMDGhost; use fork_choice::BitwiseLMDGhost;
use slot_clock::SystemTimeSlotClock; use slot_clock::SystemTimeSlotClock;
use ssz::TreeHash;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use tree_hash::TreeHash;
use types::test_utils::TestingBeaconStateBuilder; use types::test_utils::TestingBeaconStateBuilder;
use types::{BeaconBlock, ChainSpec, Hash256}; use types::{BeaconBlock, ChainSpec, Hash256};
@ -32,7 +32,7 @@ pub fn initialise_beacon_chain(
let (genesis_state, _keypairs) = state_builder.build(); let (genesis_state, _keypairs) = state_builder.build();
let mut genesis_block = BeaconBlock::empty(&spec); let mut genesis_block = BeaconBlock::empty(&spec);
genesis_block.state_root = Hash256::from_slice(&genesis_state.hash_tree_root()); genesis_block.state_root = Hash256::from_slice(&genesis_state.tree_hash_root());
// Slot clock // Slot clock
let slot_clock = SystemTimeSlotClock::new( let slot_clock = SystemTimeSlotClock::new(
@ -73,7 +73,7 @@ pub fn initialise_test_beacon_chain_with_memory_db(
let (genesis_state, _keypairs) = state_builder.build(); let (genesis_state, _keypairs) = state_builder.build();
let mut genesis_block = BeaconBlock::empty(spec); let mut genesis_block = BeaconBlock::empty(spec);
genesis_block.state_root = Hash256::from_slice(&genesis_state.hash_tree_root()); genesis_block.state_root = Hash256::from_slice(&genesis_state.tree_hash_root());
// Slot clock // Slot clock
let slot_clock = SystemTimeSlotClock::new( let slot_clock = SystemTimeSlotClock::new(

View File

@ -5,8 +5,8 @@ use db::{
}; };
use fork_choice::BitwiseLMDGhost; use fork_choice::BitwiseLMDGhost;
use slot_clock::TestingSlotClock; use slot_clock::TestingSlotClock;
use ssz::TreeHash;
use std::sync::Arc; use std::sync::Arc;
use tree_hash::TreeHash;
use types::test_utils::TestingBeaconStateBuilder; use types::test_utils::TestingBeaconStateBuilder;
use types::*; use types::*;
@ -27,7 +27,7 @@ impl TestingBeaconChainBuilder {
let (genesis_state, _keypairs) = self.state_builder.build(); let (genesis_state, _keypairs) = self.state_builder.build();
let mut genesis_block = BeaconBlock::empty(&spec); let mut genesis_block = BeaconBlock::empty(&spec);
genesis_block.state_root = Hash256::from_slice(&genesis_state.hash_tree_root()); genesis_block.state_root = Hash256::from_slice(&genesis_state.tree_hash_root());
// Create the Beacon Chain // Create the Beacon Chain
BeaconChain::from_genesis( BeaconChain::from_genesis(

View File

@ -38,5 +38,6 @@ serde_json = "1.0"
serde_yaml = "0.8" serde_yaml = "0.8"
slot_clock = { path = "../../../eth2/utils/slot_clock" } slot_clock = { path = "../../../eth2/utils/slot_clock" }
ssz = { path = "../../../eth2/utils/ssz" } ssz = { path = "../../../eth2/utils/ssz" }
tree_hash = { path = "../../../eth2/utils/tree_hash" }
types = { path = "../../../eth2/types" } types = { path = "../../../eth2/types" }
yaml-rust = "0.4.2" yaml-rust = "0.4.2"

View File

@ -9,8 +9,8 @@ use fork_choice::BitwiseLMDGhost;
use log::debug; use log::debug;
use rayon::prelude::*; use rayon::prelude::*;
use slot_clock::TestingSlotClock; use slot_clock::TestingSlotClock;
use ssz::TreeHash;
use std::sync::Arc; use std::sync::Arc;
use tree_hash::TreeHash;
use types::{test_utils::TestingBeaconStateBuilder, *}; use types::{test_utils::TestingBeaconStateBuilder, *};
type TestingBeaconChain = BeaconChain<MemoryDB, TestingSlotClock, BitwiseLMDGhost<MemoryDB>>; type TestingBeaconChain = BeaconChain<MemoryDB, TestingSlotClock, BitwiseLMDGhost<MemoryDB>>;
@ -54,7 +54,7 @@ impl BeaconChainHarness {
let (mut genesis_state, keypairs) = state_builder.build(); let (mut genesis_state, keypairs) = state_builder.build();
let mut genesis_block = BeaconBlock::empty(&spec); let mut genesis_block = BeaconBlock::empty(&spec);
genesis_block.state_root = Hash256::from_slice(&genesis_state.hash_tree_root()); genesis_block.state_root = Hash256::from_slice(&genesis_state.tree_hash_root());
genesis_state genesis_state
.build_epoch_cache(RelativeEpoch::Previous, &spec) .build_epoch_cache(RelativeEpoch::Previous, &spec)
@ -163,7 +163,7 @@ impl BeaconChainHarness {
data: data.clone(), data: data.clone(),
custody_bit: false, custody_bit: false,
} }
.hash_tree_root(); .tree_hash_root();
let domain = self.spec.get_domain( let domain = self.spec.get_domain(
state.slot.epoch(self.spec.slots_per_epoch), state.slot.epoch(self.spec.slots_per_epoch),
Domain::Attestation, Domain::Attestation,
@ -211,9 +211,8 @@ impl BeaconChainHarness {
// Ensure the validators slot clock is accurate. // Ensure the validators slot clock is accurate.
self.validators[proposer].set_slot(present_slot); self.validators[proposer].set_slot(present_slot);
let block = self.validators[proposer].produce_block().unwrap();
block self.validators[proposer].produce_block().unwrap()
} }
/// Advances the chain with a BeaconBlock and attestations from all validators. /// Advances the chain with a BeaconBlock and attestations from all validators.
@ -245,7 +244,7 @@ impl BeaconChainHarness {
.for_each(|(i, attestation)| { .for_each(|(i, attestation)| {
self.beacon_chain self.beacon_chain
.process_attestation(attestation.clone()) .process_attestation(attestation.clone())
.expect(&format!("Attestation {} invalid: {:?}", i, attestation)); .unwrap_or_else(|_| panic!("Attestation {} invalid: {:?}", i, attestation));
}); });
debug!("Attestations processed."); debug!("Attestations processed.");

View File

@ -8,7 +8,7 @@
//! producing blocks and attestations. //! producing blocks and attestations.
//! //!
//! Example: //! Example:
//! ``` //! ```rust,no_run
//! use test_harness::BeaconChainHarness; //! use test_harness::BeaconChainHarness;
//! use types::ChainSpec; //! use types::ChainSpec;
//! //!

View File

@ -4,7 +4,7 @@
use crate::beacon_chain_harness::BeaconChainHarness; use crate::beacon_chain_harness::BeaconChainHarness;
use beacon_chain::CheckPoint; use beacon_chain::CheckPoint;
use log::{info, warn}; use log::{info, warn};
use ssz::SignedRoot; use tree_hash::SignedRoot;
use types::*; use types::*;
use types::test_utils::*; use types::test_utils::*;

View File

@ -52,6 +52,7 @@ impl StateCheck {
/// # Panics /// # Panics
/// ///
/// Panics with an error message if any test fails. /// Panics with an error message if any test fails.
#[allow(clippy::cyclomatic_complexity)]
pub fn assert_valid(&self, state: &BeaconState, spec: &ChainSpec) { pub fn assert_valid(&self, state: &BeaconState, spec: &ChainSpec) {
let state_epoch = state.slot.epoch(spec.slots_per_epoch); let state_epoch = state.slot.epoch(spec.slots_per_epoch);

View File

@ -14,9 +14,6 @@ use slot_clock::SlotClock;
use std::sync::Arc; use std::sync::Arc;
use types::{AttestationData, BeaconBlock, FreeAttestation, Signature, Slot}; use types::{AttestationData, BeaconBlock, FreeAttestation, Signature, Slot};
// mod attester;
// mod producer;
/// Connect directly to a borrowed `BeaconChain` instance so an attester/producer can request/submit /// Connect directly to a borrowed `BeaconChain` instance so an attester/producer can request/submit
/// blocks/attestations. /// blocks/attestations.
/// ///
@ -42,11 +39,6 @@ impl<T: ClientDB, U: SlotClock, F: ForkChoice> DirectBeaconNode<T, U, F> {
pub fn last_published_block(&self) -> Option<BeaconBlock> { pub fn last_published_block(&self) -> Option<BeaconBlock> {
Some(self.published_blocks.read().last()?.clone()) Some(self.published_blocks.read().last()?.clone())
} }
/// Get the last published attestation (if any).
pub fn last_published_free_attestation(&self) -> Option<FreeAttestation> {
Some(self.published_attestations.read().last()?.clone())
}
} }
impl<T: ClientDB, U: SlotClock, F: ForkChoice> AttesterBeaconNode for DirectBeaconNode<T, U, F> { impl<T: ClientDB, U: SlotClock, F: ForkChoice> AttesterBeaconNode for DirectBeaconNode<T, U, F> {

View File

@ -2,8 +2,7 @@ mod direct_beacon_node;
mod direct_duties; mod direct_duties;
mod local_signer; mod local_signer;
use attester::PollOutcome as AttestationPollOutcome; use attester::Attester;
use attester::{Attester, Error as AttestationPollError};
use beacon_chain::BeaconChain; use beacon_chain::BeaconChain;
use block_proposer::PollOutcome as BlockPollOutcome; use block_proposer::PollOutcome as BlockPollOutcome;
use block_proposer::{BlockProducer, Error as BlockPollError}; use block_proposer::{BlockProducer, Error as BlockPollError};
@ -14,7 +13,7 @@ use fork_choice::BitwiseLMDGhost;
use local_signer::LocalSigner; use local_signer::LocalSigner;
use slot_clock::TestingSlotClock; use slot_clock::TestingSlotClock;
use std::sync::Arc; use std::sync::Arc;
use types::{BeaconBlock, ChainSpec, FreeAttestation, Keypair, Slot}; use types::{BeaconBlock, ChainSpec, Keypair, Slot};
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum BlockProduceError { pub enum BlockProduceError {
@ -22,12 +21,6 @@ pub enum BlockProduceError {
PollError(BlockPollError), PollError(BlockPollError),
} }
#[derive(Debug, PartialEq)]
pub enum AttestationProduceError {
DidNotProduce(AttestationPollOutcome),
PollError(AttestationPollError),
}
type TestingBlockProducer = BlockProducer< type TestingBlockProducer = BlockProducer<
TestingSlotClock, TestingSlotClock,
DirectBeaconNode<MemoryDB, TestingSlotClock, BitwiseLMDGhost<MemoryDB>>, DirectBeaconNode<MemoryDB, TestingSlotClock, BitwiseLMDGhost<MemoryDB>>,
@ -117,21 +110,6 @@ impl ValidatorHarness {
.expect("Unable to obtain produced block.")) .expect("Unable to obtain produced block."))
} }
/// Run the `poll` function on the `Attester` and produce a `FreeAttestation`.
///
/// An error is returned if the attester refuses to attest.
pub fn produce_free_attestation(&mut self) -> Result<FreeAttestation, AttestationProduceError> {
match self.attester.poll() {
Ok(AttestationPollOutcome::AttestationProduced(_)) => {}
Ok(outcome) => return Err(AttestationProduceError::DidNotProduce(outcome)),
Err(error) => return Err(AttestationProduceError::PollError(error)),
};
Ok(self
.beacon_node
.last_published_free_attestation()
.expect("Unable to obtain produced attestation."))
}
/// Set the validators slot clock to the specified slot. /// Set the validators slot clock to the specified slot.
/// ///
/// The validators slot clock will always read this value until it is set to something else. /// The validators slot clock will always read this value until it is set to something else.

View File

@ -1,3 +1,5 @@
#![cfg(not(debug_assertions))]
use env_logger::{Builder, Env}; use env_logger::{Builder, Env};
use log::debug; use log::debug;
use test_harness::BeaconChainHarness; use test_harness::BeaconChainHarness;

View File

@ -10,6 +10,7 @@ use std::path::PathBuf;
use types::multiaddr::Protocol; use types::multiaddr::Protocol;
use types::multiaddr::ToMultiaddr; use types::multiaddr::ToMultiaddr;
use types::ChainSpec; use types::ChainSpec;
use types::Multiaddr;
/// Stores the client configuration for this Lighthouse instance. /// Stores the client configuration for this Lighthouse instance.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -76,7 +77,7 @@ impl ClientConfig {
} }
// Custom listening address ipv4/ipv6 // Custom listening address ipv4/ipv6
// TODO: Handle list of addresses // TODO: Handle list of addresses
if let Some(listen_address_str) = args.value_of("listen_address") { if let Some(listen_address_str) = args.value_of("listen-address") {
if let Ok(listen_address) = listen_address_str.parse::<IpAddr>() { if let Ok(listen_address) = listen_address_str.parse::<IpAddr>() {
let multiaddr = SocketAddr::new(listen_address, config.net_conf.listen_port) let multiaddr = SocketAddr::new(listen_address, config.net_conf.listen_port)
.to_multiaddr() .to_multiaddr()
@ -88,6 +89,17 @@ impl ClientConfig {
} }
} }
// Custom bootnodes
// TODO: Handle list of addresses
if let Some(boot_addresses_str) = args.value_of("boot-nodes") {
if let Ok(boot_address) = boot_addresses_str.parse::<Multiaddr>() {
config.net_conf.boot_nodes.append(&mut vec![boot_address]);
} else {
error!(log, "Invalid Bootnode multiaddress"; "Multiaddr" => boot_addresses_str);
return Err("Invalid IP Address");
}
}
/* Filesystem related arguments */ /* Filesystem related arguments */
// Custom datadir // Custom datadir

View File

@ -15,21 +15,19 @@ use futures::{future::Future, Stream};
use network::Service as NetworkService; use network::Service as NetworkService;
use slog::{error, info, o}; use slog::{error, info, o};
use slot_clock::SlotClock; use slot_clock::SlotClock;
use ssz::TreeHash;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::sync::Arc; use std::sync::Arc;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use tokio::runtime::TaskExecutor; use tokio::runtime::TaskExecutor;
use tokio::timer::Interval; use tokio::timer::Interval;
use types::Hash256;
/// Main beacon node client service. This provides the connection and initialisation of the clients /// Main beacon node client service. This provides the connection and initialisation of the clients
/// sub-services in multiple threads. /// sub-services in multiple threads.
pub struct Client<T: ClientTypes> { pub struct Client<T: ClientTypes> {
/// Configuration for the lighthouse client. /// Configuration for the lighthouse client.
config: ClientConfig, _config: ClientConfig,
/// The beacon chain for the running client. /// The beacon chain for the running client.
beacon_chain: Arc<BeaconChain<T::DB, T::SlotClock, T::ForkChoice>>, _beacon_chain: Arc<BeaconChain<T::DB, T::SlotClock, T::ForkChoice>>,
/// Reference to the network service. /// Reference to the network service.
pub network: Arc<NetworkService>, pub network: Arc<NetworkService>,
/// Signal to terminate the RPC server. /// Signal to terminate the RPC server.
@ -92,17 +90,18 @@ impl<TClientType: ClientTypes> Client<TClientType> {
network_logger, network_logger,
)?; )?;
let mut rpc_exit_signal = None;
// spawn the RPC server // spawn the RPC server
if config.rpc_conf.enabled { let rpc_exit_signal = if config.rpc_conf.enabled {
rpc_exit_signal = Some(rpc::start_server( Some(rpc::start_server(
&config.rpc_conf, &config.rpc_conf,
executor, executor,
network_send, network_send,
beacon_chain.clone(), beacon_chain.clone(),
&log, &log,
)); ))
} } else {
None
};
let (slot_timer_exit_signal, exit) = exit_future::signal(); let (slot_timer_exit_signal, exit) = exit_future::signal();
if let Ok(Some(duration_to_next_slot)) = beacon_chain.slot_clock.duration_to_next_slot() { if let Ok(Some(duration_to_next_slot)) = beacon_chain.slot_clock.duration_to_next_slot() {
@ -131,8 +130,8 @@ impl<TClientType: ClientTypes> Client<TClientType> {
} }
Ok(Client { Ok(Client {
config, _config: config,
beacon_chain, _beacon_chain: beacon_chain,
rpc_exit_signal, rpc_exit_signal,
slot_timer_exit_signal: Some(slot_timer_exit_signal), slot_timer_exit_signal: Some(slot_timer_exit_signal),
log, log,

View File

@ -14,7 +14,7 @@ pub fn run<T: ClientTypes>(client: &Client<T>, executor: TaskExecutor, exit: Exi
// notification heartbeat // notification heartbeat
let interval = Interval::new(Instant::now(), Duration::from_secs(5)); let interval = Interval::new(Instant::now(), Duration::from_secs(5));
let log = client.log.new(o!("Service" => "Notifier")); let _log = client.log.new(o!("Service" => "Notifier"));
// TODO: Debugging only // TODO: Debugging only
let counter = Arc::new(Mutex::new(0)); let counter = Arc::new(Mutex::new(0));

View File

@ -1,6 +1,6 @@
use super::BLOCKS_DB_COLUMN as DB_COLUMN; use super::BLOCKS_DB_COLUMN as DB_COLUMN;
use super::{ClientDB, DBError}; use super::{ClientDB, DBError};
use ssz::Decodable; use ssz::decode;
use std::sync::Arc; use std::sync::Arc;
use types::{BeaconBlock, Hash256, Slot}; use types::{BeaconBlock, Hash256, Slot};
@ -30,7 +30,7 @@ impl<T: ClientDB> BeaconBlockStore<T> {
match self.get(&hash)? { match self.get(&hash)? {
None => Ok(None), None => Ok(None),
Some(ssz) => { Some(ssz) => {
let (block, _) = BeaconBlock::ssz_decode(&ssz, 0).map_err(|_| DBError { let block = decode::<BeaconBlock>(&ssz).map_err(|_| DBError {
message: "Bad BeaconBlock SSZ.".to_string(), message: "Bad BeaconBlock SSZ.".to_string(),
})?; })?;
Ok(Some(block)) Ok(Some(block))

View File

@ -1,6 +1,6 @@
use super::STATES_DB_COLUMN as DB_COLUMN; use super::STATES_DB_COLUMN as DB_COLUMN;
use super::{ClientDB, DBError}; use super::{ClientDB, DBError};
use ssz::Decodable; use ssz::decode;
use std::sync::Arc; use std::sync::Arc;
use types::{BeaconState, Hash256}; use types::{BeaconState, Hash256};
@ -23,7 +23,7 @@ impl<T: ClientDB> BeaconStateStore<T> {
match self.get(&hash)? { match self.get(&hash)? {
None => Ok(None), None => Ok(None),
Some(ssz) => { Some(ssz) => {
let (state, _) = BeaconState::ssz_decode(&ssz, 0).map_err(|_| DBError { let state = decode::<BeaconState>(&ssz).map_err(|_| DBError {
message: "Bad State SSZ.".to_string(), message: "Bad State SSZ.".to_string(),
})?; })?;
Ok(Some(state)) Ok(Some(state))

View File

@ -4,7 +4,7 @@ use self::bytes::{BufMut, BytesMut};
use super::VALIDATOR_DB_COLUMN as DB_COLUMN; use super::VALIDATOR_DB_COLUMN as DB_COLUMN;
use super::{ClientDB, DBError}; use super::{ClientDB, DBError};
use bls::PublicKey; use bls::PublicKey;
use ssz::{ssz_encode, Decodable}; use ssz::{decode, ssz_encode};
use std::sync::Arc; use std::sync::Arc;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
@ -69,8 +69,8 @@ impl<T: ClientDB> ValidatorStore<T> {
let val = self.db.get(DB_COLUMN, &key[..])?; let val = self.db.get(DB_COLUMN, &key[..])?;
match val { match val {
None => Ok(None), None => Ok(None),
Some(val) => match PublicKey::ssz_decode(&val, 0) { Some(val) => match decode::<PublicKey>(&val) {
Ok((key, _)) => Ok(Some(key)), Ok(key) => Ok(Some(key)),
Err(_) => Err(ValidatorStoreError::DecodeError), Err(_) => Err(ValidatorStoreError::DecodeError),
}, },
} }

View File

@ -65,17 +65,11 @@ impl<TSubstream: AsyncRead + AsyncWrite> NetworkBehaviourEventProcess<GossipsubE
self.events.push(BehaviourEvent::GossipMessage { self.events.push(BehaviourEvent::GossipMessage {
source: gs_msg.source, source: gs_msg.source,
topics: gs_msg.topics, topics: gs_msg.topics,
message: pubsub_message, message: Box::new(pubsub_message),
}); });
} }
GossipsubEvent::Subscribed { GossipsubEvent::Subscribed { .. } => {}
peer_id: _, GossipsubEvent::Unsubscribed { .. } => {}
topic: _,
}
| GossipsubEvent::Unsubscribed {
peer_id: _,
topic: _,
} => {}
} }
} }
} }
@ -110,7 +104,8 @@ impl<TSubstream: AsyncRead + AsyncWrite> NetworkBehaviourEventProcess<IdentifyEv
); );
info.listen_addrs.truncate(20); info.listen_addrs.truncate(20);
} }
self.events.push(BehaviourEvent::Identified(peer_id, info)); self.events
.push(BehaviourEvent::Identified(peer_id, Box::new(info)));
} }
IdentifyEvent::Error { .. } => {} IdentifyEvent::Error { .. } => {}
IdentifyEvent::SendBack { .. } => {} IdentifyEvent::SendBack { .. } => {}
@ -183,12 +178,12 @@ impl<TSubstream: AsyncRead + AsyncWrite> Behaviour<TSubstream> {
pub enum BehaviourEvent { pub enum BehaviourEvent {
RPC(PeerId, RPCEvent), RPC(PeerId, RPCEvent),
PeerDialed(PeerId), PeerDialed(PeerId),
Identified(PeerId, IdentifyInfo), Identified(PeerId, Box<IdentifyInfo>),
// TODO: This is a stub at the moment // TODO: This is a stub at the moment
GossipMessage { GossipMessage {
source: PeerId, source: PeerId,
topics: Vec<TopicHash>, topics: Vec<TopicHash>,
message: PubsubMessage, message: Box<PubsubMessage>,
}, },
} }

View File

@ -1,7 +1,7 @@
use ssz::{Decodable, DecodeError, Encodable, SszStream}; use ssz::{Decodable, DecodeError, Encodable, SszStream};
/// Available RPC methods types and ids. /// Available RPC methods types and ids.
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use types::{Attestation, BeaconBlockBody, BeaconBlockHeader, Epoch, Hash256, Slot}; use types::{BeaconBlockBody, BeaconBlockHeader, Epoch, Hash256, Slot};
#[derive(Debug)] #[derive(Debug)]
/// Available Serenity Libp2p RPC methods /// Available Serenity Libp2p RPC methods

View File

@ -26,7 +26,7 @@ pub struct Rpc<TSubstream> {
/// Pins the generic substream. /// Pins the generic substream.
marker: PhantomData<TSubstream>, marker: PhantomData<TSubstream>,
/// Slog logger for RPC behaviour. /// Slog logger for RPC behaviour.
log: slog::Logger, _log: slog::Logger,
} }
impl<TSubstream> Rpc<TSubstream> { impl<TSubstream> Rpc<TSubstream> {
@ -35,7 +35,7 @@ impl<TSubstream> Rpc<TSubstream> {
Rpc { Rpc {
events: Vec::new(), events: Vec::new(),
marker: PhantomData, marker: PhantomData,
log, _log: log,
} }
} }
@ -65,7 +65,7 @@ where
fn inject_connected(&mut self, peer_id: PeerId, connected_point: ConnectedPoint) { fn inject_connected(&mut self, peer_id: PeerId, connected_point: ConnectedPoint) {
// if initialised the connection, report this upwards to send the HELLO request // if initialised the connection, report this upwards to send the HELLO request
if let ConnectedPoint::Dialer { address: _ } = connected_point { if let ConnectedPoint::Dialer { .. } = connected_point {
self.events.push(NetworkBehaviourAction::GenerateEvent( self.events.push(NetworkBehaviourAction::GenerateEvent(
RPCMessage::PeerDialed(peer_id), RPCMessage::PeerDialed(peer_id),
)); ));

View File

@ -31,7 +31,7 @@ impl Default for RPCProtocol {
} }
/// A monotonic counter for ordering `RPCRequest`s. /// A monotonic counter for ordering `RPCRequest`s.
#[derive(Debug, Clone, PartialEq, Default)] #[derive(Debug, Clone, Default)]
pub struct RequestId(u64); pub struct RequestId(u64);
impl RequestId { impl RequestId {
@ -48,6 +48,12 @@ impl RequestId {
impl Eq for RequestId {} impl Eq for RequestId {}
impl PartialEq for RequestId {
fn eq(&self, other: &RequestId) -> bool {
self.0 == other.0
}
}
impl Hash for RequestId { impl Hash for RequestId {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.0.hash(state); self.0.hash(state);
@ -104,17 +110,15 @@ impl UpgradeInfo for RPCEvent {
} }
} }
type FnDecodeRPCEvent = fn(Vec<u8>, ()) -> Result<RPCEvent, DecodeError>;
impl<TSocket> InboundUpgrade<TSocket> for RPCProtocol impl<TSocket> InboundUpgrade<TSocket> for RPCProtocol
where where
TSocket: AsyncRead + AsyncWrite, TSocket: AsyncRead + AsyncWrite,
{ {
type Output = RPCEvent; type Output = RPCEvent;
type Error = DecodeError; type Error = DecodeError;
type Future = upgrade::ReadOneThen< type Future = upgrade::ReadOneThen<upgrade::Negotiated<TSocket>, (), FnDecodeRPCEvent>;
upgrade::Negotiated<TSocket>,
(),
fn(Vec<u8>, ()) -> Result<RPCEvent, DecodeError>,
>;
fn upgrade_inbound(self, socket: upgrade::Negotiated<TSocket>, _: Self::Info) -> Self::Future { fn upgrade_inbound(self, socket: upgrade::Negotiated<TSocket>, _: Self::Info) -> Self::Future {
upgrade::read_one_then(socket, MAX_READ_SIZE, (), |packet, ()| Ok(decode(packet)?)) upgrade::read_one_then(socket, MAX_READ_SIZE, (), |packet, ()| Ok(decode(packet)?))

View File

@ -19,13 +19,16 @@ use std::io::{Error, ErrorKind};
use std::time::Duration; use std::time::Duration;
use types::{TopicBuilder, TopicHash}; use types::{TopicBuilder, TopicHash};
type Libp2pStream = Boxed<(PeerId, StreamMuxerBox), Error>;
type Libp2pBehaviour = Behaviour<Substream<StreamMuxerBox>>;
/// The configuration and state of the libp2p components for the beacon node. /// The configuration and state of the libp2p components for the beacon node.
pub struct Service { pub struct Service {
/// The libp2p Swarm handler. /// The libp2p Swarm handler.
//TODO: Make this private //TODO: Make this private
pub swarm: Swarm<Boxed<(PeerId, StreamMuxerBox), Error>, Behaviour<Substream<StreamMuxerBox>>>, pub swarm: Swarm<Libp2pStream, Libp2pBehaviour>,
/// This node's PeerId. /// This node's PeerId.
local_peer_id: PeerId, _local_peer_id: PeerId,
/// The libp2p logger handle. /// The libp2p logger handle.
pub log: slog::Logger, pub log: slog::Logger,
} }
@ -89,7 +92,7 @@ impl Service {
info!(log, "Subscribed to topics: {:?}", subscribed_topics); info!(log, "Subscribed to topics: {:?}", subscribed_topics);
Ok(Service { Ok(Service {
local_peer_id, _local_peer_id: local_peer_id,
swarm, swarm,
log, log,
}) })
@ -179,11 +182,11 @@ pub enum Libp2pEvent {
/// Initiated the connection to a new peer. /// Initiated the connection to a new peer.
PeerDialed(PeerId), PeerDialed(PeerId),
/// Received information about a peer on the network. /// Received information about a peer on the network.
Identified(PeerId, IdentifyInfo), Identified(PeerId, Box<IdentifyInfo>),
/// Received pubsub message. /// Received pubsub message.
PubsubMessage { PubsubMessage {
source: PeerId, source: PeerId,
topics: Vec<TopicHash>, topics: Vec<TopicHash>,
message: PubsubMessage, message: Box<PubsubMessage>,
}, },
} }

View File

@ -15,6 +15,7 @@ version = { path = "../version" }
types = { path = "../../eth2/types" } types = { path = "../../eth2/types" }
slog = { version = "^2.2.3" , features = ["max_level_trace", "release_max_level_debug"] } slog = { version = "^2.2.3" , features = ["max_level_trace", "release_max_level_debug"] }
ssz = { path = "../../eth2/utils/ssz" } ssz = { path = "../../eth2/utils/ssz" }
tree_hash = { path = "../../eth2/utils/tree_hash" }
futures = "0.1.25" futures = "0.1.25"
error-chain = "0.12.0" error-chain = "0.12.0"
crossbeam-channel = "0.3.8" crossbeam-channel = "0.3.8"

View File

@ -41,7 +41,7 @@ pub enum HandlerMessage {
/// An RPC response/request has been received. /// An RPC response/request has been received.
RPC(PeerId, RPCEvent), RPC(PeerId, RPCEvent),
/// A gossip message has been received. /// A gossip message has been received.
PubsubMessage(PeerId, PubsubMessage), PubsubMessage(PeerId, Box<PubsubMessage>),
} }
impl MessageHandler { impl MessageHandler {
@ -93,7 +93,7 @@ impl MessageHandler {
} }
// we have received an RPC message request/response // we have received an RPC message request/response
HandlerMessage::PubsubMessage(peer_id, gossip) => { HandlerMessage::PubsubMessage(peer_id, gossip) => {
self.handle_gossip(peer_id, gossip); self.handle_gossip(peer_id, *gossip);
} }
//TODO: Handle all messages //TODO: Handle all messages
_ => {} _ => {}

View File

@ -17,7 +17,7 @@ use types::Topic;
/// Service that handles communication between internal services and the eth2_libp2p network service. /// Service that handles communication between internal services and the eth2_libp2p network service.
pub struct Service { pub struct Service {
//libp2p_service: Arc<Mutex<LibP2PService>>, //libp2p_service: Arc<Mutex<LibP2PService>>,
libp2p_exit: oneshot::Sender<()>, _libp2p_exit: oneshot::Sender<()>,
network_send: crossbeam_channel::Sender<NetworkMessage>, network_send: crossbeam_channel::Sender<NetworkMessage>,
//message_handler: MessageHandler, //message_handler: MessageHandler,
//message_handler_send: Sender<HandlerMessage>, //message_handler_send: Sender<HandlerMessage>,
@ -54,7 +54,7 @@ impl Service {
log, log,
)?; )?;
let network_service = Service { let network_service = Service {
libp2p_exit, _libp2p_exit: libp2p_exit,
network_send: network_send.clone(), network_send: network_send.clone(),
}; };
@ -131,9 +131,7 @@ fn network_service(
); );
} }
Libp2pEvent::PubsubMessage { Libp2pEvent::PubsubMessage {
source, source, message, ..
topics: _,
message,
} => { } => {
//TODO: Decide if we need to propagate the topic upwards. (Potentially for //TODO: Decide if we need to propagate the topic upwards. (Potentially for
//attestations) //attestations)
@ -167,7 +165,7 @@ fn network_service(
} }
Ok(NetworkMessage::Publish { topics, message }) => { Ok(NetworkMessage::Publish { topics, message }) => {
debug!(log, "Sending pubsub message on topics {:?}", topics); debug!(log, "Sending pubsub message on topics {:?}", topics);
libp2p_service.swarm.publish(topics, message); libp2p_service.swarm.publish(topics, *message);
} }
Err(TryRecvError::Empty) => break, Err(TryRecvError::Empty) => break,
Err(TryRecvError::Disconnected) => { Err(TryRecvError::Disconnected) => {
@ -190,7 +188,7 @@ pub enum NetworkMessage {
/// Publish a message to pubsub mechanism. /// Publish a message to pubsub mechanism.
Publish { Publish {
topics: Vec<Topic>, topics: Vec<Topic>,
message: PubsubMessage, message: Box<PubsubMessage>,
}, },
} }

View File

@ -2,9 +2,9 @@ use crate::beacon_chain::BeaconChain;
use eth2_libp2p::rpc::methods::*; use eth2_libp2p::rpc::methods::*;
use eth2_libp2p::PeerId; use eth2_libp2p::PeerId;
use slog::{debug, error}; use slog::{debug, error};
use ssz::TreeHash;
use std::sync::Arc; use std::sync::Arc;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use tree_hash::TreeHash;
use types::{BeaconBlock, BeaconBlockBody, BeaconBlockHeader, Hash256, Slot}; use types::{BeaconBlock, BeaconBlockBody, BeaconBlockHeader, Hash256, Slot};
/// Provides a queue for fully and partially built `BeaconBlock`s. /// Provides a queue for fully and partially built `BeaconBlock`s.
@ -15,7 +15,7 @@ use types::{BeaconBlock, BeaconBlockBody, BeaconBlockHeader, Hash256, Slot};
/// ///
/// - When we receive a `BeaconBlockBody`, the only way we can find it's matching /// - When we receive a `BeaconBlockBody`, the only way we can find it's matching
/// `BeaconBlockHeader` is to find a header such that `header.beacon_block_body == /// `BeaconBlockHeader` is to find a header such that `header.beacon_block_body ==
/// hash_tree_root(body)`. Therefore, if we used a `HashMap` we would need to use the root of /// tree_hash_root(body)`. Therefore, if we used a `HashMap` we would need to use the root of
/// `BeaconBlockBody` as the key. /// `BeaconBlockBody` as the key.
/// - It is possible for multiple distinct blocks to have identical `BeaconBlockBodies`. Therefore /// - It is possible for multiple distinct blocks to have identical `BeaconBlockBodies`. Therefore
/// we cannot use a `HashMap` keyed by the root of `BeaconBlockBody`. /// we cannot use a `HashMap` keyed by the root of `BeaconBlockBody`.
@ -166,7 +166,7 @@ impl ImportQueue {
let mut required_bodies: Vec<Hash256> = vec![]; let mut required_bodies: Vec<Hash256> = vec![];
for header in headers { for header in headers {
let block_root = Hash256::from_slice(&header.hash_tree_root()[..]); let block_root = Hash256::from_slice(&header.tree_hash_root()[..]);
if self.chain_has_not_seen_block(&block_root) { if self.chain_has_not_seen_block(&block_root) {
self.insert_header(block_root, header, sender.clone()); self.insert_header(block_root, header, sender.clone());
@ -230,7 +230,7 @@ impl ImportQueue {
/// ///
/// If the body already existed, the `inserted` time is set to `now`. /// If the body already existed, the `inserted` time is set to `now`.
fn insert_body(&mut self, body: BeaconBlockBody, sender: PeerId) { fn insert_body(&mut self, body: BeaconBlockBody, sender: PeerId) {
let body_root = Hash256::from_slice(&body.hash_tree_root()[..]); let body_root = Hash256::from_slice(&body.tree_hash_root()[..]);
self.partials.iter_mut().for_each(|mut p| { self.partials.iter_mut().for_each(|mut p| {
if let Some(header) = &mut p.header { if let Some(header) = &mut p.header {
@ -250,7 +250,7 @@ impl ImportQueue {
/// ///
/// If the partial already existed, the `inserted` time is set to `now`. /// If the partial already existed, the `inserted` time is set to `now`.
fn insert_full_block(&mut self, block: BeaconBlock, sender: PeerId) { fn insert_full_block(&mut self, block: BeaconBlock, sender: PeerId) {
let block_root = Hash256::from_slice(&block.hash_tree_root()[..]); let block_root = Hash256::from_slice(&block.tree_hash_root()[..]);
let partial = PartialBeaconBlock { let partial = PartialBeaconBlock {
slot: block.slot, slot: block.slot,

View File

@ -5,17 +5,17 @@ use eth2_libp2p::rpc::methods::*;
use eth2_libp2p::rpc::{RPCRequest, RPCResponse, RequestId}; use eth2_libp2p::rpc::{RPCRequest, RPCResponse, RequestId};
use eth2_libp2p::PeerId; use eth2_libp2p::PeerId;
use slog::{debug, error, info, o, warn}; use slog::{debug, error, info, o, warn};
use ssz::TreeHash;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use tree_hash::TreeHash;
use types::{Attestation, BeaconBlock, Epoch, Hash256, Slot}; use types::{Attestation, BeaconBlock, Epoch, Hash256, Slot};
/// The number of slots that we can import blocks ahead of us, before going into full Sync mode. /// The number of slots that we can import blocks ahead of us, before going into full Sync mode.
const SLOT_IMPORT_TOLERANCE: u64 = 100; const SLOT_IMPORT_TOLERANCE: u64 = 100;
/// The amount of seconds a block (or partial block) may exist in the import queue. /// The amount of seconds a block (or partial block) may exist in the import queue.
const QUEUE_STALE_SECS: u64 = 60; const QUEUE_STALE_SECS: u64 = 600;
/// If a block is more than `FUTURE_SLOT_TOLERANCE` slots ahead of our slot clock, we drop it. /// If a block is more than `FUTURE_SLOT_TOLERANCE` slots ahead of our slot clock, we drop it.
/// Otherwise we queue it. /// Otherwise we queue it.
@ -65,7 +65,7 @@ pub enum PeerStatus {
} }
impl PeerStatus { impl PeerStatus {
pub fn should_handshake(&self) -> bool { pub fn should_handshake(self) -> bool {
match self { match self {
PeerStatus::DifferentNetworkId => false, PeerStatus::DifferentNetworkId => false,
PeerStatus::FinalizedEpochNotInChain => false, PeerStatus::FinalizedEpochNotInChain => false,
@ -565,7 +565,7 @@ impl SimpleSync {
return false; return false;
} }
let block_root = Hash256::from_slice(&block.hash_tree_root()); let block_root = Hash256::from_slice(&block.tree_hash_root());
// Ignore any block that the chain already knows about. // Ignore any block that the chain already knows about.
if self.chain_has_seen_block(&block_root) { if self.chain_has_seen_block(&block_root) {
@ -582,7 +582,26 @@ impl SimpleSync {
); );
match self.chain.process_block(block.clone()) { match self.chain.process_block(block.clone()) {
Ok(BlockProcessingOutcome::InvalidBlock(InvalidBlock::ParentUnknown)) => { Ok(BlockProcessingOutcome::InvalidBlock(InvalidBlock::ParentUnknown)) => {
// get the parent. // The block was valid and we processed it successfully.
debug!(
self.log, "NewGossipBlock";
"msg" => "parent block unknown",
"parent_root" => format!("{}", block.previous_block_root),
"peer" => format!("{:?}", peer_id),
);
// Queue the block for later processing.
self.import_queue
.enqueue_full_blocks(vec![block], peer_id.clone());
// Send a hello to learn of the clients best slot so we can then sync the require
// parent(s).
network.send_rpc_request(
peer_id.clone(),
RPCRequest::Hello(self.chain.hello_message()),
);
// Forward the block onto our peers.
//
// Note: this may need to be changed if we decide to only forward blocks if we have
// all required info.
true true
} }
Ok(BlockProcessingOutcome::InvalidBlock(InvalidBlock::FutureSlot { Ok(BlockProcessingOutcome::InvalidBlock(InvalidBlock::FutureSlot {
@ -710,12 +729,21 @@ impl SimpleSync {
"reason" => format!("{:?}", outcome), "reason" => format!("{:?}", outcome),
); );
network.disconnect(sender, GoodbyeReason::Fault); network.disconnect(sender, GoodbyeReason::Fault);
break;
} }
// If this results to true, the item will be removed from the queue. // If this results to true, the item will be removed from the queue.
if outcome.sucessfully_processed() { if outcome.sucessfully_processed() {
successful += 1; successful += 1;
self.import_queue.remove(block_root); self.import_queue.remove(block_root);
} else {
debug!(
self.log,
"ProcessImportQueue";
"msg" => "Block not imported",
"outcome" => format!("{:?}", outcome),
"peer" => format!("{:?}", sender),
);
} }
} }
Err(e) => { Err(e) => {

View File

@ -43,9 +43,9 @@ impl AttestationService for AttestationServiceInstance {
let f = sink let f = sink
.fail(RpcStatus::new( .fail(RpcStatus::new(
RpcStatusCode::OutOfRange, RpcStatusCode::OutOfRange,
Some(format!( Some(
"AttestationData request for a slot that is in the future." "AttestationData request for a slot that is in the future.".to_string(),
)), ),
)) ))
.map_err(move |e| { .map_err(move |e| {
error!(log_clone, "Failed to reply with failure {:?}: {:?}", req, e) error!(log_clone, "Failed to reply with failure {:?}: {:?}", req, e)
@ -58,9 +58,7 @@ impl AttestationService for AttestationServiceInstance {
let f = sink let f = sink
.fail(RpcStatus::new( .fail(RpcStatus::new(
RpcStatusCode::InvalidArgument, RpcStatusCode::InvalidArgument,
Some(format!( Some("AttestationData request for a slot that is in the past.".to_string()),
"AttestationData request for a slot that is in the past."
)),
)) ))
.map_err(move |e| { .map_err(move |e| {
error!(log_clone, "Failed to reply with failure {:?}: {:?}", req, e) error!(log_clone, "Failed to reply with failure {:?}: {:?}", req, e)

View File

@ -43,7 +43,7 @@ impl BeaconBlockService for BeaconBlockServiceInstance {
let f = sink let f = sink
.fail(RpcStatus::new( .fail(RpcStatus::new(
RpcStatusCode::InvalidArgument, RpcStatusCode::InvalidArgument,
Some(format!("Invalid randao reveal signature")), Some("Invalid randao reveal signature".to_string()),
)) ))
.map_err(move |e| warn!(log_clone, "failed to reply {:?}: {:?}", req, e)); .map_err(move |e| warn!(log_clone, "failed to reply {:?}: {:?}", req, e));
return ctx.spawn(f); return ctx.spawn(f);
@ -114,7 +114,7 @@ impl BeaconBlockService for BeaconBlockServiceInstance {
self.network_chan self.network_chan
.send(NetworkMessage::Publish { .send(NetworkMessage::Publish {
topics: vec![topic], topics: vec![topic],
message, message: Box::new(message),
}) })
.unwrap_or_else(|e| { .unwrap_or_else(|e| {
error!( error!(

View File

@ -24,7 +24,7 @@ impl BeaconNodeService for BeaconNodeServiceInstance {
// get the chain state // get the chain state
let state = self.chain.get_state(); let state = self.chain.get_state();
let state_fork = state.fork.clone(); let state_fork = state.fork.clone();
let genesis_time = state.genesis_time.clone(); let genesis_time = state.genesis_time;
// build the rpc fork struct // build the rpc fork struct
let mut fork = Fork::new(); let mut fork = Fork::new();
@ -35,7 +35,7 @@ impl BeaconNodeService for BeaconNodeServiceInstance {
node_info.set_fork(fork); node_info.set_fork(fork);
node_info.set_genesis_time(genesis_time); node_info.set_genesis_time(genesis_time);
node_info.set_genesis_slot(self.chain.get_spec().genesis_slot.as_u64()); node_info.set_genesis_slot(self.chain.get_spec().genesis_slot.as_u64());
node_info.set_chain_id(self.chain.get_spec().chain_id as u32); node_info.set_chain_id(u32::from(self.chain.get_spec().chain_id));
// send the node_info the requester // send the node_info the requester
let error_log = self.log.clone(); let error_log = self.log.clone();

View File

@ -5,7 +5,7 @@ use grpcio::{RpcContext, RpcStatus, RpcStatusCode, UnarySink};
use protos::services::{ActiveValidator, GetDutiesRequest, GetDutiesResponse, ValidatorDuty}; use protos::services::{ActiveValidator, GetDutiesRequest, GetDutiesResponse, ValidatorDuty};
use protos::services_grpc::ValidatorService; use protos::services_grpc::ValidatorService;
use slog::{trace, warn}; use slog::{trace, warn};
use ssz::Decodable; use ssz::decode;
use std::sync::Arc; use std::sync::Arc;
use types::{Epoch, RelativeEpoch}; use types::{Epoch, RelativeEpoch};
@ -74,8 +74,8 @@ impl ValidatorService for ValidatorServiceInstance {
for validator_pk in validators.get_public_keys() { for validator_pk in validators.get_public_keys() {
let mut active_validator = ActiveValidator::new(); let mut active_validator = ActiveValidator::new();
let public_key = match PublicKey::ssz_decode(validator_pk, 0) { let public_key = match decode::<PublicKey>(validator_pk) {
Ok((v, _index)) => v, Ok(v) => v,
Err(_) => { Err(_) => {
let log_clone = self.log.clone(); let log_clone = self.log.clone();
let f = sink let f = sink
@ -83,7 +83,7 @@ impl ValidatorService for ValidatorServiceInstance {
RpcStatusCode::InvalidArgument, RpcStatusCode::InvalidArgument,
Some("Invalid public_key".to_string()), Some("Invalid public_key".to_string()),
)) ))
.map_err(move |e| warn!(log_clone, "failed to reply {:?}", req)); .map_err(move |_| warn!(log_clone, "failed to reply {:?}", req));
return ctx.spawn(f); return ctx.spawn(f);
} }
}; };

View File

@ -16,6 +16,7 @@ fn main() {
.version(version::version().as_str()) .version(version::version().as_str())
.author("Sigma Prime <contact@sigmaprime.io>") .author("Sigma Prime <contact@sigmaprime.io>")
.about("Eth 2.0 Client") .about("Eth 2.0 Client")
// file system related arguments
.arg( .arg(
Arg::with_name("datadir") Arg::with_name("datadir")
.long("datadir") .long("datadir")
@ -23,8 +24,9 @@ fn main() {
.help("Data directory for keys and databases.") .help("Data directory for keys and databases.")
.takes_value(true), .takes_value(true),
) )
// network related arguments
.arg( .arg(
Arg::with_name("listen_address") Arg::with_name("listen-address")
.long("listen-address") .long("listen-address")
.value_name("Listen Address") .value_name("Listen Address")
.help("The Network address to listen for p2p connections.") .help("The Network address to listen for p2p connections.")
@ -37,6 +39,14 @@ fn main() {
.help("Network listen port for p2p connections.") .help("Network listen port for p2p connections.")
.takes_value(true), .takes_value(true),
) )
.arg(
Arg::with_name("boot-nodes")
.long("boot-nodes")
.value_name("BOOTNODES")
.help("A list of comma separated multi addresses representing bootnodes to connect to.")
.takes_value(true),
)
// rpc related arguments
.arg( .arg(
Arg::with_name("rpc") Arg::with_name("rpc")
.long("rpc") .long("rpc")

View File

@ -7,4 +7,5 @@ edition = "2018"
[dependencies] [dependencies]
slot_clock = { path = "../../eth2/utils/slot_clock" } slot_clock = { path = "../../eth2/utils/slot_clock" }
ssz = { path = "../../eth2/utils/ssz" } ssz = { path = "../../eth2/utils/ssz" }
tree_hash = { path = "../../eth2/utils/tree_hash" }
types = { path = "../../eth2/types" } types = { path = "../../eth2/types" }

View File

@ -2,8 +2,8 @@ pub mod test_utils;
mod traits; mod traits;
use slot_clock::SlotClock; use slot_clock::SlotClock;
use ssz::TreeHash;
use std::sync::Arc; use std::sync::Arc;
use tree_hash::TreeHash;
use types::{AttestationData, AttestationDataAndCustodyBit, FreeAttestation, Signature, Slot}; use types::{AttestationData, AttestationDataAndCustodyBit, FreeAttestation, Signature, Slot};
pub use self::traits::{ pub use self::traits::{
@ -141,7 +141,7 @@ impl<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> Attester<T, U, V,
data: attestation_data.clone(), data: attestation_data.clone(),
custody_bit: PHASE_0_CUSTODY_BIT, custody_bit: PHASE_0_CUSTODY_BIT,
} }
.hash_tree_root(); .tree_hash_root();
self.signer self.signer
.sign_attestation_message(&message[..], DOMAIN_ATTESTATION) .sign_attestation_message(&message[..], DOMAIN_ATTESTATION)

View File

@ -8,4 +8,5 @@ edition = "2018"
int_to_bytes = { path = "../utils/int_to_bytes" } int_to_bytes = { path = "../utils/int_to_bytes" }
slot_clock = { path = "../utils/slot_clock" } slot_clock = { path = "../utils/slot_clock" }
ssz = { path = "../utils/ssz" } ssz = { path = "../utils/ssz" }
tree_hash = { path = "../../eth2/utils/tree_hash" }
types = { path = "../types" } types = { path = "../types" }

View File

@ -2,8 +2,8 @@ pub mod test_utils;
mod traits; mod traits;
use slot_clock::SlotClock; use slot_clock::SlotClock;
use ssz::{SignedRoot, TreeHash};
use std::sync::Arc; use std::sync::Arc;
use tree_hash::{SignedRoot, TreeHash};
use types::{BeaconBlock, ChainSpec, Domain, Slot}; use types::{BeaconBlock, ChainSpec, Domain, Slot};
pub use self::traits::{ pub use self::traits::{
@ -139,7 +139,7 @@ impl<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> BlockProducer<T, U
let randao_reveal = { let randao_reveal = {
// TODO: add domain, etc to this message. Also ensure result matches `into_to_bytes32`. // TODO: add domain, etc to this message. Also ensure result matches `into_to_bytes32`.
let message = slot.epoch(self.spec.slots_per_epoch).hash_tree_root(); let message = slot.epoch(self.spec.slots_per_epoch).tree_hash_root();
match self.signer.sign_randao_reveal( match self.signer.sign_randao_reveal(
&message, &message,

View File

@ -1,3 +1,4 @@
#![cfg(not(debug_assertions))]
// Tests the available fork-choice algorithms // Tests the available fork-choice algorithms
extern crate beacon_chain; extern crate beacon_chain;

View File

@ -74,15 +74,26 @@ impl AttestationId {
/// the aggregate attestation introduces, and is proportional to the size of the reward we will /// the aggregate attestation introduces, and is proportional to the size of the reward we will
/// receive for including it in a block. /// receive for including it in a block.
// TODO: this could be optimised with a map from validator index to whether that validator has // TODO: this could be optimised with a map from validator index to whether that validator has
// attested in the *current* epoch. Alternatively, we could cache an index that allows us to // attested in each of the current and previous epochs. Currently quadractic in number of validators.
// quickly look up the attestations in the current epoch for a given shard. fn attestation_score(attestation: &Attestation, state: &BeaconState, spec: &ChainSpec) -> usize {
fn attestation_score(attestation: &Attestation, state: &BeaconState) -> usize {
// Bitfield of validators whose attestations are new/fresh. // Bitfield of validators whose attestations are new/fresh.
let mut new_validators = attestation.aggregation_bitfield.clone(); let mut new_validators = attestation.aggregation_bitfield.clone();
state let attestation_epoch = attestation.data.slot.epoch(spec.slots_per_epoch);
.current_epoch_attestations
let state_attestations = if attestation_epoch == state.current_epoch(spec) {
&state.current_epoch_attestations
} else if attestation_epoch == state.previous_epoch(spec) {
&state.previous_epoch_attestations
} else {
return 0;
};
state_attestations
.iter() .iter()
// In a single epoch, an attester should only be attesting for one shard.
// TODO: we avoid including slashable attestations in the state here,
// but maybe we should do something else with them (like construct slashings).
.filter(|current_attestation| current_attestation.data.shard == attestation.data.shard) .filter(|current_attestation| current_attestation.data.shard == attestation.data.shard)
.for_each(|current_attestation| { .for_each(|current_attestation| {
// Remove the validators who have signed the existing attestation (they are not new) // Remove the validators who have signed the existing attestation (they are not new)
@ -178,7 +189,9 @@ impl OperationPool {
.filter(|attestation| validate_attestation(state, attestation, spec).is_ok()) .filter(|attestation| validate_attestation(state, attestation, spec).is_ok())
// Scored by the number of new attestations they introduce (descending) // Scored by the number of new attestations they introduce (descending)
// TODO: need to consider attestations introduced in THIS block // TODO: need to consider attestations introduced in THIS block
.map(|att| (att, attestation_score(att, state))) .map(|att| (att, attestation_score(att, state, spec)))
// Don't include any useless attestations (score 0)
.filter(|&(_, score)| score != 0)
.sorted_by_key(|&(_, score)| std::cmp::Reverse(score)) .sorted_by_key(|&(_, score)| std::cmp::Reverse(score))
// Limited to the maximum number of attestations per block // Limited to the maximum number of attestations per block
.take(spec.max_attestations as usize) .take(spec.max_attestations as usize)
@ -682,6 +695,7 @@ mod tests {
/// Create a signed attestation for use in tests. /// Create a signed attestation for use in tests.
/// Signed by all validators in `committee[signing_range]` and `committee[extra_signer]`. /// Signed by all validators in `committee[signing_range]` and `committee[extra_signer]`.
#[cfg(not(debug_assertions))]
fn signed_attestation<R: std::slice::SliceIndex<[usize], Output = [usize]>>( fn signed_attestation<R: std::slice::SliceIndex<[usize], Output = [usize]>>(
committee: &CrosslinkCommittee, committee: &CrosslinkCommittee,
keypairs: &[Keypair], keypairs: &[Keypair],
@ -714,6 +728,7 @@ mod tests {
} }
/// Test state for attestation-related tests. /// Test state for attestation-related tests.
#[cfg(not(debug_assertions))]
fn attestation_test_state( fn attestation_test_state(
spec: &ChainSpec, spec: &ChainSpec,
num_committees: usize, num_committees: usize,
@ -722,7 +737,7 @@ mod tests {
num_committees * (spec.slots_per_epoch * spec.target_committee_size) as usize; num_committees * (spec.slots_per_epoch * spec.target_committee_size) as usize;
let mut state_builder = let mut state_builder =
TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(num_validators, spec); TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(num_validators, spec);
let slot_offset = 100000; let slot_offset = 1000 * spec.slots_per_epoch + spec.slots_per_epoch / 2;
let slot = spec.genesis_slot + slot_offset; let slot = spec.genesis_slot + slot_offset;
state_builder.teleport_to_slot(slot, spec); state_builder.teleport_to_slot(slot, spec);
state_builder.build_caches(spec).unwrap(); state_builder.build_caches(spec).unwrap();
@ -730,6 +745,7 @@ mod tests {
} }
/// Set the latest crosslink in the state to match the attestation. /// Set the latest crosslink in the state to match the attestation.
#[cfg(not(debug_assertions))]
fn fake_latest_crosslink(att: &Attestation, state: &mut BeaconState, spec: &ChainSpec) { fn fake_latest_crosslink(att: &Attestation, state: &mut BeaconState, spec: &ChainSpec) {
state.latest_crosslinks[att.data.shard as usize] = Crosslink { state.latest_crosslinks[att.data.shard as usize] = Crosslink {
crosslink_data_root: att.data.crosslink_data_root, crosslink_data_root: att.data.crosslink_data_root,
@ -738,6 +754,7 @@ mod tests {
} }
#[test] #[test]
#[cfg(not(debug_assertions))]
fn test_attestation_score() { fn test_attestation_score() {
let spec = &ChainSpec::foundation(); let spec = &ChainSpec::foundation();
let (ref mut state, ref keypairs) = attestation_test_state(spec, 1); let (ref mut state, ref keypairs) = attestation_test_state(spec, 1);
@ -753,7 +770,7 @@ mod tests {
assert_eq!( assert_eq!(
att1.aggregation_bitfield.num_set_bits(), att1.aggregation_bitfield.num_set_bits(),
attestation_score(&att1, state) attestation_score(&att1, state, spec)
); );
state state
@ -762,13 +779,14 @@ mod tests {
assert_eq!( assert_eq!(
committee.committee.len() - 2, committee.committee.len() - 2,
attestation_score(&att2, &state) attestation_score(&att2, state, spec)
); );
} }
} }
/// End-to-end test of basic attestation handling. /// End-to-end test of basic attestation handling.
#[test] #[test]
#[cfg(not(debug_assertions))]
fn attestation_aggregation_insert_get_prune() { fn attestation_aggregation_insert_get_prune() {
let spec = &ChainSpec::foundation(); let spec = &ChainSpec::foundation();
let (ref mut state, ref keypairs) = attestation_test_state(spec, 1); let (ref mut state, ref keypairs) = attestation_test_state(spec, 1);
@ -834,6 +852,7 @@ mod tests {
/// Adding an attestation already in the pool should not increase the size of the pool. /// Adding an attestation already in the pool should not increase the size of the pool.
#[test] #[test]
#[cfg(not(debug_assertions))]
fn attestation_duplicate() { fn attestation_duplicate() {
let spec = &ChainSpec::foundation(); let spec = &ChainSpec::foundation();
let (ref mut state, ref keypairs) = attestation_test_state(spec, 1); let (ref mut state, ref keypairs) = attestation_test_state(spec, 1);
@ -860,6 +879,7 @@ mod tests {
/// Adding lots of attestations that only intersect pairwise should lead to two aggregate /// Adding lots of attestations that only intersect pairwise should lead to two aggregate
/// attestations. /// attestations.
#[test] #[test]
#[cfg(not(debug_assertions))]
fn attestation_pairwise_overlapping() { fn attestation_pairwise_overlapping() {
let spec = &ChainSpec::foundation(); let spec = &ChainSpec::foundation();
let (ref mut state, ref keypairs) = attestation_test_state(spec, 1); let (ref mut state, ref keypairs) = attestation_test_state(spec, 1);
@ -902,6 +922,7 @@ mod tests {
/// high-quality attestations. To ensure that no aggregation occurs, ALL attestations /// high-quality attestations. To ensure that no aggregation occurs, ALL attestations
/// are also signed by the 0th member of the committee. /// are also signed by the 0th member of the committee.
#[test] #[test]
#[cfg(not(debug_assertions))]
fn attestation_get_max() { fn attestation_get_max() {
let spec = &ChainSpec::foundation(); let spec = &ChainSpec::foundation();
let small_step_size = 2; let small_step_size = 2;

View File

@ -14,6 +14,7 @@ env_logger = "0.6.0"
serde = "1.0" serde = "1.0"
serde_derive = "1.0" serde_derive = "1.0"
serde_yaml = "0.8" serde_yaml = "0.8"
yaml-utils = { path = "yaml_utils" }
[dependencies] [dependencies]
bls = { path = "../utils/bls" } bls = { path = "../utils/bls" }
@ -25,5 +26,10 @@ log = "0.4"
merkle_proof = { path = "../utils/merkle_proof" } merkle_proof = { path = "../utils/merkle_proof" }
ssz = { path = "../utils/ssz" } ssz = { path = "../utils/ssz" }
ssz_derive = { path = "../utils/ssz_derive" } ssz_derive = { path = "../utils/ssz_derive" }
tree_hash = { path = "../utils/tree_hash" }
tree_hash_derive = { path = "../utils/tree_hash_derive" }
types = { path = "../types" } types = { path = "../types" }
rayon = "1.0" rayon = "1.0"
[features]
fake_crypto = ["bls/fake_crypto"]

View File

@ -1,6 +1,5 @@
use criterion::Criterion; use criterion::Criterion;
use criterion::{black_box, Benchmark}; use criterion::{black_box, Benchmark};
use ssz::TreeHash;
use state_processing::{ use state_processing::{
per_block_processing, per_block_processing,
per_block_processing::{ per_block_processing::{
@ -9,6 +8,7 @@ use state_processing::{
verify_block_signature, verify_block_signature,
}, },
}; };
use tree_hash::TreeHash;
use types::*; use types::*;
/// Run the detailed benchmarking suite on the given `BeaconState`. /// Run the detailed benchmarking suite on the given `BeaconState`.
@ -263,7 +263,7 @@ pub fn bench_block_processing(
c.bench( c.bench(
&format!("{}/block_processing", desc), &format!("{}/block_processing", desc),
Benchmark::new("tree_hash_block", move |b| { Benchmark::new("tree_hash_block", move |b| {
b.iter(|| black_box(block.hash_tree_root())) b.iter(|| black_box(block.tree_hash_root()))
}) })
.sample_size(10), .sample_size(10),
); );

View File

@ -1,6 +1,5 @@
use criterion::Criterion; use criterion::Criterion;
use criterion::{black_box, Benchmark}; use criterion::{black_box, Benchmark};
use ssz::TreeHash;
use state_processing::{ use state_processing::{
per_epoch_processing, per_epoch_processing,
per_epoch_processing::{ per_epoch_processing::{
@ -9,6 +8,7 @@ use state_processing::{
update_active_tree_index_roots, update_latest_slashed_balances, update_active_tree_index_roots, update_latest_slashed_balances,
}, },
}; };
use tree_hash::TreeHash;
use types::test_utils::TestingBeaconStateBuilder; use types::test_utils::TestingBeaconStateBuilder;
use types::*; use types::*;
@ -256,7 +256,7 @@ fn bench_epoch_processing(c: &mut Criterion, state: &BeaconState, spec: &ChainSp
c.bench( c.bench(
&format!("{}/epoch_processing", desc), &format!("{}/epoch_processing", desc),
Benchmark::new("tree_hash_state", move |b| { Benchmark::new("tree_hash_state", move |b| {
b.iter(|| black_box(state_clone.hash_tree_root())) b.iter(|| black_box(state_clone.tree_hash_root()))
}) })
.sample_size(SMALL_BENCHING_SAMPLE_SIZE), .sample_size(SMALL_BENCHING_SAMPLE_SIZE),
); );

View File

@ -0,0 +1 @@
../utils/bls/build.rs

View File

@ -1,708 +0,0 @@
title: Sanity tests -- small config -- 32 validators
summary: Basic sanity checks from phase 0 spec pythonization using a small state configuration and 32 validators.
All tests are run with `verify_signatures` as set to False.
Tests generated via https://github.com/ethereum/research/blob/master/spec_pythonizer/sanity_check.py
test_suite: beacon_state
fork: phase0-0.5.0
test_cases:
- name: test_empty_block_transition
config:
SHARD_COUNT: 8
TARGET_COMMITTEE_SIZE: 4
MAX_BALANCE_CHURN_QUOTIENT: 32
MAX_INDICES_PER_SLASHABLE_VOTE: 4096
MAX_EXIT_DEQUEUES_PER_EPOCH: 4
SHUFFLE_ROUND_COUNT: 90
DEPOSIT_CONTRACT_TREE_DEPTH: 32
MIN_DEPOSIT_AMOUNT: 1000000000
MAX_DEPOSIT_AMOUNT: 32000000000
FORK_CHOICE_BALANCE_INCREMENT: 1000000000
EJECTION_BALANCE: 16000000000
GENESIS_FORK_VERSION: 0
GENESIS_SLOT: 4294967296
GENESIS_EPOCH: 536870912
GENESIS_START_SHARD: 0
BLS_WITHDRAWAL_PREFIX_BYTE: '0x00'
SECONDS_PER_SLOT: 6
MIN_ATTESTATION_INCLUSION_DELAY: 2
SLOTS_PER_EPOCH: 8
MIN_SEED_LOOKAHEAD: 1
ACTIVATION_EXIT_DELAY: 4
EPOCHS_PER_ETH1_VOTING_PERIOD: 16
SLOTS_PER_HISTORICAL_ROOT: 64
MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256
PERSISTENT_COMMITTEE_PERIOD: 2048
LATEST_RANDAO_MIXES_LENGTH: 64
LATEST_ACTIVE_INDEX_ROOTS_LENGTH: 64
LATEST_SLASHED_EXIT_LENGTH: 64
BASE_REWARD_QUOTIENT: 32
WHISTLEBLOWER_REWARD_QUOTIENT: 512
ATTESTATION_INCLUSION_REWARD_QUOTIENT: 8
INACTIVITY_PENALTY_QUOTIENT: 16777216
MIN_PENALTY_QUOTIENT: 32
MAX_PROPOSER_SLASHINGS: 16
MAX_ATTESTER_SLASHINGS: 1
MAX_ATTESTATIONS: 128
MAX_DEPOSITS: 16
MAX_VOLUNTARY_EXITS: 16
MAX_TRANSFERS: 16
DOMAIN_BEACON_BLOCK: 0
DOMAIN_RANDAO: 1
DOMAIN_ATTESTATION: 2
DOMAIN_DEPOSIT: 3
DOMAIN_VOLUNTARY_EXIT: 4
DOMAIN_TRANSFER: 5
verify_signatures: false
initial_state:
slot: 4294967296
genesis_time: 0
fork:
previous_version: '0x00000000'
current_version: '0x00000000'
epoch: 536870912
validator_registry:
- pubkey: '0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000001'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000002'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x89ece308f9d1f0131765212deca99697b112d61f9be9a5f1f3780a51335b3ff981747a0b2ca2179b96d2c0c9024e5224'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000003'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xac9b60d5afcbd5663a8a44b7c5a02f19e9a77ab0a35bd65809bb5c67ec582c897feb04decc694b13e08587f3ff9b5b60'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000004'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xb0e7791fb972fe014159aa33a98622da3cdc98ff707965e536d8636b5fcc5ac7a91a8c46e59a00dca575af0f18fb13dc'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000005'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xa6e82f6da4520f85c5d27d8f329eccfa05944fd1096b20734c894966d12a9e2a9a9744529d7212d33883113a0cadb909'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000006'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xb928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000007'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xa85ae765588126f5e860d019c0e26235f567a9c0c0b2d8ff30f3e8d436b1082596e5e7462d20f5be3764fd473e57f9cf'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000008'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x99cdf3807146e68e041314ca93e1fee0991224ec2a74beb2866816fd0826ce7b6263ee31e953a86d1b72cc2215a57793'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000009'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xaf81da25ecf1c84b577fefbedd61077a81dc43b00304015b2b596ab67f00e41c86bb00ebd0f90d4b125eb0539891aeed'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000000a'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x80fd75ebcc0a21649e3177bcce15426da0e4f25d6828fbf4038d4d7ed3bd4421de3ef61d70f794687b12b2d571971a55'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000000b'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x8345dd80ffef0eaec8920e39ebb7f5e9ae9c1d6179e9129b705923df7830c67f3690cbc48649d4079eadf5397339580c'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000000c'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x851f8a0b82a6d86202a61cbc3b0f3db7d19650b914587bde4715ccd372e1e40cab95517779d840416e1679c84a6db24e'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000000d'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x99bef05aaba1ea467fcbc9c420f5e3153c9d2b5f9bf2c7e2e7f6946f854043627b45b008607b9a9108bb96f3c1c089d3'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000000e'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x8d9e19b3f4c7c233a6112e5397309f9812a4f61f754f11dd3dcb8b07d55a7b1dfea65f19a1488a14fef9a41495083582'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000000f'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xa73eb991aa22cdb794da6fcde55a427f0a4df5a4a70de23a988b5e5fc8c4d844f66d990273267a54dd21579b7ba6a086'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000010'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xb098f178f84fc753a76bb63709e9be91eec3ff5f7f3a5f4836f34fe8a1a6d6c5578d8fd820573cef3a01e2bfef3eaf3a'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000011'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x9252a4ac3529f8b2b6e8189b95a60b8865f07f9a9b73f98d5df708511d3f68632c4c7d1e2b03e6b1d1e2c01839752ada'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000012'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xb271205227c7aa27f45f20b3ba380dfea8b51efae91fd32e552774c99e2a1237aa59c0c43f52aad99bba3783ea2f36a4'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000013'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xa272e9d1d50a4aea7d8f0583948090d0888be5777f2846800b8281139cd4aa9eee05f89b069857a3e77ccfaae1615f9c'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000014'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x9780e853f8ce7eda772c6691d25e220ca1d2ab0db51a7824b700620f7ac94c06639e91c98bb6abd78128f0ec845df8ef'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000015'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xab48aa2cc6f4a0bb63b5d67be54ac3aed10326dda304c5aeb9e942b40d6e7610478377680ab90e092ef1895e62786008'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000016'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x8c8b694b04d98a749a0763c72fc020ef61b2bb3f63ebb182cb2e568f6a8b9ca3ae013ae78317599e7e7ba2a528ec754a'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000017'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x9717182463fbe215168e6762abcbb55c5c65290f2b5a2af616f8a6f50d625b46164178a11622d21913efdfa4b800648d'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000018'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xacb58c81ae0cae2e9d4d446b730922239923c345744eee58efaadb36e9a0925545b18a987acf0bad469035b291e37269'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000019'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x81ccc19e3b938ec2405099e90022a4218baa5082a3ca0974b24be0bc8b07e5fffaed64bef0d02c4dbfb6a307829afc5c'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000001a'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xab83dfefb120fab7665a607d749ef1765fbb3cc0ba5827a20a135402c09d987c701ddb5b60f0f5495026817e8ab6ea2e'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000001b'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xb6ad11e5d15f77c1143b1697344911b9c590110fdd8dd09df2e58bfd757269169deefe8be3544d4e049fb3776fb0bcfb'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000001c'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x8515e7f61ca0470e165a44d247a23f17f24bf6e37185467bedb7981c1003ea70bbec875703f793dd8d11e56afa7f74ba'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000001d'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xad84464b3966ec5bede84aa487facfca7823af383715078da03b387cc2f5d5597cdd7d025aa07db00a38b953bdeb6e3f'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000001e'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xb29043a7273d0a2dbc2b747dcf6a5eccbd7ccb44b2d72e985537b117929bc3fd3a99001481327788ad040b4077c47c0d'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000001f'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xa72841987e4f219d54f2b6a9eac5fe6e78704644753c3579e776a3691bc123743f8c63770ed0f72a71e9e964dbf58f43'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000020'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
validator_balances:
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
validator_registry_update_epoch: 536870912
latest_randao_mixes:
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
previous_shuffling_start_shard: 0
current_shuffling_start_shard: 0
previous_shuffling_epoch: 536870912
current_shuffling_epoch: 536870912
previous_shuffling_seed: '0x0000000000000000000000000000000000000000000000000000000000000000'
current_shuffling_seed: '0x7a81d831e99dc63f9f10d4abce84c26473d4c2f65ec4acf9000684059473b072'
previous_epoch_attestations: []
current_epoch_attestations: []
previous_justified_epoch: 536870912
current_justified_epoch: 536870912
previous_justified_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
current_justified_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
justification_bitfield: 0
finalized_epoch: 536870912
finalized_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
latest_crosslinks:
- epoch: 536870912
crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
- epoch: 536870912
crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
- epoch: 536870912
crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
- epoch: 536870912
crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
- epoch: 536870912
crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
- epoch: 536870912
crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
- epoch: 536870912
crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
- epoch: 536870912
crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
latest_block_roots:
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
latest_state_roots:
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
latest_active_index_roots:
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
latest_slashed_balances:
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
latest_block_header:
slot: 4294967296
previous_block_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
state_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
block_body_root: '0x13f2001ff0ee4a528b3c43f63d70a997aefca990ed8eada2223ee6ec3807f7cc'
signature: '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
historical_roots: []
latest_eth1_data:
deposit_root: '0x826d25bfcb9161aabc799844c5176f7b3444dc5288856f65e0b8060560488912'
block_hash: '0x0000000000000000000000000000000000000000000000000000000000000000'
eth1_data_votes: []
deposit_index: 32
blocks:
- slot: 4294967297
previous_block_root: '0x2befbd4b4fe8c91f3059082c8048e3376a9b7fb309e93044fac32b7cc8849773'
state_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
body:
randao_reveal: '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
eth1_data:
deposit_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
block_hash: '0x0000000000000000000000000000000000000000000000000000000000000000'
proposer_slashings: []
attester_slashings: []
attestations: []
deposits: []
voluntary_exits: []
transfers: []
signature: '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
expected_state:
slot: 4294967297

View File

@ -2,7 +2,7 @@ use types::{BeaconStateError as Error, *};
/// Exit the validator of the given `index`. /// Exit the validator of the given `index`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn exit_validator( pub fn exit_validator(
state: &mut BeaconState, state: &mut BeaconState,
validator_index: usize, validator_index: usize,

View File

@ -3,7 +3,7 @@ use types::{BeaconStateError as Error, *};
/// Slash the validator with index ``index``. /// Slash the validator with index ``index``.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn slash_validator( pub fn slash_validator(
state: &mut BeaconState, state: &mut BeaconState,
validator_index: usize, validator_index: usize,

View File

@ -4,7 +4,7 @@ use types::*;
/// ///
/// Is title `verify_bitfield` in spec. /// Is title `verify_bitfield` in spec.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn verify_bitfield_length(bitfield: &Bitfield, committee_size: usize) -> bool { pub fn verify_bitfield_length(bitfield: &Bitfield, committee_size: usize) -> bool {
if bitfield.num_bytes() != ((committee_size + 7) / 8) { if bitfield.num_bytes() != ((committee_size + 7) / 8) {
return false; return false;
@ -18,3 +18,62 @@ pub fn verify_bitfield_length(bitfield: &Bitfield, committee_size: usize) -> boo
true true
} }
#[cfg(test)]
mod test {
use super::*;
#[test]
fn bitfield_length() {
assert_eq!(
verify_bitfield_length(&Bitfield::from_bytes(&[0b0000_0001]), 4),
true
);
assert_eq!(
verify_bitfield_length(&Bitfield::from_bytes(&[0b0001_0001]), 4),
false
);
assert_eq!(
verify_bitfield_length(&Bitfield::from_bytes(&[0b0000_0000]), 4),
true
);
assert_eq!(
verify_bitfield_length(&Bitfield::from_bytes(&[0b1000_0000]), 8),
true
);
assert_eq!(
verify_bitfield_length(&Bitfield::from_bytes(&[0b1000_0000, 0b0000_0000]), 16),
true
);
assert_eq!(
verify_bitfield_length(&Bitfield::from_bytes(&[0b1000_0000, 0b0000_0000]), 15),
false
);
assert_eq!(
verify_bitfield_length(&Bitfield::from_bytes(&[0b0000_0000, 0b0000_0000]), 8),
false
);
assert_eq!(
verify_bitfield_length(
&Bitfield::from_bytes(&[0b0000_0000, 0b0000_0000, 0b0000_0000]),
8
),
false
);
assert_eq!(
verify_bitfield_length(
&Bitfield::from_bytes(&[0b0000_0000, 0b0000_0000, 0b0000_0000]),
24
),
true
);
}
}

View File

@ -1,5 +1,5 @@
use super::per_block_processing::{errors::BlockProcessingError, process_deposits}; use super::per_block_processing::{errors::BlockProcessingError, process_deposits};
use ssz::TreeHash; use tree_hash::TreeHash;
use types::*; use types::*;
pub enum GenesisError { pub enum GenesisError {
@ -9,13 +9,13 @@ pub enum GenesisError {
/// Returns the genesis `BeaconState` /// Returns the genesis `BeaconState`
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn get_genesis_state( pub fn get_genesis_state(
genesis_validator_deposits: &[Deposit], genesis_validator_deposits: &[Deposit],
genesis_time: u64, genesis_time: u64,
genesis_eth1_data: Eth1Data, genesis_eth1_data: Eth1Data,
spec: &ChainSpec, spec: &ChainSpec,
) -> Result<(), BlockProcessingError> { ) -> Result<BeaconState, BlockProcessingError> {
// Get the genesis `BeaconState` // Get the genesis `BeaconState`
let mut state = BeaconState::genesis(genesis_time, genesis_eth1_data, spec); let mut state = BeaconState::genesis(genesis_time, genesis_eth1_data, spec);
@ -36,13 +36,13 @@ pub fn get_genesis_state(
let active_validator_indices = state let active_validator_indices = state
.get_cached_active_validator_indices(RelativeEpoch::Current, spec)? .get_cached_active_validator_indices(RelativeEpoch::Current, spec)?
.to_vec(); .to_vec();
let genesis_active_index_root = Hash256::from_slice(&active_validator_indices.hash_tree_root()); let genesis_active_index_root = Hash256::from_slice(&active_validator_indices.tree_hash_root());
state.fill_active_index_roots_with(genesis_active_index_root, spec); state.fill_active_index_roots_with(genesis_active_index_root, spec);
// Generate the current shuffling seed. // Generate the current shuffling seed.
state.current_shuffling_seed = state.generate_seed(spec.genesis_epoch, spec)?; state.current_shuffling_seed = state.generate_seed(spec.genesis_epoch, spec)?;
Ok(()) Ok(state)
} }
impl From<BlockProcessingError> for GenesisError { impl From<BlockProcessingError> for GenesisError {

View File

@ -1,7 +1,7 @@
use crate::common::slash_validator; use crate::common::slash_validator;
use errors::{BlockInvalid as Invalid, BlockProcessingError as Error, IntoWithIndex}; use errors::{BlockInvalid as Invalid, BlockProcessingError as Error, IntoWithIndex};
use rayon::prelude::*; use rayon::prelude::*;
use ssz::{SignedRoot, TreeHash}; use tree_hash::{SignedRoot, TreeHash};
use types::*; use types::*;
pub use self::verify_attester_slashing::{ pub use self::verify_attester_slashing::{
@ -39,7 +39,7 @@ const VERIFY_DEPOSIT_MERKLE_PROOFS: bool = false;
/// Returns `Ok(())` if the block is valid and the state was successfully updated. Otherwise /// Returns `Ok(())` if the block is valid and the state was successfully updated. Otherwise
/// returns an error describing why the block was invalid or how the function failed to execute. /// returns an error describing why the block was invalid or how the function failed to execute.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn per_block_processing( pub fn per_block_processing(
state: &mut BeaconState, state: &mut BeaconState,
block: &BeaconBlock, block: &BeaconBlock,
@ -54,7 +54,7 @@ pub fn per_block_processing(
/// Returns `Ok(())` if the block is valid and the state was successfully updated. Otherwise /// Returns `Ok(())` if the block is valid and the state was successfully updated. Otherwise
/// returns an error describing why the block was invalid or how the function failed to execute. /// returns an error describing why the block was invalid or how the function failed to execute.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn per_block_processing_without_verifying_block_signature( pub fn per_block_processing_without_verifying_block_signature(
state: &mut BeaconState, state: &mut BeaconState,
block: &BeaconBlock, block: &BeaconBlock,
@ -69,7 +69,7 @@ pub fn per_block_processing_without_verifying_block_signature(
/// Returns `Ok(())` if the block is valid and the state was successfully updated. Otherwise /// Returns `Ok(())` if the block is valid and the state was successfully updated. Otherwise
/// returns an error describing why the block was invalid or how the function failed to execute. /// returns an error describing why the block was invalid or how the function failed to execute.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn per_block_processing_signature_optional( fn per_block_processing_signature_optional(
mut state: &mut BeaconState, mut state: &mut BeaconState,
block: &BeaconBlock, block: &BeaconBlock,
@ -99,7 +99,7 @@ fn per_block_processing_signature_optional(
/// Processes the block header. /// Processes the block header.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn process_block_header( pub fn process_block_header(
state: &mut BeaconState, state: &mut BeaconState,
block: &BeaconBlock, block: &BeaconBlock,
@ -107,12 +107,14 @@ pub fn process_block_header(
) -> Result<(), Error> { ) -> Result<(), Error> {
verify!(block.slot == state.slot, Invalid::StateSlotMismatch); verify!(block.slot == state.slot, Invalid::StateSlotMismatch);
// NOTE: this is not to spec. I think spec is broken. See: let expected_previous_block_root =
// Hash256::from_slice(&state.latest_block_header.signed_root());
// https://github.com/ethereum/eth2.0-specs/issues/797
verify!( verify!(
block.previous_block_root == *state.get_block_root(state.slot - 1, spec)?, block.previous_block_root == expected_previous_block_root,
Invalid::ParentBlockRootMismatch Invalid::ParentBlockRootMismatch {
state: expected_previous_block_root,
block: block.previous_block_root,
}
); );
state.latest_block_header = block.temporary_block_header(spec); state.latest_block_header = block.temporary_block_header(spec);
@ -122,7 +124,7 @@ pub fn process_block_header(
/// Verifies the signature of a block. /// Verifies the signature of a block.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn verify_block_signature( pub fn verify_block_signature(
state: &BeaconState, state: &BeaconState,
block: &BeaconBlock, block: &BeaconBlock,
@ -150,7 +152,7 @@ pub fn verify_block_signature(
/// Verifies the `randao_reveal` against the block's proposer pubkey and updates /// Verifies the `randao_reveal` against the block's proposer pubkey and updates
/// `state.latest_randao_mixes`. /// `state.latest_randao_mixes`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn process_randao( pub fn process_randao(
state: &mut BeaconState, state: &mut BeaconState,
block: &BeaconBlock, block: &BeaconBlock,
@ -162,7 +164,7 @@ pub fn process_randao(
// Verify the RANDAO is a valid signature of the proposer. // Verify the RANDAO is a valid signature of the proposer.
verify!( verify!(
block.body.randao_reveal.verify( block.body.randao_reveal.verify(
&state.current_epoch(spec).hash_tree_root()[..], &state.current_epoch(spec).tree_hash_root()[..],
spec.get_domain( spec.get_domain(
block.slot.epoch(spec.slots_per_epoch), block.slot.epoch(spec.slots_per_epoch),
Domain::Randao, Domain::Randao,
@ -181,7 +183,7 @@ pub fn process_randao(
/// Update the `state.eth1_data_votes` based upon the `eth1_data` provided. /// Update the `state.eth1_data_votes` based upon the `eth1_data` provided.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn process_eth1_data(state: &mut BeaconState, eth1_data: &Eth1Data) -> Result<(), Error> { pub fn process_eth1_data(state: &mut BeaconState, eth1_data: &Eth1Data) -> Result<(), Error> {
// Attempt to find a `Eth1DataVote` with matching `Eth1Data`. // Attempt to find a `Eth1DataVote` with matching `Eth1Data`.
let matching_eth1_vote_index = state let matching_eth1_vote_index = state
@ -207,7 +209,7 @@ pub fn process_eth1_data(state: &mut BeaconState, eth1_data: &Eth1Data) -> Resul
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns /// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
/// an `Err` describing the invalid object or cause of failure. /// an `Err` describing the invalid object or cause of failure.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn process_proposer_slashings( pub fn process_proposer_slashings(
state: &mut BeaconState, state: &mut BeaconState,
proposer_slashings: &[ProposerSlashing], proposer_slashings: &[ProposerSlashing],
@ -240,7 +242,7 @@ pub fn process_proposer_slashings(
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns /// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
/// an `Err` describing the invalid object or cause of failure. /// an `Err` describing the invalid object or cause of failure.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn process_attester_slashings( pub fn process_attester_slashings(
state: &mut BeaconState, state: &mut BeaconState,
attester_slashings: &[AttesterSlashing], attester_slashings: &[AttesterSlashing],
@ -298,7 +300,7 @@ pub fn process_attester_slashings(
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns /// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
/// an `Err` describing the invalid object or cause of failure. /// an `Err` describing the invalid object or cause of failure.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn process_attestations( pub fn process_attestations(
state: &mut BeaconState, state: &mut BeaconState,
attestations: &[Attestation], attestations: &[Attestation],
@ -340,7 +342,7 @@ pub fn process_attestations(
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns /// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
/// an `Err` describing the invalid object or cause of failure. /// an `Err` describing the invalid object or cause of failure.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn process_deposits( pub fn process_deposits(
state: &mut BeaconState, state: &mut BeaconState,
deposits: &[Deposit], deposits: &[Deposit],
@ -410,7 +412,7 @@ pub fn process_deposits(
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns /// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
/// an `Err` describing the invalid object or cause of failure. /// an `Err` describing the invalid object or cause of failure.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn process_exits( pub fn process_exits(
state: &mut BeaconState, state: &mut BeaconState,
voluntary_exits: &[VoluntaryExit], voluntary_exits: &[VoluntaryExit],
@ -442,7 +444,7 @@ pub fn process_exits(
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns /// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
/// an `Err` describing the invalid object or cause of failure. /// an `Err` describing the invalid object or cause of failure.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn process_transfers( pub fn process_transfers(
state: &mut BeaconState, state: &mut BeaconState,
transfers: &[Transfer], transfers: &[Transfer],

View File

@ -67,7 +67,10 @@ impl_from_beacon_state_error!(BlockProcessingError);
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum BlockInvalid { pub enum BlockInvalid {
StateSlotMismatch, StateSlotMismatch,
ParentBlockRootMismatch, ParentBlockRootMismatch {
state: Hash256,
block: Hash256,
},
BadSignature, BadSignature,
BadRandaoSignature, BadRandaoSignature,
MaxAttestationsExceeded, MaxAttestationsExceeded,
@ -271,10 +274,10 @@ pub enum ProposerSlashingValidationError {
pub enum ProposerSlashingInvalid { pub enum ProposerSlashingInvalid {
/// The proposer index is not a known validator. /// The proposer index is not a known validator.
ProposerUnknown(u64), ProposerUnknown(u64),
/// The two proposal have different slots. /// The two proposal have different epochs.
/// ///
/// (proposal_1_slot, proposal_2_slot) /// (proposal_1_slot, proposal_2_slot)
ProposalSlotMismatch(Slot, Slot), ProposalEpochMismatch(Slot, Slot),
/// The proposals are identical and therefore not slashable. /// The proposals are identical and therefore not slashable.
ProposalsIdentical, ProposalsIdentical,
/// The specified proposer has already been slashed. /// The specified proposer has already been slashed.

View File

@ -1,6 +1,6 @@
use super::errors::{AttestationInvalid as Invalid, AttestationValidationError as Error}; use super::errors::{AttestationInvalid as Invalid, AttestationValidationError as Error};
use crate::common::verify_bitfield_length; use crate::common::verify_bitfield_length;
use ssz::TreeHash; use tree_hash::TreeHash;
use types::*; use types::*;
/// Indicates if an `Attestation` is valid to be included in a block in the current epoch of the /// Indicates if an `Attestation` is valid to be included in a block in the current epoch of the
@ -8,7 +8,7 @@ use types::*;
/// ///
/// Returns `Ok(())` if the `Attestation` is valid, otherwise indicates the reason for invalidity. /// Returns `Ok(())` if the `Attestation` is valid, otherwise indicates the reason for invalidity.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn validate_attestation( pub fn validate_attestation(
state: &BeaconState, state: &BeaconState,
attestation: &Attestation, attestation: &Attestation,
@ -31,7 +31,7 @@ pub fn validate_attestation_time_independent_only(
/// ///
/// Returns `Ok(())` if the `Attestation` is valid, otherwise indicates the reason for invalidity. /// Returns `Ok(())` if the `Attestation` is valid, otherwise indicates the reason for invalidity.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn validate_attestation_without_signature( pub fn validate_attestation_without_signature(
state: &BeaconState, state: &BeaconState,
attestation: &Attestation, attestation: &Attestation,
@ -44,7 +44,7 @@ pub fn validate_attestation_without_signature(
/// given state, optionally validating the aggregate signature. /// given state, optionally validating the aggregate signature.
/// ///
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn validate_attestation_parametric( fn validate_attestation_parametric(
state: &BeaconState, state: &BeaconState,
attestation: &Attestation, attestation: &Attestation,
@ -167,7 +167,7 @@ fn validate_attestation_parametric(
/// Verify that the `source_epoch` and `source_root` of an `Attestation` correctly /// Verify that the `source_epoch` and `source_root` of an `Attestation` correctly
/// match the current (or previous) justified epoch and root from the state. /// match the current (or previous) justified epoch and root from the state.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn verify_justified_epoch_and_root( fn verify_justified_epoch_and_root(
attestation: &Attestation, attestation: &Attestation,
state: &BeaconState, state: &BeaconState,
@ -222,7 +222,7 @@ fn verify_justified_epoch_and_root(
/// - `custody_bitfield` does not have a bit for each index of `committee`. /// - `custody_bitfield` does not have a bit for each index of `committee`.
/// - A `validator_index` in `committee` is not in `state.validator_registry`. /// - A `validator_index` in `committee` is not in `state.validator_registry`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn verify_attestation_signature( fn verify_attestation_signature(
state: &BeaconState, state: &BeaconState,
committee: &[usize], committee: &[usize],
@ -270,14 +270,14 @@ fn verify_attestation_signature(
data: a.data.clone(), data: a.data.clone(),
custody_bit: false, custody_bit: false,
} }
.hash_tree_root(); .tree_hash_root();
// Message when custody bitfield is `true` // Message when custody bitfield is `true`
let message_1 = AttestationDataAndCustodyBit { let message_1 = AttestationDataAndCustodyBit {
data: a.data.clone(), data: a.data.clone(),
custody_bit: true, custody_bit: true,
} }
.hash_tree_root(); .tree_hash_root();
let mut messages = vec![]; let mut messages = vec![];
let mut keys = vec![]; let mut keys = vec![];

View File

@ -7,7 +7,7 @@ use types::*;
/// ///
/// Returns `Ok(())` if the `AttesterSlashing` is valid, otherwise indicates the reason for invalidity. /// Returns `Ok(())` if the `AttesterSlashing` is valid, otherwise indicates the reason for invalidity.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn verify_attester_slashing( pub fn verify_attester_slashing(
state: &BeaconState, state: &BeaconState,
attester_slashing: &AttesterSlashing, attester_slashing: &AttesterSlashing,
@ -41,7 +41,7 @@ pub fn verify_attester_slashing(
/// ///
/// Returns Ok(indices) if `indices.len() > 0`. /// Returns Ok(indices) if `indices.len() > 0`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn gather_attester_slashing_indices( pub fn gather_attester_slashing_indices(
state: &BeaconState, state: &BeaconState,
attester_slashing: &AttesterSlashing, attester_slashing: &AttesterSlashing,

View File

@ -15,7 +15,7 @@ use types::*;
/// ///
/// Note: this function is incomplete. /// Note: this function is incomplete.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn verify_deposit( pub fn verify_deposit(
state: &BeaconState, state: &BeaconState,
deposit: &Deposit, deposit: &Deposit,
@ -46,7 +46,7 @@ pub fn verify_deposit(
/// Verify that the `Deposit` index is correct. /// Verify that the `Deposit` index is correct.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn verify_deposit_index(state: &BeaconState, deposit: &Deposit) -> Result<(), Error> { pub fn verify_deposit_index(state: &BeaconState, deposit: &Deposit) -> Result<(), Error> {
verify!( verify!(
deposit.index == state.deposit_index, deposit.index == state.deposit_index,
@ -88,7 +88,7 @@ pub fn get_existing_validator_index(
/// Verify that a deposit is included in the state's eth1 deposit root. /// Verify that a deposit is included in the state's eth1 deposit root.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn verify_deposit_merkle_proof(state: &BeaconState, deposit: &Deposit, spec: &ChainSpec) -> bool { fn verify_deposit_merkle_proof(state: &BeaconState, deposit: &Deposit, spec: &ChainSpec) -> bool {
let leaf = hash(&get_serialized_deposit_data(deposit)); let leaf = hash(&get_serialized_deposit_data(deposit));
verify_merkle_proof( verify_merkle_proof(
@ -102,7 +102,7 @@ fn verify_deposit_merkle_proof(state: &BeaconState, deposit: &Deposit, spec: &Ch
/// Helper struct for easily getting the serialized data generated by the deposit contract. /// Helper struct for easily getting the serialized data generated by the deposit contract.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive(Encode)] #[derive(Encode)]
struct SerializedDepositData { struct SerializedDepositData {
amount: u64, amount: u64,
@ -113,7 +113,7 @@ struct SerializedDepositData {
/// Return the serialized data generated by the deposit contract that is used to generate the /// Return the serialized data generated by the deposit contract that is used to generate the
/// merkle proof. /// merkle proof.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn get_serialized_deposit_data(deposit: &Deposit) -> Vec<u8> { fn get_serialized_deposit_data(deposit: &Deposit) -> Vec<u8> {
let serialized_deposit_data = SerializedDepositData { let serialized_deposit_data = SerializedDepositData {
amount: deposit.deposit_data.amount, amount: deposit.deposit_data.amount,

View File

@ -1,5 +1,5 @@
use super::errors::{ExitInvalid as Invalid, ExitValidationError as Error}; use super::errors::{ExitInvalid as Invalid, ExitValidationError as Error};
use ssz::SignedRoot; use tree_hash::SignedRoot;
use types::*; use types::*;
/// Indicates if an `Exit` is valid to be included in a block in the current epoch of the given /// Indicates if an `Exit` is valid to be included in a block in the current epoch of the given
@ -7,7 +7,7 @@ use types::*;
/// ///
/// Returns `Ok(())` if the `Exit` is valid, otherwise indicates the reason for invalidity. /// Returns `Ok(())` if the `Exit` is valid, otherwise indicates the reason for invalidity.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn verify_exit( pub fn verify_exit(
state: &BeaconState, state: &BeaconState,
exit: &VoluntaryExit, exit: &VoluntaryExit,

View File

@ -1,5 +1,5 @@
use super::errors::{ProposerSlashingInvalid as Invalid, ProposerSlashingValidationError as Error}; use super::errors::{ProposerSlashingInvalid as Invalid, ProposerSlashingValidationError as Error};
use ssz::SignedRoot; use tree_hash::SignedRoot;
use types::*; use types::*;
/// Indicates if a `ProposerSlashing` is valid to be included in a block in the current epoch of the given /// Indicates if a `ProposerSlashing` is valid to be included in a block in the current epoch of the given
@ -7,7 +7,7 @@ use types::*;
/// ///
/// Returns `Ok(())` if the `ProposerSlashing` is valid, otherwise indicates the reason for invalidity. /// Returns `Ok(())` if the `ProposerSlashing` is valid, otherwise indicates the reason for invalidity.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn verify_proposer_slashing( pub fn verify_proposer_slashing(
proposer_slashing: &ProposerSlashing, proposer_slashing: &ProposerSlashing,
state: &BeaconState, state: &BeaconState,
@ -21,8 +21,9 @@ pub fn verify_proposer_slashing(
})?; })?;
verify!( verify!(
proposer_slashing.header_1.slot == proposer_slashing.header_2.slot, proposer_slashing.header_1.slot.epoch(spec.slots_per_epoch)
Invalid::ProposalSlotMismatch( == proposer_slashing.header_2.slot.epoch(spec.slots_per_epoch),
Invalid::ProposalEpochMismatch(
proposer_slashing.header_1.slot, proposer_slashing.header_1.slot,
proposer_slashing.header_2.slot proposer_slashing.header_2.slot
) )
@ -66,7 +67,7 @@ pub fn verify_proposer_slashing(
/// ///
/// Returns `true` if the signature is valid. /// Returns `true` if the signature is valid.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn verify_header_signature( fn verify_header_signature(
header: &BeaconBlockHeader, header: &BeaconBlockHeader,
pubkey: &PublicKey, pubkey: &PublicKey,

View File

@ -2,7 +2,7 @@ use super::errors::{
SlashableAttestationInvalid as Invalid, SlashableAttestationValidationError as Error, SlashableAttestationInvalid as Invalid, SlashableAttestationValidationError as Error,
}; };
use crate::common::verify_bitfield_length; use crate::common::verify_bitfield_length;
use ssz::TreeHash; use tree_hash::TreeHash;
use types::*; use types::*;
/// Indicates if a `SlashableAttestation` is valid to be included in a block in the current epoch of the given /// Indicates if a `SlashableAttestation` is valid to be included in a block in the current epoch of the given
@ -10,7 +10,7 @@ use types::*;
/// ///
/// Returns `Ok(())` if the `SlashableAttestation` is valid, otherwise indicates the reason for invalidity. /// Returns `Ok(())` if the `SlashableAttestation` is valid, otherwise indicates the reason for invalidity.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn verify_slashable_attestation( pub fn verify_slashable_attestation(
state: &BeaconState, state: &BeaconState,
slashable_attestation: &SlashableAttestation, slashable_attestation: &SlashableAttestation,
@ -77,12 +77,12 @@ pub fn verify_slashable_attestation(
data: slashable_attestation.data.clone(), data: slashable_attestation.data.clone(),
custody_bit: false, custody_bit: false,
} }
.hash_tree_root(); .tree_hash_root();
let message_1 = AttestationDataAndCustodyBit { let message_1 = AttestationDataAndCustodyBit {
data: slashable_attestation.data.clone(), data: slashable_attestation.data.clone(),
custody_bit: true, custody_bit: true,
} }
.hash_tree_root(); .tree_hash_root();
let mut messages = vec![]; let mut messages = vec![];
let mut keys = vec![]; let mut keys = vec![];

View File

@ -1,6 +1,6 @@
use super::errors::{TransferInvalid as Invalid, TransferValidationError as Error}; use super::errors::{TransferInvalid as Invalid, TransferValidationError as Error};
use bls::get_withdrawal_credentials; use bls::get_withdrawal_credentials;
use ssz::SignedRoot; use tree_hash::SignedRoot;
use types::*; use types::*;
/// Indicates if a `Transfer` is valid to be included in a block in the current epoch of the given /// Indicates if a `Transfer` is valid to be included in a block in the current epoch of the given
@ -10,7 +10,7 @@ use types::*;
/// ///
/// Note: this function is incomplete. /// Note: this function is incomplete.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn verify_transfer( pub fn verify_transfer(
state: &BeaconState, state: &BeaconState,
transfer: &Transfer, transfer: &Transfer,
@ -122,7 +122,7 @@ fn verify_transfer_parametric(
/// ///
/// Does not check that the transfer is valid, however checks for overflow in all actions. /// Does not check that the transfer is valid, however checks for overflow in all actions.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn execute_transfer( pub fn execute_transfer(
state: &mut BeaconState, state: &mut BeaconState,
transfer: &Transfer, transfer: &Transfer,

View File

@ -3,8 +3,8 @@ use errors::EpochProcessingError as Error;
use process_ejections::process_ejections; use process_ejections::process_ejections;
use process_exit_queue::process_exit_queue; use process_exit_queue::process_exit_queue;
use process_slashings::process_slashings; use process_slashings::process_slashings;
use ssz::TreeHash;
use std::collections::HashMap; use std::collections::HashMap;
use tree_hash::TreeHash;
use types::*; use types::*;
use update_registry_and_shuffling_data::update_registry_and_shuffling_data; use update_registry_and_shuffling_data::update_registry_and_shuffling_data;
use validator_statuses::{TotalBalances, ValidatorStatuses}; use validator_statuses::{TotalBalances, ValidatorStatuses};
@ -32,7 +32,7 @@ pub type WinningRootHashSet = HashMap<u64, WinningRoot>;
/// Mutates the given `BeaconState`, returning early if an error is encountered. If an error is /// Mutates the given `BeaconState`, returning early if an error is encountered. If an error is
/// returned, a state might be "half-processed" and therefore in an invalid state. /// returned, a state might be "half-processed" and therefore in an invalid state.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn per_epoch_processing(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> { pub fn per_epoch_processing(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> {
// Ensure the previous and next epoch caches are built. // Ensure the previous and next epoch caches are built.
state.build_epoch_cache(RelativeEpoch::Previous, spec)?; state.build_epoch_cache(RelativeEpoch::Previous, spec)?;
@ -86,7 +86,7 @@ pub fn per_epoch_processing(state: &mut BeaconState, spec: &ChainSpec) -> Result
/// Maybe resets the eth1 period. /// Maybe resets the eth1 period.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn maybe_reset_eth1_period(state: &mut BeaconState, spec: &ChainSpec) { pub fn maybe_reset_eth1_period(state: &mut BeaconState, spec: &ChainSpec) {
let next_epoch = state.next_epoch(spec); let next_epoch = state.next_epoch(spec);
let voting_period = spec.epochs_per_eth1_voting_period; let voting_period = spec.epochs_per_eth1_voting_period;
@ -108,7 +108,7 @@ pub fn maybe_reset_eth1_period(state: &mut BeaconState, spec: &ChainSpec) {
/// - `justified_epoch` /// - `justified_epoch`
/// - `previous_justified_epoch` /// - `previous_justified_epoch`
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn update_justification_and_finalization( pub fn update_justification_and_finalization(
state: &mut BeaconState, state: &mut BeaconState,
total_balances: &TotalBalances, total_balances: &TotalBalances,
@ -178,7 +178,7 @@ pub fn update_justification_and_finalization(
/// ///
/// Also returns a `WinningRootHashSet` for later use during epoch processing. /// Also returns a `WinningRootHashSet` for later use during epoch processing.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn process_crosslinks( pub fn process_crosslinks(
state: &mut BeaconState, state: &mut BeaconState,
spec: &ChainSpec, spec: &ChainSpec,
@ -221,7 +221,7 @@ pub fn process_crosslinks(
/// Finish up an epoch update. /// Finish up an epoch update.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn finish_epoch_update(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> { pub fn finish_epoch_update(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> {
let current_epoch = state.current_epoch(spec); let current_epoch = state.current_epoch(spec);
let next_epoch = state.next_epoch(spec); let next_epoch = state.next_epoch(spec);
@ -236,7 +236,7 @@ pub fn finish_epoch_update(state: &mut BeaconState, spec: &ChainSpec) -> Result<
let active_index_root = Hash256::from_slice( let active_index_root = Hash256::from_slice(
&state &state
.get_active_validator_indices(next_epoch + spec.activation_exit_delay) .get_active_validator_indices(next_epoch + spec.activation_exit_delay)
.hash_tree_root()[..], .tree_hash_root()[..],
); );
state.set_active_index_root(next_epoch, active_index_root, spec)?; state.set_active_index_root(next_epoch, active_index_root, spec)?;
@ -261,7 +261,7 @@ pub fn finish_epoch_update(state: &mut BeaconState, spec: &ChainSpec) -> Result<
let historical_batch: HistoricalBatch = state.historical_batch(); let historical_batch: HistoricalBatch = state.historical_batch();
state state
.historical_roots .historical_roots
.push(Hash256::from_slice(&historical_batch.hash_tree_root()[..])); .push(Hash256::from_slice(&historical_batch.tree_hash_root()[..]));
} }
state.previous_epoch_attestations = state.current_epoch_attestations.clone(); state.previous_epoch_attestations = state.current_epoch_attestations.clone();

View File

@ -32,7 +32,7 @@ impl std::ops::AddAssign for Delta {
/// Apply attester and proposer rewards. /// Apply attester and proposer rewards.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn apply_rewards( pub fn apply_rewards(
state: &mut BeaconState, state: &mut BeaconState,
validator_statuses: &mut ValidatorStatuses, validator_statuses: &mut ValidatorStatuses,
@ -79,7 +79,7 @@ pub fn apply_rewards(
/// Applies the attestation inclusion reward to each proposer for every validator who included an /// Applies the attestation inclusion reward to each proposer for every validator who included an
/// attestation in the previous epoch. /// attestation in the previous epoch.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn get_proposer_deltas( fn get_proposer_deltas(
deltas: &mut Vec<Delta>, deltas: &mut Vec<Delta>,
state: &mut BeaconState, state: &mut BeaconState,
@ -120,7 +120,7 @@ fn get_proposer_deltas(
/// Apply rewards for participation in attestations during the previous epoch. /// Apply rewards for participation in attestations during the previous epoch.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn get_justification_and_finalization_deltas( fn get_justification_and_finalization_deltas(
deltas: &mut Vec<Delta>, deltas: &mut Vec<Delta>,
state: &BeaconState, state: &BeaconState,
@ -163,7 +163,7 @@ fn get_justification_and_finalization_deltas(
/// Determine the delta for a single validator, if the chain is finalizing normally. /// Determine the delta for a single validator, if the chain is finalizing normally.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn compute_normal_justification_and_finalization_delta( fn compute_normal_justification_and_finalization_delta(
validator: &ValidatorStatus, validator: &ValidatorStatus,
total_balances: &TotalBalances, total_balances: &TotalBalances,
@ -215,7 +215,7 @@ fn compute_normal_justification_and_finalization_delta(
/// Determine the delta for a single delta, assuming the chain is _not_ finalizing normally. /// Determine the delta for a single delta, assuming the chain is _not_ finalizing normally.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn compute_inactivity_leak_delta( fn compute_inactivity_leak_delta(
validator: &ValidatorStatus, validator: &ValidatorStatus,
base_reward: u64, base_reward: u64,
@ -261,7 +261,7 @@ fn compute_inactivity_leak_delta(
/// Calculate the deltas based upon the winning roots for attestations during the previous epoch. /// Calculate the deltas based upon the winning roots for attestations during the previous epoch.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn get_crosslink_deltas( fn get_crosslink_deltas(
deltas: &mut Vec<Delta>, deltas: &mut Vec<Delta>,
state: &BeaconState, state: &BeaconState,
@ -295,7 +295,7 @@ fn get_crosslink_deltas(
/// Returns the base reward for some validator. /// Returns the base reward for some validator.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn get_base_reward( fn get_base_reward(
state: &BeaconState, state: &BeaconState,
index: usize, index: usize,
@ -312,7 +312,7 @@ fn get_base_reward(
/// Returns the inactivity penalty for some validator. /// Returns the inactivity penalty for some validator.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn get_inactivity_penalty( fn get_inactivity_penalty(
state: &BeaconState, state: &BeaconState,
index: usize, index: usize,
@ -328,7 +328,7 @@ fn get_inactivity_penalty(
/// Returns the epochs since the last finalized epoch. /// Returns the epochs since the last finalized epoch.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn epochs_since_finality(state: &BeaconState, spec: &ChainSpec) -> Epoch { fn epochs_since_finality(state: &BeaconState, spec: &ChainSpec) -> Epoch {
state.current_epoch(spec) + 1 - state.finalized_epoch state.current_epoch(spec) + 1 - state.finalized_epoch
} }

View File

@ -3,7 +3,7 @@ use types::*;
/// Returns validator indices which participated in the attestation. /// Returns validator indices which participated in the attestation.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn get_attestation_participants( pub fn get_attestation_participants(
state: &BeaconState, state: &BeaconState,
attestation_data: &AttestationData, attestation_data: &AttestationData,

View File

@ -5,7 +5,7 @@ use types::*;
/// Returns the distance between the first included attestation for some validator and this /// Returns the distance between the first included attestation for some validator and this
/// slot. /// slot.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn inclusion_distance( pub fn inclusion_distance(
state: &BeaconState, state: &BeaconState,
attestations: &[&PendingAttestation], attestations: &[&PendingAttestation],
@ -18,7 +18,7 @@ pub fn inclusion_distance(
/// Returns the slot of the earliest included attestation for some validator. /// Returns the slot of the earliest included attestation for some validator.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn inclusion_slot( pub fn inclusion_slot(
state: &BeaconState, state: &BeaconState,
attestations: &[&PendingAttestation], attestations: &[&PendingAttestation],
@ -31,7 +31,7 @@ pub fn inclusion_slot(
/// Finds the earliest included attestation for some validator. /// Finds the earliest included attestation for some validator.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn earliest_included_attestation( fn earliest_included_attestation(
state: &BeaconState, state: &BeaconState,
attestations: &[&PendingAttestation], attestations: &[&PendingAttestation],

View File

@ -4,7 +4,7 @@ use types::{BeaconStateError as Error, *};
/// Iterate through the validator registry and eject active validators with balance below /// Iterate through the validator registry and eject active validators with balance below
/// ``EJECTION_BALANCE``. /// ``EJECTION_BALANCE``.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn process_ejections(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> { pub fn process_ejections(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> {
// There is an awkward double (triple?) loop here because we can't loop across the borrowed // There is an awkward double (triple?) loop here because we can't loop across the borrowed
// active validator indices and mutate state in the one loop. // active validator indices and mutate state in the one loop.

View File

@ -2,7 +2,7 @@ use types::*;
/// Process the exit queue. /// Process the exit queue.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn process_exit_queue(state: &mut BeaconState, spec: &ChainSpec) { pub fn process_exit_queue(state: &mut BeaconState, spec: &ChainSpec) {
let current_epoch = state.current_epoch(spec); let current_epoch = state.current_epoch(spec);
@ -31,7 +31,7 @@ pub fn process_exit_queue(state: &mut BeaconState, spec: &ChainSpec) {
/// Initiate an exit for the validator of the given `index`. /// Initiate an exit for the validator of the given `index`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn prepare_validator_for_withdrawal( fn prepare_validator_for_withdrawal(
state: &mut BeaconState, state: &mut BeaconState,
validator_index: usize, validator_index: usize,

View File

@ -2,7 +2,7 @@ use types::{BeaconStateError as Error, *};
/// Process slashings. /// Process slashings.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn process_slashings( pub fn process_slashings(
state: &mut BeaconState, state: &mut BeaconState,
current_total_balance: u64, current_total_balance: u64,

View File

@ -4,7 +4,7 @@ use types::*;
/// Peforms a validator registry update, if required. /// Peforms a validator registry update, if required.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn update_registry_and_shuffling_data( pub fn update_registry_and_shuffling_data(
state: &mut BeaconState, state: &mut BeaconState,
current_total_balance: u64, current_total_balance: u64,
@ -49,7 +49,7 @@ pub fn update_registry_and_shuffling_data(
/// Returns `true` if the validator registry should be updated during an epoch processing. /// Returns `true` if the validator registry should be updated during an epoch processing.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn should_update_validator_registry( pub fn should_update_validator_registry(
state: &BeaconState, state: &BeaconState,
spec: &ChainSpec, spec: &ChainSpec,
@ -78,7 +78,7 @@ pub fn should_update_validator_registry(
/// ///
/// Note: Utilizes the cache and will fail if the appropriate cache is not initialized. /// Note: Utilizes the cache and will fail if the appropriate cache is not initialized.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn update_validator_registry( pub fn update_validator_registry(
state: &mut BeaconState, state: &mut BeaconState,
current_total_balance: u64, current_total_balance: u64,
@ -133,7 +133,7 @@ pub fn update_validator_registry(
/// Activate the validator of the given ``index``. /// Activate the validator of the given ``index``.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn activate_validator( pub fn activate_validator(
state: &mut BeaconState, state: &mut BeaconState,
validator_index: usize, validator_index: usize,

View File

@ -160,7 +160,7 @@ impl ValidatorStatuses {
/// - Active validators /// - Active validators
/// - Total balances for the current and previous epochs. /// - Total balances for the current and previous epochs.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn new(state: &BeaconState, spec: &ChainSpec) -> Result<Self, BeaconStateError> { pub fn new(state: &BeaconState, spec: &ChainSpec) -> Result<Self, BeaconStateError> {
let mut statuses = Vec::with_capacity(state.validator_registry.len()); let mut statuses = Vec::with_capacity(state.validator_registry.len());
let mut total_balances = TotalBalances::default(); let mut total_balances = TotalBalances::default();
@ -195,7 +195,7 @@ impl ValidatorStatuses {
/// Process some attestations from the given `state` updating the `statuses` and /// Process some attestations from the given `state` updating the `statuses` and
/// `total_balances` fields. /// `total_balances` fields.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn process_attestations( pub fn process_attestations(
&mut self, &mut self,
state: &BeaconState, state: &BeaconState,
@ -261,7 +261,7 @@ impl ValidatorStatuses {
/// Update the `statuses` for each validator based upon whether or not they attested to the /// Update the `statuses` for each validator based upon whether or not they attested to the
/// "winning" shard block root for the previous epoch. /// "winning" shard block root for the previous epoch.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn process_winning_roots( pub fn process_winning_roots(
&mut self, &mut self,
state: &BeaconState, state: &BeaconState,
@ -297,14 +297,14 @@ impl ValidatorStatuses {
/// Returns the distance between when the attestation was created and when it was included in a /// Returns the distance between when the attestation was created and when it was included in a
/// block. /// block.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn inclusion_distance(a: &PendingAttestation) -> Slot { fn inclusion_distance(a: &PendingAttestation) -> Slot {
a.inclusion_slot - a.data.slot a.inclusion_slot - a.data.slot
} }
/// Returns `true` if some `PendingAttestation` is from the supplied `epoch`. /// Returns `true` if some `PendingAttestation` is from the supplied `epoch`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn is_from_epoch(a: &PendingAttestation, epoch: Epoch, spec: &ChainSpec) -> bool { fn is_from_epoch(a: &PendingAttestation, epoch: Epoch, spec: &ChainSpec) -> bool {
a.data.slot.epoch(spec.slots_per_epoch) == epoch a.data.slot.epoch(spec.slots_per_epoch) == epoch
} }
@ -312,7 +312,7 @@ fn is_from_epoch(a: &PendingAttestation, epoch: Epoch, spec: &ChainSpec) -> bool
/// Returns `true` if a `PendingAttestation` and `BeaconState` share the same beacon block hash for /// Returns `true` if a `PendingAttestation` and `BeaconState` share the same beacon block hash for
/// the first slot of the given epoch. /// the first slot of the given epoch.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn has_common_epoch_boundary_root( fn has_common_epoch_boundary_root(
a: &PendingAttestation, a: &PendingAttestation,
state: &BeaconState, state: &BeaconState,
@ -328,7 +328,7 @@ fn has_common_epoch_boundary_root(
/// Returns `true` if a `PendingAttestation` and `BeaconState` share the same beacon block hash for /// Returns `true` if a `PendingAttestation` and `BeaconState` share the same beacon block hash for
/// the current slot of the `PendingAttestation`. /// the current slot of the `PendingAttestation`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn has_common_beacon_block_root( fn has_common_beacon_block_root(
a: &PendingAttestation, a: &PendingAttestation,
state: &BeaconState, state: &BeaconState,

View File

@ -16,7 +16,7 @@ impl WinningRoot {
/// A winning root is "better" than another if it has a higher `total_attesting_balance`. Ties /// A winning root is "better" than another if it has a higher `total_attesting_balance`. Ties
/// are broken by favouring the higher `crosslink_data_root` value. /// are broken by favouring the higher `crosslink_data_root` value.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn is_better_than(&self, other: &Self) -> bool { pub fn is_better_than(&self, other: &Self) -> bool {
if self.total_attesting_balance > other.total_attesting_balance { if self.total_attesting_balance > other.total_attesting_balance {
true true
@ -34,7 +34,7 @@ impl WinningRoot {
/// The `WinningRoot` object also contains additional fields that are useful in later stages of /// The `WinningRoot` object also contains additional fields that are useful in later stages of
/// per-epoch processing. /// per-epoch processing.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn winning_root( pub fn winning_root(
state: &BeaconState, state: &BeaconState,
shard: u64, shard: u64,
@ -89,7 +89,7 @@ pub fn winning_root(
/// Returns `true` if pending attestation `a` is eligible to become a winning root. /// Returns `true` if pending attestation `a` is eligible to become a winning root.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn is_eligible_for_winning_root(state: &BeaconState, a: &PendingAttestation, shard: Shard) -> bool { fn is_eligible_for_winning_root(state: &BeaconState, a: &PendingAttestation, shard: Shard) -> bool {
if shard >= state.latest_crosslinks.len() as u64 { if shard >= state.latest_crosslinks.len() as u64 {
return false; return false;
@ -100,7 +100,7 @@ fn is_eligible_for_winning_root(state: &BeaconState, a: &PendingAttestation, sha
/// Returns all indices which voted for a given crosslink. Does not contain duplicates. /// Returns all indices which voted for a given crosslink. Does not contain duplicates.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn get_attesting_validator_indices( fn get_attesting_validator_indices(
state: &BeaconState, state: &BeaconState,
shard: u64, shard: u64,

View File

@ -1,5 +1,5 @@
use crate::*; use crate::*;
use ssz::TreeHash; use tree_hash::SignedRoot;
use types::*; use types::*;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
@ -10,13 +10,9 @@ pub enum Error {
/// Advances a state forward by one slot, performing per-epoch processing if required. /// Advances a state forward by one slot, performing per-epoch processing if required.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn per_slot_processing( pub fn per_slot_processing(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> {
state: &mut BeaconState, cache_state(state, spec)?;
latest_block_header: &BeaconBlockHeader,
spec: &ChainSpec,
) -> Result<(), Error> {
cache_state(state, latest_block_header, spec)?;
if (state.slot + 1) % spec.slots_per_epoch == 0 { if (state.slot + 1) % spec.slots_per_epoch == 0 {
per_epoch_processing(state, spec)?; per_epoch_processing(state, spec)?;
@ -27,12 +23,8 @@ pub fn per_slot_processing(
Ok(()) Ok(())
} }
fn cache_state( fn cache_state(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> {
state: &mut BeaconState, let previous_slot_state_root = state.update_tree_hash_cache()?;
latest_block_header: &BeaconBlockHeader,
spec: &ChainSpec,
) -> Result<(), Error> {
let previous_slot_state_root = Hash256::from_slice(&state.hash_tree_root()[..]);
// Note: increment the state slot here to allow use of our `state_root` and `block_root` // Note: increment the state slot here to allow use of our `state_root` and `block_root`
// getter/setter functions. // getter/setter functions.
@ -46,7 +38,10 @@ fn cache_state(
state.latest_block_header.state_root = previous_slot_state_root state.latest_block_header.state_root = previous_slot_state_root
} }
let latest_block_root = Hash256::from_slice(&latest_block_header.hash_tree_root()[..]); // Store the previous slot's post state transition root.
state.set_state_root(previous_slot, previous_slot_state_root, spec)?;
let latest_block_root = Hash256::from_slice(&state.latest_block_header.signed_root()[..]);
state.set_block_root(previous_slot, latest_block_root, spec)?; state.set_block_root(previous_slot, latest_block_root, spec)?;
// Set the state slot back to what it should be. // Set the state slot back to what it should be.

View File

@ -1,6 +1,60 @@
#![cfg(not(debug_assertions))]
use serde_derive::Deserialize; use serde_derive::Deserialize;
use serde_yaml;
use state_processing::{per_block_processing, per_slot_processing};
use std::{fs::File, io::prelude::*, path::PathBuf};
use types::*; use types::*;
#[derive(Debug, Deserialize)]
pub struct ExpectedState {
pub slot: Option<Slot>,
pub genesis_time: Option<u64>,
pub fork: Option<Fork>,
pub validator_registry: Option<Vec<Validator>>,
pub validator_balances: Option<Vec<u64>>,
pub previous_epoch_attestations: Option<Vec<PendingAttestation>>,
pub current_epoch_attestations: Option<Vec<PendingAttestation>>,
pub historical_roots: Option<Vec<Hash256>>,
pub finalized_epoch: Option<Epoch>,
pub latest_block_roots: Option<TreeHashVector<Hash256>>,
}
impl ExpectedState {
// Return a list of fields that differ, and a string representation of the beacon state's field.
fn check(&self, state: &BeaconState) -> Vec<(&str, String)> {
// Check field equality
macro_rules! cfe {
($field_name:ident) => {
if self.$field_name.as_ref().map_or(true, |$field_name| {
println!(" > Checking {}", stringify!($field_name));
$field_name == &state.$field_name
}) {
vec![]
} else {
vec![(stringify!($field_name), format!("{:#?}", state.$field_name))]
}
};
}
vec![
cfe!(slot),
cfe!(genesis_time),
cfe!(fork),
cfe!(validator_registry),
cfe!(validator_balances),
cfe!(previous_epoch_attestations),
cfe!(current_epoch_attestations),
cfe!(historical_roots),
cfe!(finalized_epoch),
cfe!(latest_block_roots),
]
.into_iter()
.flat_map(|x| x)
.collect()
}
}
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct TestCase { pub struct TestCase {
pub name: String, pub name: String,
@ -8,6 +62,7 @@ pub struct TestCase {
pub verify_signatures: bool, pub verify_signatures: bool,
pub initial_state: BeaconState, pub initial_state: BeaconState,
pub blocks: Vec<BeaconBlock>, pub blocks: Vec<BeaconBlock>,
pub expected_state: ExpectedState,
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
@ -18,23 +73,81 @@ pub struct TestDoc {
pub test_cases: Vec<TestCase>, pub test_cases: Vec<TestCase>,
} }
#[test] fn load_test_case(test_name: &str) -> TestDoc {
fn yaml() {
use serde_yaml;
use std::{fs::File, io::prelude::*, path::PathBuf};
let mut file = { let mut file = {
let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
file_path_buf.push("specs/example.yml"); file_path_buf.push(format!("yaml_utils/specs/{}", test_name));
File::open(file_path_buf).unwrap() File::open(file_path_buf).unwrap()
}; };
let mut yaml_str = String::new(); let mut yaml_str = String::new();
file.read_to_string(&mut yaml_str).unwrap(); file.read_to_string(&mut yaml_str).unwrap();
yaml_str = yaml_str.to_lowercase();
let yaml_str = yaml_str.to_lowercase(); serde_yaml::from_str(&yaml_str.as_str()).unwrap()
}
let _doc: TestDoc = serde_yaml::from_str(&yaml_str.as_str()).unwrap();
fn run_state_transition_test(test_name: &str) {
let doc = load_test_case(test_name);
// Run Tests
let mut ok = true;
for (i, test_case) in doc.test_cases.iter().enumerate() {
let fake_crypto = cfg!(feature = "fake_crypto");
if !test_case.verify_signatures == fake_crypto {
println!("Running {}", test_case.name);
} else {
println!(
"Skipping {} (fake_crypto: {}, need fake: {})",
test_case.name, fake_crypto, !test_case.verify_signatures
);
continue;
}
let mut state = test_case.initial_state.clone();
for (j, block) in test_case.blocks.iter().enumerate() {
while block.slot > state.slot {
per_slot_processing(&mut state, &test_case.config).unwrap();
}
let res = per_block_processing(&mut state, &block, &test_case.config);
if res.is_err() {
println!("Error in {} (#{}), on block {}", test_case.name, i, j);
println!("{:?}", res);
ok = false;
}
}
let mismatched_fields = test_case.expected_state.check(&state);
if !mismatched_fields.is_empty() {
println!(
"Error in expected state, these fields didn't match: {:?}",
mismatched_fields.iter().map(|(f, _)| f).collect::<Vec<_>>()
);
for (field_name, state_val) in mismatched_fields {
println!("state.{} was: {}", field_name, state_val);
}
ok = false;
}
}
assert!(ok, "one or more tests failed, see above");
}
#[test]
#[cfg(not(debug_assertions))]
fn test_read_yaml() {
load_test_case("sanity-check_small-config_32-vals.yaml");
load_test_case("sanity-check_default-config_100-vals.yaml");
}
#[test]
#[cfg(not(debug_assertions))]
fn run_state_transition_tests_small() {
run_state_transition_test("sanity-check_small-config_32-vals.yaml");
}
// Run with --ignored to run this test
#[test]
#[ignore]
fn run_state_transition_tests_large() {
run_state_transition_test("sanity-check_default-config_100-vals.yaml");
} }

View File

@ -0,0 +1,14 @@
[package]
name = "yaml-utils"
version = "0.1.0"
authors = ["Kirk Baird <baird.k@outlook.com>"]
edition = "2018"
[build-dependencies]
reqwest = "0.9"
[dependencies]
[lib]
name = "yaml_utils"
path = "src/lib.rs"

View File

@ -0,0 +1,27 @@
extern crate reqwest;
use std::fs::File;
use std::io::copy;
fn main() {
// These test files are not to be stored in the lighthouse repo as they are quite large (32MB).
// They will be downloaded at build time by yaml-utils crate (in build.rs)
let git_path = "https://raw.githubusercontent.com/ethereum/eth2.0-tests/master/state/";
let test_names = vec![
"sanity-check_default-config_100-vals.yaml",
"sanity-check_small-config_32-vals.yaml",
];
for test in test_names {
let mut target = String::from(git_path);
target.push_str(test);
let mut response = reqwest::get(target.as_str()).unwrap();
let mut dest = {
let mut file_name = String::from("specs/");
file_name.push_str(test);
File::create(file_name).unwrap()
};
copy(&mut response, &mut dest).unwrap();
}
}

View File

@ -0,0 +1,15 @@
#!/usr/bin/env python3
# Script to extract all the fields of the state mentioned in `expected_state` fields of tests
# in the `spec` directory. These fields can then be added to the `ExpectedState` struct.
# Might take a while to run.
import os, yaml
if __name__ == "__main__":
yaml_files = (filename for filename in os.listdir("specs") if filename.endswith(".yaml"))
parsed_yaml = (yaml.load(open("specs/" + filename, "r")) for filename in yaml_files)
all_fields = set()
for y in parsed_yaml:
all_fields.update(*({key for key in case["expected_state"]} for case in y["test_cases"]))
print(all_fields)

View File

@ -0,0 +1 @@
*.yaml

View File

@ -0,0 +1 @@
// This is a place holder such that yaml-utils is now a crate hence build.rs will be run when 'cargo test' is called

View File

@ -7,6 +7,7 @@ edition = "2018"
[dependencies] [dependencies]
bls = { path = "../utils/bls" } bls = { path = "../utils/bls" }
boolean-bitfield = { path = "../utils/boolean-bitfield" } boolean-bitfield = { path = "../utils/boolean-bitfield" }
cached_tree_hash = { path = "../utils/cached_tree_hash" }
dirs = "1.0" dirs = "1.0"
derivative = "1.0" derivative = "1.0"
ethereum-types = "0.5" ethereum-types = "0.5"
@ -26,6 +27,8 @@ ssz = { path = "../utils/ssz" }
ssz_derive = { path = "../utils/ssz_derive" } ssz_derive = { path = "../utils/ssz_derive" }
swap_or_not_shuffle = { path = "../utils/swap_or_not_shuffle" } swap_or_not_shuffle = { path = "../utils/swap_or_not_shuffle" }
test_random_derive = { path = "../utils/test_random_derive" } test_random_derive = { path = "../utils/test_random_derive" }
tree_hash = { path = "../utils/tree_hash" }
tree_hash_derive = { path = "../utils/tree_hash_derive" }
libp2p = { git = "https://github.com/SigP/rust-libp2p", rev = "b3c32d9a821ae6cc89079499cc6e8a6bab0bffc3" } libp2p = { git = "https://github.com/SigP/rust-libp2p", rev = "b3c32d9a821ae6cc89079499cc6e8a6bab0bffc3" }
[dev-dependencies] [dev-dependencies]

View File

@ -2,13 +2,14 @@ use super::{AggregateSignature, AttestationData, Bitfield};
use crate::test_utils::TestRandom; use crate::test_utils::TestRandom;
use rand::RngCore; use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz::TreeHash; use ssz_derive::{Decode, Encode};
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash::TreeHash;
use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// Details an attestation that can be slashable. /// Details an attestation that can be slashable.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive( #[derive(
Debug, Debug,
Clone, Clone,
@ -18,6 +19,7 @@ use test_random_derive::TestRandom;
Encode, Encode,
Decode, Decode,
TreeHash, TreeHash,
CachedTreeHash,
TestRandom, TestRandom,
SignedRoot, SignedRoot,
)] )]
@ -25,6 +27,7 @@ pub struct Attestation {
pub aggregation_bitfield: Bitfield, pub aggregation_bitfield: Bitfield,
pub data: AttestationData, pub data: AttestationData,
pub custody_bitfield: Bitfield, pub custody_bitfield: Bitfield,
#[signed_root(skip_hashing)]
pub aggregate_signature: AggregateSignature, pub aggregate_signature: AggregateSignature,
} }
@ -56,4 +59,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(Attestation); ssz_tests!(Attestation);
cached_tree_hash_tests!(Attestation);
} }

View File

@ -2,13 +2,14 @@ use crate::test_utils::TestRandom;
use crate::{Crosslink, Epoch, Hash256, Slot}; use crate::{Crosslink, Epoch, Hash256, Slot};
use rand::RngCore; use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz::TreeHash; use ssz_derive::{Decode, Encode};
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash::TreeHash;
use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// The data upon which an attestation is based. /// The data upon which an attestation is based.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive( #[derive(
Debug, Debug,
Clone, Clone,
@ -20,6 +21,7 @@ use test_random_derive::TestRandom;
Encode, Encode,
Decode, Decode,
TreeHash, TreeHash,
CachedTreeHash,
TestRandom, TestRandom,
SignedRoot, SignedRoot,
)] )]
@ -46,4 +48,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(AttestationData); ssz_tests!(AttestationData);
cached_tree_hash_tests!(AttestationData);
} }

View File

@ -2,12 +2,13 @@ use super::AttestationData;
use crate::test_utils::TestRandom; use crate::test_utils::TestRandom;
use rand::RngCore; use rand::RngCore;
use serde_derive::Serialize; use serde_derive::Serialize;
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode};
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Used for pairing an attestation with a proof-of-custody. /// Used for pairing an attestation with a proof-of-custody.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive(Debug, Clone, PartialEq, Default, Serialize, Encode, Decode, TreeHash)] #[derive(Debug, Clone, PartialEq, Default, Serialize, Encode, Decode, TreeHash, CachedTreeHash)]
pub struct AttestationDataAndCustodyBit { pub struct AttestationDataAndCustodyBit {
pub data: AttestationData, pub data: AttestationData,
pub custody_bit: bool, pub custody_bit: bool,
@ -27,4 +28,5 @@ mod test {
use super::*; use super::*;
ssz_tests!(AttestationDataAndCustodyBit); ssz_tests!(AttestationDataAndCustodyBit);
cached_tree_hash_tests!(AttestationDataAndCustodyBit);
} }

View File

@ -1,13 +1,25 @@
use crate::{test_utils::TestRandom, SlashableAttestation}; use crate::{test_utils::TestRandom, SlashableAttestation};
use rand::RngCore; use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Two conflicting attestations. /// Two conflicting attestations.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] #[derive(
Debug,
PartialEq,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct AttesterSlashing { pub struct AttesterSlashing {
pub slashable_attestation_1: SlashableAttestation, pub slashable_attestation_1: SlashableAttestation,
pub slashable_attestation_2: SlashableAttestation, pub slashable_attestation_2: SlashableAttestation,
@ -18,4 +30,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(AttesterSlashing); ssz_tests!(AttesterSlashing);
cached_tree_hash_tests!(AttesterSlashing);
} }

View File

@ -3,13 +3,14 @@ use crate::*;
use bls::Signature; use bls::Signature;
use rand::RngCore; use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz::TreeHash; use ssz_derive::{Decode, Encode};
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash::TreeHash;
use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// A block of the `BeaconChain`. /// A block of the `BeaconChain`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive( #[derive(
Debug, Debug,
PartialEq, PartialEq,
@ -19,6 +20,7 @@ use test_random_derive::TestRandom;
Encode, Encode,
Decode, Decode,
TreeHash, TreeHash,
CachedTreeHash,
TestRandom, TestRandom,
SignedRoot, SignedRoot,
)] )]
@ -27,13 +29,14 @@ pub struct BeaconBlock {
pub previous_block_root: Hash256, pub previous_block_root: Hash256,
pub state_root: Hash256, pub state_root: Hash256,
pub body: BeaconBlockBody, pub body: BeaconBlockBody,
#[signed_root(skip_hashing)]
pub signature: Signature, pub signature: Signature,
} }
impl BeaconBlock { impl BeaconBlock {
/// Returns an empty block to be used during genesis. /// Returns an empty block to be used during genesis.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn empty(spec: &ChainSpec) -> BeaconBlock { pub fn empty(spec: &ChainSpec) -> BeaconBlock {
BeaconBlock { BeaconBlock {
slot: spec.genesis_slot, slot: spec.genesis_slot,
@ -56,11 +59,11 @@ impl BeaconBlock {
} }
} }
/// Returns the `hash_tree_root` of the block. /// Returns the `tree_hash_root | update` of the block.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn canonical_root(&self) -> Hash256 { pub fn canonical_root(&self) -> Hash256 {
Hash256::from_slice(&self.hash_tree_root()[..]) Hash256::from_slice(&self.tree_hash_root()[..])
} }
/// Returns a full `BeaconBlockHeader` of this block. /// Returns a full `BeaconBlockHeader` of this block.
@ -70,20 +73,20 @@ impl BeaconBlock {
/// ///
/// Note: performs a full tree-hash of `self.body`. /// Note: performs a full tree-hash of `self.body`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn block_header(&self) -> BeaconBlockHeader { pub fn block_header(&self) -> BeaconBlockHeader {
BeaconBlockHeader { BeaconBlockHeader {
slot: self.slot, slot: self.slot,
previous_block_root: self.previous_block_root, previous_block_root: self.previous_block_root,
state_root: self.state_root, state_root: self.state_root,
block_body_root: Hash256::from_slice(&self.body.hash_tree_root()[..]), block_body_root: Hash256::from_slice(&self.body.tree_hash_root()[..]),
signature: self.signature.clone(), signature: self.signature.clone(),
} }
} }
/// Returns a "temporary" header, where the `state_root` is `spec.zero_hash`. /// Returns a "temporary" header, where the `state_root` is `spec.zero_hash`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn temporary_block_header(&self, spec: &ChainSpec) -> BeaconBlockHeader { pub fn temporary_block_header(&self, spec: &ChainSpec) -> BeaconBlockHeader {
BeaconBlockHeader { BeaconBlockHeader {
state_root: spec.zero_hash, state_root: spec.zero_hash,
@ -98,4 +101,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(BeaconBlock); ssz_tests!(BeaconBlock);
cached_tree_hash_tests!(BeaconBlock);
} }

View File

@ -2,13 +2,25 @@ use crate::test_utils::TestRandom;
use crate::*; use crate::*;
use rand::RngCore; use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// The body of a `BeaconChain` block, containing operations. /// The body of a `BeaconChain` block, containing operations.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] #[derive(
Debug,
PartialEq,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct BeaconBlockBody { pub struct BeaconBlockBody {
pub randao_reveal: Signature, pub randao_reveal: Signature,
pub eth1_data: Eth1Data, pub eth1_data: Eth1Data,
@ -25,4 +37,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(BeaconBlockBody); ssz_tests!(BeaconBlockBody);
cached_tree_hash_tests!(BeaconBlockBody);
} }

View File

@ -3,13 +3,14 @@ use crate::*;
use bls::Signature; use bls::Signature;
use rand::RngCore; use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz::TreeHash; use ssz_derive::{Decode, Encode};
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash::{SignedRoot, TreeHash};
use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// A header of a `BeaconBlock`. /// A header of a `BeaconBlock`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive( #[derive(
Debug, Debug,
PartialEq, PartialEq,
@ -19,6 +20,7 @@ use test_random_derive::TestRandom;
Encode, Encode,
Decode, Decode,
TreeHash, TreeHash,
CachedTreeHash,
TestRandom, TestRandom,
SignedRoot, SignedRoot,
)] )]
@ -27,20 +29,21 @@ pub struct BeaconBlockHeader {
pub previous_block_root: Hash256, pub previous_block_root: Hash256,
pub state_root: Hash256, pub state_root: Hash256,
pub block_body_root: Hash256, pub block_body_root: Hash256,
#[signed_root(skip_hashing)]
pub signature: Signature, pub signature: Signature,
} }
impl BeaconBlockHeader { impl BeaconBlockHeader {
/// Returns the `hash_tree_root` of the header. /// Returns the `tree_hash_root` of the header.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn canonical_root(&self) -> Hash256 { pub fn canonical_root(&self) -> Hash256 {
Hash256::from_slice(&self.hash_tree_root()[..]) Hash256::from_slice(&self.signed_root()[..])
} }
/// Given a `body`, consumes `self` and returns a complete `BeaconBlock`. /// Given a `body`, consumes `self` and returns a complete `BeaconBlock`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn into_block(self, body: BeaconBlockBody) -> BeaconBlock { pub fn into_block(self, body: BeaconBlockBody) -> BeaconBlock {
BeaconBlock { BeaconBlock {
slot: self.slot, slot: self.slot,
@ -57,4 +60,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(BeaconBlockHeader); ssz_tests!(BeaconBlockHeader);
cached_tree_hash_tests!(BeaconBlockHeader);
} }

View File

@ -1,13 +1,16 @@
use self::epoch_cache::{get_active_validator_indices, EpochCache, Error as EpochCacheError}; use self::epoch_cache::{get_active_validator_indices, EpochCache, Error as EpochCacheError};
use crate::test_utils::TestRandom; use crate::test_utils::TestRandom;
use crate::*; use crate::*;
use cached_tree_hash::{Error as TreeHashCacheError, TreeHashCache};
use int_to_bytes::int_to_bytes32; use int_to_bytes::int_to_bytes32;
use pubkey_cache::PubkeyCache; use pubkey_cache::PubkeyCache;
use rand::RngCore; use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz::{hash, ssz_encode, TreeHash}; use ssz::{hash, ssz_encode};
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash::TreeHash;
use tree_hash_derive::{CachedTreeHash, TreeHash};
mod epoch_cache; mod epoch_cache;
mod pubkey_cache; mod pubkey_cache;
@ -40,12 +43,24 @@ pub enum Error {
EpochCacheUninitialized(RelativeEpoch), EpochCacheUninitialized(RelativeEpoch),
RelativeEpochError(RelativeEpochError), RelativeEpochError(RelativeEpochError),
EpochCacheError(EpochCacheError), EpochCacheError(EpochCacheError),
TreeHashCacheError(TreeHashCacheError),
} }
/// The state of the `BeaconChain` at some slot. /// The state of the `BeaconChain` at some slot.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, TestRandom, Encode, Decode, TreeHash)] #[derive(
Debug,
PartialEq,
Clone,
Serialize,
Deserialize,
TestRandom,
Encode,
Decode,
TreeHash,
CachedTreeHash,
)]
pub struct BeaconState { pub struct BeaconState {
// Misc // Misc
pub slot: Slot, pub slot: Slot,
@ -58,7 +73,7 @@ pub struct BeaconState {
pub validator_registry_update_epoch: Epoch, pub validator_registry_update_epoch: Epoch,
// Randomness and committees // Randomness and committees
pub latest_randao_mixes: Vec<Hash256>, pub latest_randao_mixes: TreeHashVector<Hash256>,
pub previous_shuffling_start_shard: u64, pub previous_shuffling_start_shard: u64,
pub current_shuffling_start_shard: u64, pub current_shuffling_start_shard: u64,
pub previous_shuffling_epoch: Epoch, pub previous_shuffling_epoch: Epoch,
@ -78,11 +93,11 @@ pub struct BeaconState {
pub finalized_root: Hash256, pub finalized_root: Hash256,
// Recent state // Recent state
pub latest_crosslinks: Vec<Crosslink>, pub latest_crosslinks: TreeHashVector<Crosslink>,
latest_block_roots: Vec<Hash256>, pub latest_block_roots: TreeHashVector<Hash256>,
latest_state_roots: Vec<Hash256>, latest_state_roots: TreeHashVector<Hash256>,
latest_active_index_roots: Vec<Hash256>, latest_active_index_roots: TreeHashVector<Hash256>,
latest_slashed_balances: Vec<u64>, latest_slashed_balances: TreeHashVector<u64>,
pub latest_block_header: BeaconBlockHeader, pub latest_block_header: BeaconBlockHeader,
pub historical_roots: Vec<Hash256>, pub historical_roots: Vec<Hash256>,
@ -110,6 +125,12 @@ pub struct BeaconState {
#[tree_hash(skip_hashing)] #[tree_hash(skip_hashing)]
#[test_random(default)] #[test_random(default)]
pub pubkey_cache: PubkeyCache, pub pubkey_cache: PubkeyCache,
#[serde(skip_serializing, skip_deserializing)]
#[ssz(skip_serializing)]
#[ssz(skip_deserializing)]
#[tree_hash(skip_hashing)]
#[test_random(default)]
pub tree_hash_cache: TreeHashCache,
} }
impl BeaconState { impl BeaconState {
@ -118,7 +139,7 @@ impl BeaconState {
/// This does not fully build a genesis beacon state, it omits processing of initial validator /// This does not fully build a genesis beacon state, it omits processing of initial validator
/// deposits. To obtain a full genesis beacon state, use the `BeaconStateBuilder`. /// deposits. To obtain a full genesis beacon state, use the `BeaconStateBuilder`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn genesis(genesis_time: u64, latest_eth1_data: Eth1Data, spec: &ChainSpec) -> BeaconState { pub fn genesis(genesis_time: u64, latest_eth1_data: Eth1Data, spec: &ChainSpec) -> BeaconState {
let initial_crosslink = Crosslink { let initial_crosslink = Crosslink {
epoch: spec.genesis_epoch, epoch: spec.genesis_epoch,
@ -137,7 +158,8 @@ impl BeaconState {
validator_registry_update_epoch: spec.genesis_epoch, validator_registry_update_epoch: spec.genesis_epoch,
// Randomness and committees // Randomness and committees
latest_randao_mixes: vec![spec.zero_hash; spec.latest_randao_mixes_length as usize], latest_randao_mixes: vec![spec.zero_hash; spec.latest_randao_mixes_length as usize]
.into(),
previous_shuffling_start_shard: spec.genesis_start_shard, previous_shuffling_start_shard: spec.genesis_start_shard,
current_shuffling_start_shard: spec.genesis_start_shard, current_shuffling_start_shard: spec.genesis_start_shard,
previous_shuffling_epoch: spec.genesis_epoch, previous_shuffling_epoch: spec.genesis_epoch,
@ -157,11 +179,12 @@ impl BeaconState {
finalized_root: spec.zero_hash, finalized_root: spec.zero_hash,
// Recent state // Recent state
latest_crosslinks: vec![initial_crosslink; spec.shard_count as usize], latest_crosslinks: vec![initial_crosslink; spec.shard_count as usize].into(),
latest_block_roots: vec![spec.zero_hash; spec.slots_per_historical_root], latest_block_roots: vec![spec.zero_hash; spec.slots_per_historical_root].into(),
latest_state_roots: vec![spec.zero_hash; spec.slots_per_historical_root], latest_state_roots: vec![spec.zero_hash; spec.slots_per_historical_root].into(),
latest_active_index_roots: vec![spec.zero_hash; spec.latest_active_index_roots_length], latest_active_index_roots: vec![spec.zero_hash; spec.latest_active_index_roots_length]
latest_slashed_balances: vec![0; spec.latest_slashed_exit_length], .into(),
latest_slashed_balances: vec![0; spec.latest_slashed_exit_length].into(),
latest_block_header: BeaconBlock::empty(spec).temporary_block_header(spec), latest_block_header: BeaconBlock::empty(spec).temporary_block_header(spec),
historical_roots: vec![], historical_roots: vec![],
@ -183,14 +206,15 @@ impl BeaconState {
EpochCache::default(), EpochCache::default(),
], ],
pubkey_cache: PubkeyCache::default(), pubkey_cache: PubkeyCache::default(),
tree_hash_cache: TreeHashCache::default(),
} }
} }
/// Returns the `hash_tree_root` of the state. /// Returns the `tree_hash_root` of the state.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn canonical_root(&self) -> Hash256 { pub fn canonical_root(&self) -> Hash256 {
Hash256::from_slice(&self.hash_tree_root()[..]) Hash256::from_slice(&self.tree_hash_root()[..])
} }
pub fn historical_batch(&self) -> HistoricalBatch { pub fn historical_batch(&self) -> HistoricalBatch {
@ -217,7 +241,7 @@ impl BeaconState {
/// The epoch corresponding to `self.slot`. /// The epoch corresponding to `self.slot`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn current_epoch(&self, spec: &ChainSpec) -> Epoch { pub fn current_epoch(&self, spec: &ChainSpec) -> Epoch {
self.slot.epoch(spec.slots_per_epoch) self.slot.epoch(spec.slots_per_epoch)
} }
@ -226,14 +250,14 @@ impl BeaconState {
/// ///
/// If the current epoch is the genesis epoch, the genesis_epoch is returned. /// If the current epoch is the genesis epoch, the genesis_epoch is returned.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn previous_epoch(&self, spec: &ChainSpec) -> Epoch { pub fn previous_epoch(&self, spec: &ChainSpec) -> Epoch {
self.current_epoch(&spec) - 1 self.current_epoch(&spec) - 1
} }
/// The epoch following `self.current_epoch()`. /// The epoch following `self.current_epoch()`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn next_epoch(&self, spec: &ChainSpec) -> Epoch { pub fn next_epoch(&self, spec: &ChainSpec) -> Epoch {
self.current_epoch(spec) + 1 self.current_epoch(spec) + 1
} }
@ -246,7 +270,7 @@ impl BeaconState {
/// ///
/// Note: Utilizes the cache and will fail if the appropriate cache is not initialized. /// Note: Utilizes the cache and will fail if the appropriate cache is not initialized.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn get_cached_active_validator_indices( pub fn get_cached_active_validator_indices(
&self, &self,
relative_epoch: RelativeEpoch, relative_epoch: RelativeEpoch,
@ -261,7 +285,7 @@ impl BeaconState {
/// ///
/// Does not utilize the cache, performs a full iteration over the validator registry. /// Does not utilize the cache, performs a full iteration over the validator registry.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn get_active_validator_indices(&self, epoch: Epoch) -> Vec<usize> { pub fn get_active_validator_indices(&self, epoch: Epoch) -> Vec<usize> {
get_active_validator_indices(&self.validator_registry, epoch) get_active_validator_indices(&self.validator_registry, epoch)
} }
@ -270,7 +294,7 @@ impl BeaconState {
/// ///
/// Note: Utilizes the cache and will fail if the appropriate cache is not initialized. /// Note: Utilizes the cache and will fail if the appropriate cache is not initialized.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn get_crosslink_committees_at_slot( pub fn get_crosslink_committees_at_slot(
&self, &self,
slot: Slot, slot: Slot,
@ -295,7 +319,7 @@ impl BeaconState {
/// ///
/// Note: Utilizes the cache and will fail if the appropriate cache is not initialized. /// Note: Utilizes the cache and will fail if the appropriate cache is not initialized.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn get_crosslink_committee_for_shard( pub fn get_crosslink_committee_for_shard(
&self, &self,
epoch: Epoch, epoch: Epoch,
@ -321,7 +345,7 @@ impl BeaconState {
/// ///
/// If the state does not contain an index for a beacon proposer at the requested `slot`, then `None` is returned. /// If the state does not contain an index for a beacon proposer at the requested `slot`, then `None` is returned.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn get_beacon_proposer_index( pub fn get_beacon_proposer_index(
&self, &self,
slot: Slot, slot: Slot,
@ -350,7 +374,7 @@ impl BeaconState {
/// Safely obtains the index for latest block roots, given some `slot`. /// Safely obtains the index for latest block roots, given some `slot`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn get_latest_block_roots_index(&self, slot: Slot, spec: &ChainSpec) -> Result<usize, Error> { fn get_latest_block_roots_index(&self, slot: Slot, spec: &ChainSpec) -> Result<usize, Error> {
if (slot < self.slot) && (self.slot <= slot + spec.slots_per_historical_root as u64) { if (slot < self.slot) && (self.slot <= slot + spec.slots_per_historical_root as u64) {
let i = slot.as_usize() % spec.slots_per_historical_root; let i = slot.as_usize() % spec.slots_per_historical_root;
@ -366,7 +390,7 @@ impl BeaconState {
/// Return the block root at a recent `slot`. /// Return the block root at a recent `slot`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn get_block_root( pub fn get_block_root(
&self, &self,
slot: Slot, slot: Slot,
@ -378,7 +402,7 @@ impl BeaconState {
/// Sets the block root for some given slot. /// Sets the block root for some given slot.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn set_block_root( pub fn set_block_root(
&mut self, &mut self,
slot: Slot, slot: Slot,
@ -392,7 +416,7 @@ impl BeaconState {
/// Safely obtains the index for `latest_randao_mixes` /// Safely obtains the index for `latest_randao_mixes`
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn get_randao_mix_index(&self, epoch: Epoch, spec: &ChainSpec) -> Result<usize, Error> { fn get_randao_mix_index(&self, epoch: Epoch, spec: &ChainSpec) -> Result<usize, Error> {
let current_epoch = self.current_epoch(spec); let current_epoch = self.current_epoch(spec);
@ -416,7 +440,7 @@ impl BeaconState {
/// ///
/// See `Self::get_randao_mix`. /// See `Self::get_randao_mix`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn update_randao_mix( pub fn update_randao_mix(
&mut self, &mut self,
epoch: Epoch, epoch: Epoch,
@ -434,7 +458,7 @@ impl BeaconState {
/// Return the randao mix at a recent ``epoch``. /// Return the randao mix at a recent ``epoch``.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn get_randao_mix(&self, epoch: Epoch, spec: &ChainSpec) -> Result<&Hash256, Error> { pub fn get_randao_mix(&self, epoch: Epoch, spec: &ChainSpec) -> Result<&Hash256, Error> {
let i = self.get_randao_mix_index(epoch, spec)?; let i = self.get_randao_mix_index(epoch, spec)?;
Ok(&self.latest_randao_mixes[i]) Ok(&self.latest_randao_mixes[i])
@ -442,7 +466,7 @@ impl BeaconState {
/// Set the randao mix at a recent ``epoch``. /// Set the randao mix at a recent ``epoch``.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn set_randao_mix( pub fn set_randao_mix(
&mut self, &mut self,
epoch: Epoch, epoch: Epoch,
@ -456,7 +480,7 @@ impl BeaconState {
/// Safely obtains the index for `latest_active_index_roots`, given some `epoch`. /// Safely obtains the index for `latest_active_index_roots`, given some `epoch`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn get_active_index_root_index(&self, epoch: Epoch, spec: &ChainSpec) -> Result<usize, Error> { fn get_active_index_root_index(&self, epoch: Epoch, spec: &ChainSpec) -> Result<usize, Error> {
let current_epoch = self.current_epoch(spec); let current_epoch = self.current_epoch(spec);
@ -478,7 +502,7 @@ impl BeaconState {
/// Return the `active_index_root` at a recent `epoch`. /// Return the `active_index_root` at a recent `epoch`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn get_active_index_root(&self, epoch: Epoch, spec: &ChainSpec) -> Result<Hash256, Error> { pub fn get_active_index_root(&self, epoch: Epoch, spec: &ChainSpec) -> Result<Hash256, Error> {
let i = self.get_active_index_root_index(epoch, spec)?; let i = self.get_active_index_root_index(epoch, spec)?;
Ok(self.latest_active_index_roots[i]) Ok(self.latest_active_index_roots[i])
@ -486,7 +510,7 @@ impl BeaconState {
/// Set the `active_index_root` at a recent `epoch`. /// Set the `active_index_root` at a recent `epoch`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn set_active_index_root( pub fn set_active_index_root(
&mut self, &mut self,
epoch: Epoch, epoch: Epoch,
@ -500,15 +524,15 @@ impl BeaconState {
/// Replace `active_index_roots` with clones of `index_root`. /// Replace `active_index_roots` with clones of `index_root`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn fill_active_index_roots_with(&mut self, index_root: Hash256, spec: &ChainSpec) { pub fn fill_active_index_roots_with(&mut self, index_root: Hash256, spec: &ChainSpec) {
self.latest_active_index_roots = self.latest_active_index_roots =
vec![index_root; spec.latest_active_index_roots_length as usize] vec![index_root; spec.latest_active_index_roots_length as usize].into()
} }
/// Safely obtains the index for latest state roots, given some `slot`. /// Safely obtains the index for latest state roots, given some `slot`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn get_latest_state_roots_index(&self, slot: Slot, spec: &ChainSpec) -> Result<usize, Error> { fn get_latest_state_roots_index(&self, slot: Slot, spec: &ChainSpec) -> Result<usize, Error> {
if (slot < self.slot) && (self.slot <= slot + spec.slots_per_historical_root as u64) { if (slot < self.slot) && (self.slot <= slot + spec.slots_per_historical_root as u64) {
let i = slot.as_usize() % spec.slots_per_historical_root; let i = slot.as_usize() % spec.slots_per_historical_root;
@ -524,7 +548,7 @@ impl BeaconState {
/// Gets the state root for some slot. /// Gets the state root for some slot.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn get_state_root(&mut self, slot: Slot, spec: &ChainSpec) -> Result<&Hash256, Error> { pub fn get_state_root(&mut self, slot: Slot, spec: &ChainSpec) -> Result<&Hash256, Error> {
let i = self.get_latest_state_roots_index(slot, spec)?; let i = self.get_latest_state_roots_index(slot, spec)?;
Ok(&self.latest_state_roots[i]) Ok(&self.latest_state_roots[i])
@ -532,7 +556,7 @@ impl BeaconState {
/// Sets the latest state root for slot. /// Sets the latest state root for slot.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn set_state_root( pub fn set_state_root(
&mut self, &mut self,
slot: Slot, slot: Slot,
@ -546,7 +570,7 @@ impl BeaconState {
/// Safely obtains the index for `latest_slashed_balances`, given some `epoch`. /// Safely obtains the index for `latest_slashed_balances`, given some `epoch`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
fn get_slashed_balance_index(&self, epoch: Epoch, spec: &ChainSpec) -> Result<usize, Error> { fn get_slashed_balance_index(&self, epoch: Epoch, spec: &ChainSpec) -> Result<usize, Error> {
let i = epoch.as_usize() % spec.latest_slashed_exit_length; let i = epoch.as_usize() % spec.latest_slashed_exit_length;
@ -561,7 +585,7 @@ impl BeaconState {
/// Gets the total slashed balances for some epoch. /// Gets the total slashed balances for some epoch.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn get_slashed_balance(&self, epoch: Epoch, spec: &ChainSpec) -> Result<u64, Error> { pub fn get_slashed_balance(&self, epoch: Epoch, spec: &ChainSpec) -> Result<u64, Error> {
let i = self.get_slashed_balance_index(epoch, spec)?; let i = self.get_slashed_balance_index(epoch, spec)?;
Ok(self.latest_slashed_balances[i]) Ok(self.latest_slashed_balances[i])
@ -569,7 +593,7 @@ impl BeaconState {
/// Sets the total slashed balances for some epoch. /// Sets the total slashed balances for some epoch.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn set_slashed_balance( pub fn set_slashed_balance(
&mut self, &mut self,
epoch: Epoch, epoch: Epoch,
@ -583,7 +607,7 @@ impl BeaconState {
/// Generate a seed for the given `epoch`. /// Generate a seed for the given `epoch`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn generate_seed(&self, epoch: Epoch, spec: &ChainSpec) -> Result<Hash256, Error> { pub fn generate_seed(&self, epoch: Epoch, spec: &ChainSpec) -> Result<Hash256, Error> {
let mut input = self let mut input = self
.get_randao_mix(epoch - spec.min_seed_lookahead, spec)? .get_randao_mix(epoch - spec.min_seed_lookahead, spec)?
@ -599,7 +623,7 @@ impl BeaconState {
/// Return the effective balance (also known as "balance at stake") for a validator with the given ``index``. /// Return the effective balance (also known as "balance at stake") for a validator with the given ``index``.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn get_effective_balance( pub fn get_effective_balance(
&self, &self,
validator_index: usize, validator_index: usize,
@ -614,14 +638,14 @@ impl BeaconState {
/// Return the epoch at which an activation or exit triggered in ``epoch`` takes effect. /// Return the epoch at which an activation or exit triggered in ``epoch`` takes effect.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn get_delayed_activation_exit_epoch(&self, epoch: Epoch, spec: &ChainSpec) -> Epoch { pub fn get_delayed_activation_exit_epoch(&self, epoch: Epoch, spec: &ChainSpec) -> Epoch {
epoch + 1 + spec.activation_exit_delay epoch + 1 + spec.activation_exit_delay
} }
/// Initiate an exit for the validator of the given `index`. /// Initiate an exit for the validator of the given `index`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn initiate_validator_exit(&mut self, validator_index: usize) { pub fn initiate_validator_exit(&mut self, validator_index: usize) {
self.validator_registry[validator_index].initiated_exit = true; self.validator_registry[validator_index].initiated_exit = true;
} }
@ -633,7 +657,7 @@ impl BeaconState {
/// ///
/// Note: Utilizes the cache and will fail if the appropriate cache is not initialized. /// Note: Utilizes the cache and will fail if the appropriate cache is not initialized.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn get_attestation_duties( pub fn get_attestation_duties(
&self, &self,
validator_index: usize, validator_index: usize,
@ -649,7 +673,7 @@ impl BeaconState {
/// Return the combined effective balance of an array of validators. /// Return the combined effective balance of an array of validators.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn get_total_balance( pub fn get_total_balance(
&self, &self,
validator_indices: &[usize], validator_indices: &[usize],
@ -668,6 +692,7 @@ impl BeaconState {
self.build_epoch_cache(RelativeEpoch::NextWithoutRegistryChange, spec)?; self.build_epoch_cache(RelativeEpoch::NextWithoutRegistryChange, spec)?;
self.build_epoch_cache(RelativeEpoch::NextWithRegistryChange, spec)?; self.build_epoch_cache(RelativeEpoch::NextWithRegistryChange, spec)?;
self.update_pubkey_cache()?; self.update_pubkey_cache()?;
self.update_tree_hash_cache()?;
Ok(()) Ok(())
} }
@ -774,6 +799,39 @@ impl BeaconState {
pub fn drop_pubkey_cache(&mut self) { pub fn drop_pubkey_cache(&mut self) {
self.pubkey_cache = PubkeyCache::default() self.pubkey_cache = PubkeyCache::default()
} }
/// Update the tree hash cache, building it for the first time if it is empty.
///
/// Returns the `tree_hash_root` resulting from the update. This root can be considered the
/// canonical root of `self`.
pub fn update_tree_hash_cache(&mut self) -> Result<Hash256, Error> {
if self.tree_hash_cache.is_empty() {
self.tree_hash_cache = TreeHashCache::new(self)?;
} else {
// Move the cache outside of `self` to satisfy the borrow checker.
let mut cache = std::mem::replace(&mut self.tree_hash_cache, TreeHashCache::default());
cache.update(self)?;
// Move the updated cache back into `self`.
self.tree_hash_cache = cache
}
self.cached_tree_hash_root()
}
/// Returns the tree hash root determined by the last execution of `self.update_tree_hash_cache(..)`.
///
/// Note: does _not_ update the cache and may return an outdated root.
///
/// Returns an error if the cache is not initialized or if an error is encountered during the
/// cache update.
pub fn cached_tree_hash_root(&self) -> Result<Hash256, Error> {
self.tree_hash_cache
.tree_hash_root()
.and_then(|b| Ok(Hash256::from_slice(b)))
.map_err(|e| e.into())
}
} }
impl From<RelativeEpochError> for Error { impl From<RelativeEpochError> for Error {
@ -787,3 +845,9 @@ impl From<EpochCacheError> for Error {
Error::EpochCacheError(e) Error::EpochCacheError(e)
} }
} }
impl From<TreeHashCacheError> for Error {
fn from(e: TreeHashCacheError) -> Error {
Error::TreeHashCacheError(e)
}
}

View File

@ -138,7 +138,7 @@ impl EpochCache {
/// Returns a list of all `validator_registry` indices where the validator is active at the given /// Returns a list of all `validator_registry` indices where the validator is active at the given
/// `epoch`. /// `epoch`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn get_active_validator_indices(validators: &[Validator], epoch: Epoch) -> Vec<usize> { pub fn get_active_validator_indices(validators: &[Validator], epoch: Epoch) -> Vec<usize> {
let mut active = Vec::with_capacity(validators.len()); let mut active = Vec::with_capacity(validators.len());
@ -288,7 +288,7 @@ impl EpochCrosslinkCommitteesBuilder {
self.active_validator_indices, self.active_validator_indices,
spec.shuffle_round_count, spec.shuffle_round_count,
&self.shuffling_seed[..], &self.shuffling_seed[..],
true, false,
) )
.ok_or_else(|| Error::UnableToShuffle)? .ok_or_else(|| Error::UnableToShuffle)?
}; };

View File

@ -27,7 +27,7 @@ fn do_sane_cache_test(
active_indices, active_indices,
spec.shuffle_round_count, spec.shuffle_round_count,
&expected_seed[..], &expected_seed[..],
true, false,
) )
.unwrap(); .unwrap();

View File

@ -3,6 +3,7 @@ use super::*;
use crate::test_utils::*; use crate::test_utils::*;
ssz_tests!(BeaconState); ssz_tests!(BeaconState);
cached_tree_hash_tests!(BeaconState);
/// Test that /// Test that
/// ///
@ -55,3 +56,22 @@ fn cache_initialization() {
test_cache_initialization(&mut state, RelativeEpoch::NextWithRegistryChange, &spec); test_cache_initialization(&mut state, RelativeEpoch::NextWithRegistryChange, &spec);
test_cache_initialization(&mut state, RelativeEpoch::NextWithoutRegistryChange, &spec); test_cache_initialization(&mut state, RelativeEpoch::NextWithoutRegistryChange, &spec);
} }
#[test]
fn tree_hash_cache() {
use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng};
use tree_hash::TreeHash;
let mut rng = XorShiftRng::from_seed([42; 16]);
let mut state = BeaconState::random_for_test(&mut rng);
let root = state.update_tree_hash_cache().unwrap();
assert_eq!(root.as_bytes(), &state.tree_hash_root()[..]);
state.slot = state.slot + 1;
let root = state.update_tree_hash_cache().unwrap();
assert_eq!(root.as_bytes(), &state.tree_hash_root()[..]);
}

View File

@ -8,7 +8,7 @@ const GWEI: u64 = 1_000_000_000;
/// Each of the BLS signature domains. /// Each of the BLS signature domains.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub enum Domain { pub enum Domain {
BeaconBlock, BeaconBlock,
Randao, Randao,
@ -20,7 +20,7 @@ pub enum Domain {
/// Holds all the "constants" for a BeaconChain. /// Holds all the "constants" for a BeaconChain.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive(PartialEq, Debug, Clone, Deserialize)] #[derive(PartialEq, Debug, Clone, Deserialize)]
#[serde(default)] #[serde(default)]
pub struct ChainSpec { pub struct ChainSpec {
@ -126,7 +126,7 @@ pub struct ChainSpec {
impl ChainSpec { impl ChainSpec {
/// Return the number of committees in one epoch. /// Return the number of committees in one epoch.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn get_epoch_committee_count(&self, active_validator_count: usize) -> u64 { pub fn get_epoch_committee_count(&self, active_validator_count: usize) -> u64 {
std::cmp::max( std::cmp::max(
1, 1,
@ -139,7 +139,7 @@ impl ChainSpec {
/// Get the domain number that represents the fork meta and signature domain. /// Get the domain number that represents the fork meta and signature domain.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn get_domain(&self, epoch: Epoch, domain: Domain, fork: &Fork) -> u64 { pub fn get_domain(&self, epoch: Epoch, domain: Domain, fork: &Fork) -> u64 {
let domain_constant = match domain { let domain_constant = match domain {
Domain::BeaconBlock => self.domain_beacon_block, Domain::BeaconBlock => self.domain_beacon_block,
@ -161,7 +161,7 @@ impl ChainSpec {
/// Returns a `ChainSpec` compatible with the Ethereum Foundation specification. /// Returns a `ChainSpec` compatible with the Ethereum Foundation specification.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn foundation() -> Self { pub fn foundation() -> Self {
let genesis_slot = Slot::new(2_u64.pow(32)); let genesis_slot = Slot::new(2_u64.pow(32));
let slots_per_epoch = 64; let slots_per_epoch = 64;

View File

@ -2,12 +2,13 @@ use crate::test_utils::TestRandom;
use crate::{Epoch, Hash256}; use crate::{Epoch, Hash256};
use rand::RngCore; use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Specifies the block hash for a shard at an epoch. /// Specifies the block hash for a shard at an epoch.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive( #[derive(
Debug, Debug,
Clone, Clone,
@ -19,6 +20,7 @@ use test_random_derive::TestRandom;
Encode, Encode,
Decode, Decode,
TreeHash, TreeHash,
CachedTreeHash,
TestRandom, TestRandom,
)] )]
pub struct Crosslink { pub struct Crosslink {
@ -31,4 +33,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(Crosslink); ssz_tests!(Crosslink);
cached_tree_hash_tests!(Crosslink);
} }

View File

@ -1,8 +1,20 @@
use crate::*; use crate::*;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode};
use tree_hash_derive::{CachedTreeHash, TreeHash};
#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize, Decode, Encode, TreeHash)] #[derive(
Default,
Clone,
Debug,
PartialEq,
Serialize,
Deserialize,
Decode,
Encode,
TreeHash,
CachedTreeHash,
)]
pub struct CrosslinkCommittee { pub struct CrosslinkCommittee {
pub slot: Slot, pub slot: Slot,
pub shard: Shard, pub shard: Shard,

View File

@ -1,16 +1,28 @@
use super::{DepositData, Hash256}; use super::{DepositData, Hash256, TreeHashVector};
use crate::test_utils::TestRandom; use crate::test_utils::TestRandom;
use rand::RngCore; use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// A deposit to potentially become a beacon chain validator. /// A deposit to potentially become a beacon chain validator.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] #[derive(
Debug,
PartialEq,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct Deposit { pub struct Deposit {
pub proof: Vec<Hash256>, pub proof: TreeHashVector<Hash256>,
pub index: u64, pub index: u64,
pub deposit_data: DepositData, pub deposit_data: DepositData,
} }
@ -20,4 +32,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(Deposit); ssz_tests!(Deposit);
cached_tree_hash_tests!(Deposit);
} }

View File

@ -2,13 +2,25 @@ use super::DepositInput;
use crate::test_utils::TestRandom; use crate::test_utils::TestRandom;
use rand::RngCore; use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Data generated by the deposit contract. /// Data generated by the deposit contract.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] #[derive(
Debug,
PartialEq,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct DepositData { pub struct DepositData {
pub amount: u64, pub amount: u64,
pub timestamp: u64, pub timestamp: u64,
@ -20,4 +32,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(DepositData); ssz_tests!(DepositData);
cached_tree_hash_tests!(DepositData);
} }

View File

@ -3,13 +3,14 @@ use crate::*;
use bls::{PublicKey, Signature}; use bls::{PublicKey, Signature};
use rand::RngCore; use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz::{SignedRoot, TreeHash}; use ssz_derive::{Decode, Encode};
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash::{SignedRoot, TreeHash};
use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// The data supplied by the user to the deposit contract. /// The data supplied by the user to the deposit contract.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive( #[derive(
Debug, Debug,
PartialEq, PartialEq,
@ -20,18 +21,20 @@ use test_random_derive::TestRandom;
Decode, Decode,
SignedRoot, SignedRoot,
TreeHash, TreeHash,
CachedTreeHash,
TestRandom, TestRandom,
)] )]
pub struct DepositInput { pub struct DepositInput {
pub pubkey: PublicKey, pub pubkey: PublicKey,
pub withdrawal_credentials: Hash256, pub withdrawal_credentials: Hash256,
#[signed_root(skip_hashing)]
pub proof_of_possession: Signature, pub proof_of_possession: Signature,
} }
impl DepositInput { impl DepositInput {
/// Generate the 'proof_of_posession' signature for a given DepositInput details. /// Generate the 'proof_of_posession' signature for a given DepositInput details.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn create_proof_of_possession( pub fn create_proof_of_possession(
&self, &self,
secret_key: &SecretKey, secret_key: &SecretKey,
@ -47,7 +50,7 @@ impl DepositInput {
/// Verify that proof-of-possession is valid. /// Verify that proof-of-possession is valid.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn validate_proof_of_possession( pub fn validate_proof_of_possession(
&self, &self,
epoch: Epoch, epoch: Epoch,
@ -66,6 +69,7 @@ mod tests {
use super::*; use super::*;
ssz_tests!(DepositInput); ssz_tests!(DepositInput);
cached_tree_hash_tests!(DepositInput);
#[test] #[test]
fn can_create_and_validate() { fn can_create_and_validate() {

Some files were not shown because too many files have changed in this diff Show More