Compare commits
44 Commits
v1.0.1-bet
...
v1.0.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a1e79e2a1 | ||
|
|
e09e48a02f | ||
|
|
b605f1f913 | ||
|
|
9fedf1909d | ||
|
|
24dc208170 | ||
|
|
60606d3919 | ||
|
|
5a1c39da09 | ||
|
|
cfeab77017 | ||
|
|
9e8ee517d7 | ||
|
|
ca1d1cb08d | ||
|
|
670009d1e1 | ||
|
|
4608da6c13 | ||
|
|
d1f95d5fd3 | ||
|
|
ad3ff6452d | ||
|
|
0a64615f1e | ||
|
|
2a79ac1622 | ||
|
|
0e797c53b7 | ||
|
|
3f3f8d02cf | ||
|
|
5bd73320ba | ||
|
|
894b1e3c8d | ||
|
|
3d3f9694a4 | ||
|
|
f6ec491548 | ||
|
|
e0205f5983 | ||
|
|
69fe8db258 | ||
|
|
ed10dfa6bf | ||
|
|
3da36e6a55 | ||
|
|
c2feabad39 | ||
|
|
b0fcc0a663 | ||
|
|
58a91af56c | ||
|
|
cca7667dcd | ||
|
|
1a50838431 | ||
|
|
d52d8a5f05 | ||
|
|
935c9e3c6a | ||
|
|
cb1afd2b14 | ||
|
|
7bd1c1f23d | ||
|
|
537c5db510 | ||
|
|
40620b478c | ||
|
|
e81c728ff6 | ||
|
|
bfb73f8068 | ||
|
|
397f6f6108 | ||
|
|
b242e890d2 | ||
|
|
ba0152fea9 | ||
|
|
844ed90c28 | ||
|
|
f94b7de003 |
38
CHANGELOG.md
38
CHANGELOG.md
@@ -1,5 +1,43 @@
|
||||
# Changelog
|
||||
|
||||
## v1.0.5
|
||||
|
||||
SECURITY
|
||||
* [\#63](https://github.com/binance-chain/bsc/pull/63) security patches from go-ethereum
|
||||
* [\#54](https://github.com/binance-chain/bsc/pull/54) les: fix GetProofsV2 that could potentially cause a panic.
|
||||
|
||||
FEATURES
|
||||
* [\#56](https://github.com/binance-chain/bsc/pull/56) apply mirror sync upgrade
|
||||
* [\#53](https://github.com/binance-chain/bsc/pull/53) support fork id in header; elegant upgrade
|
||||
|
||||
IMPROVEMENT
|
||||
* [\#61](https://github.com/binance-chain/bsc/pull/61)Add `x-forward-for` log message when handle message failed
|
||||
* [\#60](https://github.com/binance-chain/bsc/pull/61) add rpc method request gauge
|
||||
|
||||
BUGFIX
|
||||
* [\#59](https://github.com/binance-chain/bsc/pull/59) fix potential deadlock of pub/sub module
|
||||
|
||||
|
||||
|
||||
## v1.0.4
|
||||
|
||||
IMPROVEMENT
|
||||
* [\#35](https://github.com/binance-chain/bsc/pull/35) use fixed gas price when network is idle
|
||||
* [\#38](https://github.com/binance-chain/bsc/pull/38) disable noisy log from consensus engine
|
||||
* [\#47](https://github.com/binance-chain/bsc/pull/47) upgrade to golang1.15.5
|
||||
* [\#49](https://github.com/binance-chain/bsc/pull/49) Create pull request template for all developer to follow
|
||||
|
||||
|
||||
## v1.0.3
|
||||
|
||||
IMPROVEMENT
|
||||
* [\#36](https://github.com/binance-chain/bsc/pull/36) add max gas allwance calculation
|
||||
|
||||
## v1.0.2
|
||||
|
||||
IMPROVEMENT
|
||||
* [\#29](https://github.com/binance-chain/bsc/pull/29) eth/tracers: revert reason in call_tracer + error for failed internal…
|
||||
|
||||
## v1.0.1-beta
|
||||
|
||||
IMPROVEMENT
|
||||
|
||||
15
Dockerfile
15
Dockerfile
@@ -1,7 +1,12 @@
|
||||
# Build Geth in a stock Go builder container
|
||||
FROM golang:1.14-alpine as builder
|
||||
FROM golang:1.15-alpine as builder
|
||||
|
||||
RUN apk add --no-cache make gcc musl-dev linux-headers git
|
||||
RUN apk add --no-cache make gcc musl-dev linux-headers git bash
|
||||
|
||||
# Temporarily pull a custom Go bundle
|
||||
ADD https://golang.org/dl/go1.15.5.src.tar.gz /tmp/go.tar.gz
|
||||
RUN (cd /tmp && tar -xf go.tar.gz)
|
||||
RUN (cd /tmp/go/src && ./make.bash)
|
||||
ENV PATH="/tmp/go/bin:${PATH}"
|
||||
|
||||
ADD . /go-ethereum
|
||||
RUN cd /go-ethereum && make geth
|
||||
@@ -9,8 +14,8 @@ RUN cd /go-ethereum && make geth
|
||||
# Pull Geth into a second stage deploy alpine container
|
||||
FROM alpine:latest
|
||||
|
||||
RUN apk add --no-cache ca-certificates
|
||||
RUN apk add --no-cache ca-certificates curl
|
||||
COPY --from=builder /go-ethereum/build/bin/geth /usr/local/bin/
|
||||
|
||||
EXPOSE 8545 8546 8547 30303 30303/udp
|
||||
ENTRYPOINT ["geth"]
|
||||
ENTRYPOINT ["geth"]
|
||||
31
PULL_REQUEST_TEMPLATE
Normal file
31
PULL_REQUEST_TEMPLATE
Normal file
@@ -0,0 +1,31 @@
|
||||
### Description
|
||||
|
||||
add a description of your changes here...
|
||||
|
||||
### Rationale
|
||||
|
||||
tell us why we need these changes...
|
||||
|
||||
### Example
|
||||
|
||||
add an example CLI or API response...
|
||||
|
||||
### Changes
|
||||
|
||||
Notable changes:
|
||||
* add each change in a bullet point here
|
||||
* ...
|
||||
|
||||
### Preflight checks
|
||||
|
||||
- [ ] build passed (`make build`)
|
||||
- [ ] tests passed (`make test`)
|
||||
- [ ] manual transaction test passed
|
||||
|
||||
### Already reviewed by
|
||||
|
||||
...
|
||||
|
||||
### Related issues
|
||||
|
||||
... reference related issue #'s here ...
|
||||
@@ -1,10 +1,3 @@
|
||||
## Disclaimer
|
||||
|
||||
**The software and related documentation are under active development,
|
||||
all subject to potential future change without notification and not ready for production use.
|
||||
The code and security audit have not been fully completed and not ready for any bug bounty.
|
||||
We advise you to be careful and experiment on the network at your own risk. Stay safe out there.**
|
||||
|
||||
## Binance Smart Chain
|
||||
|
||||
The goal of Binance Smart Chain is to bring programmability and interoperability to Binance Chain. In order to embrace the existing popular community and advanced technology, it will bring huge benefits by staying compatible with all the existing smart contracts on Ethereum and Ethereum tooling. And to achieve that, the easiest solution is to develop based on go-ethereum fork, as we respect the great work of Ethereum very much.
|
||||
|
||||
@@ -350,7 +350,7 @@ func isDynamicType(t Type) bool {
|
||||
func getTypeSize(t Type) int {
|
||||
if t.T == ArrayTy && !isDynamicType(*t.Elem) {
|
||||
// Recursively calculate type size if it is a nested array
|
||||
if t.Elem.T == ArrayTy {
|
||||
if t.Elem.T == ArrayTy || t.Elem.T == TupleTy {
|
||||
return t.Size * getTypeSize(*t.Elem)
|
||||
}
|
||||
return t.Size * 32
|
||||
|
||||
@@ -94,7 +94,7 @@ with minimal requirements.
|
||||
On the `client` qube, we need to create a listener which will receive the request from the Dapp, and proxy it.
|
||||
|
||||
|
||||
[qubes-client.py](qubes/client/qubes-client.py):
|
||||
[qubes-client.py](qubes/qubes-client.py):
|
||||
|
||||
```python
|
||||
|
||||
|
||||
@@ -135,6 +135,7 @@ type CParamsParams struct {
|
||||
ConstantinopleFixForkBlock *math.HexOrDecimal64 `json:"constantinopleFixForkBlock"`
|
||||
IstanbulBlock *math.HexOrDecimal64 `json:"istanbulForkBlock"`
|
||||
RamanujanForkBlock *math.HexOrDecimal64 `json:"ramanujanForkBlock"`
|
||||
MirrorSyncForkBlock *math.HexOrDecimal64 `json:"mirrorSyncForkBlock"`
|
||||
ChainID *math.HexOrDecimal256 `json:"chainID"`
|
||||
MaximumExtraDataSize math.HexOrDecimal64 `json:"maximumExtraDataSize"`
|
||||
TieBreakingGas bool `json:"tieBreakingGas"`
|
||||
@@ -325,6 +326,7 @@ func (api *RetestethAPI) SetChainParams(ctx context.Context, chainParams ChainPa
|
||||
petersburgBlock *big.Int
|
||||
istanbulBlock *big.Int
|
||||
ramanujanBlock *big.Int
|
||||
mirrorSyncBlock *big.Int
|
||||
)
|
||||
if chainParams.Params.HomesteadForkBlock != nil {
|
||||
homesteadBlock = big.NewInt(int64(*chainParams.Params.HomesteadForkBlock))
|
||||
@@ -357,6 +359,9 @@ func (api *RetestethAPI) SetChainParams(ctx context.Context, chainParams ChainPa
|
||||
if chainParams.Params.RamanujanForkBlock != nil {
|
||||
ramanujanBlock = big.NewInt(int64(*chainParams.Params.RamanujanForkBlock))
|
||||
}
|
||||
if chainParams.Params.MirrorSyncForkBlock != nil {
|
||||
mirrorSyncBlock = big.NewInt(int64(*chainParams.Params.MirrorSyncForkBlock))
|
||||
}
|
||||
|
||||
genesis := &core.Genesis{
|
||||
Config: ¶ms.ChainConfig{
|
||||
@@ -372,6 +377,7 @@ func (api *RetestethAPI) SetChainParams(ctx context.Context, chainParams ChainPa
|
||||
PetersburgBlock: petersburgBlock,
|
||||
IstanbulBlock: istanbulBlock,
|
||||
RamanujanBlock: ramanujanBlock,
|
||||
MirrorSyncBlock: mirrorSyncBlock,
|
||||
},
|
||||
Nonce: uint64(chainParams.Genesis.Nonce),
|
||||
Timestamp: uint64(chainParams.Genesis.Timestamp),
|
||||
|
||||
@@ -304,16 +304,16 @@ func generateDataset(dest []uint32, epoch uint64, cache []uint32) {
|
||||
keccak512 := makeHasher(sha3.NewLegacyKeccak512())
|
||||
|
||||
// Calculate the data segment this thread should generate
|
||||
batch := uint32((size + hashBytes*uint64(threads) - 1) / (hashBytes * uint64(threads)))
|
||||
first := uint32(id) * batch
|
||||
batch := (size + hashBytes*uint64(threads) - 1) / (hashBytes * uint64(threads))
|
||||
first := uint64(id) * batch
|
||||
limit := first + batch
|
||||
if limit > uint32(size/hashBytes) {
|
||||
limit = uint32(size / hashBytes)
|
||||
if limit > size/hashBytes {
|
||||
limit = size / hashBytes
|
||||
}
|
||||
// Calculate the dataset segment
|
||||
percent := uint32(size / hashBytes / 100)
|
||||
for index := first; index < limit; index++ {
|
||||
item := generateDatasetItem(cache, index, keccak512)
|
||||
item := generateDatasetItem(cache, uint32(index), keccak512)
|
||||
if swapped {
|
||||
swap(item)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package parlia
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -25,6 +26,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/consensus"
|
||||
"github.com/ethereum/go-ethereum/consensus/misc"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/forkid"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/systemcontracts"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
@@ -45,8 +47,9 @@ const (
|
||||
checkpointInterval = 1024 // Number of blocks after which to save the snapshot to the database
|
||||
defaultEpochLength = uint64(100) // Default number of blocks of checkpoint to update validatorSet from contract
|
||||
|
||||
extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity
|
||||
extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal
|
||||
extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity
|
||||
extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal
|
||||
nextForkHashSize = 4 // Fixed number of extra-data suffix bytes reserved for nextForkHash.
|
||||
|
||||
validatorBytesLength = common.AddressLength
|
||||
wiggleTime = uint64(1) // second, Random delay (per signer) to allow concurrent signers
|
||||
@@ -188,7 +191,8 @@ func ParliaRLP(header *types.Header, chainId *big.Int) []byte {
|
||||
type Parlia struct {
|
||||
chainConfig *params.ChainConfig // Chain config
|
||||
config *params.ParliaConfig // Consensus engine configuration parameters for parlia consensus
|
||||
db ethdb.Database // Database to store and retrieve snapshot checkpoints
|
||||
genesisHash common.Hash
|
||||
db ethdb.Database // Database to store and retrieve snapshot checkpoints
|
||||
|
||||
recentSnaps *lru.ARCCache // Snapshots for recent block to speed up
|
||||
signatures *lru.ARCCache // Signatures of recent blocks to speed up mining
|
||||
@@ -214,6 +218,7 @@ func New(
|
||||
chainConfig *params.ChainConfig,
|
||||
db ethdb.Database,
|
||||
ethAPI *ethapi.PublicBlockChainAPI,
|
||||
genesisHash common.Hash,
|
||||
) *Parlia {
|
||||
// get parlia config
|
||||
parliaConfig := chainConfig.Parlia
|
||||
@@ -243,6 +248,7 @@ func New(
|
||||
c := &Parlia{
|
||||
chainConfig: chainConfig,
|
||||
config: parliaConfig,
|
||||
genesisHash: genesisHash,
|
||||
db: db,
|
||||
ethAPI: ethAPI,
|
||||
recentSnaps: recentSnaps,
|
||||
@@ -599,10 +605,12 @@ func (p *Parlia) Prepare(chain consensus.ChainReader, header *types.Header) erro
|
||||
header.Difficulty = CalcDifficulty(snap, p.val)
|
||||
|
||||
// Ensure the extra data has all it's components
|
||||
if len(header.Extra) < extraVanity {
|
||||
header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-len(header.Extra))...)
|
||||
if len(header.Extra) < extraVanity-nextForkHashSize {
|
||||
header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-nextForkHashSize-len(header.Extra))...)
|
||||
}
|
||||
header.Extra = header.Extra[:extraVanity]
|
||||
header.Extra = header.Extra[:extraVanity-nextForkHashSize]
|
||||
nextForkHash := forkid.NextForkHash(p.chainConfig, p.genesisHash, number)
|
||||
header.Extra = append(header.Extra, nextForkHash[:]...)
|
||||
|
||||
if number%p.config.Epoch == 0 {
|
||||
newValidators, err := p.getCurrentValidators(header.ParentHash)
|
||||
@@ -638,6 +646,16 @@ func (p *Parlia) Prepare(chain consensus.ChainReader, header *types.Header) erro
|
||||
// rewards given.
|
||||
func (p *Parlia) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction,
|
||||
uncles []*types.Header, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, usedGas *uint64) error {
|
||||
// warn if not in majority fork
|
||||
number := header.Number.Uint64()
|
||||
snap, err := p.snapshot(chain, number-1, header.ParentHash, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
nextForkHash := forkid.NextForkHash(p.chainConfig, p.genesisHash, number)
|
||||
if !snap.isMajorityFork(hex.EncodeToString(nextForkHash[:])) {
|
||||
log.Warn("there is a possible fork, and your client is not the majority. Please check...", "nextForkHash", hex.EncodeToString(nextForkHash[:]))
|
||||
}
|
||||
// If the block is a epoch end block, verify the validator list
|
||||
// The verification can only be done when the state is ready, it can't be done in VerifyHeader.
|
||||
if header.Number.Uint64()%p.config.Epoch == 0 {
|
||||
@@ -666,11 +684,6 @@ func (p *Parlia) Finalize(chain consensus.ChainReader, header *types.Header, sta
|
||||
}
|
||||
}
|
||||
if header.Difficulty.Cmp(diffInTurn) != 0 {
|
||||
number := header.Number.Uint64()
|
||||
snap, err := p.snapshot(chain, number-1, header.ParentHash, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
spoiledVal := snap.supposeValidator()
|
||||
signedRecently := false
|
||||
for _, recent := range snap.Recents {
|
||||
@@ -680,7 +693,7 @@ func (p *Parlia) Finalize(chain consensus.ChainReader, header *types.Header, sta
|
||||
}
|
||||
}
|
||||
if !signedRecently {
|
||||
log.Info("slash validator", "block hash", header.Hash(), "address", spoiledVal)
|
||||
log.Trace("slash validator", "block hash", header.Hash(), "address", spoiledVal)
|
||||
err = p.slash(spoiledVal, state, header, cx, txs, receipts, systemTxs, usedGas, false)
|
||||
if err != nil {
|
||||
// it is possible that slash validator failed because of the slash channel is disabled.
|
||||
@@ -689,7 +702,7 @@ func (p *Parlia) Finalize(chain consensus.ChainReader, header *types.Header, sta
|
||||
}
|
||||
}
|
||||
val := header.Coinbase
|
||||
err := p.distributeIncoming(val, state, header, cx, txs, receipts, systemTxs, usedGas, false)
|
||||
err = p.distributeIncoming(val, state, header, cx, txs, receipts, systemTxs, usedGas, false)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -947,11 +960,11 @@ func (p *Parlia) distributeIncoming(val common.Address, state *state.StateDB, he
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Info("distribute to system reward pool", "block hash", header.Hash(), "amount", rewards)
|
||||
log.Trace("distribute to system reward pool", "block hash", header.Hash(), "amount", rewards)
|
||||
balance = balance.Sub(balance, rewards)
|
||||
}
|
||||
}
|
||||
log.Info("distribute to validator contract", "block hash", header.Hash(), "amount", balance)
|
||||
log.Trace("distribute to validator contract", "block hash", header.Hash(), "amount", balance)
|
||||
return p.distributeToValidator(balance, val, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
|
||||
}
|
||||
|
||||
@@ -999,7 +1012,7 @@ func (p *Parlia) initContract(state *state.StateDB, header *types.Header, chain
|
||||
for _, c := range contracts {
|
||||
msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(c), data, common.Big0)
|
||||
// apply message
|
||||
log.Info("init contract", "block hash", header.Hash(), "contract", c)
|
||||
log.Trace("init contract", "block hash", header.Hash(), "contract", c)
|
||||
err = p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -18,6 +18,7 @@ package parlia
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math/big"
|
||||
@@ -38,10 +39,11 @@ type Snapshot struct {
|
||||
ethAPI *ethapi.PublicBlockChainAPI
|
||||
sigCache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover
|
||||
|
||||
Number uint64 `json:"number"` // Block number where the snapshot was created
|
||||
Hash common.Hash `json:"hash"` // Block hash where the snapshot was created
|
||||
Validators map[common.Address]struct{} `json:"validators"` // Set of authorized validators at this moment
|
||||
Recents map[uint64]common.Address `json:"recents"` // Set of recent validators for spam protections
|
||||
Number uint64 `json:"number"` // Block number where the snapshot was created
|
||||
Hash common.Hash `json:"hash"` // Block hash where the snapshot was created
|
||||
Validators map[common.Address]struct{} `json:"validators"` // Set of authorized validators at this moment
|
||||
Recents map[uint64]common.Address `json:"recents"` // Set of recent validators for spam protections
|
||||
RecentForkHashes map[uint64]string `json:"recent_fork_hashes"` // Set of recent forkHash
|
||||
}
|
||||
|
||||
// newSnapshot creates a new snapshot with the specified startup parameters. This
|
||||
@@ -56,13 +58,14 @@ func newSnapshot(
|
||||
ethAPI *ethapi.PublicBlockChainAPI,
|
||||
) *Snapshot {
|
||||
snap := &Snapshot{
|
||||
config: config,
|
||||
ethAPI: ethAPI,
|
||||
sigCache: sigCache,
|
||||
Number: number,
|
||||
Hash: hash,
|
||||
Recents: make(map[uint64]common.Address),
|
||||
Validators: make(map[common.Address]struct{}),
|
||||
config: config,
|
||||
ethAPI: ethAPI,
|
||||
sigCache: sigCache,
|
||||
Number: number,
|
||||
Hash: hash,
|
||||
Recents: make(map[uint64]common.Address),
|
||||
RecentForkHashes: make(map[uint64]string),
|
||||
Validators: make(map[common.Address]struct{}),
|
||||
}
|
||||
for _, v := range validators {
|
||||
snap.Validators[v] = struct{}{}
|
||||
@@ -106,13 +109,14 @@ func (s *Snapshot) store(db ethdb.Database) error {
|
||||
// copy creates a deep copy of the snapshot
|
||||
func (s *Snapshot) copy() *Snapshot {
|
||||
cpy := &Snapshot{
|
||||
config: s.config,
|
||||
ethAPI: s.ethAPI,
|
||||
sigCache: s.sigCache,
|
||||
Number: s.Number,
|
||||
Hash: s.Hash,
|
||||
Validators: make(map[common.Address]struct{}),
|
||||
Recents: make(map[uint64]common.Address),
|
||||
config: s.config,
|
||||
ethAPI: s.ethAPI,
|
||||
sigCache: s.sigCache,
|
||||
Number: s.Number,
|
||||
Hash: s.Hash,
|
||||
Validators: make(map[common.Address]struct{}),
|
||||
Recents: make(map[uint64]common.Address),
|
||||
RecentForkHashes: make(map[uint64]string),
|
||||
}
|
||||
|
||||
for v := range s.Validators {
|
||||
@@ -121,9 +125,22 @@ func (s *Snapshot) copy() *Snapshot {
|
||||
for block, v := range s.Recents {
|
||||
cpy.Recents[block] = v
|
||||
}
|
||||
for block, id := range s.RecentForkHashes {
|
||||
cpy.RecentForkHashes[block] = id
|
||||
}
|
||||
return cpy
|
||||
}
|
||||
|
||||
func (s *Snapshot) isMajorityFork(forkHash string) bool {
|
||||
ally := 0
|
||||
for _, h := range s.RecentForkHashes {
|
||||
if h == forkHash {
|
||||
ally++
|
||||
}
|
||||
}
|
||||
return ally > len(s.RecentForkHashes)/2
|
||||
}
|
||||
|
||||
func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainReader, parents []*types.Header, chainId *big.Int) (*Snapshot, error) {
|
||||
// Allow passing in no headers for cleaner code
|
||||
if len(headers) == 0 {
|
||||
@@ -153,6 +170,9 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainReader, p
|
||||
if limit := uint64(len(snap.Validators)/2 + 1); number >= limit {
|
||||
delete(snap.Recents, number-limit)
|
||||
}
|
||||
if limit := uint64(len(snap.Validators)); number >= limit {
|
||||
delete(snap.RecentForkHashes, number-limit)
|
||||
}
|
||||
// Resolve the authorization key and check against signers
|
||||
validator, err := ecrecover(header, s.sigCache, chainId)
|
||||
if err != nil {
|
||||
@@ -191,8 +211,16 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainReader, p
|
||||
delete(snap.Recents, number-uint64(newLimit)-uint64(i))
|
||||
}
|
||||
}
|
||||
oldLimit = len(snap.Validators)
|
||||
newLimit = len(newVals)
|
||||
if newLimit < oldLimit {
|
||||
for i := 0; i < oldLimit-newLimit; i++ {
|
||||
delete(snap.RecentForkHashes, number-uint64(newLimit)-uint64(i))
|
||||
}
|
||||
}
|
||||
snap.Validators = newVals
|
||||
}
|
||||
snap.RecentForkHashes[number] = hex.EncodeToString(header.Extra[extraVanity-nextForkHashSize : extraVanity])
|
||||
}
|
||||
snap.Number += uint64(len(headers))
|
||||
snap.Hash = headers[len(headers)-1].Hash()
|
||||
|
||||
@@ -62,6 +62,28 @@ func NewID(chain *core.BlockChain) ID {
|
||||
)
|
||||
}
|
||||
|
||||
func NextForkHash(config *params.ChainConfig, genesis common.Hash, head uint64) [4]byte {
|
||||
// Calculate the starting checksum from the genesis hash
|
||||
hash := crc32.ChecksumIEEE(genesis[:])
|
||||
|
||||
// Calculate the current fork checksum and the next fork block
|
||||
var next uint64
|
||||
for _, fork := range gatherForks(config) {
|
||||
if fork <= head {
|
||||
// Fork already passed, checksum the previous hash and the fork number
|
||||
hash = checksumUpdate(hash, fork)
|
||||
continue
|
||||
}
|
||||
next = fork
|
||||
break
|
||||
}
|
||||
if next == 0 {
|
||||
return checksumToBytes(hash)
|
||||
} else {
|
||||
return checksumToBytes(checksumUpdate(hash, next))
|
||||
}
|
||||
}
|
||||
|
||||
// newID is the internal version of NewID, which takes extracted values as its
|
||||
// arguments instead of a chain. The reason is to allow testing the IDs without
|
||||
// having to simulate an entire blockchain.
|
||||
|
||||
@@ -256,6 +256,8 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
|
||||
return params.RinkebyChainConfig
|
||||
case ghash == params.GoerliGenesisHash:
|
||||
return params.GoerliChainConfig
|
||||
case ghash == params.BSCGenesisHash:
|
||||
return params.BSCChainConfig
|
||||
case ghash == params.ChapelGenesisHash:
|
||||
return params.ChapelChainConfig
|
||||
case ghash == params.RialtoGenesisHash:
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -814,6 +814,7 @@ func (pool *TxPool) addTxs(txs []*types.Transaction, local, sync bool) []error {
|
||||
nilSlot++
|
||||
}
|
||||
errs[nilSlot] = err
|
||||
nilSlot++
|
||||
}
|
||||
// Reorg the pool internals if needed and return
|
||||
done := pool.requestPromoteExecutables(dirtyAddrs)
|
||||
|
||||
@@ -158,7 +158,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
||||
|
||||
eth.APIBackend = &EthAPIBackend{ctx.ExtRPCEnabled(), eth, nil}
|
||||
ethAPI := ethapi.NewPublicBlockChainAPI(eth.APIBackend)
|
||||
eth.engine = CreateConsensusEngine(ctx, chainConfig, &config.Ethash, config.Miner.Notify, config.Miner.Noverify, chainDb, ethAPI)
|
||||
eth.engine = CreateConsensusEngine(ctx, chainConfig, &config.Ethash, config.Miner.Notify, config.Miner.Noverify, chainDb, ethAPI, genesisHash)
|
||||
|
||||
bcVersion := rawdb.ReadDatabaseVersion(chainDb)
|
||||
var dbVer = "<nil>"
|
||||
@@ -243,21 +243,21 @@ func makeExtraData(extra []byte) []byte {
|
||||
runtime.GOOS,
|
||||
})
|
||||
}
|
||||
if uint64(len(extra)) > params.MaximumExtraDataSize {
|
||||
log.Warn("Miner extra data exceed limit", "extra", hexutil.Bytes(extra), "limit", params.MaximumExtraDataSize)
|
||||
if uint64(len(extra)) > params.MaximumExtraDataSize-params.ForkIDSize {
|
||||
log.Warn("Miner extra data exceed limit", "extra", hexutil.Bytes(extra), "limit", params.MaximumExtraDataSize-params.ForkIDSize)
|
||||
extra = nil
|
||||
}
|
||||
return extra
|
||||
}
|
||||
|
||||
// CreateConsensusEngine creates the required type of consensus engine instance for an Ethereum service
|
||||
func CreateConsensusEngine(ctx *node.ServiceContext, chainConfig *params.ChainConfig, config *ethash.Config, notify []string, noverify bool, db ethdb.Database, ee *ethapi.PublicBlockChainAPI) consensus.Engine {
|
||||
func CreateConsensusEngine(ctx *node.ServiceContext, chainConfig *params.ChainConfig, config *ethash.Config, notify []string, noverify bool, db ethdb.Database, ee *ethapi.PublicBlockChainAPI, genesisHash common.Hash) consensus.Engine {
|
||||
// If proof-of-authority is requested, set it up
|
||||
if chainConfig.Clique != nil {
|
||||
return clique.New(chainConfig.Clique, db)
|
||||
}
|
||||
if chainConfig.Parlia != nil {
|
||||
return parlia.New(chainConfig, db, ee)
|
||||
return parlia.New(chainConfig, db, ee, genesisHash)
|
||||
}
|
||||
// Otherwise assume proof-of-work
|
||||
switch config.PowMode {
|
||||
|
||||
@@ -61,8 +61,9 @@ var DefaultConfig = Config{
|
||||
},
|
||||
TxPool: core.DefaultTxPoolConfig,
|
||||
GPO: gasprice.Config{
|
||||
Blocks: 20,
|
||||
Percentile: 60,
|
||||
Blocks: 20,
|
||||
Percentile: 60,
|
||||
OracleThreshold: 1000,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -107,20 +107,16 @@ func (api *PublicFilterAPI) NewPendingTransactionFilter() rpc.ID {
|
||||
pendingTxs = make(chan []common.Hash)
|
||||
pendingTxSub = api.events.SubscribePendingTxs(pendingTxs)
|
||||
)
|
||||
|
||||
f := &filter{typ: PendingTransactionsSubscription, deadline: time.NewTimer(deadline), hashes: make([]common.Hash, 0), s: pendingTxSub}
|
||||
api.filtersMu.Lock()
|
||||
api.filters[pendingTxSub.ID] = &filter{typ: PendingTransactionsSubscription, deadline: time.NewTimer(deadline), hashes: make([]common.Hash, 0), s: pendingTxSub}
|
||||
api.filters[pendingTxSub.ID] = f
|
||||
api.filtersMu.Unlock()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case ph := <-pendingTxs:
|
||||
api.filtersMu.Lock()
|
||||
if f, found := api.filters[pendingTxSub.ID]; found {
|
||||
f.hashes = append(f.hashes, ph...)
|
||||
}
|
||||
api.filtersMu.Unlock()
|
||||
f.hashes = append(f.hashes, ph...)
|
||||
case <-pendingTxSub.Err():
|
||||
api.filtersMu.Lock()
|
||||
delete(api.filters, pendingTxSub.ID)
|
||||
|
||||
@@ -174,6 +174,17 @@ func (sub *Subscription) Unsubscribe() {
|
||||
// this ensures that the manager won't use the event channel which
|
||||
// will probably be closed by the client asap after this method returns.
|
||||
<-sub.Err()
|
||||
|
||||
drainLoop:
|
||||
for {
|
||||
select {
|
||||
case <-sub.f.logs:
|
||||
case <-sub.f.hashes:
|
||||
case <-sub.f.headers:
|
||||
default:
|
||||
break drainLoop
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -32,9 +32,10 @@ import (
|
||||
var maxPrice = big.NewInt(500 * params.GWei)
|
||||
|
||||
type Config struct {
|
||||
Blocks int
|
||||
Percentile int
|
||||
Default *big.Int `toml:",omitempty"`
|
||||
Blocks int
|
||||
Percentile int
|
||||
Default *big.Int `toml:",omitempty"`
|
||||
OracleThreshold int `toml:",omitempty"`
|
||||
}
|
||||
|
||||
// Oracle recommends gas prices based on the content of recent
|
||||
@@ -46,6 +47,9 @@ type Oracle struct {
|
||||
cacheLock sync.RWMutex
|
||||
fetchLock sync.Mutex
|
||||
|
||||
defaultPrice *big.Int
|
||||
sampleTxThreshold int
|
||||
|
||||
checkBlocks, maxEmpty, maxBlocks int
|
||||
percentile int
|
||||
}
|
||||
@@ -64,12 +68,14 @@ func NewOracle(backend ethapi.Backend, params Config) *Oracle {
|
||||
percent = 100
|
||||
}
|
||||
return &Oracle{
|
||||
backend: backend,
|
||||
lastPrice: params.Default,
|
||||
checkBlocks: blocks,
|
||||
maxEmpty: blocks / 2,
|
||||
maxBlocks: blocks * 5,
|
||||
percentile: percent,
|
||||
backend: backend,
|
||||
lastPrice: params.Default,
|
||||
defaultPrice: params.Default,
|
||||
checkBlocks: blocks,
|
||||
maxEmpty: blocks / 2,
|
||||
maxBlocks: blocks * 5,
|
||||
percentile: percent,
|
||||
sampleTxThreshold: params.OracleThreshold,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +109,7 @@ func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) {
|
||||
sent := 0
|
||||
exp := 0
|
||||
var blockPrices []*big.Int
|
||||
var totalTxSamples int
|
||||
for sent < gpo.checkBlocks && blockNum > 0 {
|
||||
go gpo.getBlockPrices(ctx, types.MakeSigner(gpo.backend.ChainConfig(), big.NewInt(int64(blockNum))), blockNum, ch)
|
||||
sent++
|
||||
@@ -118,6 +125,7 @@ func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) {
|
||||
exp--
|
||||
if res.price != nil {
|
||||
blockPrices = append(blockPrices, res.price)
|
||||
totalTxSamples = totalTxSamples + res.number
|
||||
continue
|
||||
}
|
||||
if maxEmpty > 0 {
|
||||
@@ -132,9 +140,11 @@ func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) {
|
||||
}
|
||||
}
|
||||
price := lastPrice
|
||||
if len(blockPrices) > 0 {
|
||||
if len(blockPrices) > 0 && totalTxSamples > gpo.sampleTxThreshold {
|
||||
sort.Sort(bigIntArray(blockPrices))
|
||||
price = blockPrices[(len(blockPrices)-1)*gpo.percentile/100]
|
||||
} else {
|
||||
price = gpo.defaultPrice
|
||||
}
|
||||
if price.Cmp(maxPrice) > 0 {
|
||||
price = new(big.Int).Set(maxPrice)
|
||||
@@ -148,8 +158,9 @@ func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) {
|
||||
}
|
||||
|
||||
type getBlockPricesResult struct {
|
||||
price *big.Int
|
||||
err error
|
||||
number int
|
||||
price *big.Int
|
||||
err error
|
||||
}
|
||||
|
||||
type transactionsByGasPrice []*types.Transaction
|
||||
@@ -163,7 +174,7 @@ func (t transactionsByGasPrice) Less(i, j int) bool { return t[i].GasPrice().Cmp
|
||||
func (gpo *Oracle) getBlockPrices(ctx context.Context, signer types.Signer, blockNum uint64, ch chan getBlockPricesResult) {
|
||||
block, err := gpo.backend.BlockByNumber(ctx, rpc.BlockNumber(blockNum))
|
||||
if block == nil {
|
||||
ch <- getBlockPricesResult{nil, err}
|
||||
ch <- getBlockPricesResult{0, nil, err}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -175,11 +186,11 @@ func (gpo *Oracle) getBlockPrices(ctx context.Context, signer types.Signer, bloc
|
||||
for _, tx := range txs {
|
||||
sender, err := types.Sender(signer, tx)
|
||||
if err == nil && sender != block.Coinbase() {
|
||||
ch <- getBlockPricesResult{tx.GasPrice(), nil}
|
||||
ch <- getBlockPricesResult{len(txs), tx.GasPrice(), nil}
|
||||
return
|
||||
}
|
||||
}
|
||||
ch <- getBlockPricesResult{nil, nil}
|
||||
ch <- getBlockPricesResult{0, nil, nil}
|
||||
}
|
||||
|
||||
type bigIntArray []*big.Int
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -132,13 +132,12 @@
|
||||
// If the call was a contract call, retrieve the gas usage and output
|
||||
if (call.gas !== undefined) {
|
||||
call.gasUsed = '0x' + bigInt(call.gasIn - call.gasCost + call.gas - log.getGas()).toString(16);
|
||||
|
||||
var ret = log.stack.peek(0);
|
||||
if (!ret.equals(0)) {
|
||||
call.output = toHex(log.memory.slice(call.outOff, call.outOff + call.outLen));
|
||||
} else if (call.error === undefined) {
|
||||
call.error = "internal failure"; // TODO(karalabe): surface these faults somehow
|
||||
}
|
||||
}
|
||||
var ret = log.stack.peek(0);
|
||||
if (!ret.equals(0)) {
|
||||
call.output = toHex(log.memory.slice(call.outOff, call.outOff + call.outLen));
|
||||
} else if (call.error === undefined) {
|
||||
call.error = "internal failure"; // TODO(karalabe): surface these faults somehow
|
||||
}
|
||||
delete call.gasIn; delete call.gasCost;
|
||||
delete call.outOff; delete call.outLen;
|
||||
@@ -208,7 +207,7 @@
|
||||
} else if (ctx.error !== undefined) {
|
||||
result.error = ctx.error;
|
||||
}
|
||||
if (result.error !== undefined) {
|
||||
if (result.error !== undefined && (result.error !== "execution reverted" || result.output ==="0x")) {
|
||||
delete result.output;
|
||||
}
|
||||
return this.finalize(result);
|
||||
|
||||
72
eth/tracers/testdata/call_tracer_inner_instafail.json
vendored
Normal file
72
eth/tracers/testdata/call_tracer_inner_instafail.json
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"genesis": {
|
||||
"difficulty": "117067574",
|
||||
"extraData": "0xd783010502846765746887676f312e372e33856c696e7578",
|
||||
"gasLimit": "4712380",
|
||||
"hash": "0xe05db05eeb3f288041ecb10a787df121c0ed69499355716e17c307de313a4486",
|
||||
"miner": "0x0c062b329265c965deef1eede55183b3acb8f611",
|
||||
"mixHash": "0xb669ae39118a53d2c65fd3b1e1d3850dd3f8c6842030698ed846a2762d68b61d",
|
||||
"nonce": "0x2b469722b8e28c45",
|
||||
"number": "24973",
|
||||
"stateRoot": "0x532a5c3f75453a696428db078e32ae283c85cb97e4d8560dbdf022adac6df369",
|
||||
"timestamp": "1479891145",
|
||||
"totalDifficulty": "1892250259406",
|
||||
"alloc": {
|
||||
"0x6c06b16512b332e6cd8293a2974872674716ce18": {
|
||||
"balance": "0x0",
|
||||
"nonce": "1",
|
||||
"code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900480632e1a7d4d146036575b6000565b34600057604e60048080359060200190919050506050565b005b3373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051809050600060405180830381858888f19350505050505b5056",
|
||||
"storage": {}
|
||||
},
|
||||
"0x66fdfd05e46126a07465ad24e40cc0597bc1ef31": {
|
||||
"balance": "0x229ebbb36c3e0f20",
|
||||
"nonce": "3",
|
||||
"code": "0x",
|
||||
"storage": {}
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"chainId": 3,
|
||||
"homesteadBlock": 0,
|
||||
"daoForkSupport": true,
|
||||
"eip150Block": 0,
|
||||
"eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d",
|
||||
"eip155Block": 10,
|
||||
"eip158Block": 10,
|
||||
"byzantiumBlock": 1700000,
|
||||
"constantinopleBlock": 4230000,
|
||||
"petersburgBlock": 4939394,
|
||||
"istanbulBlock": 6485846,
|
||||
"muirGlacierBlock": 7117117,
|
||||
"ethash": {}
|
||||
}
|
||||
},
|
||||
"context": {
|
||||
"number": "24974",
|
||||
"difficulty": "117067574",
|
||||
"timestamp": "1479891162",
|
||||
"gasLimit": "4712388",
|
||||
"miner": "0xc822ef32e6d26e170b70cf761e204c1806265914"
|
||||
},
|
||||
"input": "0xf889038504a81557008301f97e946c06b16512b332e6cd8293a2974872674716ce1880a42e1a7d4d00000000000000000000000000000000000000000000000014d1120d7b1600002aa0e2a6558040c5d72bc59f2fb62a38993a314c849cd22fb393018d2c5af3112095a01bdb6d7ba32263ccc2ecc880d38c49d9f0c5a72d8b7908e3122b31356d349745",
|
||||
"result": {
|
||||
"type": "CALL",
|
||||
"from": "0x66fdfd05e46126a07465ad24e40cc0597bc1ef31",
|
||||
"to": "0x6c06b16512b332e6cd8293a2974872674716ce18",
|
||||
"value": "0x0",
|
||||
"gas": "0x1a466",
|
||||
"gasUsed": "0x1dc6",
|
||||
"input": "0x2e1a7d4d00000000000000000000000000000000000000000000000014d1120d7b160000",
|
||||
"output": "0x",
|
||||
"calls": [
|
||||
{
|
||||
"type": "CALL",
|
||||
"from": "0x6c06b16512b332e6cd8293a2974872674716ce18",
|
||||
"to": "0x66fdfd05e46126a07465ad24e40cc0597bc1ef31",
|
||||
"value": "0x14d1120d7b160000",
|
||||
"error":"internal failure",
|
||||
"input": "0x"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
64
eth/tracers/testdata/call_tracer_revert_reason.json
vendored
Normal file
64
eth/tracers/testdata/call_tracer_revert_reason.json
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -269,9 +269,31 @@ func TestCallTracer(t *testing.T) {
|
||||
t.Fatalf("failed to unmarshal trace result: %v", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(ret, test.Result) {
|
||||
if !jsonEqual(ret, test.Result) {
|
||||
// uncomment this for easier debugging
|
||||
//have, _ := json.MarshalIndent(ret, "", " ")
|
||||
//want, _ := json.MarshalIndent(test.Result, "", " ")
|
||||
//t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", string(have), string(want))
|
||||
t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", ret, test.Result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// jsonEqual is similar to reflect.DeepEqual, but does a 'bounce' via json prior to
|
||||
// comparison
|
||||
func jsonEqual(x, y interface{}) bool {
|
||||
xTrace := new(callTrace)
|
||||
yTrace := new(callTrace)
|
||||
if xj, err := json.Marshal(x); err == nil {
|
||||
json.Unmarshal(xj, xTrace)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
if yj, err := json.Marshal(y); err == nil {
|
||||
json.Unmarshal(yj, yTrace)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
return reflect.DeepEqual(xTrace, yTrace)
|
||||
}
|
||||
|
||||
2
go.mod
2
go.mod
@@ -1,6 +1,6 @@
|
||||
module github.com/ethereum/go-ethereum
|
||||
|
||||
go 1.13
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/Azure/azure-pipeline-go v0.2.2 // indirect
|
||||
|
||||
@@ -887,6 +887,11 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNrOrHash
|
||||
hi uint64
|
||||
cap uint64
|
||||
)
|
||||
// Use zero address if sender unspecified.
|
||||
if args.From == nil {
|
||||
return 0, fmt.Errorf("missing from address")
|
||||
}
|
||||
// Determine the highest gas limit can be used during the estimation.
|
||||
if args.Gas != nil && uint64(*args.Gas) >= params.TxGas {
|
||||
hi = uint64(*args.Gas)
|
||||
} else {
|
||||
@@ -895,18 +900,45 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNrOrHash
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if block == nil {
|
||||
return 0, errors.New("block not found")
|
||||
}
|
||||
hi = block.GasLimit()
|
||||
}
|
||||
// Recap the highest gas limit with account's available balance.
|
||||
if args.GasPrice != nil && args.GasPrice.ToInt().BitLen() != 0 {
|
||||
state, _, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
balance := state.GetBalance(*args.From) // from can't be nil
|
||||
available := new(big.Int).Set(balance)
|
||||
if args.Value != nil {
|
||||
if args.Value.ToInt().Cmp(available) >= 0 {
|
||||
return 0, errors.New("insufficient funds for transfer")
|
||||
}
|
||||
available.Sub(available, args.Value.ToInt())
|
||||
}
|
||||
allowance := new(big.Int).Div(available, args.GasPrice.ToInt())
|
||||
|
||||
// If the allowance is larger than maximum uint64, skip checking
|
||||
if allowance.IsUint64() && hi > allowance.Uint64() {
|
||||
transfer := args.Value
|
||||
if transfer == nil {
|
||||
transfer = new(hexutil.Big)
|
||||
}
|
||||
log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance,
|
||||
"sent", transfer.ToInt(), "gasprice", args.GasPrice.ToInt(), "fundable", allowance)
|
||||
hi = allowance.Uint64()
|
||||
}
|
||||
}
|
||||
// Recap the highest gas allowance with specified gascap.
|
||||
if gasCap != nil && hi > gasCap.Uint64() {
|
||||
log.Warn("Caller gas above allowance, capping", "requested", hi, "cap", gasCap)
|
||||
hi = gasCap.Uint64()
|
||||
}
|
||||
cap = hi
|
||||
|
||||
// Use zero address if sender unspecified.
|
||||
if args.From == nil {
|
||||
args.From = new(common.Address)
|
||||
}
|
||||
// Create a helper to check if a gas allowance results in an executable transaction
|
||||
executable := func(gas uint64) bool {
|
||||
args.Gas = (*hexutil.Uint64)(&gas)
|
||||
|
||||
@@ -493,6 +493,13 @@ web3._extend({
|
||||
params: 1,
|
||||
inputFormatter: [web3._extend.formatters.inputTransactionFormatter]
|
||||
}),
|
||||
new web3._extend.Method({
|
||||
name: 'estimateGas',
|
||||
call: 'eth_estimateGas',
|
||||
params: 2,
|
||||
inputFormatter: [web3._extend.formatters.inputCallFormatter, web3._extend.formatters.inputBlockNumberFormatter],
|
||||
outputFormatter: web3._extend.utils.toDecimal
|
||||
}),
|
||||
new web3._extend.Method({
|
||||
name: 'submitTransaction',
|
||||
call: 'eth_submitTransaction',
|
||||
|
||||
@@ -102,7 +102,7 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
|
||||
eventMux: ctx.EventMux,
|
||||
reqDist: newRequestDistributor(peers, &mclock.System{}),
|
||||
accountManager: ctx.AccountManager,
|
||||
engine: eth.CreateConsensusEngine(ctx, chainConfig, &config.Ethash, nil, false, chainDb, nil),
|
||||
engine: eth.CreateConsensusEngine(ctx, chainConfig, &config.Ethash, nil, false, chainDb, nil, genesisHash),
|
||||
bloomRequests: make(chan chan *bloombits.Retrieval),
|
||||
bloomIndexer: eth.NewBloomIndexer(chainDb, params.BloomBitsBlocksClient, params.HelperTrieConfirmations),
|
||||
serverPool: newServerPool(chainDb, config.UltraLightServers),
|
||||
|
||||
@@ -582,6 +582,7 @@ func (h *serverHandler) handleMsg(p *clientPeer, wg *sync.WaitGroup) error {
|
||||
var (
|
||||
lastBHash common.Hash
|
||||
root common.Hash
|
||||
header *types.Header
|
||||
)
|
||||
reqCnt := len(req.Reqs)
|
||||
if accept(req.ReqID, uint64(reqCnt), MaxProofsFetch) {
|
||||
@@ -596,10 +597,6 @@ func (h *serverHandler) handleMsg(p *clientPeer, wg *sync.WaitGroup) error {
|
||||
return
|
||||
}
|
||||
// Look up the root hash belonging to the request
|
||||
var (
|
||||
header *types.Header
|
||||
trie state.Trie
|
||||
)
|
||||
if request.BHash != lastBHash {
|
||||
root, lastBHash = common.Hash{}, request.BHash
|
||||
|
||||
@@ -626,6 +623,7 @@ func (h *serverHandler) handleMsg(p *clientPeer, wg *sync.WaitGroup) error {
|
||||
// Open the account or storage trie for the request
|
||||
statedb := h.blockchain.StateCache()
|
||||
|
||||
var trie state.Trie
|
||||
switch len(request.AccKey) {
|
||||
case 0:
|
||||
// No account key specified, open an account trie
|
||||
|
||||
@@ -419,9 +419,20 @@ func (t *UDPv5) call(node *enode.Node, responseType byte, packet packetV5) *call
|
||||
|
||||
// callDone tells dispatch that the active call is done.
|
||||
func (t *UDPv5) callDone(c *callV5) {
|
||||
select {
|
||||
case t.callDoneCh <- c:
|
||||
case <-t.closeCtx.Done():
|
||||
// This needs a loop because further responses may be incoming until the
|
||||
// send to callDoneCh has completed. Such responses need to be discarded
|
||||
// in order to avoid blocking the dispatch loop.
|
||||
for {
|
||||
select {
|
||||
case <-c.ch:
|
||||
// late response, discard.
|
||||
case <-c.err:
|
||||
// late error, discard.
|
||||
case t.callDoneCh <- c:
|
||||
return
|
||||
case <-t.closeCtx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,10 @@ const (
|
||||
dbVersion = 9
|
||||
)
|
||||
|
||||
var (
|
||||
errInvalidIP = errors.New("invalid IP")
|
||||
)
|
||||
|
||||
var zeroIP = make(net.IP, 16)
|
||||
|
||||
// DB is the node database, storing previously seen nodes and any collected metadata about
|
||||
@@ -359,16 +363,25 @@ func (db *DB) expireNodes() {
|
||||
// LastPingReceived retrieves the time of the last ping packet received from
|
||||
// a remote node.
|
||||
func (db *DB) LastPingReceived(id ID, ip net.IP) time.Time {
|
||||
if ip = ip.To16(); ip == nil {
|
||||
return time.Time{}
|
||||
}
|
||||
return time.Unix(db.fetchInt64(nodeItemKey(id, ip, dbNodePing)), 0)
|
||||
}
|
||||
|
||||
// UpdateLastPingReceived updates the last time we tried contacting a remote node.
|
||||
func (db *DB) UpdateLastPingReceived(id ID, ip net.IP, instance time.Time) error {
|
||||
if ip = ip.To16(); ip == nil {
|
||||
return errInvalidIP
|
||||
}
|
||||
return db.storeInt64(nodeItemKey(id, ip, dbNodePing), instance.Unix())
|
||||
}
|
||||
|
||||
// LastPongReceived retrieves the time of the last successful pong from remote node.
|
||||
func (db *DB) LastPongReceived(id ID, ip net.IP) time.Time {
|
||||
if ip = ip.To16(); ip == nil {
|
||||
return time.Time{}
|
||||
}
|
||||
// Launch expirer
|
||||
db.ensureExpirer()
|
||||
return time.Unix(db.fetchInt64(nodeItemKey(id, ip, dbNodePong)), 0)
|
||||
@@ -376,26 +389,41 @@ func (db *DB) LastPongReceived(id ID, ip net.IP) time.Time {
|
||||
|
||||
// UpdateLastPongReceived updates the last pong time of a node.
|
||||
func (db *DB) UpdateLastPongReceived(id ID, ip net.IP, instance time.Time) error {
|
||||
if ip = ip.To16(); ip == nil {
|
||||
return errInvalidIP
|
||||
}
|
||||
return db.storeInt64(nodeItemKey(id, ip, dbNodePong), instance.Unix())
|
||||
}
|
||||
|
||||
// FindFails retrieves the number of findnode failures since bonding.
|
||||
func (db *DB) FindFails(id ID, ip net.IP) int {
|
||||
if ip = ip.To16(); ip == nil {
|
||||
return 0
|
||||
}
|
||||
return int(db.fetchInt64(nodeItemKey(id, ip, dbNodeFindFails)))
|
||||
}
|
||||
|
||||
// UpdateFindFails updates the number of findnode failures since bonding.
|
||||
func (db *DB) UpdateFindFails(id ID, ip net.IP, fails int) error {
|
||||
if ip = ip.To16(); ip == nil {
|
||||
return errInvalidIP
|
||||
}
|
||||
return db.storeInt64(nodeItemKey(id, ip, dbNodeFindFails), int64(fails))
|
||||
}
|
||||
|
||||
// FindFailsV5 retrieves the discv5 findnode failure counter.
|
||||
func (db *DB) FindFailsV5(id ID, ip net.IP) int {
|
||||
if ip = ip.To16(); ip == nil {
|
||||
return 0
|
||||
}
|
||||
return int(db.fetchInt64(v5Key(id, ip, dbNodeFindFails)))
|
||||
}
|
||||
|
||||
// UpdateFindFailsV5 stores the discv5 findnode failure counter.
|
||||
func (db *DB) UpdateFindFailsV5(id ID, ip net.IP, fails int) error {
|
||||
if ip = ip.To16(); ip == nil {
|
||||
return errInvalidIP
|
||||
}
|
||||
return db.storeInt64(v5Key(id, ip, dbNodeFindFails), int64(fails))
|
||||
}
|
||||
|
||||
|
||||
@@ -32,8 +32,9 @@ var (
|
||||
RinkebyGenesisHash = common.HexToHash("0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177")
|
||||
GoerliGenesisHash = common.HexToHash("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a")
|
||||
|
||||
BSCGenesisHash = common.HexToHash("0x0d21840abff46b96c84b2ac9e10e4f5cdaeb5693cb665db62a2f3b02d2d57b5b")
|
||||
ChapelGenesisHash = common.HexToHash("0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34")
|
||||
RialtoGenesisHash = common.HexToHash("0xaa1c1e0af675e846942719466ab72822eff51ebf8462ead0897ae1240e3c0da1")
|
||||
RialtoGenesisHash = common.HexToHash("0x005dc005bddd1967de6187c1c23be801eb7abdd80cebcc24f341b727b70311d6")
|
||||
)
|
||||
|
||||
// TrustedCheckpoints associates each known checkpoint with the genesis hash of
|
||||
@@ -213,6 +214,26 @@ var (
|
||||
Threshold: 2,
|
||||
}
|
||||
|
||||
BSCChainConfig = &ChainConfig{
|
||||
ChainID: big.NewInt(56),
|
||||
HomesteadBlock: big.NewInt(0),
|
||||
EIP150Block: big.NewInt(0),
|
||||
EIP155Block: big.NewInt(0),
|
||||
EIP158Block: big.NewInt(0),
|
||||
ByzantiumBlock: big.NewInt(0),
|
||||
ConstantinopleBlock: big.NewInt(0),
|
||||
PetersburgBlock: big.NewInt(0),
|
||||
IstanbulBlock: big.NewInt(0),
|
||||
MuirGlacierBlock: big.NewInt(0),
|
||||
RamanujanBlock: big.NewInt(0),
|
||||
NielsBlock: big.NewInt(0),
|
||||
MirrorSyncBlock: big.NewInt(0),
|
||||
Parlia: &ParliaConfig{
|
||||
Period: 3,
|
||||
Epoch: 200,
|
||||
},
|
||||
}
|
||||
|
||||
ChapelChainConfig = &ChainConfig{
|
||||
ChainID: big.NewInt(97),
|
||||
HomesteadBlock: big.NewInt(0),
|
||||
@@ -226,6 +247,7 @@ var (
|
||||
MuirGlacierBlock: big.NewInt(0),
|
||||
RamanujanBlock: big.NewInt(1010000),
|
||||
NielsBlock: big.NewInt(1014369),
|
||||
MirrorSyncBlock: big.NewInt(5582500),
|
||||
Parlia: &ParliaConfig{
|
||||
Period: 3,
|
||||
Epoch: 200,
|
||||
@@ -245,6 +267,7 @@ var (
|
||||
MuirGlacierBlock: big.NewInt(0),
|
||||
RamanujanBlock: big.NewInt(400),
|
||||
NielsBlock: big.NewInt(0),
|
||||
MirrorSyncBlock: big.NewInt(400),
|
||||
Parlia: &ParliaConfig{
|
||||
Period: 3,
|
||||
Epoch: 200,
|
||||
@@ -256,16 +279,16 @@ var (
|
||||
//
|
||||
// This configuration is intentionally not using keyed fields to force anyone
|
||||
// adding flags to the config to also have to set these fields.
|
||||
AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, new(EthashConfig), nil, nil}
|
||||
AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, new(EthashConfig), nil, nil}
|
||||
|
||||
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
|
||||
// and accepted by the Ethereum core developers into the Clique consensus.
|
||||
//
|
||||
// This configuration is intentionally not using keyed fields to force anyone
|
||||
// adding flags to the config to also have to set these fields.
|
||||
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil}
|
||||
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil}
|
||||
|
||||
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, new(EthashConfig), nil, nil}
|
||||
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, new(EthashConfig), nil, nil}
|
||||
TestRules = TestChainConfig.Rules(new(big.Int))
|
||||
)
|
||||
|
||||
@@ -339,6 +362,7 @@ type ChainConfig struct {
|
||||
EWASMBlock *big.Int `json:"ewasmBlock,omitempty" toml:",omitempty"` // EWASM switch block (nil = no fork, 0 = already activated)
|
||||
RamanujanBlock *big.Int `json:"ramanujanBlock,omitempty" toml:",omitempty"` // ramanujanBlock switch block (nil = no fork, 0 = already activated)
|
||||
NielsBlock *big.Int `json:"nielsBlock,omitempty" toml:",omitempty"` // nielsBlock switch block (nil = no fork, 0 = already activated)
|
||||
MirrorSyncBlock *big.Int `json:"mirrorSyncBlock,omitempty" toml:",omitempty"` // mirrorSyncBlock switch block (nil = no fork, 0 = already activated)
|
||||
|
||||
// Various consensus engines
|
||||
Ethash *EthashConfig `json:"ethash,omitempty" toml:",omitempty"`
|
||||
@@ -389,7 +413,7 @@ func (c *ChainConfig) String() string {
|
||||
default:
|
||||
engine = "unknown"
|
||||
}
|
||||
return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Ramanujan: %v, Niels: %v, Engine: %v}",
|
||||
return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Ramanujan: %v, Niels: %v, MirrorSync: %v, Engine: %v}",
|
||||
c.ChainID,
|
||||
c.HomesteadBlock,
|
||||
c.DAOForkBlock,
|
||||
@@ -404,6 +428,7 @@ func (c *ChainConfig) String() string {
|
||||
c.MuirGlacierBlock,
|
||||
c.RamanujanBlock,
|
||||
c.NielsBlock,
|
||||
c.MirrorSyncBlock,
|
||||
engine,
|
||||
)
|
||||
}
|
||||
@@ -463,6 +488,17 @@ func (c *ChainConfig) IsOnNiels(num *big.Int) bool {
|
||||
return configNumEqual(c.NielsBlock, num)
|
||||
}
|
||||
|
||||
// IsMirrorSync returns whether num is either equal to the MirrorSync fork block or greater.
|
||||
func (c *ChainConfig) IsMirrorSync(num *big.Int) bool {
|
||||
return isForked(c.MirrorSyncBlock, num)
|
||||
}
|
||||
|
||||
// IsOnMirrorSync returns whether num is equal to the MirrorSync fork block
|
||||
func (c *ChainConfig) IsOnMirrorSync(num *big.Int) bool {
|
||||
return configNumEqual(c.MirrorSyncBlock, num)
|
||||
}
|
||||
|
||||
|
||||
// IsMuirGlacier returns whether num is either equal to the Muir Glacier (EIP-2384) fork block or greater.
|
||||
func (c *ChainConfig) IsMuirGlacier(num *big.Int) bool {
|
||||
return isForked(c.MuirGlacierBlock, num)
|
||||
@@ -522,6 +558,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
|
||||
{"istanbulBlock", c.IstanbulBlock},
|
||||
{"muirGlacierBlock", c.MuirGlacierBlock},
|
||||
{"ramanujanBlock", c.RamanujanBlock},
|
||||
{"mirrorSyncBlock", c.MirrorSyncBlock},
|
||||
} {
|
||||
if lastFork.name != "" {
|
||||
// Next one must be higher number
|
||||
@@ -584,6 +621,9 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *Confi
|
||||
if isForkIncompatible(c.RamanujanBlock, newcfg.RamanujanBlock, head) {
|
||||
return newCompatError("ramanujan fork block", c.RamanujanBlock, newcfg.RamanujanBlock)
|
||||
}
|
||||
if isForkIncompatible(c.MirrorSyncBlock, newcfg.MirrorSyncBlock, head) {
|
||||
return newCompatError("mirrorSync fork block", c.MirrorSyncBlock, newcfg.MirrorSyncBlock)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ const (
|
||||
GenesisGasLimit uint64 = 4712388 // Gas limit of the Genesis block.
|
||||
|
||||
MaximumExtraDataSize uint64 = 32 // Maximum size extra data may be after Genesis.
|
||||
ForkIDSize uint64 = 4 // The length of fork id
|
||||
ExpByteGas uint64 = 10 // Times ceil(log256(exponent)) for the EXP instruction.
|
||||
SloadGas uint64 = 50 // Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added.
|
||||
CallValueTransferGas uint64 = 9000 // Paid for CALL when the value transfer is non-zero.
|
||||
|
||||
@@ -21,10 +21,10 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
VersionMajor = 1 // Major version component of the current release
|
||||
VersionMinor = 0 // Minor version component of the current release
|
||||
VersionPatch = 1 // Patch version component of the current release
|
||||
VersionMeta = "beta.2" // Version metadata to append to the version string
|
||||
VersionMajor = 1 // Major version component of the current release
|
||||
VersionMinor = 0 // Minor version component of the current release
|
||||
VersionPatch = 5 // Patch version component of the current release
|
||||
VersionMeta = "" // Version metadata to append to the version string
|
||||
)
|
||||
|
||||
// Version holds the textual version string.
|
||||
|
||||
@@ -552,9 +552,9 @@ func (c *Client) dispatch(codec ServerCodec) {
|
||||
// Read path:
|
||||
case op := <-c.readOp:
|
||||
if op.batch {
|
||||
conn.handler.handleBatch(op.msgs)
|
||||
conn.handler.handleBatch(context.Background(), op.msgs)
|
||||
} else {
|
||||
conn.handler.handleMsg(op.msgs[0])
|
||||
conn.handler.handleMsg(context.Background(), op.msgs[0])
|
||||
}
|
||||
|
||||
case err := <-c.readErr:
|
||||
|
||||
@@ -93,7 +93,7 @@ func newHandler(connCtx context.Context, conn jsonWriter, idgen func() ID, reg *
|
||||
}
|
||||
|
||||
// handleBatch executes all messages in a batch and returns the responses.
|
||||
func (h *handler) handleBatch(msgs []*jsonrpcMessage) {
|
||||
func (h *handler) handleBatch(ctx context.Context, msgs []*jsonrpcMessage) {
|
||||
// Emit error response for empty batches:
|
||||
if len(msgs) == 0 {
|
||||
h.startCallProc(func(cp *callProc) {
|
||||
@@ -116,7 +116,7 @@ func (h *handler) handleBatch(msgs []*jsonrpcMessage) {
|
||||
h.startCallProc(func(cp *callProc) {
|
||||
answers := make([]*jsonrpcMessage, 0, len(msgs))
|
||||
for _, msg := range calls {
|
||||
if answer := h.handleCallMsg(cp, msg); answer != nil {
|
||||
if answer := h.handleCallMsg(cp, ctx, msg); answer != nil {
|
||||
answers = append(answers, answer)
|
||||
}
|
||||
}
|
||||
@@ -131,12 +131,12 @@ func (h *handler) handleBatch(msgs []*jsonrpcMessage) {
|
||||
}
|
||||
|
||||
// handleMsg handles a single message.
|
||||
func (h *handler) handleMsg(msg *jsonrpcMessage) {
|
||||
func (h *handler) handleMsg(ctx context.Context, msg *jsonrpcMessage) {
|
||||
if ok := h.handleImmediate(msg); ok {
|
||||
return
|
||||
}
|
||||
h.startCallProc(func(cp *callProc) {
|
||||
answer := h.handleCallMsg(cp, msg)
|
||||
answer := h.handleCallMsg(cp, ctx, msg)
|
||||
h.addSubscriptions(cp.notifiers)
|
||||
if answer != nil {
|
||||
h.conn.writeJSON(cp.ctx, answer)
|
||||
@@ -287,7 +287,7 @@ func (h *handler) handleResponse(msg *jsonrpcMessage) {
|
||||
}
|
||||
|
||||
// handleCallMsg executes a call message and returns the answer.
|
||||
func (h *handler) handleCallMsg(ctx *callProc, msg *jsonrpcMessage) *jsonrpcMessage {
|
||||
func (h *handler) handleCallMsg(ctx *callProc, reqCtx context.Context, msg *jsonrpcMessage) *jsonrpcMessage {
|
||||
start := time.Now()
|
||||
switch {
|
||||
case msg.isNotification():
|
||||
@@ -297,7 +297,8 @@ func (h *handler) handleCallMsg(ctx *callProc, msg *jsonrpcMessage) *jsonrpcMess
|
||||
case msg.isCall():
|
||||
resp := h.handleCall(ctx, msg)
|
||||
if resp.Error != nil {
|
||||
h.log.Warn("Served "+msg.Method, "reqid", idForLog{msg.ID}, "t", time.Since(start), "err", resp.Error.Message)
|
||||
xForward := reqCtx.Value("X-Forwarded-For")
|
||||
h.log.Warn("Served "+msg.Method, "reqid", idForLog{msg.ID}, "t", time.Since(start), "err", resp.Error.Message, "X-Forwarded-For", xForward)
|
||||
} else {
|
||||
h.log.Debug("Served "+msg.Method, "reqid", idForLog{msg.ID}, "t", time.Since(start))
|
||||
}
|
||||
@@ -340,6 +341,7 @@ func (h *handler) handleCall(cp *callProc, msg *jsonrpcMessage) *jsonrpcMessage
|
||||
successfulRequestGauge.Inc(1)
|
||||
}
|
||||
rpcServingTimer.UpdateSince(start)
|
||||
newRPCRequestGauge(msg.Method).Inc(1)
|
||||
newRPCServingTimer(msg.Method, answer.Error == nil).UpdateSince(start)
|
||||
}
|
||||
return answer
|
||||
|
||||
@@ -227,6 +227,9 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if origin := r.Header.Get("Origin"); origin != "" {
|
||||
ctx = context.WithValue(ctx, "Origin", origin)
|
||||
}
|
||||
if xForward := r.Header.Get("X-Forwarded-For"); xForward != "" {
|
||||
ctx = context.WithValue(ctx, "X-Forwarded-For", xForward)
|
||||
}
|
||||
|
||||
w.Header().Set("content-type", contentType)
|
||||
codec := newHTTPServerConn(r, w)
|
||||
|
||||
13
rpc/json.go
13
rpc/json.go
@@ -194,15 +194,22 @@ func (c *jsonCodec) remoteAddr() string {
|
||||
return c.remote
|
||||
}
|
||||
|
||||
func (c *jsonCodec) readBatch() (msg []*jsonrpcMessage, batch bool, err error) {
|
||||
func (c *jsonCodec) readBatch() (messages []*jsonrpcMessage, batch bool, err error) {
|
||||
// Decode the next JSON object in the input stream.
|
||||
// This verifies basic syntax, etc.
|
||||
var rawmsg json.RawMessage
|
||||
if err := c.decode(&rawmsg); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
msg, batch = parseMessage(rawmsg)
|
||||
return msg, batch, nil
|
||||
messages, batch = parseMessage(rawmsg)
|
||||
for i, msg := range messages {
|
||||
if msg == nil {
|
||||
// Message is JSON 'null'. Replace with zero value so it
|
||||
// will be treated like any other invalid message.
|
||||
messages[i] = new(jsonrpcMessage)
|
||||
}
|
||||
}
|
||||
return messages, batch, nil
|
||||
}
|
||||
|
||||
func (c *jsonCodec) writeJSON(ctx context.Context, v interface{}) error {
|
||||
|
||||
@@ -37,3 +37,8 @@ func newRPCServingTimer(method string, valid bool) metrics.Timer {
|
||||
m := fmt.Sprintf("rpc/duration/%s/%s", method, flag)
|
||||
return metrics.GetOrRegisterTimer(m, nil)
|
||||
}
|
||||
|
||||
func newRPCRequestGauge(method string) metrics.Gauge {
|
||||
m := fmt.Sprintf("rpc/count/%s", method)
|
||||
return metrics.GetOrRegisterGauge(m, nil)
|
||||
}
|
||||
|
||||
@@ -109,9 +109,9 @@ func (s *Server) serveSingleRequest(ctx context.Context, codec ServerCodec) {
|
||||
return
|
||||
}
|
||||
if batch {
|
||||
h.handleBatch(reqs)
|
||||
h.handleBatch(ctx, reqs)
|
||||
} else {
|
||||
h.handleMsg(reqs[0])
|
||||
h.handleMsg(ctx, reqs[0])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
3
rpc/testdata/invalid-batch.js
vendored
3
rpc/testdata/invalid-batch.js
vendored
@@ -10,5 +10,8 @@
|
||||
--> [1,2,3]
|
||||
<-- [{"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"invalid request"}},{"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"invalid request"}},{"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"invalid request"}}]
|
||||
|
||||
--> [null]
|
||||
<-- [{"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"invalid request"}}]
|
||||
|
||||
--> [{"jsonrpc":"2.0","id":1,"method":"test_echo","params":["foo",1]},55,{"jsonrpc":"2.0","id":2,"method":"unknown_method"},{"foo":"bar"}]
|
||||
<-- [{"jsonrpc":"2.0","id":1,"result":{"String":"foo","Int":1,"Args":null}},{"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"invalid request"}},{"jsonrpc":"2.0","id":2,"error":{"code":-32601,"message":"the method unknown_method does not exist/is not available"}},{"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"invalid request"}}]
|
||||
|
||||
3
rpc/testdata/invalid-nonobj.js
vendored
3
rpc/testdata/invalid-nonobj.js
vendored
@@ -2,3 +2,6 @@
|
||||
|
||||
--> 1
|
||||
<-- {"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"invalid request"}}
|
||||
|
||||
--> null
|
||||
<-- {"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"invalid request"}}
|
||||
|
||||
@@ -151,11 +151,11 @@ func encrypt(key []byte, plaintext []byte, additionalData []byte) ([]byte, []byt
|
||||
return nil, nil, err
|
||||
}
|
||||
aesgcm, err := cipher.NewGCM(block)
|
||||
nonce := make([]byte, aesgcm.NonceSize())
|
||||
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err != nil {
|
||||
nonce := make([]byte, aesgcm.NonceSize())
|
||||
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ciphertext := aesgcm.Seal(nil, nonce, plaintext, additionalData)
|
||||
|
||||
Reference in New Issue
Block a user