Skip to content

Commit

Permalink
Merge pull request #1860 from bnb-chain/develop
Browse files Browse the repository at this point in the history
draft release v1.2.12
  • Loading branch information
brilliant-lx committed Sep 11, 2023
2 parents 7a19cd2 + 1c17c47 commit bb6bdc0
Show file tree
Hide file tree
Showing 27 changed files with 368 additions and 108 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
# Changelog
## v1.2.12
FEATURE
* [\#1852](https://github.com/bnb-chain/bsc/pull/1852) discov: add hardcoded bootnodes

BUGFIX
* [\#1844](https://github.com/bnb-chain/bsc/pull/1844) crypto: Update BLST to v0.3.11
* [\#1854](https://github.com/bnb-chain/bsc/pull/1854) fetcher: no import blocks before or equal to the finalized height
* [\#1855](https://github.com/bnb-chain/bsc/pull/1855) eth/tracers: trace system tx should add intrinsicGas

IMPROVEMENT
* [\#1839](https://github.com/bnb-chain/bsc/pull/1839) Update init-network command
* [\#1858](https://github.com/bnb-chain/bsc/pull/1858) vote: check consensus key match vote key before voting

## v1.2.11
FEATURE
* [\#1797](https://github.com/bnb-chain/bsc/pull/1797) client: add FinalizedHeader/Block to use the fast finality
Expand Down
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,35 @@ APIs!**
- [BSC-Deploy](https://github.com/bnb-chain/node-deploy/): deploy tool for setting up both BNB Beacon Chain, BNB Smart Chain and the cross chain infrastructure between them.
- [BSC-Docker](https://github.com/bnb-chain/bsc-docker): deploy tool for setting up local BSC cluster in container.


## Running a bootnode

Bootnodes are super-lightweight nodes that are not behind a NAT and are running just discovery protocol. When you start up a node it should log your enode, which is a public identifier that others can use to connect to your node.

First the bootnode requires a key, which can be created with the following command, which will save a key to boot.key:

```
bootnode -genkey boot.key
```

This key can then be used to generate a bootnode as follows:

```
bootnode -nodekey boot.key -addr :30311 -network bsc
```

The choice of port passed to -addr is arbitrary.
The bootnode command returns the following logs to the terminal, confirming that it is running:

```
enode://3063d1c9e1b824cfbb7c7b6abafa34faec6bb4e7e06941d218d760acdd7963b274278c5c3e63914bd6d1b58504c59ec5522c56f883baceb8538674b92da48a96@127.0.0.1:0?discport=30311
Note: you're using cmd/bootnode, a developer tool.
We recommend using a regular node as bootstrap node for production deployments.
INFO [08-21|11:11:30.687] New local node record seq=1,692,616,290,684 id=2c9af1742f8f85ce ip=<nil> udp=0 tcp=0
INFO [08-21|12:11:30.753] New local node record seq=1,692,616,290,685 id=2c9af1742f8f85ce ip=54.217.128.118 udp=30311 tcp=0
INFO [09-01|02:46:26.234] New local node record seq=1,692,616,290,686 id=2c9af1742f8f85ce ip=34.250.32.100 udp=30311 tcp=0
```

## Contribution

Thank you for considering to help out with the source code! We welcome contributions
Expand Down
146 changes: 107 additions & 39 deletions cmd/geth/chaincmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"encoding/json"
"errors"
"fmt"
"io"
"net"
"os"
"path"
Expand Down Expand Up @@ -237,31 +238,17 @@ func initGenesis(ctx *cli.Context) error {
return nil
}

// initNetwork will bootstrap and initialize a new genesis block, and nodekey, config files for network nodes
func initNetwork(ctx *cli.Context) error {
initDir := ctx.String(utils.InitNetworkDir.Name)
if len(initDir) == 0 {
utils.Fatalf("init.dir is required")
}
size := ctx.Int(utils.InitNetworkSize.Name)
port := ctx.Int(utils.InitNetworkPort.Name)
ipStr := ctx.String(utils.InitNetworkIps.Name)
cfgFile := ctx.String(configFileFlag.Name)

if len(cfgFile) == 0 {
utils.Fatalf("config file is required")
}
func parseIps(ipStr string, size int) ([]string, error) {
var ips []string
if len(ipStr) != 0 {
ips = strings.Split(ipStr, ",")
if len(ips) != size {
utils.Fatalf("mismatch of size and length of ips")
return nil, errors.New("mismatch of size and length of ips")
}
for i := 0; i < size; i++ {
_, err := net.ResolveIPAddr("", ips[i])
if err != nil {
utils.Fatalf("invalid format of ip")
return err
return nil, errors.New("invalid format of ip")
}
}
} else {
Expand All @@ -270,61 +257,142 @@ func initNetwork(ctx *cli.Context) error {
ips[i] = "127.0.0.1"
}
}
return ips, nil
}

func createPorts(ipStr string, port int, size int) []int {
ports := make([]int, size)
if len(ipStr) == 0 { // localhost , so different ports
for i := 0; i < size; i++ {
ports[i] = port + i
}
} else { // different machines, keep same port
for i := 0; i < size; i++ {
ports[i] = port
}
}
return ports
}

// Create config for node i in the cluster
func createNodeConfig(baseConfig gethConfig, enodes []*enode.Node, ip string, port int, size int, i int) gethConfig {
baseConfig.Node.HTTPHost = ip
baseConfig.Node.P2P.ListenAddr = fmt.Sprintf(":%d", port+i)
baseConfig.Node.P2P.BootstrapNodes = make([]*enode.Node, size-1)
// Set the P2P connections between this node and the other nodes
for j := 0; j < i; j++ {
baseConfig.Node.P2P.BootstrapNodes[j] = enodes[j]
}
for j := i + 1; j < size; j++ {
baseConfig.Node.P2P.BootstrapNodes[j-1] = enodes[j]
}
return baseConfig
}

// Create configs for nodes in the cluster
func createNodeConfigs(baseConfig gethConfig, initDir string, ips []string, ports []int, size int) ([]gethConfig, error) {
// Create the nodes
enodes := make([]*enode.Node, size)
for i := 0; i < size; i++ {
stack, err := node.New(&baseConfig.Node)
if err != nil {
return nil, err
}
stack.Config().DataDir = path.Join(initDir, fmt.Sprintf("node%d", i))
pk := stack.Config().NodeKey()
enodes[i] = enode.NewV4(&pk.PublicKey, net.ParseIP(ips[i]), ports[i], ports[i])
}

// Create the configs
configs := make([]gethConfig, size)
for i := 0; i < size; i++ {
configs[i] = createNodeConfig(baseConfig, enodes, ips[i], ports[i], size, i)
}
return configs, nil
}

// initNetwork will bootstrap and initialize a new genesis block, and nodekey, config files for network nodes
func initNetwork(ctx *cli.Context) error {
initDir := ctx.String(utils.InitNetworkDir.Name)
if len(initDir) == 0 {
utils.Fatalf("init.dir is required")
}
size := ctx.Int(utils.InitNetworkSize.Name)
if size <= 0 {
utils.Fatalf("size should be greater than 0")
}
port := ctx.Int(utils.InitNetworkPort.Name)
if port <= 0 {
utils.Fatalf("port should be greater than 0")
}
ipStr := ctx.String(utils.InitNetworkIps.Name)
cfgFile := ctx.String(configFileFlag.Name)

if len(cfgFile) == 0 {
utils.Fatalf("config file is required")
}

ips, err := parseIps(ipStr, size)
if err != nil {
utils.Fatalf("Failed to pase ips string: %v", err)
}

ports := createPorts(ipStr, port, size)

// Make sure we have a valid genesis JSON
genesisPath := ctx.Args().First()
if len(genesisPath) == 0 {
utils.Fatalf("Must supply path to genesis JSON file")
}
file, err := os.Open(genesisPath)
inGenesisFile, err := os.Open(genesisPath)
if err != nil {
utils.Fatalf("Failed to read genesis file: %v", err)
}
defer file.Close()
defer inGenesisFile.Close()

genesis := new(core.Genesis)
if err := json.NewDecoder(file).Decode(genesis); err != nil {
if err := json.NewDecoder(inGenesisFile).Decode(genesis); err != nil {
utils.Fatalf("invalid genesis file: %v", err)
}
enodes := make([]*enode.Node, size)

// load config
var config gethConfig
err = loadConfig(cfgFile, &config)
if err != nil {
return err
}
config.Eth.Genesis = genesis

configs, err := createNodeConfigs(config, initDir, ips, ports, size)
if err != nil {
utils.Fatalf("Failed to create node configs: %v", err)
}

for i := 0; i < size; i++ {
stack, err := node.New(&config.Node)
// Write config.toml
configBytes, err := tomlSettings.Marshal(configs[i])
if err != nil {
return err
}
stack.Config().DataDir = path.Join(initDir, fmt.Sprintf("node%d", i))
pk := stack.Config().NodeKey()
enodes[i] = enode.NewV4(&pk.PublicKey, net.ParseIP(ips[i]), port, port)
}

for i := 0; i < size; i++ {
config.Node.HTTPHost = ips[i]
config.Node.P2P.StaticNodes = make([]*enode.Node, size-1)
for j := 0; j < i; j++ {
config.Node.P2P.StaticNodes[j] = enodes[j]
configFile, err := os.OpenFile(path.Join(initDir, fmt.Sprintf("node%d", i), "config.toml"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
return err
}
for j := i + 1; j < size; j++ {
config.Node.P2P.StaticNodes[j-1] = enodes[j]
defer configFile.Close()
configFile.Write(configBytes)

// Write the input genesis.json to the node's directory
outGenesisFile, err := os.OpenFile(path.Join(initDir, fmt.Sprintf("node%d", i), "genesis.json"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
return err
}
out, err := tomlSettings.Marshal(config)
_, err = inGenesisFile.Seek(0, io.SeekStart)
if err != nil {
return err
}
dump, err := os.OpenFile(path.Join(initDir, fmt.Sprintf("node%d", i), "config.toml"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
_, err = io.Copy(outGenesisFile, inGenesisFile)
if err != nil {
return err
}
defer dump.Close()
dump.Write(out)
}
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,5 +155,5 @@ type PoSA interface {
GetJustifiedNumberAndHash(chain ChainHeaderReader, header *types.Header) (uint64, common.Hash, error)
GetFinalizedHeader(chain ChainHeaderReader, header *types.Header) *types.Header
VerifyVote(chain ChainHeaderReader, vote *types.VoteEnvelope) error
IsActiveValidatorAt(chain ChainHeaderReader, header *types.Header) bool
IsActiveValidatorAt(chain ChainHeaderReader, header *types.Header, checkVoteKeyFn func(bLSPublicKey *types.BLSPublicKey) bool) bool
}
7 changes: 4 additions & 3 deletions consensus/parlia/parlia.go
Original file line number Diff line number Diff line change
Expand Up @@ -1205,16 +1205,17 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
return blk, receipts, nil
}

func (p *Parlia) IsActiveValidatorAt(chain consensus.ChainHeaderReader, header *types.Header) bool {
func (p *Parlia) IsActiveValidatorAt(chain consensus.ChainHeaderReader, header *types.Header, checkVoteKeyFn func(bLSPublicKey *types.BLSPublicKey) bool) bool {
number := header.Number.Uint64()
snap, err := p.snapshot(chain, number-1, header.ParentHash, nil)
if err != nil {
log.Error("failed to get the snapshot from consensus", "error", err)
return false
}
validators := snap.Validators
_, ok := validators[p.val]
return ok
validatorInfo, ok := validators[p.val]

return ok && (checkVoteKeyFn == nil || (validatorInfo != nil && checkVoteKeyFn(&validatorInfo.VoteAddress)))
}

// VerifyVote will verify: 1. If the vote comes from valid validators 2. If the vote's sourceNumber and sourceHash are correct
Expand Down
1 change: 1 addition & 0 deletions core/vm/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type EVMLogger interface {
// Transaction level
CaptureTxStart(gasLimit uint64)
CaptureTxEnd(restGas uint64)
CaptureSystemTxEnd(intrinsicGas uint64)
// Top call frame
CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int)
CaptureEnd(output []byte, gasUsed uint64, err error)
Expand Down
18 changes: 16 additions & 2 deletions core/vote/vote_manager.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package vote

import (
"bytes"
"fmt"
"sync"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
Expand Down Expand Up @@ -97,6 +99,7 @@ func (voteManager *VoteManager) loop() {
dlEventCh := events.Chan()

startVote := true
var once sync.Once
for {
select {
case ev := <-dlEventCh:
Expand Down Expand Up @@ -132,11 +135,22 @@ func (voteManager *VoteManager) loop() {

curHead := cHead.Block.Header()
// Check if cur validator is within the validatorSet at curHead
if !voteManager.engine.IsActiveValidatorAt(voteManager.chain, curHead) {
if !voteManager.engine.IsActiveValidatorAt(voteManager.chain, curHead,
func(bLSPublicKey *types.BLSPublicKey) bool {
return bytes.Equal(voteManager.signer.PubKey[:], bLSPublicKey[:])
}) {
log.Debug("cur validator is not within the validatorSet at curHead")
continue
}

// Add VoteKey to `miner-info`
once.Do(func() {
minerInfo := metrics.Get("miner-info")
if minerInfo != nil {
minerInfo.(metrics.Label).Value()["VoteKey"] = common.Bytes2Hex(voteManager.signer.PubKey[:])
}
})

// Vote for curBlockHeader block.
vote := &types.VoteData{
TargetNumber: curHead.Number.Uint64(),
Expand Down Expand Up @@ -174,7 +188,7 @@ func (voteManager *VoteManager) loop() {
}
case event := <-voteManager.syncVoteCh:
voteMessage := event.Vote
if voteManager.eth.IsMining() || !voteManager.signer.UsingKey(&voteMessage.VoteAddress) {
if voteManager.eth.IsMining() || !bytes.Equal(voteManager.signer.PubKey[:], voteMessage.VoteAddress[:]) {
continue
}
if err := voteManager.journal.WriteVote(voteMessage); err != nil {
Expand Down
4 changes: 2 additions & 2 deletions core/vote/vote_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,11 @@ func (m *mockInvalidPOSA) VerifyVote(chain consensus.ChainHeaderReader, vote *ty
return nil
}

func (m *mockPOSA) IsActiveValidatorAt(chain consensus.ChainHeaderReader, header *types.Header) bool {
func (m *mockPOSA) IsActiveValidatorAt(chain consensus.ChainHeaderReader, header *types.Header, checkVoteKeyFn func(bLSPublicKey *types.BLSPublicKey) bool) bool {
return true
}

func (m *mockInvalidPOSA) IsActiveValidatorAt(chain consensus.ChainHeaderReader, header *types.Header) bool {
func (m *mockInvalidPOSA) IsActiveValidatorAt(chain consensus.ChainHeaderReader, header *types.Header, checkVoteKeyFn func(bLSPublicKey *types.BLSPublicKey) bool) bool {
return true
}

Expand Down
Loading

0 comments on commit bb6bdc0

Please sign in to comment.