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
*.sk
*.raw_keypairs
flamegraph.svg
perf.data*

View File

@ -1,4 +1,9 @@
language: rust
cache:
directories:
- /home/travis/.cargo
before_cache:
- rm -rf /home/travis/.cargo/registry
before_install:
- 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
@ -6,11 +11,13 @@ before_install:
- sudo mv protoc3/include/* /usr/local/include/
- sudo chown $USER /usr/local/bin/protoc
- 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:
- cargo build --verbose --all
- cargo build --verbose --release --all
- cargo test --verbose --all
- cargo test --verbose --release --all
- cargo build --verbose $BUILD
- cargo test --verbose $BUILD
- cargo fmt --all -- --check
# No clippy until later...
#- cargo clippy
@ -22,6 +29,15 @@ matrix:
allow_failures:
- rust: nightly
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:
- rustup component add rustfmt
- rustup component add clippy

View File

@ -9,6 +9,7 @@ members = [
"eth2/types",
"eth2/utils/bls",
"eth2/utils/boolean-bitfield",
"eth2/utils/cached_tree_hash",
"eth2/utils/hashing",
"eth2/utils/honey-badger-split",
"eth2/utils/merkle_proof",
@ -18,6 +19,8 @@ members = [
"eth2/utils/ssz",
"eth2/utils/ssz_derive",
"eth2/utils/swap_or_not_shuffle",
"eth2/utils/tree_hash",
"eth2/utils/tree_hash_derive",
"eth2/utils/fisher_yates_shuffle",
"eth2/utils/test_random_derive",
"beacon_node",

5
Jenkinsfile vendored
View File

@ -23,6 +23,11 @@ pipeline {
steps {
sh 'cargo test --verbose --all'
sh 'cargo test --verbose --all --release'
sh 'cargo test --manifest-path eth2/state_processing/Cargo.toml --verbose \
--release --features fake_crypto'
sh 'cargo test --manifest-path eth2/state_processing/Cargo.toml --verbose \
--release --features fake_crypto -- --ignored'
}
}
}

476
LICENSE
View File

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

View File

@ -24,6 +24,7 @@ present-Ethereum functionality.
- [About Lighthouse](docs/lighthouse.md): Goals, Ideology and Ethos surrounding
this implementation.
- [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
\#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" }
ssz = { path = "../../eth2/utils/ssz" }
state_processing = { path = "../../eth2/state_processing" }
tree_hash = { path = "../../eth2/utils/tree_hash" }
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
/// find the state at an old slot.
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() {
Ok(Some(slot)) => slot,
_ => return Err(Error::UnableToReadSlot),
@ -312,7 +310,7 @@ where
// If required, transition the new state to the present slot.
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)?;
@ -324,8 +322,6 @@ where
/// Ensures the current canonical `BeaconState` has been transitioned to match the `slot_clock`.
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() {
Ok(Some(slot)) => slot,
_ => return Err(Error::UnableToReadSlot),
@ -339,7 +335,7 @@ where
state.build_epoch_cache(RelativeEpoch::NextWithoutRegistryChange, &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)?;
@ -617,9 +613,8 @@ where
// Transition the parent state to the block slot.
let mut state = parent_state;
let previous_block_header = parent_block.block_header();
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(
InvalidBlock::SlotProcessingError(e),
));

View File

@ -7,9 +7,9 @@ use db::stores::{BeaconBlockStore, BeaconStateStore};
use db::{DiskDB, MemoryDB};
use fork_choice::BitwiseLMDGhost;
use slot_clock::SystemTimeSlotClock;
use ssz::TreeHash;
use std::path::PathBuf;
use std::sync::Arc;
use tree_hash::TreeHash;
use types::test_utils::TestingBeaconStateBuilder;
use types::{BeaconBlock, ChainSpec, Hash256};
@ -32,7 +32,7 @@ pub fn initialise_beacon_chain(
let (genesis_state, _keypairs) = state_builder.build();
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
let slot_clock = SystemTimeSlotClock::new(
@ -73,7 +73,7 @@ pub fn initialise_test_beacon_chain(
let (genesis_state, _keypairs) = state_builder.build();
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
let slot_clock = SystemTimeSlotClock::new(

View File

@ -5,8 +5,8 @@ use db::{
};
use fork_choice::BitwiseLMDGhost;
use slot_clock::TestingSlotClock;
use ssz::TreeHash;
use std::sync::Arc;
use tree_hash::TreeHash;
use types::test_utils::TestingBeaconStateBuilder;
use types::*;
@ -27,7 +27,7 @@ impl TestingBeaconChainBuilder {
let (genesis_state, _keypairs) = self.state_builder.build();
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
BeaconChain::from_genesis(

View File

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

View File

@ -9,8 +9,8 @@ use fork_choice::BitwiseLMDGhost;
use log::debug;
use rayon::prelude::*;
use slot_clock::TestingSlotClock;
use ssz::TreeHash;
use std::sync::Arc;
use tree_hash::TreeHash;
use types::{test_utils::TestingBeaconStateBuilder, *};
type TestingBeaconChain = BeaconChain<MemoryDB, TestingSlotClock, BitwiseLMDGhost<MemoryDB>>;
@ -54,7 +54,7 @@ impl BeaconChainHarness {
let (mut genesis_state, keypairs) = state_builder.build();
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
.build_epoch_cache(RelativeEpoch::Previous, &spec)
@ -163,7 +163,7 @@ impl BeaconChainHarness {
data: data.clone(),
custody_bit: false,
}
.hash_tree_root();
.tree_hash_root();
let domain = self.spec.get_domain(
state.slot.epoch(self.spec.slots_per_epoch),
Domain::Attestation,

View File

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

View File

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

View File

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

View File

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

View File

@ -2,9 +2,9 @@ use crate::beacon_chain::BeaconChain;
use eth2_libp2p::rpc::methods::*;
use eth2_libp2p::PeerId;
use slog::{debug, error};
use ssz::TreeHash;
use std::sync::Arc;
use std::time::{Duration, Instant};
use tree_hash::TreeHash;
use types::{BeaconBlock, BeaconBlockBody, BeaconBlockHeader, Hash256, Slot};
/// 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
/// `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.
/// - It is possible for multiple distinct blocks to have identical `BeaconBlockBodies`. Therefore
/// we cannot use a `HashMap` keyed by the root of `BeaconBlockBody`.
@ -166,7 +166,7 @@ impl ImportQueue {
let mut required_bodies: Vec<Hash256> = vec![];
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) {
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`.
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| {
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`.
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 {
slot: block.slot,

View File

@ -5,10 +5,10 @@ use eth2_libp2p::rpc::methods::*;
use eth2_libp2p::rpc::{RPCRequest, RPCResponse, RequestId};
use eth2_libp2p::PeerId;
use slog::{debug, error, info, o, warn};
use ssz::TreeHash;
use std::collections::HashMap;
use std::sync::Arc;
use std::time::Duration;
use tree_hash::TreeHash;
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.
@ -565,7 +565,7 @@ impl SimpleSync {
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.
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]
slot_clock = { path = "../../eth2/utils/slot_clock" }
ssz = { path = "../../eth2/utils/ssz" }
tree_hash = { path = "../../eth2/utils/tree_hash" }
types = { path = "../../eth2/types" }

View File

@ -2,8 +2,8 @@ pub mod test_utils;
mod traits;
use slot_clock::SlotClock;
use ssz::TreeHash;
use std::sync::Arc;
use tree_hash::TreeHash;
use types::{AttestationData, AttestationDataAndCustodyBit, FreeAttestation, Signature, Slot};
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(),
custody_bit: PHASE_0_CUSTODY_BIT,
}
.hash_tree_root();
.tree_hash_root();
self.signer
.sign_attestation_message(&message[..], DOMAIN_ATTESTATION)

View File

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

View File

@ -2,8 +2,8 @@ pub mod test_utils;
mod traits;
use slot_clock::SlotClock;
use ssz::{SignedRoot, TreeHash};
use std::sync::Arc;
use tree_hash::{SignedRoot, TreeHash};
use types::{BeaconBlock, ChainSpec, Domain, Slot};
pub use self::traits::{
@ -139,7 +139,7 @@ impl<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> BlockProducer<T, U
let randao_reveal = {
// 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(
&message,

View File

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

View File

@ -26,5 +26,10 @@ log = "0.4"
merkle_proof = { path = "../utils/merkle_proof" }
ssz = { path = "../utils/ssz" }
ssz_derive = { path = "../utils/ssz_derive" }
tree_hash = { path = "../utils/tree_hash" }
tree_hash_derive = { path = "../utils/tree_hash_derive" }
types = { path = "../types" }
rayon = "1.0"
[features]
fake_crypto = ["bls/fake_crypto"]

View File

@ -1,6 +1,5 @@
use criterion::Criterion;
use criterion::{black_box, Benchmark};
use ssz::TreeHash;
use state_processing::{
per_block_processing,
per_block_processing::{
@ -9,6 +8,7 @@ use state_processing::{
verify_block_signature,
},
};
use tree_hash::TreeHash;
use types::*;
/// Run the detailed benchmarking suite on the given `BeaconState`.
@ -263,7 +263,7 @@ pub fn bench_block_processing(
c.bench(
&format!("{}/block_processing", desc),
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),
);

View File

@ -1,6 +1,5 @@
use criterion::Criterion;
use criterion::{black_box, Benchmark};
use ssz::TreeHash;
use state_processing::{
per_epoch_processing,
per_epoch_processing::{
@ -9,6 +8,7 @@ use state_processing::{
update_active_tree_index_roots, update_latest_slashed_balances,
},
};
use tree_hash::TreeHash;
use types::test_utils::TestingBeaconStateBuilder;
use types::*;
@ -256,7 +256,7 @@ fn bench_epoch_processing(c: &mut Criterion, state: &BeaconState, spec: &ChainSp
c.bench(
&format!("{}/epoch_processing", desc),
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),
);

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`.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn exit_validator(
state: &mut BeaconState,
validator_index: usize,

View File

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

View File

@ -4,7 +4,7 @@ use types::*;
///
/// 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 {
if bitfield.num_bytes() != ((committee_size + 7) / 8) {
return false;
@ -18,3 +18,62 @@ pub fn verify_bitfield_length(bitfield: &Bitfield, committee_size: usize) -> boo
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 ssz::TreeHash;
use tree_hash::TreeHash;
use types::*;
pub enum GenesisError {
@ -9,13 +9,13 @@ pub enum GenesisError {
/// Returns the genesis `BeaconState`
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_genesis_state(
genesis_validator_deposits: &[Deposit],
genesis_time: u64,
genesis_eth1_data: Eth1Data,
spec: &ChainSpec,
) -> Result<(), BlockProcessingError> {
) -> Result<BeaconState, BlockProcessingError> {
// Get the genesis `BeaconState`
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
.get_cached_active_validator_indices(RelativeEpoch::Current, spec)?
.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);
// Generate the current shuffling seed.
state.current_shuffling_seed = state.generate_seed(spec.genesis_epoch, spec)?;
Ok(())
Ok(state)
}
impl From<BlockProcessingError> for GenesisError {

View File

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

View File

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

View File

@ -1,6 +1,6 @@
use super::errors::{AttestationInvalid as Invalid, AttestationValidationError as Error};
use crate::common::verify_bitfield_length;
use ssz::TreeHash;
use tree_hash::TreeHash;
use types::*;
/// 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.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn validate_attestation(
state: &BeaconState,
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.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn validate_attestation_without_signature(
state: &BeaconState,
attestation: &Attestation,
@ -44,7 +44,7 @@ pub fn validate_attestation_without_signature(
/// given state, optionally validating the aggregate signature.
///
///
/// Spec v0.5.0
/// Spec v0.5.1
fn validate_attestation_parametric(
state: &BeaconState,
attestation: &Attestation,
@ -167,7 +167,7 @@ fn validate_attestation_parametric(
/// Verify that the `source_epoch` and `source_root` of an `Attestation` correctly
/// 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(
attestation: &Attestation,
state: &BeaconState,
@ -222,7 +222,7 @@ fn verify_justified_epoch_and_root(
/// - `custody_bitfield` does not have a bit for each index of `committee`.
/// - A `validator_index` in `committee` is not in `state.validator_registry`.
///
/// Spec v0.5.0
/// Spec v0.5.1
fn verify_attestation_signature(
state: &BeaconState,
committee: &[usize],
@ -270,14 +270,14 @@ fn verify_attestation_signature(
data: a.data.clone(),
custody_bit: false,
}
.hash_tree_root();
.tree_hash_root();
// Message when custody bitfield is `true`
let message_1 = AttestationDataAndCustodyBit {
data: a.data.clone(),
custody_bit: true,
}
.hash_tree_root();
.tree_hash_root();
let mut messages = 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.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn verify_attester_slashing(
state: &BeaconState,
attester_slashing: &AttesterSlashing,
@ -41,7 +41,7 @@ pub fn verify_attester_slashing(
///
/// Returns Ok(indices) if `indices.len() > 0`.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn gather_attester_slashing_indices(
state: &BeaconState,
attester_slashing: &AttesterSlashing,

View File

@ -15,7 +15,7 @@ use types::*;
///
/// Note: this function is incomplete.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn verify_deposit(
state: &BeaconState,
deposit: &Deposit,
@ -46,7 +46,7 @@ pub fn verify_deposit(
/// 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> {
verify!(
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.
///
/// Spec v0.5.0
/// Spec v0.5.1
fn verify_deposit_merkle_proof(state: &BeaconState, deposit: &Deposit, spec: &ChainSpec) -> bool {
let leaf = hash(&get_serialized_deposit_data(deposit));
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.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(Encode)]
struct SerializedDepositData {
amount: u64,
@ -113,7 +113,7 @@ struct SerializedDepositData {
/// Return the serialized data generated by the deposit contract that is used to generate the
/// merkle proof.
///
/// Spec v0.5.0
/// Spec v0.5.1
fn get_serialized_deposit_data(deposit: &Deposit) -> Vec<u8> {
let serialized_deposit_data = SerializedDepositData {
amount: deposit.deposit_data.amount,

View File

@ -1,5 +1,5 @@
use super::errors::{ExitInvalid as Invalid, ExitValidationError as Error};
use ssz::SignedRoot;
use tree_hash::SignedRoot;
use types::*;
/// 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.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn verify_exit(
state: &BeaconState,
exit: &VoluntaryExit,

View File

@ -1,5 +1,5 @@
use super::errors::{ProposerSlashingInvalid as Invalid, ProposerSlashingValidationError as Error};
use ssz::SignedRoot;
use tree_hash::SignedRoot;
use types::*;
/// 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.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn verify_proposer_slashing(
proposer_slashing: &ProposerSlashing,
state: &BeaconState,
@ -21,8 +21,9 @@ pub fn verify_proposer_slashing(
})?;
verify!(
proposer_slashing.header_1.slot == proposer_slashing.header_2.slot,
Invalid::ProposalSlotMismatch(
proposer_slashing.header_1.slot.epoch(spec.slots_per_epoch)
== proposer_slashing.header_2.slot.epoch(spec.slots_per_epoch),
Invalid::ProposalEpochMismatch(
proposer_slashing.header_1.slot,
proposer_slashing.header_2.slot
)
@ -66,7 +67,7 @@ pub fn verify_proposer_slashing(
///
/// Returns `true` if the signature is valid.
///
/// Spec v0.5.0
/// Spec v0.5.1
fn verify_header_signature(
header: &BeaconBlockHeader,
pubkey: &PublicKey,

View File

@ -2,7 +2,7 @@ use super::errors::{
SlashableAttestationInvalid as Invalid, SlashableAttestationValidationError as Error,
};
use crate::common::verify_bitfield_length;
use ssz::TreeHash;
use tree_hash::TreeHash;
use types::*;
/// 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.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn verify_slashable_attestation(
state: &BeaconState,
slashable_attestation: &SlashableAttestation,
@ -77,12 +77,12 @@ pub fn verify_slashable_attestation(
data: slashable_attestation.data.clone(),
custody_bit: false,
}
.hash_tree_root();
.tree_hash_root();
let message_1 = AttestationDataAndCustodyBit {
data: slashable_attestation.data.clone(),
custody_bit: true,
}
.hash_tree_root();
.tree_hash_root();
let mut messages = vec![];
let mut keys = vec![];

View File

@ -1,6 +1,6 @@
use super::errors::{TransferInvalid as Invalid, TransferValidationError as Error};
use bls::get_withdrawal_credentials;
use ssz::SignedRoot;
use tree_hash::SignedRoot;
use types::*;
/// 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.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn verify_transfer(
state: &BeaconState,
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.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn execute_transfer(
state: &mut BeaconState,
transfer: &Transfer,

View File

@ -3,8 +3,8 @@ use errors::EpochProcessingError as Error;
use process_ejections::process_ejections;
use process_exit_queue::process_exit_queue;
use process_slashings::process_slashings;
use ssz::TreeHash;
use std::collections::HashMap;
use tree_hash::TreeHash;
use types::*;
use update_registry_and_shuffling_data::update_registry_and_shuffling_data;
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
/// 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> {
// Ensure the previous and next epoch caches are built.
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.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn maybe_reset_eth1_period(state: &mut BeaconState, spec: &ChainSpec) {
let next_epoch = state.next_epoch(spec);
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`
/// - `previous_justified_epoch`
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn update_justification_and_finalization(
state: &mut BeaconState,
total_balances: &TotalBalances,
@ -178,7 +178,7 @@ pub fn update_justification_and_finalization(
///
/// Also returns a `WinningRootHashSet` for later use during epoch processing.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn process_crosslinks(
state: &mut BeaconState,
spec: &ChainSpec,
@ -221,7 +221,7 @@ pub fn process_crosslinks(
/// 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> {
let current_epoch = state.current_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(
&state
.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)?;
@ -261,7 +261,7 @@ pub fn finish_epoch_update(state: &mut BeaconState, spec: &ChainSpec) -> Result<
let historical_batch: HistoricalBatch = state.historical_batch();
state
.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();

View File

@ -32,7 +32,7 @@ impl std::ops::AddAssign for Delta {
/// Apply attester and proposer rewards.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn apply_rewards(
state: &mut BeaconState,
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
/// attestation in the previous epoch.
///
/// Spec v0.5.0
/// Spec v0.5.1
fn get_proposer_deltas(
deltas: &mut Vec<Delta>,
state: &mut BeaconState,
@ -120,7 +120,7 @@ fn get_proposer_deltas(
/// Apply rewards for participation in attestations during the previous epoch.
///
/// Spec v0.5.0
/// Spec v0.5.1
fn get_justification_and_finalization_deltas(
deltas: &mut Vec<Delta>,
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.
///
/// Spec v0.5.0
/// Spec v0.5.1
fn compute_normal_justification_and_finalization_delta(
validator: &ValidatorStatus,
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.
///
/// Spec v0.5.0
/// Spec v0.5.1
fn compute_inactivity_leak_delta(
validator: &ValidatorStatus,
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.
///
/// Spec v0.5.0
/// Spec v0.5.1
fn get_crosslink_deltas(
deltas: &mut Vec<Delta>,
state: &BeaconState,
@ -295,7 +295,7 @@ fn get_crosslink_deltas(
/// Returns the base reward for some validator.
///
/// Spec v0.5.0
/// Spec v0.5.1
fn get_base_reward(
state: &BeaconState,
index: usize,
@ -312,7 +312,7 @@ fn get_base_reward(
/// Returns the inactivity penalty for some validator.
///
/// Spec v0.5.0
/// Spec v0.5.1
fn get_inactivity_penalty(
state: &BeaconState,
index: usize,
@ -328,7 +328,7 @@ fn get_inactivity_penalty(
/// 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 {
state.current_epoch(spec) + 1 - state.finalized_epoch
}

View File

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

View File

@ -5,7 +5,7 @@ use types::*;
/// Returns the distance between the first included attestation for some validator and this
/// slot.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn inclusion_distance(
state: &BeaconState,
attestations: &[&PendingAttestation],
@ -18,7 +18,7 @@ pub fn inclusion_distance(
/// Returns the slot of the earliest included attestation for some validator.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn inclusion_slot(
state: &BeaconState,
attestations: &[&PendingAttestation],
@ -31,7 +31,7 @@ pub fn inclusion_slot(
/// Finds the earliest included attestation for some validator.
///
/// Spec v0.5.0
/// Spec v0.5.1
fn earliest_included_attestation(
state: &BeaconState,
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
/// ``EJECTION_BALANCE``.
///
/// Spec v0.5.0
/// Spec v0.5.1
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
// active validator indices and mutate state in the one loop.

View File

@ -2,7 +2,7 @@ use types::*;
/// Process the exit queue.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn process_exit_queue(state: &mut BeaconState, spec: &ChainSpec) {
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`.
///
/// Spec v0.5.0
/// Spec v0.5.1
fn prepare_validator_for_withdrawal(
state: &mut BeaconState,
validator_index: usize,

View File

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

View File

@ -4,7 +4,7 @@ use types::*;
/// Peforms a validator registry update, if required.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn update_registry_and_shuffling_data(
state: &mut BeaconState,
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.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn should_update_validator_registry(
state: &BeaconState,
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.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn update_validator_registry(
state: &mut BeaconState,
current_total_balance: u64,
@ -133,7 +133,7 @@ pub fn update_validator_registry(
/// Activate the validator of the given ``index``.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn activate_validator(
state: &mut BeaconState,
validator_index: usize,

View File

@ -160,7 +160,7 @@ impl ValidatorStatuses {
/// - Active validators
/// - 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> {
let mut statuses = Vec::with_capacity(state.validator_registry.len());
let mut total_balances = TotalBalances::default();
@ -195,7 +195,7 @@ impl ValidatorStatuses {
/// Process some attestations from the given `state` updating the `statuses` and
/// `total_balances` fields.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn process_attestations(
&mut self,
state: &BeaconState,
@ -261,7 +261,7 @@ impl ValidatorStatuses {
/// Update the `statuses` for each validator based upon whether or not they attested to the
/// "winning" shard block root for the previous epoch.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn process_winning_roots(
&mut self,
state: &BeaconState,
@ -297,14 +297,14 @@ impl ValidatorStatuses {
/// Returns the distance between when the attestation was created and when it was included in a
/// block.
///
/// Spec v0.5.0
/// Spec v0.5.1
fn inclusion_distance(a: &PendingAttestation) -> Slot {
a.inclusion_slot - a.data.slot
}
/// 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 {
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
/// the first slot of the given epoch.
///
/// Spec v0.5.0
/// Spec v0.5.1
fn has_common_epoch_boundary_root(
a: &PendingAttestation,
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
/// the current slot of the `PendingAttestation`.
///
/// Spec v0.5.0
/// Spec v0.5.1
fn has_common_beacon_block_root(
a: &PendingAttestation,
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
/// 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 {
if self.total_attesting_balance > other.total_attesting_balance {
true
@ -34,7 +34,7 @@ impl WinningRoot {
/// The `WinningRoot` object also contains additional fields that are useful in later stages of
/// per-epoch processing.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn winning_root(
state: &BeaconState,
shard: u64,
@ -89,7 +89,7 @@ pub fn 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 {
if shard >= state.latest_crosslinks.len() as u64 {
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.
///
/// Spec v0.5.0
/// Spec v0.5.1
fn get_attesting_validator_indices(
state: &BeaconState,
shard: u64,

View File

@ -1,5 +1,5 @@
use crate::*;
use ssz::TreeHash;
use tree_hash::SignedRoot;
use types::*;
#[derive(Debug, PartialEq)]
@ -10,13 +10,9 @@ pub enum Error {
/// Advances a state forward by one slot, performing per-epoch processing if required.
///
/// Spec v0.5.0
pub fn per_slot_processing(
state: &mut BeaconState,
latest_block_header: &BeaconBlockHeader,
spec: &ChainSpec,
) -> Result<(), Error> {
cache_state(state, latest_block_header, spec)?;
/// Spec v0.5.1
pub fn per_slot_processing(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> {
cache_state(state, spec)?;
if (state.slot + 1) % spec.slots_per_epoch == 0 {
per_epoch_processing(state, spec)?;
@ -27,12 +23,8 @@ pub fn per_slot_processing(
Ok(())
}
fn cache_state(
state: &mut BeaconState,
latest_block_header: &BeaconBlockHeader,
spec: &ChainSpec,
) -> Result<(), Error> {
let previous_slot_state_root = Hash256::from_slice(&state.hash_tree_root()[..]);
fn cache_state(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> {
let previous_slot_state_root = state.update_tree_hash_cache()?;
// Note: increment the state slot here to allow use of our `state_root` and `block_root`
// getter/setter functions.
@ -46,7 +38,10 @@ fn cache_state(
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)?;
// 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_yaml;
#[cfg(not(debug_assertions))]
use state_processing::{
per_block_processing, per_block_processing_without_verifying_block_signature,
per_slot_processing,
};
use state_processing::{per_block_processing, per_slot_processing};
use std::{fs::File, io::prelude::*, path::PathBuf};
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)]
pub struct TestCase {
@ -17,6 +62,7 @@ pub struct TestCase {
pub verify_signatures: bool,
pub initial_state: BeaconState,
pub blocks: Vec<BeaconBlock>,
pub expected_state: ExpectedState,
}
#[derive(Debug, Deserialize)]
@ -27,82 +73,81 @@ pub struct TestDoc {
pub test_cases: Vec<TestCase>,
}
#[test]
fn test_read_yaml() {
// Test sanity-check_small-config_32-vals.yaml
fn load_test_case(test_name: &str) -> TestDoc {
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");
file_path_buf.push(format!("yaml_utils/specs/{}", test_name));
File::open(file_path_buf).unwrap()
};
let mut yaml_str = String::new();
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();
serde_yaml::from_str(&yaml_str.as_str()).unwrap()
}
// Test sanity-check_default-config_100-vals.yaml
file = {
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");
fn run_state_transition_test(test_name: &str) {
let doc = load_test_case(test_name);
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();
let _doc: TestDoc = serde_yaml::from_str(&yaml_str.as_str()).unwrap();
#[test]
#[cfg(not(debug_assertions))]
fn test_read_yaml() {
load_test_case("sanity-check_small-config_32-vals.yaml");
load_test_case("sanity-check_default-config_100-vals.yaml");
}
#[test]
#[cfg(not(debug_assertions))]
fn run_state_transition_tests_small() {
// 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");
File::open(file_path_buf).unwrap()
};
let mut yaml_str = String::new();
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);
}
}
}
}
run_state_transition_test("sanity-check_small-config_32-vals.yaml");
}
// Run with --ignored to run this test
#[test]
#[ignore]
fn run_state_transition_tests_large() {
run_state_transition_test("sanity-check_default-config_100-vals.yaml");
}

View File

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

View File

@ -1,5 +1,4 @@
extern crate reqwest;
extern crate tempdir;
use std::fs::File;
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]
bls = { path = "../utils/bls" }
boolean-bitfield = { path = "../utils/boolean-bitfield" }
cached_tree_hash = { path = "../utils/cached_tree_hash" }
dirs = "1.0"
derivative = "1.0"
ethereum-types = "0.5"
@ -26,6 +27,8 @@ ssz = { path = "../utils/ssz" }
ssz_derive = { path = "../utils/ssz_derive" }
swap_or_not_shuffle = { path = "../utils/swap_or_not_shuffle" }
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" }
[dev-dependencies]

View File

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

View File

@ -2,12 +2,13 @@ use super::AttestationData;
use crate::test_utils::TestRandom;
use rand::RngCore;
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.
///
/// Spec v0.5.0
#[derive(Debug, Clone, PartialEq, Default, Serialize, Encode, Decode, TreeHash)]
/// Spec v0.5.1
#[derive(Debug, Clone, PartialEq, Default, Serialize, Encode, Decode, TreeHash, CachedTreeHash)]
pub struct AttestationDataAndCustodyBit {
pub data: AttestationData,
pub custody_bit: bool,
@ -27,4 +28,5 @@ mod test {
use super::*;
ssz_tests!(AttestationDataAndCustodyBit);
cached_tree_hash_tests!(AttestationDataAndCustodyBit);
}

View File

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

View File

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

View File

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

View File

@ -3,13 +3,14 @@ use crate::*;
use bls::Signature;
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz::TreeHash;
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash::{SignedRoot, TreeHash};
use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// A header of a `BeaconBlock`.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(
Debug,
PartialEq,
@ -19,6 +20,7 @@ use test_random_derive::TestRandom;
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
SignedRoot,
)]
@ -27,20 +29,21 @@ pub struct BeaconBlockHeader {
pub previous_block_root: Hash256,
pub state_root: Hash256,
pub block_body_root: Hash256,
#[signed_root(skip_hashing)]
pub signature: Signature,
}
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 {
Hash256::from_slice(&self.hash_tree_root()[..])
Hash256::from_slice(&self.signed_root()[..])
}
/// 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 {
BeaconBlock {
slot: self.slot,
@ -57,4 +60,5 @@ mod tests {
use super::*;
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 crate::test_utils::TestRandom;
use crate::*;
use cached_tree_hash::{Error as TreeHashCacheError, TreeHashCache};
use int_to_bytes::int_to_bytes32;
use pubkey_cache::PubkeyCache;
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz::{hash, ssz_encode, TreeHash};
use ssz_derive::{Decode, Encode, TreeHash};
use ssz::{hash, ssz_encode};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash::TreeHash;
use tree_hash_derive::{CachedTreeHash, TreeHash};
mod epoch_cache;
mod pubkey_cache;
@ -40,12 +43,24 @@ pub enum Error {
EpochCacheUninitialized(RelativeEpoch),
RelativeEpochError(RelativeEpochError),
EpochCacheError(EpochCacheError),
TreeHashCacheError(TreeHashCacheError),
}
/// The state of the `BeaconChain` at some slot.
///
/// Spec v0.5.0
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, TestRandom, Encode, Decode, TreeHash)]
/// Spec v0.5.1
#[derive(
Debug,
PartialEq,
Clone,
Serialize,
Deserialize,
TestRandom,
Encode,
Decode,
TreeHash,
CachedTreeHash,
)]
pub struct BeaconState {
// Misc
pub slot: Slot,
@ -58,7 +73,7 @@ pub struct BeaconState {
pub validator_registry_update_epoch: Epoch,
// Randomness and committees
pub latest_randao_mixes: Vec<Hash256>,
pub latest_randao_mixes: TreeHashVector<Hash256>,
pub previous_shuffling_start_shard: u64,
pub current_shuffling_start_shard: u64,
pub previous_shuffling_epoch: Epoch,
@ -78,11 +93,11 @@ pub struct BeaconState {
pub finalized_root: Hash256,
// Recent state
pub latest_crosslinks: Vec<Crosslink>,
latest_block_roots: Vec<Hash256>,
latest_state_roots: Vec<Hash256>,
latest_active_index_roots: Vec<Hash256>,
latest_slashed_balances: Vec<u64>,
pub latest_crosslinks: TreeHashVector<Crosslink>,
pub latest_block_roots: TreeHashVector<Hash256>,
latest_state_roots: TreeHashVector<Hash256>,
latest_active_index_roots: TreeHashVector<Hash256>,
latest_slashed_balances: TreeHashVector<u64>,
pub latest_block_header: BeaconBlockHeader,
pub historical_roots: Vec<Hash256>,
@ -110,6 +125,12 @@ pub struct BeaconState {
#[tree_hash(skip_hashing)]
#[test_random(default)]
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 {
@ -118,7 +139,7 @@ impl BeaconState {
/// 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`.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn genesis(genesis_time: u64, latest_eth1_data: Eth1Data, spec: &ChainSpec) -> BeaconState {
let initial_crosslink = Crosslink {
epoch: spec.genesis_epoch,
@ -137,7 +158,8 @@ impl BeaconState {
validator_registry_update_epoch: spec.genesis_epoch,
// 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,
current_shuffling_start_shard: spec.genesis_start_shard,
previous_shuffling_epoch: spec.genesis_epoch,
@ -157,11 +179,12 @@ impl BeaconState {
finalized_root: spec.zero_hash,
// Recent state
latest_crosslinks: vec![initial_crosslink; spec.shard_count as usize],
latest_block_roots: vec![spec.zero_hash; spec.slots_per_historical_root],
latest_state_roots: vec![spec.zero_hash; spec.slots_per_historical_root],
latest_active_index_roots: vec![spec.zero_hash; spec.latest_active_index_roots_length],
latest_slashed_balances: vec![0; spec.latest_slashed_exit_length],
latest_crosslinks: vec![initial_crosslink; spec.shard_count as usize].into(),
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].into(),
latest_active_index_roots: vec![spec.zero_hash; spec.latest_active_index_roots_length]
.into(),
latest_slashed_balances: vec![0; spec.latest_slashed_exit_length].into(),
latest_block_header: BeaconBlock::empty(spec).temporary_block_header(spec),
historical_roots: vec![],
@ -183,14 +206,15 @@ impl BeaconState {
EpochCache::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 {
Hash256::from_slice(&self.hash_tree_root()[..])
Hash256::from_slice(&self.tree_hash_root()[..])
}
pub fn historical_batch(&self) -> HistoricalBatch {
@ -217,7 +241,7 @@ impl BeaconState {
/// The epoch corresponding to `self.slot`.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn current_epoch(&self, spec: &ChainSpec) -> 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.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn previous_epoch(&self, spec: &ChainSpec) -> Epoch {
self.current_epoch(&spec) - 1
}
/// The epoch following `self.current_epoch()`.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn next_epoch(&self, spec: &ChainSpec) -> Epoch {
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.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_cached_active_validator_indices(
&self,
relative_epoch: RelativeEpoch,
@ -261,7 +285,7 @@ impl BeaconState {
///
/// 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> {
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.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_crosslink_committees_at_slot(
&self,
slot: Slot,
@ -295,7 +319,7 @@ impl BeaconState {
///
/// 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(
&self,
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.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_beacon_proposer_index(
&self,
slot: Slot,
@ -350,7 +374,7 @@ impl BeaconState {
/// 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> {
if (slot < self.slot) && (self.slot <= slot + spec.slots_per_historical_root as u64) {
let i = slot.as_usize() % spec.slots_per_historical_root;
@ -366,7 +390,7 @@ impl BeaconState {
/// Return the block root at a recent `slot`.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_block_root(
&self,
slot: Slot,
@ -378,7 +402,7 @@ impl BeaconState {
/// Sets the block root for some given slot.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn set_block_root(
&mut self,
slot: Slot,
@ -392,7 +416,7 @@ impl BeaconState {
/// 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> {
let current_epoch = self.current_epoch(spec);
@ -416,7 +440,7 @@ impl BeaconState {
///
/// See `Self::get_randao_mix`.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn update_randao_mix(
&mut self,
epoch: Epoch,
@ -434,7 +458,7 @@ impl BeaconState {
/// 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> {
let i = self.get_randao_mix_index(epoch, spec)?;
Ok(&self.latest_randao_mixes[i])
@ -442,7 +466,7 @@ impl BeaconState {
/// Set the randao mix at a recent ``epoch``.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn set_randao_mix(
&mut self,
epoch: Epoch,
@ -456,7 +480,7 @@ impl BeaconState {
/// 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> {
let current_epoch = self.current_epoch(spec);
@ -478,7 +502,7 @@ impl BeaconState {
/// 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> {
let i = self.get_active_index_root_index(epoch, spec)?;
Ok(self.latest_active_index_roots[i])
@ -486,7 +510,7 @@ impl BeaconState {
/// Set the `active_index_root` at a recent `epoch`.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn set_active_index_root(
&mut self,
epoch: Epoch,
@ -500,15 +524,15 @@ impl BeaconState {
/// 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) {
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`.
///
/// Spec v0.5.0
/// Spec v0.5.1
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) {
let i = slot.as_usize() % spec.slots_per_historical_root;
@ -524,7 +548,7 @@ impl BeaconState {
/// 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> {
let i = self.get_latest_state_roots_index(slot, spec)?;
Ok(&self.latest_state_roots[i])
@ -532,7 +556,7 @@ impl BeaconState {
/// Sets the latest state root for slot.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn set_state_root(
&mut self,
slot: Slot,
@ -546,7 +570,7 @@ impl BeaconState {
/// 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> {
let i = epoch.as_usize() % spec.latest_slashed_exit_length;
@ -561,7 +585,7 @@ impl BeaconState {
/// 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> {
let i = self.get_slashed_balance_index(epoch, spec)?;
Ok(self.latest_slashed_balances[i])
@ -569,7 +593,7 @@ impl BeaconState {
/// Sets the total slashed balances for some epoch.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn set_slashed_balance(
&mut self,
epoch: Epoch,
@ -583,7 +607,7 @@ impl BeaconState {
/// 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> {
let mut input = self
.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``.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_effective_balance(
&self,
validator_index: usize,
@ -614,14 +638,14 @@ impl BeaconState {
/// 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 {
epoch + 1 + spec.activation_exit_delay
}
/// 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) {
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.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_attestation_duties(
&self,
validator_index: usize,
@ -649,7 +673,7 @@ impl BeaconState {
/// Return the combined effective balance of an array of validators.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_total_balance(
&self,
validator_indices: &[usize],
@ -668,6 +692,7 @@ impl BeaconState {
self.build_epoch_cache(RelativeEpoch::NextWithoutRegistryChange, spec)?;
self.build_epoch_cache(RelativeEpoch::NextWithRegistryChange, spec)?;
self.update_pubkey_cache()?;
self.update_tree_hash_cache()?;
Ok(())
}
@ -774,6 +799,39 @@ impl BeaconState {
pub fn drop_pubkey_cache(&mut self) {
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 {
@ -787,3 +845,9 @@ impl From<EpochCacheError> for Error {
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
/// `epoch`.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_active_validator_indices(validators: &[Validator], epoch: Epoch) -> Vec<usize> {
let mut active = Vec::with_capacity(validators.len());
@ -288,7 +288,7 @@ impl EpochCrosslinkCommitteesBuilder {
self.active_validator_indices,
spec.shuffle_round_count,
&self.shuffling_seed[..],
true,
false,
)
.ok_or_else(|| Error::UnableToShuffle)?
};

View File

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

View File

@ -3,6 +3,7 @@ use super::*;
use crate::test_utils::*;
ssz_tests!(BeaconState);
cached_tree_hash_tests!(BeaconState);
/// Test that
///
@ -55,3 +56,22 @@ fn cache_initialization() {
test_cache_initialization(&mut state, RelativeEpoch::NextWithRegistryChange, &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.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub enum Domain {
BeaconBlock,
Randao,
@ -20,7 +20,7 @@ pub enum Domain {
/// Holds all the "constants" for a BeaconChain.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(PartialEq, Debug, Clone, Deserialize)]
#[serde(default)]
pub struct ChainSpec {
@ -126,7 +126,7 @@ pub struct ChainSpec {
impl ChainSpec {
/// 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 {
std::cmp::max(
1,
@ -139,7 +139,7 @@ impl ChainSpec {
/// 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 {
let domain_constant = match domain {
Domain::BeaconBlock => self.domain_beacon_block,
@ -161,7 +161,7 @@ impl ChainSpec {
/// Returns a `ChainSpec` compatible with the Ethereum Foundation specification.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn foundation() -> Self {
let genesis_slot = Slot::new(2_u64.pow(32));
let slots_per_epoch = 64;

View File

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

View File

@ -1,8 +1,20 @@
use crate::*;
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 slot: Slot,
pub shard: Shard,

View File

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

View File

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

View File

@ -3,13 +3,14 @@ use crate::*;
use bls::{PublicKey, Signature};
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz::{SignedRoot, TreeHash};
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use ssz_derive::{Decode, Encode};
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.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(
Debug,
PartialEq,
@ -20,18 +21,20 @@ use test_random_derive::TestRandom;
Decode,
SignedRoot,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct DepositInput {
pub pubkey: PublicKey,
pub withdrawal_credentials: Hash256,
#[signed_root(skip_hashing)]
pub proof_of_possession: Signature,
}
impl DepositInput {
/// 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(
&self,
secret_key: &SecretKey,
@ -47,7 +50,7 @@ impl DepositInput {
/// Verify that proof-of-possession is valid.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn validate_proof_of_possession(
&self,
epoch: Epoch,
@ -66,6 +69,7 @@ mod tests {
use super::*;
ssz_tests!(DepositInput);
cached_tree_hash_tests!(DepositInput);
#[test]
fn can_create_and_validate() {

View File

@ -2,14 +2,25 @@ use super::Hash256;
use crate::test_utils::TestRandom;
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Contains data obtained from the Eth1 chain.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[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 deposit_root: Hash256,
@ -21,4 +32,5 @@ mod tests {
use super::*;
ssz_tests!(Eth1Data);
cached_tree_hash_tests!(Eth1Data);
}

View File

@ -2,14 +2,25 @@ use super::Eth1Data;
use crate::test_utils::TestRandom;
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// A summation of votes for some `Eth1Data`.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[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 eth1_data: Eth1Data,
@ -21,4 +32,5 @@ mod tests {
use super::*;
ssz_tests!(Eth1DataVote);
cached_tree_hash_tests!(Eth1DataVote);
}

View File

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

View File

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

View File

@ -27,6 +27,7 @@ pub mod pending_attestation;
pub mod proposer_slashing;
pub mod slashable_attestation;
pub mod transfer;
pub mod tree_hash_vector;
pub mod voluntary_exit;
#[macro_use]
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_height::SlotHeight;
pub use crate::transfer::Transfer;
pub use crate::tree_hash_vector::TreeHashVector;
pub use crate::validator::Validator;
pub use crate::voluntary_exit::VoluntaryExit;

View File

@ -2,13 +2,25 @@ use crate::test_utils::TestRandom;
use crate::{Attestation, AttestationData, Bitfield, Slot};
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash};
use ssz_derive::{Decode, Encode};
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.
///
/// Spec v0.5.0
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
/// Spec v0.5.1
#[derive(
Debug,
Clone,
PartialEq,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct PendingAttestation {
pub aggregation_bitfield: Bitfield,
pub data: AttestationData,
@ -33,4 +45,5 @@ mod tests {
use super::*;
ssz_tests!(PendingAttestation);
cached_tree_hash_tests!(PendingAttestation);
}

View File

@ -2,13 +2,25 @@ use super::BeaconBlockHeader;
use crate::test_utils::TestRandom;
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Two conflicting proposals from the same proposer (validator).
///
/// Spec v0.5.0
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
/// Spec v0.5.1
#[derive(
Debug,
PartialEq,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct ProposerSlashing {
pub proposer_index: u64,
pub header_1: BeaconBlockHeader,
@ -20,4 +32,5 @@ mod tests {
use super::*;
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
/// to and following some epoch.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum RelativeEpoch {
/// The prior epoch.
@ -32,7 +32,7 @@ pub enum RelativeEpoch {
impl RelativeEpoch {
/// 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 {
match self {
RelativeEpoch::Previous => base - 1,
@ -51,7 +51,7 @@ impl RelativeEpoch {
/// - `AmbiguiousNextEpoch` whenever `other` is one after `base`, because it's unknowable if
/// 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> {
if other == base - 1 {
Ok(RelativeEpoch::Previous)

View File

@ -1,15 +1,16 @@
use crate::{test_utils::TestRandom, AggregateSignature, AttestationData, Bitfield, ChainSpec};
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz::TreeHash;
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash::TreeHash;
use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// Details an attestation that can be slashable.
///
/// To be included in an `AttesterSlashing`.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(
Debug,
PartialEq,
@ -19,6 +20,7 @@ use test_random_derive::TestRandom;
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
SignedRoot,
)]
@ -27,20 +29,21 @@ pub struct SlashableAttestation {
pub validator_indices: Vec<u64>,
pub data: AttestationData,
pub custody_bitfield: Bitfield,
#[signed_root(skip_hashing)]
pub aggregate_signature: AggregateSignature,
}
impl SlashableAttestation {
/// 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 {
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``.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn is_surround_vote(&self, other: &SlashableAttestation, spec: &ChainSpec) -> bool {
let source_epoch_1 = self.data.source_epoch;
let source_epoch_2 = other.data.source_epoch;
@ -131,6 +134,7 @@ mod tests {
}
ssz_tests!(SlashableAttestation);
cached_tree_hash_tests!(SlashableAttestation);
fn create_slashable_attestation(
slot_factor: u64,

View File

@ -14,7 +14,7 @@ use crate::test_utils::TestRandom;
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
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::fmt;
use std::hash::{Hash, Hasher};

View File

@ -206,11 +206,41 @@ macro_rules! impl_ssz {
}
}
impl TreeHash for $type {
fn hash_tree_root(&self) -> Vec<u8> {
let mut result: Vec<u8> = vec![];
result.append(&mut self.0.hash_tree_root());
hash(&result)
impl tree_hash::TreeHash for $type {
fn tree_hash_type() -> tree_hash::TreeHashType {
tree_hash::TreeHashType::Basic
}
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_tests!($type);
ssz_tests!($type);
cached_tree_hash_tests!($type);
mod u64_tests {
use super::*;

View File

@ -2,7 +2,7 @@ use crate::slot_epoch::{Epoch, Slot};
use crate::test_utils::TestRandom;
use rand::RngCore;
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::fmt;
use std::hash::{Hash, Hasher};

View File

@ -17,14 +17,14 @@ macro_rules! ssz_tests {
}
#[test]
pub fn test_hash_tree_root() {
pub fn test_tree_hash_root() {
use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng};
use ssz::TreeHash;
use tree_hash::TreeHash;
let mut rng = XorShiftRng::from_seed([42; 16]);
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);
// 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_keypairs;
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 test_random::TestRandom;
pub use testing_attestation_builder::TestingAttestationBuilder;

View File

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

View File

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

View File

@ -1,5 +1,5 @@
use crate::*;
use ssz::TreeHash;
use tree_hash::TreeHash;
/// Builds an `AttesterSlashing`.
///
@ -66,7 +66,7 @@ impl TestingAttesterSlashingBuilder {
data: attestation.data.clone(),
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() {
attestation.custody_bitfield.set(i, false);

View File

@ -6,7 +6,7 @@ use crate::{
*,
};
use rayon::prelude::*;
use ssz::{SignedRoot, TreeHash};
use tree_hash::{SignedRoot, TreeHash};
/// 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.
pub fn set_randao_reveal(&mut self, sk: &SecretKey, fork: &Fork, spec: &ChainSpec) {
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);
self.block.body.randao_reveal = Signature::new(&message, domain, sk);
}

View File

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

View File

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

View File

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

View File

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

View File

@ -4,13 +4,14 @@ use bls::{PublicKey, Signature};
use derivative::Derivative;
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz::TreeHash;
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash::TreeHash;
use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// The data submitted to the deposit contract.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(
Debug,
Clone,
@ -19,6 +20,7 @@ use test_random_derive::TestRandom;
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
SignedRoot,
Derivative,
@ -32,6 +34,7 @@ pub struct Transfer {
pub slot: Slot,
pub pubkey: PublicKey,
#[derivative(Hash = "ignore")]
#[signed_root(skip_hashing)]
pub signature: Signature,
}
@ -40,4 +43,5 @@ mod tests {
use super::*;
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 rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Information about a `BeaconChain` validator.
///
/// Spec v0.5.0
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TestRandom, TreeHash)]
/// Spec v0.5.1
#[derive(
Debug,
Clone,
PartialEq,
Serialize,
Deserialize,
Encode,
Decode,
TestRandom,
TreeHash,
CachedTreeHash,
)]
pub struct Validator {
pub pubkey: PublicKey,
pub withdrawal_credentials: Hash256,
@ -110,4 +122,5 @@ mod tests {
}
ssz_tests!(Validator);
cached_tree_hash_tests!(Validator);
}

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