-
Notifications
You must be signed in to change notification settings - Fork 3
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
CIP-64 / CIP-66 compatible TransactionArgs
#123
Changes from 1 commit
d434cce
577d152
526563d
8e46539
9f238e6
9d0aa80
815cb7c
7a87ae6
3689a77
27a328d
dbb2c57
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
package types | ||
|
||
import ( | ||
"bytes" | ||
"math/big" | ||
|
||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/rlp" | ||
) | ||
|
||
type CeloDenominatedTx struct { | ||
ChainID *big.Int | ||
Nonce uint64 | ||
GasTipCap *big.Int | ||
GasFeeCap *big.Int | ||
Gas uint64 | ||
To *common.Address `rlp:"nil"` // nil means contract creation | ||
Value *big.Int | ||
Data []byte | ||
AccessList AccessList | ||
|
||
FeeCurrency *common.Address `rlp:"nil"` // nil means native currency | ||
MaxFeeInFeeCurrency *big.Int | ||
|
||
// Signature values | ||
V *big.Int `json:"v" gencodec:"required"` | ||
R *big.Int `json:"r" gencodec:"required"` | ||
S *big.Int `json:"s" gencodec:"required"` | ||
} | ||
|
||
// copy creates a deep copy of the transaction data and initializes all fields. | ||
func (tx *CeloDenominatedTx) copy() TxData { | ||
cpy := &CeloDenominatedTx{ | ||
Nonce: tx.Nonce, | ||
To: copyAddressPtr(tx.To), | ||
Data: common.CopyBytes(tx.Data), | ||
Gas: tx.Gas, | ||
FeeCurrency: copyAddressPtr(tx.FeeCurrency), | ||
// These are copied below. | ||
AccessList: make(AccessList, len(tx.AccessList)), | ||
Value: new(big.Int), | ||
ChainID: new(big.Int), | ||
GasTipCap: new(big.Int), | ||
GasFeeCap: new(big.Int), | ||
V: new(big.Int), | ||
R: new(big.Int), | ||
S: new(big.Int), | ||
} | ||
if tx.MaxFeeInFeeCurrency != nil { | ||
cpy.MaxFeeInFeeCurrency = new(big.Int).Set(tx.MaxFeeInFeeCurrency) | ||
} | ||
copy(cpy.AccessList, tx.AccessList) | ||
if tx.Value != nil { | ||
cpy.Value.Set(tx.Value) | ||
} | ||
if tx.ChainID != nil { | ||
cpy.ChainID.Set(tx.ChainID) | ||
} | ||
if tx.GasTipCap != nil { | ||
cpy.GasTipCap.Set(tx.GasTipCap) | ||
} | ||
if tx.GasFeeCap != nil { | ||
cpy.GasFeeCap.Set(tx.GasFeeCap) | ||
} | ||
if tx.V != nil { | ||
cpy.V.Set(tx.V) | ||
} | ||
if tx.R != nil { | ||
cpy.R.Set(tx.R) | ||
} | ||
if tx.S != nil { | ||
cpy.S.Set(tx.S) | ||
} | ||
return cpy | ||
} | ||
|
||
// accessors for innerTx. | ||
func (tx *CeloDenominatedTx) txType() byte { return CeloDenominatedTxType } | ||
func (tx *CeloDenominatedTx) chainID() *big.Int { return tx.ChainID } | ||
func (tx *CeloDenominatedTx) accessList() AccessList { return tx.AccessList } | ||
func (tx *CeloDenominatedTx) data() []byte { return tx.Data } | ||
func (tx *CeloDenominatedTx) gas() uint64 { return tx.Gas } | ||
func (tx *CeloDenominatedTx) gasFeeCap() *big.Int { return tx.GasFeeCap } | ||
func (tx *CeloDenominatedTx) gasTipCap() *big.Int { return tx.GasTipCap } | ||
func (tx *CeloDenominatedTx) gasPrice() *big.Int { return tx.GasFeeCap } | ||
func (tx *CeloDenominatedTx) value() *big.Int { return tx.Value } | ||
func (tx *CeloDenominatedTx) nonce() uint64 { return tx.Nonce } | ||
func (tx *CeloDenominatedTx) to() *common.Address { return tx.To } | ||
func (tx *CeloDenominatedTx) isSystemTx() bool { return false } | ||
|
||
func (tx *CeloDenominatedTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { | ||
if baseFee == nil { | ||
return dst.Set(tx.GasFeeCap) | ||
} | ||
tip := dst.Sub(tx.GasFeeCap, baseFee) | ||
if tip.Cmp(tx.GasTipCap) > 0 { | ||
tip.Set(tx.GasTipCap) | ||
} | ||
return tip.Add(tip, baseFee) | ||
} | ||
|
||
func (tx *CeloDenominatedTx) rawSignatureValues() (v, r, s *big.Int) { | ||
return tx.V, tx.R, tx.S | ||
} | ||
|
||
func (tx *CeloDenominatedTx) setSignatureValues(chainID, v, r, s *big.Int) { | ||
tx.ChainID, tx.V, tx.R, tx.S = chainID, v, r, s | ||
} | ||
|
||
func (tx *CeloDenominatedTx) encode(b *bytes.Buffer) error { | ||
return rlp.Encode(b, tx) | ||
} | ||
|
||
func (tx *CeloDenominatedTx) decode(input []byte) error { | ||
return rlp.DecodeBytes(input, tx) | ||
} | ||
|
||
func (tx *CeloDenominatedTx) feeCurrency() *common.Address { return tx.FeeCurrency } | ||
|
||
func (tx *CeloDenominatedTx) maxFeeInFeeCurrency() *big.Int { return tx.MaxFeeInFeeCurrency } |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -51,7 +51,8 @@ const ( | |
DynamicFeeTxType = 0x02 | ||
BlobTxType = 0x03 | ||
// CeloDynamicFeeTxType = 0x7c old Celo tx type with gateway fee | ||
CeloDynamicFeeTxType = 0x7b | ||
CeloDynamicFeeTxType = 0x7b | ||
CeloDenominatedTxType = 0x7a | ||
) | ||
|
||
// Transaction is an Ethereum transaction. | ||
|
@@ -110,6 +111,7 @@ type TxData interface { | |
|
||
// Celo specific fields | ||
feeCurrency() *common.Address | ||
maxFeeInFeeCurrency() *big.Int | ||
} | ||
|
||
// EncodeRLP implements rlp.Encoder | ||
|
@@ -216,6 +218,8 @@ func (tx *Transaction) decodeTyped(b []byte) (TxData, error) { | |
inner = new(DynamicFeeTx) | ||
case CeloDynamicFeeTxType: | ||
inner = new(CeloDynamicFeeTx) | ||
case CeloDenominatedTxType: | ||
inner = new(CeloDenominatedTx) | ||
case BlobTxType: | ||
inner = new(BlobTx) | ||
case DepositTxType: | ||
|
@@ -628,6 +632,11 @@ func (tx *Transaction) FeeCurrency() *common.Address { | |
return copyAddressPtr(tx.inner.feeCurrency()) | ||
} | ||
|
||
// MaxFeeInFeeCurrency returns the max fee in the fee_currency for celo denominated txs. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment feels too much like the variable name. We can add some more information here. Suggestion:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done in dbb2c57 |
||
func (tx *Transaction) MaxFeeInFeeCurrency() *big.Int { | ||
return new(big.Int).Set(tx.inner.maxFeeInFeeCurrency()) | ||
} | ||
|
||
// Transactions implements DerivableList for transactions. | ||
type Transactions []*Transaction | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC @piersy suggested that we can avoid extending TxData by checking the tx type and casting to a specific tx type whenever we want to use a tx-type-specific attribute. I think that can work, but for consistency it should either be done for
feeCurrency
too or not at all.I think going with the current approach is fine for now. I just wanted to bring up the point to see if there are any strong opionions or other thoughs about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I generally don't like the concept of the TxData interface exposing the union of all struct fields.
If I would contribute to upstream, I would vote to keep the changes of this PR as is for the purpose of consistency though.
When considering minimizing the diff and stronger segregation of Celo specific features for our fork I tend to lean towards the suggestion of @piersy.
So do you suggest implementing this in this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, let's keep it as it is. If we want to change it, we should do so in a separate PR.