Compare commits

..

44 Commits

Author SHA1 Message Date
zjubfd
0a1e79e2a1 prepare for release v1.0.5 (#64) 2021-01-19 11:46:02 +08:00
HaoyangLiu
e09e48a02f R4R: apply mirror sync upgrade (#56)
* apply mirror sync upgrade

remove 0x

update rialto genesis hash

update tokenhub code

* update tokenhub code

* update relayer incentive contract code

* update upgrade height and remove mainnet upgrade
2021-01-19 11:35:01 +08:00
zjubfd
b605f1f913 Merge pull request #63 from binance-chain/secure_patch
[R4R] security patch from go-ethereum
2021-01-11 16:43:45 +08:00
zjubfd
9fedf1909d Merge pull request #53 from binance-chain/elegant_upgrade
[R4R]support fork id in header; elegant upgrade
2021-01-11 14:54:20 +08:00
fudongbai
24dc208170 avoid false warn log 2021-01-11 14:42:06 +08:00
fudongbai
60606d3919 support fork id in header; elegant upgrade 2021-01-11 13:54:35 +08:00
zjubfd
5a1c39da09 Merge pull request #60 from binance-chain/x-forward-for
[R4R] Add `x-forward-for` log message when handle message failed
2021-01-11 13:52:38 +08:00
zjubfd
cfeab77017 Merge pull request #61 from binance-chain/requestGauge
[R4R]add rpc method request gauge
2021-01-11 13:52:21 +08:00
Nishant Das
9e8ee517d7 p2p/discover: fix deadlock in discv5 message dispatch (#21858)
This fixes a deadlock that could occur when a response packet arrived
after a call had already received enough responses and was about to
signal completion to the dispatch loop.

Co-authored-by: Felix Lange <fjl@twurst.com>
2021-01-11 11:27:17 +08:00
Felix Lange
ca1d1cb08d p2p/enode: avoid crashing for invalid IP (#21981)
The database panicked for invalid IPs. This is usually no problem
because all code paths leading to node DB access verify the IP, but it's
dangerous because improper validation can turn this panic into a DoS
vulnerability. The quick fix here is to just turn database accesses
using invalid IP into a noop. This isn't great, but I'm planning to
remove the node DB for discv5 long-term, so it should be fine to have
this quick fix for half a year.

Fixes #21849
2021-01-11 11:26:39 +08:00
Fuyang Deng
670009d1e1 accounts/abi: fix a bug in getTypeSize method (#21501)
* accounts/abi: fix a bug in getTypeSize method

e.g. for "Tuple[2]" type, the element of the array is a tuple type and the size of the tuple may not be 32.

* accounts/abi: add unit test of getTypeSize method
2021-01-11 11:26:29 +08:00
Felix Lange
4608da6c13 rpc: fix issue with null JSON-RPC messages (#21497) 2021-01-11 11:23:44 +08:00
Marius van der Wijden
d1f95d5fd3 internal/ethapi: fix nil deref + fix estimateGas console bindings (#21601)
* tried to fix

* fix for js api

* fix for nil pointer ex

* rev space

* rev space

* input call formatter
2021-01-11 11:23:18 +08:00
Martin Holst Swende
ad3ff6452d core: fix txpool off-by-one error (#21683) 2021-01-11 11:22:52 +08:00
6543
0a64615f1e signer/storage: fix a badly ordered error check (#21379) 2021-01-11 11:22:25 +08:00
Slava Karpenko
2a79ac1622 consensus/ethash: use 64bit indexes for the DAG generation (#21793)
* Bit boundary fix for the DAG generation routine

* Fix unnecessary conversion warnings

Co-authored-by: Sergey Pavlov <spavlov@gmail.com>
2021-01-11 11:20:54 +08:00
fudongbai
0e797c53b7 add x-forward-for message in log 2021-01-11 10:49:34 +08:00
zjubfd
3f3f8d02cf Merge pull request #59 from binance-chain/issue_58
[R4R]fix potential deadlock of pub/sub module
2021-01-11 10:40:14 +08:00
fudongbai
5bd73320ba add rpc method request gauge 2021-01-10 22:01:20 +08:00
zjubfd
894b1e3c8d Merge pull request #54 from binance-chain/fixLess
[R4R]les: fix GetProofsV2 bug (#21896)
2021-01-08 16:47:59 +08:00
fudongbai
3d3f9694a4 fix potential deadlock of pub/sub module 2020-12-30 15:13:11 +08:00
zjubfd
f6ec491548 Merge pull request #55 from binance-chain/curl_image
[R4R]add curl in docker image
2020-12-18 14:48:49 +08:00
Felföldi Zsolt
e0205f5983 les: fix GetProofsV2 bug (#21896) 2020-12-15 14:11:44 +08:00
fudongbai
69fe8db258 add curl in docker image 2020-12-14 20:29:44 +08:00
zjubfd
ed10dfa6bf Merge pull request #50 from binance-chain/p1.0.4
[R4R]add change log for release v1.0.4
2020-11-23 18:01:10 +08:00
fudongbai
3da36e6a55 add change log for release v1.0.4 2020-11-23 17:57:40 +08:00
zjubfd
c2feabad39 Merge pull request #49 from binance-chain/pr_template
[R4R]Create PULL_REQUEST_TEMPLATE
2020-11-17 17:26:20 +08:00
zjubfd
b0fcc0a663 Create PULL_REQUEST_TEMPLATE 2020-11-17 17:19:00 +08:00
zjubfd
58a91af56c Merge pull request #38 from hyunsikswap/remove-log
Disable noisy log from consensus engine
2020-11-17 16:51:30 +08:00
zjubfd
cca7667dcd Merge pull request #47 from binance-chain/golang1.15.5
[R4R]upgrade to golang1.15.5
2020-11-17 16:47:25 +08:00
zjubfd
1a50838431 Merge pull request #35 from binance-chain/fixedGas
[R4R]use fixed gas price when network is idle
2020-11-17 16:46:30 +08:00
fudongbai
d52d8a5f05 use fixed gas price since bsc network is idle 2020-11-17 16:38:20 +08:00
fudongbai
935c9e3c6a upgrade to golang1.15.5 2020-11-16 13:56:57 +08:00
Hyunsik Lee
cb1afd2b14 Hide some smart contract tracing logs from parlia consensus engine 2020-09-30 02:43:10 +09:00
Hyunsik Lee
7bd1c1f23d Disable noisy log from consensus engine 2020-09-30 02:43:09 +09:00
zjubfd
537c5db510 Merge pull request #41 from binance-chain/branch_1.0.3
[R4R]prepare release 1.0.3
2020-09-24 14:17:03 +08:00
fudongbai
40620b478c prepare release 1.0.3 2020-09-24 13:59:06 +08:00
HaoyangLiu
e81c728ff6 R4R: add max gas allwance calculation (#36)
* calculate max gas allwance

* return error for missing from
2020-09-11 22:22:11 +08:00
zjubfd
bfb73f8068 Merge pull request #32 from binance-chain/releasev1.0.2
[R4R]prepare for release 1.0.2
2020-08-28 10:33:56 +08:00
fudongbai
397f6f6108 prepare for release 1.0.2 2020-08-28 10:29:05 +08:00
HaoyangLiu
b242e890d2 Merge pull request #30 from binance-chain/rmdisclaim
[R4R]remove disclaim
2020-08-27 17:57:33 +08:00
zjubfd
ba0152fea9 Merge pull request #29 from binance-chain/improve-tracer
R4R: improve tracers
2020-08-27 17:52:39 +08:00
fudongbai
844ed90c28 remove disclaim 2020-08-27 17:51:47 +08:00
libotony
f94b7de003 eth/tracers: revert reason in call_tracer + error for failed internal calls (#21387)
* tests: add testdata of call tracer

* eth/tracers: return revert reason in call_tracer

* eth/tracers: regenerate assets

* eth/tracers: add error message even if no exec occurrs, fixes #21438

Co-authored-by: Martin Holst Swende <martin@swende.se>
2020-08-27 17:45:47 +08:00
43 changed files with 641 additions and 136 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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: &params.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),

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -61,8 +61,9 @@ var DefaultConfig = Config{
},
TxPool: core.DefaultTxPoolConfig,
GPO: gasprice.Config{
Blocks: 20,
Percentile: 60,
Blocks: 20,
Percentile: 60,
OracleThreshold: 1000,
},
}

View File

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

View File

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

View File

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

View File

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

View 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"
}
]
}
}

File diff suppressed because one or more lines are too long

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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