Skip to content
Open
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
46 changes: 46 additions & 0 deletions op-node/rollup/derive/span_batch_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,19 @@ type spanBatchSetCodeTxData struct {

func (txData *spanBatchSetCodeTxData) txType() byte { return types.SetCodeTxType }

type spanBatchCeloDynamicFeeTxV2Data struct {
Value *big.Int
GasTipCap *big.Int // a.k.a. maxPriorityFeePerGas
GasFeeCap *big.Int // a.k.a. maxFeePerGas
Data []byte
AccessList types.AccessList
FeeCurrency *common.Address `rlp:"nil"`
}

func (txData *spanBatchCeloDynamicFeeTxV2Data) txType() byte {
return types.CeloDynamicFeeTxV2Type
}

// Type returns the transaction type.
func (tx *spanBatchTx) Type() uint8 {
return tx.inner.txType()
Expand Down Expand Up @@ -112,6 +125,13 @@ func (tx *spanBatchTx) decodeTyped(b []byte) (spanBatchTxData, error) {
return nil, fmt.Errorf("failed to decode spanBatchSetCodeTxData: %w", err)
}
return &inner, nil
case types.CeloDynamicFeeTxV2Type:
var inner spanBatchCeloDynamicFeeTxV2Data
err := rlp.DecodeBytes(b[1:], &inner)
if err != nil {
return nil, fmt.Errorf("failed to decode spanBatchCeloDynamicFeeTxV2Data: %w", err)
}
return &inner, nil
default:
return nil, types.ErrTxTypeNotSupported
}
Expand Down Expand Up @@ -208,6 +228,23 @@ func (tx *spanBatchTx) convertToFullTx(nonce, gas uint64, to *common.Address, ch
R: uint256.MustFromBig(R),
S: uint256.MustFromBig(S),
}
case types.CeloDynamicFeeTxV2Type:
batchTxInner := tx.inner.(*spanBatchCeloDynamicFeeTxV2Data)
inner = &types.CeloDynamicFeeTxV2{
ChainID: chainID,
Nonce: nonce,
GasTipCap: batchTxInner.GasTipCap,
GasFeeCap: batchTxInner.GasFeeCap,
Gas: gas,
To: to,
Value: batchTxInner.Value,
Data: batchTxInner.Data,
AccessList: batchTxInner.AccessList,
FeeCurrency: batchTxInner.FeeCurrency,
V: V,
R: R,
S: S,
}
default:
return nil, fmt.Errorf("invalid tx type: %d", tx.Type())
}
Expand Down Expand Up @@ -248,6 +285,15 @@ func newSpanBatchTx(tx *types.Transaction) (*spanBatchTx, error) {
AccessList: tx.AccessList(),
AuthorizationList: tx.SetCodeAuthorizations(),
}
case types.CeloDynamicFeeTxV2Type:
inner = &spanBatchCeloDynamicFeeTxV2Data{
GasTipCap: tx.GasTipCap(),
GasFeeCap: tx.GasFeeCap(),
Value: tx.Value(),
Data: tx.Data(),
AccessList: tx.AccessList(),
FeeCurrency: tx.FeeCurrency(),
}
default:
return nil, fmt.Errorf("invalid tx type: %d", tx.Type())
}
Expand Down
21 changes: 13 additions & 8 deletions op-node/rollup/derive/span_batch_tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,30 @@ type spanBatchTxTest struct {
protected bool
}

// spanBatchTestSigner returns a signer that supports all tx types including
// Celo CIP-64. LatestSignerForChainID wraps with the Celo signer overlay.
func spanBatchTestSigner(chainID *big.Int, protected bool) types.Signer {
if !protected {
return types.HomesteadSigner{}
}
return types.LatestSignerForChainID(chainID)
}

func TestSpanBatchTxConvert(t *testing.T) {
cases := []spanBatchTxTest{
{"unprotected legacy tx", 32, testutils.RandomLegacyTx, false},
{"legacy tx", 32, testutils.RandomLegacyTx, true},
{"access list tx", 32, testutils.RandomAccessListTx, true},
{"dynamic fee tx", 32, testutils.RandomDynamicFeeTx, true},
{"setcode tx", 32, testutils.RandomSetCodeTx, true},
{"celo dynamic fee tx v2", 32, testutils.RandomCeloDynamicFeeTxV2, true},
}

for i, testCase := range cases {
t.Run(testCase.name, func(t *testing.T) {
rng := rand.New(rand.NewSource(int64(0x1331 + i)))
chainID := big.NewInt(rng.Int63n(1000))
signer := types.NewIsthmusSigner(chainID)
if !testCase.protected {
signer = types.HomesteadSigner{}
}
signer := spanBatchTestSigner(chainID, testCase.protected)

for txIdx := 0; txIdx < testCase.trials; txIdx++ {
tx := testCase.mkTx(rng, signer)
Expand Down Expand Up @@ -65,16 +72,14 @@ func TestSpanBatchTxRoundTrip(t *testing.T) {
{"access list tx", 32, testutils.RandomAccessListTx, true},
{"dynamic fee tx", 32, testutils.RandomDynamicFeeTx, true},
{"setcode tx", 32, testutils.RandomSetCodeTx, true},
{"celo dynamic fee tx v2", 32, testutils.RandomCeloDynamicFeeTxV2, true},
}

for i, testCase := range cases {
t.Run(testCase.name, func(t *testing.T) {
rng := rand.New(rand.NewSource(int64(0x1332 + i)))
chainID := big.NewInt(rng.Int63n(1000))
signer := types.NewIsthmusSigner(chainID)
if !testCase.protected {
signer = types.HomesteadSigner{}
}
signer := spanBatchTestSigner(chainID, testCase.protected)

for txIdx := 0; txIdx < testCase.trials; txIdx++ {
tx := testCase.mkTx(rng, signer)
Expand Down
4 changes: 4 additions & 0 deletions op-node/rollup/derive/span_batch_txs.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,8 @@ func (btx *spanBatchTxs) recoverV(chainID *big.Int) error {
v = bit
case types.SetCodeTxType:
v = bit
case types.CeloDynamicFeeTxV2Type:
v = bit
default:
return fmt.Errorf("invalid tx type: %d", txType)
}
Expand Down Expand Up @@ -390,6 +392,8 @@ func convertVToYParity(v uint64, txType int) (uint, error) {
yParityBit = uint(v)
case types.SetCodeTxType:
yParityBit = uint(v)
case types.CeloDynamicFeeTxV2Type:
yParityBit = uint(v)
default:
return 0, fmt.Errorf("invalid tx type: %d", txType)
}
Expand Down
6 changes: 6 additions & 0 deletions op-node/rollup/derive/span_batch_txs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ func TestSpanBatchTxsRecoverV(t *testing.T) {

chainID := big.NewInt(rng.Int63n(1000))
isthmusSigner := types.NewIsthmusSigner(chainID)
celoSigner := types.LatestSignerForChainID(chainID)
totalblockTxCount := 20 + rng.Intn(100)

cases := []txTypeTest{
Expand All @@ -342,6 +343,7 @@ func TestSpanBatchTxsRecoverV(t *testing.T) {
{"access list tx", testutils.RandomAccessListTx, isthmusSigner},
{"dynamic fee tx", testutils.RandomDynamicFeeTx, isthmusSigner},
{"setcode tx", testutils.RandomSetCodeTx, isthmusSigner},
{"celo dynamic fee tx v2", testutils.RandomCeloDynamicFeeTxV2, celoSigner},
}

for _, testCase := range cases {
Expand Down Expand Up @@ -426,13 +428,15 @@ func TestSpanBatchTxsRoundTripFullTxs(t *testing.T) {
rng := rand.New(rand.NewSource(0x13377331))
chainID := big.NewInt(rng.Int63n(1000))
isthmusSigner := types.NewIsthmusSigner(chainID)
celoSigner := types.LatestSignerForChainID(chainID)

cases := []txTypeTest{
{"unprotected legacy tx", testutils.RandomLegacyTx, types.HomesteadSigner{}},
{"legacy tx", testutils.RandomLegacyTx, isthmusSigner},
{"access list tx", testutils.RandomAccessListTx, isthmusSigner},
{"dynamic fee tx", testutils.RandomDynamicFeeTx, isthmusSigner},
{"setcode tx", testutils.RandomSetCodeTx, isthmusSigner},
{"celo dynamic fee tx v2", testutils.RandomCeloDynamicFeeTxV2, celoSigner},
}

for _, testCase := range cases {
Expand Down Expand Up @@ -477,13 +481,15 @@ func TestSpanBatchTxsFullTxNotEnoughTxTos(t *testing.T) {
rng := rand.New(rand.NewSource(0x13572468))
chainID := big.NewInt(rng.Int63n(1000))
isthmusSigner := types.NewIsthmusSigner(chainID)
celoSigner := types.LatestSignerForChainID(chainID)

cases := []txTypeTest{
{"unprotected legacy tx", testutils.RandomLegacyTx, types.HomesteadSigner{}},
{"legacy tx", testutils.RandomLegacyTx, isthmusSigner},
{"access list tx", testutils.RandomAccessListTx, isthmusSigner},
{"dynamic fee tx", testutils.RandomDynamicFeeTx, isthmusSigner},
{"setcode tx", testutils.RandomSetCodeTx, isthmusSigner},
{"celo dynamic fee tx v2", testutils.RandomCeloDynamicFeeTxV2, celoSigner},
}

for _, testCase := range cases {
Expand Down
24 changes: 24 additions & 0 deletions op-service/testutils/random.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,30 @@ func RandomSetCodeTx(rng *rand.Rand, signer types.Signer) *types.Transaction {
return tx
}

func RandomCeloDynamicFeeTxV2(rng *rand.Rand, signer types.Signer) *types.Transaction {
baseFee := new(big.Int).SetUint64(rng.Uint64())
key := InsecureRandomKey(rng)
tip := big.NewInt(rng.Int63n(10 * params.GWei))
feeCurrency := RandomAddress(rng)
txData := &types.CeloDynamicFeeTxV2{
ChainID: signer.ChainID(),
Nonce: rng.Uint64(),
GasTipCap: tip,
GasFeeCap: new(big.Int).Add(baseFee, tip),
Gas: params.TxGas + uint64(rng.Int63n(2_000_000)),
To: RandomTo(rng),
Value: RandomETH(rng, 10),
Data: RandomData(rng, rng.Intn(RandomDataSize)),
AccessList: nil,
FeeCurrency: &feeCurrency,
}
tx, err := types.SignNewTx(key, signer, txData)
if err != nil {
panic(err)
}
return tx
}

func RandomReceipt(rng *rand.Rand, signer types.Signer, tx *types.Transaction, txIndex uint64, cumulativeGasUsed uint64) *types.Receipt {
gasUsed := params.TxGas + uint64(rng.Int63n(int64(tx.Gas()-params.TxGas+1)))
logs := make([]*types.Log, rng.Intn(10))
Expand Down
Loading