Esempio n. 1
0
        public async Task GenesisHead()
        {
            // Arrange
            var testServiceProvider = TestSystem.BuildTestServiceProvider(useStore: true);
            var state = TestState.PrepareTestState(testServiceProvider);

            var miscellaneousParameters = testServiceProvider.GetService <IOptions <MiscellaneousParameters> >().Value;
            var timeParameters          = testServiceProvider.GetService <IOptions <TimeParameters> >().Value;
            var stateListLengths        = testServiceProvider.GetService <IOptions <StateListLengths> >().Value;
            var maxOperationsPerBlock   = testServiceProvider.GetService <IOptions <MaxOperationsPerBlock> >().Value;

            var options = new System.Text.Json.JsonSerializerOptions {
                WriteIndented = true
            };

            options.AddCortexContainerConverters();
            var debugState = System.Text.Json.JsonSerializer.Serialize(state, options);

            // Initialization
            var forkChoice = testServiceProvider.GetService <ForkChoice>();
            var store      = forkChoice.GetGenesisStore(state);

            // Act
            var headRoot = await forkChoice.GetHeadAsync(store);

            // Assert
            var stateRoot    = state.HashTreeRoot(miscellaneousParameters, timeParameters, stateListLengths, maxOperationsPerBlock);
            var genesisBlock = new BeaconBlock(stateRoot);
            var expectedRoot = genesisBlock.SigningRoot(miscellaneousParameters, maxOperationsPerBlock);

            headRoot.ShouldBe(expectedRoot);
        }
Esempio n. 2
0
        public async Task ChainNoAttestations()
        {
            // Arrange
            IServiceProvider testServiceProvider = TestSystem.BuildTestServiceProvider(useStore: true);
            BeaconState      state = TestState.PrepareTestState(testServiceProvider);

            MiscellaneousParameters miscellaneousParameters = testServiceProvider.GetService <IOptions <MiscellaneousParameters> >().Value;
            MaxOperationsPerBlock   maxOperationsPerBlock   = testServiceProvider.GetService <IOptions <MaxOperationsPerBlock> >().Value;

            // Initialization
            ForkChoice forkChoice = testServiceProvider.GetService <ForkChoice>();
            IStore     store      = forkChoice.GetGenesisStore(state);

            // On receiving a block of `GENESIS_SLOT + 1` slot
            BeaconBlock block1 = TestBlock.BuildEmptyBlockForNextSlot(testServiceProvider, state, signed: true);

            TestState.StateTransitionAndSignBlock(testServiceProvider, state, block1);
            AddBlockToStore(testServiceProvider, store, block1);

            // On receiving a block of next epoch
            BeaconBlock block2 = TestBlock.BuildEmptyBlockForNextSlot(testServiceProvider, state, signed: true);

            TestState.StateTransitionAndSignBlock(testServiceProvider, state, block2);
            AddBlockToStore(testServiceProvider, store, block2);

            // Act
            Hash32 headRoot = await forkChoice.GetHeadAsync(store);

            // Assert
            Hash32 expectedRoot = block2.SigningRoot(miscellaneousParameters, maxOperationsPerBlock);

            headRoot.ShouldBe(expectedRoot);
        }
        public Hash32 SigningRoot(BeaconBlock beaconBlock)
        {
            MiscellaneousParameters miscellaneousParameters = _miscellaneousParameterOptions.CurrentValue;
            MaxOperationsPerBlock   maxOperationsPerBlock   = _maxOperationsPerBlockOptions.CurrentValue;

            return(beaconBlock.SigningRoot(maxOperationsPerBlock.MaximumProposerSlashings,
                                           maxOperationsPerBlock.MaximumAttesterSlashings, maxOperationsPerBlock.MaximumAttestations,
                                           maxOperationsPerBlock.MaximumDeposits, maxOperationsPerBlock.MaximumVoluntaryExits,
                                           miscellaneousParameters.MaximumValidatorsPerCommittee));
        }
Esempio n. 4
0
 public Hash32 SigningRoot(BeaconBlock beaconBlock)
 {
     // TODO: Signing root version of Nethermind SSZ; or are removed in later version of spec, so maybe just wait until then
     
     MiscellaneousParameters miscellaneousParameters = _miscellaneousParameterOptions.CurrentValue;
     MaxOperationsPerBlock maxOperationsPerBlock = _maxOperationsPerBlockOptions.CurrentValue;
     return beaconBlock.SigningRoot(maxOperationsPerBlock.MaximumProposerSlashings,
         maxOperationsPerBlock.MaximumAttesterSlashings, maxOperationsPerBlock.MaximumAttestations,
         maxOperationsPerBlock.MaximumDeposits, maxOperationsPerBlock.MaximumVoluntaryExits,
         miscellaneousParameters.MaximumValidatorsPerCommittee);
 }
Esempio n. 5
0
        public static void SignBlock(IServiceProvider testServiceProvider, BeaconState state, BeaconBlock block, ValidatorIndex proposerIndex)
        {
            var miscellaneousParameters = testServiceProvider.GetService <IOptions <MiscellaneousParameters> >().Value;
            var timeParameters          = testServiceProvider.GetService <IOptions <TimeParameters> >().Value;
            var maxOperationsPerBlock   = testServiceProvider.GetService <IOptions <MaxOperationsPerBlock> >().Value;
            var signatureDomains        = testServiceProvider.GetService <IOptions <SignatureDomains> >().Value;

            var beaconChainUtility    = testServiceProvider.GetService <BeaconChainUtility>();
            var beaconStateAccessor   = testServiceProvider.GetService <BeaconStateAccessor>();
            var beaconStateTransition = testServiceProvider.GetService <BeaconStateTransition>();

            if (state.Slot > block.Slot)
            {
                throw new ArgumentOutOfRangeException("block.Slot", block.Slot, $"Slot of block must be equal or less that state slot {state.Slot}");
            }

            var blockEpoch = beaconChainUtility.ComputeEpochAtSlot(block.Slot);

            if (proposerIndex == ValidatorIndex.None)
            {
                if (block.Slot == state.Slot)
                {
                    proposerIndex = beaconStateAccessor.GetBeaconProposerIndex(state);
                }
                else
                {
                    var stateEpoch = beaconChainUtility.ComputeEpochAtSlot(state.Slot);
                    if (stateEpoch + new Epoch(1) > blockEpoch)
                    {
                        Console.WriteLine("WARNING: Block slot far away, and no proposer index manually given."
                                          + " Signing block is slow due to transition for proposer index calculation.");
                    }
                    // use stub state to get proposer index of future slot
                    var stubState = BeaconState.Clone(state);
                    beaconStateTransition.ProcessSlots(stubState, block.Slot);
                    proposerIndex = beaconStateAccessor.GetBeaconProposerIndex(stubState);
                }
            }

            var privateKeys = TestKeys.PrivateKeys(timeParameters).ToArray();
            var privateKey  = privateKeys[(int)(ulong)proposerIndex];

            var randaoDomain     = beaconStateAccessor.GetDomain(state, signatureDomains.Randao, blockEpoch);
            var randaoRevealHash = blockEpoch.HashTreeRoot();
            var randaoReveal     = TestSecurity.BlsSign(randaoRevealHash, privateKey, randaoDomain);

            block.Body.SetRandaoReveal(randaoReveal);

            var signatureDomain = beaconStateAccessor.GetDomain(state, signatureDomains.BeaconProposer, blockEpoch);
            var signingRoot     = block.SigningRoot(miscellaneousParameters, maxOperationsPerBlock);
            var signature       = TestSecurity.BlsSign(signingRoot, privateKey, signatureDomain);

            block.SetSignature(signature);
        }
Esempio n. 6
0
        public async Task ShorterChainButHeavierWeight()
        {
            // Arrange
            IServiceProvider testServiceProvider = TestSystem.BuildTestServiceProvider(useStore: true);
            BeaconState      state = TestState.PrepareTestState(testServiceProvider);

            MiscellaneousParameters miscellaneousParameters = testServiceProvider.GetService <IOptions <MiscellaneousParameters> >().Value;
            MaxOperationsPerBlock   maxOperationsPerBlock   = testServiceProvider.GetService <IOptions <MaxOperationsPerBlock> >().Value;

            // Initialization
            ForkChoice  forkChoice   = testServiceProvider.GetService <ForkChoice>();
            IStore      store        = forkChoice.GetGenesisStore(state);
            BeaconState genesisState = BeaconState.Clone(state);

            // build longer tree
            Hash32      longRoot  = default;
            BeaconState longState = BeaconState.Clone(genesisState);

            for (int i = 0; i < 3; i++)
            {
                BeaconBlock longBlock = TestBlock.BuildEmptyBlockForNextSlot(testServiceProvider, longState, signed: true);
                TestState.StateTransitionAndSignBlock(testServiceProvider, longState, longBlock);
                AddBlockToStore(testServiceProvider, store, longBlock);
                if (i == 2)
                {
                    longRoot = longBlock.SigningRoot(miscellaneousParameters, maxOperationsPerBlock);
                }
            }

            // build short tree
            BeaconState shortState = BeaconState.Clone(genesisState);
            BeaconBlock shortBlock = TestBlock.BuildEmptyBlockForNextSlot(testServiceProvider, shortState, signed: true);

            shortBlock.Body.SetGraffiti(new Bytes32(Enumerable.Repeat((byte)0x42, 32).ToArray()));
            TestBlock.SignBlock(testServiceProvider, shortState, shortBlock, ValidatorIndex.None);
            TestState.StateTransitionAndSignBlock(testServiceProvider, shortState, shortBlock);
            AddBlockToStore(testServiceProvider, store, shortBlock);

            Attestation shortAttestation = TestAttestation.GetValidAttestation(testServiceProvider, shortState, shortBlock.Slot, CommitteeIndex.None, signed: true);

            AddAttestationToStore(testServiceProvider, store, shortAttestation);

            // Act
            Hash32 headRoot = await forkChoice.GetHeadAsync(store);

            // Assert
            Hash32 expectedRoot = shortBlock.SigningRoot(miscellaneousParameters, maxOperationsPerBlock);

            headRoot.ShouldBe(expectedRoot);
            headRoot.ShouldNotBe(longRoot);
        }
Esempio n. 7
0
        public void ProcessBlockHeader(BeaconState state, BeaconBlock block)
        {
            _logger.LogInformation(Event.ProcessBlock, "Process block header for block {BeaconBlock}", block);
            // Verify that the slots match
            if (block.Slot != state.Slot)
            {
                throw new ArgumentOutOfRangeException("block.Slot", block.Slot, $"Block slot must match state slot {state.Slot}.");
            }
            // Verify that the parent matches
            var latestBlockSigningRoot = state.LatestBlockHeader.SigningRoot();

            if (block.ParentRoot != latestBlockSigningRoot)
            {
                throw new ArgumentOutOfRangeException("block.ParentRoot", block.ParentRoot, $"Block parent root must match latest block header root {latestBlockSigningRoot}.");
            }

            // Save current block as the new latest block
            var bodyRoot       = block.Body.HashTreeRoot(_miscellaneousParameterOptions.CurrentValue, _maxOperationsPerBlockOptions.CurrentValue);
            var newBlockHeader = new BeaconBlockHeader(block.Slot,
                                                       block.ParentRoot,
                                                       Hash32.Zero,       // `state_root` is zeroed and overwritten in the next `process_slot` call
                                                       bodyRoot,
                                                       new BlsSignature() //`signature` is zeroed
                                                       );

            state.SetLatestBlockHeader(newBlockHeader);

            // Verify proposer is not slashed
            var beaconProposerIndex = _beaconStateAccessor.GetBeaconProposerIndex(state);
            var proposer            = state.Validators[(int)(ulong)beaconProposerIndex];

            if (proposer.IsSlashed)
            {
                throw new Exception("Beacon proposer must not be slashed.");
            }

            // Verify proposer signature
            var signingRoot    = block.SigningRoot(_miscellaneousParameterOptions.CurrentValue, _maxOperationsPerBlockOptions.CurrentValue);
            var domain         = _beaconStateAccessor.GetDomain(state, _signatureDomainOptions.CurrentValue.BeaconProposer, Epoch.None);
            var validSignature = _cryptographyService.BlsVerify(proposer.PublicKey, signingRoot, block.Signature, domain);

            if (!validSignature)
            {
                throw new Exception($"Block signature must match proposer public key {proposer.PublicKey}");
            }
        }
Esempio n. 8
0
        public async Task SplitTieBreakerNoAttestations()
        {
            // Arrange
            IServiceProvider testServiceProvider = TestSystem.BuildTestServiceProvider(useStore: true);
            BeaconState      state = TestState.PrepareTestState(testServiceProvider);

            MiscellaneousParameters miscellaneousParameters = testServiceProvider.GetService <IOptions <MiscellaneousParameters> >().Value;
            MaxOperationsPerBlock   maxOperationsPerBlock   = testServiceProvider.GetService <IOptions <MaxOperationsPerBlock> >().Value;

            // Initialization
            ForkChoice  forkChoice   = testServiceProvider.GetService <ForkChoice>();
            IStore      store        = forkChoice.GetGenesisStore(state);
            BeaconState genesisState = BeaconState.Clone(state);

            // block at slot 1
            BeaconState block1State = BeaconState.Clone(genesisState);
            BeaconBlock block1      = TestBlock.BuildEmptyBlockForNextSlot(testServiceProvider, block1State, signed: true);

            TestState.StateTransitionAndSignBlock(testServiceProvider, block1State, block1);
            AddBlockToStore(testServiceProvider, store, block1);
            Hash32 block1Root = block1.SigningRoot(miscellaneousParameters, maxOperationsPerBlock);

            // build short tree
            BeaconState block2State = BeaconState.Clone(genesisState);
            BeaconBlock block2      = TestBlock.BuildEmptyBlockForNextSlot(testServiceProvider, block2State, signed: true);

            block2.Body.SetGraffiti(new Bytes32(Enumerable.Repeat((byte)0x42, 32).ToArray()));
            TestBlock.SignBlock(testServiceProvider, block2State, block2, ValidatorIndex.None);
            TestState.StateTransitionAndSignBlock(testServiceProvider, block2State, block2);
            AddBlockToStore(testServiceProvider, store, block2);
            Hash32 block2Root = block2.SigningRoot(miscellaneousParameters, maxOperationsPerBlock);

            // Act
            Hash32 headRoot = await forkChoice.GetHeadAsync(store);

            // Assert
            Console.WriteLine("block1 {0}", block1Root);
            Console.WriteLine("block2 {0}", block2Root);
            Hash32 highestRoot = block1Root.CompareTo(block2Root) > 0 ? block1Root : block2Root;

            Console.WriteLine("highest {0}", highestRoot);
            headRoot.ShouldBe(highestRoot);
        }
Esempio n. 9
0
        public IStore GetGenesisStore(BeaconState genesisState)
        {
            var miscellaneousParameters = _miscellaneousParameterOptions.CurrentValue;
            var maxOperationsPerBlock   = _maxOperationsPerBlockOptions.CurrentValue;

            var stateRoot           = genesisState.HashTreeRoot(miscellaneousParameters, _timeParameterOptions.CurrentValue, _stateListLengthOptions.CurrentValue, maxOperationsPerBlock);
            var genesisBlock        = new BeaconBlock(stateRoot);
            var root                = genesisBlock.SigningRoot(miscellaneousParameters, maxOperationsPerBlock);
            var justifiedCheckpoint = new Checkpoint(_initialValueOptions.CurrentValue.GenesisEpoch, root);
            var finalizedCheckpoint = new Checkpoint(_initialValueOptions.CurrentValue.GenesisEpoch, root);

            _logger.LogInformation(Event.CreateGenesisStore, "Creating genesis store with block {BeaconBlock} for state {BeaconState}, with checkpoint {JustifiedCheckpoint}, with signing root {SigningRoot}",
                                   genesisBlock, genesisState, justifiedCheckpoint, root);

            var blocks = new Dictionary <Hash32, BeaconBlock>
            {
                [root] = genesisBlock
            };
            var blockStates = new Dictionary <Hash32, BeaconState>
            {
                [root] = BeaconState.Clone(genesisState)
            };
            var checkpointStates = new Dictionary <Checkpoint, BeaconState>
            {
                [justifiedCheckpoint] = BeaconState.Clone(genesisState)
            };

            var store = _storeProvider.CreateStore(
                genesisState.GenesisTime,
                genesisState.GenesisTime,
                justifiedCheckpoint,
                finalizedCheckpoint,
                justifiedCheckpoint,
                blocks,
                blockStates,
                checkpointStates,
                new Dictionary <ValidatorIndex, LatestMessage>()
                );

            return(store);
        }
Esempio n. 10
0
        private void RunOnBlock(IServiceProvider testServiceProvider, IStore store, BeaconBlock block, bool expectValid)
        {
            var miscellaneousParameters = testServiceProvider.GetService <IOptions <MiscellaneousParameters> >().Value;
            var maxOperationsPerBlock   = testServiceProvider.GetService <IOptions <MaxOperationsPerBlock> >().Value;

            var forkChoice = testServiceProvider.GetService <ForkChoice>();

            if (!expectValid)
            {
                Should.Throw <Exception>(() =>
                {
                    forkChoice.OnBlock(store, block);
                });
                return;
            }

            forkChoice.OnBlock(store, block);
            var signingRoot = block.SigningRoot(miscellaneousParameters, maxOperationsPerBlock);
            var storeBlock  = store.Blocks[signingRoot];

            storeBlock.ShouldBe(block);
        }
Esempio n. 11
0
        public void OnBlock(IStore store, BeaconBlock block)
        {
            // Make a copy of the state to avoid mutability issues
            if (!store.TryGetBlockState(block.ParentRoot, out BeaconState? parentState) || parentState is null)
            {
                throw new ArgumentOutOfRangeException(nameof(block), block.ParentRoot, "Block parent root not found in the block states history.");
            }

            var preState = BeaconState.Clone(parentState);

            // Blocks cannot be in the future. If they are, their consideration must be delayed until the are in the past.
            var blockTime = preState.GenesisTime + (ulong)block.Slot * _timeParameterOptions.CurrentValue.SecondsPerSlot;

            if (blockTime > store.Time)
            {
                throw new ArgumentOutOfRangeException(nameof(block), blockTime, $"Block slot time cannot be in the future, compared to store time {store.Time}.");
            }

            // Add new block to the store
            var signingRoot = block.SigningRoot(_miscellaneousParameterOptions.CurrentValue, _maxOperationsPerBlockOptions.CurrentValue);

            store.SetBlock(signingRoot, block);

            // Check block is a descendant of the finalized block
            if (!store.TryGetBlock(store.FinalizedCheckpoint.Root, out var finalizedCheckpointBlock))
            {
                throw new Exception($"Block not found for finalized checkpoint root {store.FinalizedCheckpoint.Root}.");
            }

            Hash32 ancestor = GetAncestor(store, signingRoot, finalizedCheckpointBlock !.Slot);

            if (ancestor != store.FinalizedCheckpoint.Root)
            {
                throw new Exception($"Block with signing root {signingRoot} is not a descendant of the finalized block {store.FinalizedCheckpoint.Root} at slot {finalizedCheckpointBlock.Slot}.");
            }

            // Check that block is later than the finalized epoch slot
            var finalizedEpochStartSlot = _beaconChainUtility.ComputeStartSlotOfEpoch(store.FinalizedCheckpoint.Epoch);

            if (block.Slot <= finalizedEpochStartSlot)
            {
                throw new ArgumentOutOfRangeException(nameof(block), block.Slot, $"Block slot must be later than the finalized epoch start slot {finalizedEpochStartSlot}.");
            }

            // Check the block is valid and compute the post-state
            var state = _beaconStateTransition.StateTransition(preState, block, validateStateRoot: true);

            // Add new state for this block to the store
            store.SetBlockState(signingRoot, state);

            _logger.LogInformation(Event.CreateGenesisStore, "Store added block {BeaconBlock} generating state {BeaconState}, with signing root {SigningRoot}",
                                   block, state, signingRoot);

            // Update justified checkpoint
            if (state.CurrentJustifiedCheckpoint.Epoch > store.JustifiedCheckpoint.Epoch)
            {
                store.SetBestJustifiedCheckpoint(state.CurrentJustifiedCheckpoint);
                var shouldUpdateJustifiedCheckpoint = ShouldUpdateJustifiedCheckpoint(store, state.CurrentJustifiedCheckpoint);
                if (shouldUpdateJustifiedCheckpoint)
                {
                    store.SetJustifiedCheckpoint(state.CurrentJustifiedCheckpoint);
                    _logger.LogDebug("Updated justified checkpoint {JustifiedCheckpoint}", state.CurrentJustifiedCheckpoint);
                }
                else
                {
                    _logger.LogDebug("Updated best justified checkpoint {JustifiedCheckpoint}", state.CurrentJustifiedCheckpoint);
                }
            }

            // Update finalized checkpoint
            if (state.FinalizedCheckpoint.Epoch > store.FinalizedCheckpoint.Epoch)
            {
                store.SetFinalizedCheckpoint(state.FinalizedCheckpoint);
                _logger.LogDebug("Updated finalized checkpoint {FinalizedCheckpoint}", state.FinalizedCheckpoint);
            }
        }