public static BeaconBlock BuildEmptyBlock(IServiceProvider testServiceProvider, BeaconState state, Slot slot, bool signed) { //if (slot) is none 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 eth1Data = new Eth1Data(state.Eth1DepositIndex, Hash32.Zero); var previousBlockHeader = BeaconBlockHeader.Clone(state.LatestBlockHeader); if (previousBlockHeader.StateRoot == Hash32.Zero) { var stateRoot = state.HashTreeRoot(miscellaneousParameters, timeParameters, stateListLengths, maxOperationsPerBlock); previousBlockHeader.SetStateRoot(stateRoot); } var previousBlockSigningRoot = previousBlockHeader.SigningRoot(); var emptyBlock = new BeaconBlock(slot, previousBlockSigningRoot, Hash32.Zero, new BeaconBlockBody( BlsSignature.Empty, eth1Data, new Bytes32(), Array.Empty <ProposerSlashing>(), Array.Empty <AttesterSlashing>(), Array.Empty <Attestation>(), Array.Empty <Deposit>(), Array.Empty <VoluntaryExit>() ), BlsSignature.Empty); if (signed) { SignBlock(testServiceProvider, state, emptyBlock, ValidatorIndex.None); } return(emptyBlock); }
public async Task <BeaconBlock> NewBlockAsync(Slot slot, BlsSignature randaoReveal) { if (!_storeProvider.TryGetStore(out IStore? store)) { throw new Exception("Beacon chain is currently syncing or waiting for genesis."); } Hash32 head = await _forkChoice.GetHeadAsync(store !); // get previous head block, based on the fork choice // get latest state // process outstanding slots for state // get parent header (state root, signature, slot, parent root, body root) BeaconBlockBody body = new BeaconBlockBody(randaoReveal, new Eth1Data(0, Hash32.Zero), new Bytes32(), Array.Empty <ProposerSlashing>(), Array.Empty <AttesterSlashing>(), Array.Empty <Attestation>(), Array.Empty <Deposit>(), Array.Empty <VoluntaryExit>()); BeaconBlock block = new BeaconBlock(slot, Hash32.Zero, Hash32.Zero, body, BlsSignature.Empty); // new block = slot, parent root, // signature = null // body = assemble body // assemble body: // from opPool get proposer slashings, attester slashings, attestations, voluntary exits // get eth1data // generate deposits (based on new data) // -> if eth1data deposit count > state deposit index, then get from op pool, sort and calculate merkle tree // deposit root = merkleRoot // randaoReveal // apply block to state transition // block.stateRoot = new state hash return(await Task.Run(() => block)); }
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 + 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); }