mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-18 02:40:45 +00:00
parent
62272ed4e6
commit
c287f9eddd
4 changed files with 69 additions and 25 deletions
|
|
@ -38,6 +38,9 @@ var (
|
||||||
ErrTxTypeNotSupported = errors.New("transaction type not supported")
|
ErrTxTypeNotSupported = errors.New("transaction type not supported")
|
||||||
ErrGasFeeCapTooLow = errors.New("fee cap less than base fee")
|
ErrGasFeeCapTooLow = errors.New("fee cap less than base fee")
|
||||||
errShortTypedTx = errors.New("typed transaction too short")
|
errShortTypedTx = errors.New("typed transaction too short")
|
||||||
|
errInvalidYParity = errors.New("'yParity' field must be 0 or 1")
|
||||||
|
errVYParityMismatch = errors.New("'v' and 'yParity' fields do not match")
|
||||||
|
errVYParityMissing = errors.New("missing 'yParity' or 'v' field in transaction")
|
||||||
|
|
||||||
skipNonceDestinationAddress = map[common.Address]bool{
|
skipNonceDestinationAddress = map[common.Address]bool{
|
||||||
common.XDCXAddrBinary: true,
|
common.XDCXAddrBinary: true,
|
||||||
|
|
|
||||||
|
|
@ -42,11 +42,32 @@ type txJSON struct {
|
||||||
V *hexutil.Big `json:"v"`
|
V *hexutil.Big `json:"v"`
|
||||||
R *hexutil.Big `json:"r"`
|
R *hexutil.Big `json:"r"`
|
||||||
S *hexutil.Big `json:"s"`
|
S *hexutil.Big `json:"s"`
|
||||||
|
YParity *hexutil.Uint64 `json:"yParity,omitempty"`
|
||||||
|
|
||||||
// Only used for encoding:
|
// Only used for encoding:
|
||||||
Hash common.Hash `json:"hash"`
|
Hash common.Hash `json:"hash"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// yParityValue returns the YParity value from JSON. For backwards-compatibility reasons,
|
||||||
|
// this can be given in the 'v' field or the 'yParity' field. If both exist, they must match.
|
||||||
|
func (tx *txJSON) yParityValue() (*big.Int, error) {
|
||||||
|
if tx.YParity != nil {
|
||||||
|
val := uint64(*tx.YParity)
|
||||||
|
if val != 0 && val != 1 {
|
||||||
|
return nil, errInvalidYParity
|
||||||
|
}
|
||||||
|
bigval := new(big.Int).SetUint64(val)
|
||||||
|
if tx.V != nil && tx.V.ToInt().Cmp(bigval) != 0 {
|
||||||
|
return nil, errVYParityMismatch
|
||||||
|
}
|
||||||
|
return bigval, nil
|
||||||
|
}
|
||||||
|
if tx.V != nil {
|
||||||
|
return tx.V.ToInt(), nil
|
||||||
|
}
|
||||||
|
return nil, errVYParityMissing
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalJSON marshals as JSON with a hash.
|
// MarshalJSON marshals as JSON with a hash.
|
||||||
func (tx *Transaction) MarshalJSON() ([]byte, error) {
|
func (tx *Transaction) MarshalJSON() ([]byte, error) {
|
||||||
var enc txJSON
|
var enc txJSON
|
||||||
|
|
@ -82,6 +103,8 @@ func (tx *Transaction) MarshalJSON() ([]byte, error) {
|
||||||
enc.V = (*hexutil.Big)(itx.V)
|
enc.V = (*hexutil.Big)(itx.V)
|
||||||
enc.R = (*hexutil.Big)(itx.R)
|
enc.R = (*hexutil.Big)(itx.R)
|
||||||
enc.S = (*hexutil.Big)(itx.S)
|
enc.S = (*hexutil.Big)(itx.S)
|
||||||
|
yparity := itx.V.Uint64()
|
||||||
|
enc.YParity = (*hexutil.Uint64)(&yparity)
|
||||||
|
|
||||||
case *DynamicFeeTx:
|
case *DynamicFeeTx:
|
||||||
enc.ChainID = (*hexutil.Big)(itx.ChainID)
|
enc.ChainID = (*hexutil.Big)(itx.ChainID)
|
||||||
|
|
@ -96,6 +119,8 @@ func (tx *Transaction) MarshalJSON() ([]byte, error) {
|
||||||
enc.V = (*hexutil.Big)(itx.V)
|
enc.V = (*hexutil.Big)(itx.V)
|
||||||
enc.R = (*hexutil.Big)(itx.R)
|
enc.R = (*hexutil.Big)(itx.R)
|
||||||
enc.S = (*hexutil.Big)(itx.S)
|
enc.S = (*hexutil.Big)(itx.S)
|
||||||
|
yparity := itx.V.Uint64()
|
||||||
|
enc.YParity = (*hexutil.Uint64)(&yparity)
|
||||||
}
|
}
|
||||||
|
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
|
|
@ -104,7 +129,8 @@ func (tx *Transaction) MarshalJSON() ([]byte, error) {
|
||||||
// UnmarshalJSON unmarshals from JSON.
|
// UnmarshalJSON unmarshals from JSON.
|
||||||
func (tx *Transaction) UnmarshalJSON(input []byte) error {
|
func (tx *Transaction) UnmarshalJSON(input []byte) error {
|
||||||
var dec txJSON
|
var dec txJSON
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
err := json.Unmarshal(input, &dec)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,20 +164,22 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
|
||||||
}
|
}
|
||||||
itx.Data = *dec.Input
|
itx.Data = *dec.Input
|
||||||
|
|
||||||
if dec.V == nil {
|
// signature R
|
||||||
return errors.New("missing required field 'v' in transaction")
|
|
||||||
}
|
|
||||||
itx.V = (*big.Int)(dec.V)
|
|
||||||
if dec.R == nil {
|
if dec.R == nil {
|
||||||
return errors.New("missing required field 'r' in transaction")
|
return errors.New("missing required field 'r' in transaction")
|
||||||
}
|
}
|
||||||
itx.R = (*big.Int)(dec.R)
|
itx.R = (*big.Int)(dec.R)
|
||||||
|
// signature S
|
||||||
if dec.S == nil {
|
if dec.S == nil {
|
||||||
return errors.New("missing required field 's' in transaction")
|
return errors.New("missing required field 's' in transaction")
|
||||||
}
|
}
|
||||||
itx.S = (*big.Int)(dec.S)
|
itx.S = (*big.Int)(dec.S)
|
||||||
withSignature := itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0
|
// signature V
|
||||||
if withSignature {
|
if dec.V == nil {
|
||||||
|
return errors.New("missing required field 'v' in transaction")
|
||||||
|
}
|
||||||
|
itx.V = (*big.Int)(dec.V)
|
||||||
|
if itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0 {
|
||||||
if err := sanityCheckSignature(itx.V, itx.R, itx.S, true); err != nil {
|
if err := sanityCheckSignature(itx.V, itx.R, itx.S, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -191,20 +219,22 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
|
||||||
itx.AccessList = *dec.AccessList
|
itx.AccessList = *dec.AccessList
|
||||||
}
|
}
|
||||||
|
|
||||||
if dec.V == nil {
|
// signature R
|
||||||
return errors.New("missing required field 'v' in transaction")
|
|
||||||
}
|
|
||||||
itx.V = (*big.Int)(dec.V)
|
|
||||||
if dec.R == nil {
|
if dec.R == nil {
|
||||||
return errors.New("missing required field 'r' in transaction")
|
return errors.New("missing required field 'r' in transaction")
|
||||||
}
|
}
|
||||||
itx.R = (*big.Int)(dec.R)
|
itx.R = (*big.Int)(dec.R)
|
||||||
|
// signature S
|
||||||
if dec.S == nil {
|
if dec.S == nil {
|
||||||
return errors.New("missing required field 's' in transaction")
|
return errors.New("missing required field 's' in transaction")
|
||||||
}
|
}
|
||||||
itx.S = (*big.Int)(dec.S)
|
itx.S = (*big.Int)(dec.S)
|
||||||
withSignature := itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0
|
// signature V
|
||||||
if withSignature {
|
itx.V, err = dec.yParityValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0 {
|
||||||
if err := sanityCheckSignature(itx.V, itx.R, itx.S, false); err != nil {
|
if err := sanityCheckSignature(itx.V, itx.R, itx.S, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -248,20 +278,22 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
|
||||||
itx.AccessList = *dec.AccessList
|
itx.AccessList = *dec.AccessList
|
||||||
}
|
}
|
||||||
|
|
||||||
if dec.V == nil {
|
// signature R
|
||||||
return errors.New("missing required field 'v' in transaction")
|
|
||||||
}
|
|
||||||
itx.V = (*big.Int)(dec.V)
|
|
||||||
if dec.R == nil {
|
if dec.R == nil {
|
||||||
return errors.New("missing required field 'r' in transaction")
|
return errors.New("missing required field 'r' in transaction")
|
||||||
}
|
}
|
||||||
itx.R = (*big.Int)(dec.R)
|
itx.R = (*big.Int)(dec.R)
|
||||||
|
// signature S
|
||||||
if dec.S == nil {
|
if dec.S == nil {
|
||||||
return errors.New("missing required field 's' in transaction")
|
return errors.New("missing required field 's' in transaction")
|
||||||
}
|
}
|
||||||
itx.S = (*big.Int)(dec.S)
|
itx.S = (*big.Int)(dec.S)
|
||||||
withSignature := itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0
|
// signature V
|
||||||
if withSignature {
|
itx.V, err = dec.yParityValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0 {
|
||||||
if err := sanityCheckSignature(itx.V, itx.R, itx.S, false); err != nil {
|
if err := sanityCheckSignature(itx.V, itx.R, itx.S, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1670,6 +1670,7 @@ type RPCTransaction struct {
|
||||||
V *hexutil.Big `json:"v"`
|
V *hexutil.Big `json:"v"`
|
||||||
R *hexutil.Big `json:"r"`
|
R *hexutil.Big `json:"r"`
|
||||||
S *hexutil.Big `json:"s"`
|
S *hexutil.Big `json:"s"`
|
||||||
|
YParity *hexutil.Uint64 `json:"yParity,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// newRPCTransaction returns a transaction that will serialize to the RPC
|
// newRPCTransaction returns a transaction that will serialize to the RPC
|
||||||
|
|
@ -1697,6 +1698,7 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
|
||||||
result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber))
|
result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber))
|
||||||
result.TransactionIndex = (*hexutil.Uint64)(&index)
|
result.TransactionIndex = (*hexutil.Uint64)(&index)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch tx.Type() {
|
switch tx.Type() {
|
||||||
case types.LegacyTxType:
|
case types.LegacyTxType:
|
||||||
// if a legacy transaction has an EIP-155 chain id, include it explicitly
|
// if a legacy transaction has an EIP-155 chain id, include it explicitly
|
||||||
|
|
@ -1705,12 +1707,17 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
|
||||||
}
|
}
|
||||||
case types.AccessListTxType:
|
case types.AccessListTxType:
|
||||||
al := tx.AccessList()
|
al := tx.AccessList()
|
||||||
|
yparity := hexutil.Uint64(v.Sign())
|
||||||
result.Accesses = &al
|
result.Accesses = &al
|
||||||
result.ChainID = (*hexutil.Big)(tx.ChainId())
|
result.ChainID = (*hexutil.Big)(tx.ChainId())
|
||||||
|
result.YParity = &yparity
|
||||||
|
|
||||||
case types.DynamicFeeTxType:
|
case types.DynamicFeeTxType:
|
||||||
al := tx.AccessList()
|
al := tx.AccessList()
|
||||||
|
yparity := hexutil.Uint64(v.Sign())
|
||||||
result.Accesses = &al
|
result.Accesses = &al
|
||||||
result.ChainID = (*hexutil.Big)(tx.ChainId())
|
result.ChainID = (*hexutil.Big)(tx.ChainId())
|
||||||
|
result.YParity = &yparity
|
||||||
result.GasFeeCap = (*hexutil.Big)(tx.GasFeeCap())
|
result.GasFeeCap = (*hexutil.Big)(tx.GasFeeCap())
|
||||||
result.GasTipCap = (*hexutil.Big)(tx.GasTipCap())
|
result.GasTipCap = (*hexutil.Big)(tx.GasTipCap())
|
||||||
// if the transaction has been mined, compute the effective gas price
|
// if the transaction has been mined, compute the effective gas price
|
||||||
|
|
|
||||||
|
|
@ -189,25 +189,26 @@ func TestRPCMarshalBlock(t *testing.T) {
|
||||||
"value":"0x6f",
|
"value":"0x6f",
|
||||||
"type":"0x1",
|
"type":"0x1",
|
||||||
"accessList":[],
|
"accessList":[],
|
||||||
"chainId": "0x539",
|
|
||||||
"chainId":"0x539",
|
"chainId":"0x539",
|
||||||
"v":"0x0",
|
"v":"0x0",
|
||||||
"r":"0x0",
|
"r":"0x0",
|
||||||
"s":"0x0"
|
"s":"0x0",
|
||||||
|
"yParity":"0x0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"blockHash":"0x2cb4e4b5b5be5a2520377e87e8d7d2cf83fc0783fa6518d67b9606d3c5317b50",
|
"blockHash":"0x2cb4e4b5b5be5a2520377e87e8d7d2cf83fc0783fa6518d67b9606d3c5317b50",
|
||||||
"blockNumber":"0x64",
|
"blockNumber":"0x64",
|
||||||
"from":"0x0000000000000000000000000000000000000000",
|
"from":"0x0000000000000000000000000000000000000000",
|
||||||
"gas":"0x457",
|
"gas":"0x457",
|
||||||
"gasPrice":"0x2b67","hash":"0x9bba4c34e57c875ff57ac8d172805a26ae912006985395dc1bdf8f44140a7bf4",
|
"gasPrice":"0x2b67",
|
||||||
|
"hash":"0x9bba4c34e57c875ff57ac8d172805a26ae912006985395dc1bdf8f44140a7bf4",
|
||||||
"input":"0x111111",
|
"input":"0x111111",
|
||||||
"nonce":"0x2",
|
"nonce":"0x2",
|
||||||
"to":"0x0000000000000000000000000000000000000011",
|
"to":"0x0000000000000000000000000000000000000011",
|
||||||
"transactionIndex":"0x1",
|
"transactionIndex":"0x1",
|
||||||
"value":"0x6f",
|
"value":"0x6f",
|
||||||
"type":"0x0",
|
"type":"0x0",
|
||||||
"chainId": "0x7fffffffffffffee",
|
"chainId":"0x7fffffffffffffee",
|
||||||
"v":"0x0",
|
"v":"0x0",
|
||||||
"r":"0x0",
|
"r":"0x0",
|
||||||
"s":"0x0"
|
"s":"0x0"
|
||||||
|
|
@ -229,7 +230,8 @@ func TestRPCMarshalBlock(t *testing.T) {
|
||||||
"chainId":"0x539",
|
"chainId":"0x539",
|
||||||
"v":"0x0",
|
"v":"0x0",
|
||||||
"r":"0x0",
|
"r":"0x0",
|
||||||
"s":"0x0"
|
"s":"0x0",
|
||||||
|
"yParity":"0x0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"blockHash":"0x2cb4e4b5b5be5a2520377e87e8d7d2cf83fc0783fa6518d67b9606d3c5317b50",
|
"blockHash":"0x2cb4e4b5b5be5a2520377e87e8d7d2cf83fc0783fa6518d67b9606d3c5317b50",
|
||||||
|
|
@ -244,7 +246,7 @@ func TestRPCMarshalBlock(t *testing.T) {
|
||||||
"transactionIndex":"0x3",
|
"transactionIndex":"0x3",
|
||||||
"value":"0x6f",
|
"value":"0x6f",
|
||||||
"type":"0x0",
|
"type":"0x0",
|
||||||
"chainId": "0x7fffffffffffffee",
|
"chainId":"0x7fffffffffffffee",
|
||||||
"v":"0x0",
|
"v":"0x0",
|
||||||
"r":"0x0",
|
"r":"0x0",
|
||||||
"s":"0x0"
|
"s":"0x0"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue