Skip to content

Add ArbitrumRetryTx type #12

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

Closed
wants to merge 14 commits into from
Closed
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
4 changes: 2 additions & 2 deletions core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import (
var emptyCodeHash = crypto.Keccak256Hash(nil)

type TxProcessingHook interface {
InterceptMessage() (*ExecutionResult, error)
StartTxHook() (*ExecutionResult, error)
ExtraGasChargingHook(gasRemaining *uint64, gasPool *GasPool) error
EndTxHook(totalGasUsed uint64, gasPool *GasPool, success bool) error
}
Expand Down Expand Up @@ -366,7 +366,7 @@ func (st *StateTransition) transitionDbImpl() (*ExecutionResult, error) {

func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
if st.processingHook != nil {
res, err := st.processingHook.InterceptMessage()
res, err := st.processingHook.StartTxHook()
if res != nil || err != nil {
return res, err
}
Expand Down
107 changes: 106 additions & 1 deletion core/types/arb_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,111 @@ func (tx *ArbitrumContractTx) rawSignatureValues() (v, r, s *big.Int) {
func (tx *ArbitrumContractTx) setSignatureValues(chainID, v, r, s *big.Int) {}
func (tx *ArbitrumContractTx) isFake() bool { return true }

type ArbitrumRetryTx struct {
ArbitrumContractTx
TicketId common.Hash
RefundTo common.Address
}

func (tx *ArbitrumRetryTx) txType() byte { return ArbitrumRetryTxType }

func (tx *ArbitrumRetryTx) copy() TxData {
return &ArbitrumRetryTx{
*tx.ArbitrumContractTx.copy().(*ArbitrumContractTx),
tx.TicketId,
tx.RefundTo,
}
}

func (tx *ArbitrumRetryTx) chainID() *big.Int { return tx.ArbitrumContractTx.chainID() }
func (tx *ArbitrumRetryTx) accessList() AccessList { return tx.ArbitrumContractTx.accessList() }
func (tx *ArbitrumRetryTx) data() []byte { return tx.ArbitrumContractTx.data() }
func (tx *ArbitrumRetryTx) gas() uint64 { return tx.ArbitrumContractTx.gas() }
func (tx *ArbitrumRetryTx) gasPrice() *big.Int { return tx.ArbitrumContractTx.gasPrice() }
func (tx *ArbitrumRetryTx) gasTipCap() *big.Int { return tx.ArbitrumContractTx.gasTipCap() }
func (tx *ArbitrumRetryTx) gasFeeCap() *big.Int { return tx.ArbitrumContractTx.gasFeeCap() }
func (tx *ArbitrumRetryTx) value() *big.Int { return tx.ArbitrumContractTx.value() }
func (tx *ArbitrumRetryTx) nonce() uint64 { return tx.ArbitrumContractTx.nonce() }
func (tx *ArbitrumRetryTx) to() *common.Address { return tx.ArbitrumContractTx.to() }
func (tx *ArbitrumRetryTx) rawSignatureValues() (v, r, s *big.Int) {
return tx.ArbitrumContractTx.rawSignatureValues()
}
func (tx *ArbitrumRetryTx) setSignatureValues(chainID, v, r, s *big.Int) {
tx.ArbitrumContractTx.setSignatureValues(chainID, v, r, s)
}
func (tx *ArbitrumRetryTx) isFake() bool { return true }

type ArbitrumSubmitRetryableTx struct {
ChainId *big.Int
RequestId common.Hash
From common.Address

DepositValue *big.Int
GasPrice *big.Int // wei per gas
Gas uint64 // gas limit
To *common.Address `rlp:"nil"` // nil means contract creation
Value *big.Int // wei amount
Beneficiary common.Address
SubmissionFeePaid *big.Int
FeeRefundAddr common.Address
Data []byte // contract invocation input data
}

func (tx *ArbitrumSubmitRetryableTx) txType() byte { return ArbitrumSubmitRetryableTxType }

func (tx *ArbitrumSubmitRetryableTx) copy() TxData {
cpy := &ArbitrumSubmitRetryableTx{
ChainId: new(big.Int),
RequestId: tx.RequestId,
DepositValue: tx.DepositValue,
GasPrice: tx.GasPrice,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe all the big ints here should be new(big.Int) like ChainId. As-is, I don't think it does a deep copy.

Gas: tx.Gas,
From: tx.From,
To: tx.To,
Value: tx.Value,
Beneficiary: tx.Beneficiary,
SubmissionFeePaid: tx.SubmissionFeePaid,
FeeRefundAddr: tx.FeeRefundAddr,
Data: common.CopyBytes(tx.Data),
}
if tx.ChainId != nil {
cpy.ChainId.Set(tx.ChainId)
}
if tx.DepositValue != nil {
cpy.DepositValue.Set(tx.DepositValue)
}
if tx.GasPrice != nil {
cpy.GasPrice.Set(tx.GasPrice)
}
if tx.To != nil {
tmp := *tx.To
cpy.To = &tmp
}
if tx.Value != nil {
cpy.Value.Set(tx.Value)
}
if tx.SubmissionFeePaid != nil {
cpy.SubmissionFeePaid.Set(tx.SubmissionFeePaid)
}
return cpy
}

func (tx *ArbitrumSubmitRetryableTx) chainID() *big.Int { return tx.ChainId }
func (tx *ArbitrumSubmitRetryableTx) accessList() AccessList { return nil }
func (tx *ArbitrumSubmitRetryableTx) data() []byte { return tx.Data }
func (tx *ArbitrumSubmitRetryableTx) gas() uint64 { return tx.Gas }
func (tx *ArbitrumSubmitRetryableTx) gasPrice() *big.Int { return tx.GasPrice }
func (tx *ArbitrumSubmitRetryableTx) gasTipCap() *big.Int { return tx.GasPrice }
func (tx *ArbitrumSubmitRetryableTx) gasFeeCap() *big.Int { return tx.GasPrice }
func (tx *ArbitrumSubmitRetryableTx) value() *big.Int { return tx.Value }
func (tx *ArbitrumSubmitRetryableTx) nonce() uint64 { return 0 }
func (tx *ArbitrumSubmitRetryableTx) to() *common.Address { return tx.To }
func (tx *ArbitrumSubmitRetryableTx) rawSignatureValues() (v, r, s *big.Int) {
return bigZero, bigZero, bigZero
}
func (tx *ArbitrumSubmitRetryableTx) setSignatureValues(chainID, v, r, s *big.Int) {}
func (tx *ArbitrumSubmitRetryableTx) isFake() bool { return true }

type ArbitrumDepositTx struct {
ChainId *big.Int
L1RequestId common.Hash
Expand Down Expand Up @@ -159,7 +264,7 @@ func (d *ArbitrumDepositTx) copy() TxData {
func (d *ArbitrumDepositTx) chainID() *big.Int { return d.ChainId }
func (d *ArbitrumDepositTx) accessList() AccessList { return nil }
func (d *ArbitrumDepositTx) data() []byte { return nil }
func (d ArbitrumDepositTx) gas() uint64 { return 0 }
func (d *ArbitrumDepositTx) gas() uint64 { return 0 }
func (d *ArbitrumDepositTx) gasPrice() *big.Int { return bigZero }
func (d *ArbitrumDepositTx) gasTipCap() *big.Int { return bigZero }
func (d *ArbitrumDepositTx) gasFeeCap() *big.Int { return bigZero }
Expand Down
8 changes: 8 additions & 0 deletions core/types/arbitrum_signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ func (s arbitrumSigner) Sender(tx *Transaction) (common.Address, error) {
return inner.From, nil
case *ArbitrumDepositTx:
return arbAddress, nil
case *ArbitrumRetryTx:
return inner.From, nil
case *ArbitrumSubmitRetryableTx:
return inner.From, nil
default:
return s.Signer.Sender(tx)
}
Expand All @@ -40,6 +44,10 @@ func (s arbitrumSigner) SignatureValues(tx *Transaction, sig []byte) (R, S, V *b
return bigZero, bigZero, bigZero, nil
case *ArbitrumDepositTx:
return bigZero, bigZero, bigZero, nil
case *ArbitrumRetryTx:
return bigZero, bigZero, bigZero, nil
case *ArbitrumSubmitRetryableTx:
return bigZero, bigZero, bigZero, nil
default:
return s.Signer.SignatureValues(tx, sig)
}
Expand Down
24 changes: 19 additions & 5 deletions core/types/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,12 @@ const (
LegacyTxType = iota
AccessListTxType
DynamicFeeTxType
ArbitrumDepositTxType = 200
ArbitrumUnsignedTxType = 201
ArbitrumContractTxType = 202
ArbitrumWrappedTxType = 203
ArbitrumDepositTxType = 100
ArbitrumUnsignedTxType = 101
ArbitrumContractTxType = 102
ArbitrumWrappedTxType = 103
ArbitrumRetryTxType = 104
ArbitrumSubmitRetryableTxType = 105
)

// Transaction is an Ethereum transaction.
Expand Down Expand Up @@ -170,7 +172,7 @@ func (tx *Transaction) UnmarshalBinary(b []byte) error {
return nil
}
// It's an EIP2718 typed transaction envelope.
inner, err := tx.decodeTyped(b, false)
inner, err := tx.decodeTyped(b, true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we want arb parsing here, as this function is called for external input, e.g. sendRawTransaction. We only want to accept normal transaction types there.

if err != nil {
return err
}
Expand Down Expand Up @@ -201,6 +203,14 @@ func (tx *Transaction) decodeTyped(b []byte, arbParsing bool) (TxData, error) {
var inner ArbitrumWrappedTx
err := rlp.DecodeBytes(b[1:], &inner)
return &inner, err
case ArbitrumRetryTxType:
var inner ArbitrumRetryTx
err := rlp.DecodeBytes(b[1:], &inner)
return &inner, err
case ArbitrumSubmitRetryableTxType:
var inner ArbitrumSubmitRetryableTx
err := rlp.DecodeBytes(b[1:], &inner)
return &inner, err
}
}
switch b[0] {
Expand Down Expand Up @@ -412,6 +422,10 @@ func (tx *Transaction) Hash() common.Hash {
var h common.Hash
if tx.Type() == LegacyTxType {
h = rlpHash(tx.inner)
} else if tx.Type() == ArbitrumSubmitRetryableTxType {
h = tx.inner.(*ArbitrumSubmitRetryableTx).RequestId
} else if tx.Type() == ArbitrumRetryTxType {
h = tx.inner.(*ArbitrumRetryTx).RequestId
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These seem a bit dangerous to override if we could avoid it, but I'm guessing using the request id as the hash really simplifies things?

} else {
h = prefixedRlpHash(tx.Type(), tx.inner)
}
Expand Down
12 changes: 12 additions & 0 deletions core/types/transaction_signing.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,18 @@ func (s eip2930Signer) Sender(tx *Transaction) (common.Address, error) {
// AL txs are defined to use 0 and 1 as their recovery
// id, add 27 to become equivalent to unprotected Homestead signatures.
V = new(big.Int).Add(V, big.NewInt(27))
case ArbitrumDepositTxType:
return tx.inner.(*ArbitrumDepositTx).To, nil
case ArbitrumUnsignedTxType:
return tx.inner.(*ArbitrumUnsignedTx).From, nil
case ArbitrumContractTxType:
return tx.inner.(*ArbitrumContractTx).From, nil
case ArbitrumWrappedTxType:
return s.Sender(NewTx(tx.inner.(*ArbitrumWrappedTx).TxData))
case ArbitrumRetryTxType:
return tx.inner.(*ArbitrumRetryTx).From, nil
case ArbitrumSubmitRetryableTxType:
return tx.inner.(*ArbitrumSubmitRetryableTx).From, nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe these cases should happen in the ArbitrumSigner, which we always instantiate on Arbitrum chains

default:
return common.Address{}, ErrTxTypeNotSupported
}
Expand Down