-
Notifications
You must be signed in to change notification settings - Fork 1
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 all commits
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,121 @@ | ||
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 | ||
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. | ||
MaxFeeInFeeCurrency: new(big.Int), | ||
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.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 | ||
Comment on lines
113
to
+114
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. 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 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. I generally don't like the concept of the TxData interface exposing the union of all struct fields. So do you suggest implementing this in this PR? 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. No, let's keep it as it is. If we want to change it, we should do so in a separate PR. |
||
} | ||
|
||
// 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,16 @@ func (tx *Transaction) FeeCurrency() *common.Address { | |
return copyAddressPtr(tx.inner.feeCurrency()) | ||
} | ||
|
||
// MaxFeeInFeeCurrency is only used to guard against very quickly changing exchange rates. | ||
// Txs must be discarded if MaxFeeInFeeCurrency is exceeded. | ||
func (tx *Transaction) MaxFeeInFeeCurrency() *big.Int { | ||
mfifc := tx.inner.maxFeeInFeeCurrency() | ||
if mfifc == nil { | ||
return nil | ||
} | ||
return new(big.Int).Set(mfifc) | ||
} | ||
|
||
// 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.
Is this change safe for the case where
tx.Type() == types.CeloDynamicFeeTxType
butmsg.FeeCurrency == nil
? Unfortunately, we didn't forbidnil
currencies for CIP-64.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.
Yes, the
ConvertGoldToCurrency
function just returns the passed in value in that case (herebaseFee
, which has the same effect as omitting the if case).