diff --git a/.circleci/config.yml b/.circleci/config.yml index 0e3bca25b..ee523c98d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -18,7 +18,12 @@ jobs: keys: - v1-gradle-dir-{{ checksum "build.gradle" }} - v1-gradle-dir- - + - run: + name: Install git-lfs for submodules with large files + command: | + sudo sh -c "echo 'deb http://ftp.debian.org/debian stretch-backports main' >> /etc/apt/sources.list" + curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash + sudo apt-get update && sudo apt-get install -y git-lfs - run: name: Downloading dependencies command: ./gradlew allDependencies diff --git a/.gitmodules b/.gitmodules index de4e57278..0b4451122 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ -[submodule "test/src/test/resources/eth2.0-tests"] - path = test/src/test/resources/eth2.0-tests - url = https://github.com/ethereum/eth2.0-tests.git [submodule "crypto/src/main/resources/bls-key-pairs"] path = crypto/src/main/resources/bls-key-pairs url = https://github.com/harmony-dev/bls-key-pairs +[submodule "test/src/test/resources/eth2.0-spec-tests"] + path = test/src/test/resources/eth2.0-spec-tests + url = https://github.com/ethereum/eth2.0-spec-tests.git diff --git a/consensus/src/main/java/org/ethereum/beacon/consensus/spec/EpochProcessing.java b/consensus/src/main/java/org/ethereum/beacon/consensus/spec/EpochProcessing.java index 47f52e49a..81104ca3e 100644 --- a/consensus/src/main/java/org/ethereum/beacon/consensus/spec/EpochProcessing.java +++ b/consensus/src/main/java/org/ethereum/beacon/consensus/spec/EpochProcessing.java @@ -293,8 +293,7 @@ def process_crosslinks(state: BeaconState) -> None: state.current_crosslinks[shard] = winning_crosslink */ default void process_crosslinks(MutableBeaconState state) { - state.getPreviousCrosslinks().clear(); - state.getPreviousCrosslinks().addAll(state.getCurrentCrosslinks().listCopy()); + state.getPreviousCrosslinks().replaceAll(state.getCurrentCrosslinks().listCopy()); for (EpochNumber epoch : get_previous_epoch(state).iterateTo(get_current_epoch(state).increment())) { for (UInt64 offset : UInt64s.iterate(UInt64.ZERO, get_epoch_committee_count(state, epoch))) { @@ -694,8 +693,7 @@ default void process_final_updates(MutableBeaconState state) { /* Rotate current/previous epoch attestations state.previous_epoch_attestations = state.current_epoch_attestations state.current_epoch_attestations = [] */ - state.getPreviousEpochAttestations().clear(); - state.getPreviousEpochAttestations().addAll(state.getCurrentEpochAttestations().listCopy()); + state.getPreviousEpochAttestations().replaceAll(state.getCurrentEpochAttestations().listCopy()); state.getCurrentEpochAttestations().clear(); } } diff --git a/consensus/src/main/java/org/ethereum/beacon/consensus/spec/HelperFunction.java b/consensus/src/main/java/org/ethereum/beacon/consensus/spec/HelperFunction.java index e135904f3..5e6faec59 100644 --- a/consensus/src/main/java/org/ethereum/beacon/consensus/spec/HelperFunction.java +++ b/consensus/src/main/java/org/ethereum/beacon/consensus/spec/HelperFunction.java @@ -484,10 +484,15 @@ def compute_committee(indices: List[ValidatorIndex], seed: Bytes32, index: int, default List compute_committee(List indices, Bytes32 seed, UInt64 index, UInt64 count) { UInt64 start = index.times(indices.size()).dividedBy(count); UInt64 end = index.increment().times(indices.size()).dividedBy(count); + + return compute_committee(indices, start, end, seed); + } + + default List compute_committee(List validator_indices, UInt64 start, UInt64 end, Bytes32 seed) { List result = new ArrayList<>(); for (UInt64 i = start; i.compareTo(end) < 0; i = i.increment()) { - UInt64 shuffled_index = get_shuffled_index(i, UInt64.valueOf(indices.size()), seed); - result.add(indices.get(shuffled_index.getIntValue())); + UInt64 shuffled_index = get_shuffled_index(i, UInt64.valueOf(validator_indices.size()), seed); + result.add(validator_indices.get(shuffled_index.getIntValue())); } return result; } @@ -497,9 +502,15 @@ default List compute_committee(List indices, Byt * Based on {@link #get_permuted_list(List, Bytes32)}. */ default List compute_committee2(List indices, Bytes32 seed, UInt64 index, UInt64 count) { - List shuffled_indices = get_permuted_list(indices, seed) + UInt64 start = index.times(indices.size()).dividedBy(count); + UInt64 end = index.increment().times(indices.size()).dividedBy(count); + return compute_committee2(indices, start, end, seed); + } + + default List compute_committee2(List validator_indices, UInt64 start, UInt64 end, Bytes32 seed) { + List shuffled_indices = get_permuted_list(validator_indices, seed) .stream().map(ValidatorIndex::new).collect(toList()); - return split(shuffled_indices, count.getIntValue()).get(index.getIntValue()); + return shuffled_indices.subList(start.intValue(), end.intValue()); } /* diff --git a/consensus/src/main/java/org/ethereum/beacon/consensus/spec/SpecCommons.java b/consensus/src/main/java/org/ethereum/beacon/consensus/spec/SpecCommons.java index e14d135b3..0e1b8636c 100644 --- a/consensus/src/main/java/org/ethereum/beacon/consensus/spec/SpecCommons.java +++ b/consensus/src/main/java/org/ethereum/beacon/consensus/spec/SpecCommons.java @@ -1,6 +1,5 @@ package org.ethereum.beacon.consensus.spec; -import java.util.function.Function; import org.ethereum.beacon.consensus.hasher.ObjectHasher; import org.ethereum.beacon.core.BeaconState; import org.ethereum.beacon.core.spec.SpecConstants; @@ -9,6 +8,8 @@ import tech.pegasys.artemis.ethereum.core.Hash32; import tech.pegasys.artemis.util.bytes.BytesValue; +import java.util.function.Function; + /** * A common part of the spec that is shared by all its components. */ @@ -42,5 +43,17 @@ default void checkShardRange(ShardNumber shard) { assertTrue(shard.less(getConstants().getShardCount())); } - class SpecAssertionFailed extends RuntimeException {} + class SpecAssertionFailed extends RuntimeException { + @Override + public String getMessage() { + return toString(); + } + + @Override + public String toString() { + return String.format( + "SpecAssertionFailed{%s}", + getStackTrace().length > 1 ? getStackTrace()[1].toString() : ""); + } + } } diff --git a/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/AttestationVerifier.java b/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/AttestationVerifier.java index d8954169f..66afab281 100644 --- a/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/AttestationVerifier.java +++ b/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/AttestationVerifier.java @@ -1,6 +1,7 @@ package org.ethereum.beacon.consensus.verifier.operation; import org.ethereum.beacon.consensus.BeaconChainSpec; +import org.ethereum.beacon.consensus.spec.SpecCommons; import org.ethereum.beacon.consensus.verifier.OperationVerifier; import org.ethereum.beacon.consensus.verifier.VerificationResult; import org.ethereum.beacon.core.BeaconState; @@ -27,7 +28,7 @@ public VerificationResult verify(Attestation attestation, BeaconState state) { try { spec.verify_attestation(state, attestation); return VerificationResult.PASSED; - } catch (Exception e) { + } catch (SpecCommons.SpecAssertionFailed e) { return VerificationResult.failedResult(e.getMessage()); } } diff --git a/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/AttesterSlashingVerifier.java b/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/AttesterSlashingVerifier.java index 65b89e545..c9a440b06 100644 --- a/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/AttesterSlashingVerifier.java +++ b/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/AttesterSlashingVerifier.java @@ -1,6 +1,7 @@ package org.ethereum.beacon.consensus.verifier.operation; import org.ethereum.beacon.consensus.BeaconChainSpec; +import org.ethereum.beacon.consensus.spec.SpecCommons; import org.ethereum.beacon.consensus.verifier.OperationVerifier; import org.ethereum.beacon.consensus.verifier.VerificationResult; import org.ethereum.beacon.core.BeaconState; @@ -27,7 +28,7 @@ public VerificationResult verify(AttesterSlashing attesterSlashing, BeaconState try { spec.verify_attester_slashing(state, attesterSlashing); return VerificationResult.PASSED; - } catch (Exception e) { + } catch (SpecCommons.SpecAssertionFailed e) { return VerificationResult.failedResult(e.getMessage()); } } diff --git a/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/DepositVerifier.java b/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/DepositVerifier.java index 52856fe05..245510d36 100644 --- a/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/DepositVerifier.java +++ b/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/DepositVerifier.java @@ -1,6 +1,7 @@ package org.ethereum.beacon.consensus.verifier.operation; import org.ethereum.beacon.consensus.BeaconChainSpec; +import org.ethereum.beacon.consensus.spec.SpecCommons; import org.ethereum.beacon.consensus.verifier.OperationVerifier; import org.ethereum.beacon.consensus.verifier.VerificationResult; import org.ethereum.beacon.core.BeaconState; @@ -30,7 +31,7 @@ public VerificationResult verify(Deposit deposit, BeaconState state) { try { spec.verify_deposit(state, deposit); return VerificationResult.PASSED; - } catch (Exception e) { + } catch (SpecCommons.SpecAssertionFailed e) { return VerificationResult.failedResult(e.getMessage()); } } diff --git a/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/ProposerSlashingVerifier.java b/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/ProposerSlashingVerifier.java index c58c592ef..50a057d90 100644 --- a/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/ProposerSlashingVerifier.java +++ b/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/ProposerSlashingVerifier.java @@ -1,6 +1,7 @@ package org.ethereum.beacon.consensus.verifier.operation; import org.ethereum.beacon.consensus.BeaconChainSpec; +import org.ethereum.beacon.consensus.spec.SpecCommons; import org.ethereum.beacon.consensus.verifier.OperationVerifier; import org.ethereum.beacon.consensus.verifier.VerificationResult; import org.ethereum.beacon.core.BeaconState; @@ -27,7 +28,7 @@ public VerificationResult verify(ProposerSlashing proposerSlashing, BeaconState try { spec.verify_proposer_slashing(state, proposerSlashing); return VerificationResult.PASSED; - } catch (Exception e) { + } catch (SpecCommons.SpecAssertionFailed e) { return VerificationResult.failedResult(e.getMessage()); } } diff --git a/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/TransferVerifier.java b/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/TransferVerifier.java index 67eafc159..6e04f9070 100644 --- a/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/TransferVerifier.java +++ b/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/TransferVerifier.java @@ -1,6 +1,7 @@ package org.ethereum.beacon.consensus.verifier.operation; import org.ethereum.beacon.consensus.BeaconChainSpec; +import org.ethereum.beacon.consensus.spec.SpecCommons; import org.ethereum.beacon.consensus.verifier.OperationVerifier; import org.ethereum.beacon.consensus.verifier.VerificationResult; import org.ethereum.beacon.core.BeaconState; @@ -26,7 +27,7 @@ public VerificationResult verify(Transfer transfer, BeaconState state) { try { spec.verify_transfer(state, transfer); return VerificationResult.PASSED; - } catch (Exception e) { + } catch (SpecCommons.SpecAssertionFailed e) { return VerificationResult.failedResult(e.getMessage()); } } diff --git a/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/VoluntaryExitVerifier.java b/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/VoluntaryExitVerifier.java index 2c4abc20c..fb8280be1 100644 --- a/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/VoluntaryExitVerifier.java +++ b/consensus/src/main/java/org/ethereum/beacon/consensus/verifier/operation/VoluntaryExitVerifier.java @@ -1,6 +1,7 @@ package org.ethereum.beacon.consensus.verifier.operation; import org.ethereum.beacon.consensus.BeaconChainSpec; +import org.ethereum.beacon.consensus.spec.SpecCommons; import org.ethereum.beacon.consensus.verifier.OperationVerifier; import org.ethereum.beacon.consensus.verifier.VerificationResult; import org.ethereum.beacon.core.BeaconState; @@ -27,7 +28,7 @@ public VerificationResult verify(VoluntaryExit voluntaryExit, BeaconState state) try { spec.verify_voluntary_exit(state, voluntaryExit); return VerificationResult.PASSED; - } catch (Exception e) { + } catch (SpecCommons.SpecAssertionFailed e) { return VerificationResult.failedResult(e.getMessage()); } } diff --git a/start/config/src/main/java/org/ethereum/beacon/emulator/config/chainspec/SpecBuilder.java b/start/config/src/main/java/org/ethereum/beacon/emulator/config/chainspec/SpecBuilder.java index 7436e338d..1ba2f4c4d 100644 --- a/start/config/src/main/java/org/ethereum/beacon/emulator/config/chainspec/SpecBuilder.java +++ b/start/config/src/main/java/org/ethereum/beacon/emulator/config/chainspec/SpecBuilder.java @@ -253,7 +253,7 @@ public EpochNumber getMinValidatorWithdrawabilityDelay() { @Override public EpochNumber getGenesisEpoch() { - return initialValues.getGenesisEpoch(); + return getGenesisSlot().dividedBy(getSlotsPerEpoch()); } @Override diff --git a/test/build.gradle b/test/build.gradle index 54db7f41a..f6d18e70c 100644 --- a/test/build.gradle +++ b/test/build.gradle @@ -17,6 +17,7 @@ dependencies { task submodulesUpdate(type:Exec) { description 'Updates (and inits) git submodules' + commandLine 'git', 'lfs', 'install' commandLine 'git', 'submodule', 'update', '--init', '--recursive' group 'Build Setup' } diff --git a/test/src/test/java/org/ethereum/beacon/test/BlsTests.java b/test/src/test/java/org/ethereum/beacon/test/BlsTests.java index b29a49e60..1ec480566 100644 --- a/test/src/test/java/org/ethereum/beacon/test/BlsTests.java +++ b/test/src/test/java/org/ethereum/beacon/test/BlsTests.java @@ -1,14 +1,17 @@ package org.ethereum.beacon.test; -import org.ethereum.beacon.consensus.BeaconChainSpec; import org.ethereum.beacon.test.runner.bls.BlsAggregatePubKeys; import org.ethereum.beacon.test.runner.bls.BlsAggregateSigs; import org.ethereum.beacon.test.runner.bls.BlsMessageHash; import org.ethereum.beacon.test.runner.bls.BlsMessageHashCompressed; import org.ethereum.beacon.test.runner.bls.BlsPrivateToPublic; import org.ethereum.beacon.test.runner.bls.BlsSignMessage; -import org.ethereum.beacon.test.type.bls.BlsTest; -import org.ethereum.beacon.test.type.UniversalTest; +import org.ethereum.beacon.test.type.bls.BlsAggregatePubKeysTest; +import org.ethereum.beacon.test.type.bls.BlsAggregateSigsTest; +import org.ethereum.beacon.test.type.bls.BlsMessageHashCompressedTest; +import org.ethereum.beacon.test.type.bls.BlsMessageHashTest; +import org.ethereum.beacon.test.type.bls.BlsPrivateToPublicTest; +import org.ethereum.beacon.test.type.bls.BlsSignMessageTest; import org.junit.Ignore; import org.junit.Test; @@ -18,29 +21,29 @@ import static org.junit.Assert.fail; -@Ignore +/** + * Tests for BLS methods. + * Test format description: https://github.com/ethereum/eth2.0-specs/tree/dev/specs/test_formats/bls + */ public class BlsTests extends TestUtils { private String TESTS_DIR = "bls"; - private String FILENAME = "test_bls.yml"; - private BeaconChainSpec spec; - - public BlsTests() { - this.spec = BeaconChainSpec.createWithDefaults(); - } @Test @Ignore("Fixtures uses Jacobian coordinates, testBlsMessageHashCompressed covers same cases") public void testBlsMessageHash() { - Path testFilePath = Paths.get(PATH_TO_TESTS, TESTS_DIR, FILENAME); - BlsTest test = readTest(getResourceFile(testFilePath.toString()), BlsTest.class); + Path testFilePath = + Paths.get(PATH_TO_TESTS, TESTS_DIR, "msg_hash_g2_uncompressed", "g2_uncompressed.yaml"); + BlsMessageHashTest test = + readTest(getResourceFile(testFilePath.toString()), BlsMessageHashTest.class); Optional errors = runAllCasesInTest( - test.buildBlsMessageHashTest(), - testCase -> { - BlsMessageHash testRunner = new BlsMessageHash(testCase, spec); + test, + input -> { + BlsMessageHash testRunner = new BlsMessageHash(input.getValue0(), input.getValue1()); return testRunner.run(); }, - UniversalTest.class); + BlsMessageHashTest.class, + true); if (errors.isPresent()) { System.out.println(errors.get()); fail(); @@ -48,18 +51,22 @@ public void testBlsMessageHash() { } @Test + @Ignore("Fixtures should be updated with sha256 as hash function instead of keccak256") public void testBlsMessageHashCompressed() { - Path testFilePath = Paths.get(PATH_TO_TESTS, TESTS_DIR, FILENAME); - BlsTest test = readTest(getResourceFile(testFilePath.toString()), BlsTest.class); + Path testFilePath = + Paths.get(PATH_TO_TESTS, TESTS_DIR, "msg_hash_g2_compressed", "g2_compressed.yaml"); + BlsMessageHashCompressedTest test = + readTest(getResourceFile(testFilePath.toString()), BlsMessageHashCompressedTest.class); Optional errors = runAllCasesInTest( - test.buildBlsMessageHashCompressedTest(), - testCase -> { + test, + input -> { BlsMessageHashCompressed testRunner = - new BlsMessageHashCompressed(testCase, spec); + new BlsMessageHashCompressed(input.getValue0(), input.getValue1()); return testRunner.run(); }, - UniversalTest.class); + BlsMessageHashCompressedTest.class, + true); if (errors.isPresent()) { System.out.println(errors.get()); fail(); @@ -68,16 +75,19 @@ public void testBlsMessageHashCompressed() { @Test public void testBlsPrivateToPublic() { - Path testFilePath = Paths.get(PATH_TO_TESTS, TESTS_DIR, FILENAME); - BlsTest test = readTest(getResourceFile(testFilePath.toString()), BlsTest.class); + Path testFilePath = Paths.get(PATH_TO_TESTS, TESTS_DIR, "priv_to_pub", "priv_to_pub.yaml"); + BlsPrivateToPublicTest test = + readTest(getResourceFile(testFilePath.toString()), BlsPrivateToPublicTest.class); Optional errors = runAllCasesInTest( - test.buildBlsPrivateToPublicTest(), - testCase -> { - BlsPrivateToPublic testRunner = new BlsPrivateToPublic(testCase, spec); + test, + input -> { + BlsPrivateToPublic testRunner = + new BlsPrivateToPublic(input.getValue0(), input.getValue1()); return testRunner.run(); }, - UniversalTest.class); + BlsPrivateToPublicTest.class, + true); if (errors.isPresent()) { System.out.println(errors.get()); fail(); @@ -85,17 +95,20 @@ public void testBlsPrivateToPublic() { } @Test + @Ignore("Fixtures should be updated with sha256 as hash function instead of keccak256") public void testBlsSignMessage() { - Path testFilePath = Paths.get(PATH_TO_TESTS, TESTS_DIR, FILENAME); - BlsTest test = readTest(getResourceFile(testFilePath.toString()), BlsTest.class); + Path testFilePath = Paths.get(PATH_TO_TESTS, TESTS_DIR, "sign_msg", "sign_msg.yaml"); + BlsSignMessageTest test = + readTest(getResourceFile(testFilePath.toString()), BlsSignMessageTest.class); Optional errors = runAllCasesInTest( - test.buildBlsSignMessageTest(), - testCase -> { - BlsSignMessage testRunner = new BlsSignMessage(testCase, spec); + test, + input -> { + BlsSignMessage testRunner = new BlsSignMessage(input.getValue0(), input.getValue1()); return testRunner.run(); }, - UniversalTest.class); + BlsSignMessageTest.class, + true); if (errors.isPresent()) { System.out.println(errors.get()); fail(); @@ -104,16 +117,20 @@ public void testBlsSignMessage() { @Test public void testBlsAggregateSigs() { - Path testFilePath = Paths.get(PATH_TO_TESTS, TESTS_DIR, FILENAME); - BlsTest test = readTest(getResourceFile(testFilePath.toString()), BlsTest.class); + Path testFilePath = + Paths.get(PATH_TO_TESTS, TESTS_DIR, "aggregate_sigs", "aggregate_sigs.yaml"); + BlsAggregateSigsTest test = + readTest(getResourceFile(testFilePath.toString()), BlsAggregateSigsTest.class); Optional errors = runAllCasesInTest( - test.buildBlsAggregateSigsTest(), - testCase -> { - BlsAggregateSigs testRunner = new BlsAggregateSigs(testCase, spec); + test, + input -> { + BlsAggregateSigs testRunner = + new BlsAggregateSigs(input.getValue0(), input.getValue1()); return testRunner.run(); }, - UniversalTest.class); + BlsAggregateSigsTest.class, + true); if (errors.isPresent()) { System.out.println(errors.get()); fail(); @@ -122,16 +139,20 @@ public void testBlsAggregateSigs() { @Test public void testBlsAggregatePubKeys() { - Path testFilePath = Paths.get(PATH_TO_TESTS, TESTS_DIR, FILENAME); - BlsTest test = readTest(getResourceFile(testFilePath.toString()), BlsTest.class); + Path testFilePath = + Paths.get(PATH_TO_TESTS, TESTS_DIR, "aggregate_pubkeys", "aggregate_pubkeys.yaml"); + BlsAggregatePubKeysTest test = + readTest(getResourceFile(testFilePath.toString()), BlsAggregatePubKeysTest.class); Optional errors = runAllCasesInTest( - test.buildBlsAggregatePubKeysTest(), - testCase -> { - BlsAggregatePubKeys testRunner = new BlsAggregatePubKeys(testCase, spec); + test, + input -> { + BlsAggregatePubKeys testRunner = + new BlsAggregatePubKeys(input.getValue0(), input.getValue1()); return testRunner.run(); }, - UniversalTest.class); + BlsAggregatePubKeysTest.class, + true); if (errors.isPresent()) { System.out.println(errors.get()); fail(); diff --git a/test/src/test/java/org/ethereum/beacon/test/ShuffleTests.java b/test/src/test/java/org/ethereum/beacon/test/ShuffleTests.java index a1ec17e95..6786ff7ae 100644 --- a/test/src/test/java/org/ethereum/beacon/test/ShuffleTests.java +++ b/test/src/test/java/org/ethereum/beacon/test/ShuffleTests.java @@ -1,96 +1,68 @@ package org.ethereum.beacon.test; import org.ethereum.beacon.consensus.BeaconChainSpec; -import org.ethereum.beacon.core.spec.SpecConstants; -import org.ethereum.beacon.core.types.EpochNumber; -import org.ethereum.beacon.core.types.ShardNumber; -import org.ethereum.beacon.core.types.SlotNumber; -import org.ethereum.beacon.core.types.ValidatorIndex; import org.ethereum.beacon.test.runner.shuffle.ShuffleRunner; import org.ethereum.beacon.test.type.shuffle.ShuffleTest; import org.junit.Test; -import tech.pegasys.artemis.ethereum.core.Hash32; -import tech.pegasys.artemis.util.collections.ReadList; +import tech.pegasys.artemis.util.bytes.Bytes32; import tech.pegasys.artemis.util.uint.UInt64; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.List; +/** Committee shuffle test */ public class ShuffleTests extends TestUtils { private String TESTS_DIR = "shuffling"; - private BeaconChainSpec spec; - - public ShuffleTests() { - // xxx EPOCH_LENGTH = 2**6 # 64 slots, 6.4 minutes - // xxx FAR_FUTURE_EPOCH = 2**64 - 1 # uint64 max - // xxx SHARD_COUNT = 2**10 # 1024 - // xxx TARGET_COMMITTEE_SIZE = 2**7 # 128 validators - // xxx ENTRY_EXIT_DELAY = 2**2 # 4 epochs - SpecConstants specConstants = - new SpecConstants() { - @Override - public EpochNumber getFarFutureEpoch() { - return EpochNumber.castFrom(UInt64.MAX_VALUE); - } - - @Override - public ValidatorIndex getTargetCommitteeSize() { - return ValidatorIndex.of(128); - } - - @Override - public SlotNumber.EpochLength getSlotsPerEpoch() { - return new SlotNumber.EpochLength(UInt64.valueOf(1 << 6)); - } - - @Override - public ShardNumber getShardCount() { - return ShardNumber.of(1024); - } - - @Override - public EpochNumber getActivationExitDelay() { - return EpochNumber.of(4); - } - }; - this.spec = BeaconChainSpec.createWithDefaultHasher(specConstants); - } + private String TESTS_SUBDIR = "core"; @Test public void testShuffling() { - // TODO wait until tests are updated to v0.6.0 -// Path sszTestsPath = Paths.get(PATH_TO_TESTS, TESTS_DIR); -// runTestsInResourceDir( -// sszTestsPath, -// ShuffleTest.class, -// testCase -> { -// ShuffleRunner testCaseRunner = -// new ShuffleRunner( -// testCase, -// spec, -// objects -> -// spec.get_shuffling( -// objects.getValue0(), objects.getValue1(), objects.getValue2())); -// return testCaseRunner.run(); -// }); + Path testFileDir = Paths.get(PATH_TO_TESTS, TESTS_DIR, TESTS_SUBDIR); + runTestsInResourceDir( + testFileDir, + ShuffleTest.class, + input -> { + ShuffleRunner testRunner = + new ShuffleRunner( + input.getValue0(), + input.getValue1(), + objects -> + input + .getValue1() + .compute_committee( + objects.getValue0(), + UInt64.ZERO, + UInt64.valueOf(objects.getValue2()), + objects.getValue1())); + return testRunner.run(); + }); } + /** + * Runs tests on optimized version of get_shuffling, like in {@link + * BeaconChainSpec#compute_committee2(List, UInt64, UInt64, Bytes32)} + */ @Test public void testShuffling2() { - // TODO wait until tests are updated to v0.6.0 -// Path sszTestsPath = Paths.get(PATH_TO_TESTS, TESTS_DIR); -// runTestsInResourceDir( -// sszTestsPath, -// ShuffleTest.class, -// testCase -> { -// ShuffleRunner testCaseRunner = -// new ShuffleRunner( -// testCase, -// spec, -// objects -> -// spec.get_shuffling2( -// objects.getValue0(), objects.getValue1(), objects.getValue2())); -// return testCaseRunner.run(); -// }); + Path testFileDir = Paths.get(PATH_TO_TESTS, TESTS_DIR, TESTS_SUBDIR); + runTestsInResourceDir( + testFileDir, + ShuffleTest.class, + input -> { + ShuffleRunner testRunner = + new ShuffleRunner( + input.getValue0(), + input.getValue1(), + objects -> + input + .getValue1() + .compute_committee2( + objects.getValue0(), + UInt64.ZERO, + UInt64.valueOf(objects.getValue2()), + objects.getValue1())); + return testRunner.run(); + }); } } diff --git a/test/src/test/java/org/ethereum/beacon/test/SszTests.java b/test/src/test/java/org/ethereum/beacon/test/SszTests.java index 46c36936b..91e561313 100644 --- a/test/src/test/java/org/ethereum/beacon/test/SszTests.java +++ b/test/src/test/java/org/ethereum/beacon/test/SszTests.java @@ -1,30 +1,38 @@ package org.ethereum.beacon.test; -import org.ethereum.beacon.consensus.BeaconChainSpec; -import org.ethereum.beacon.test.runner.ssz.SszRunner; -import org.ethereum.beacon.test.type.ssz.SszTest; +import org.ethereum.beacon.test.runner.ssz.SszGenericRunner; +import org.ethereum.beacon.test.runner.ssz.SszStaticRunner; +import org.ethereum.beacon.test.type.ssz.SszGenericTest; +import org.ethereum.beacon.test.type.ssz.SszStaticTest; import org.junit.Test; import java.nio.file.Path; import java.nio.file.Paths; +/** SSZ tests, generic with primitive values and static, with known container types */ public class SszTests extends TestUtils { - private String TESTS_DIR = "ssz"; - private BeaconChainSpec spec; - public SszTests() { - this.spec = BeaconChainSpec.createWithDefaults(); + @Test + public void testSszGeneric() { + Path testFileDir = Paths.get(PATH_TO_TESTS, "ssz_generic", "uint"); + runTestsInResourceDir( + testFileDir, + SszGenericTest.class, + input -> { + SszGenericRunner testRunner = new SszGenericRunner(input.getValue0(), input.getValue1()); + return testRunner.run(); + }); } @Test - public void testSsz() { - Path sszTestsPath = Paths.get(PATH_TO_TESTS, TESTS_DIR); + public void testSszStatic() { + Path testFileDir = Paths.get(PATH_TO_TESTS, "ssz_static", "core"); runTestsInResourceDir( - sszTestsPath, - SszTest.class, - testCase -> { - SszRunner testCaseRunner = new SszRunner(testCase, spec); - return testCaseRunner.run(); + testFileDir, + SszStaticTest.class, + input -> { + SszStaticRunner testRunner = new SszStaticRunner(input.getValue0(), input.getValue1()); + return testRunner.run(); }); } } diff --git a/test/src/test/java/org/ethereum/beacon/test/StateTestUtils.java b/test/src/test/java/org/ethereum/beacon/test/StateTestUtils.java index d31173c13..473839a7d 100644 --- a/test/src/test/java/org/ethereum/beacon/test/StateTestUtils.java +++ b/test/src/test/java/org/ethereum/beacon/test/StateTestUtils.java @@ -42,7 +42,7 @@ import org.ethereum.beacon.test.type.state.StateTestCase.BeaconStateData.ValidatorData; import org.ethereum.beacon.test.type.state.StateTestCase.BlockData.BlockBodyData.Eth1; import org.ethereum.beacon.test.type.state.StateTestCase.BlockData.BlockBodyData.ProposerSlashingData; -import org.ethereum.beacon.test.type.state.StateTestCase.BlockData.BlockBodyData.SlashableAttestationData; +import org.ethereum.beacon.test.type.state.StateTestCase.BlockData.BlockBodyData.IndexedAttestationData; import org.javatuples.Pair; import tech.pegasys.artemis.ethereum.core.Hash32; import tech.pegasys.artemis.util.bytes.Bytes32; @@ -70,7 +70,7 @@ public static Pair> parseBlockData( Bitfield.of(BytesValue.fromHexString(attestationData.getAggregationBitfield())), attestationData1, Bitfield.of(BytesValue.fromHexString(attestationData.getCustodyBitfield())), - BLSSignature.wrap(Bytes96.fromHexString(attestationData.getAggregateSignature()))); + BLSSignature.wrap(Bytes96.fromHexString(attestationData.getSignature()))); attestations.add(attestation); } @@ -93,11 +93,11 @@ public static Pair> parseBlockData( .collect(Collectors.toList()), Integer::new), UInt64.valueOf(depositData.getIndex()), new DepositData( - BLSPubkey.fromHexString(depositData.getDepositData().getPubkey()), - Hash32.fromHexString(depositData.getDepositData().getWithdrawalCredentials()), - Gwei.castFrom(UInt64.valueOf(depositData.getDepositData().getAmount())), + BLSPubkey.fromHexString(depositData.getData().getPubkey()), + Hash32.fromHexString(depositData.getData().getWithdrawalCredentials()), + Gwei.castFrom(UInt64.valueOf(depositData.getData().getAmount())), BLSSignature.wrap( - Bytes96.fromHexString(depositData.getDepositData().getSignature())))); + Bytes96.fromHexString(depositData.getData().getSignature())))); deposits.add(deposit); } @@ -175,7 +175,7 @@ public static Pair> parseBlockData( return Pair.with(block, Optional.empty()); } - public static IndexedAttestation parseSlashableAttestation(SlashableAttestationData data) { + public static IndexedAttestation parseSlashableAttestation(IndexedAttestationData data) { return new IndexedAttestation( data.getCustodyBit0Indices().stream().map(ValidatorIndex::of).collect(Collectors.toList()), data.getCustodyBit1Indices().stream().map(ValidatorIndex::of).collect(Collectors.toList()), @@ -204,19 +204,21 @@ public static MutableBeaconState parseBeaconState(SpecConstants specConstants, B state.setLatestEth1Data(parseEth1Data(data.getLatestEth1Data())); state.setDepositIndex(UInt64.valueOf(data.getDepositIndex())); - state.getValidatorRegistry().addAll(parseValidatorRegistry(data.getValidatorRegistry())); - state.getBalances().addAll(parseBalances(data.getValidatorBalances())); + state.getValidatorRegistry().replaceAll(parseValidatorRegistry(data.getValidatorRegistry())); + state.getBalances().replaceAll(parseBalances(data.getBalances())); state.getLatestRandaoMixes().setAll(parseHashes(data.getLatestRandaoMixes())); - state.getPreviousEpochAttestations().addAll( + state.getPreviousEpochAttestations().replaceAll( parsePendingAttestations(data.getPreviousEpochAttestations())); - state.getCurrentEpochAttestations().addAll( + state.getCurrentEpochAttestations().replaceAll( parsePendingAttestations(data.getCurrentEpochAttestations())); - state.getCurrentCrosslinks().addAll(parseCrosslinks(data.getLatestCrosslinks())); + state.getCurrentCrosslinks().replaceAll(parseCrosslinks(data.getCurrentCrosslinks())); + state.getPreviousCrosslinks().replaceAll(parseCrosslinks(data.getPreviousCrosslinks())); state.getLatestBlockRoots().setAll(parseHashes(data.getLatestBlockRoots())); state.getLatestStateRoots().setAll(parseHashes(data.getLatestStateRoots())); state.getLatestActiveIndexRoots().setAll(parseHashes(data.getLatestActiveIndexRoots())); - state.getHistoricalRoots().addAll(parseHashes(data.getHistoricalRoots())); + state.getHistoricalRoots().replaceAll(parseHashes(data.getHistoricalRoots())); state.getLatestSlashedBalances().setAll(parseBalances(data.getLatestSlashedBalances())); + state.setLatestStartShard(ShardNumber.of(UInt64.valueOf(data.getLatestStartShard()))); return state; } @@ -300,7 +302,7 @@ public static AttestationData parseAttestationData(AttestationDataContainer data Hash32.fromHexString(data.getBeaconBlockRoot()), EpochNumber.castFrom(UInt64.valueOf(data.getSourceEpoch())), Hash32.fromHexString(data.getSourceRoot()), - EpochNumber.castFrom(UInt64.valueOf(data.getSourceEpoch())), + EpochNumber.castFrom(UInt64.valueOf(data.getTargetEpoch())), Hash32.fromHexString(data.getTargetRoot()), ShardNumber.of(data.getShard()), Hash32.fromHexString(data.getPreviousCrosslinkRoot()), diff --git a/test/src/test/java/org/ethereum/beacon/test/StateTests.java b/test/src/test/java/org/ethereum/beacon/test/StateTests.java index 61b48b428..a7828b0c1 100644 --- a/test/src/test/java/org/ethereum/beacon/test/StateTests.java +++ b/test/src/test/java/org/ethereum/beacon/test/StateTests.java @@ -1,24 +1,38 @@ package org.ethereum.beacon.test; -import java.nio.file.Path; -import java.nio.file.Paths; import org.ethereum.beacon.test.runner.state.StateRunner; import org.ethereum.beacon.test.type.state.StateTest; import org.junit.Ignore; import org.junit.Test; +import java.nio.file.Path; +import java.nio.file.Paths; + public class StateTests extends TestUtils { - private String TESTS_DIR = "state"; + private String OPERATIONS_TESTS_DIR = "operations"; - public StateTests() {} + @Test + @Ignore("Postponed till generator updates") + public void testAttestationOperations() { + Path testFileDir = Paths.get(PATH_TO_TESTS, OPERATIONS_TESTS_DIR, "attestations"); + runTestsInResourceDir( + testFileDir, + StateTest.class, + input -> { + StateRunner testRunner = new StateRunner(input.getValue0(), input.getValue1()); + return testRunner.run(); + }); + } @Test - @Ignore("signing_root and hash_tree_root results do not match") - public void testState() { - Path stateTestsPath = Paths.get(PATH_TO_TESTS, TESTS_DIR); + public void testDepositOperations() { + Path testFileDir = Paths.get(PATH_TO_TESTS, OPERATIONS_TESTS_DIR, "deposits"); runTestsInResourceDir( - stateTestsPath, + testFileDir, StateTest.class, - testCase -> new StateRunner(testCase).run()); + input -> { + StateRunner testRunner = new StateRunner(input.getValue0(), input.getValue1()); + return testRunner.run(); + }); } } diff --git a/test/src/test/java/org/ethereum/beacon/test/TestUtils.java b/test/src/test/java/org/ethereum/beacon/test/TestUtils.java index 2daf4f9f0..fd1fba23e 100644 --- a/test/src/test/java/org/ethereum/beacon/test/TestUtils.java +++ b/test/src/test/java/org/ethereum/beacon/test/TestUtils.java @@ -1,18 +1,31 @@ package org.ethereum.beacon.test; -import static org.junit.Assert.assertFalse; - import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import com.google.common.base.Charsets; import com.google.common.io.CharStreams; import com.google.common.io.Resources; +import org.ethereum.beacon.consensus.BeaconChainSpec; +import org.ethereum.beacon.emulator.config.chainspec.SpecBuilder; +import org.ethereum.beacon.emulator.config.chainspec.SpecConstantsData; +import org.ethereum.beacon.emulator.config.chainspec.SpecData; +import org.ethereum.beacon.emulator.config.chainspec.SpecDataUtils; +import org.ethereum.beacon.emulator.config.chainspec.SpecHelpersData; +import org.ethereum.beacon.test.type.NamedTestCase; +import org.ethereum.beacon.test.type.SpecConstantsDataMerged; +import org.ethereum.beacon.test.type.TestCase; +import org.ethereum.beacon.test.type.TestSkeleton; +import org.ethereum.beacon.util.Objects; +import org.javatuples.Pair; + import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.StringWriter; import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; @@ -27,14 +40,17 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import java.util.stream.Collectors; -import org.ethereum.beacon.test.type.NamedTestCase; -import org.ethereum.beacon.test.type.TestCase; -import org.ethereum.beacon.test.type.TestSkeleton; + +import static org.junit.Assert.assertFalse; public class TestUtils { + private static final String GIT_COMMAND = + "git submodule init & git submodule update --recursive --remote"; static ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory()); - String PATH_TO_TESTS = "eth2.0-tests"; - private static final String GIT_COMMAND = "git submodule init & git submodule update --recursive --remote"; + static String PATH_TO_TESTS = "eth2.0-spec-tests/tests"; + static String PATH_TO_CONFIGS = "eth2.0-temp-test-configs"; + static String SPEC_CONFIG_DIR = "constant_presets"; + static String FORK_CONFIG_DIR = "fork_timelines"; static File getResourceFile(String relativePath) { try { @@ -68,6 +84,10 @@ static List getResourceFiles(String dir) { } static V readTest(File file, Class clazz) { + return readYamlFile(file, clazz); + } + + private static V readYamlFile(File file, Class clazz) { String content; try (InputStream inputStream = new FileInputStream(file); InputStreamReader streamReader = new InputStreamReader(inputStream, Charsets.UTF_8)) { @@ -79,45 +99,63 @@ static V readTest(File file, Class clazz) String.format("Error reading contents of file: %s", file.toPath().toString()), e); } - V test = readTest(content, clazz); - - return test; + return parseYamlData(content, clazz); } static Optional runAllTestsInFile( - File file, Function> testCaseRunner, Class clazz) { + File file, + Function, Optional> testCaseRunner, + Class clazz) { return runAllTestsInFile(file, testCaseRunner, clazz, Collections.emptySet()); } static Optional runAllTestsInFile( - File file, Function> testCaseRunner, Class clazz, + File file, + Function, Optional> testCaseRunner, + Class clazz, Collection exclusions) { V test = readTest(file, clazz); - return runAllCasesInTest(test, testCaseRunner, clazz, exclusions); + return runAllCasesInTest(test, testCaseRunner, clazz, exclusions, false); } + static Optional runAllCasesInTest( - V test, Function> testCaseRunner, Class clazz) { - return runAllCasesInTest(test, testCaseRunner, clazz, Collections.emptySet()); + V test, + Function, Optional> testCaseRunner, + Class clazz) { + return runAllCasesInTest(test, testCaseRunner, clazz, Collections.emptySet(), false); } static Optional runAllCasesInTest( - V test, Function> testCaseRunner, Class clazz, - Collection exclusions) { + V test, + Function, Optional> testCaseRunner, + Class clazz, + boolean isBlsVerified) { + return runAllCasesInTest(test, testCaseRunner, clazz, Collections.emptySet(), isBlsVerified); + } + + static Optional runAllCasesInTest( + V test, + Function, Optional> testCaseRunner, + Class clazz, + Collection exclusions, + boolean isBlsVerified) { StringBuilder errors = new StringBuilder(); AtomicInteger failed = new AtomicInteger(0); int total = 0; for (TestCase testCase : test.getTestCases()) { ++total; - String name = testCase instanceof NamedTestCase - ? ((NamedTestCase) testCase).getName() - : "Test #" + (total - 1); + String name = + testCase instanceof NamedTestCase + ? ((NamedTestCase) testCase).getName() + : "Test #" + (total - 1); if (exclusions.contains(name)) { System.out.println(String.format("[ ] %s ignored", name)); continue; } long s = System.nanoTime(); - Optional err = runTestCase(testCase, test, testCaseRunner); + BeaconChainSpec spec = loadSpecByName(test.getConfig(), isBlsVerified); + Optional err = runTestCase(testCase, spec, test, testCaseRunner); long completionTime = System.nanoTime() - s; if (err.isPresent()) { @@ -143,8 +181,20 @@ static Optional runAllCasesInTest( } static Optional runTestCase( - TestCase testCase, V test, Function> testCaseRunner) { - Optional testCaseErrors = testCaseRunner.apply(testCase); + TestCase testCase, + BeaconChainSpec spec, + V test, + Function, Optional> testCaseRunner) { + Optional testCaseErrors; + try { + testCaseErrors = testCaseRunner.apply(Pair.with(testCase, spec)); + } catch (Exception ex) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + ex.printStackTrace(pw); + String error = String.format("Unexpected error when running case %s: %s", testCase, sw.toString()); + testCaseErrors = Optional.of(error); + } if (testCaseErrors.isPresent()) { StringBuilder errors = new StringBuilder(); errors @@ -163,7 +213,7 @@ static Optional runTestCase( return Optional.empty(); } - static V readTest(String content, Class clazz) { + static V parseYamlData(String content, Class clazz) { try { return yamlMapper.readValue(content, clazz); } catch (IOException e) { @@ -174,20 +224,49 @@ static V readTest(String content, Class clazz) { } static void runTestsInResourceDir( - Path dir, Class testsType, Function> testCaseRunner) { + Path dir, + Class testsType, + Function, Optional> testCaseRunner) { runTestsInResourceDirImpl(dir, testsType, testCaseRunner, Collections.emptySet()); } static void runTestsInResourceDir( Path dir, Class testsType, - Function> testCaseRunner, + Function, Optional> testCaseRunner, Ignored ignored) { runTestsInResourceDirImpl(dir, testsType, testCaseRunner, ignored.testCases); } + static BeaconChainSpec loadSpecByName(String name, boolean isBlsVerified) { + Path configPath = Paths.get(PATH_TO_CONFIGS, SPEC_CONFIG_DIR, name + ".yaml"); + File config = getResourceFile(configPath.toString()); + + SpecConstantsData specConstantsDataRaw = readYamlFile(config, SpecConstantsDataMerged.class); + SpecConstantsData specConstantsData; + try { + specConstantsData = + Objects.copyProperties( + SpecDataUtils.createSpecConstantsData(BeaconChainSpec.DEFAULT_CONSTANTS), + specConstantsDataRaw); + } catch (Exception ex) { + throw new RuntimeException("Cannot merge spec constants with default settings"); + } + + SpecHelpersData specHelpersData = new SpecHelpersData(); + specHelpersData.setBlsVerify(isBlsVerified); + + SpecData specData = new SpecData(); + specData.setSpecHelpersOptions(specHelpersData); + specData.setSpecConstants(specConstantsData); + + return new SpecBuilder().withSpec(specData).buildSpec(); + } + private static void runTestsInResourceDirImpl( - Path dir, Class testsType, Function> testCaseRunner, + Path dir, + Class testsType, + Function, Optional> testCaseRunner, Collection exclusions) { List files = getResourceFiles(dir.toString()); boolean failed = false; diff --git a/test/src/test/java/org/ethereum/beacon/test/TreeHashTests.java b/test/src/test/java/org/ethereum/beacon/test/TreeHashTests.java deleted file mode 100644 index 45f7df270..000000000 --- a/test/src/test/java/org/ethereum/beacon/test/TreeHashTests.java +++ /dev/null @@ -1,107 +0,0 @@ -package org.ethereum.beacon.test; - -import org.ethereum.beacon.consensus.BeaconChainSpec; -import org.ethereum.beacon.test.runner.hash.TreeHashBasicRunner; -import org.ethereum.beacon.test.runner.hash.TreeHashContainerRunner; -import org.ethereum.beacon.test.runner.hash.TreeHashListRunner; -import org.ethereum.beacon.test.runner.hash.TreeHashVectorRunner; -import org.ethereum.beacon.test.type.hash.TreeHashBasicTest; -import org.ethereum.beacon.test.type.hash.TreeHashContainerTest; -import org.ethereum.beacon.test.type.hash.TreeHashListTest; -import org.junit.Ignore; -import org.junit.Test; - -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Optional; - -import static org.junit.Assert.fail; - -public class TreeHashTests extends TestUtils { - private String TESTS_DIR = "tree_hash"; - private BeaconChainSpec spec; - - public TreeHashTests() { - this.spec = BeaconChainSpec.createWithDefaults(); - } - - @Test - @Ignore("Remove when yaml is added to `eth2.0-test` repository") - public void testBasicTypesTreeHash() { - Path testFilePath = Paths.get(PATH_TO_TESTS, TESTS_DIR, "basic_types.yaml"); - TreeHashBasicTest test = - readTest(getResourceFile(testFilePath.toString()), TreeHashBasicTest.class); - Optional errors = - runAllCasesInTest( - test, - testCase -> { - TreeHashBasicRunner testRunner = new TreeHashBasicRunner(testCase, spec); - return testRunner.run(); - }, - TreeHashBasicTest.class); - if (errors.isPresent()) { - System.out.println(errors.get()); - fail(); - } - } - - @Test - @Ignore("Remove when yaml is added to `eth2.0-test` repository") - public void testListTypeTreeHash() { - Path testFilePath = Paths.get(PATH_TO_TESTS, TESTS_DIR, "basic_lists.yaml"); - TreeHashListTest test = - readTest(getResourceFile(testFilePath.toString()), TreeHashListTest.class); - Optional errors = - runAllCasesInTest( - test, - testCase -> { - TreeHashListRunner testRunner = new TreeHashListRunner(testCase, spec); - return testRunner.run(); - }, - TreeHashListTest.class); - if (errors.isPresent()) { - System.out.println(errors.get()); - fail(); - } - } - - @Test - @Ignore("Remove when yaml is added to `eth2.0-test` repository") - public void testVectorTypeTreeHash() { - Path testFilePath = Paths.get(PATH_TO_TESTS, TESTS_DIR, "basic_vectors.yaml"); - TreeHashListTest test = - readTest(getResourceFile(testFilePath.toString()), TreeHashListTest.class); - Optional errors = - runAllCasesInTest( - test, - testCase -> { - TreeHashVectorRunner testRunner = new TreeHashVectorRunner(testCase, spec); - return testRunner.run(); - }, - TreeHashListTest.class); - if (errors.isPresent()) { - System.out.println(errors.get()); - fail(); - } - } - - @Test - @Ignore("Remove when yaml is added to `eth2.0-test` repository") - public void testContainerTypeTreeHash() { - Path testFilePath = Paths.get(PATH_TO_TESTS, TESTS_DIR, "basic_containers.yaml"); - TreeHashContainerTest test = - readTest(getResourceFile(testFilePath.toString()), TreeHashContainerTest.class); - Optional errors = - runAllCasesInTest( - test, - testCase -> { - TreeHashContainerRunner testRunner = new TreeHashContainerRunner(testCase, spec); - return testRunner.run(); - }, - TreeHashContainerTest.class); - if (errors.isPresent()) { - System.out.println(errors.get()); - fail(); - } - } -} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsAggregatePubKeys.java b/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsAggregatePubKeys.java index 5d88e8ebb..d10d9de8e 100644 --- a/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsAggregatePubKeys.java +++ b/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsAggregatePubKeys.java @@ -3,8 +3,8 @@ import org.ethereum.beacon.consensus.BeaconChainSpec; import org.ethereum.beacon.core.types.BLSPubkey; import org.ethereum.beacon.test.runner.Runner; -import org.ethereum.beacon.test.type.bls.BlsTest; import org.ethereum.beacon.test.type.TestCase; +import org.ethereum.beacon.test.type.bls.BlsAggregatePubKeysCase; import tech.pegasys.artemis.util.bytes.Bytes48; import java.util.ArrayList; @@ -14,19 +14,21 @@ import static org.ethereum.beacon.test.SilentAsserts.assertHexStrings; /** - * TestRunner for {@link BlsTest.BlsAggregatePubKeysCase} + * TestRunner for {@link BlsAggregatePubKeysCase} * *

Aggregates public keys + * Test format description: https://github.com/ethereum/eth2.0-specs/blob/dev/specs/test_formats/bls/aggregate_pubkeys.md */ public class BlsAggregatePubKeys implements Runner { - private BlsTest.BlsAggregatePubKeysCase testCase; + private BlsAggregatePubKeysCase testCase; private BeaconChainSpec spec; public BlsAggregatePubKeys(TestCase testCase, BeaconChainSpec spec) { - if (!(testCase instanceof BlsTest.BlsAggregatePubKeysCase)) { + if (!(testCase instanceof BlsAggregatePubKeysCase)) { throw new RuntimeException("TestCase runner accepts only BlsAggregatePubKeysCase as input!"); } - this.testCase = (BlsTest.BlsAggregatePubKeysCase) testCase; + this.testCase = (BlsAggregatePubKeysCase) testCase; + assert spec.isBlsVerify(); this.spec = spec; } @@ -38,7 +40,6 @@ public Optional run() { } return assertHexStrings( - testCase.getOutput(), - spec.bls_aggregate_pubkeys(pubkeys).getEncodedBytes().toString()); + testCase.getOutput(), spec.bls_aggregate_pubkeys(pubkeys).getEncodedBytes().toString()); } } diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsAggregateSigs.java b/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsAggregateSigs.java index d23b82cd2..152e96ef5 100644 --- a/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsAggregateSigs.java +++ b/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsAggregateSigs.java @@ -6,8 +6,8 @@ import org.ethereum.beacon.crypto.BLS381; import org.ethereum.beacon.crypto.bls.milagro.MilagroCodecs; import org.ethereum.beacon.test.runner.Runner; -import org.ethereum.beacon.test.type.bls.BlsTest; import org.ethereum.beacon.test.type.TestCase; +import org.ethereum.beacon.test.type.bls.BlsAggregateSigsCase; import tech.pegasys.artemis.util.bytes.Bytes96; import java.util.ArrayList; @@ -17,19 +17,20 @@ import static org.ethereum.beacon.test.SilentAsserts.assertHexStrings; /** - * TestRunner for {@link BlsTest.BlsAggregateSigsCase} + * TestRunner for {@link BlsAggregateSigsCase} * *

Aggregates signatures + * Test format description: https://github.com/ethereum/eth2.0-specs/blob/dev/specs/test_formats/bls/aggregate_sigs.md */ public class BlsAggregateSigs implements Runner { - private BlsTest.BlsAggregateSigsCase testCase; + private BlsAggregateSigsCase testCase; private BeaconChainSpec spec; public BlsAggregateSigs(TestCase testCase, BeaconChainSpec spec) { - if (!(testCase instanceof BlsTest.BlsAggregateSigsCase)) { + if (!(testCase instanceof BlsAggregateSigsCase)) { throw new RuntimeException("TestCase runner accepts only BlsAggregateSigsCase as input!"); } - this.testCase = (BlsTest.BlsAggregateSigsCase) testCase; + this.testCase = (BlsAggregateSigsCase) testCase; this.spec = spec; } @@ -40,8 +41,12 @@ public Optional run() { signatures.add(blsSignature); } ECP2 product = new ECP2(); - signatures.forEach((s) -> {product.add(MilagroCodecs.G2.decode(s));}); + signatures.forEach( + (s) -> { + product.add(MilagroCodecs.G2.decode(s)); + }); - return assertHexStrings(testCase.getOutput(), BLS381.Signature.create(product).getEncoded().toString()); + return assertHexStrings( + testCase.getOutput(), BLS381.Signature.create(product).getEncoded().toString()); } } diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsMessageHash.java b/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsMessageHash.java index 17cf8482e..1086fee82 100644 --- a/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsMessageHash.java +++ b/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsMessageHash.java @@ -6,8 +6,8 @@ import org.ethereum.beacon.crypto.MessageParameters; import org.ethereum.beacon.crypto.bls.milagro.MilagroMessageMapper; import org.ethereum.beacon.test.runner.Runner; -import org.ethereum.beacon.test.type.bls.BlsTest; import org.ethereum.beacon.test.type.TestCase; +import org.ethereum.beacon.test.type.bls.BlsMessageHashCase; import tech.pegasys.artemis.ethereum.core.Hash32; import tech.pegasys.artemis.util.bytes.Bytes32; import tech.pegasys.artemis.util.bytes.Bytes8; @@ -19,24 +19,20 @@ import static org.ethereum.beacon.test.SilentAsserts.assertLists; /** - * TestRunner for {@link BlsTest.BlsMessageHashCase} + * TestRunner for {@link BlsMessageHashCase} * - *

Hash message - * Input: - * - Message as bytes - * - domain as uint64 - * Output: - * - Message hash as a G2 point (uncompressed) + *

Hash message as G2 point (uncompressed) + * Test format description: https://github.com/ethereum/eth2.0-specs/blob/dev/specs/test_formats/bls/msg_hash_g2_uncompressed.md */ public class BlsMessageHash implements Runner { - private BlsTest.BlsMessageHashCase testCase; + private BlsMessageHashCase testCase; private BeaconChainSpec spec; public BlsMessageHash(TestCase testCase, BeaconChainSpec spec) { - if (!(testCase instanceof BlsTest.BlsMessageHashCase)) { + if (!(testCase instanceof BlsMessageHashCase)) { throw new RuntimeException("TestCase runner accepts only BlsMessageHashCase as input!"); } - this.testCase = (BlsTest.BlsMessageHashCase) testCase; + this.testCase = (BlsMessageHashCase) testCase; this.spec = spec; } @@ -49,12 +45,9 @@ public Optional run() { MilagroMessageMapper milagroMessageMapper = new MilagroMessageMapper(); ECP2 point = milagroMessageMapper.map(messageParameters); - Optional compareX = - assertLists(testCase.getOutput().get(0), serialize(point.getX())); - Optional compareY = - assertLists(testCase.getOutput().get(1), serialize(point.getY())); - Optional compareZ = - assertLists(testCase.getOutput().get(2), serialize(point.getz())); + Optional compareX = assertLists(testCase.getOutput().get(0), serialize(point.getX())); + Optional compareY = assertLists(testCase.getOutput().get(1), serialize(point.getY())); + Optional compareZ = assertLists(testCase.getOutput().get(2), serialize(point.getz())); if (!compareX.isPresent() && !compareY.isPresent() && !compareZ.isPresent()) { return Optional.empty(); diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsMessageHashCompressed.java b/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsMessageHashCompressed.java index 61b0e0aed..e4aeec53c 100644 --- a/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsMessageHashCompressed.java +++ b/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsMessageHashCompressed.java @@ -6,8 +6,8 @@ import org.ethereum.beacon.crypto.bls.milagro.MilagroCodecs; import org.ethereum.beacon.crypto.bls.milagro.MilagroMessageMapper; import org.ethereum.beacon.test.runner.Runner; -import org.ethereum.beacon.test.type.bls.BlsTest; import org.ethereum.beacon.test.type.TestCase; +import org.ethereum.beacon.test.type.bls.BlsMessageHashCompressedCase; import tech.pegasys.artemis.ethereum.core.Hash32; import tech.pegasys.artemis.util.bytes.Bytes32; import tech.pegasys.artemis.util.bytes.Bytes48; @@ -19,25 +19,21 @@ import static org.ethereum.beacon.test.SilentAsserts.assertHexStrings; /** - * TestRunner for {@link BlsTest.BlsMessageHashCompressedCase} + * TestRunner for {@link BlsMessageHashCompressedCase} * - *

Hash message - * Input: - * - Message as bytes - * - domain as uint64 - * Output: - * - Message hash as a compressed G2 point + *

Hash message as G2 point (compressed) + * Test format description: https://github.com/ethereum/eth2.0-specs/blob/dev/specs/test_formats/bls/msg_hash_g2_compressed.md */ public class BlsMessageHashCompressed implements Runner { - private BlsTest.BlsMessageHashCompressedCase testCase; + private BlsMessageHashCompressedCase testCase; private BeaconChainSpec spec; public BlsMessageHashCompressed(TestCase testCase, BeaconChainSpec spec) { - if (!(testCase instanceof BlsTest.BlsMessageHashCompressedCase)) { + if (!(testCase instanceof BlsMessageHashCompressedCase)) { throw new RuntimeException( "TestCase runner accepts only BlsMessageHashCompressedCase as input!"); } - this.testCase = (BlsTest.BlsMessageHashCompressedCase) testCase; + this.testCase = (BlsMessageHashCompressedCase) testCase; this.spec = spec; } diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsPrivateToPublic.java b/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsPrivateToPublic.java index 07904ac1c..c071bd80b 100644 --- a/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsPrivateToPublic.java +++ b/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsPrivateToPublic.java @@ -3,8 +3,8 @@ import org.ethereum.beacon.consensus.BeaconChainSpec; import org.ethereum.beacon.crypto.BLS381; import org.ethereum.beacon.test.runner.Runner; -import org.ethereum.beacon.test.type.bls.BlsTest; import org.ethereum.beacon.test.type.TestCase; +import org.ethereum.beacon.test.type.bls.BlsPrivateToPublicCase; import tech.pegasys.artemis.util.bytes.Bytes32; import java.util.Optional; @@ -12,19 +12,20 @@ import static org.ethereum.beacon.test.SilentAsserts.assertHexStrings; /** - * TestRunner for {@link BlsTest.BlsPrivateToPublicCase} + * TestRunner for {@link BlsPrivateToPublicCase} * *

Verifies public key creation using private key + * Test format description: https://github.com/ethereum/eth2.0-specs/blob/dev/specs/test_formats/bls/priv_to_pub.md */ public class BlsPrivateToPublic implements Runner { - private BlsTest.BlsPrivateToPublicCase testCase; + private BlsPrivateToPublicCase testCase; private BeaconChainSpec spec; public BlsPrivateToPublic(TestCase testCase, BeaconChainSpec spec) { - if (!(testCase instanceof BlsTest.BlsPrivateToPublicCase)) { + if (!(testCase instanceof BlsPrivateToPublicCase)) { throw new RuntimeException("TestCase runner accepts only BlsPrivateToPublicCase as input!"); } - this.testCase = (BlsTest.BlsPrivateToPublicCase) testCase; + this.testCase = (BlsPrivateToPublicCase) testCase; this.spec = spec; } diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsSignMessage.java b/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsSignMessage.java index f1baed81b..abeaa5ec0 100644 --- a/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsSignMessage.java +++ b/test/src/test/java/org/ethereum/beacon/test/runner/bls/BlsSignMessage.java @@ -1,34 +1,36 @@ package org.ethereum.beacon.test.runner.bls; -import static org.ethereum.beacon.test.SilentAsserts.assertEquals; - -import java.util.Optional; import org.ethereum.beacon.consensus.BeaconChainSpec; import org.ethereum.beacon.core.types.BLSSignature; import org.ethereum.beacon.crypto.BLS381; import org.ethereum.beacon.crypto.MessageParameters; import org.ethereum.beacon.test.runner.Runner; -import org.ethereum.beacon.test.type.bls.BlsTest; import org.ethereum.beacon.test.type.TestCase; +import org.ethereum.beacon.test.type.bls.BlsSignMessageCase; import tech.pegasys.artemis.ethereum.core.Hash32; import tech.pegasys.artemis.util.bytes.Bytes32; import tech.pegasys.artemis.util.bytes.Bytes8; import tech.pegasys.artemis.util.bytes.Bytes96; +import java.util.Optional; + +import static org.ethereum.beacon.test.SilentAsserts.assertEquals; + /** - * TestRunner for {@link BlsTest.BlsSignMessageCase} + * TestRunner for {@link BlsSignMessageCase} * *

Signs message by signer defined by private key + * Test format description: https://github.com/ethereum/eth2.0-specs/blob/dev/specs/test_formats/bls/sign_msg.md */ public class BlsSignMessage implements Runner { - private BlsTest.BlsSignMessageCase testCase; + private BlsSignMessageCase testCase; private BeaconChainSpec spec; public BlsSignMessage(TestCase testCase, BeaconChainSpec spec) { - if (!(testCase instanceof BlsTest.BlsSignMessageCase)) { + if (!(testCase instanceof BlsSignMessageCase)) { throw new RuntimeException("TestCase runner accepts only BlsSignMessageCase as input!"); } - this.testCase = (BlsTest.BlsSignMessageCase) testCase; + this.testCase = (BlsSignMessageCase) testCase; this.spec = spec; } diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/hash/TreeHashBasicRunner.java b/test/src/test/java/org/ethereum/beacon/test/runner/hash/TreeHashBasicRunner.java deleted file mode 100644 index 335fa724c..000000000 --- a/test/src/test/java/org/ethereum/beacon/test/runner/hash/TreeHashBasicRunner.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.ethereum.beacon.test.runner.hash; - -import org.ethereum.beacon.consensus.BeaconChainSpec; -import org.ethereum.beacon.consensus.hasher.SSZObjectHasher; -import org.ethereum.beacon.core.spec.SpecConstantsResolver; -import org.ethereum.beacon.crypto.Hashes; -import org.ethereum.beacon.ssz.SSZBuilder; -import org.ethereum.beacon.ssz.SSZHasher; -import org.ethereum.beacon.ssz.access.SSZField; -import org.ethereum.beacon.ssz.type.SimpleTypeResolver; -import org.ethereum.beacon.ssz.type.TypeResolver; -import org.ethereum.beacon.test.runner.Runner; -import org.ethereum.beacon.test.type.TestCase; -import org.ethereum.beacon.test.type.hash.TreeHashBasicTestCase; -import tech.pegasys.artemis.ethereum.core.Hash32; -import tech.pegasys.artemis.util.bytes.BytesValue; - -import java.math.BigInteger; -import java.util.Optional; -import java.util.function.Function; - -import static org.ethereum.beacon.test.SilentAsserts.assertEquals; - -/** TestRunner for {@link TreeHashBasicTestCase} */ -public class TreeHashBasicRunner implements Runner { - private TreeHashBasicTestCase testCase; - private SSZObjectHasher hasher; - private SSZField field; - - public TreeHashBasicRunner(TestCase testCase, BeaconChainSpec spec) { - if (!(testCase instanceof TreeHashBasicTestCase)) { - throw new RuntimeException( - "TestCase runner accepts only TreeHashBasicTestCase.class as input!"); - } - this.testCase = (TreeHashBasicTestCase) testCase; - Function hashFunction = Hashes::sha256; - SSZHasher sszHasher = - new SSZBuilder().withExternalVarResolver(new SpecConstantsResolver(spec.getConstants())) - .withIncrementalHasher(true) - .withTypeResolverBuilder( - objects -> { - TypeResolver delegate = - new SimpleTypeResolver(objects.getValue0(), objects.getValue1()); - return descriptor -> delegate.resolveSSZType(field); - }) - .buildHasher(hashFunction); - this.hasher = new SSZObjectHasher(sszHasher); - } - - public static SSZField parseBasicFieldType(String type) { - if (type.equals("bool")) { - return new SSZField(Boolean.class, null, null, null, "value", "getValue"); - } else if (type.startsWith("uint")) { - return new SSZField( - BigInteger.class, null, "uint", Integer.valueOf(type.substring(4)), "value", "getValue"); - } else { - throw new RuntimeException("Type " + type + " is not supported"); - } - } - - public static Object instantiateValue(String value, String type) { - Object res; - if (type.equals("bool")) { - res = Boolean.valueOf(value); - } else if (type.startsWith("uint")) { - res = new BigInteger(value); - } else { - throw new RuntimeException("Type " + type + " is not supported"); - } - - return res; - } - - private void activateSchemeMock(String type) { - this.field = parseBasicFieldType(type); - } - - public Optional run() { - activateSchemeMock(testCase.getType()); - Object object = instantiateValue(testCase.getValue(), testCase.getType()); - Hash32 res = hasher.getHash(object); - String expected = testCase.getRoot(); - if (!expected.startsWith("0x")) { - expected = "0x" + expected; - } - String actual = res.toString(); - return assertEquals(expected, actual); - } -} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/hash/TreeHashContainerRunner.java b/test/src/test/java/org/ethereum/beacon/test/runner/hash/TreeHashContainerRunner.java deleted file mode 100644 index 7f948ae76..000000000 --- a/test/src/test/java/org/ethereum/beacon/test/runner/hash/TreeHashContainerRunner.java +++ /dev/null @@ -1,184 +0,0 @@ -package org.ethereum.beacon.test.runner.hash; - -import org.ethereum.beacon.consensus.BeaconChainSpec; -import org.ethereum.beacon.consensus.hasher.SSZObjectHasher; -import org.ethereum.beacon.core.spec.SpecConstantsResolver; -import org.ethereum.beacon.crypto.Hashes; -import org.ethereum.beacon.ssz.ExternalVarResolver; -import org.ethereum.beacon.ssz.SSZBuilder; -import org.ethereum.beacon.ssz.SSZHasher; -import org.ethereum.beacon.ssz.access.AccessorResolver; -import org.ethereum.beacon.ssz.access.SSZContainerAccessor; -import org.ethereum.beacon.ssz.access.SSZField; -import org.ethereum.beacon.ssz.annotation.SSZSerializable; -import org.ethereum.beacon.ssz.type.SSZContainerType; -import org.ethereum.beacon.ssz.type.SSZType; -import org.ethereum.beacon.ssz.type.SimpleTypeResolver; -import org.ethereum.beacon.test.runner.Runner; -import org.ethereum.beacon.test.type.TestCase; -import org.ethereum.beacon.test.type.hash.TreeHashContainerTestCase; -import tech.pegasys.artemis.ethereum.core.Hash32; -import tech.pegasys.artemis.util.bytes.BytesValue; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.Function; -import java.util.stream.Collectors; - -import static org.ethereum.beacon.test.SilentAsserts.assertEquals; -import static org.ethereum.beacon.test.runner.hash.TreeHashBasicRunner.instantiateValue; -import static org.ethereum.beacon.test.runner.hash.TreeHashBasicRunner.parseBasicFieldType; - -/** TestRunner for {@link TreeHashContainerTestCase} */ -public class TreeHashContainerRunner implements Runner { - private TreeHashContainerTestCase testCase; - private SSZObjectHasher hasher; - private List fields; - - public TreeHashContainerRunner(TestCase testCase, BeaconChainSpec spec) { - if (!(testCase instanceof TreeHashContainerTestCase)) { - throw new RuntimeException( - "TestCase runner accepts only TreeHashContainerTestCase.class as input!"); - } - this.testCase = (TreeHashContainerTestCase) testCase; - Function hashFunction = Hashes::sha256; - SSZHasher sszHasher = - new SSZBuilder().withExternalVarResolver(new SpecConstantsResolver(spec.getConstants())) - .withIncrementalHasher(true) - .withTypeResolverBuilder( - objects -> { - return new CustomTypeResolver(objects.getValue0(), objects.getValue1()); - }) - .buildHasher(hashFunction); - - this.hasher = new SSZObjectHasher(sszHasher); - } - - public Optional run() { - // Guaranteeing order when matching type and value content maps - List entries = new ArrayList<>(); - Map entrySet = new HashMap<>(); - testCase - .getType() - .forEach( - (key, value) -> { - CustomTypeValue entry = new CustomTypeValue(); - entry.setType(value); - entrySet.put(key, entry); - }); - testCase - .getValue() - .forEach( - (key, value) -> { - CustomTypeValue entry = entrySet.get(key); - entry.setValue(value); - }); - entrySet.entrySet().stream() - .sorted( - Comparator.comparingInt( - (Map.Entry entry) -> { - return Integer.valueOf(entry.getKey().substring(5)); // "fieldXXX" - })) - .forEachOrdered(e -> entries.add(e.getValue())); - this.fields = entries; - - String expected = testCase.getRoot(); - if (!expected.startsWith("0x")) { - expected = "0x" + expected; - } - String actual = hasher.getHash(entries).toString(); - return assertEquals(expected, actual); - } - - static class TestContainerAccessor implements SSZContainerAccessor { - private List fields; - - public TestContainerAccessor(List fields) { - this.fields = fields; - } - - @Override - public ContainerAccessor getAccessor(SSZField containerDescriptor) { - return new ContainerAccessor() { - @Override - public List getChildDescriptors() { - return fields.stream() - .map( - field -> { - String type = field.getType(); - return parseBasicFieldType(type); - }) - .collect(Collectors.toList()); - } - - @Override - public Object getChildValue(Object compositeInstance, int childIndex) { - String value = fields.get(childIndex).getValue(); - String type = fields.get(childIndex).getType(); - return instantiateValue(value, type); - } - }; - } - - @Override - public ContainerInstanceBuilder createInstanceBuilder(SSZField containerDescriptor) { - return null; - } - - @Override - public boolean isSupported(SSZField field) { - return field.getRawClass().equals(SerializableContainerMock.class); - } - } - - static class CustomTypeValue { - private String type; - private String value; - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - } - - @SSZSerializable - public static class SerializableContainerMock {} - - class CustomTypeResolver extends SimpleTypeResolver { - private AccessorResolver accessorResolver; - - public CustomTypeResolver( - AccessorResolver accessorResolver, ExternalVarResolver externalVarResolver) { - super(accessorResolver, externalVarResolver); - this.accessorResolver = accessorResolver; - } - - @Override - public SSZType resolveSSZType(SSZField descriptor) { - if (new HashSet(Arrays.asList(descriptor.getRawClass().getInterfaces())) - .contains(List.class)) { - TestContainerAccessor containerAccessor = new TestContainerAccessor(fields); - return new SSZContainerType(this, descriptor, containerAccessor); - } else { - return super.resolveSSZType(descriptor); - } - } - } -} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/hash/TreeHashListRunner.java b/test/src/test/java/org/ethereum/beacon/test/runner/hash/TreeHashListRunner.java deleted file mode 100644 index d48390b6d..000000000 --- a/test/src/test/java/org/ethereum/beacon/test/runner/hash/TreeHashListRunner.java +++ /dev/null @@ -1,94 +0,0 @@ -package org.ethereum.beacon.test.runner.hash; - -import org.ethereum.beacon.consensus.BeaconChainSpec; -import org.ethereum.beacon.consensus.hasher.SSZObjectHasher; -import org.ethereum.beacon.core.spec.SpecConstantsResolver; -import org.ethereum.beacon.crypto.Hashes; -import org.ethereum.beacon.ssz.ExternalVarResolver; -import org.ethereum.beacon.ssz.SSZBuilder; -import org.ethereum.beacon.ssz.SSZHasher; -import org.ethereum.beacon.ssz.access.AccessorResolver; -import org.ethereum.beacon.ssz.access.SSZField; -import org.ethereum.beacon.ssz.type.SSZType; -import org.ethereum.beacon.ssz.type.SimpleTypeResolver; -import org.ethereum.beacon.test.runner.Runner; -import org.ethereum.beacon.test.type.TestCase; -import org.ethereum.beacon.test.type.hash.TreeHashListTestCase; -import tech.pegasys.artemis.ethereum.core.Hash32; -import tech.pegasys.artemis.util.bytes.BytesValue; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.function.Function; -import java.util.stream.Collectors; - -import static org.ethereum.beacon.test.SilentAsserts.assertEquals; -import static org.ethereum.beacon.test.SilentAsserts.assertTrue; -import static org.ethereum.beacon.test.runner.hash.TreeHashBasicRunner.instantiateValue; -import static org.ethereum.beacon.test.runner.hash.TreeHashBasicRunner.parseBasicFieldType; - -/** TestRunner for {@link TreeHashListTestCase} for list cases */ -public class TreeHashListRunner implements Runner { - private TreeHashListTestCase testCase; - private SSZObjectHasher hasher; - private SSZField field; - - public TreeHashListRunner(TestCase testCase, BeaconChainSpec spec) { - if (!(testCase instanceof TreeHashListTestCase)) { - throw new RuntimeException( - "TestCase runner accepts only TreeHashListTestCase.class as input!"); - } - this.testCase = (TreeHashListTestCase) testCase; - Function hashFunction = Hashes::sha256; - SSZHasher sszHasher = - new SSZBuilder().withExternalVarResolver(new SpecConstantsResolver(spec.getConstants())) - .withIncrementalHasher(true) - .withTypeResolverBuilder( - objects -> { - return new CustomTypeResolver(objects.getValue0(), objects.getValue1()); - }) - .buildHasher(hashFunction); - - this.hasher = new SSZObjectHasher(sszHasher); - } - - private void activateSchemeMock(String type) { - this.field = parseBasicFieldType(type); - } - - public Optional run() { - assertTrue("Only one type parameter lists are supported", testCase.getType().size() == 1); - String internalType = testCase.getType().get(0); - activateSchemeMock(internalType); - List input = - testCase.getValue().stream() - .map(v -> instantiateValue(v, internalType)) - .collect(Collectors.toList()); - Hash32 res = hasher.getHash(input); - String expected = testCase.getRoot(); - if (!expected.startsWith("0x")) { - expected = "0x" + expected; - } - String actual = res.toString(); - return assertEquals(expected, actual); - } - - class CustomTypeResolver extends SimpleTypeResolver { - public CustomTypeResolver( - AccessorResolver accessorResolver, ExternalVarResolver externalVarResolver) { - super(accessorResolver, externalVarResolver); - } - - @Override - public SSZType resolveSSZType(SSZField descriptor) { - if (new HashSet(Arrays.asList(descriptor.getRawClass().getInterfaces())) - .contains(List.class)) { - return super.resolveSSZType(descriptor); - } else { - return super.resolveSSZType(field); - } - } - } -} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/hash/TreeHashVectorRunner.java b/test/src/test/java/org/ethereum/beacon/test/runner/hash/TreeHashVectorRunner.java deleted file mode 100644 index 14cba1d8a..000000000 --- a/test/src/test/java/org/ethereum/beacon/test/runner/hash/TreeHashVectorRunner.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.ethereum.beacon.test.runner.hash; - -import org.ethereum.beacon.consensus.BeaconChainSpec; -import org.ethereum.beacon.consensus.hasher.SSZObjectHasher; -import org.ethereum.beacon.core.spec.SpecConstantsResolver; -import org.ethereum.beacon.crypto.Hashes; -import org.ethereum.beacon.ssz.ExternalVarResolver; -import org.ethereum.beacon.ssz.SSZBuilder; -import org.ethereum.beacon.ssz.SSZHasher; -import org.ethereum.beacon.ssz.access.AccessorResolver; -import org.ethereum.beacon.ssz.access.SSZField; -import org.ethereum.beacon.ssz.type.SSZListType; -import org.ethereum.beacon.ssz.type.SSZType; -import org.ethereum.beacon.ssz.type.SimpleTypeResolver; -import org.ethereum.beacon.test.runner.Runner; -import org.ethereum.beacon.test.type.TestCase; -import org.ethereum.beacon.test.type.hash.TreeHashListTestCase; -import tech.pegasys.artemis.ethereum.core.Hash32; -import tech.pegasys.artemis.util.bytes.BytesValue; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.function.Function; -import java.util.stream.Collectors; - -import static org.ethereum.beacon.test.SilentAsserts.assertEquals; -import static org.ethereum.beacon.test.SilentAsserts.assertTrue; -import static org.ethereum.beacon.test.runner.hash.TreeHashBasicRunner.instantiateValue; -import static org.ethereum.beacon.test.runner.hash.TreeHashBasicRunner.parseBasicFieldType; - -/** TestRunner for {@link TreeHashListTestCase} for vector cases */ -public class TreeHashVectorRunner implements Runner { - private TreeHashListTestCase testCase; - private SSZObjectHasher hasher; - private SSZField field; - private int vectorSize; - - public TreeHashVectorRunner(TestCase testCase, BeaconChainSpec spec) { - if (!(testCase instanceof TreeHashListTestCase)) { - throw new RuntimeException( - "TestCase runner accepts only TreeHashListTestCase.class as input!"); - } - this.testCase = (TreeHashListTestCase) testCase; - Function hashFunction = Hashes::sha256; - SSZHasher sszHasher = - new SSZBuilder().withExternalVarResolver(new SpecConstantsResolver(spec.getConstants())) - .withIncrementalHasher(true) - .withTypeResolverBuilder( - objects -> { - return new CustomTypeResolver(objects.getValue0(), objects.getValue1()); - }) - .buildHasher(hashFunction); - this.hasher = new SSZObjectHasher(sszHasher); - } - - private void activateSchemeMock(String type, int vectorSize) { - this.vectorSize = vectorSize; - this.field = parseBasicFieldType(type); - } - - public Optional run() { - assertTrue("Only two type parameters vectors are supported", testCase.getType().size() == 2); - String internalType = testCase.getType().get(0); - String vectorSize = testCase.getType().get(1); - activateSchemeMock(internalType, Integer.valueOf(vectorSize)); - List input = - testCase.getValue().stream() - .map(v -> instantiateValue(v, internalType)) - .collect(Collectors.toList()); - Hash32 res = hasher.getHash(input); - String expected = testCase.getRoot(); - if (!expected.startsWith("0x")) { - expected = "0x" + expected; - } - String actual = res.toString(); - return assertEquals(expected, actual); - } - - class CustomTypeResolver extends SimpleTypeResolver { - private AccessorResolver accessorResolver; - - public CustomTypeResolver( - AccessorResolver accessorResolver, ExternalVarResolver externalVarResolver) { - super(accessorResolver, externalVarResolver); - this.accessorResolver = accessorResolver; - } - - @Override - public SSZType resolveSSZType(SSZField descriptor) { - if (new HashSet(Arrays.asList(descriptor.getRawClass().getInterfaces())) - .contains(List.class)) { - return new SSZListType( - descriptor, this, accessorResolver.resolveListAccessor(descriptor).get(), vectorSize); - } else { - return super.resolveSSZType(field); - } - } - } -} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/shuffle/ShuffleRunner.java b/test/src/test/java/org/ethereum/beacon/test/runner/shuffle/ShuffleRunner.java index c7a9ef00d..7cf24c86d 100644 --- a/test/src/test/java/org/ethereum/beacon/test/runner/shuffle/ShuffleRunner.java +++ b/test/src/test/java/org/ethereum/beacon/test/runner/shuffle/ShuffleRunner.java @@ -1,23 +1,18 @@ package org.ethereum.beacon.test.runner.shuffle; import org.ethereum.beacon.consensus.BeaconChainSpec; -import org.ethereum.beacon.core.state.ValidatorRecord; -import org.ethereum.beacon.core.types.BLSPubkey; -import org.ethereum.beacon.core.types.EpochNumber; -import org.ethereum.beacon.core.types.Gwei; import org.ethereum.beacon.core.types.ValidatorIndex; import org.ethereum.beacon.test.runner.Runner; -import org.ethereum.beacon.test.type.shuffle.ShuffleTestCase; import org.ethereum.beacon.test.type.TestCase; +import org.ethereum.beacon.test.type.shuffle.ShuffleTestCase; import org.javatuples.Triplet; -import tech.pegasys.artemis.ethereum.core.Hash32; -import tech.pegasys.artemis.util.collections.ReadList; -import tech.pegasys.artemis.util.uint.UInt64; +import tech.pegasys.artemis.util.bytes.Bytes32; -import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; import static org.ethereum.beacon.test.SilentAsserts.assertLists; @@ -25,17 +20,13 @@ public class ShuffleRunner implements Runner { private ShuffleTestCase testCase; private BeaconChainSpec spec; - private Function< - Triplet, EpochNumber>, - List>> + private Function, Bytes32, Integer>, List> getShuffling; public ShuffleRunner( TestCase testCase, BeaconChainSpec spec, - Function< - Triplet, EpochNumber>, - List>> + Function, Bytes32, Integer>, List> getShuffling) { if (!(testCase instanceof ShuffleTestCase)) { throw new RuntimeException("TestCase runner accepts only ShuffleTestCase.class as input!"); @@ -46,40 +37,18 @@ public ShuffleRunner( } public Optional run() { - - EpochNumber currentEpoch = EpochNumber.castFrom(UInt64.valueOf(testCase.getInput().getEpoch())); - List validators = new ArrayList<>(); - for (ShuffleTestCase.ShuffleInput.ShuffleTestValidator testValidator : - testCase.getInput().getValidators()) { - ValidatorRecord validatorRecord = - new ValidatorRecord( - BLSPubkey.ZERO, - Hash32.ZERO, - spec.getConstants().getFarFutureEpoch(), - EpochNumber.castFrom(UInt64.valueOf(testValidator.getActivation_epoch())), - EpochNumber.castFrom(UInt64.valueOf(testValidator.getExit_epoch())), - EpochNumber.castFrom(UInt64.valueOf(testValidator.getActivation_epoch())) - .plus(spec.getConstants().getMinValidatorWithdrawabilityDelay()), - false, - spec.getConstants().getMaxEffectiveBalance()); - validators.add(validatorRecord); - } - - ReadList validatorReadList = - ReadList.wrap(validators, ValidatorIndex::of); - - List> expectedIndices = new ArrayList<>(); - for (List entry : testCase.getOutput()) { - List indices = new ArrayList<>(); - for (Integer index : entry) { - indices.add(ValidatorIndex.of(index)); - } - expectedIndices.add(indices); - } - List> validatorIndices = + List initialValidatorIndices = + IntStream.range(0, testCase.getCount()) + .mapToObj(ValidatorIndex::new) + .collect(Collectors.toList()); + List expectedIndices = + testCase.getShuffled().stream().map(ValidatorIndex::new).collect(Collectors.toList()); + List validatorIndices = getShuffling.apply( new Triplet<>( - Hash32.fromHexString(testCase.getSeed()), validatorReadList, currentEpoch)); + initialValidatorIndices, + Bytes32.fromHexString(testCase.getSeed()), + testCase.getCount())); return assertLists(expectedIndices, validatorIndices); } } diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/SszRunner.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/SszGenericRunner.java similarity index 81% rename from test/src/test/java/org/ethereum/beacon/test/runner/ssz/SszRunner.java rename to test/src/test/java/org/ethereum/beacon/test/runner/ssz/SszGenericRunner.java index 5fe164382..3fe0d4d57 100644 --- a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/SszRunner.java +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/SszGenericRunner.java @@ -11,22 +11,24 @@ import org.ethereum.beacon.ssz.access.container.SSZSchemeBuilder; import org.ethereum.beacon.ssz.annotation.SSZSerializable; import org.ethereum.beacon.test.runner.Runner; -import org.ethereum.beacon.test.type.ssz.SszTestCase; +import org.ethereum.beacon.test.type.ssz.SszGenericCase; import org.ethereum.beacon.test.type.TestCase; import tech.pegasys.artemis.util.bytes.BytesValue; -/** TestRunner for {@link SszTestCase} */ -public class SszRunner implements Runner { - private SszTestCase testCase; +/** TestRunner for {@link SszGenericCase} + *

Test format description: https://github.com/ethereum/eth2.0-specs/tree/dev/specs/test_formats/ssz_generic + */ +public class SszGenericRunner implements Runner { + private SszGenericCase testCase; private BeaconChainSpec spec; private SSZSchemeBuilder.SSZScheme currentScheme; private SSZSerializer sszSerializer; - public SszRunner(TestCase testCase, BeaconChainSpec spec) { - if (!(testCase instanceof SszTestCase)) { - throw new RuntimeException("TestCase runner accepts only SszTestCase.class as input!"); + public SszGenericRunner(TestCase testCase, BeaconChainSpec spec) { + if (!(testCase instanceof SszGenericCase)) { + throw new RuntimeException("TestCase runner accepts only SszGenericCase.class as input!"); } - this.testCase = (SszTestCase) testCase; + this.testCase = (SszGenericCase) testCase; this.spec = spec; SSZBuilder builder = new SSZBuilder(); builder.withSSZSchemeBuilder(clazz -> currentScheme); diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/SszStaticRunner.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/SszStaticRunner.java new file mode 100644 index 000000000..d54892277 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/SszStaticRunner.java @@ -0,0 +1,150 @@ +package org.ethereum.beacon.test.runner.ssz; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import com.google.common.reflect.ClassPath; +import com.google.common.reflect.ClassPath.ClassInfo; +import org.ethereum.beacon.consensus.BeaconChainSpec; +import org.ethereum.beacon.core.spec.SpecConstantsResolver; +import org.ethereum.beacon.ssz.SSZBuilder; +import org.ethereum.beacon.ssz.SSZSerializer; +import org.ethereum.beacon.ssz.creator.ConstructorObjCreator; +import org.ethereum.beacon.test.runner.Runner; +import org.ethereum.beacon.test.runner.ssz.mapper.ObjectSerializer; +import org.ethereum.beacon.test.type.TestCase; +import org.ethereum.beacon.test.type.ssz.SszStaticCase; +import tech.pegasys.artemis.util.bytes.BytesValue; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import static org.ethereum.beacon.test.SilentAsserts.assertEquals; +import static org.ethereum.beacon.test.SilentAsserts.assertHexStrings; + +/** + * SSZ, Hash root, signing root tests for known types + * + *

Test format description: https://github.com/ethereum/eth2.0-specs/blob/dev/specs/test_formats/ssz_static/core.md + */ +public class SszStaticRunner implements Runner { + private SszStaticCase testCase; + private SSZSerializer sszSerializer; + private ObjectMapper yamlMapper; + private BeaconChainSpec spec; + private Map objectSerializers = new HashMap<>(); + private Set coreTypes; + + public SszStaticRunner(TestCase testCase, BeaconChainSpec spec) { + if (!(testCase instanceof SszStaticCase)) { + throw new RuntimeException("TestCase runner accepts only SszStaticCase.class as input!"); + } + this.testCase = (SszStaticCase) testCase; + SSZBuilder builder = new SSZBuilder(); + this.sszSerializer = + builder + .withExternalVarResolver(new SpecConstantsResolver(spec.getConstants())) + .buildSerializer(); + this.yamlMapper = new ObjectMapper(new YAMLFactory()); + this.spec = spec; + + // objectSerializers filling + Set availableSerializers = + findClassesInPackage("org.ethereum.beacon.test.runner.ssz.mapper"); + availableSerializers.stream() + .map(this::fromInfo) + .map((Class mapperType) -> createInstance(mapperType, yamlMapper)) + .forEach( + m -> { + if (m == null) { + return; // Couldn't create instance, for example, for interface, so it's not a + // serializer + } + ObjectSerializer mapper = (ObjectSerializer) m; + objectSerializers.put(mapper.accepts(), mapper); + }); + + // Filling set with spec types + this.coreTypes = findClassesInPackage("org.ethereum.beacon.core"); + } + + /** Instantiating {@link ObjectSerializer} */ + private ObjectSerializer createInstance( + Class mapperType, ObjectMapper jacksonMapper) { + return ConstructorObjCreator.createInstanceWithConstructor( + mapperType, new Class[] {ObjectMapper.class}, new Object[] {jacksonMapper}); + } + + private Set findClassesInPackage(String packageName) { + ClassPath classPath = null; + try { + classPath = ClassPath.from(getClass().getClassLoader()); + } catch (IOException e) { + throw new RuntimeException(e); + } + Set classes = classPath.getTopLevelClassesRecursive(packageName); + + return classes; + } + + /** {@link ClassInfo} -> {@link Class} mapper */ + private Class fromInfo(ClassInfo classInfo) { + Class valueType = null; + try { + valueType = Class.forName(classInfo.getName()); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + + return valueType; + } + + private Class findSpecClassByName(String name) { + final String searchName; + if (name.equals("Validator")) { + searchName = "ValidatorRecord"; // XXX: we have different naming + } else if (name.equals("BeaconState")) { + searchName = "BeaconStateImpl"; // XXX: we have several implementations + } else { + searchName = name; + } + List classes = + coreTypes.stream() + .filter((type) -> type.getSimpleName().equals(searchName)) + .collect(Collectors.toList()); + ClassInfo valueTypeInfo; + if (classes.size() != 1) { + throw new RuntimeException( + String.format( + "Failed: should be only one appropriate core class for %s (%s classes found) ", + name, classes.size())); + } else { + valueTypeInfo = classes.get(0); + } + + return fromInfo(valueTypeInfo); + } + + public Optional run() { + Class valueType = findSpecClassByName(testCase.getTypeName()); + Object fromSerialized = + sszSerializer.decode(BytesValue.fromHexString(testCase.getSerialized()), valueType); + Object simplified = objectSerializers.get(valueType).map(fromSerialized); + ObjectNode expectedValue = yamlMapper.convertValue(testCase.getValue(), ObjectNode.class); + // XXX: expected goes second as our constructed node contains with overridden `equals` operators + // which should be used in comparison + assertEquals(simplified, expectedValue); + assertHexStrings(testCase.getRoot(), spec.hash_tree_root(fromSerialized).toString()); + if (testCase.getSigningRoot() != null) { + assertHexStrings(testCase.getSigningRoot(), spec.signing_root(fromSerialized).toString()); + } + + return Optional.empty(); + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/AttestationDataAndCustodyBitSerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/AttestationDataAndCustodyBitSerializer.java new file mode 100644 index 000000000..da922113b --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/AttestationDataAndCustodyBitSerializer.java @@ -0,0 +1,27 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ethereum.beacon.core.operations.attestation.AttestationDataAndCustodyBit; + +public class AttestationDataAndCustodyBitSerializer implements ObjectSerializer { + private com.fasterxml.jackson.databind.ObjectMapper mapper; + private AttestationDataSerializer attestationDataSerializer; + + public AttestationDataAndCustodyBitSerializer(com.fasterxml.jackson.databind.ObjectMapper mapper) { + this.mapper = mapper; + this.attestationDataSerializer = new AttestationDataSerializer(mapper); + } + + @Override + public Class accepts() { + return AttestationDataAndCustodyBit.class; + } + + @Override + public ObjectNode map(AttestationDataAndCustodyBit instance) { + ObjectNode attestationDataAndCustodyBit = mapper.createObjectNode(); + attestationDataAndCustodyBit.set("data", attestationDataSerializer.map(instance.getData())); + attestationDataAndCustodyBit.put("custody_bit", instance.isCustodyBit()); + return attestationDataAndCustodyBit; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/AttestationDataSerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/AttestationDataSerializer.java new file mode 100644 index 000000000..90da6ff76 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/AttestationDataSerializer.java @@ -0,0 +1,31 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ethereum.beacon.core.operations.attestation.AttestationData; + +public class AttestationDataSerializer implements ObjectSerializer { + private com.fasterxml.jackson.databind.ObjectMapper mapper; + + public AttestationDataSerializer(com.fasterxml.jackson.databind.ObjectMapper mapper) { + this.mapper = mapper; + } + + @Override + public Class accepts() { + return AttestationData.class; + } + + @Override + public ObjectNode map(AttestationData instance) { + ObjectNode attestationData = mapper.createObjectNode(); + attestationData.put("beacon_block_root", instance.getBeaconBlockRoot().toString()); + attestationData.set("source_epoch", ComparableBigIntegerNode.valueOf(instance.getSourceEpoch())); + attestationData.put("source_root", instance.getSourceRoot().toString()); + attestationData.set("target_epoch", ComparableBigIntegerNode.valueOf(instance.getTargetEpoch())); + attestationData.put("target_root", instance.getTargetRoot().toString()); + attestationData.set("shard", ComparableBigIntegerNode.valueOf(instance.getShard())); + attestationData.put("previous_crosslink_root", instance.getPreviousCrosslinkRoot().toString()); + attestationData.put("crosslink_data_root", instance.getCrosslinkDataRoot().toString()); + return attestationData; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/AttestationSerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/AttestationSerializer.java new file mode 100644 index 000000000..1592a48f1 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/AttestationSerializer.java @@ -0,0 +1,30 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ethereum.beacon.core.operations.Attestation; +import tech.pegasys.artemis.util.bytes.BytesValue; + +public class AttestationSerializer implements ObjectSerializer { + private com.fasterxml.jackson.databind.ObjectMapper mapper; + private AttestationDataSerializer attestationDataSerializer; + + public AttestationSerializer(com.fasterxml.jackson.databind.ObjectMapper mapper) { + this.mapper = mapper; + this.attestationDataSerializer = new AttestationDataSerializer(mapper); + } + + @Override + public Class accepts() { + return Attestation.class; + } + + @Override + public ObjectNode map(Attestation instance) { + ObjectNode attestation = mapper.createObjectNode(); + attestation.put("aggregation_bitfield", instance.getAggregationBitfield().toString()); + attestation.set("data", attestationDataSerializer.map(instance.getData())); + attestation.put("custody_bitfield", instance.getCustodyBitfield().toString()); + attestation.put("signature", BytesValue.wrap(instance.getSignature().getArrayUnsafe()).toString()); + return attestation; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/AttesterSlashingSerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/AttesterSlashingSerializer.java new file mode 100644 index 000000000..82ab399b2 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/AttesterSlashingSerializer.java @@ -0,0 +1,28 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ethereum.beacon.core.operations.ProposerSlashing; +import org.ethereum.beacon.core.operations.slashing.AttesterSlashing; + +public class AttesterSlashingSerializer implements ObjectSerializer { + private com.fasterxml.jackson.databind.ObjectMapper mapper; + private IndexedAttestationSerializer indexedAttestationSerializer; + + public AttesterSlashingSerializer(com.fasterxml.jackson.databind.ObjectMapper mapper) { + this.mapper = mapper; + this.indexedAttestationSerializer = new IndexedAttestationSerializer(mapper); + } + + @Override + public Class accepts() { + return AttesterSlashing.class; + } + + @Override + public ObjectNode map(AttesterSlashing instance) { + ObjectNode attesterSlashing = mapper.createObjectNode(); + attesterSlashing.set("attestation_1", indexedAttestationSerializer.map(instance.getAttestation1())); + attesterSlashing.set("attestation_2", indexedAttestationSerializer.map(instance.getAttestation2())); + return attesterSlashing; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/BeaconBlockHeaderSerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/BeaconBlockHeaderSerializer.java new file mode 100644 index 000000000..26f25c685 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/BeaconBlockHeaderSerializer.java @@ -0,0 +1,29 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ethereum.beacon.core.BeaconBlockHeader; +import tech.pegasys.artemis.util.bytes.BytesValue; + +public class BeaconBlockHeaderSerializer implements ObjectSerializer { + private com.fasterxml.jackson.databind.ObjectMapper mapper; + + public BeaconBlockHeaderSerializer(com.fasterxml.jackson.databind.ObjectMapper mapper) { + this.mapper = mapper; + } + + @Override + public Class accepts() { + return BeaconBlockHeader.class; + } + + @Override + public ObjectNode map(BeaconBlockHeader instance) { + ObjectNode beaconBlockHeader = mapper.createObjectNode(); + beaconBlockHeader.set("slot", ComparableBigIntegerNode.valueOf(instance.getSlot())); + beaconBlockHeader.put("previous_block_root", instance.getPreviousBlockRoot().toString()); + beaconBlockHeader.put("state_root", instance.getStateRoot().toString()); + beaconBlockHeader.put("block_body_root", instance.getBlockBodyRoot().toString()); + beaconBlockHeader.put("signature", BytesValue.wrap(instance.getSignature().getArrayUnsafe()).toString()); + return beaconBlockHeader; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/BeaconStateSerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/BeaconStateSerializer.java new file mode 100644 index 000000000..fc7c6f479 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/BeaconStateSerializer.java @@ -0,0 +1,99 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ethereum.beacon.core.state.BeaconStateImpl; +import tech.pegasys.artemis.ethereum.core.Hash32; + +public class BeaconStateSerializer implements ObjectSerializer { + private com.fasterxml.jackson.databind.ObjectMapper mapper; + private ForkSerializer forkSerializer; + private ValidatorSerializer validatorSerializer; + private PendingAttestationSerializer pendingAttestationSerializer; + private CrosslinkSerializer crosslinkSerializer; + private BeaconBlockHeaderSerializer beaconBlockHeaderSerializer; + private Eth1DataSerializer eth1DataSerializer; + + public BeaconStateSerializer(com.fasterxml.jackson.databind.ObjectMapper mapper) { + this.mapper = mapper; + this.forkSerializer = new ForkSerializer(mapper); + this.validatorSerializer = new ValidatorSerializer(mapper); + this.pendingAttestationSerializer = new PendingAttestationSerializer(mapper); + this.crosslinkSerializer = new CrosslinkSerializer(mapper); + this.beaconBlockHeaderSerializer = new BeaconBlockHeaderSerializer(mapper); + this.eth1DataSerializer = new Eth1DataSerializer(mapper); + } + + @Override + public Class accepts() { + return BeaconStateImpl.class; + } + + @Override + public ObjectNode map(BeaconStateImpl instance) { + ObjectNode beaconState = mapper.createObjectNode(); + beaconState.set("slot", ComparableBigIntegerNode.valueOf(instance.getSlot())); + beaconState.set("genesis_time", ComparableBigIntegerNode.valueOf(instance.getGenesisTime())); + beaconState.set("fork", forkSerializer.map(instance.getFork())); + + ArrayNode validatorRegistryNode = mapper.createArrayNode(); + instance.getValidatorRegistry().stream().map(o -> validatorSerializer.map(o)).forEachOrdered(validatorRegistryNode::add); + beaconState.set("validator_registry", validatorRegistryNode); + ArrayNode balancesNode = mapper.createArrayNode(); + instance.getBalances().stream().map(ComparableBigIntegerNode::valueOf).forEachOrdered(balancesNode::add); + beaconState.set("balances", balancesNode); + + ArrayNode latestRandaoMixes = mapper.createArrayNode(); + instance.getLatestRandaoMixes().stream() + .map(Hash32::toString) + .forEachOrdered(latestRandaoMixes::add); + beaconState.set("latest_randao_mixes", latestRandaoMixes); + beaconState.set("latest_start_shard", ComparableBigIntegerNode.valueOf(instance.getLatestStartShard())); + + ArrayNode previousEpochAttestationNode = mapper.createArrayNode(); + instance.getPreviousEpochAttestations().stream().map(o -> pendingAttestationSerializer.map(o)).forEachOrdered(previousEpochAttestationNode::add); + beaconState.set("previous_epoch_attestations", previousEpochAttestationNode); + ArrayNode currentEpochAttestationsNode = mapper.createArrayNode(); + instance.getCurrentEpochAttestations().stream().map(o -> pendingAttestationSerializer.map(o)).forEachOrdered(currentEpochAttestationsNode::add); + beaconState.set("current_epoch_attestations", currentEpochAttestationsNode); + beaconState.set("previous_justified_epoch", ComparableBigIntegerNode.valueOf(instance.getPreviousJustifiedEpoch())); + beaconState.set("current_justified_epoch", ComparableBigIntegerNode.valueOf(instance.getCurrentJustifiedEpoch())); + beaconState.put("previous_justified_root", instance.getPreviousJustifiedRoot().toString()); + beaconState.put("current_justified_root", instance.getCurrentJustifiedRoot().toString()); + beaconState.put("justification_bitfield", instance.getJustificationBitfield().toString()); + beaconState.set("finalized_epoch", ComparableBigIntegerNode.valueOf(instance.getFinalizedEpoch())); + beaconState.put("finalized_root", instance.getFinalizedRoot().toString()); + + ArrayNode currentCrosslinksNode = mapper.createArrayNode(); + instance.getCurrentCrosslinks().stream().map(o -> crosslinkSerializer.map(o)).forEachOrdered(currentCrosslinksNode::add); + beaconState.set("current_crosslinks", currentCrosslinksNode); + ArrayNode previousCrosslinksNode = mapper.createArrayNode(); + instance.getPreviousCrosslinks().stream().map(o -> crosslinkSerializer.map(o)).forEachOrdered(previousCrosslinksNode::add); + beaconState.set("previous_crosslinks", previousCrosslinksNode); + ArrayNode latestBlockRootsNode = mapper.createArrayNode(); + instance.getLatestBlockRoots().stream().map(Hash32::toString).forEachOrdered(latestBlockRootsNode::add); + beaconState.set("latest_block_roots", latestBlockRootsNode); + ArrayNode latestStateRootsNode = mapper.createArrayNode(); + instance.getLatestStateRoots().stream().map(Hash32::toString).forEachOrdered(latestStateRootsNode::add); + beaconState.set("latest_state_roots", latestStateRootsNode); + ArrayNode latestActiveIndexRootsNode = mapper.createArrayNode(); + instance.getLatestActiveIndexRoots().stream().map(Hash32::toString).forEachOrdered(latestActiveIndexRootsNode::add); + beaconState.set("latest_active_index_roots", latestActiveIndexRootsNode); + ArrayNode latestSlashedBalancesNode = mapper.createArrayNode(); + instance.getLatestSlashedBalances().stream() + .map(ComparableBigIntegerNode::valueOf) + .forEachOrdered(latestSlashedBalancesNode::add); + beaconState.set("latest_slashed_balances", latestSlashedBalancesNode); + beaconState.set("latest_block_header", beaconBlockHeaderSerializer.map(instance.getLatestBlockHeader())); + ArrayNode historicalRootsNode = mapper.createArrayNode(); + instance.getHistoricalRoots().stream().map(Hash32::toString).forEachOrdered(historicalRootsNode::add); + beaconState.set("historical_roots", historicalRootsNode); + + beaconState.set("latest_eth1_data", eth1DataSerializer.map(instance.getLatestEth1Data())); + ArrayNode eth1DataVotesNode = mapper.createArrayNode(); + instance.getEth1DataVotes().stream().map(o -> eth1DataSerializer.map(o)).forEachOrdered(eth1DataVotesNode::add); + beaconState.set("eth1_data_votes", eth1DataVotesNode); + beaconState.set("deposit_index", ComparableBigIntegerNode.valueOf(instance.getDepositIndex())); + return beaconState; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/BlockBodySerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/BlockBodySerializer.java new file mode 100644 index 000000000..4f247d46a --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/BlockBodySerializer.java @@ -0,0 +1,59 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ethereum.beacon.core.BeaconBlockBody; + +public class BlockBodySerializer implements ObjectSerializer { + private com.fasterxml.jackson.databind.ObjectMapper mapper; + private Eth1DataSerializer eth1DataSerializer; + private ProposerSlashingSerializer proposerSlashingSerializer; + private AttesterSlashingSerializer attesterSlashingSerializer; + private AttestationSerializer attestationSerializer; + private DepositSerializer depositSerializer; + private VoluntaryExitSerializer voluntaryExitSerializer; + private TransferSerializer transferSerializer; + + public BlockBodySerializer(com.fasterxml.jackson.databind.ObjectMapper mapper) { + this.mapper = mapper; + this.eth1DataSerializer = new Eth1DataSerializer(mapper); + this.proposerSlashingSerializer = new ProposerSlashingSerializer(mapper); + this.attesterSlashingSerializer = new AttesterSlashingSerializer(mapper); + this.attestationSerializer = new AttestationSerializer(mapper); + this.depositSerializer = new DepositSerializer(mapper); + this.voluntaryExitSerializer = new VoluntaryExitSerializer(mapper); + this.transferSerializer = new TransferSerializer(mapper); + } + + @Override + public Class accepts() { + return BeaconBlockBody.class; + } + + @Override + public ObjectNode map(BeaconBlockBody instance) { + ObjectNode blockBody = mapper.createObjectNode(); + blockBody.put("randao_reveal", instance.getRandaoReveal().toString()); + blockBody.set("eth1_data", eth1DataSerializer.map(instance.getEth1Data())); + blockBody.put("graffiti", instance.getGraffiti().toString()); + ArrayNode proposerSlashingNode = mapper.createArrayNode(); + instance.getProposerSlashings().stream().map(o -> proposerSlashingSerializer.map(o)).forEachOrdered(proposerSlashingNode::add); + blockBody.set("proposer_slashings", proposerSlashingNode); + ArrayNode attesterSlashingNode = mapper.createArrayNode(); + instance.getAttesterSlashings().stream().map(o -> attesterSlashingSerializer.map(o)).forEachOrdered(attesterSlashingNode::add); + blockBody.set("attester_slashings", attesterSlashingNode); + ArrayNode attestationsNode = mapper.createArrayNode(); + instance.getAttestations().stream().map(o -> attestationSerializer.map(o)).forEachOrdered(attestationsNode::add); + blockBody.set("attestations", attestationsNode); + ArrayNode depositsNode = mapper.createArrayNode(); + instance.getDeposits().stream().map(o -> depositSerializer.map(o)).forEachOrdered(depositsNode::add); + blockBody.set("deposits", depositsNode); + ArrayNode voluntaryExitsNode = mapper.createArrayNode(); + instance.getVoluntaryExits().stream().map(o -> voluntaryExitSerializer.map(o)).forEachOrdered(voluntaryExitsNode::add); + blockBody.set("voluntary_exits", voluntaryExitsNode); + ArrayNode transfersNode = mapper.createArrayNode(); + instance.getTransfers().stream().map(o -> transferSerializer.map(o)).forEachOrdered(transfersNode::add); + blockBody.set("transfers", transfersNode); + return blockBody; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/BlockSerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/BlockSerializer.java new file mode 100644 index 000000000..59af1ed88 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/BlockSerializer.java @@ -0,0 +1,31 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ethereum.beacon.core.BeaconBlock; +import tech.pegasys.artemis.util.bytes.BytesValue; + +public class BlockSerializer implements ObjectSerializer { + private com.fasterxml.jackson.databind.ObjectMapper mapper; + private BlockBodySerializer blockBodySerializer; + + public BlockSerializer(com.fasterxml.jackson.databind.ObjectMapper mapper) { + this.mapper = mapper; + this.blockBodySerializer = new BlockBodySerializer(mapper); + } + + @Override + public Class accepts() { + return BeaconBlock.class; + } + + @Override + public ObjectNode map(BeaconBlock instance) { + ObjectNode beaconBlock = mapper.createObjectNode(); + beaconBlock.set("slot", ComparableBigIntegerNode.valueOf(instance.getSlot())); + beaconBlock.put("previous_block_root", instance.getPreviousBlockRoot().toString()); + beaconBlock.put("state_root", instance.getStateRoot().toString()); + beaconBlock.set("body", blockBodySerializer.map(instance.getBody())); + beaconBlock.put("signature", BytesValue.wrap(instance.getSignature().getArrayUnsafe()).toString()); + return beaconBlock; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/ComparableBigIntegerNode.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/ComparableBigIntegerNode.java new file mode 100644 index 000000000..b0645a614 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/ComparableBigIntegerNode.java @@ -0,0 +1,41 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.BigIntegerNode; +import com.fasterxml.jackson.databind.node.IntNode; +import com.fasterxml.jackson.databind.node.LongNode; +import com.fasterxml.jackson.databind.node.NumericNode; +import tech.pegasys.artemis.util.uint.UInt64; + +import java.math.BigInteger; + +/** + * {@link BigIntegerNode} with overridden {@link #equals(Object)} method which ignores type of + * {@link NumericNode} when comparing to another {@link NumericNode}, so only contents is compared. + * Please note, as {@link #equals(Object)} method is called from the first object when comparing + * like `a.equals(b)`, Object `a` should be of type {@link ComparableBigIntegerNode} + */ +public class ComparableBigIntegerNode extends BigIntegerNode { + + private ComparableBigIntegerNode(BigInteger v) { + super(v); + } + + static JsonNode valueOf(UInt64 value) { + return new ComparableBigIntegerNode(value.toBI()); + } + + @Override + public boolean equals(Object o) { + boolean superResult = super.equals(o); + if (superResult) { + return true; + } + + if (o instanceof IntNode || o instanceof LongNode) { + return ((NumericNode) o).bigIntegerValue().equals(this.bigIntegerValue()); + } + + return false; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/CrosslinkSerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/CrosslinkSerializer.java new file mode 100644 index 000000000..21d078631 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/CrosslinkSerializer.java @@ -0,0 +1,26 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ethereum.beacon.core.operations.attestation.Crosslink; + +public class CrosslinkSerializer implements ObjectSerializer { + private com.fasterxml.jackson.databind.ObjectMapper mapper; + + public CrosslinkSerializer(com.fasterxml.jackson.databind.ObjectMapper mapper) { + this.mapper = mapper; + } + + @Override + public Class accepts() { + return Crosslink.class; + } + + @Override + public ObjectNode map(Crosslink instance) { + ObjectNode crosslink = mapper.createObjectNode(); + crosslink.set("epoch", ComparableBigIntegerNode.valueOf(instance.getEpoch())); + crosslink.put("previous_crosslink_root", instance.getPreviousCrosslinkRoot().toString()); + crosslink.put("crosslink_data_root", instance.getCrosslinkDataRoot().toString()); + return crosslink; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/DepositDataSerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/DepositDataSerializer.java new file mode 100644 index 000000000..e3933db43 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/DepositDataSerializer.java @@ -0,0 +1,29 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ethereum.beacon.core.operations.deposit.DepositData; +import org.ethereum.beacon.core.state.Fork; +import tech.pegasys.artemis.util.bytes.BytesValue; + +public class DepositDataSerializer implements ObjectSerializer { + private com.fasterxml.jackson.databind.ObjectMapper mapper; + + public DepositDataSerializer(com.fasterxml.jackson.databind.ObjectMapper mapper) { + this.mapper = mapper; + } + + @Override + public Class accepts() { + return DepositData.class; + } + + @Override + public ObjectNode map(DepositData instance) { + ObjectNode depositData = mapper.createObjectNode(); + depositData.put("pubkey", BytesValue.wrap(instance.getPubKey().getArrayUnsafe()).toString()); + depositData.put("withdrawal_credentials", instance.getWithdrawalCredentials().toString()); + depositData.set("amount", ComparableBigIntegerNode.valueOf(instance.getAmount())); + depositData.put("signature", BytesValue.wrap(instance.getSignature().getArrayUnsafe()).toString()); + return depositData; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/DepositSerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/DepositSerializer.java new file mode 100644 index 000000000..2b321a1bf --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/DepositSerializer.java @@ -0,0 +1,33 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ethereum.beacon.core.operations.Deposit; + +import java.util.Objects; + +public class DepositSerializer implements ObjectSerializer { + private com.fasterxml.jackson.databind.ObjectMapper mapper; + private DepositDataSerializer depositDataSerializer; + + public DepositSerializer(com.fasterxml.jackson.databind.ObjectMapper mapper) { + this.mapper = mapper; + this.depositDataSerializer = new DepositDataSerializer(mapper); + } + + @Override + public Class accepts() { + return Deposit.class; + } + + @Override + public ObjectNode map(Deposit instance) { + ObjectNode attestation = mapper.createObjectNode(); + ArrayNode proofNode = mapper.createArrayNode(); + instance.getProof().stream().map(Objects::toString).forEachOrdered(proofNode::add); + attestation.set("proof", proofNode); + attestation.put("index", instance.getIndex().getValue()); + attestation.set("data", depositDataSerializer.map(instance.getData())); + return attestation; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/Eth1DataSerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/Eth1DataSerializer.java new file mode 100644 index 000000000..3bb3f00af --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/Eth1DataSerializer.java @@ -0,0 +1,26 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ethereum.beacon.core.state.Eth1Data; + +public class Eth1DataSerializer implements ObjectSerializer { + private com.fasterxml.jackson.databind.ObjectMapper mapper; + + public Eth1DataSerializer(com.fasterxml.jackson.databind.ObjectMapper mapper) { + this.mapper = mapper; + } + + @Override + public Class accepts() { + return Eth1Data.class; + } + + @Override + public ObjectNode map(Eth1Data instance) { + ObjectNode eth1Data = mapper.createObjectNode(); + eth1Data.put("deposit_root", instance.getDepositRoot().toString()); + eth1Data.set("deposit_count", ComparableBigIntegerNode.valueOf(instance.getDepositCount())); + eth1Data.put("block_hash", instance.getBlockHash().toString()); + return eth1Data; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/ForkSerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/ForkSerializer.java new file mode 100644 index 000000000..67c072e8e --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/ForkSerializer.java @@ -0,0 +1,26 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ethereum.beacon.core.state.Fork; + +public class ForkSerializer implements ObjectSerializer { + private com.fasterxml.jackson.databind.ObjectMapper mapper; + + public ForkSerializer(com.fasterxml.jackson.databind.ObjectMapper mapper) { + this.mapper = mapper; + } + + @Override + public Class accepts() { + return Fork.class; + } + + @Override + public ObjectNode map(Fork instance) { + ObjectNode fork = mapper.createObjectNode(); + fork.put("previous_version", instance.getPreviousVersion().toString()); + fork.put("current_version", instance.getCurrentVersion().toString()); + fork.set("epoch", ComparableBigIntegerNode.valueOf(instance.getEpoch())); + return fork; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/HistoricalBatchSerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/HistoricalBatchSerializer.java new file mode 100644 index 000000000..949fc796b --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/HistoricalBatchSerializer.java @@ -0,0 +1,32 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ethereum.beacon.core.state.HistoricalBatch; + +import java.util.Objects; + +public class HistoricalBatchSerializer implements ObjectSerializer { + private com.fasterxml.jackson.databind.ObjectMapper mapper; + + public HistoricalBatchSerializer(com.fasterxml.jackson.databind.ObjectMapper mapper) { + this.mapper = mapper; + } + + @Override + public Class accepts() { + return HistoricalBatch.class; + } + + @Override + public ObjectNode map(HistoricalBatch instance) { + ObjectNode historicalBatch = mapper.createObjectNode(); + ArrayNode blockRootsNode = mapper.createArrayNode(); + instance.getBlockRoots().stream().map(Objects::toString).forEachOrdered(blockRootsNode::add); + historicalBatch.set("block_roots", blockRootsNode); + ArrayNode stateRootsNode = mapper.createArrayNode(); + instance.getStateRoots().stream().map(Objects::toString).forEachOrdered(stateRootsNode::add); + historicalBatch.set("state_roots", stateRootsNode); + return historicalBatch; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/IndexedAttestationSerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/IndexedAttestationSerializer.java new file mode 100644 index 000000000..1a5e86690 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/IndexedAttestationSerializer.java @@ -0,0 +1,35 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ethereum.beacon.core.operations.slashing.IndexedAttestation; +import tech.pegasys.artemis.util.bytes.BytesValue; + +public class IndexedAttestationSerializer implements ObjectSerializer { + private com.fasterxml.jackson.databind.ObjectMapper mapper; + private AttestationDataSerializer attestationDataSerializer; + + public IndexedAttestationSerializer(com.fasterxml.jackson.databind.ObjectMapper mapper) { + this.mapper = mapper; + this.attestationDataSerializer = new AttestationDataSerializer(mapper); + } + + @Override + public Class accepts() { + return IndexedAttestation.class; + } + + @Override + public ObjectNode map(IndexedAttestation instance) { + ObjectNode slashableAttestation = mapper.createObjectNode(); + ArrayNode indices0 = mapper.createArrayNode(); + instance.getCustodyBit0Indices().stream().map(ComparableBigIntegerNode::valueOf).forEachOrdered(indices0::add); + slashableAttestation.set("custody_bit_0_indices", indices0); + ArrayNode indices1 = mapper.createArrayNode(); + instance.getCustodyBit1Indices().stream().map(ComparableBigIntegerNode::valueOf).forEachOrdered(indices1::add); + slashableAttestation.set("custody_bit_1_indices", indices1); + slashableAttestation.set("data", attestationDataSerializer.map(instance.getData())); + slashableAttestation.put("signature", BytesValue.wrap(instance.getSignature().getArrayUnsafe()).toString()); + return slashableAttestation; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/ObjectSerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/ObjectSerializer.java new file mode 100644 index 000000000..8ac7c93df --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/ObjectSerializer.java @@ -0,0 +1,17 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.BigIntegerNode; +import com.fasterxml.jackson.databind.node.IntNode; +import com.fasterxml.jackson.databind.node.LongNode; +import com.fasterxml.jackson.databind.node.NumericNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import tech.pegasys.artemis.util.uint.UInt64; + +import java.math.BigInteger; + +public interface ObjectSerializer { + Class accepts(); + + Object map(V instance); +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/PendingAttestationSerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/PendingAttestationSerializer.java new file mode 100644 index 000000000..f2a79f5eb --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/PendingAttestationSerializer.java @@ -0,0 +1,29 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ethereum.beacon.core.state.PendingAttestation; + +public class PendingAttestationSerializer implements ObjectSerializer { + private com.fasterxml.jackson.databind.ObjectMapper mapper; + private AttestationDataSerializer attestationDataSerializer; + + public PendingAttestationSerializer(com.fasterxml.jackson.databind.ObjectMapper mapper) { + this.mapper = mapper; + this.attestationDataSerializer = new AttestationDataSerializer(mapper); + } + + @Override + public Class accepts() { + return PendingAttestation.class; + } + + @Override + public ObjectNode map(PendingAttestation instance) { + ObjectNode pendingAttestation = mapper.createObjectNode(); + pendingAttestation.put("aggregation_bitfield", instance.getAggregationBitfield().toString()); + pendingAttestation.set("data", attestationDataSerializer.map(instance.getData())); + pendingAttestation.set("inclusion_delay", ComparableBigIntegerNode.valueOf(instance.getInclusionDelay())); + pendingAttestation.set("proposer_index", ComparableBigIntegerNode.valueOf(instance.getProposerIndex())); + return pendingAttestation; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/ProposerSlashingSerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/ProposerSlashingSerializer.java new file mode 100644 index 000000000..b9d95f74d --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/ProposerSlashingSerializer.java @@ -0,0 +1,28 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ethereum.beacon.core.operations.ProposerSlashing; + +public class ProposerSlashingSerializer implements ObjectSerializer { + private com.fasterxml.jackson.databind.ObjectMapper mapper; + private BeaconBlockHeaderSerializer beaconBlockHeaderSerializer; + + public ProposerSlashingSerializer(com.fasterxml.jackson.databind.ObjectMapper mapper) { + this.mapper = mapper; + this.beaconBlockHeaderSerializer = new BeaconBlockHeaderSerializer(mapper); + } + + @Override + public Class accepts() { + return ProposerSlashing.class; + } + + @Override + public ObjectNode map(ProposerSlashing instance) { + ObjectNode proposerSlashing = mapper.createObjectNode(); + proposerSlashing.put("proposer_index", instance.getProposerIndex().getValue()); + proposerSlashing.set("header_1", beaconBlockHeaderSerializer.map(instance.getHeader1())); + proposerSlashing.set("header_2", beaconBlockHeaderSerializer.map(instance.getHeader2())); + return proposerSlashing; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/TransferSerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/TransferSerializer.java new file mode 100644 index 000000000..8e5492816 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/TransferSerializer.java @@ -0,0 +1,31 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ethereum.beacon.core.operations.Transfer; +import tech.pegasys.artemis.util.bytes.BytesValue; + +public class TransferSerializer implements ObjectSerializer { + private com.fasterxml.jackson.databind.ObjectMapper mapper; + + public TransferSerializer(com.fasterxml.jackson.databind.ObjectMapper mapper) { + this.mapper = mapper; + } + + @Override + public Class accepts() { + return Transfer.class; + } + + @Override + public ObjectNode map(Transfer instance) { + ObjectNode transfer = mapper.createObjectNode(); + transfer.set("sender", ComparableBigIntegerNode.valueOf(instance.getSender())); + transfer.set("recipient", ComparableBigIntegerNode.valueOf(instance.getRecipient())); + transfer.set("amount", ComparableBigIntegerNode.valueOf(instance.getAmount())); + transfer.set("fee", ComparableBigIntegerNode.valueOf(instance.getFee())); + transfer.set("slot", ComparableBigIntegerNode.valueOf(instance.getSlot())); + transfer.put("pubkey", BytesValue.wrap(instance.getPubkey().getArrayUnsafe()).toString()); + transfer.put("signature", BytesValue.wrap(instance.getSignature().getArrayUnsafe()).toString()); + return transfer; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/ValidatorSerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/ValidatorSerializer.java new file mode 100644 index 000000000..918bec6a3 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/ValidatorSerializer.java @@ -0,0 +1,32 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ethereum.beacon.core.state.ValidatorRecord; +import tech.pegasys.artemis.util.bytes.BytesValue; + +public class ValidatorSerializer implements ObjectSerializer { + private com.fasterxml.jackson.databind.ObjectMapper mapper; + + public ValidatorSerializer(com.fasterxml.jackson.databind.ObjectMapper mapper) { + this.mapper = mapper; + } + + @Override + public Class accepts() { + return ValidatorRecord.class; + } + + @Override + public ObjectNode map(ValidatorRecord instance) { + ObjectNode validatorRecord = mapper.createObjectNode(); + validatorRecord.put("pubkey", BytesValue.wrap(instance.getPubKey().getArrayUnsafe()).toString()); + validatorRecord.put("withdrawal_credentials", instance.getWithdrawalCredentials().toString()); + validatorRecord.set("activation_eligibility_epoch", ComparableBigIntegerNode.valueOf(instance.getActivationEligibilityEpoch())); + validatorRecord.set("activation_epoch", ComparableBigIntegerNode.valueOf(instance.getActivationEpoch())); + validatorRecord.set("exit_epoch", ComparableBigIntegerNode.valueOf(instance.getExitEpoch())); + validatorRecord.set("withdrawable_epoch", ComparableBigIntegerNode.valueOf(instance.getWithdrawableEpoch())); + validatorRecord.put("slashed", instance.getSlashed()); + validatorRecord.set("high_balance", ComparableBigIntegerNode.valueOf(instance.getEffectiveBalance())); + return validatorRecord; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/VoluntaryExitSerializer.java b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/VoluntaryExitSerializer.java new file mode 100644 index 000000000..ec89de027 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/runner/ssz/mapper/VoluntaryExitSerializer.java @@ -0,0 +1,27 @@ +package org.ethereum.beacon.test.runner.ssz.mapper; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ethereum.beacon.core.operations.VoluntaryExit; +import tech.pegasys.artemis.util.bytes.BytesValue; + +public class VoluntaryExitSerializer implements ObjectSerializer { + private com.fasterxml.jackson.databind.ObjectMapper mapper; + + public VoluntaryExitSerializer(com.fasterxml.jackson.databind.ObjectMapper mapper) { + this.mapper = mapper; + } + + @Override + public Class accepts() { + return VoluntaryExit.class; + } + + @Override + public ObjectNode map(VoluntaryExit instance) { + ObjectNode voluntaryExit = mapper.createObjectNode(); + voluntaryExit.set("epoch", ComparableBigIntegerNode.valueOf(instance.getEpoch())); + voluntaryExit.set("validator_index", ComparableBigIntegerNode.valueOf(instance.getValidatorIndex())); + voluntaryExit.put("signature", BytesValue.wrap(instance.getSignature().getArrayUnsafe()).toString()); + return voluntaryExit; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/state/StateComparator.java b/test/src/test/java/org/ethereum/beacon/test/runner/state/StateComparator.java index 87ed60b9f..3030ff032 100644 --- a/test/src/test/java/org/ethereum/beacon/test/runner/state/StateComparator.java +++ b/test/src/test/java/org/ethereum/beacon/test/runner/state/StateComparator.java @@ -7,8 +7,9 @@ import java.util.List; import java.util.Optional; import java.util.function.Supplier; -import org.ethereum.beacon.consensus.BeaconStateEx; + import org.ethereum.beacon.core.BeaconBlockHeader; +import org.ethereum.beacon.core.BeaconState; import org.ethereum.beacon.core.operations.attestation.Crosslink; import org.ethereum.beacon.core.state.Eth1Data; import org.ethereum.beacon.core.state.PendingAttestation; @@ -22,14 +23,14 @@ import tech.pegasys.artemis.util.uint.UInt64; public class StateComparator { - private BeaconStateEx actual; + private BeaconState actual; private StateTestCase.BeaconStateData expected; - public static Optional compare(StateTestCase.BeaconStateData expected, BeaconStateEx actual) { + public static Optional compare(StateTestCase.BeaconStateData expected, BeaconState actual) { return new StateComparator(expected, actual).compare(); } - private StateComparator(StateTestCase.BeaconStateData expected, BeaconStateEx actual) { + private StateComparator(StateTestCase.BeaconStateData expected, BeaconState actual) { this.expected = expected; this.actual = actual; } @@ -68,7 +69,8 @@ public Optional compare() { runComparison( "Latest active index roots do not match: ", this::compareLatestActiveIndexRoots, error); runComparison("Latest block header doesn't match: ", this::compareLatestBlockHeader, error); - runComparison("Latest crosslinks do not match: ", this::compareLatestCrosslinks, error); + runComparison("Current crosslinks do not match: ", this::compareCurrentCrosslinks, error); + runComparison("Previous crosslinks do not match: ", this::comparePreviousCrosslinks, error); runComparison("Latest Eth1 data doesn't match: ", this::compareLatestEth1Data, error); runComparison("Latest randao mixes do not match: ", this::compareLatestRandaoMixes, error); runComparison("Latest slashed balances do not match: ", this::compareSlashedBalances, error); @@ -109,12 +111,12 @@ private Optional compareLatestBlockRoots() { } private Optional compareValidatorBalances() { - if (expected.getValidatorBalances() == null) { + if (expected.getBalances() == null) { return Optional.empty(); } return assertLists( - StateTestUtils.parseBalances(expected.getValidatorBalances()), + StateTestUtils.parseBalances(expected.getBalances()), actual.getBalances().listCopy()); } @@ -184,17 +186,26 @@ private Optional compareLatestActiveIndexRoots() { return assertLists(expectedRoots, actual.getLatestActiveIndexRoots().listCopy()); } - private Optional compareLatestCrosslinks() { - if (expected.getLatestCrosslinks() == null) { + private Optional compareCurrentCrosslinks() { + if (expected.getCurrentCrosslinks() == null) { return Optional.empty(); } - // FIXME: already modified by Michael, it couldn't match the test fixtures List expectedCrosslinks = - StateTestUtils.parseCrosslinks(expected.getLatestCrosslinks()); + StateTestUtils.parseCrosslinks(expected.getCurrentCrosslinks()); return assertLists(expectedCrosslinks, actual.getCurrentCrosslinks().listCopy()); } + private Optional comparePreviousCrosslinks() { + if (expected.getPreviousCrosslinks() == null) { + return Optional.empty(); + } + + List expectedCrosslinks = + StateTestUtils.parseCrosslinks(expected.getPreviousCrosslinks()); + return assertLists(expectedCrosslinks, actual.getPreviousCrosslinks().listCopy()); + } + private Optional comparePreviousEpochAttestations() { if (expected.getPreviousEpochAttestations() == null) { return Optional.empty(); diff --git a/test/src/test/java/org/ethereum/beacon/test/runner/state/StateRunner.java b/test/src/test/java/org/ethereum/beacon/test/runner/state/StateRunner.java index 2e0379400..fa2712bc1 100644 --- a/test/src/test/java/org/ethereum/beacon/test/runner/state/StateRunner.java +++ b/test/src/test/java/org/ethereum/beacon/test/runner/state/StateRunner.java @@ -1,103 +1,116 @@ package org.ethereum.beacon.test.runner.state; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.lang.reflect.InvocationTargetException; -import java.util.Optional; import org.ethereum.beacon.consensus.BeaconChainSpec; -import org.ethereum.beacon.consensus.BeaconStateEx; -import org.ethereum.beacon.consensus.BlockTransition; -import org.ethereum.beacon.consensus.StateTransitions; -import org.ethereum.beacon.consensus.TransitionType; -import org.ethereum.beacon.consensus.transition.BeaconStateExImpl; -import org.ethereum.beacon.consensus.transition.EmptySlotTransition; -import org.ethereum.beacon.core.BeaconBlock; +import org.ethereum.beacon.consensus.spec.SpecCommons; +import org.ethereum.beacon.consensus.verifier.OperationVerifier; +import org.ethereum.beacon.consensus.verifier.VerificationResult; +import org.ethereum.beacon.consensus.verifier.operation.AttestationVerifier; +import org.ethereum.beacon.consensus.verifier.operation.DepositVerifier; import org.ethereum.beacon.core.BeaconState; -import org.ethereum.beacon.emulator.config.chainspec.SpecBuilder; -import org.ethereum.beacon.emulator.config.chainspec.SpecConstantsData; -import org.ethereum.beacon.emulator.config.chainspec.SpecData; -import org.ethereum.beacon.emulator.config.chainspec.SpecDataUtils; -import org.ethereum.beacon.emulator.config.chainspec.SpecHelpersData; +import org.ethereum.beacon.core.MutableBeaconState; +import org.ethereum.beacon.core.operations.Attestation; +import org.ethereum.beacon.core.operations.Deposit; import org.ethereum.beacon.test.StateTestUtils; import org.ethereum.beacon.test.runner.Runner; -import org.ethereum.beacon.test.runner.state.StateComparator; +import org.ethereum.beacon.test.type.TestCase; import org.ethereum.beacon.test.type.state.StateTestCase; import org.ethereum.beacon.test.type.state.StateTestCase.BeaconStateData; -import org.ethereum.beacon.test.type.TestCase; -import org.ethereum.beacon.util.Objects; import org.javatuples.Pair; -/** TestRunner for {@link StateTestCase} */ +import java.util.Optional; +import java.util.function.Consumer; + +/** + * TestRunner for {@link StateTestCase} + * + *

Test format description: https://github.com/ethereum/eth2.0-specs/tree/dev/specs/test_formats/operations + */ public class StateRunner implements Runner { private StateTestCase testCase; + private BeaconChainSpec spec; - public StateRunner(TestCase testCase) { + public StateRunner(TestCase testCase, BeaconChainSpec spec) { if (!(testCase instanceof StateTestCase)) { throw new RuntimeException("TestCase runner accepts only StateTestCase.class as input!"); } this.testCase = (StateTestCase) testCase; + this.spec = spec; } public Optional run() { - BeaconChainSpec spec; - try { - spec = buildSpec(testCase); - } catch (Exception e) { - return Optional.of("Failed to build BeaconChainSpec: " + e.getMessage()); - } - - BeaconStateEx initialState = buildInitialState(spec, testCase.getInitialState()); - Optional err = StateComparator.compare(testCase.getInitialState(), initialState); + BeaconState initialState = buildInitialState(spec, testCase.getPre()); + Optional err = StateComparator.compare(testCase.getPre(), initialState); if (err.isPresent()) { return Optional.of("Initial state parsed incorrectly: " + err.get()); } + BeaconState latestState = initialState; + Optional processingError; - EmptySlotTransition preBlockTransition = StateTransitions.preBlockTransition(spec); - BlockTransition blockTransition = StateTransitions.blockTransition(spec); + if (testCase.getDeposit() != null) { + processingError = processDeposit(testCase.getDepositOperation(), latestState); + } else if (testCase.getAttestation() != null) { + processingError = processAttestation(testCase.getAttestationOperation(), latestState); + } else { + throw new RuntimeException("Only Attestation and Deposit test cases are implemented!!!"); + } - BeaconStateEx latestState = initialState; - for (StateTestCase.BlockData blockData : testCase.getBlocks()) { - Pair> blockPair = StateTestUtils.parseBlockData(blockData); - if (blockPair.getValue1().isPresent()) { - return blockPair.getValue1(); + if (testCase.getPost() == null) { // XXX: Not changed + return StateComparator.compare(testCase.getPre(), latestState); + } else { + Optional compareResult = StateComparator.compare(testCase.getPost(), latestState); + if (!compareResult.isPresent()) { + return Optional.empty(); } - BeaconBlock block = blockPair.getValue0(); - BeaconStateEx postBlockState; - try { - BeaconStateEx preBlockState = preBlockTransition.apply(latestState, block.getSlot()); - postBlockState = blockTransition.apply(preBlockState, block); - } catch (Exception ex) { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - ex.printStackTrace(pw); - return Optional.of("Error happened during transition: " + sw.toString()); + String processingErrorMessage = "Processing error: "; + if (processingError.isPresent()) { + processingErrorMessage += processingError.get(); } - latestState = postBlockState; + return Optional.of(compareResult.get() + processingErrorMessage); } - - return StateComparator.compare(testCase.getExpectedState(), latestState); } - private BeaconStateEx buildInitialState(BeaconChainSpec spec, BeaconStateData stateData) { - BeaconState state = StateTestUtils.parseBeaconState(spec.getConstants(), stateData); - return new BeaconStateExImpl(state, TransitionType.BLOCK); + private Optional processDeposit(Deposit deposit, BeaconState state) { + DepositVerifier depositVerifier = new DepositVerifier(spec); + return processOperation( + deposit, + state, + depositVerifier, + objects -> + spec.process_deposit((MutableBeaconState) objects.getValue1(), objects.getValue0())); } - private BeaconChainSpec buildSpec(StateTestCase testCase) - throws InvocationTargetException, IllegalAccessException { - SpecConstantsData specConstantsData = - Objects.copyProperties( - SpecDataUtils.createSpecConstantsData(BeaconChainSpec.DEFAULT_CONSTANTS), - testCase.getConfig()); - - SpecHelpersData specHelpersData = new SpecHelpersData(); - specHelpersData.setBlsVerify(testCase.getVerifySignatures()); + private Optional processAttestation(Attestation attestation, BeaconState state) { + AttestationVerifier attestationVerifier = new AttestationVerifier(spec); + return processOperation( + attestation, + state, + attestationVerifier, + objects -> + spec.process_attestation( + (MutableBeaconState) objects.getValue1(), objects.getValue0())); + } - SpecData specData = new SpecData(); - specData.setSpecHelpersOptions(specHelpersData); - specData.setSpecConstants(specConstantsData); + private Optional processOperation( + O operation, + BeaconState state, + OperationVerifier verifier, + Consumer> operationProcessor) { + try { + VerificationResult verificationResult = verifier.verify(operation, state); + if (verificationResult.isPassed()) { + operationProcessor.accept(Pair.with(operation, state)); + return Optional.empty(); + } else { + return Optional.of(verificationResult.getMessage()); + } + } catch (SpecCommons.SpecAssertionFailed ex) { + return Optional.of(ex.getMessage()); + } + } - return new SpecBuilder().withSpec(specData).buildSpec(); + private BeaconState buildInitialState(BeaconChainSpec spec, BeaconStateData stateData) { + return StateTestUtils.parseBeaconState(spec.getConstants(), stateData); } } diff --git a/test/src/test/java/org/ethereum/beacon/test/type/TestSkeleton.java b/test/src/test/java/org/ethereum/beacon/test/type/TestSkeleton.java index 86b700514..d968a3d50 100644 --- a/test/src/test/java/org/ethereum/beacon/test/type/TestSkeleton.java +++ b/test/src/test/java/org/ethereum/beacon/test/type/TestSkeleton.java @@ -6,22 +6,23 @@ import java.util.List; /** - * Non-specific test from https://github.com/ethereum/eth2.0-tests/ - - * Eth2.0 community tests repository. Following fields, or a bit less are in any test. + * Common test suite format description: https://github.com/ethereum/eth2.0-specs/tree/dev/specs/test_formats#test-suite * *

Specific test cases are made by extension of this class. */ @JsonIgnoreProperties(ignoreUnknown = true) public abstract class TestSkeleton { - private String title; - private String summary; - private String version; - @JsonProperty("test_suite") - private String testSuite; - private String fork; @JsonProperty("test_cases") protected List testCases; + private String title; + private String summary; + @JsonProperty("forks_timeline") + private String forksTimeline; + private List forks; + private String config; + private String runner; + private String handler; public String getTitle() { return title; @@ -39,28 +40,44 @@ public void setSummary(String summary) { this.summary = summary; } - public String getTestSuite() { - return testSuite; + public String getForksTimeline() { + return forksTimeline; + } + + public void setForksTimeline(String forksTimeline) { + this.forksTimeline = forksTimeline; + } + + public List getForks() { + return forks; + } + + public void setForks(List forks) { + this.forks = forks; + } + + public String getConfig() { + return config; } - public void setTestSuite(String testSuite) { - this.testSuite = testSuite; + public void setConfig(String config) { + this.config = config; } - public String getFork() { - return fork; + public String getRunner() { + return runner; } - public void setFork(String fork) { - this.fork = fork; + public void setRunner(String runner) { + this.runner = runner; } - public String getVersion() { - return version; + public String getHandler() { + return handler; } - public void setVersion(String version) { - this.version = version; + public void setHandler(String handler) { + this.handler = handler; } public List getTestCases() { @@ -69,6 +86,6 @@ public List getTestCases() { @Override public String toString() { - return "Test \"" + title + " " + fork + '\"'; + return "Test \"" + title + " [" + String.join(",", forks) + "]\""; } } diff --git a/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsAggregatePubKeysCase.java b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsAggregatePubKeysCase.java new file mode 100644 index 000000000..3068546a2 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsAggregatePubKeysCase.java @@ -0,0 +1,38 @@ +package org.ethereum.beacon.test.type.bls; + +import org.ethereum.beacon.test.type.TestCase; + +import java.util.List; + +/** BLS aggregate public keys case */ +public class BlsAggregatePubKeysCase implements TestCase { + private List input; + private String output; + + public List getInput() { + return input; + } + + public void setInput(List input) { + this.input = input; + } + + public String getOutput() { + return output; + } + + public void setOutput(String output) { + this.output = output; + } + + @Override + public String toString() { + return "Aggregate public keys {" + + "input=" + + input.get(0).substring(0, 18) + + "...(total: " + + input.size() + + " public keys)" + + '}'; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsAggregatePubKeysTest.java b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsAggregatePubKeysTest.java new file mode 100644 index 000000000..28c7a254e --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsAggregatePubKeysTest.java @@ -0,0 +1,22 @@ +package org.ethereum.beacon.test.type.bls; + +import org.ethereum.beacon.test.type.TestCase; +import org.ethereum.beacon.test.type.TestSkeleton; + +import java.util.List; + +/** Container for bls aggregate public keys tests */ +public class BlsAggregatePubKeysTest extends TestSkeleton { + public List getTestCases() { + return testCases; + } + + public void setTestCases(List testCases) { + this.testCases = (List) (List) testCases; + } + + @Override + public String toString() { + return "Test \"" + getTitle() + " [" + String.join(",", getForks()) + "]\""; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsAggregateSigsCase.java b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsAggregateSigsCase.java new file mode 100644 index 000000000..e665a2736 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsAggregateSigsCase.java @@ -0,0 +1,38 @@ +package org.ethereum.beacon.test.type.bls; + +import org.ethereum.beacon.test.type.TestCase; + +import java.util.List; + +/** BLS aggregate signatures case */ +public class BlsAggregateSigsCase implements TestCase { + private List input; + private String output; + + public List getInput() { + return input; + } + + public void setInput(List input) { + this.input = input; + } + + public String getOutput() { + return output; + } + + public void setOutput(String output) { + this.output = output; + } + + @Override + public String toString() { + return "Aggregate signatures {" + + "input=" + + input.get(0).substring(0, 18) + + "...(total: " + + input.size() + + " signatures)" + + '}'; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsAggregateSigsTest.java b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsAggregateSigsTest.java new file mode 100644 index 000000000..ac4645251 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsAggregateSigsTest.java @@ -0,0 +1,22 @@ +package org.ethereum.beacon.test.type.bls; + +import org.ethereum.beacon.test.type.TestCase; +import org.ethereum.beacon.test.type.TestSkeleton; + +import java.util.List; + +/** Container for bls aggregate signatures tests */ +public class BlsAggregateSigsTest extends TestSkeleton { + public List getTestCases() { + return testCases; + } + + public void setTestCases(List testCases) { + this.testCases = (List) (List) testCases; + } + + @Override + public String toString() { + return "Test \"" + getTitle() + " [" + String.join(",", getForks()) + "]\""; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsMessageHashCase.java b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsMessageHashCase.java new file mode 100644 index 000000000..96e6d0b0a --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsMessageHashCase.java @@ -0,0 +1,58 @@ +package org.ethereum.beacon.test.type.bls; + +import org.ethereum.beacon.test.type.TestCase; + +import java.util.List; + +/** BLS message hash uncompressed test case */ +public class BlsMessageHashCase implements TestCase { + private BlsMessageHashInput input; + private List> output; + + public BlsMessageHashInput getInput() { + return input; + } + + public void setInput(BlsMessageHashInput input) { + this.input = input; + } + + public List> getOutput() { + return output; + } + + public void setOutput(List> output) { + this.output = output; + } + + @Override + public String toString() { + return "Message hash as a G2 point (uncompressed) with input: " + input; + } + + public static class BlsMessageHashInput { + private String domain; + private String message; + + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + @Override + public String toString() { + return "Input{" + "domain='" + domain + '\'' + ", message='" + message + '\'' + '}'; + } + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsMessageHashCompressedCase.java b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsMessageHashCompressedCase.java new file mode 100644 index 000000000..0b8fc33c6 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsMessageHashCompressedCase.java @@ -0,0 +1,32 @@ +package org.ethereum.beacon.test.type.bls; + +import org.ethereum.beacon.test.type.TestCase; + +import java.util.List; + +/** BLS message hash compressed test case */ +public class BlsMessageHashCompressedCase implements TestCase { + private BlsMessageHashCase.BlsMessageHashInput input; + private List output; + + public BlsMessageHashCase.BlsMessageHashInput getInput() { + return input; + } + + public void setInput(BlsMessageHashCase.BlsMessageHashInput input) { + this.input = input; + } + + public List getOutput() { + return output; + } + + public void setOutput(List output) { + this.output = output; + } + + @Override + public String toString() { + return "Message hash as a compressed G2 point with input: " + input; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsMessageHashCompressedTest.java b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsMessageHashCompressedTest.java new file mode 100644 index 000000000..353fd9a46 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsMessageHashCompressedTest.java @@ -0,0 +1,22 @@ +package org.ethereum.beacon.test.type.bls; + +import org.ethereum.beacon.test.type.TestCase; +import org.ethereum.beacon.test.type.TestSkeleton; + +import java.util.List; + +/** Container for bls message hash test cases, compressed */ +public class BlsMessageHashCompressedTest extends TestSkeleton { + public List getTestCases() { + return testCases; + } + + public void setTestCases(List testCases) { + this.testCases = (List) (List) testCases; + } + + @Override + public String toString() { + return "Test \"" + getTitle() + " [" + String.join(",", getForks()) + "]\""; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsMessageHashTest.java b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsMessageHashTest.java new file mode 100644 index 000000000..041fd7c15 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsMessageHashTest.java @@ -0,0 +1,22 @@ +package org.ethereum.beacon.test.type.bls; + +import org.ethereum.beacon.test.type.TestCase; +import org.ethereum.beacon.test.type.TestSkeleton; + +import java.util.List; + +/** Container for bls message hash test cases, uncompressed */ +public class BlsMessageHashTest extends TestSkeleton { + public List getTestCases() { + return testCases; + } + + public void setTestCases(List testCases) { + this.testCases = (List) (List) testCases; + } + + @Override + public String toString() { + return "Test \"" + getTitle() + " [" + String.join(",", getForks()) + "]\""; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsPrivateToPublicCase.java b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsPrivateToPublicCase.java new file mode 100644 index 000000000..320ac90f2 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsPrivateToPublicCase.java @@ -0,0 +1,30 @@ +package org.ethereum.beacon.test.type.bls; + +import org.ethereum.beacon.test.type.TestCase; + +/** BLS private to public test case */ +public class BlsPrivateToPublicCase implements TestCase { + private String input; + private String output; + + public String getInput() { + return input; + } + + public void setInput(String input) { + this.input = input; + } + + public String getOutput() { + return output; + } + + public void setOutput(String output) { + this.output = output; + } + + @Override + public String toString() { + return "Private to public key with input: " + input; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsPrivateToPublicTest.java b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsPrivateToPublicTest.java new file mode 100644 index 000000000..49e654e34 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsPrivateToPublicTest.java @@ -0,0 +1,22 @@ +package org.ethereum.beacon.test.type.bls; + +import org.ethereum.beacon.test.type.TestCase; +import org.ethereum.beacon.test.type.TestSkeleton; + +import java.util.List; + +/** Container for bls private to public test cases */ +public class BlsPrivateToPublicTest extends TestSkeleton { + public List getTestCases() { + return testCases; + } + + public void setTestCases(List testCases) { + this.testCases = (List) (List) testCases; + } + + @Override + public String toString() { + return "Test \"" + getTitle() + " [" + String.join(",", getForks()) + "]\""; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsSignMessageCase.java b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsSignMessageCase.java new file mode 100644 index 000000000..5abcbef46 --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsSignMessageCase.java @@ -0,0 +1,42 @@ +package org.ethereum.beacon.test.type.bls; + +import org.ethereum.beacon.test.type.TestCase; + +/** BLS sign message test case */ +public class BlsSignMessageCase implements TestCase { + private BlsSignMessageInput input; + private String output; + + public BlsSignMessageInput getInput() { + return input; + } + + public void setInput(BlsSignMessageInput input) { + this.input = input; + } + + public String getOutput() { + return output; + } + + public void setOutput(String output) { + this.output = output; + } + + @Override + public String toString() { + return "Sign Message Test Case{" + "input=" + input + '}'; + } + + public static class BlsSignMessageInput extends BlsMessageHashCase.BlsMessageHashInput { + private String privkey; + + public String getPrivkey() { + return privkey; + } + + public void setPrivkey(String privkey) { + this.privkey = privkey; + } + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/type/hash/TreeHashListTest.java b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsSignMessageTest.java similarity index 51% rename from test/src/test/java/org/ethereum/beacon/test/type/hash/TreeHashListTest.java rename to test/src/test/java/org/ethereum/beacon/test/type/bls/BlsSignMessageTest.java index 90782e459..976bae44e 100644 --- a/test/src/test/java/org/ethereum/beacon/test/type/hash/TreeHashListTest.java +++ b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsSignMessageTest.java @@ -1,22 +1,22 @@ -package org.ethereum.beacon.test.type.hash; +package org.ethereum.beacon.test.type.bls; import org.ethereum.beacon.test.type.TestCase; import org.ethereum.beacon.test.type.TestSkeleton; import java.util.List; -/** Tree hash test with list/vector cases */ -public class TreeHashListTest extends TestSkeleton { +/** Container for bls sign message tests */ +public class BlsSignMessageTest extends TestSkeleton { public List getTestCases() { return testCases; } - public void setTestCases(List testCases) { + public void setTestCases(List testCases) { this.testCases = (List) (List) testCases; } @Override public String toString() { - return "Test \"" + getTitle() + " " + getVersion() + '\"'; + return "Test \"" + getTitle() + " [" + String.join(",", getForks()) + "]\""; } } diff --git a/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsTest.java b/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsTest.java deleted file mode 100644 index 7600aa2c2..000000000 --- a/test/src/test/java/org/ethereum/beacon/test/type/bls/BlsTest.java +++ /dev/null @@ -1,353 +0,0 @@ -package org.ethereum.beacon.test.type.bls; - -import com.fasterxml.jackson.annotation.JsonProperty; -import org.ethereum.beacon.test.type.TestCase; -import org.ethereum.beacon.test.type.TestSkeleton; -import org.ethereum.beacon.test.type.UniversalTest; - -import java.util.List; - -/** - * Container for BLS tests https://github.com/ethereum/eth2.0-tests/tree/master/bls - */ -public class BlsTest extends TestSkeleton { - @JsonProperty("case01_message_hash_G2_uncompressed") - private List blsMessageHashCases; - - @JsonProperty("case02_message_hash_G2_compressed") - private List blsMessageHashCompressedCases; - - @JsonProperty("case03_private_to_public_key") - private List blsPrivateToPublicCases; - - @JsonProperty("case04_sign_messages") - private List blsSignMessageCases; - // XXX: 05 is too slow and is not a part of standard tests therefore - @JsonProperty("case06_aggregate_sigs") - private List blsAggregateSigsCases; - - @JsonProperty("case07_aggregate_pubkeys") - private List blsAggregatePubKeysCases; - - public UniversalTest buildBlsMessageHashTest() { - UniversalTest test = new UniversalTest(); - test.setFork(this.getFork()); - test.setSummary(this.getSummary()); - test.setTestSuite(this.getTestSuite()); - test.setTitle(this.getTitle()); - test.setTestCases(getBlsMessageHashCases()); - - return test; - } - - public UniversalTest buildBlsMessageHashCompressedTest() { - UniversalTest test = new UniversalTest(); - test.setFork(this.getFork()); - test.setSummary(this.getSummary()); - test.setTestSuite(this.getTestSuite()); - test.setTitle(this.getTitle()); - test.setTestCases(getBlsMessageHashCompressedCases()); - - return test; - } - - public UniversalTest buildBlsPrivateToPublicTest() { - UniversalTest test = new UniversalTest(); - test.setFork(this.getFork()); - test.setSummary(this.getSummary()); - test.setTestSuite(this.getTestSuite()); - test.setTitle(this.getTitle()); - test.setTestCases(getBlsPrivateToPublicCases()); - - return test; - } - - public UniversalTest buildBlsSignMessageTest() { - UniversalTest test = new UniversalTest(); - test.setFork(this.getFork()); - test.setSummary(this.getSummary()); - test.setTestSuite(this.getTestSuite()); - test.setTitle(this.getTitle()); - test.setTestCases(getBlsSignMessageCases()); - - return test; - } - - public UniversalTest buildBlsAggregateSigsTest() { - UniversalTest test = new UniversalTest(); - test.setFork(this.getFork()); - test.setSummary(this.getSummary()); - test.setTestSuite(this.getTestSuite()); - test.setTitle(this.getTitle()); - test.setTestCases(getBlsAggregateSigsCases()); - - return test; - } - - public UniversalTest buildBlsAggregatePubKeysTest() { - UniversalTest test = new UniversalTest(); - test.setFork(this.getFork()); - test.setSummary(this.getSummary()); - test.setTestSuite(this.getTestSuite()); - test.setTitle(this.getTitle()); - test.setTestCases(getBlsAggregatePubKeysCases()); - - return test; - } - - public List getBlsMessageHashCases() { - return blsMessageHashCases; - } - - public void setBlsMessageHashCases(List blsMessageHashCases) { - this.blsMessageHashCases = blsMessageHashCases; - } - - public List getBlsMessageHashCompressedCases() { - return blsMessageHashCompressedCases; - } - - public void setBlsMessageHashCompressedCases( - List blsMessageHashCompressedCases) { - this.blsMessageHashCompressedCases = blsMessageHashCompressedCases; - } - - public List getBlsPrivateToPublicCases() { - return blsPrivateToPublicCases; - } - - public void setBlsPrivateToPublicCases(List blsPrivateToPublicCases) { - this.blsPrivateToPublicCases = blsPrivateToPublicCases; - } - - public List getBlsSignMessageCases() { - return blsSignMessageCases; - } - - public void setBlsSignMessageCases(List blsSignMessageCases) { - this.blsSignMessageCases = blsSignMessageCases; - } - - public List getBlsAggregateSigsCases() { - return blsAggregateSigsCases; - } - - public void setBlsAggregateSigsCases(List blsAggregateSigsCases) { - this.blsAggregateSigsCases = blsAggregateSigsCases; - } - - public List getBlsAggregatePubKeysCases() { - return blsAggregatePubKeysCases; - } - - public void setBlsAggregatePubKeysCases(List blsAggregatePubKeysCases) { - this.blsAggregatePubKeysCases = blsAggregatePubKeysCases; - } - - public static class BlsMessageHashCase implements TestCase { - private BlsMessageHashInput input; - private List> output; - - public BlsMessageHashInput getInput() { - return input; - } - - public void setInput(BlsMessageHashInput input) { - this.input = input; - } - - public List> getOutput() { - return output; - } - - public void setOutput(List> output) { - this.output = output; - } - - @Override - public String toString() { - return "Message hash as a G2 point (uncompressed) with input: " + input; - } - } - - public static class BlsMessageHashCompressedCase implements TestCase { - private BlsMessageHashInput input; - private List output; - - public BlsMessageHashInput getInput() { - return input; - } - - public void setInput(BlsMessageHashInput input) { - this.input = input; - } - - public List getOutput() { - return output; - } - - public void setOutput(List output) { - this.output = output; - } - - @Override - public String toString() { - return "Message hash as a compressed G2 point with input: " + input; - } - } - - public static class BlsMessageHashInput { - private String domain; - private String message; - - public String getDomain() { - return domain; - } - - public void setDomain(String domain) { - this.domain = domain; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - @Override - public String toString() { - return "Input{" + "domain='" + domain + '\'' + ", message='" + message + '\'' + '}'; - } - } - - public static class BlsPrivateToPublicCase implements TestCase { - private String input; - private String output; - - public String getInput() { - return input; - } - - public void setInput(String input) { - this.input = input; - } - - public String getOutput() { - return output; - } - - public void setOutput(String output) { - this.output = output; - } - - @Override - public String toString() { - return "Private to public key with input: " + input; - } - } - - public static class BlsSignMessageCase implements TestCase { - private BlsSignMessageInput input; - private String output; - - public BlsSignMessageInput getInput() { - return input; - } - - public void setInput(BlsSignMessageInput input) { - this.input = input; - } - - public String getOutput() { - return output; - } - - public void setOutput(String output) { - this.output = output; - } - - @Override - public String toString() { - return "Sign Message Test Case{" + "input=" + input + '}'; - } - - public static class BlsSignMessageInput extends BlsMessageHashInput { - private String privkey; - - public String getPrivkey() { - return privkey; - } - - public void setPrivkey(String privkey) { - this.privkey = privkey; - } - } - } - - public static class BlsAggregateSigsCase implements TestCase { - private List input; - private String output; - - public List getInput() { - return input; - } - - public void setInput(List input) { - this.input = input; - } - - public String getOutput() { - return output; - } - - public void setOutput(String output) { - this.output = output; - } - - @Override - public String toString() { - return "Aggregate signatures {" - + "input=" - + input.get(0).substring(0, 18) - + "...(total: " - + input.size() - + " signatures)" - + '}'; - } - } - - public static class BlsAggregatePubKeysCase implements TestCase { - private List input; - private String output; - - public List getInput() { - return input; - } - - public void setInput(List input) { - this.input = input; - } - - public String getOutput() { - return output; - } - - public void setOutput(String output) { - this.output = output; - } - - @Override - public String toString() { - return "Aggregate public keys {" - + "input=" - + input.get(0).substring(0, 18) - + "...(total: " - + input.size() - + " public keys)" - + '}'; - } - } -} diff --git a/test/src/test/java/org/ethereum/beacon/test/type/hash/TreeHashBasicTest.java b/test/src/test/java/org/ethereum/beacon/test/type/hash/TreeHashBasicTest.java deleted file mode 100644 index 09bf2f83c..000000000 --- a/test/src/test/java/org/ethereum/beacon/test/type/hash/TreeHashBasicTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.ethereum.beacon.test.type.hash; - -import org.ethereum.beacon.test.type.TestCase; -import org.ethereum.beacon.test.type.TestSkeleton; - -import java.util.List; - -/** Container for basic types tree hash tests, no containers, lists etc. */ -public class TreeHashBasicTest extends TestSkeleton { - public List getTestCases() { - return testCases; - } - - public void setTestCases(List testCases) { - this.testCases = (List) (List) testCases; - } - - @Override - public String toString() { - return "Test \"" + getTitle() + " " + getVersion() + '\"'; - } -} diff --git a/test/src/test/java/org/ethereum/beacon/test/type/hash/TreeHashBasicTestCase.java b/test/src/test/java/org/ethereum/beacon/test/type/hash/TreeHashBasicTestCase.java deleted file mode 100644 index ea77af823..000000000 --- a/test/src/test/java/org/ethereum/beacon/test/type/hash/TreeHashBasicTestCase.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.ethereum.beacon.test.type.hash; - -import org.ethereum.beacon.test.type.TestCase; - -import java.util.List; - -/** Tree hash test case with basic value like number */ -public class TreeHashBasicTestCase implements TestCase { - private String type; - private String root; - private List tags; - private String value; - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getRoot() { - return root; - } - - public void setRoot(String root) { - this.root = root; - } - - public List getTags() { - return tags; - } - - public void setTags(List tags) { - this.tags = tags; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } -} diff --git a/test/src/test/java/org/ethereum/beacon/test/type/hash/TreeHashContainerTestCase.java b/test/src/test/java/org/ethereum/beacon/test/type/hash/TreeHashContainerTestCase.java deleted file mode 100644 index b495c7993..000000000 --- a/test/src/test/java/org/ethereum/beacon/test/type/hash/TreeHashContainerTestCase.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.ethereum.beacon.test.type.hash; - -import org.ethereum.beacon.test.type.TestCase; - -import java.util.List; -import java.util.Map; - -/** Tree hash test case with container */ -public class TreeHashContainerTestCase implements TestCase { - private Map type; - private String root; - private List tags; - private Map value; - - public String getRoot() { - return root; - } - - public void setRoot(String root) { - this.root = root; - } - - public List getTags() { - return tags; - } - - public void setTags(List tags) { - this.tags = tags; - } - - public Map getType() { - return type; - } - - public void setType(Map type) { - this.type = type; - } - - public Map getValue() { - return value; - } - - public void setValue(Map value) { - this.value = value; - } -} diff --git a/test/src/test/java/org/ethereum/beacon/test/type/hash/TreeHashListTestCase.java b/test/src/test/java/org/ethereum/beacon/test/type/hash/TreeHashListTestCase.java deleted file mode 100644 index ddc7e3e1c..000000000 --- a/test/src/test/java/org/ethereum/beacon/test/type/hash/TreeHashListTestCase.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.ethereum.beacon.test.type.hash; - -import org.ethereum.beacon.test.type.TestCase; - -import java.util.List; - -/** Tree hash list/vector test case */ -public class TreeHashListTestCase implements TestCase { - private List type; - private String root; - private List tags; - private List value; - - public String getRoot() { - return root; - } - - public void setRoot(String root) { - this.root = root; - } - - public List getTags() { - return tags; - } - - public void setTags(List tags) { - this.tags = tags; - } - - public List getType() { - return type; - } - - public void setType(List type) { - this.type = type; - } - - public List getValue() { - return value; - } - - public void setValue(List value) { - this.value = value; - } -} diff --git a/test/src/test/java/org/ethereum/beacon/test/type/shuffle/ShuffleTestCase.java b/test/src/test/java/org/ethereum/beacon/test/type/shuffle/ShuffleTestCase.java index 2be6be261..4c1ba5b54 100644 --- a/test/src/test/java/org/ethereum/beacon/test/type/shuffle/ShuffleTestCase.java +++ b/test/src/test/java/org/ethereum/beacon/test/type/shuffle/ShuffleTestCase.java @@ -6,125 +6,47 @@ /** * Shuffling test case https://github.com/ethereum/eth2.0-tests/tree/master/shuffling + * href="https://github.com/ethereum/eth2.0-specs/tree/dev/specs/test_formats/shuffling">https://github.com/ethereum/eth2.0-specs/tree/dev/specs/test_formats/shuffling */ public class ShuffleTestCase implements TestCase { - private ShuffleInput input; - private List> output; private String seed; + private Integer count; + private List shuffled; - public ShuffleInput getInput() { - return input; + public String getSeed() { + return seed; } - public void setInput(ShuffleInput input) { - this.input = input; + public void setSeed(String seed) { + this.seed = seed; } - public List> getOutput() { - return output; + public Integer getCount() { + return count; } - public void setOutput(List> output) { - this.output = output; + public void setCount(Integer count) { + this.count = count; } - public String getSeed() { - return seed; + public List getShuffled() { + return shuffled; } - public void setSeed(String seed) { - this.seed = seed; + public void setShuffled(List shuffled) { + this.shuffled = shuffled; } @Override public String toString() { return "ShuffleTestCase{" - + "input=" - + input - + ", output=[...]" - + ", seed='" + + "seed='" + seed + '\'' + + ", count=" + + count + + ", shuffled=" + + shuffled + '}'; } - - public static class ShuffleInput { - private String epoch; - private List validators; - - public String getEpoch() { - return epoch; - } - - public void setEpoch(String epoch) { - this.epoch = epoch; - } - - public List getValidators() { - return validators; - } - - public void setValidators(List validators) { - this.validators = validators; - } - - @Override - public String toString() { - return "Input{" - + "epoch='" - + epoch - + '\'' - + ", validators=" - + (validators.isEmpty() ? "" : validators.get(0)) - + " (total " - + validators.size() - + " validators)" - + '}'; - } - - public static class ShuffleTestValidator { - private String activation_epoch; - private String exit_epoch; - private Integer original_index; - - public String getActivation_epoch() { - return activation_epoch; - } - - public void setActivation_epoch(String activation_epoch) { - this.activation_epoch = activation_epoch; - } - - public String getExit_epoch() { - return exit_epoch; - } - - public void setExit_epoch(String exit_epoch) { - this.exit_epoch = exit_epoch; - } - - public Integer getOriginal_index() { - return original_index; - } - - public void setOriginal_index(Integer original_index) { - this.original_index = original_index; - } - - @Override - public String toString() { - return "Validator{" - + "activation_epoch='" - + activation_epoch - + '\'' - + ", exit_epoch='" - + exit_epoch - + '\'' - + ", original_index=" - + original_index - + '}'; - } - } - } } diff --git a/test/src/test/java/org/ethereum/beacon/test/type/ssz/SszTestCase.java b/test/src/test/java/org/ethereum/beacon/test/type/ssz/SszGenericCase.java similarity index 74% rename from test/src/test/java/org/ethereum/beacon/test/type/ssz/SszTestCase.java rename to test/src/test/java/org/ethereum/beacon/test/type/ssz/SszGenericCase.java index 609688e52..0aa301b76 100644 --- a/test/src/test/java/org/ethereum/beacon/test/type/ssz/SszTestCase.java +++ b/test/src/test/java/org/ethereum/beacon/test/type/ssz/SszGenericCase.java @@ -5,10 +5,12 @@ import java.util.List; /** - * SSZ test case https://github.com/ethereum/eth2.0-tests/tree/master/ssz + * SSZ test case + * + *

Test format description: https://github.com/ethereum/eth2.0-specs/tree/dev/specs/test_formats/ssz_generic */ -public class SszTestCase implements TestCase { +public class SszGenericCase implements TestCase { private String type; private String valid; private String ssz; diff --git a/test/src/test/java/org/ethereum/beacon/test/type/ssz/SszTest.java b/test/src/test/java/org/ethereum/beacon/test/type/ssz/SszGenericTest.java similarity index 54% rename from test/src/test/java/org/ethereum/beacon/test/type/ssz/SszTest.java rename to test/src/test/java/org/ethereum/beacon/test/type/ssz/SszGenericTest.java index f5acef109..1119e64e6 100644 --- a/test/src/test/java/org/ethereum/beacon/test/type/ssz/SszTest.java +++ b/test/src/test/java/org/ethereum/beacon/test/type/ssz/SszGenericTest.java @@ -6,15 +6,14 @@ import java.util.List; /** - * Container for ssz tests https://github.com/ethereum/eth2.0-tests/tree/master/ssz + * Container for generic ssz tests */ -public class SszTest extends TestSkeleton { +public class SszGenericTest extends TestSkeleton { public List getTestCases() { return testCases; } - public void setTestCases(List testCases) { + public void setTestCases(List testCases) { this.testCases = (List) (List) testCases; } } diff --git a/test/src/test/java/org/ethereum/beacon/test/type/ssz/SszStaticCase.java b/test/src/test/java/org/ethereum/beacon/test/type/ssz/SszStaticCase.java new file mode 100644 index 000000000..620711e9b --- /dev/null +++ b/test/src/test/java/org/ethereum/beacon/test/type/ssz/SszStaticCase.java @@ -0,0 +1,62 @@ +package org.ethereum.beacon.test.type.ssz; + +import com.fasterxml.jackson.annotation.JsonProperty; +import org.ethereum.beacon.test.type.TestCase; + +/** + * Ssz static tests with known containers. + * + *

Test format description: https://github.com/ethereum/eth2.0-specs/blob/dev/specs/test_formats/ssz_static/core.md + */ +public class SszStaticCase implements TestCase { + @JsonProperty("type_name") + private String typeName; + + private Object value; + private String serialized; + private String root; + + @JsonProperty("signing_root") + private String signingRoot; + + public String getTypeName() { + return typeName; + } + + public void setTypeName(String typeName) { + this.typeName = typeName; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + + public String getSerialized() { + return serialized; + } + + public void setSerialized(String serialized) { + this.serialized = serialized; + } + + public String getRoot() { + return root; + } + + public void setRoot(String root) { + this.root = root; + } + + public String getSigningRoot() { + return signingRoot; + } + + public void setSigningRoot(String signingRoot) { + this.signingRoot = signingRoot; + } +} diff --git a/test/src/test/java/org/ethereum/beacon/test/type/hash/TreeHashContainerTest.java b/test/src/test/java/org/ethereum/beacon/test/type/ssz/SszStaticTest.java similarity index 51% rename from test/src/test/java/org/ethereum/beacon/test/type/hash/TreeHashContainerTest.java rename to test/src/test/java/org/ethereum/beacon/test/type/ssz/SszStaticTest.java index 7bdc53b44..983f44979 100644 --- a/test/src/test/java/org/ethereum/beacon/test/type/hash/TreeHashContainerTest.java +++ b/test/src/test/java/org/ethereum/beacon/test/type/ssz/SszStaticTest.java @@ -1,22 +1,22 @@ -package org.ethereum.beacon.test.type.hash; +package org.ethereum.beacon.test.type.ssz; import org.ethereum.beacon.test.type.TestCase; import org.ethereum.beacon.test.type.TestSkeleton; import java.util.List; -/** Tree hash tests with containers */ -public class TreeHashContainerTest extends TestSkeleton { +/** Ssz static tests with known containers */ +public class SszStaticTest extends TestSkeleton { public List getTestCases() { return testCases; } - public void setTestCases(List testCases) { + public void setTestCases(List testCases) { this.testCases = (List) (List) testCases; } @Override public String toString() { - return "Test \"" + getTitle() + " " + getVersion() + '\"'; + return "Test \"" + getTitle() + " [" + String.join(",", getForks()) + "]\""; } } diff --git a/test/src/test/java/org/ethereum/beacon/test/type/state/StateTestCase.java b/test/src/test/java/org/ethereum/beacon/test/type/state/StateTestCase.java index 3c96ee01c..7b9945f28 100644 --- a/test/src/test/java/org/ethereum/beacon/test/type/state/StateTestCase.java +++ b/test/src/test/java/org/ethereum/beacon/test/type/state/StateTestCase.java @@ -4,82 +4,113 @@ import com.fasterxml.jackson.annotation.JsonProperty; import java.util.List; - +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.ethereum.beacon.core.operations.Attestation; +import org.ethereum.beacon.core.operations.Deposit; +import org.ethereum.beacon.core.operations.deposit.DepositData; +import org.ethereum.beacon.core.types.BLSPubkey; +import org.ethereum.beacon.core.types.BLSSignature; +import org.ethereum.beacon.core.types.Bitfield; +import org.ethereum.beacon.core.types.Gwei; import org.ethereum.beacon.test.type.NamedTestCase; -import org.ethereum.beacon.test.type.SpecConstantsDataMerged; import org.ethereum.beacon.test.type.state.StateTestCase.BeaconStateData.AttestationData.AttestationDataContainer; +import tech.pegasys.artemis.ethereum.core.Hash32; +import tech.pegasys.artemis.util.bytes.Bytes96; +import tech.pegasys.artemis.util.bytes.BytesValue; +import tech.pegasys.artemis.util.collections.ReadVector; +import tech.pegasys.artemis.util.uint.UInt64; + +import static org.ethereum.beacon.test.StateTestUtils.parseAttestationData; /** * State test case https://github.com/ethereum/eth2.0-tests/tree/master/state */ public class StateTestCase implements NamedTestCase { - private String name; - private SpecConstantsDataMerged config; - - @JsonProperty("verify_signatures") - private Boolean verifySignatures; - - @JsonProperty("initial_state") - private BeaconStateData initialState; - - private List blocks; - - @JsonProperty("expected_state") - private BeaconStateData expectedState; + private String description; + @JsonProperty + private BlockData.BlockBodyData.DepositData deposit; + @JsonProperty + private BeaconStateData.AttestationData attestation; + private BeaconStateData pre; + private BeaconStateData post; + + public String getDescription() { + return description; + } - @Override - public String getName() { - return name; + public void setDescription(String description) { + this.description = description; } - public void setName(String name) { - this.name = name; + public BlockData.BlockBodyData.DepositData getDeposit() { + return deposit; } - public SpecConstantsDataMerged getConfig() { - return config; + public Deposit getDepositOperation() { + Deposit deposit = + new Deposit( + ReadVector.wrap(getDeposit().getProof().stream().map(Hash32::fromHexString).collect(Collectors.toList()), Function.identity()), + UInt64.valueOf(getDeposit().getIndex()), + new DepositData( + BLSPubkey.fromHexString(getDeposit().getData().getPubkey()), + Hash32.fromHexString(getDeposit().getData().getWithdrawalCredentials()), + Gwei.castFrom(UInt64.valueOf(getDeposit().getData().getAmount())), + BLSSignature.wrap( + Bytes96.fromHexString(getDeposit().getData().getSignature())))); + + return deposit; } - public void setConfig(SpecConstantsDataMerged config) { - this.config = config; + public void setDeposit(BlockData.BlockBodyData.DepositData deposit) { + this.deposit = deposit; } - public Boolean getVerifySignatures() { - return verifySignatures; + public BeaconStateData.AttestationData getAttestation() { + return attestation; } - public void setVerifySignatures(Boolean verifySignatures) { - this.verifySignatures = verifySignatures; + public Attestation getAttestationOperation() { + Attestation attestation = + new Attestation( + Bitfield.of(BytesValue.fromHexString(getAttestation().getAggregationBitfield())), + parseAttestationData((getAttestation().getData())), + Bitfield.of(BytesValue.fromHexString(getAttestation().getCustodyBitfield())), + BLSSignature.wrap(Bytes96.fromHexString(getAttestation().getSignature()))); + + return attestation; } - public BeaconStateData getInitialState() { - return initialState; + public void setAttestation(BeaconStateData.AttestationData attestation) { + this.attestation = attestation; } - public void setInitialState(BeaconStateData initialState) { - this.initialState = initialState; + public BeaconStateData getPre() { + return pre; } - public List getBlocks() { - return blocks; + public void setPre(BeaconStateData pre) { + this.pre = pre; } - public void setBlocks(List blocks) { - this.blocks = blocks; + public BeaconStateData getPost() { + return post; } - public BeaconStateData getExpectedState() { - return expectedState; + public void setPost(BeaconStateData post) { + this.post = post; } - public void setExpectedState(BeaconStateData expectedState) { - this.expectedState = expectedState; + @Override + public String getName() { + return getDescription(); } @Override public String toString() { - return "StateTestCase{" + "name='" + name + '\'' + '}'; + return "StateTestCase{" + "description='" + description + '\'' + '}'; } public static class BeaconStateData { @@ -93,32 +124,13 @@ public static class BeaconStateData { @JsonProperty("validator_registry") private List validatorRegistry; - @JsonProperty("validator_balances") - private List validatorBalances; - - @JsonProperty("validator_registry_update_epoch") - private String validatorRegistryUpdateEpoch; + private List balances; @JsonProperty("latest_randao_mixes") private List latestRandaoMixes; - @JsonProperty("previous_shuffling_start_shard") - private Long previousShufflingStartShard; - - @JsonProperty("current_shuffling_start_shard") - private Long currentShufflingStartShard; - - @JsonProperty("previous_shuffling_epoch") - private String previousShufflingEpoch; - - @JsonProperty("current_shuffling_epoch") - private String currentShufflingEpoch; - - @JsonProperty("previous_shuffling_seed") - private String previousShufflingSeed; - - @JsonProperty("current_shuffling_seed") - private String currentShufflingSeed; + @JsonProperty("latest_start_shard") + private Long latestStartShard; @JsonProperty("previous_epoch_attestations") private List previousEpochAttestations; @@ -147,8 +159,11 @@ public static class BeaconStateData { @JsonProperty("finalized_root") private String finalizedRoot; - @JsonProperty("latest_crosslinks") - private List latestCrosslinks; + @JsonProperty("current_crosslinks") + private List currentCrosslinks; + + @JsonProperty("previous_crosslinks") + private List previousCrosslinks; @JsonProperty("latest_block_roots") private List latestBlockRoots; @@ -172,7 +187,7 @@ public static class BeaconStateData { private BlockData.BlockBodyData.Eth1 latestEth1Data; @JsonProperty("eth1_data_votes") - private List eth1DataVotes; + private List eth1DataVotes; @JsonProperty("deposit_index") private Long depositIndex; @@ -209,20 +224,12 @@ public void setValidatorRegistry(List validatorRegistry) { this.validatorRegistry = validatorRegistry; } - public List getValidatorBalances() { - return validatorBalances; - } - - public void setValidatorBalances(List validatorBalances) { - this.validatorBalances = validatorBalances; - } - - public String getValidatorRegistryUpdateEpoch() { - return validatorRegistryUpdateEpoch; + public List getBalances() { + return balances; } - public void setValidatorRegistryUpdateEpoch(String validatorRegistryUpdateEpoch) { - this.validatorRegistryUpdateEpoch = validatorRegistryUpdateEpoch; + public void setBalances(List balances) { + this.balances = balances; } public List getLatestRandaoMixes() { @@ -233,52 +240,12 @@ public void setLatestRandaoMixes(List latestRandaoMixes) { this.latestRandaoMixes = latestRandaoMixes; } - public Long getPreviousShufflingStartShard() { - return previousShufflingStartShard; - } - - public void setPreviousShufflingStartShard(Long previousShufflingStartShard) { - this.previousShufflingStartShard = previousShufflingStartShard; - } - - public Long getCurrentShufflingStartShard() { - return currentShufflingStartShard; - } - - public void setCurrentShufflingStartShard(Long currentShufflingStartShard) { - this.currentShufflingStartShard = currentShufflingStartShard; - } - - public String getPreviousShufflingEpoch() { - return previousShufflingEpoch; - } - - public void setPreviousShufflingEpoch(String previousShufflingEpoch) { - this.previousShufflingEpoch = previousShufflingEpoch; - } - - public String getCurrentShufflingEpoch() { - return currentShufflingEpoch; + public Long getLatestStartShard() { + return latestStartShard; } - public void setCurrentShufflingEpoch(String currentShufflingEpoch) { - this.currentShufflingEpoch = currentShufflingEpoch; - } - - public String getPreviousShufflingSeed() { - return previousShufflingSeed; - } - - public void setPreviousShufflingSeed(String previousShufflingSeed) { - this.previousShufflingSeed = previousShufflingSeed; - } - - public String getCurrentShufflingSeed() { - return currentShufflingSeed; - } - - public void setCurrentShufflingSeed(String currentShufflingSeed) { - this.currentShufflingSeed = currentShufflingSeed; + public void setLatestStartShard(Long latestStartShard) { + this.latestStartShard = latestStartShard; } public List getPreviousEpochAttestations() { @@ -353,12 +320,20 @@ public void setFinalizedRoot(String finalizedRoot) { this.finalizedRoot = finalizedRoot; } - public List getLatestCrosslinks() { - return latestCrosslinks; + public List getCurrentCrosslinks() { + return currentCrosslinks; + } + + public void setCurrentCrosslinks(List currentCrosslinks) { + this.currentCrosslinks = currentCrosslinks; + } + + public List getPreviousCrosslinks() { + return previousCrosslinks; } - public void setLatestCrosslinks(List latestCrosslinks) { - this.latestCrosslinks = latestCrosslinks; + public void setPreviousCrosslinks(List previousCrosslinks) { + this.previousCrosslinks = previousCrosslinks; } public List getLatestBlockRoots() { @@ -417,11 +392,11 @@ public void setLatestEth1Data(BlockData.BlockBodyData.Eth1 latestEth1Data) { this.latestEth1Data = latestEth1Data; } - public List getEth1DataVotes() { + public List getEth1DataVotes() { return eth1DataVotes; } - public void setEth1DataVotes(List eth1DataVotes) { + public void setEth1DataVotes(List eth1DataVotes) { this.eth1DataVotes = eth1DataVotes; } @@ -565,8 +540,7 @@ public static class AttestationData { @JsonProperty("custody_bitfield") private String custodyBitfield; - @JsonProperty("aggregate_signature") - private String aggregateSignature; + private String signature; @JsonProperty("inclusion_slot") private String inclusionSlot; @@ -606,12 +580,12 @@ public void setCustodyBitfield(String custodyBitfield) { this.custodyBitfield = custodyBitfield; } - public String getAggregateSignature() { - return aggregateSignature; + public String getSignature() { + return signature; } - public void setAggregateSignature(String aggregateSignature) { - this.aggregateSignature = aggregateSignature; + public void setSignature(String signature) { + this.signature = signature; } public Long getProposerIndex() { @@ -623,8 +597,6 @@ public void setProposerIndex(Long proposerIndex) { } public static class AttestationDataContainer { - private String slot; - @JsonProperty("beacon_block_root") private String beaconBlockRoot; @@ -634,6 +606,9 @@ public static class AttestationDataContainer { @JsonProperty("source_root") private String sourceRoot; + @JsonProperty("target_epoch") + private String targetEpoch; + @JsonProperty("target_root") private String targetRoot; @@ -645,14 +620,6 @@ public static class AttestationDataContainer { @JsonProperty("crosslink_data_root") private String crosslinkDataRoot; - public String getSlot() { - return slot; - } - - public void setSlot(String slot) { - this.slot = slot; - } - public String getBeaconBlockRoot() { return beaconBlockRoot; } @@ -708,6 +675,14 @@ public String getCrosslinkDataRoot() { public void setCrosslinkDataRoot(String crosslinkDataRoot) { this.crosslinkDataRoot = crosslinkDataRoot; } + + public String getTargetEpoch() { + return targetEpoch; + } + + public void setTargetEpoch(String targetEpoch) { + this.targetEpoch = targetEpoch; + } } } @@ -799,8 +774,6 @@ public void setSignature(String signature) { this.signature = signature; } } - - public static class Eth1Vote {} } public static class BlockData { @@ -1010,7 +983,7 @@ public void setHeader2(BeaconStateData.BlockHeaderData header2) { } } - public static class SlashableAttestationData { + public static class IndexedAttestationData { @JsonProperty("custody_bit_0_indices") private List custodyBit0Indices; @JsonProperty("custody_bit_1_indices") @@ -1063,25 +1036,25 @@ public void setAggregateSignature(String aggregateSignature) { public static class AttesterSlashingData { @JsonProperty("slashable_attestation_1") - private SlashableAttestationData slashableAttestation1; + private IndexedAttestationData slashableAttestation1; @JsonProperty("slashable_attestation_2") - private SlashableAttestationData slashableAttestation2; + private IndexedAttestationData slashableAttestation2; - public SlashableAttestationData getSlashableAttestation1() { + public IndexedAttestationData getSlashableAttestation1() { return slashableAttestation1; } public void setSlashableAttestation1( - SlashableAttestationData slashableAttestation1) { + IndexedAttestationData slashableAttestation1) { this.slashableAttestation1 = slashableAttestation1; } - public SlashableAttestationData getSlashableAttestation2() { + public IndexedAttestationData getSlashableAttestation2() { return slashableAttestation2; } public void setSlashableAttestation2( - SlashableAttestationData slashableAttestation2) { + IndexedAttestationData slashableAttestation2) { this.slashableAttestation2 = slashableAttestation2; } } @@ -1090,8 +1063,7 @@ public static class DepositData { private List proof; private Long index; - @JsonProperty("deposit_data") - private DepositDataContainer depositData; + private DepositDataContainer data; public List getProof() { return proof; @@ -1109,12 +1081,12 @@ public void setIndex(Long index) { this.index = index; } - public DepositDataContainer getDepositData() { - return depositData; + public DepositDataContainer getData() { + return data; } - public void setDepositData(DepositDataContainer depositData) { - this.depositData = depositData; + public void setData(DepositDataContainer data) { + this.data = data; } public static class DepositDataContainer { diff --git a/test/src/test/resources/eth2.0-spec-tests b/test/src/test/resources/eth2.0-spec-tests new file mode 160000 index 000000000..161a36ee6 --- /dev/null +++ b/test/src/test/resources/eth2.0-spec-tests @@ -0,0 +1 @@ +Subproject commit 161a36ee6232d8d251d798c8262638ed0c34c9c6 diff --git a/test/src/test/resources/eth2.0-temp-test-configs/constant_presets/README.md b/test/src/test/resources/eth2.0-temp-test-configs/constant_presets/README.md new file mode 100644 index 000000000..45148862e --- /dev/null +++ b/test/src/test/resources/eth2.0-temp-test-configs/constant_presets/README.md @@ -0,0 +1,20 @@ +# Constant Presets + +This directory contains a set of constants presets used for testing, testnets, and mainnet. + +A preset file contains all the constants known for its target. +Later-fork constants can be ignored, e.g. ignore phase1 constants as a client that only supports phase 0 currently. + +## Format + +Each preset is a key-value mapping. + +**Key**: an `UPPER_SNAKE_CASE` (a.k.a. "macro case") formatted string, name of the constant. +**Value**: can be any of: + - an unsigned integer number, can be up to 64 bits (incl.) + - a hexadecimal string, prefixed with `0x` + +Presets may contain comments to describe the values. + +See `mainnet.yaml` for a complete example. + diff --git a/test/src/test/resources/eth2.0-temp-test-configs/constant_presets/mainnet.yaml b/test/src/test/resources/eth2.0-temp-test-configs/constant_presets/mainnet.yaml new file mode 100644 index 000000000..d63c617b7 --- /dev/null +++ b/test/src/test/resources/eth2.0-temp-test-configs/constant_presets/mainnet.yaml @@ -0,0 +1,123 @@ +# Mainnet preset +# Note: the intention of this file (for now) is to illustrate what a mainnet configuration could look like. +# Some of these constants may still change before the launch of Phase 0. + + +# Misc +# --------------------------------------------------------------- +# 2**10 (= 1,024) +SHARD_COUNT: 1024 +# 2**7 (= 128) +TARGET_COMMITTEE_SIZE: 128 +# 2**12 (= 4,096) +MAX_INDICES_PER_ATTESTATION: 4096 +# 2**2 (= 4) +MIN_PER_EPOCH_CHURN_LIMIT: 4 +# 2**16 (= 65,536) +CHURN_LIMIT_QUOTIENT: 65536 +# See issue 563 +SHUFFLE_ROUND_COUNT: 90 + + +# Deposit contract +# --------------------------------------------------------------- +# **TBD** +DEPOSIT_CONTRACT_ADDRESS: 0x1234567890123456789012345678901234567890 +# 2**5 (= 32) +DEPOSIT_CONTRACT_TREE_DEPTH: 32 + + +# Gwei values +# --------------------------------------------------------------- +# 2**0 * 10**9 (= 1,000,000,000) Gwei +MIN_DEPOSIT_AMOUNT: 1000000000 +# 2**5 * 10**9 (= 32,000,000,000) Gwei +MAX_EFFECTIVE_BALANCE: 32000000000 +# 2**4 * 10**9 (= 16,000,000,000) Gwei +EJECTION_BALANCE: 16000000000 +# 2**0 * 10**9 (= 1,000,000,000) Gwei +HIGH_BALANCE_INCREMENT: 1000000000 + + +# Initial values +# --------------------------------------------------------------- +GENESIS_FORK_VERSION: 0x00000000 +# 0, GENESIS_EPOCH is derived from this constant +GENESIS_SLOT: 0 +# 2**64 - 1 +FAR_FUTURE_EPOCH: 18446744073709551615 +BLS_WITHDRAWAL_PREFIX_BYTE: 0x00 + + +# Time parameters +# --------------------------------------------------------------- +# 6 seconds 6 seconds +SECONDS_PER_SLOT: 6 +# 2**2 (= 4) slots 24 seconds +MIN_ATTESTATION_INCLUSION_DELAY: 4 +# 2**6 (= 64) slots 6.4 minutes +SLOTS_PER_EPOCH: 64 +# 2**0 (= 1) epochs 6.4 minutes +MIN_SEED_LOOKAHEAD: 1 +# 2**2 (= 4) epochs 25.6 minutes +ACTIVATION_EXIT_DELAY: 4 +# 2**10 (= 1,024) slots ~1.7 hours +SLOTS_PER_ETH1_VOTING_PERIOD: 1024 +# 2**13 (= 8,192) slots ~13 hours +SLOTS_PER_HISTORICAL_ROOT: 8192 +# 2**8 (= 256) epochs ~27 hours +MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256 +# 2**11 (= 2,048) epochs 9 days +PERSISTENT_COMMITTEE_PERIOD: 2048 +# 2**6 (= 64) epochs ~7 hours +MAX_CROSSLINK_EPOCHS: 64 + + +# State list lengths +# --------------------------------------------------------------- +# 2**13 (= 8,192) epochs ~36 days +LATEST_RANDAO_MIXES_LENGTH: 8192 +# 2**13 (= 8,192) epochs ~36 days +LATEST_ACTIVE_INDEX_ROOTS_LENGTH: 8192 +# 2**13 (= 8,192) epochs ~36 days +LATEST_SLASHED_EXIT_LENGTH: 8192 + + +# Reward and penalty quotients +# --------------------------------------------------------------- +# 2**5 (= 32) +BASE_REWARD_QUOTIENT: 32 +# 2**9 (= 512) +WHISTLEBLOWING_REWARD_QUOTIENT: 512 +# 2**3 (= 8) +PROPOSER_REWARD_QUOTIENT: 8 +# 2**24 (= 16,777,216) +INACTIVITY_PENALTY_QUOTIENT: 16777216 + + +# Max operations per block +# --------------------------------------------------------------- +# 2**5 (= 32) +MIN_PENALTY_QUOTIENT: 32 +# 2**4 (= 16) +MAX_PROPOSER_SLASHINGS: 16 +# 2**0 (= 1) +MAX_ATTESTER_SLASHINGS: 1 +# 2**7 (= 128) +MAX_ATTESTATIONS: 128 +# 2**4 (= 16) +MAX_DEPOSITS: 16 +# 2**4 (= 16) +MAX_VOLUNTARY_EXITS: 16 +# Originally 2**4 (= 16), disabled for now. +MAX_TRANSFERS: 0 + + +# Signature domains +# --------------------------------------------------------------- +DOMAIN_BEACON_PROPOSER: 0 +DOMAIN_RANDAO: 1 +DOMAIN_ATTESTATION: 2 +DOMAIN_DEPOSIT: 3 +DOMAIN_VOLUNTARY_EXIT: 4 +DOMAIN_TRANSFER: 5 \ No newline at end of file diff --git a/test/src/test/resources/eth2.0-temp-test-configs/constant_presets/minimal.yaml b/test/src/test/resources/eth2.0-temp-test-configs/constant_presets/minimal.yaml new file mode 100644 index 000000000..711f6737d --- /dev/null +++ b/test/src/test/resources/eth2.0-temp-test-configs/constant_presets/minimal.yaml @@ -0,0 +1,123 @@ +# Minimal preset + + +# Misc +# --------------------------------------------------------------- + +# [customized] Just 8 shards for testing purposes +SHARD_COUNT: 8 + +# [customized] unsecure, but fast +TARGET_COMMITTEE_SIZE: 4 +# 2**12 (= 4,096) +MAX_INDICES_PER_ATTESTATION: 4096 +# 2**2 (= 4) +MIN_PER_EPOCH_CHURN_LIMIT: 4 +# 2**16 (= 65,536) +CHURN_LIMIT_QUOTIENT: 65536 +# [customized] Faster, but unsecure. +SHUFFLE_ROUND_COUNT: 10 + + +# Deposit contract +# --------------------------------------------------------------- +# **TBD** +DEPOSIT_CONTRACT_ADDRESS: 0x1234567890123456789012345678901234567890 +# 2**5 (= 32) +DEPOSIT_CONTRACT_TREE_DEPTH: 32 + + +# Gwei values +# --------------------------------------------------------------- +# 2**0 * 10**9 (= 1,000,000,000) Gwei +MIN_DEPOSIT_AMOUNT: 1000000000 +# 2**5 * 10**9 (= 32,000,000,000) Gwei +MAX_EFFECTIVE_BALANCE: 32000000000 +# 2**4 * 10**9 (= 16,000,000,000) Gwei +EJECTION_BALANCE: 16000000000 +# 2**0 * 10**9 (= 1,000,000,000) Gwei +HIGH_BALANCE_INCREMENT: 1000000000 + + +# Initial values +# --------------------------------------------------------------- +GENESIS_FORK_VERSION: 0x00000000 +# 0, GENESIS_EPOCH is derived from this constant +GENESIS_SLOT: 0 +# 2**64 - 1 +FAR_FUTURE_EPOCH: 18446744073709551615 +BLS_WITHDRAWAL_PREFIX_BYTE: 0x00 + + +# Time parameters +# --------------------------------------------------------------- +# 6 seconds 6 seconds +SECONDS_PER_SLOT: 6 +# [customized] 2 slots +MIN_ATTESTATION_INCLUSION_DELAY: 2 +# [customized] fast epochs +SLOTS_PER_EPOCH: 8 +# 2**0 (= 1) epochs 6.4 minutes +MIN_SEED_LOOKAHEAD: 1 +# 2**2 (= 4) epochs 25.6 minutes +ACTIVATION_EXIT_DELAY: 4 +# [customized] higher frequency new deposits from eth1 for testing +SLOTS_PER_ETH1_VOTING_PERIOD: 16 +# [customized] smaller state +SLOTS_PER_HISTORICAL_ROOT: 64 +# 2**8 (= 256) epochs ~27 hours +MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256 +# 2**11 (= 2,048) epochs 9 days +PERSISTENT_COMMITTEE_PERIOD: 2048 +# 2**6 (= 64) epochs ~7 hours +MAX_CROSSLINK_EPOCHS: 64 + + +# State list lengths +# --------------------------------------------------------------- +# [customized] smaller state +LATEST_RANDAO_MIXES_LENGTH: 64 +# [customized] smaller state +LATEST_ACTIVE_INDEX_ROOTS_LENGTH: 64 +# [customized] smaller state +LATEST_SLASHED_EXIT_LENGTH: 64 + + +# Reward and penalty quotients +# --------------------------------------------------------------- +# 2**5 (= 32) +BASE_REWARD_QUOTIENT: 32 +# 2**9 (= 512) +WHISTLEBLOWING_REWARD_QUOTIENT: 512 +# 2**3 (= 8) +PROPOSER_REWARD_QUOTIENT: 8 +# 2**24 (= 16,777,216) +INACTIVITY_PENALTY_QUOTIENT: 16777216 + + +# Max operations per block +# --------------------------------------------------------------- +# 2**5 (= 32) +MIN_PENALTY_QUOTIENT: 32 +# 2**4 (= 16) +MAX_PROPOSER_SLASHINGS: 16 +# 2**0 (= 1) +MAX_ATTESTER_SLASHINGS: 1 +# 2**7 (= 128) +MAX_ATTESTATIONS: 128 +# 2**4 (= 16) +MAX_DEPOSITS: 16 +# 2**4 (= 16) +MAX_VOLUNTARY_EXITS: 16 +# Originally 2**4 (= 16), disabled for now. +MAX_TRANSFERS: 0 + + +# Signature domains +# --------------------------------------------------------------- +DOMAIN_BEACON_PROPOSER: 0 +DOMAIN_RANDAO: 1 +DOMAIN_ATTESTATION: 2 +DOMAIN_DEPOSIT: 3 +DOMAIN_VOLUNTARY_EXIT: 4 +DOMAIN_TRANSFER: 5 \ No newline at end of file diff --git a/test/src/test/resources/eth2.0-temp-test-configs/fork_timelines/README.md b/test/src/test/resources/eth2.0-temp-test-configs/fork_timelines/README.md new file mode 100644 index 000000000..c93b415f5 --- /dev/null +++ b/test/src/test/resources/eth2.0-temp-test-configs/fork_timelines/README.md @@ -0,0 +1,18 @@ +# Fork timelines + +This directory contains a set of fork timelines used for testing, testnets, and mainnet. + +A timeline file contains all the forks known for its target. +Later forks can be ignored, e.g. ignore fork `phase1` as a client that only supports phase 0 currently. + +## Format + +Each preset is a key-value mapping. + +**Key**: an `lower_snake_case` (a.k.a. "python case") formatted string, name of the fork. +**Value**: an unsigned integer number, epoch number of activation of the fork + +Timelines may contain comments to describe the values. + +See `mainnet.yaml` for a complete example. + diff --git a/test/src/test/resources/eth2.0-temp-test-configs/fork_timelines/mainnet.yaml b/test/src/test/resources/eth2.0-temp-test-configs/fork_timelines/mainnet.yaml new file mode 100644 index 000000000..8d51d6582 --- /dev/null +++ b/test/src/test/resources/eth2.0-temp-test-configs/fork_timelines/mainnet.yaml @@ -0,0 +1,12 @@ +# Mainnet fork timeline + +# Equal to GENESIS_EPOCH +phase0: 67108864 + +# Example 1: +# phase0_funny_fork_name: 67116000 + +# Example 2: +# Should be equal to PHASE_1_GENESIS_EPOCH +# (placeholder in example value here) +# phase1: 67163000 diff --git a/test/src/test/resources/eth2.0-temp-test-configs/fork_timelines/testing.yaml b/test/src/test/resources/eth2.0-temp-test-configs/fork_timelines/testing.yaml new file mode 100644 index 000000000..957a53b8c --- /dev/null +++ b/test/src/test/resources/eth2.0-temp-test-configs/fork_timelines/testing.yaml @@ -0,0 +1,6 @@ +# Testing fork timeline + +# Equal to GENESIS_EPOCH +phase0: 536870912 + +# No other forks considered in testing yet (to be implemented) diff --git a/test/src/test/resources/eth2.0-tests b/test/src/test/resources/eth2.0-tests deleted file mode 160000 index 33e762c76..000000000 --- a/test/src/test/resources/eth2.0-tests +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 33e762c76e0a9458d9d89fa4f9c696e769fb2e2f diff --git a/types/src/main/java/tech/pegasys/artemis/util/collections/WriteList.java b/types/src/main/java/tech/pegasys/artemis/util/collections/WriteList.java index 917766b40..abaab6a83 100644 --- a/types/src/main/java/tech/pegasys/artemis/util/collections/WriteList.java +++ b/types/src/main/java/tech/pegasys/artemis/util/collections/WriteList.java @@ -29,6 +29,11 @@ public interface WriteList boolean addAll(IndexType index, @NotNull Collection c); + default void replaceAll(@NotNull Collection c) { + this.clear(); + this.addAll(c); + } + void sort(Comparator c); void clear(); diff --git a/types/src/main/java/tech/pegasys/artemis/util/uint/UInt64.java b/types/src/main/java/tech/pegasys/artemis/util/uint/UInt64.java index ae2f434e9..dfe964d60 100644 --- a/types/src/main/java/tech/pegasys/artemis/util/uint/UInt64.java +++ b/types/src/main/java/tech/pegasys/artemis/util/uint/UInt64.java @@ -14,6 +14,8 @@ package tech.pegasys.artemis.util.uint; import com.google.common.primitives.UnsignedLongs; + +import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Objects; @@ -434,6 +436,10 @@ public long longValue() { return getValue(); } + public BigInteger toBI() { + return new BigInteger(1, toBytesBigEndian().extractArray()); + } + @Override public float floatValue() { return getValue();