Skip to content

Commit

Permalink
refactor: #666 Refactor states and services. (#716)
Browse files Browse the repository at this point in the history
# Description
See the following PRs:
#688
#701
#691

---------

Co-authored-by: Hristiyan Mitov <[email protected]>
Co-authored-by: Hristiyan Mitov <[email protected]>
  • Loading branch information
3 people authored Jan 27, 2025
1 parent 0e86c95 commit a1a422a
Show file tree
Hide file tree
Showing 66 changed files with 1,097 additions and 696 deletions.
8 changes: 8 additions & 0 deletions src/main/java/com/limechain/NodeService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.limechain;

public interface NodeService {

void start();

void stop();
}
14 changes: 14 additions & 0 deletions src/main/java/com/limechain/ServiceConsensusState.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.limechain;

import com.limechain.runtime.Runtime;

/**
* This interface defines states that are initialized by runtime data and updated
* via consensus messages (e.g. BABE, GRANDPA, BEEFY).
*
* <p>Implementing classes initialize state from runtime and update it with consensus messages.</p>
*/
public interface ServiceConsensusState {

void populateDataFromRuntime(Runtime runtime);
}
10 changes: 10 additions & 0 deletions src/main/java/com/limechain/ServiceState.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.limechain;

public interface ServiceState {

void initialize();

void initializeFromDatabase();

void persistState();
}
30 changes: 16 additions & 14 deletions src/main/java/com/limechain/babe/BabeService.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
import com.limechain.network.protocol.warp.dto.ConsensusEngine;
import com.limechain.network.protocol.warp.dto.DigestType;
import com.limechain.network.protocol.warp.dto.HeaderDigest;
import com.limechain.rpc.server.AppBean;
import com.limechain.runtime.Runtime;
import com.limechain.runtime.RuntimeBuilder;
import com.limechain.state.StateManager;
import com.limechain.storage.block.BlockHandler;
import com.limechain.storage.block.BlockState;
import com.limechain.storage.block.state.BlockState;
import com.limechain.storage.crypto.KeyStore;
import com.limechain.storage.crypto.KeyType;
import com.limechain.transaction.TransactionState;
Expand Down Expand Up @@ -55,27 +55,26 @@
@Component
public class BabeService implements SlotChangeListener {

private final TransactionState transactionState;
private final EpochState epochState;
private final BlockState blockState;
private final StateManager stateManager;
private final KeyStore keyStore;
private final AsyncExecutor asyncExecutor;
private final Map<BigInteger, BabePreDigest> slotToPreRuntimeDigest = new HashedMap<>();
private final RuntimeBuilder runtimeBuilder;
private final BlockHandler blockHandler;

public BabeService(TransactionState transactionState, EpochState epochState, KeyStore keyStore, RuntimeBuilder runtimeBuilder, BlockHandler blockHandler) {
this.transactionState = transactionState;
this.epochState = epochState;
public BabeService(StateManager stateManager,
KeyStore keyStore,
RuntimeBuilder runtimeBuilder,
BlockHandler blockHandler) {
this.stateManager = stateManager;
this.keyStore = keyStore;
this.runtimeBuilder = runtimeBuilder;

blockState = BlockState.getInstance();
asyncExecutor = AsyncExecutor.withSingleThread();
this.blockHandler = blockHandler;
}

private void executeEpochLottery(BigInteger epochIndex) {
EpochState epochState = stateManager.getEpochState();
var epochStartSlotNumber = epochState.getEpochStartSlotNumber(epochIndex);
var epochEndSlotNumber = epochStartSlotNumber.add(epochState.getEpochLength());

Expand All @@ -102,14 +101,15 @@ private void handleSlot(Slot slot, BabePreDigest preDigest) {
return;
}

blockHandler.handleProducedBlock(block);
blockHandler.handleProduced(block);
}

private Block produceBlock(BlockHeader parentHeader, Slot slot, BabePreDigest preDigest) {
BlockHeader newBlockHeader = new BlockHeader();
newBlockHeader.setParentHash(parentHeader.getHash());
newBlockHeader.setBlockNumber(slot.getNumber().add(BigInteger.ONE));

BlockState blockState = stateManager.getBlockState();
Runtime runtime = blockState.getRuntime(parentHeader.getHash());
Runtime newRuntime = runtimeBuilder.copyRuntime(runtime);
newRuntime.initializeBlock(newBlockHeader);
Expand All @@ -126,7 +126,7 @@ private Block produceBlock(BlockHeader parentHeader, Slot slot, BabePreDigest pr
try {
finalizedHeader = newRuntime.finalizeBlock();
} catch (Exception e) {
transactions.forEach(transactionState::pushTransaction);
transactions.forEach(stateManager.getTransactionState()::pushTransaction);
throw new BabeGenericException("Block finalization failed. Pushed transaction back to queue.");
}
log.fine("Finished with finalizing block.");
Expand Down Expand Up @@ -159,7 +159,7 @@ private HeaderDigest[] produceDigests(BlockHeader header, BabePreDigest digest)

newDigests[length + 1] = preDigest;

Authority auth = epochState.getCurrentEpochData().getAuthorities()
Authority auth = stateManager.getEpochState().getCurrentEpochData().getAuthorities()
.get((int) digest.getAuthorityIndex());
Schnorrkel.KeyPair keyPair = keyStore.getKeyPair(KeyType.BABE, auth.getPublicKey())
.orElseThrow(() -> new KeyStoreException("No KeyPair found for provided pub key."));
Expand All @@ -179,6 +179,7 @@ private List<ValidTransaction> produceBlockTransactions(Slot slot, Runtime runti

Duration timeout = Duration.between(Instant.now(), slotEnd);

TransactionState transactionState = stateManager.getTransactionState();
// while not End-Of-Slot
while (timeout.isPositive()) {
timeout = Duration.between(Instant.now(), slotEnd);
Expand Down Expand Up @@ -247,12 +248,13 @@ private ExtrinsicArray produceBlockInherents(Slot slot, Runtime runtime) {
}

private BlockHeader getParentBlockHeader(BigInteger slotNum) {
BlockState blockState = stateManager.getBlockState();
BlockHeader parentHeader = blockState.bestBlockHeader();
if (parentHeader == null) {
throw new BlockStorageGenericException("Could not get best block header");
}

boolean parentIsGenesis = blockState.getGenesisHash().equals(parentHeader.getHash());
boolean parentIsGenesis = blockState.getGenesisBlockHeader().getHash().equals(parentHeader.getHash());
if (!parentIsGenesis) {
BigInteger bestBlockSlotNum = DigestHelper.getBabePreRuntimeDigest(parentHeader.getDigest())
.orElseThrow(() ->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.limechain.babe.api.scale;

import com.limechain.babe.api.BabeApiConfiguration;
import com.limechain.chain.lightsyncstate.BabeEpoch;
import com.limechain.chain.lightsyncstate.scale.AuthorityReader;
import com.limechain.babe.api.BabeApiConfiguration;
import com.limechain.utils.scale.readers.PairReader;
import io.emeraldpay.polkaj.scale.ScaleCodecReader;
import io.emeraldpay.polkaj.scale.ScaleReader;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.limechain.babe.predigest.scale;

import com.limechain.babe.predigest.PreDigestType;
import com.limechain.babe.predigest.BabePreDigest;
import com.limechain.babe.predigest.PreDigestType;
import io.emeraldpay.polkaj.scale.ScaleCodecWriter;
import io.emeraldpay.polkaj.scale.ScaleWriter;
import io.emeraldpay.polkaj.scale.writer.UInt64Writer;
Expand Down
27 changes: 22 additions & 5 deletions src/main/java/com/limechain/babe/state/EpochState.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.limechain.babe.state;

import com.limechain.babe.api.BabeApiConfiguration;
import com.limechain.ServiceConsensusState;
import com.limechain.babe.consensus.BabeConsensusMessage;
import com.limechain.runtime.Runtime;
import com.limechain.state.AbstractState;
import com.limechain.storage.KVRepository;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.math.BigInteger;
Expand All @@ -15,9 +19,10 @@
*/
@Getter
@Component
public class EpochState {
@RequiredArgsConstructor
public class EpochState extends AbstractState implements ServiceConsensusState {

private boolean isInitialized = false;
private final KVRepository<String, Object> repository;

private BigInteger disabledAuthority;
private BigInteger slotDuration;
Expand All @@ -30,14 +35,26 @@ public class EpochState {
private EpochData nextEpochData;
private EpochDescriptor nextEpochDescriptor;

public void initialize(BabeApiConfiguration babeApiConfiguration) {
@Override
public void populateDataFromRuntime(Runtime runtime) {
var babeApiConfiguration = runtime.getBabeApiConfiguration();
this.slotDuration = babeApiConfiguration.getSlotDuration();
this.epochLength = babeApiConfiguration.getEpochLength();
this.currentEpochData = new EpochData(
babeApiConfiguration.getAuthorities(), babeApiConfiguration.getRandomness());
this.currentEpochDescriptor = new EpochDescriptor(
babeApiConfiguration.getConstant(), babeApiConfiguration.getAllowedSlots());
this.isInitialized = true;
setGenesisSlotNumber(runtime.getGenesisSlotNumber());
}

@Override
public void initializeFromDatabase() {
//TODO: Add methods to load epoch state data.
}

@Override
public void persistState() {
//TODO: Add methods to store epoch state data.
}

public void updateNextEpochConfig(BabeConsensusMessage message) {
Expand Down
89 changes: 0 additions & 89 deletions src/main/java/com/limechain/client/AbstractNode.java

This file was deleted.

28 changes: 24 additions & 4 deletions src/main/java/com/limechain/client/AuthoringNode.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
package com.limechain.client;

public class AuthoringNode extends AbstractNode {
import com.limechain.babe.state.EpochState;
import com.limechain.grandpa.state.GrandpaSetState;
import com.limechain.network.NetworkService;
import com.limechain.rpc.server.AppBean;
import com.limechain.storage.block.state.BlockState;
import com.limechain.sync.SyncService;
import com.limechain.sync.state.SyncState;
import com.limechain.transaction.TransactionState;

@Override
public void start() {
super.start();
import java.util.List;
import java.util.Objects;

public class AuthoringNode extends HostNode {

public AuthoringNode() {
super(List.of(
//TODO Add babe and grandpa services.
Objects.requireNonNull(AppBean.getBean(NetworkService.class)),
Objects.requireNonNull(AppBean.getBean(SyncService.class))),
List.of(
Objects.requireNonNull(AppBean.getBean(BlockState.class)),
Objects.requireNonNull(AppBean.getBean(SyncState.class)),
Objects.requireNonNull(AppBean.getBean(EpochState.class)),
Objects.requireNonNull(AppBean.getBean(GrandpaSetState.class)),
Objects.requireNonNull(AppBean.getBean(TransactionState.class))));
}
}
26 changes: 20 additions & 6 deletions src/main/java/com/limechain/client/FullNode.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
package com.limechain.client;

import lombok.extern.java.Log;
import com.limechain.babe.state.EpochState;
import com.limechain.grandpa.state.GrandpaSetState;
import com.limechain.network.NetworkService;
import com.limechain.rpc.server.AppBean;
import com.limechain.storage.block.state.BlockState;
import com.limechain.sync.SyncService;
import com.limechain.sync.state.SyncState;

@Log
public class FullNode extends AbstractNode {
import java.util.List;
import java.util.Objects;

@Override
public void start() {
super.start();
public class FullNode extends HostNode {

public FullNode() {
super(List.of(
Objects.requireNonNull(AppBean.getBean(NetworkService.class)),
Objects.requireNonNull(AppBean.getBean(SyncService.class))),
List.of(
Objects.requireNonNull(AppBean.getBean(BlockState.class)),
Objects.requireNonNull(AppBean.getBean(SyncState.class)),
Objects.requireNonNull(AppBean.getBean(EpochState.class)),
Objects.requireNonNull(AppBean.getBean(GrandpaSetState.class))));
}
}
Loading

0 comments on commit a1a422a

Please sign in to comment.