Merge tag 'v1.10.6' into develop
This commit is contained in:
commit
299b5cb05c
11
cmd/evm/testdata/12/alloc.json
vendored
Normal file
11
cmd/evm/testdata/12/alloc.json
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||||
|
"balance" : "84000000",
|
||||||
|
"code" : "0x",
|
||||||
|
"nonce" : "0x00",
|
||||||
|
"storage" : {
|
||||||
|
"0x00" : "0x00"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
10
cmd/evm/testdata/12/env.json
vendored
Normal file
10
cmd/evm/testdata/12/env.json
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
||||||
|
"currentDifficulty" : "0x020000",
|
||||||
|
"currentNumber" : "0x01",
|
||||||
|
"currentTimestamp" : "0x03e8",
|
||||||
|
"previousHash" : "0xfda4419b3660e99f37e536dae1ab081c180136bb38c837a93e93d9aab58553b2",
|
||||||
|
"currentGasLimit" : "0x0f4240",
|
||||||
|
"currentBaseFee" : "0x20"
|
||||||
|
}
|
||||||
|
|
40
cmd/evm/testdata/12/readme.md
vendored
Normal file
40
cmd/evm/testdata/12/readme.md
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
## Test 1559 balance + gasCap
|
||||||
|
|
||||||
|
This test contains an EIP-1559 consensus issue which happened on Ropsten, where
|
||||||
|
`geth` did not properly account for the value transfer while doing the check on `max_fee_per_gas * gas_limit`.
|
||||||
|
|
||||||
|
Before the issue was fixed, this invocation allowed the transaction to pass into a block:
|
||||||
|
```
|
||||||
|
dir=./testdata/12 && ./evm t8n --state.fork=London --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --output.alloc=stdout --output.result=stdout
|
||||||
|
```
|
||||||
|
|
||||||
|
With the fix applied, the result is:
|
||||||
|
```
|
||||||
|
dir=./testdata/12 && ./evm t8n --state.fork=London --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --output.alloc=stdout --output.result=stdout
|
||||||
|
INFO [07-21|19:03:50.276] rejected tx index=0 hash=ccc996..d83435 from=0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B error="insufficient funds for gas * price + value: address 0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B have 84000000 want 84000032"
|
||||||
|
INFO [07-21|19:03:50.276] Trie dumping started root=e05f81..6597a5
|
||||||
|
INFO [07-21|19:03:50.276] Trie dumping complete accounts=1 elapsed="39.549µs"
|
||||||
|
{
|
||||||
|
"alloc": {
|
||||||
|
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
|
||||||
|
"balance": "0x501bd00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"result": {
|
||||||
|
"stateRoot": "0xe05f81f8244a76503ceec6f88abfcd03047a612a1001217f37d30984536597a5",
|
||||||
|
"txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
|
"receiptRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
|
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"receipts": [],
|
||||||
|
"rejected": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"error": "insufficient funds for gas * price + value: address 0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B have 84000000 want 84000032"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The transaction is rejected.
|
20
cmd/evm/testdata/12/txs.json
vendored
Normal file
20
cmd/evm/testdata/12/txs.json
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"input" : "0x",
|
||||||
|
"gas" : "0x5208",
|
||||||
|
"nonce" : "0x0",
|
||||||
|
"to" : "0x1111111111111111111111111111111111111111",
|
||||||
|
"value" : "0x20",
|
||||||
|
"v" : "0x0",
|
||||||
|
"r" : "0x0",
|
||||||
|
"s" : "0x0",
|
||||||
|
"secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
|
||||||
|
"chainId" : "0x1",
|
||||||
|
"type" : "0x2",
|
||||||
|
"maxFeePerGas" : "0xfa0",
|
||||||
|
"maxPriorityFeePerGas" : "0x20",
|
||||||
|
"accessList" : [
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
@ -118,7 +118,7 @@ func TestStateProcessorErrors(t *testing.T) {
|
|||||||
txs: []*types.Transaction{
|
txs: []*types.Transaction{
|
||||||
makeTx(0, common.Address{}, big.NewInt(1000000000000000000), params.TxGas, big.NewInt(875000000), nil),
|
makeTx(0, common.Address{}, big.NewInt(1000000000000000000), params.TxGas, big.NewInt(875000000), nil),
|
||||||
},
|
},
|
||||||
want: "could not apply tx 0 [0x98c796b470f7fcab40aaef5c965a602b0238e1034cce6fb73823042dd0638d74]: insufficient funds for transfer: address 0x71562b71999873DB5b286dF957af199Ec94617F7",
|
want: "could not apply tx 0 [0x98c796b470f7fcab40aaef5c965a602b0238e1034cce6fb73823042dd0638d74]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 have 1000000000000000000 want 1000018375000000000",
|
||||||
},
|
},
|
||||||
{ // ErrInsufficientFunds
|
{ // ErrInsufficientFunds
|
||||||
txs: []*types.Transaction{
|
txs: []*types.Transaction{
|
||||||
|
@ -193,6 +193,7 @@ func (st *StateTransition) buyGas() error {
|
|||||||
if st.gasFeeCap != nil {
|
if st.gasFeeCap != nil {
|
||||||
balanceCheck = new(big.Int).SetUint64(st.msg.Gas())
|
balanceCheck = new(big.Int).SetUint64(st.msg.Gas())
|
||||||
balanceCheck = balanceCheck.Mul(balanceCheck, st.gasFeeCap)
|
balanceCheck = balanceCheck.Mul(balanceCheck, st.gasFeeCap)
|
||||||
|
balanceCheck.Add(balanceCheck, st.value)
|
||||||
}
|
}
|
||||||
if have, want := st.state.GetBalance(st.msg.From()), balanceCheck; have.Cmp(want) < 0 {
|
if have, want := st.state.GetBalance(st.msg.From()), balanceCheck; have.Cmp(want) < 0 {
|
||||||
return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From().Hex(), have, want)
|
return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From().Hex(), have, want)
|
||||||
|
@ -18,12 +18,12 @@ func (l Log) MarshalJSON() ([]byte, error) {
|
|||||||
Address common.Address `json:"address" gencodec:"required"`
|
Address common.Address `json:"address" gencodec:"required"`
|
||||||
Topics []common.Hash `json:"topics" gencodec:"required"`
|
Topics []common.Hash `json:"topics" gencodec:"required"`
|
||||||
Data hexutil.Bytes `json:"data" gencodec:"required"`
|
Data hexutil.Bytes `json:"data" gencodec:"required"`
|
||||||
BlockNumber hexutil.Uint64 `json:"blockNumber" rlp:"-"`
|
BlockNumber hexutil.Uint64 `json:"blockNumber"`
|
||||||
TxHash common.Hash `json:"transactionHash" gencodec:"required" rlp:"-"`
|
TxHash common.Hash `json:"transactionHash" gencodec:"required"`
|
||||||
TxIndex hexutil.Uint `json:"transactionIndex" rlp:"-"`
|
TxIndex hexutil.Uint `json:"transactionIndex"`
|
||||||
BlockHash common.Hash `json:"blockHash" rlp:"-"`
|
BlockHash common.Hash `json:"blockHash"`
|
||||||
Index hexutil.Uint `json:"logIndex" rlp:"-"`
|
Index hexutil.Uint `json:"logIndex"`
|
||||||
Removed bool `json:"removed" rlp:"-"`
|
Removed bool `json:"removed"`
|
||||||
}
|
}
|
||||||
var enc Log
|
var enc Log
|
||||||
enc.Address = l.Address
|
enc.Address = l.Address
|
||||||
@ -44,12 +44,12 @@ func (l *Log) UnmarshalJSON(input []byte) error {
|
|||||||
Address *common.Address `json:"address" gencodec:"required"`
|
Address *common.Address `json:"address" gencodec:"required"`
|
||||||
Topics []common.Hash `json:"topics" gencodec:"required"`
|
Topics []common.Hash `json:"topics" gencodec:"required"`
|
||||||
Data *hexutil.Bytes `json:"data" gencodec:"required"`
|
Data *hexutil.Bytes `json:"data" gencodec:"required"`
|
||||||
BlockNumber *hexutil.Uint64 `json:"blockNumber" rlp:"-"`
|
BlockNumber *hexutil.Uint64 `json:"blockNumber"`
|
||||||
TxHash *common.Hash `json:"transactionHash" gencodec:"required" rlp:"-"`
|
TxHash *common.Hash `json:"transactionHash" gencodec:"required"`
|
||||||
TxIndex *hexutil.Uint `json:"transactionIndex" rlp:"-"`
|
TxIndex *hexutil.Uint `json:"transactionIndex"`
|
||||||
BlockHash *common.Hash `json:"blockHash" rlp:"-"`
|
BlockHash *common.Hash `json:"blockHash"`
|
||||||
Index *hexutil.Uint `json:"logIndex" rlp:"-"`
|
Index *hexutil.Uint `json:"logIndex"`
|
||||||
Removed *bool `json:"removed" rlp:"-"`
|
Removed *bool `json:"removed"`
|
||||||
}
|
}
|
||||||
var dec Log
|
var dec Log
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
@ -17,8 +17,11 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate gencodec -type Log -field-override logMarshaling -out gen_log_json.go
|
//go:generate gencodec -type Log -field-override logMarshaling -out gen_log_json.go
|
||||||
@ -37,19 +40,19 @@ type Log struct {
|
|||||||
// Derived fields. These fields are filled in by the node
|
// Derived fields. These fields are filled in by the node
|
||||||
// but not secured by consensus.
|
// but not secured by consensus.
|
||||||
// block in which the transaction was included
|
// block in which the transaction was included
|
||||||
BlockNumber uint64 `json:"blockNumber" rlp:"-"`
|
BlockNumber uint64 `json:"blockNumber"`
|
||||||
// hash of the transaction
|
// hash of the transaction
|
||||||
TxHash common.Hash `json:"transactionHash" gencodec:"required" rlp:"-"`
|
TxHash common.Hash `json:"transactionHash" gencodec:"required"`
|
||||||
// index of the transaction in the block
|
// index of the transaction in the block
|
||||||
TxIndex uint `json:"transactionIndex" rlp:"-"`
|
TxIndex uint `json:"transactionIndex"`
|
||||||
// hash of the block in which the transaction was included
|
// hash of the block in which the transaction was included
|
||||||
BlockHash common.Hash `json:"blockHash" rlp:"-"`
|
BlockHash common.Hash `json:"blockHash"`
|
||||||
// index of the log in the block
|
// index of the log in the block
|
||||||
Index uint `json:"logIndex" rlp:"-"`
|
Index uint `json:"logIndex"`
|
||||||
|
|
||||||
// The Removed field is true if this log was reverted due to a chain reorganisation.
|
// The Removed field is true if this log was reverted due to a chain reorganisation.
|
||||||
// You must pay attention to this field if you receive logs through a filter query.
|
// You must pay attention to this field if you receive logs through a filter query.
|
||||||
Removed bool `json:"removed" rlp:"-"`
|
Removed bool `json:"removed"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type logMarshaling struct {
|
type logMarshaling struct {
|
||||||
@ -58,3 +61,83 @@ type logMarshaling struct {
|
|||||||
TxIndex hexutil.Uint
|
TxIndex hexutil.Uint
|
||||||
Index hexutil.Uint
|
Index hexutil.Uint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type rlpLog struct {
|
||||||
|
Address common.Address
|
||||||
|
Topics []common.Hash
|
||||||
|
Data []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// rlpStorageLog is the storage encoding of a log.
|
||||||
|
type rlpStorageLog rlpLog
|
||||||
|
|
||||||
|
// legacyRlpStorageLog is the previous storage encoding of a log including some redundant fields.
|
||||||
|
type legacyRlpStorageLog struct {
|
||||||
|
Address common.Address
|
||||||
|
Topics []common.Hash
|
||||||
|
Data []byte
|
||||||
|
BlockNumber uint64
|
||||||
|
TxHash common.Hash
|
||||||
|
TxIndex uint
|
||||||
|
BlockHash common.Hash
|
||||||
|
Index uint
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeRLP implements rlp.Encoder.
|
||||||
|
func (l *Log) EncodeRLP(w io.Writer) error {
|
||||||
|
return rlp.Encode(w, rlpLog{Address: l.Address, Topics: l.Topics, Data: l.Data})
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeRLP implements rlp.Decoder.
|
||||||
|
func (l *Log) DecodeRLP(s *rlp.Stream) error {
|
||||||
|
var dec rlpLog
|
||||||
|
err := s.Decode(&dec)
|
||||||
|
if err == nil {
|
||||||
|
l.Address, l.Topics, l.Data = dec.Address, dec.Topics, dec.Data
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// LogForStorage is a wrapper around a Log that flattens and parses the entire content of
|
||||||
|
// a log including non-consensus fields.
|
||||||
|
type LogForStorage Log
|
||||||
|
|
||||||
|
// EncodeRLP implements rlp.Encoder.
|
||||||
|
func (l *LogForStorage) EncodeRLP(w io.Writer) error {
|
||||||
|
return rlp.Encode(w, rlpStorageLog{
|
||||||
|
Address: l.Address,
|
||||||
|
Topics: l.Topics,
|
||||||
|
Data: l.Data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeRLP implements rlp.Decoder.
|
||||||
|
//
|
||||||
|
// Note some redundant fields(e.g. block number, tx hash etc) will be assembled later.
|
||||||
|
func (l *LogForStorage) DecodeRLP(s *rlp.Stream) error {
|
||||||
|
blob, err := s.Raw()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var dec rlpStorageLog
|
||||||
|
err = rlp.DecodeBytes(blob, &dec)
|
||||||
|
if err == nil {
|
||||||
|
*l = LogForStorage{
|
||||||
|
Address: dec.Address,
|
||||||
|
Topics: dec.Topics,
|
||||||
|
Data: dec.Data,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Try to decode log with previous definition.
|
||||||
|
var dec legacyRlpStorageLog
|
||||||
|
err = rlp.DecodeBytes(blob, &dec)
|
||||||
|
if err == nil {
|
||||||
|
*l = LogForStorage{
|
||||||
|
Address: dec.Address,
|
||||||
|
Topics: dec.Topics,
|
||||||
|
Data: dec.Data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
@ -94,7 +94,28 @@ type receiptRLP struct {
|
|||||||
type storedReceiptRLP struct {
|
type storedReceiptRLP struct {
|
||||||
PostStateOrStatus []byte
|
PostStateOrStatus []byte
|
||||||
CumulativeGasUsed uint64
|
CumulativeGasUsed uint64
|
||||||
Logs []*Log
|
Logs []*LogForStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
// v4StoredReceiptRLP is the storage encoding of a receipt used in database version 4.
|
||||||
|
type v4StoredReceiptRLP struct {
|
||||||
|
PostStateOrStatus []byte
|
||||||
|
CumulativeGasUsed uint64
|
||||||
|
TxHash common.Hash
|
||||||
|
ContractAddress common.Address
|
||||||
|
Logs []*LogForStorage
|
||||||
|
GasUsed uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// v3StoredReceiptRLP is the original storage encoding of a receipt including some unnecessary fields.
|
||||||
|
type v3StoredReceiptRLP struct {
|
||||||
|
PostStateOrStatus []byte
|
||||||
|
CumulativeGasUsed uint64
|
||||||
|
Bloom Bloom
|
||||||
|
TxHash common.Hash
|
||||||
|
ContractAddress common.Address
|
||||||
|
Logs []*LogForStorage
|
||||||
|
GasUsed uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewReceipt creates a barebone transaction receipt, copying the init fields.
|
// NewReceipt creates a barebone transaction receipt, copying the init fields.
|
||||||
@ -212,28 +233,96 @@ func (r *Receipt) Size() common.StorageSize {
|
|||||||
// entire content of a receipt, as opposed to only the consensus fields originally.
|
// entire content of a receipt, as opposed to only the consensus fields originally.
|
||||||
type ReceiptForStorage Receipt
|
type ReceiptForStorage Receipt
|
||||||
|
|
||||||
// EncodeRLP implements rlp.Encoder.
|
// EncodeRLP implements rlp.Encoder, and flattens all content fields of a receipt
|
||||||
|
// into an RLP stream.
|
||||||
func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error {
|
func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error {
|
||||||
enc := &storedReceiptRLP{
|
enc := &storedReceiptRLP{
|
||||||
PostStateOrStatus: (*Receipt)(r).statusEncoding(),
|
PostStateOrStatus: (*Receipt)(r).statusEncoding(),
|
||||||
CumulativeGasUsed: r.CumulativeGasUsed,
|
CumulativeGasUsed: r.CumulativeGasUsed,
|
||||||
Logs: r.Logs,
|
Logs: make([]*LogForStorage, len(r.Logs)),
|
||||||
|
}
|
||||||
|
for i, log := range r.Logs {
|
||||||
|
enc.Logs[i] = (*LogForStorage)(log)
|
||||||
}
|
}
|
||||||
return rlp.Encode(w, enc)
|
return rlp.Encode(w, enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeRLP implements rlp.Decoder.
|
// DecodeRLP implements rlp.Decoder, and loads both consensus and implementation
|
||||||
|
// fields of a receipt from an RLP stream.
|
||||||
func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
|
func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
|
||||||
|
// Retrieve the entire receipt blob as we need to try multiple decoders
|
||||||
|
blob, err := s.Raw()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Try decoding from the newest format for future proofness, then the older one
|
||||||
|
// for old nodes that just upgraded. V4 was an intermediate unreleased format so
|
||||||
|
// we do need to decode it, but it's not common (try last).
|
||||||
|
if err := decodeStoredReceiptRLP(r, blob); err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := decodeV3StoredReceiptRLP(r, blob); err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return decodeV4StoredReceiptRLP(r, blob)
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeStoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
|
||||||
var stored storedReceiptRLP
|
var stored storedReceiptRLP
|
||||||
if err := s.Decode(&stored); err != nil {
|
if err := rlp.DecodeBytes(blob, &stored); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := (*Receipt)(r).setStatus(stored.PostStateOrStatus); err != nil {
|
if err := (*Receipt)(r).setStatus(stored.PostStateOrStatus); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
r.CumulativeGasUsed = stored.CumulativeGasUsed
|
r.CumulativeGasUsed = stored.CumulativeGasUsed
|
||||||
r.Logs = stored.Logs
|
r.Logs = make([]*Log, len(stored.Logs))
|
||||||
|
for i, log := range stored.Logs {
|
||||||
|
r.Logs[i] = (*Log)(log)
|
||||||
|
}
|
||||||
r.Bloom = CreateBloom(Receipts{(*Receipt)(r)})
|
r.Bloom = CreateBloom(Receipts{(*Receipt)(r)})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeV4StoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
|
||||||
|
var stored v4StoredReceiptRLP
|
||||||
|
if err := rlp.DecodeBytes(blob, &stored); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := (*Receipt)(r).setStatus(stored.PostStateOrStatus); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.CumulativeGasUsed = stored.CumulativeGasUsed
|
||||||
|
r.TxHash = stored.TxHash
|
||||||
|
r.ContractAddress = stored.ContractAddress
|
||||||
|
r.GasUsed = stored.GasUsed
|
||||||
|
r.Logs = make([]*Log, len(stored.Logs))
|
||||||
|
for i, log := range stored.Logs {
|
||||||
|
r.Logs[i] = (*Log)(log)
|
||||||
|
}
|
||||||
|
r.Bloom = CreateBloom(Receipts{(*Receipt)(r)})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeV3StoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
|
||||||
|
var stored v3StoredReceiptRLP
|
||||||
|
if err := rlp.DecodeBytes(blob, &stored); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := (*Receipt)(r).setStatus(stored.PostStateOrStatus); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.CumulativeGasUsed = stored.CumulativeGasUsed
|
||||||
|
r.Bloom = stored.Bloom
|
||||||
|
r.TxHash = stored.TxHash
|
||||||
|
r.ContractAddress = stored.ContractAddress
|
||||||
|
r.GasUsed = stored.GasUsed
|
||||||
|
r.Logs = make([]*Log, len(stored.Logs))
|
||||||
|
for i, log := range stored.Logs {
|
||||||
|
r.Logs[i] = (*Log)(log)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"math"
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@ -37,6 +38,128 @@ func TestDecodeEmptyTypedReceipt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLegacyReceiptDecoding(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
encode func(*Receipt) ([]byte, error)
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"StoredReceiptRLP",
|
||||||
|
encodeAsStoredReceiptRLP,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"V4StoredReceiptRLP",
|
||||||
|
encodeAsV4StoredReceiptRLP,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"V3StoredReceiptRLP",
|
||||||
|
encodeAsV3StoredReceiptRLP,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
tx := NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil)
|
||||||
|
receipt := &Receipt{
|
||||||
|
Status: ReceiptStatusFailed,
|
||||||
|
CumulativeGasUsed: 1,
|
||||||
|
Logs: []*Log{
|
||||||
|
{
|
||||||
|
Address: common.BytesToAddress([]byte{0x11}),
|
||||||
|
Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")},
|
||||||
|
Data: []byte{0x01, 0x00, 0xff},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: common.BytesToAddress([]byte{0x01, 0x11}),
|
||||||
|
Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")},
|
||||||
|
Data: []byte{0x01, 0x00, 0xff},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TxHash: tx.Hash(),
|
||||||
|
ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
|
||||||
|
GasUsed: 111111,
|
||||||
|
}
|
||||||
|
receipt.Bloom = CreateBloom(Receipts{receipt})
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
enc, err := tc.encode(receipt)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error encoding receipt: %v", err)
|
||||||
|
}
|
||||||
|
var dec ReceiptForStorage
|
||||||
|
if err := rlp.DecodeBytes(enc, &dec); err != nil {
|
||||||
|
t.Fatalf("Error decoding RLP receipt: %v", err)
|
||||||
|
}
|
||||||
|
// Check whether all consensus fields are correct.
|
||||||
|
if dec.Status != receipt.Status {
|
||||||
|
t.Fatalf("Receipt status mismatch, want %v, have %v", receipt.Status, dec.Status)
|
||||||
|
}
|
||||||
|
if dec.CumulativeGasUsed != receipt.CumulativeGasUsed {
|
||||||
|
t.Fatalf("Receipt CumulativeGasUsed mismatch, want %v, have %v", receipt.CumulativeGasUsed, dec.CumulativeGasUsed)
|
||||||
|
}
|
||||||
|
if dec.Bloom != receipt.Bloom {
|
||||||
|
t.Fatalf("Bloom data mismatch, want %v, have %v", receipt.Bloom, dec.Bloom)
|
||||||
|
}
|
||||||
|
if len(dec.Logs) != len(receipt.Logs) {
|
||||||
|
t.Fatalf("Receipt log number mismatch, want %v, have %v", len(receipt.Logs), len(dec.Logs))
|
||||||
|
}
|
||||||
|
for i := 0; i < len(dec.Logs); i++ {
|
||||||
|
if dec.Logs[i].Address != receipt.Logs[i].Address {
|
||||||
|
t.Fatalf("Receipt log %d address mismatch, want %v, have %v", i, receipt.Logs[i].Address, dec.Logs[i].Address)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(dec.Logs[i].Topics, receipt.Logs[i].Topics) {
|
||||||
|
t.Fatalf("Receipt log %d topics mismatch, want %v, have %v", i, receipt.Logs[i].Topics, dec.Logs[i].Topics)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(dec.Logs[i].Data, receipt.Logs[i].Data) {
|
||||||
|
t.Fatalf("Receipt log %d data mismatch, want %v, have %v", i, receipt.Logs[i].Data, dec.Logs[i].Data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeAsStoredReceiptRLP(want *Receipt) ([]byte, error) {
|
||||||
|
stored := &storedReceiptRLP{
|
||||||
|
PostStateOrStatus: want.statusEncoding(),
|
||||||
|
CumulativeGasUsed: want.CumulativeGasUsed,
|
||||||
|
Logs: make([]*LogForStorage, len(want.Logs)),
|
||||||
|
}
|
||||||
|
for i, log := range want.Logs {
|
||||||
|
stored.Logs[i] = (*LogForStorage)(log)
|
||||||
|
}
|
||||||
|
return rlp.EncodeToBytes(stored)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeAsV4StoredReceiptRLP(want *Receipt) ([]byte, error) {
|
||||||
|
stored := &v4StoredReceiptRLP{
|
||||||
|
PostStateOrStatus: want.statusEncoding(),
|
||||||
|
CumulativeGasUsed: want.CumulativeGasUsed,
|
||||||
|
TxHash: want.TxHash,
|
||||||
|
ContractAddress: want.ContractAddress,
|
||||||
|
Logs: make([]*LogForStorage, len(want.Logs)),
|
||||||
|
GasUsed: want.GasUsed,
|
||||||
|
}
|
||||||
|
for i, log := range want.Logs {
|
||||||
|
stored.Logs[i] = (*LogForStorage)(log)
|
||||||
|
}
|
||||||
|
return rlp.EncodeToBytes(stored)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeAsV3StoredReceiptRLP(want *Receipt) ([]byte, error) {
|
||||||
|
stored := &v3StoredReceiptRLP{
|
||||||
|
PostStateOrStatus: want.statusEncoding(),
|
||||||
|
CumulativeGasUsed: want.CumulativeGasUsed,
|
||||||
|
Bloom: want.Bloom,
|
||||||
|
TxHash: want.TxHash,
|
||||||
|
ContractAddress: want.ContractAddress,
|
||||||
|
Logs: make([]*LogForStorage, len(want.Logs)),
|
||||||
|
GasUsed: want.GasUsed,
|
||||||
|
}
|
||||||
|
for i, log := range want.Logs {
|
||||||
|
stored.Logs[i] = (*LogForStorage)(log)
|
||||||
|
}
|
||||||
|
return rlp.EncodeToBytes(stored)
|
||||||
|
}
|
||||||
|
|
||||||
// Tests that receipt data can be correctly derived from the contextual infos
|
// Tests that receipt data can be correctly derived from the contextual infos
|
||||||
func TestDeriveFields(t *testing.T) {
|
func TestDeriveFields(t *testing.T) {
|
||||||
// Create a few transactions to have receipts for
|
// Create a few transactions to have receipts for
|
||||||
|
@ -306,7 +306,7 @@ func TestTraceCall(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOverridenTraceCall(t *testing.T) {
|
func TestOverriddenTraceCall(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Initialize test accounts
|
// Initialize test accounts
|
||||||
@ -369,7 +369,7 @@ func TestOverridenTraceCall(t *testing.T) {
|
|||||||
config: &TraceCallConfig{
|
config: &TraceCallConfig{
|
||||||
Tracer: &tracer,
|
Tracer: &tracer,
|
||||||
},
|
},
|
||||||
expectErr: core.ErrInsufficientFundsForTransfer,
|
expectErr: core.ErrInsufficientFunds,
|
||||||
expect: nil,
|
expect: nil,
|
||||||
},
|
},
|
||||||
// Successful simple contract call
|
// Successful simple contract call
|
||||||
|
@ -60,8 +60,11 @@ func (b *LesApiBackend) SetHead(number uint64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
|
func (b *LesApiBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
|
||||||
|
// Return the latest current as the pending one since there
|
||||||
|
// is no pending notion in the light client. TODO(rjl493456442)
|
||||||
|
// unify the behavior of `HeaderByNumber` and `PendingBlockAndReceipts`.
|
||||||
if number == rpc.PendingBlockNumber {
|
if number == rpc.PendingBlockNumber {
|
||||||
return nil, nil
|
return b.eth.blockchain.CurrentHeader(), nil
|
||||||
}
|
}
|
||||||
if number == rpc.LatestBlockNumber {
|
if number == rpc.LatestBlockNumber {
|
||||||
return b.eth.blockchain.CurrentHeader(), nil
|
return b.eth.blockchain.CurrentHeader(), nil
|
||||||
|
@ -251,7 +251,7 @@ func (h *httpServer) doStop() {
|
|||||||
|
|
||||||
// Shut down the server.
|
// Shut down the server.
|
||||||
httpHandler := h.httpHandler.Load().(*rpcHandler)
|
httpHandler := h.httpHandler.Load().(*rpcHandler)
|
||||||
wsHandler := h.httpHandler.Load().(*rpcHandler)
|
wsHandler := h.wsHandler.Load().(*rpcHandler)
|
||||||
if httpHandler != nil {
|
if httpHandler != nil {
|
||||||
h.httpHandler.Store((*rpcHandler)(nil))
|
h.httpHandler.Store((*rpcHandler)(nil))
|
||||||
httpHandler.server.Stop()
|
httpHandler.server.Stop()
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
VersionMajor = 1 // Major version component of the current release
|
VersionMajor = 1 // Major version component of the current release
|
||||||
VersionMinor = 10 // Minor version component of the current release
|
VersionMinor = 10 // Minor version component of the current release
|
||||||
VersionPatch = 5 // Patch version component of the current release
|
VersionPatch = 6 // Patch version component of the current release
|
||||||
VersionMeta = "stable" // Version metadata to append to the version string
|
VersionMeta = "stable" // Version metadata to append to the version string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user