Merge tag 'v1.10.6' into develop

This commit is contained in:
Austin Roberts 2021-10-18 11:08:43 -05:00
commit 299b5cb05c
14 changed files with 410 additions and 30 deletions

11
cmd/evm/testdata/12/alloc.json vendored Normal file
View 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
View 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
View 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
View 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" : [
]
}
]

View File

@ -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{

View File

@ -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)

View File

@ -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 {

View File

@ -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
}

View File

@ -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
} }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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
) )