Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

logic of BatcherSubmitter #37

Merged
merged 1 commit into from
Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions hildr-batcher/src/main/java/io/optimism/batcher/BatcherSubmitter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright 2023 q315xia@163.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package io.optimism.batcher;

import com.google.common.util.concurrent.AbstractExecutionThreadService;
import io.optimism.batcher.channel.ChannelManager;
import io.optimism.batcher.config.Config;
import io.optimism.batcher.ex.BatcherExecutionException;
import io.optimism.batcher.loader.BlockLoader;
import io.optimism.batcher.loader.LoaderConfig;
import io.optimism.batcher.publisher.ChannelDataPublisher;
import io.optimism.batcher.publisher.PublisherConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.web3j.protocol.core.methods.response.TransactionReceipt;

/**
* BatcherSubmitter class.
*
* @author thinkAfCod
* @since 0.1.1
*/
@SuppressWarnings("UnusedVariable")
public class BatcherSubmitter extends AbstractExecutionThreadService {

private static final Logger LOGGER = LoggerFactory.getLogger(BatcherSubmitter.class);

private final Config config;

private final ChannelManager channelManager;
private final BlockLoader blockLoader;
private final ChannelDataPublisher channelPublisher;

private volatile boolean isShutdownTriggered = false;

/**
* Constructor of BatcherSubmitter.
*
* @param config BatcherSubmitter config
*/
public BatcherSubmitter(Config config) {
this.config = config;
this.channelManager = new ChannelManager();
this.blockLoader = new BlockLoader(LoaderConfig.from(config), this.channelManager::addL2Block);

this.channelPublisher =
new ChannelDataPublisher(
PublisherConfig.from(config, this.blockLoader.getRollConfig().batchInboxAddress()),
this.channelManager::txData,
this::handleReceipt);
}

private void trySubmitBatchData() {
this.blockLoader.loadBlock();
// If no data has been sent, then sleep for a period of time.
if (!this.channelPublisher.publishPendingBlock()) {
try {
Thread.sleep(config.pollInterval());
} catch (InterruptedException e) {
thinkAfCod marked this conversation as resolved.
Show resolved Hide resolved
Thread.currentThread().interrupt();
throw new BatcherExecutionException(e);
}
}
}

private void handleReceipt(TransactionReceipt receipt) {
if (receipt.isStatusOK()) {
// todo this.channelManager.txConfirmed();
} else {
// todo this.channelManager.txFailed();
}
}

@Override
protected void run() throws Exception {
while (isRunning() && !this.isShutdownTriggered) {
this.trySubmitBatchData();
}
}

@Override
protected void shutDown() throws Exception {
super.shutDown();
this.blockLoader.close();
this.channelPublisher.close();
this.channelManager.clear();
}

@Override
protected void triggerShutdown() {
this.isShutdownTriggered = true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2023 q315xia@163.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package io.optimism.batcher.channel;

import org.apache.commons.lang3.ArrayUtils;

/**
* Channel interface. cache batch submit data.
*
* @author thinkAfCod
* @since 0.1.1
*/
public interface Channel {

/** Derivation version. */
byte DERIVATION_VERSION_0 = 0;

/**
* Channel Tx Data class.
*
* @param data L2 block data that will send to L1
* @param channelId channelId
* @param frameNumber channel frame number
*/
record TxData(byte[] data, byte[] channelId, int frameNumber) {
/**
* Get tx bytes.
*
* @return tx bytes
*/
public byte[] txBytes() {
return ArrayUtils.addAll(new byte[] {DERIVATION_VERSION_0}, data());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2023 q315xia@163.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package io.optimism.batcher.channel;

import io.optimism.batcher.config.Config;

/**
* ChannelConfig class.
*
* @param channelTimeout The maximum number of L1 blocks that the inclusion transactions of a
* channel's frames can span.
* @param maxChannelDuration If 0, duration checks are disabled.
* @param maxFrameSize The maximum byte-size a frame can have.
* @author thinkAfCod
* @since 0.1.1
*/
public record ChannelConfig(long channelTimeout, long maxChannelDuration, int maxFrameSize) {

/**
* Create a ChannelConfig instance from Config instance.
*
* @param config Config instance
* @return ChannelConfig instance
*/
public static ChannelConfig from(Config config) {
return new ChannelConfig(30000, 0, 120_000);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2023 q315xia@163.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package io.optimism.batcher.channel;

/**
* Channel class.Record the batcher data of block transaction and process this data with framing.
*
* @author thinkAfCod
* @since 0.1.1
*/
public class ChannelImpl implements Channel {

/** Constructor of ChannelImpl. */
public ChannelImpl() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright 2023 q315xia@163.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package io.optimism.batcher.channel;

import io.optimism.batcher.ex.ReorgException;
import io.optimism.type.BlockId;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.web3j.protocol.core.methods.response.EthBlock;

/**
* ChannelManager class. create and remove channel object.
*
* @author thinkAfCod
* @since 0.1.1
*/
public class ChannelManager {

private List<EthBlock.Block> blocks;

private String latestBlockHash;

/** Constructor of ChannelManager. */
public ChannelManager() {
this.blocks = new ArrayList<>(256);
}

/**
* Adds an L2 block to the internal blocks queue. It throws ReorgException if the block does not
* extend the last block loaded into the state. If no blocks were added yet, the parent hash check
* is skipped.
*
* @param block L2 block data
*/
public void addL2Block(EthBlock.Block block) {
if (!StringUtils.isEmpty(latestBlockHash) && !latestBlockHash.equals(block.getParentHash())) {
throw new ReorgException("block does not extend existing chain");
}
// todo metrics pending block
this.blocks.add(block);
this.latestBlockHash = block.getHash();
}

/**
* Returns the next tx data that should be submitted to L1.
*
* <p>It currently only uses one frame per transaction. If the pending channel is full, it only
* returns the remaining frames of this channel until it got successfully fully sent to L1. It
* returns io.EOF if there's no pending frame.
*
* @param l1Head l1 head block id
* @return The next tx data that should be submitted to L1.
*/
public Channel.TxData txData(BlockId l1Head) {
return null;
}

/**
* Records a transaction as failed. It will attempt to resubmit the data in the failed
* transaction.
*
* @param txId channel tx id
*/
public void txFailed(Channel.TxData txId) {}

/**
* Marks a transaction as confirmed on L1. Unfortunately even if all frames in a channel have been
* marked as confirmed on L1 the channel may be invalid and need to be resubmitted. This function
* may reset the pending channel if the pending channel has timed out.
*
* @param txId channel tx id
* @param inclusionBlock inclusion block id
*/
public void txConfirmed(Channel.TxData txId, BlockId inclusionBlock) {}

/** Clear blocks and channels that have not entered the pending state. */
public void clear() {}
}
41 changes: 41 additions & 0 deletions hildr-batcher/src/main/java/io/optimism/batcher/config/Config.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2023 q315xia@163.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package io.optimism.batcher.config;

/**
* Batcher config.
*
* @param l1RpcUrl L1 rpc url
* @param l2RpcUrl L2 rpc url
* @param rollupRpcUrl Op-node rpc url
* @param l1Signer L1 signer private key
* @param batchInboxAddress address of BatchInboxContract on l1
* @param subSafetyMargin Sub-safety margin
* @param pollInterval Milliseconds of poll interval
* @param maxL1TxSize Max L1 Tx Size
* @author thinkAfCod
* @since 0.1.1
*/
public record Config(
String l1RpcUrl,
String l2RpcUrl,
String rollupRpcUrl,
String l1Signer,
String batchInboxAddress,
Long subSafetyMargin,
Long pollInterval,
Long maxL1TxSize) {}
Loading
Loading