Skip to content

Commit

Permalink
fix: decode system config from ecotone tx input
Browse files Browse the repository at this point in the history
  • Loading branch information
thinkAfCod committed Mar 9, 2024
1 parent 2258ce5 commit 1389b93
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 26 deletions.
33 changes: 32 additions & 1 deletion hildr-node/src/main/java/io/optimism/config/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,37 @@ public record SystemConfig(
BigInteger l1FeeScalar,
String unsafeBlockSigner) {

/**
* Create SystemConfig from Bedrock tx input.
* @param unsafeBlockSigner the unsafe block signer
* @param gasLimit l2 gas limit
* @param input l2 block tx input
* @return the system config
*/
public static SystemConfig fromBedrockTxInput(String unsafeBlockSigner, BigInteger gasLimit, byte[] input) {
final String batchSender = Numeric.toHexString(Arrays.copyOfRange(input, 176, 196));
var l1FeeOverhead = Numeric.toBigInt(Arrays.copyOfRange(input, 196, 228));
var l1FeeScalar = Numeric.toBigInt(Arrays.copyOfRange(input, 228, 260));
return new Config.SystemConfig(batchSender, gasLimit, l1FeeOverhead, l1FeeScalar, unsafeBlockSigner);
}

/**
* Create SystemConfig from Ecotone tx input.
* @param unsafeBlockSigner the unsafe block signer
* @param gasLimit l2 gas limit
* @param input l2 block tx input
* @return the system config
*/
public static SystemConfig fromEcotoneTxInput(String unsafeBlockSigner, BigInteger gasLimit, byte[] input) {
final String batchSender = Numeric.toHexString(Arrays.copyOfRange(input, 144, 164));
var originFeeScalar = Arrays.copyOfRange(input, 4, 12);
var destFeeScalar = new byte[32];
System.arraycopy(originFeeScalar, 0, destFeeScalar, 24, originFeeScalar.length);
destFeeScalar[0] = 1;
var l1FeeScalar = Numeric.toBigInt(destFeeScalar);
return new Config.SystemConfig(batchSender, gasLimit, BigInteger.ZERO, l1FeeScalar, unsafeBlockSigner);
}

/**
* Batch hash string.
*
Expand All @@ -724,7 +755,7 @@ public String batcherHash() {
}

/**
* get base fee scalar.
* Get base fee scalar.
* @return tuple contains blobBaseFeeScalar and baseFeeScalar
*/
public Tuple2<BigInteger, BigInteger> ecotoneScalars() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
Expand Down Expand Up @@ -291,7 +292,7 @@ public static UserDeposited fromLog(LogObject log) {
* The type AttributesDeposited.
*
* @param number the number
* @param timestamp the timestamp
* @param timestamp the l1 block timestamp
* @param baseFee the base fee
* @param hash the hash
* @param sequenceNumber the sequence number
Expand Down Expand Up @@ -352,6 +353,95 @@ public static AttributesDeposited fromBlockInfo(
isSystemTx);
}

/**
* decode from l2 bedrock tx input.
* @param txInput the l2 bedrock tx input
* @return the attributes deposited
*/
public static AttributesDeposited decode(String txInput) {
byte[] input = Numeric.hexStringToByteArray(txInput);
if (input.length != 260) {
throw new IllegalArgumentException("bedrock deposit tx input length is not 164 bytes");
}
int offset = 4;
BigInteger l1BlockNum = Numeric.toBigInt(Arrays.copyOfRange(input, offset, offset + 32));
offset += 32;
BigInteger l1BlockTime = Numeric.toBigInt(Arrays.copyOfRange(input, offset, offset + 32));
offset += 32;
BigInteger baseFee = Numeric.toBigInt(Arrays.copyOfRange(input, offset, offset + 32));
offset += 32;
String l1BlockHash = Numeric.toHexString(Arrays.copyOfRange(input, offset, offset + 32));
offset += 32;
BigInteger seqNum = Numeric.toBigInt(Arrays.copyOfRange(input, offset, offset + 32));
offset += 32;
String batcherHash = Numeric.toHexString(Arrays.copyOfRange(input, offset, offset + 32));
offset += 32;
BigInteger l1FeeOverhead = Numeric.toBigInt(Arrays.copyOfRange(input, offset, offset + 32));
offset += 32;
BigInteger l1FeeScalar = Numeric.toBigInt(Arrays.copyOfRange(input, offset, offset + 32));
return new AttributesDeposited(
l1BlockNum,
l1BlockTime,
baseFee,
l1BlockHash,
seqNum,
batcherHash,
l1FeeOverhead,
l1FeeScalar,
BigInteger.ZERO,
BigInteger.ZERO,
BigInteger.ZERO,
BigInteger.ZERO,
false);
}

/**
* decode from l2 ecotone tx input.
* @param txInput the l2 ecotone tx input
* @return the attributes deposited
*/
public static AttributesDeposited decodeForEcotone(String txInput) {
byte[] input = Numeric.hexStringToByteArray(txInput);
if (input.length != 164) {
throw new IllegalArgumentException("ecotone deposit tx input length is not 164 bytes");
}
int offset = 4;
BigInteger baseFeeScalar = Numeric.toBigInt(Arrays.copyOfRange(input, offset, offset + 4));
offset += 4;
BigInteger blobBaseFeeScalar = Numeric.toBigInt(Arrays.copyOfRange(input, offset, offset + 4));
offset += 4;

BigInteger sequenceNum = Numeric.toBigInt(Arrays.copyOfRange(input, offset, offset + 8));
offset += 8;
BigInteger l1Timestamp = Numeric.toBigInt(Arrays.copyOfRange(input, offset, offset + 8));
offset += 8;
BigInteger l1BlockNum = Numeric.toBigInt(Arrays.copyOfRange(input, offset, offset + 8));
offset += 8;

BigInteger baseFee = Numeric.toBigInt(Arrays.copyOfRange(input, offset, offset + 32));
offset += 32;
BigInteger blobBaseFee = Numeric.toBigInt(Arrays.copyOfRange(input, offset, offset + 32));
offset += 32;
String l1BlockHash = Numeric.toHexString(Arrays.copyOfRange(input, offset, offset + 32));
offset += 32;
String batcherHash = Numeric.toHexString(Arrays.copyOfRange(input, offset, offset + 32));

return new AttributesDeposited(
l1BlockNum,
l1Timestamp,
baseFee,
l1BlockHash,
sequenceNum,
batcherHash,
BigInteger.ZERO,
BigInteger.ZERO,
BigInteger.ZERO,
blobBaseFee,
baseFeeScalar,
blobBaseFeeScalar,
false);
}

/**
* Encode bytes.
*
Expand Down Expand Up @@ -421,6 +511,7 @@ public record DepositedTransaction(
* From deposited transaction.
*
* @param config the chain config
* @param l2BlockTime the l2 block time
* @param attributesDeposited the attributes deposited
* @return the deposited transaction
*/
Expand Down
42 changes: 20 additions & 22 deletions hildr-node/src/main/java/io/optimism/l1/InnerWatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -184,34 +184,32 @@ public InnerWatcher(

private void getMetadataFromL2(BigInteger l2StartBlock) {
Web3j l2Client = Web3jProvider.createClient(config.l2RpcUrl());
EthBlock.Block block;
EthBlock.Block l2Block;
try {
block = this.pollBlockByNumber(l2Client, l2StartBlock.subtract(BigInteger.ONE));
l2Block = this.pollBlockByNumber(l2Client, l2StartBlock.subtract(BigInteger.ONE));
if (l2Block.getTransactions() == null || l2Block.getTransactions().isEmpty()) {
throw new L1AttributesDepositedTxNotFoundException();
}

EthBlock.TransactionObject tx = (EthBlock.TransactionObject)
l2Block.getTransactions().getFirst().get();
final byte[] input = Numeric.hexStringToByteArray(tx.getInput());
var gasLimit = l2Block.getGasLimit();
if (this.config.chainConfig().isEcotoneAndNotFirst(l2Block.getTimestamp())) {
this.systemConfig = Config.SystemConfig.fromEcotoneTxInput(
config.chainConfig().systemConfig().unsafeBlockSigner(), gasLimit, input);
} else {
this.systemConfig = Config.SystemConfig.fromBedrockTxInput(
config.chainConfig().systemConfig().unsafeBlockSigner(), gasLimit, input);
}
} catch (InterruptedException | ExecutionException e) {
if (e instanceof InterruptedException) {
Thread.currentThread().interrupt();
}
l2Client.shutdown();
throw new HildrServiceExecutionException(e);
} finally {
l2Client.shutdown();
}
if (block.getTransactions().isEmpty()) {
throw new L1AttributesDepositedTxNotFoundException();
}
EthBlock.TransactionObject tx =
(EthBlock.TransactionObject) block.getTransactions().getFirst().get();
final byte[] input = Numeric.hexStringToByteArray(tx.getInput());

final String batchSender = Numeric.toHexString(Arrays.copyOfRange(input, 176, 196));
var l1FeeOverhead = Numeric.toBigInt(Arrays.copyOfRange(input, 196, 228));
var l1FeeScalar = Numeric.toBigInt(Arrays.copyOfRange(input, 228, 260));
var gasLimit = block.getGasLimit();
this.systemConfig = new Config.SystemConfig(
batchSender,
gasLimit,
l1FeeOverhead,
l1FeeScalar,
config.chainConfig().systemConfig().unsafeBlockSigner());
l2Client.shutdown();
}

private Disposable subscribeL1NewHeads() {
Expand Down Expand Up @@ -564,7 +562,7 @@ protected void startUp() throws Exception {
} else {
this.getMetadataFromL2(this.l2StartBlock);
}
// this.subscribeL1NewHeads();
this.subscribeL1NewHeads();
}

@Override
Expand Down
48 changes: 48 additions & 0 deletions hildr-node/src/test/java/io/optimism/config/SystemConfigTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package io.optimism.config;

import io.optimism.derive.stages.Attributes;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.web3j.abi.datatypes.generated.Bytes32;
import org.web3j.tuples.generated.Tuple2;
import org.web3j.utils.Numeric;

import java.math.BigInteger;

import static org.junit.Assert.assertEquals;

/**
* The type of SystemConfigTest.
*
* @author thinkAfCod
* @since 0.2.7
*/
public class SystemConfigTest {

@Test
@DisplayName("decode Bedrock tx input successfully")
void decodeBedrockTxInput() {
String txInput =
"015d8eb900000000000000000000000000000000000000000000000000000000005169650000000000000000000000000000000000000000000000000000000065d62bbc0000000000000000000000000000000000000000000000000000000234deaa21e680e3ec5290b08570531865205fe15ddc5dbac1f55b4156e2444e77f36d97f400000000000000000000000000000000000000000000000000000000000000040000000000000000000000008f23bb38f531600e5d8fddaaec41f13fab46e98c00000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000a6fe0";
Config.SystemConfig systemConfig =
Config.SystemConfig.fromBedrockTxInput("", null, Numeric.hexStringToByteArray(txInput));
Attributes.AttributesDeposited decode = Attributes.AttributesDeposited.decode(txInput);
assertEquals(new BigInteger("188"), systemConfig.l1FeeOverhead());
assertEquals(new BigInteger("684000"), systemConfig.l1FeeScalar());
assertEquals("0x8f23bb38f531600e5d8fddaaec41f13fab46e98c", systemConfig.batchSender());
}

@Test
@DisplayName("decode Ecotone tx input successfully")
void decodeEcotoneTxInput() {
String txInput =
"0x440a5e20000a6fe00000000000000000000000050000000065d62bbc00000000005169650000000000000000000000000000000000000000000000000000000234deaa2100000000000000000000000000000000000000000000000000000005dcb37612e680e3ec5290b08570531865205fe15ddc5dbac1f55b4156e2444e77f36d97f40000000000000000000000008f23bb38f531600e5d8fddaaec41f13fab46e98c";
Config.SystemConfig systemConfig =
Config.SystemConfig.fromEcotoneTxInput("", null, Numeric.hexStringToByteArray(txInput));
Tuple2<BigInteger, BigInteger> blobAndBaseScalar = systemConfig.ecotoneScalars();
assertEquals(BigInteger.ZERO, systemConfig.l1FeeOverhead());
assertEquals(new BigInteger("684000"), blobAndBaseScalar.component1());
assertEquals(new BigInteger("0"), blobAndBaseScalar.component2());
assertEquals("0x8f23bb38f531600e5d8fddaaec41f13fab46e98c", systemConfig.batchSender());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

import java.math.BigInteger;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.web3j.utils.Numeric;

import static org.junit.jupiter.api.Assertions.assertEquals;

/**
* The type AttributesDepositedTest.
*
Expand All @@ -13,8 +16,12 @@
*/
public class AttributesDepositedTest {

private static final String TX_INPUT =
"0x440a5e20000a6fe00000000000000000000000050000000065d62bbc00000000005169650000000000000000000000000000000000000000000000000000000234deaa2100000000000000000000000000000000000000000000000000000005dcb37612e680e3ec5290b08570531865205fe15ddc5dbac1f55b4156e2444e77f36d97f40000000000000000000000008f23bb38f531600e5d8fddaaec41f13fab46e98c";

@Test
void testEncode() {
@DisplayName("Test encode ecotone tx input successfully")
void testEcotoneEncode() {
Attributes.AttributesDeposited deposited = new Attributes.AttributesDeposited(
BigInteger.valueOf(5335397L),
BigInteger.valueOf(1708534716L),
Expand All @@ -31,7 +38,22 @@ void testEncode() {
false);
byte[] bytes = deposited.encodeInEcotone();
Assertions.assertEquals(
"0x440a5e20000a6fe00000000000000000000000050000000065d62bbc00000000005169650000000000000000000000000000000000000000000000000000000234deaa2100000000000000000000000000000000000000000000000000000005dcb37612e680e3ec5290b08570531865205fe15ddc5dbac1f55b4156e2444e77f36d97f40000000000000000000000008f23bb38f531600e5d8fddaaec41f13fab46e98c",
TX_INPUT,
Numeric.toHexString(bytes));
}

@Test
@DisplayName("Test decode ecotone tx input successfully")
void testEcotoneDecode() {
Attributes.AttributesDeposited decode = Attributes.AttributesDeposited.decodeForEcotone(TX_INPUT);
assertEquals(BigInteger.valueOf(5335397L), decode.number());
assertEquals(BigInteger.valueOf(1708534716L), decode.timestamp());
assertEquals("0xe680e3ec5290b08570531865205fe15ddc5dbac1f55b4156e2444e77f36d97f4", decode.hash());
assertEquals(BigInteger.valueOf(5L), decode.sequenceNumber());
assertEquals("0x0000000000000000000000008f23bb38f531600e5d8fddaaec41f13fab46e98c", decode.batcherHash());
assertEquals(new BigInteger("25177585170"), decode.blobBaseFee());
assertEquals(new BigInteger("9476942369"), decode.baseFee());
assertEquals(BigInteger.ZERO, decode.blobBaseFeeScalar());
assertEquals(BigInteger.valueOf(684000L), decode.baseFeeScalar());
}
}

0 comments on commit 1389b93

Please sign in to comment.