Merge branch 'master' into testnet-key-load

This commit is contained in:
Luke Anderson 2019-05-06 11:13:16 +10:00
commit 934cb5af5f
No known key found for this signature in database
GPG Key ID: 44408169EC61E228
144 changed files with 4850 additions and 1141 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,11 +11,13 @@ 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... # No clippy until later...
#- cargo clippy #- cargo clippy
@ -22,6 +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 - rustup component add clippy

View File

@ -9,6 +9,7 @@ members = [
"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",
@ -18,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",

5
Jenkinsfile vendored
View File

@ -23,6 +23,11 @@ pipeline {
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'
} }
} }
} }

474
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,
c) Accompany it with the information you received as to the offer defend, and hold each Contributor harmless for any liability
to distribute corresponding source code. (This alternative is incurred by, or claims asserted against, such Contributor by reason
allowed only for noncommercial distribution and only if you of your accepting any such warranty or additional liability.
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs APPENDIX: How to apply the Apache License to your work.
If you develop a new program, and you want it to be of the greatest To apply the Apache License to your work, attach the following
possible use to the public, the best way to achieve this is to make it boilerplate notice, with the fields enclosed by brackets "[]"
free software which everyone can redistribute and change under these terms. replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
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.
To do so, attach the following notices to the program. It is safest Copyright 2018 Sigma Prime Pty Ltd
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.> Licensed under the Apache License, Version 2.0 (the "License");
Copyright (C) <year> <name of author> you may not use this file except in compliance with the License.
You may obtain a copy of the License at
This program is free software; you can redistribute it and/or modify http://www.apache.org/licenses/LICENSE-2.0
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, Unless required by applicable law or agreed to in writing, software
but WITHOUT ANY WARRANTY; without even the implied warranty of distributed under the License is distributed on an "AS IS" BASIS,
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
GNU General Public License for more details. See the License for the specific language governing permissions and
limitations under the License.
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

@ -24,6 +24,7 @@ present-Ethereum functionality.
- [About Lighthouse](docs/lighthouse.md): Goals, Ideology and Ethos surrounding - [About Lighthouse](docs/lighthouse.md): Goals, Ideology and Ethos surrounding
this implementation. this implementation.
- [What is Ethereum Serenity](docs/serenity.md): an introduction to Ethereum Serenity. - [What is Ethereum Serenity](docs/serenity.md): an introduction to Ethereum Serenity.
- [Lighthouse Technical Documentation](http://lighthouse-docs.sigmaprime.io/): The Rust generated documentation, updated regularly.
If you'd like some background on Sigma Prime, please see the [Lighthouse Update If you'd like some background on Sigma Prime, please see the [Lighthouse Update
\#00](https://lighthouse.sigmaprime.io/update-00.html) blog post or the \#00](https://lighthouse.sigmaprime.io/update-00.html) blog post or the

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)?;
@ -617,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(
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,

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

@ -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

@ -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

@ -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,10 +5,10 @@ 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.
@ -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) {

14
docs/documentation.md Normal file
View File

@ -0,0 +1,14 @@
# Lighthouse Technical Documentation
The technical documentation, as generated by Rust, is available at [lighthouse-docs.sigmaprime.io](http://lighthouse-docs.sigmaprime.io/).
This documentation is generated from Lighthouse and updated regularly.
### How to update:
- `cargo doc`: builds the docs inside the `target/doc/` directory.
- `aws s3 sync target/doc/ s3://lighthouse-docs.sigmaprime.io/`: Uploads all of the docs, as generated with `cargo doc`, to the S3 bucket.
**Note**: You will need appropriate credentials to make the upload.

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

@ -26,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

@ -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,14 +1,59 @@
#![cfg(not(debug_assertions))]
use serde_derive::Deserialize; use serde_derive::Deserialize;
use serde_yaml; use serde_yaml;
#[cfg(not(debug_assertions))] use state_processing::{per_block_processing, per_slot_processing};
use state_processing::{
per_block_processing, per_block_processing_without_verifying_block_signature,
per_slot_processing,
};
use std::{fs::File, io::prelude::*, path::PathBuf}; use std::{fs::File, io::prelude::*, path::PathBuf};
use types::*; use types::*;
#[allow(unused_imports)]
use yaml_utils; #[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 {
@ -17,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)]
@ -27,82 +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 test_read_yaml() {
// Test sanity-check_small-config_32-vals.yaml
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("yaml_utils/specs/sanity-check_small-config_32-vals.yaml"); 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(); yaml_str = yaml_str.to_lowercase();
let _doc: TestDoc = serde_yaml::from_str(&yaml_str.as_str()).unwrap(); serde_yaml::from_str(&yaml_str.as_str()).unwrap()
}
// Test sanity-check_default-config_100-vals.yaml fn run_state_transition_test(test_name: &str) {
file = { let doc = load_test_case(test_name);
let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
file_path_buf.push("yaml_utils/specs/sanity-check_default-config_100-vals.yaml");
File::open(file_path_buf).unwrap() // 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;
}
}
yaml_str = String::new(); 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;
}
}
file.read_to_string(&mut yaml_str).unwrap(); assert!(ok, "one or more tests failed, see above");
}
yaml_str = yaml_str.to_lowercase(); #[test]
#[cfg(not(debug_assertions))]
let _doc: TestDoc = serde_yaml::from_str(&yaml_str.as_str()).unwrap(); 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] #[test]
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
fn run_state_transition_tests_small() { fn run_state_transition_tests_small() {
// Test sanity-check_small-config_32-vals.yaml run_state_transition_test("sanity-check_small-config_32-vals.yaml");
let mut file = { }
let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
file_path_buf.push("yaml_utils/specs/sanity-check_small-config_32-vals.yaml"); // Run with --ignored to run this test
#[test]
File::open(file_path_buf).unwrap() #[ignore]
}; fn run_state_transition_tests_large() {
let mut yaml_str = String::new(); run_state_transition_test("sanity-check_default-config_100-vals.yaml");
file.read_to_string(&mut yaml_str).unwrap();
yaml_str = yaml_str.to_lowercase();
let doc: TestDoc = serde_yaml::from_str(&yaml_str.as_str()).unwrap();
// Run Tests
for (i, test_case) in doc.test_cases.iter().enumerate() {
let mut state = test_case.initial_state.clone();
for block in test_case.blocks.iter() {
while block.slot > state.slot {
let latest_block_header = state.latest_block_header.clone();
per_slot_processing(&mut state, &latest_block_header, &test_case.config).unwrap();
}
if test_case.verify_signatures {
let res = per_block_processing(&mut state, &block, &test_case.config);
if res.is_err() {
println!("{:?}", i);
println!("{:?}", res);
};
} else {
let res = per_block_processing_without_verifying_block_signature(
&mut state,
&block,
&test_case.config,
);
if res.is_err() {
println!("{:?}", i);
println!("{:?}", res);
}
}
}
}
} }

View File

@ -6,7 +6,6 @@ edition = "2018"
[build-dependencies] [build-dependencies]
reqwest = "0.9" reqwest = "0.9"
tempdir = "0.3"
[dependencies] [dependencies]

View File

@ -1,5 +1,4 @@
extern crate reqwest; extern crate reqwest;
extern crate tempdir;
use std::fs::File; use std::fs::File;
use std::io::copy; use std::io::copy;

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

@ -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() {

View File

@ -2,14 +2,25 @@ use super::Hash256;
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};
/// Contains data obtained from the Eth1 chain. /// Contains data obtained from the Eth1 chain.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive( #[derive(
Debug, PartialEq, Clone, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom, Debug,
PartialEq,
Clone,
Default,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)] )]
pub struct Eth1Data { pub struct Eth1Data {
pub deposit_root: Hash256, pub deposit_root: Hash256,
@ -21,4 +32,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(Eth1Data); ssz_tests!(Eth1Data);
cached_tree_hash_tests!(Eth1Data);
} }

View File

@ -2,14 +2,25 @@ use super::Eth1Data;
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 summation of votes for some `Eth1Data`. /// A summation of votes for some `Eth1Data`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive( #[derive(
Debug, PartialEq, Clone, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom, Debug,
PartialEq,
Clone,
Default,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)] )]
pub struct Eth1DataVote { pub struct Eth1DataVote {
pub eth1_data: Eth1Data, pub eth1_data: Eth1Data,
@ -21,4 +32,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(Eth1DataVote); ssz_tests!(Eth1DataVote);
cached_tree_hash_tests!(Eth1DataVote);
} }

View File

@ -5,14 +5,25 @@ use crate::{
use int_to_bytes::int_to_bytes4; use int_to_bytes::int_to_bytes4;
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 a fork of the `BeaconChain`, to prevent replay attacks. /// Specifies a fork of the `BeaconChain`, to prevent replay attacks.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive( #[derive(
Debug, Clone, PartialEq, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom, Debug,
Clone,
PartialEq,
Default,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)] )]
pub struct Fork { pub struct Fork {
#[serde(deserialize_with = "fork_from_hex_str")] #[serde(deserialize_with = "fork_from_hex_str")]
@ -25,7 +36,7 @@ pub struct Fork {
impl Fork { impl Fork {
/// Initialize the `Fork` from the genesis parameters in the `spec`. /// Initialize the `Fork` from the genesis parameters in the `spec`.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn genesis(spec: &ChainSpec) -> Self { pub fn genesis(spec: &ChainSpec) -> Self {
let mut current_version: [u8; 4] = [0; 4]; let mut current_version: [u8; 4] = [0; 4];
current_version.copy_from_slice(&int_to_bytes4(spec.genesis_fork_version)); current_version.copy_from_slice(&int_to_bytes4(spec.genesis_fork_version));
@ -39,7 +50,7 @@ impl Fork {
/// Return the fork version of the given ``epoch``. /// Return the fork version of the given ``epoch``.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn get_fork_version(&self, epoch: Epoch) -> [u8; 4] { pub fn get_fork_version(&self, epoch: Epoch) -> [u8; 4] {
if epoch < self.epoch { if epoch < self.epoch {
return self.previous_version; return self.previous_version;
@ -53,6 +64,7 @@ mod tests {
use super::*; use super::*;
ssz_tests!(Fork); ssz_tests!(Fork);
cached_tree_hash_tests!(Fork);
fn test_genesis(version: u32, epoch: Epoch) { fn test_genesis(version: u32, epoch: Epoch) {
let mut spec = ChainSpec::foundation(); let mut spec = ChainSpec::foundation();

View File

@ -1,17 +1,29 @@
use crate::test_utils::TestRandom; use crate::test_utils::TestRandom;
use crate::Hash256; use crate::{Hash256, TreeHashVector};
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};
/// Historical block and state roots. /// Historical block and state roots.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] #[derive(
Debug,
Clone,
PartialEq,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct HistoricalBatch { pub struct HistoricalBatch {
pub block_roots: Vec<Hash256>, pub block_roots: TreeHashVector<Hash256>,
pub state_roots: Vec<Hash256>, pub state_roots: TreeHashVector<Hash256>,
} }
#[cfg(test)] #[cfg(test)]
@ -19,4 +31,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(HistoricalBatch); ssz_tests!(HistoricalBatch);
cached_tree_hash_tests!(HistoricalBatch);
} }

View File

@ -27,6 +27,7 @@ pub mod pending_attestation;
pub mod proposer_slashing; pub mod proposer_slashing;
pub mod slashable_attestation; pub mod slashable_attestation;
pub mod transfer; pub mod transfer;
pub mod tree_hash_vector;
pub mod voluntary_exit; pub mod voluntary_exit;
#[macro_use] #[macro_use]
pub mod slot_epoch_macros; pub mod slot_epoch_macros;
@ -65,6 +66,7 @@ pub use crate::slashable_attestation::SlashableAttestation;
pub use crate::slot_epoch::{Epoch, Slot}; pub use crate::slot_epoch::{Epoch, Slot};
pub use crate::slot_height::SlotHeight; pub use crate::slot_height::SlotHeight;
pub use crate::transfer::Transfer; pub use crate::transfer::Transfer;
pub use crate::tree_hash_vector::TreeHashVector;
pub use crate::validator::Validator; pub use crate::validator::Validator;
pub use crate::voluntary_exit::VoluntaryExit; pub use crate::voluntary_exit::VoluntaryExit;

View File

@ -2,13 +2,25 @@ use crate::test_utils::TestRandom;
use crate::{Attestation, AttestationData, Bitfield, Slot}; use crate::{Attestation, AttestationData, Bitfield, Slot};
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};
/// An attestation that has been included in the state but not yet fully processed. /// An attestation that has been included in the state but not yet fully processed.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] #[derive(
Debug,
Clone,
PartialEq,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct PendingAttestation { pub struct PendingAttestation {
pub aggregation_bitfield: Bitfield, pub aggregation_bitfield: Bitfield,
pub data: AttestationData, pub data: AttestationData,
@ -33,4 +45,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(PendingAttestation); ssz_tests!(PendingAttestation);
cached_tree_hash_tests!(PendingAttestation);
} }

View File

@ -2,13 +2,25 @@ use super::BeaconBlockHeader;
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};
/// Two conflicting proposals from the same proposer (validator). /// Two conflicting proposals from the same proposer (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 ProposerSlashing { pub struct ProposerSlashing {
pub proposer_index: u64, pub proposer_index: u64,
pub header_1: BeaconBlockHeader, pub header_1: BeaconBlockHeader,
@ -20,4 +32,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(ProposerSlashing); ssz_tests!(ProposerSlashing);
cached_tree_hash_tests!(ProposerSlashing);
} }

View File

@ -10,7 +10,7 @@ pub enum Error {
/// Defines the epochs relative to some epoch. Most useful when referring to the committees prior /// Defines the epochs relative to some epoch. Most useful when referring to the committees prior
/// to and following some epoch. /// to and following some epoch.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive(Debug, PartialEq, Clone, Copy)] #[derive(Debug, PartialEq, Clone, Copy)]
pub enum RelativeEpoch { pub enum RelativeEpoch {
/// The prior epoch. /// The prior epoch.
@ -32,7 +32,7 @@ pub enum RelativeEpoch {
impl RelativeEpoch { impl RelativeEpoch {
/// Returns the `epoch` that `self` refers to, with respect to the `base` epoch. /// Returns the `epoch` that `self` refers to, with respect to the `base` epoch.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn into_epoch(self, base: Epoch) -> Epoch { pub fn into_epoch(self, base: Epoch) -> Epoch {
match self { match self {
RelativeEpoch::Previous => base - 1, RelativeEpoch::Previous => base - 1,
@ -51,7 +51,7 @@ impl RelativeEpoch {
/// - `AmbiguiousNextEpoch` whenever `other` is one after `base`, because it's unknowable if /// - `AmbiguiousNextEpoch` whenever `other` is one after `base`, because it's unknowable if
/// there will be a registry change. /// there will be a registry change.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn from_epoch(base: Epoch, other: Epoch) -> Result<Self, Error> { pub fn from_epoch(base: Epoch, other: Epoch) -> Result<Self, Error> {
if other == base - 1 { if other == base - 1 {
Ok(RelativeEpoch::Previous) Ok(RelativeEpoch::Previous)

View File

@ -1,15 +1,16 @@
use crate::{test_utils::TestRandom, AggregateSignature, AttestationData, Bitfield, ChainSpec}; use crate::{test_utils::TestRandom, AggregateSignature, AttestationData, Bitfield, ChainSpec};
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.
/// ///
/// To be included in an `AttesterSlashing`. /// To be included in an `AttesterSlashing`.
/// ///
/// 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 SlashableAttestation {
pub validator_indices: Vec<u64>, pub validator_indices: Vec<u64>,
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,
} }
impl SlashableAttestation { impl SlashableAttestation {
/// Check if ``attestation_data_1`` and ``attestation_data_2`` have the same target. /// Check if ``attestation_data_1`` and ``attestation_data_2`` have the same target.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn is_double_vote(&self, other: &SlashableAttestation, spec: &ChainSpec) -> bool { pub fn is_double_vote(&self, other: &SlashableAttestation, spec: &ChainSpec) -> bool {
self.data.slot.epoch(spec.slots_per_epoch) == other.data.slot.epoch(spec.slots_per_epoch) self.data.slot.epoch(spec.slots_per_epoch) == other.data.slot.epoch(spec.slots_per_epoch)
} }
/// Check if ``attestation_data_1`` surrounds ``attestation_data_2``. /// Check if ``attestation_data_1`` surrounds ``attestation_data_2``.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
pub fn is_surround_vote(&self, other: &SlashableAttestation, spec: &ChainSpec) -> bool { pub fn is_surround_vote(&self, other: &SlashableAttestation, spec: &ChainSpec) -> bool {
let source_epoch_1 = self.data.source_epoch; let source_epoch_1 = self.data.source_epoch;
let source_epoch_2 = other.data.source_epoch; let source_epoch_2 = other.data.source_epoch;
@ -131,6 +134,7 @@ mod tests {
} }
ssz_tests!(SlashableAttestation); ssz_tests!(SlashableAttestation);
cached_tree_hash_tests!(SlashableAttestation);
fn create_slashable_attestation( fn create_slashable_attestation(
slot_factor: u64, slot_factor: u64,

View File

@ -14,7 +14,7 @@ use crate::test_utils::TestRandom;
use rand::RngCore; use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use slog; use slog;
use ssz::{hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash}; use ssz::{ssz_encode, Decodable, DecodeError, Encodable, SszStream};
use std::cmp::{Ord, Ordering}; use std::cmp::{Ord, Ordering};
use std::fmt; use std::fmt;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};

View File

@ -206,11 +206,41 @@ macro_rules! impl_ssz {
} }
} }
impl TreeHash for $type { impl tree_hash::TreeHash for $type {
fn hash_tree_root(&self) -> Vec<u8> { fn tree_hash_type() -> tree_hash::TreeHashType {
let mut result: Vec<u8> = vec![]; tree_hash::TreeHashType::Basic
result.append(&mut self.0.hash_tree_root()); }
hash(&result)
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
ssz_encode(self)
}
fn tree_hash_packing_factor() -> usize {
32 / 8
}
fn tree_hash_root(&self) -> Vec<u8> {
int_to_bytes::int_to_bytes32(self.0)
}
}
impl cached_tree_hash::CachedTreeHash for $type {
fn new_tree_hash_cache(
&self,
depth: usize,
) -> Result<cached_tree_hash::TreeHashCache, cached_tree_hash::Error> {
self.0.new_tree_hash_cache(depth)
}
fn tree_hash_cache_schema(&self, depth: usize) -> cached_tree_hash::BTreeSchema {
self.0.tree_hash_cache_schema(depth)
}
fn update_tree_hash_cache(
&self,
cache: &mut cached_tree_hash::TreeHashCache,
) -> Result<(), cached_tree_hash::Error> {
self.0.update_tree_hash_cache(cache)
} }
} }
@ -535,6 +565,7 @@ macro_rules! all_tests {
math_between_tests!($type, $type); math_between_tests!($type, $type);
math_tests!($type); math_tests!($type);
ssz_tests!($type); ssz_tests!($type);
cached_tree_hash_tests!($type);
mod u64_tests { mod u64_tests {
use super::*; use super::*;

View File

@ -2,7 +2,7 @@ use crate::slot_epoch::{Epoch, Slot};
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::{hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash}; use ssz::{ssz_encode, Decodable, DecodeError, Encodable, SszStream};
use std::cmp::{Ord, Ordering}; use std::cmp::{Ord, Ordering};
use std::fmt; use std::fmt;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};

View File

@ -17,14 +17,14 @@ macro_rules! ssz_tests {
} }
#[test] #[test]
pub fn test_hash_tree_root() { pub fn test_tree_hash_root() {
use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng}; use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng};
use ssz::TreeHash; use tree_hash::TreeHash;
let mut rng = XorShiftRng::from_seed([42; 16]); let mut rng = XorShiftRng::from_seed([42; 16]);
let original = $type::random_for_test(&mut rng); let original = $type::random_for_test(&mut rng);
let result = original.hash_tree_root(); let result = original.tree_hash_root();
assert_eq!(result.len(), 32); assert_eq!(result.len(), 32);
// TODO: Add further tests // TODO: Add further tests
@ -32,3 +32,51 @@ macro_rules! ssz_tests {
} }
}; };
} }
#[cfg(test)]
#[macro_export]
macro_rules! cached_tree_hash_tests {
($type: ident) => {
#[test]
pub fn test_cached_tree_hash() {
use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng};
use tree_hash::TreeHash;
let mut rng = XorShiftRng::from_seed([42; 16]);
// Test the original hash
let original = $type::random_for_test(&mut rng);
let mut cache = cached_tree_hash::TreeHashCache::new(&original).unwrap();
assert_eq!(
cache.tree_hash_root().unwrap().to_vec(),
original.tree_hash_root(),
"Original hash failed."
);
// Test the updated hash
let modified = $type::random_for_test(&mut rng);
cache.update(&modified).unwrap();
assert_eq!(
cache.tree_hash_root().unwrap().to_vec(),
modified.tree_hash_root(),
"Modification hash failed"
);
// Produce a new cache for the modified object and compare it to the updated cache.
let mut modified_cache = cached_tree_hash::TreeHashCache::new(&modified).unwrap();
// Reset the caches.
cache.reset_modifications();
modified_cache.reset_modifications();
// Ensure the modified cache is the same as a newly created cache. This is a sanity
// check to make sure there are no artifacts of the original cache remaining after an
// update.
assert_eq!(
modified_cache, cache,
"The modified cache does not match a new cache."
)
}
};
}

View File

@ -18,7 +18,10 @@ mod testing_voluntary_exit_builder;
pub use generate_deterministic_keypairs::generate_deterministic_keypair; pub use generate_deterministic_keypairs::generate_deterministic_keypair;
pub use generate_deterministic_keypairs::generate_deterministic_keypairs; pub use generate_deterministic_keypairs::generate_deterministic_keypairs;
pub use keypairs_file::KeypairsFile; pub use keypairs_file::KeypairsFile;
pub use rand::{prng::XorShiftRng, SeedableRng}; pub use rand::{
RngCore,
{prng::XorShiftRng, SeedableRng},
};
pub use serde_utils::{fork_from_hex_str, u8_from_hex_str}; pub use serde_utils::{fork_from_hex_str, u8_from_hex_str};
pub use test_random::TestRandom; pub use test_random::TestRandom;
pub use testing_attestation_builder::TestingAttestationBuilder; pub use testing_attestation_builder::TestingAttestationBuilder;

View File

@ -44,11 +44,13 @@ where
U: TestRandom<T>, U: TestRandom<T>,
{ {
fn random_for_test(rng: &mut T) -> Self { fn random_for_test(rng: &mut T) -> Self {
vec![ let mut output = vec![];
<U>::random_for_test(rng),
<U>::random_for_test(rng), for _ in 0..(usize::random_for_test(rng) % 4) {
<U>::random_for_test(rng), output.push(<U>::random_for_test(rng));
] }
output
} }
} }

View File

@ -1,6 +1,6 @@
use crate::test_utils::TestingAttestationDataBuilder; use crate::test_utils::TestingAttestationDataBuilder;
use crate::*; use crate::*;
use ssz::TreeHash; use tree_hash::TreeHash;
/// Builds an attestation to be used for testing purposes. /// Builds an attestation to be used for testing purposes.
/// ///
@ -74,7 +74,7 @@ impl TestingAttestationBuilder {
data: self.attestation.data.clone(), data: self.attestation.data.clone(),
custody_bit: false, custody_bit: false,
} }
.hash_tree_root(); .tree_hash_root();
let domain = spec.get_domain( let domain = spec.get_domain(
self.attestation.data.slot.epoch(spec.slots_per_epoch), self.attestation.data.slot.epoch(spec.slots_per_epoch),

View File

@ -1,5 +1,5 @@
use crate::*; use crate::*;
use ssz::TreeHash; use tree_hash::TreeHash;
/// Builds an `AttesterSlashing`. /// Builds an `AttesterSlashing`.
/// ///
@ -66,7 +66,7 @@ impl TestingAttesterSlashingBuilder {
data: attestation.data.clone(), data: attestation.data.clone(),
custody_bit: false, custody_bit: false,
}; };
let message = attestation_data_and_custody_bit.hash_tree_root(); let message = attestation_data_and_custody_bit.tree_hash_root();
for (i, validator_index) in validator_indices.iter().enumerate() { for (i, validator_index) in validator_indices.iter().enumerate() {
attestation.custody_bitfield.set(i, false); attestation.custody_bitfield.set(i, false);

View File

@ -6,7 +6,7 @@ use crate::{
*, *,
}; };
use rayon::prelude::*; use rayon::prelude::*;
use ssz::{SignedRoot, TreeHash}; use tree_hash::{SignedRoot, TreeHash};
/// Builds a beacon block to be used for testing purposes. /// Builds a beacon block to be used for testing purposes.
/// ///
@ -43,7 +43,7 @@ impl TestingBeaconBlockBuilder {
/// Modifying the block's slot after signing may invalidate the signature. /// Modifying the block's slot after signing may invalidate the signature.
pub fn set_randao_reveal(&mut self, sk: &SecretKey, fork: &Fork, spec: &ChainSpec) { pub fn set_randao_reveal(&mut self, sk: &SecretKey, fork: &Fork, spec: &ChainSpec) {
let epoch = self.block.slot.epoch(spec.slots_per_epoch); let epoch = self.block.slot.epoch(spec.slots_per_epoch);
let message = epoch.hash_tree_root(); let message = epoch.tree_hash_root();
let domain = spec.get_domain(epoch, Domain::Randao, fork); let domain = spec.get_domain(epoch, Domain::Randao, fork);
self.block.body.randao_reveal = Signature::new(&message, domain, sk); self.block.body.randao_reveal = Signature::new(&message, domain, sk);
} }

View File

@ -12,7 +12,7 @@ impl TestingDepositBuilder {
/// Instantiates a new builder. /// Instantiates a new builder.
pub fn new(pubkey: PublicKey, amount: u64) -> Self { pub fn new(pubkey: PublicKey, amount: u64) -> Self {
let deposit = Deposit { let deposit = Deposit {
proof: vec![], proof: vec![].into(),
index: 0, index: 0,
deposit_data: DepositData { deposit_data: DepositData {
amount, amount,

View File

@ -1,5 +1,5 @@
use crate::*; use crate::*;
use ssz::SignedRoot; use tree_hash::SignedRoot;
/// Builds a `ProposerSlashing`. /// Builds a `ProposerSlashing`.
/// ///

View File

@ -1,5 +1,5 @@
use crate::*; use crate::*;
use ssz::SignedRoot; use tree_hash::SignedRoot;
/// Builds a transfer to be used for testing purposes. /// Builds a transfer to be used for testing purposes.
/// ///

View File

@ -1,5 +1,5 @@
use crate::*; use crate::*;
use ssz::SignedRoot; use tree_hash::SignedRoot;
/// Builds an exit to be used for testing purposes. /// Builds an exit to be used for testing purposes.
/// ///

View File

@ -4,13 +4,14 @@ use bls::{PublicKey, Signature};
use derivative::Derivative; use derivative::Derivative;
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 submitted to the deposit contract. /// The data submitted to the deposit contract.
/// ///
/// 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,
SignedRoot, SignedRoot,
Derivative, Derivative,
@ -32,6 +34,7 @@ pub struct Transfer {
pub slot: Slot, pub slot: Slot,
pub pubkey: PublicKey, pub pubkey: PublicKey,
#[derivative(Hash = "ignore")] #[derivative(Hash = "ignore")]
#[signed_root(skip_hashing)]
pub signature: Signature, pub signature: Signature,
} }
@ -40,4 +43,5 @@ mod tests {
use super::*; use super::*;
ssz_tests!(Transfer); ssz_tests!(Transfer);
cached_tree_hash_tests!(Transfer);
} }

View File

@ -0,0 +1,142 @@
use crate::test_utils::{RngCore, TestRandom};
use cached_tree_hash::CachedTreeHash;
use serde_derive::{Deserialize, Serialize};
use ssz::{Decodable, DecodeError, Encodable, SszStream};
use std::ops::{Deref, DerefMut};
use tree_hash::TreeHash;
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct TreeHashVector<T>(Vec<T>);
impl<T> From<Vec<T>> for TreeHashVector<T> {
fn from(vec: Vec<T>) -> TreeHashVector<T> {
TreeHashVector(vec)
}
}
impl<T> Into<Vec<T>> for TreeHashVector<T> {
fn into(self) -> Vec<T> {
self.0
}
}
impl<T> Deref for TreeHashVector<T> {
type Target = Vec<T>;
fn deref(&self) -> &Vec<T> {
&self.0
}
}
impl<T> DerefMut for TreeHashVector<T> {
fn deref_mut(&mut self) -> &mut Vec<T> {
&mut self.0
}
}
impl<T> tree_hash::TreeHash for TreeHashVector<T>
where
T: TreeHash,
{
fn tree_hash_type() -> tree_hash::TreeHashType {
tree_hash::TreeHashType::Vector
}
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
unreachable!("Vector should never be packed.")
}
fn tree_hash_packing_factor() -> usize {
unreachable!("Vector should never be packed.")
}
fn tree_hash_root(&self) -> Vec<u8> {
tree_hash::impls::vec_tree_hash_root(self)
}
}
impl<T> CachedTreeHash for TreeHashVector<T>
where
T: CachedTreeHash + TreeHash,
{
fn new_tree_hash_cache(
&self,
depth: usize,
) -> Result<cached_tree_hash::TreeHashCache, cached_tree_hash::Error> {
let (cache, _overlay) = cached_tree_hash::vec::new_tree_hash_cache(self, depth)?;
Ok(cache)
}
fn tree_hash_cache_schema(&self, depth: usize) -> cached_tree_hash::BTreeSchema {
cached_tree_hash::vec::produce_schema(self, depth)
}
fn update_tree_hash_cache(
&self,
cache: &mut cached_tree_hash::TreeHashCache,
) -> Result<(), cached_tree_hash::Error> {
cached_tree_hash::vec::update_tree_hash_cache(self, cache)?;
Ok(())
}
}
impl<T> Encodable for TreeHashVector<T>
where
T: Encodable,
{
fn ssz_append(&self, s: &mut SszStream) {
s.append_vec(self)
}
}
impl<T> Decodable for TreeHashVector<T>
where
T: Decodable,
{
fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError> {
ssz::decode_ssz_list(bytes, index).and_then(|(vec, i)| Ok((vec.into(), i)))
}
}
impl<T: RngCore, U> TestRandom<T> for TreeHashVector<U>
where
U: TestRandom<T>,
{
fn random_for_test(rng: &mut T) -> Self {
TreeHashVector::from(vec![
U::random_for_test(rng),
U::random_for_test(rng),
U::random_for_test(rng),
])
}
}
#[cfg(test)]
mod test {
use super::*;
use tree_hash::TreeHash;
#[test]
pub fn test_cached_tree_hash() {
let original = TreeHashVector::from(vec![1_u64, 2, 3, 4]);
let mut cache = cached_tree_hash::TreeHashCache::new(&original).unwrap();
assert_eq!(
cache.tree_hash_root().unwrap().to_vec(),
original.tree_hash_root()
);
let modified = TreeHashVector::from(vec![1_u64, 1, 1, 1]);
cache.update(&modified).unwrap();
assert_eq!(
cache.tree_hash_root().unwrap().to_vec(),
modified.tree_hash_root()
);
}
}

View File

@ -1,13 +1,25 @@
use crate::{test_utils::TestRandom, Epoch, Hash256, PublicKey}; use crate::{test_utils::TestRandom, Epoch, Hash256, PublicKey};
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};
/// Information about a `BeaconChain` validator. /// Information about a `BeaconChain` validator.
/// ///
/// Spec v0.5.0 /// Spec v0.5.1
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TestRandom, TreeHash)] #[derive(
Debug,
Clone,
PartialEq,
Serialize,
Deserialize,
Encode,
Decode,
TestRandom,
TreeHash,
CachedTreeHash,
)]
pub struct Validator { pub struct Validator {
pub pubkey: PublicKey, pub pubkey: PublicKey,
pub withdrawal_credentials: Hash256, pub withdrawal_credentials: Hash256,
@ -110,4 +122,5 @@ mod tests {
} }
ssz_tests!(Validator); ssz_tests!(Validator);
cached_tree_hash_tests!(Validator);
} }

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