laconicd/x/evm/types/tx_data.go
Federico Kunze Küllmer d84837a438
evm: fix Chain ID derivation (#579)
* evm: fix Chain ID derivation

* update

* changelog
2021-09-21 11:31:19 +00:00

110 lines
2.3 KiB
Go

package types
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
)
var (
_ TxData = &LegacyTx{}
_ TxData = &AccessListTx{}
_ TxData = &DynamicFeeTx{}
)
// TxData implements the Ethereum transaction tx structure. It is used
// solely as intended in Ethereum abiding by the protocol.
type TxData interface {
// TODO: embed ethtypes.TxData. See https://github.com/ethereum/go-ethereum/issues/23154
TxType() byte
Copy() TxData
GetChainID() *big.Int
GetAccessList() ethtypes.AccessList
GetData() []byte
GetNonce() uint64
GetGas() uint64
GetGasPrice() *big.Int
GetGasTipCap() *big.Int
GetGasFeeCap() *big.Int
GetValue() *big.Int
GetTo() *common.Address
GetRawSignatureValues() (v, r, s *big.Int)
SetSignatureValues(chainID, v, r, s *big.Int)
AsEthereumData() ethtypes.TxData
Validate() error
Fee() *big.Int
Cost() *big.Int
}
func NewTxDataFromTx(tx *ethtypes.Transaction) TxData {
var txData TxData
switch tx.Type() {
// case ethtypes.DynamicFeeTxType:
// txData = newDynamicFeeTx(tx)
case ethtypes.AccessListTxType:
txData = newAccessListTx(tx)
default:
txData = newLegacyTx(tx)
}
return txData
}
// DeriveChainID derives the chain id from the given v parameter.
//
// CONTRACT: v value is either:
//
// - {0,1} + CHAIN_ID * 2 + 35, if EIP155 is used
// - {0,1} + 27, otherwise
// Ref: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md
func DeriveChainID(v *big.Int) *big.Int {
if v == nil || v.Sign() < 1 {
return nil
}
if v.BitLen() <= 64 {
v := v.Uint64()
if v == 27 || v == 28 {
return new(big.Int)
}
if v < 35 {
return nil
}
// V MUST be of the form {0,1} + CHAIN_ID * 2 + 35
return new(big.Int).SetUint64((v - 35) / 2)
}
v = new(big.Int).Sub(v, big.NewInt(35))
return v.Div(v, big.NewInt(2))
}
func rawSignatureValues(vBz, rBz, sBz []byte) (v, r, s *big.Int) {
if len(vBz) > 0 {
v = new(big.Int).SetBytes(vBz)
}
if len(rBz) > 0 {
r = new(big.Int).SetBytes(rBz)
}
if len(sBz) > 0 {
s = new(big.Int).SetBytes(sBz)
}
return v, r, s
}
func fee(gasPrice *big.Int, gas uint64) *big.Int {
gasLimit := new(big.Int).SetUint64(gas)
return new(big.Int).Mul(gasPrice, gasLimit)
}
func cost(fee, value *big.Int) *big.Int {
if value != nil {
return new(big.Int).Add(fee, value)
}
return fee
}