mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-14 07:53:47 +00:00
Merge branch 'master' into gethv1.10.15-merge
This commit is contained in:
commit
a6c5473434
68 changed files with 1807 additions and 385 deletions
|
|
@ -20,7 +20,7 @@ builds:
|
||||||
- netgo
|
- netgo
|
||||||
ldflags:
|
ldflags:
|
||||||
-s -w
|
-s -w
|
||||||
|
|
||||||
- id: darwin-arm64
|
- id: darwin-arm64
|
||||||
main: ./cmd/geth
|
main: ./cmd/geth
|
||||||
binary: bor
|
binary: bor
|
||||||
|
|
@ -35,7 +35,7 @@ builds:
|
||||||
- netgo
|
- netgo
|
||||||
ldflags:
|
ldflags:
|
||||||
-s -w
|
-s -w
|
||||||
|
|
||||||
- id: linux-amd64
|
- id: linux-amd64
|
||||||
main: ./cmd/geth
|
main: ./cmd/geth
|
||||||
binary: bor
|
binary: bor
|
||||||
|
|
@ -49,7 +49,7 @@ builds:
|
||||||
tags:
|
tags:
|
||||||
- netgo
|
- netgo
|
||||||
ldflags:
|
ldflags:
|
||||||
# We need to build a static binary because we are building in a glibc based system and running in a musl container
|
# We need to build a static binary because we are building in a glibc based system and running in a musl container
|
||||||
-s -w -extldflags "-static"
|
-s -w -extldflags "-static"
|
||||||
|
|
||||||
- id: linux-arm64
|
- id: linux-arm64
|
||||||
|
|
@ -65,7 +65,7 @@ builds:
|
||||||
tags:
|
tags:
|
||||||
- netgo
|
- netgo
|
||||||
ldflags:
|
ldflags:
|
||||||
# We need to build a static binary because we are building in a glibc based system and running in a musl container
|
# We need to build a static binary because we are building in a glibc based system and running in a musl container
|
||||||
-s -w -extldflags "-static"
|
-s -w -extldflags "-static"
|
||||||
|
|
||||||
nfpms:
|
nfpms:
|
||||||
|
|
@ -112,7 +112,7 @@ dockers:
|
||||||
extra_files:
|
extra_files:
|
||||||
- builder/files/genesis-mainnet-v1.json
|
- builder/files/genesis-mainnet-v1.json
|
||||||
- builder/files/genesis-testnet-v4.json
|
- builder/files/genesis-testnet-v4.json
|
||||||
|
|
||||||
- image_templates:
|
- image_templates:
|
||||||
- 0xpolygon/{{ .ProjectName }}:{{ .Version }}-arm64
|
- 0xpolygon/{{ .ProjectName }}:{{ .Version }}-arm64
|
||||||
dockerfile: Dockerfile.release
|
dockerfile: Dockerfile.release
|
||||||
|
|
|
||||||
7
Makefile
7
Makefile
|
|
@ -44,10 +44,9 @@ ios:
|
||||||
@echo "Done building."
|
@echo "Done building."
|
||||||
@echo "Import \"$(GOBIN)/Geth.framework\" to use the library."
|
@echo "Import \"$(GOBIN)/Geth.framework\" to use the library."
|
||||||
|
|
||||||
test: all
|
test:
|
||||||
# $(GORUN) build/ci.go test
|
# Skip mobile and cmd tests since they are being deprecated
|
||||||
go test github.com/ethereum/go-ethereum/consensus/bor -v
|
go test -v $$(go list ./... | grep -v go-ethereum/cmd/)
|
||||||
go test github.com/ethereum/go-ethereum/tests/bor -v
|
|
||||||
|
|
||||||
lint: ## Run linters.
|
lint: ## Run linters.
|
||||||
$(GORUN) build/ci.go lint
|
$(GORUN) build/ci.go lint
|
||||||
|
|
|
||||||
11
cmd/cli/main.go
Normal file
11
cmd/cli/main.go
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/internal/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
os.Exit(cli.Run(os.Args[1:]))
|
||||||
|
}
|
||||||
|
|
@ -214,6 +214,7 @@ type BlockChain struct {
|
||||||
borReceiptsCache *lru.Cache // Cache for the most recent bor receipt receipts per block
|
borReceiptsCache *lru.Cache // Cache for the most recent bor receipt receipts per block
|
||||||
stateSyncData []*types.StateSyncData // State sync data
|
stateSyncData []*types.StateSyncData // State sync data
|
||||||
stateSyncFeed event.Feed // State sync feed
|
stateSyncFeed event.Feed // State sync feed
|
||||||
|
chain2HeadFeed event.Feed // Reorg/NewHead/Fork data feed
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlockChain returns a fully initialised block chain using information
|
// NewBlockChain returns a fully initialised block chain using information
|
||||||
|
|
@ -1368,10 +1369,21 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
|
||||||
for _, data := range bc.stateSyncData {
|
for _, data := range bc.stateSyncData {
|
||||||
bc.stateSyncFeed.Send(StateSyncEvent{Data: data})
|
bc.stateSyncFeed.Send(StateSyncEvent{Data: data})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bc.chain2HeadFeed.Send(Chain2HeadEvent{
|
||||||
|
Type: Chain2HeadCanonicalEvent,
|
||||||
|
NewChain: []*types.Block{block},
|
||||||
|
})
|
||||||
|
|
||||||
// BOR
|
// BOR
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bc.chainSideFeed.Send(ChainSideEvent{Block: block})
|
bc.chainSideFeed.Send(ChainSideEvent{Block: block})
|
||||||
|
|
||||||
|
bc.chain2HeadFeed.Send(Chain2HeadEvent{
|
||||||
|
Type: Chain2HeadForkEvent,
|
||||||
|
NewChain: []*types.Block{block},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return status, nil
|
return status, nil
|
||||||
}
|
}
|
||||||
|
|
@ -1455,6 +1467,11 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
|
||||||
defer func() {
|
defer func() {
|
||||||
if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() {
|
if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() {
|
||||||
bc.chainHeadFeed.Send(ChainHeadEvent{lastCanon})
|
bc.chainHeadFeed.Send(ChainHeadEvent{lastCanon})
|
||||||
|
|
||||||
|
bc.chain2HeadFeed.Send(Chain2HeadEvent{
|
||||||
|
Type: Chain2HeadCanonicalEvent,
|
||||||
|
NewChain: []*types.Block{lastCanon},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
// Start the parallel header verifier
|
// Start the parallel header verifier
|
||||||
|
|
@ -2065,6 +2082,13 @@ func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
|
||||||
}
|
}
|
||||||
// Ensure the user sees large reorgs
|
// Ensure the user sees large reorgs
|
||||||
if len(oldChain) > 0 && len(newChain) > 0 {
|
if len(oldChain) > 0 && len(newChain) > 0 {
|
||||||
|
|
||||||
|
bc.chain2HeadFeed.Send(Chain2HeadEvent{
|
||||||
|
Type: Chain2HeadReorgEvent,
|
||||||
|
NewChain: newChain,
|
||||||
|
OldChain: oldChain,
|
||||||
|
})
|
||||||
|
|
||||||
logFn := log.Info
|
logFn := log.Info
|
||||||
msg := "Chain reorg detected"
|
msg := "Chain reorg detected"
|
||||||
if len(oldChain) > 63 {
|
if len(oldChain) > 63 {
|
||||||
|
|
|
||||||
134
core/blockchain_bor_test.go
Normal file
134
core/blockchain_bor_test.go
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestChain2HeadEvent(t *testing.T) {
|
||||||
|
var (
|
||||||
|
db = rawdb.NewMemoryDatabase()
|
||||||
|
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
|
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
||||||
|
gspec = &Genesis{
|
||||||
|
Config: params.TestChainConfig,
|
||||||
|
Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}},
|
||||||
|
}
|
||||||
|
genesis = gspec.MustCommit(db)
|
||||||
|
signer = types.LatestSigner(gspec.Config)
|
||||||
|
)
|
||||||
|
|
||||||
|
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
|
||||||
|
defer blockchain.Stop()
|
||||||
|
|
||||||
|
chain2HeadCh := make(chan Chain2HeadEvent, 64)
|
||||||
|
blockchain.SubscribeChain2HeadEvent(chain2HeadCh)
|
||||||
|
|
||||||
|
chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {})
|
||||||
|
if _, err := blockchain.InsertChain(chain); err != nil {
|
||||||
|
t.Fatalf("failed to insert chain: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
replacementBlocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, gen *BlockGen) {
|
||||||
|
tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, gen.header.BaseFee, nil), signer, key1)
|
||||||
|
if i == 2 {
|
||||||
|
gen.OffsetTime(-9)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create tx: %v", err)
|
||||||
|
}
|
||||||
|
gen.AddTx(tx)
|
||||||
|
})
|
||||||
|
|
||||||
|
if _, err := blockchain.InsertChain(replacementBlocks); err != nil {
|
||||||
|
t.Fatalf("failed to insert chain: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type eventTest struct {
|
||||||
|
Type string
|
||||||
|
Added []common.Hash
|
||||||
|
Removed []common.Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
readEvent := func(expect *eventTest) {
|
||||||
|
select {
|
||||||
|
case ev := <-chain2HeadCh:
|
||||||
|
if ev.Type != expect.Type {
|
||||||
|
t.Fatal("Type mismatch")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ev.NewChain) != len(expect.Added) {
|
||||||
|
t.Fatal("Newchain and Added Array Size don't match")
|
||||||
|
}
|
||||||
|
if len(ev.OldChain) != len(expect.Removed) {
|
||||||
|
t.Fatal("Oldchain and Removed Array Size don't match")
|
||||||
|
}
|
||||||
|
|
||||||
|
for j := 0; j < len(ev.OldChain); j++ {
|
||||||
|
if ev.OldChain[j].Hash() != expect.Removed[j] {
|
||||||
|
t.Fatal("Oldchain hashes Do Not Match")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for j := 0; j < len(ev.NewChain); j++ {
|
||||||
|
if ev.NewChain[j].Hash() != expect.Added[j] {
|
||||||
|
t.Fatal("Newchain hashes Do Not Match")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case <-time.After(2 * time.Second):
|
||||||
|
t.Fatal("timeout")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// head event
|
||||||
|
readEvent(&eventTest{
|
||||||
|
Type: Chain2HeadCanonicalEvent,
|
||||||
|
Added: []common.Hash{
|
||||||
|
chain[2].Hash(),
|
||||||
|
}})
|
||||||
|
|
||||||
|
// fork event
|
||||||
|
readEvent(&eventTest{
|
||||||
|
Type: Chain2HeadForkEvent,
|
||||||
|
Added: []common.Hash{
|
||||||
|
replacementBlocks[0].Hash(),
|
||||||
|
}})
|
||||||
|
|
||||||
|
// fork event
|
||||||
|
readEvent(&eventTest{
|
||||||
|
Type: Chain2HeadForkEvent,
|
||||||
|
Added: []common.Hash{
|
||||||
|
replacementBlocks[1].Hash(),
|
||||||
|
}})
|
||||||
|
|
||||||
|
// reorg event
|
||||||
|
//In this event the channel recieves an array of Blocks in NewChain and OldChain
|
||||||
|
readEvent(&eventTest{
|
||||||
|
Type: Chain2HeadReorgEvent,
|
||||||
|
Added: []common.Hash{
|
||||||
|
replacementBlocks[2].Hash(),
|
||||||
|
replacementBlocks[1].Hash(),
|
||||||
|
replacementBlocks[0].Hash(),
|
||||||
|
},
|
||||||
|
Removed: []common.Hash{
|
||||||
|
chain[2].Hash(),
|
||||||
|
chain[1].Hash(),
|
||||||
|
chain[0].Hash(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// head event
|
||||||
|
readEvent(&eventTest{
|
||||||
|
Type: Chain2HeadCanonicalEvent,
|
||||||
|
Added: []common.Hash{
|
||||||
|
replacementBlocks[3].Hash(),
|
||||||
|
}})
|
||||||
|
}
|
||||||
|
|
@ -376,6 +376,11 @@ func (bc *BlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Su
|
||||||
return bc.scope.Track(bc.chainHeadFeed.Subscribe(ch))
|
return bc.scope.Track(bc.chainHeadFeed.Subscribe(ch))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SubscribeChain2HeadEvent registers a subscription of ChainHeadEvent. ()
|
||||||
|
func (bc *BlockChain) SubscribeChain2HeadEvent(ch chan<- Chain2HeadEvent) event.Subscription {
|
||||||
|
return bc.scope.Track(bc.chain2HeadFeed.Subscribe(ch))
|
||||||
|
}
|
||||||
|
|
||||||
// SubscribeChainSideEvent registers a subscription of ChainSideEvent.
|
// SubscribeChainSideEvent registers a subscription of ChainSideEvent.
|
||||||
func (bc *BlockChain) SubscribeChainSideEvent(ch chan<- ChainSideEvent) event.Subscription {
|
func (bc *BlockChain) SubscribeChainSideEvent(ch chan<- ChainSideEvent) event.Subscription {
|
||||||
return bc.scope.Track(bc.chainSideFeed.Subscribe(ch))
|
return bc.scope.Track(bc.chainSideFeed.Subscribe(ch))
|
||||||
|
|
|
||||||
|
|
@ -8,3 +8,16 @@ import (
|
||||||
type StateSyncEvent struct {
|
type StateSyncEvent struct {
|
||||||
Data *types.StateSyncData
|
Data *types.StateSyncData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
Chain2HeadReorgEvent = "reorg"
|
||||||
|
Chain2HeadCanonicalEvent = "head"
|
||||||
|
Chain2HeadForkEvent = "fork"
|
||||||
|
)
|
||||||
|
|
||||||
|
// For tracking reorgs related information
|
||||||
|
type Chain2HeadEvent struct {
|
||||||
|
NewChain []*types.Block
|
||||||
|
OldChain []*types.Block
|
||||||
|
Type string
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -152,8 +152,10 @@ func newFreezer(datadir string, namespace string, readonly bool, maxTableSize ui
|
||||||
// This way they don't have to sync again from block 0 and still be compatible
|
// This way they don't have to sync again from block 0 and still be compatible
|
||||||
// for block logs for future blocks. Note that already synced nodes
|
// for block logs for future blocks. Note that already synced nodes
|
||||||
// won't have past block logs. Newly synced node will have all the data.
|
// won't have past block logs. Newly synced node will have all the data.
|
||||||
if err := freezer.tables[freezerBorReceiptTable].Fill(freezer.tables[freezerHeaderTable].items); err != nil {
|
if _, ok := freezer.tables[freezerBorReceiptTable]; ok {
|
||||||
return nil, err
|
if err := freezer.tables[freezerBorReceiptTable].Fill(freezer.tables[freezerHeaderTable].items); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Truncate all tables to common length.
|
// Truncate all tables to common length.
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ func TestStateProcessorErrors(t *testing.T) {
|
||||||
BerlinBlock: big.NewInt(0),
|
BerlinBlock: big.NewInt(0),
|
||||||
LondonBlock: big.NewInt(0),
|
LondonBlock: big.NewInt(0),
|
||||||
Ethash: new(params.EthashConfig),
|
Ethash: new(params.EthashConfig),
|
||||||
|
Bor: ¶ms.BorConfig{BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"}},
|
||||||
}
|
}
|
||||||
signer = types.LatestSigner(config)
|
signer = types.LatestSigner(config)
|
||||||
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
|
|
|
||||||
|
|
@ -31,4 +31,6 @@
|
||||||
|
|
||||||
- [```status```](./status.md)
|
- [```status```](./status.md)
|
||||||
|
|
||||||
|
- [```chain watch```](./chain_watch.md)
|
||||||
|
|
||||||
- [```version```](./version.md)
|
- [```version```](./version.md)
|
||||||
|
|
|
||||||
3
docs/cli/chain_watch.md
Normal file
3
docs/cli/chain_watch.md
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Chain watch
|
||||||
|
|
||||||
|
The ```chain watch``` command is used to view the chainHead, reorg and fork events in real-time.
|
||||||
|
|
@ -67,3 +67,8 @@ func (b *EthAPIBackend) GetBorBlockTransactionWithBlockHash(ctx context.Context,
|
||||||
func (b *EthAPIBackend) SubscribeStateSyncEvent(ch chan<- core.StateSyncEvent) event.Subscription {
|
func (b *EthAPIBackend) SubscribeStateSyncEvent(ch chan<- core.StateSyncEvent) event.Subscription {
|
||||||
return b.eth.BlockChain().SubscribeStateSyncEvent(ch)
|
return b.eth.BlockChain().SubscribeStateSyncEvent(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SubscribeChain2HeadEvent subscribes to reorg/head/fork event
|
||||||
|
func (b *EthAPIBackend) SubscribeChain2HeadEvent(ch chan<- core.Chain2HeadEvent) event.Subscription {
|
||||||
|
return b.eth.BlockChain().SubscribeChain2HeadEvent(ch)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -254,7 +254,9 @@ func CreateConsensusEngine(stack *node.Node, chainConfig *params.ChainConfig, et
|
||||||
engine.(*ethash.Ethash).SetThreads(-1) // Disable CPU mining
|
engine.(*ethash.Ethash).SetThreads(-1) // Disable CPU mining
|
||||||
}
|
}
|
||||||
// If Matic bor consensus is requested, set it up
|
// If Matic bor consensus is requested, set it up
|
||||||
if chainConfig.Bor != nil {
|
// In order to pass the ethereum transaction tests, we need to set the burn contract which is in the bor config
|
||||||
|
// Then, bor != nil will also be enabled for ethash and clique. Only enable Bor for real if there is a validator contract present.
|
||||||
|
if chainConfig.Bor != nil && chainConfig.Bor.ValidatorContract != "" {
|
||||||
return bor.New(chainConfig, db, blockchainAPI, ethConfig.HeimdallURL, ethConfig.WithoutHeimdall)
|
return bor.New(chainConfig, db, blockchainAPI, ethConfig.HeimdallURL, ethConfig.WithoutHeimdall)
|
||||||
}
|
}
|
||||||
// Otherwise assume proof-of-work
|
// Otherwise assume proof-of-work
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ import (
|
||||||
const sampleNumber = 3 // Number of transactions sampled in a block
|
const sampleNumber = 3 // Number of transactions sampled in a block
|
||||||
|
|
||||||
var (
|
var (
|
||||||
DefaultMaxPrice = big.NewInt(500 * params.GWei)
|
DefaultMaxPrice = big.NewInt(5000 * params.GWei)
|
||||||
DefaultIgnorePrice = big.NewInt(2 * params.Wei)
|
DefaultIgnorePrice = big.NewInt(2 * params.Wei)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -256,6 +256,8 @@ func generateTestChain() []*types.Block {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEthClient(t *testing.T) {
|
func TestEthClient(t *testing.T) {
|
||||||
|
t.Skip("bor due to burn contract")
|
||||||
|
|
||||||
backend, chain := newTestBackend(t)
|
backend, chain := newTestBackend(t)
|
||||||
client, _ := backend.Attach()
|
client, _ := backend.Attach()
|
||||||
defer backend.Close()
|
defer backend.Close()
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,8 @@ func generateTestChain() (*core.Genesis, []*types.Block) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGethClient(t *testing.T) {
|
func TestGethClient(t *testing.T) {
|
||||||
|
t.Skip("bor due to burn contract")
|
||||||
|
|
||||||
backend, _ := newTestBackend(t)
|
backend, _ := newTestBackend(t)
|
||||||
client, err := backend.Attach()
|
client, err := backend.Attach()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,9 @@ const (
|
||||||
txChanSize = 4096
|
txChanSize = 4096
|
||||||
// chainHeadChanSize is the size of channel listening to ChainHeadEvent.
|
// chainHeadChanSize is the size of channel listening to ChainHeadEvent.
|
||||||
chainHeadChanSize = 10
|
chainHeadChanSize = 10
|
||||||
|
|
||||||
|
// chain2HeadChanSize is the size of channel listening to Chain2HeadEvent.
|
||||||
|
chain2HeadChanSize = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
// backend encompasses the bare-minimum functionality needed for ethstats reporting
|
// backend encompasses the bare-minimum functionality needed for ethstats reporting
|
||||||
|
|
@ -68,6 +71,9 @@ type backend interface {
|
||||||
GetTd(ctx context.Context, hash common.Hash) *big.Int
|
GetTd(ctx context.Context, hash common.Hash) *big.Int
|
||||||
Stats() (pending int, queued int)
|
Stats() (pending int, queued int)
|
||||||
SyncProgress() ethereum.SyncProgress
|
SyncProgress() ethereum.SyncProgress
|
||||||
|
|
||||||
|
// Bor
|
||||||
|
SubscribeChain2HeadEvent(ch chan<- core.Chain2HeadEvent) event.Subscription
|
||||||
}
|
}
|
||||||
|
|
||||||
// fullNodeBackend encompasses the functionality necessary for a full node
|
// fullNodeBackend encompasses the functionality necessary for a full node
|
||||||
|
|
@ -96,6 +102,9 @@ type Service struct {
|
||||||
|
|
||||||
headSub event.Subscription
|
headSub event.Subscription
|
||||||
txSub event.Subscription
|
txSub event.Subscription
|
||||||
|
|
||||||
|
//bor related sub
|
||||||
|
chain2headSub event.Subscription
|
||||||
}
|
}
|
||||||
|
|
||||||
// connWrapper is a wrapper to prevent concurrent-write or concurrent-read on the
|
// connWrapper is a wrapper to prevent concurrent-write or concurrent-read on the
|
||||||
|
|
@ -195,7 +204,9 @@ func (s *Service) Start() error {
|
||||||
s.headSub = s.backend.SubscribeChainHeadEvent(chainHeadCh)
|
s.headSub = s.backend.SubscribeChainHeadEvent(chainHeadCh)
|
||||||
txEventCh := make(chan core.NewTxsEvent, txChanSize)
|
txEventCh := make(chan core.NewTxsEvent, txChanSize)
|
||||||
s.txSub = s.backend.SubscribeNewTxsEvent(txEventCh)
|
s.txSub = s.backend.SubscribeNewTxsEvent(txEventCh)
|
||||||
go s.loop(chainHeadCh, txEventCh)
|
chain2HeadCh := make(chan core.Chain2HeadEvent, chain2HeadChanSize)
|
||||||
|
s.chain2headSub = s.backend.SubscribeChain2HeadEvent(chain2HeadCh)
|
||||||
|
go s.loop(chainHeadCh, chain2HeadCh, txEventCh)
|
||||||
|
|
||||||
log.Info("Stats daemon started")
|
log.Info("Stats daemon started")
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -211,12 +222,13 @@ func (s *Service) Stop() error {
|
||||||
|
|
||||||
// loop keeps trying to connect to the netstats server, reporting chain events
|
// loop keeps trying to connect to the netstats server, reporting chain events
|
||||||
// until termination.
|
// until termination.
|
||||||
func (s *Service) loop(chainHeadCh chan core.ChainHeadEvent, txEventCh chan core.NewTxsEvent) {
|
func (s *Service) loop(chainHeadCh chan core.ChainHeadEvent, chain2HeadCh chan core.Chain2HeadEvent, txEventCh chan core.NewTxsEvent) {
|
||||||
// Start a goroutine that exhausts the subscriptions to avoid events piling up
|
// Start a goroutine that exhausts the subscriptions to avoid events piling up
|
||||||
var (
|
var (
|
||||||
quitCh = make(chan struct{})
|
quitCh = make(chan struct{})
|
||||||
headCh = make(chan *types.Block, 1)
|
headCh = make(chan *types.Block, 1)
|
||||||
txCh = make(chan struct{}, 1)
|
txCh = make(chan struct{}, 1)
|
||||||
|
head2Ch = make(chan core.Chain2HeadEvent, 100)
|
||||||
)
|
)
|
||||||
go func() {
|
go func() {
|
||||||
var lastTx mclock.AbsTime
|
var lastTx mclock.AbsTime
|
||||||
|
|
@ -231,6 +243,13 @@ func (s *Service) loop(chainHeadCh chan core.ChainHeadEvent, txEventCh chan core
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notify of chain2head events, but drop if too frequent
|
||||||
|
case chain2head := <-chain2HeadCh:
|
||||||
|
select {
|
||||||
|
case head2Ch <- chain2head:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
// Notify of new transaction events, but drop if too frequent
|
// Notify of new transaction events, but drop if too frequent
|
||||||
case <-txEventCh:
|
case <-txEventCh:
|
||||||
if time.Duration(mclock.Now()-lastTx) < time.Second {
|
if time.Duration(mclock.Now()-lastTx) < time.Second {
|
||||||
|
|
@ -333,6 +352,12 @@ func (s *Service) loop(chainHeadCh chan core.ChainHeadEvent, txEventCh chan core
|
||||||
if err = s.reportPending(conn); err != nil {
|
if err = s.reportPending(conn); err != nil {
|
||||||
log.Warn("Post-block transaction stats report failed", "err", err)
|
log.Warn("Post-block transaction stats report failed", "err", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case chain2head := <-head2Ch:
|
||||||
|
if err = s.reportChain2Head(conn, &chain2head); err != nil {
|
||||||
|
log.Warn("Reorg stats report failed", "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
case <-txCh:
|
case <-txCh:
|
||||||
if err = s.reportPending(conn); err != nil {
|
if err = s.reportPending(conn); err != nil {
|
||||||
log.Warn("Transaction stats report failed", "err", err)
|
log.Warn("Transaction stats report failed", "err", err)
|
||||||
|
|
@ -750,6 +775,49 @@ func (s *Service) reportPending(conn *connWrapper) error {
|
||||||
return conn.WriteJSON(report)
|
return conn.WriteJSON(report)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type blockStub struct {
|
||||||
|
Hash string `json:"hash"`
|
||||||
|
Number uint64 `json:"number"`
|
||||||
|
ParentHash string `json:"parent_hash"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func createStub(b *types.Block) *blockStub {
|
||||||
|
s := &blockStub{
|
||||||
|
Hash: b.Hash().String(),
|
||||||
|
ParentHash: b.ParentHash().String(),
|
||||||
|
Number: b.NumberU64(),
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
type ChainHeadEvent struct {
|
||||||
|
NewChain []*blockStub `json:"added"`
|
||||||
|
OldChain []*blockStub `json:"removed"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// reportChain2Head checks for reorg and sends current head to stats server.
|
||||||
|
func (s *Service) reportChain2Head(conn *connWrapper, chain2HeadData *core.Chain2HeadEvent) error {
|
||||||
|
chainHeadEvent := ChainHeadEvent{
|
||||||
|
Type: chain2HeadData.Type,
|
||||||
|
}
|
||||||
|
for _, block := range chain2HeadData.NewChain {
|
||||||
|
chainHeadEvent.NewChain = append(chainHeadEvent.NewChain, createStub(block))
|
||||||
|
}
|
||||||
|
for _, block := range chain2HeadData.OldChain {
|
||||||
|
chainHeadEvent.OldChain = append(chainHeadEvent.OldChain, createStub(block))
|
||||||
|
}
|
||||||
|
|
||||||
|
stats := map[string]interface{}{
|
||||||
|
"id": s.node,
|
||||||
|
"event": chainHeadEvent,
|
||||||
|
}
|
||||||
|
report := map[string][]interface{}{
|
||||||
|
"emit": {"headEvent", stats},
|
||||||
|
}
|
||||||
|
return conn.WriteJSON(report)
|
||||||
|
}
|
||||||
|
|
||||||
// nodeStats is the information to report about the local node.
|
// nodeStats is the information to report about the local node.
|
||||||
type nodeStats struct {
|
type nodeStats struct {
|
||||||
Active bool `json:"active"`
|
Active bool `json:"active"`
|
||||||
|
|
|
||||||
1
go.mod
1
go.mod
|
|
@ -53,6 +53,7 @@ require (
|
||||||
github.com/mattn/go-colorable v0.1.8
|
github.com/mattn/go-colorable v0.1.8
|
||||||
github.com/mattn/go-isatty v0.0.12
|
github.com/mattn/go-isatty v0.0.12
|
||||||
github.com/mitchellh/cli v1.1.2
|
github.com/mitchellh/cli v1.1.2
|
||||||
|
github.com/mitchellh/go-grpc-net-conn v0.0.0-20200427190222-eb030e4876f0 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/naoina/go-stringutil v0.1.0 // indirect
|
github.com/naoina/go-stringutil v0.1.0 // indirect
|
||||||
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416
|
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416
|
||||||
|
|
|
||||||
4
go.sum
4
go.sum
|
|
@ -33,7 +33,6 @@ github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSW
|
||||||
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
|
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
|
||||||
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||||
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||||
github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc=
|
|
||||||
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
|
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
|
||||||
github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY=
|
github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY=
|
||||||
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
|
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
|
||||||
|
|
@ -375,6 +374,8 @@ github.com/mitchellh/cli v1.1.2 h1:PvH+lL2B7IQ101xQL63Of8yFS2y+aDlsFcsqNc+u/Kw=
|
||||||
github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4=
|
github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4=
|
||||||
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
|
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
|
||||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||||
|
github.com/mitchellh/go-grpc-net-conn v0.0.0-20200427190222-eb030e4876f0 h1:oZuel4h7224ILBLg2SlTxdaMYXDyqcVfL4Cg1PJQHZs=
|
||||||
|
github.com/mitchellh/go-grpc-net-conn v0.0.0-20200427190222-eb030e4876f0/go.mod h1:ZCzL0JMR6qfm7VrDC8HGwVtPA8D2Ijc/edUSBw58x94=
|
||||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
|
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
|
||||||
|
|
@ -732,6 +733,7 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac
|
||||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||||
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
|
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package main
|
package cli
|
||||||
|
|
||||||
import "github.com/mitchellh/cli"
|
import "github.com/mitchellh/cli"
|
||||||
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
package main
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/command/flagset"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/cli/flagset"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AccountImportCommand struct {
|
type AccountImportCommand struct {
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
package main
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/command/flagset"
|
"github.com/ethereum/go-ethereum/internal/cli/flagset"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AccountListCommand struct {
|
type AccountListCommand struct {
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package main
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/command/flagset"
|
"github.com/ethereum/go-ethereum/internal/cli/flagset"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AccountNewCommand struct {
|
type AccountNewCommand struct {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package main
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
package main
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/command/flagset"
|
"github.com/ethereum/go-ethereum/internal/cli/flagset"
|
||||||
"github.com/ethereum/go-ethereum/command/server/proto"
|
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ChainSetHeadCommand is the command to group the peers commands
|
// ChainSetHeadCommand is the command to group the peers commands
|
||||||
89
internal/cli/chain_watch.go
Normal file
89
internal/cli/chain_watch.go
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/core"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/cli/flagset"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ChainWatchCommand is the command to group the peers commands
|
||||||
|
type ChainWatchCommand struct {
|
||||||
|
*Meta2
|
||||||
|
}
|
||||||
|
|
||||||
|
// Help implements the cli.Command interface
|
||||||
|
func (c *ChainWatchCommand) Help() string {
|
||||||
|
return `Usage: bor chain watch
|
||||||
|
|
||||||
|
This command is used to view the chainHead, reorg and fork events in real-time`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ChainWatchCommand) Flags() *flagset.Flagset {
|
||||||
|
flags := c.NewFlagSet("chain watch")
|
||||||
|
|
||||||
|
return flags
|
||||||
|
}
|
||||||
|
|
||||||
|
// Synopsis implements the cli.Command interface
|
||||||
|
func (c *ChainWatchCommand) Synopsis() string {
|
||||||
|
return "Watch the chainHead, reorg and fork events in real-time"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run implements the cli.Command interface
|
||||||
|
func (c *ChainWatchCommand) Run(args []string) int {
|
||||||
|
flags := c.Flags()
|
||||||
|
if err := flags.Parse(args); err != nil {
|
||||||
|
c.UI.Error(err.Error())
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
borClt, err := c.BorConn()
|
||||||
|
if err != nil {
|
||||||
|
c.UI.Error(err.Error())
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
sub, err := borClt.ChainWatch(context.Background(), &proto.ChainWatchRequest{})
|
||||||
|
if err != nil {
|
||||||
|
c.UI.Error(err.Error())
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
signalCh := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
<-signalCh
|
||||||
|
sub.CloseSend()
|
||||||
|
}()
|
||||||
|
|
||||||
|
for {
|
||||||
|
msg, err := sub.Recv()
|
||||||
|
if err != nil {
|
||||||
|
// if err == EOF if finished on the other side
|
||||||
|
c.UI.Output(err.Error())
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c.UI.Output(formatHeadEvent(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatHeadEvent(msg *proto.ChainWatchResponse) string {
|
||||||
|
var out string
|
||||||
|
if msg.Type == core.Chain2HeadCanonicalEvent {
|
||||||
|
out = fmt.Sprintf("Block Added : %v", msg.Newchain)
|
||||||
|
} else if msg.Type == core.Chain2HeadForkEvent {
|
||||||
|
out = fmt.Sprintf("New Fork Block : %v", msg.Newchain)
|
||||||
|
} else if msg.Type == core.Chain2HeadReorgEvent {
|
||||||
|
out = fmt.Sprintf("Reorg Detected \nAdded : %v \nRemoved : %v", msg.Newchain, msg.Oldchain)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
@ -1,23 +1,19 @@
|
||||||
package main
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
"github.com/ethereum/go-ethereum/command/flagset"
|
"github.com/ethereum/go-ethereum/internal/cli/flagset"
|
||||||
"github.com/ethereum/go-ethereum/command/server"
|
"github.com/ethereum/go-ethereum/internal/cli/server"
|
||||||
"github.com/ethereum/go-ethereum/command/server/proto"
|
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
"github.com/ryanuber/columnize"
|
"github.com/ryanuber/columnize"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
|
||||||
os.Exit(Run(os.Args[1:]))
|
|
||||||
}
|
|
||||||
|
|
||||||
func Run(args []string) int {
|
func Run(args []string) int {
|
||||||
commands := commands()
|
commands := commands()
|
||||||
|
|
||||||
|
|
@ -69,6 +65,11 @@ func commands() map[string]cli.CommandFactory {
|
||||||
UI: ui,
|
UI: ui,
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
"chain watch": func() (cli.Command, error) {
|
||||||
|
return &ChainWatchCommand{
|
||||||
|
Meta2: meta2,
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
"chain sethead": func() (cli.Command, error) {
|
"chain sethead": func() (cli.Command, error) {
|
||||||
return &ChainSetHeadCommand{
|
return &ChainSetHeadCommand{
|
||||||
Meta2: meta2,
|
Meta2: meta2,
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package main
|
package cli
|
||||||
|
|
||||||
// Based on https://github.com/hashicorp/nomad/blob/main/command/operator_debug.go
|
// Based on https://github.com/hashicorp/nomad/blob/main/command/operator_debug.go
|
||||||
|
|
||||||
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
@ -17,8 +16,12 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/command/flagset"
|
"github.com/ethereum/go-ethereum/internal/cli/flagset"
|
||||||
"github.com/ethereum/go-ethereum/command/server/proto"
|
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
|
||||||
|
"github.com/golang/protobuf/jsonpb"
|
||||||
|
gproto "github.com/golang/protobuf/proto"
|
||||||
|
"github.com/golang/protobuf/ptypes/empty"
|
||||||
|
grpc_net_conn "github.com/mitchellh/go-grpc-net-conn"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DebugCommand struct {
|
type DebugCommand struct {
|
||||||
|
|
@ -118,16 +121,35 @@ func (d *DebugCommand) Run(args []string) int {
|
||||||
req.Type = proto.PprofRequest_LOOKUP
|
req.Type = proto.PprofRequest_LOOKUP
|
||||||
req.Profile = profile
|
req.Profile = profile
|
||||||
}
|
}
|
||||||
resp, err := clt.Pprof(ctx, req)
|
stream, err := clt.Pprof(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// write file
|
// wait for open request
|
||||||
raw, err := hex.DecodeString(resp.Payload)
|
msg, err := stream.Recv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile(filepath.Join(tmp, filename+".prof"), raw, 0755); err != nil {
|
if _, ok := msg.Event.(*proto.PprofResponse_Open_); !ok {
|
||||||
|
return fmt.Errorf("expected open message")
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the stream
|
||||||
|
conn := &grpc_net_conn.Conn{
|
||||||
|
Stream: stream,
|
||||||
|
Response: &proto.PprofResponse_Input{},
|
||||||
|
Decode: grpc_net_conn.SimpleDecoder(func(msg gproto.Message) *[]byte {
|
||||||
|
return &msg.(*proto.PprofResponse_Input).Data
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := os.OpenFile(filepath.Join(tmp, filename+".prof"), os.O_RDWR|os.O_CREATE, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
if _, err := io.Copy(file, conn); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -148,6 +170,25 @@ func (d *DebugCommand) Run(args []string) int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// append the status
|
||||||
|
{
|
||||||
|
statusResp, err := clt.Status(ctx, &empty.Empty{})
|
||||||
|
if err != nil {
|
||||||
|
d.UI.Output(fmt.Sprintf("Failed to get status: %v", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
m := jsonpb.Marshaler{}
|
||||||
|
data, err := m.MarshalToString(statusResp)
|
||||||
|
if err != nil {
|
||||||
|
d.UI.Output(err.Error())
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if err := ioutil.WriteFile(filepath.Join(tmp, "status.json"), []byte(data), 0644); err != nil {
|
||||||
|
d.UI.Output(fmt.Sprintf("Failed to write status: %v", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Exit before archive if output directory was specified
|
// Exit before archive if output directory was specified
|
||||||
if d.output != "" {
|
if d.output != "" {
|
||||||
d.UI.Output(fmt.Sprintf("Created debug directory: %s", tmp))
|
d.UI.Output(fmt.Sprintf("Created debug directory: %s", tmp))
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package main
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
package main
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/command/flagset"
|
"github.com/ethereum/go-ethereum/internal/cli/flagset"
|
||||||
"github.com/ethereum/go-ethereum/command/server/proto"
|
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PeersAddCommand is the command to group the peers commands
|
// PeersAddCommand is the command to group the peers commands
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
package main
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/command/flagset"
|
"github.com/ethereum/go-ethereum/internal/cli/flagset"
|
||||||
"github.com/ethereum/go-ethereum/command/server/proto"
|
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PeersListCommand is the command to group the peers commands
|
// PeersListCommand is the command to group the peers commands
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
package main
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/command/flagset"
|
"github.com/ethereum/go-ethereum/internal/cli/flagset"
|
||||||
"github.com/ethereum/go-ethereum/command/server/proto"
|
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PeersRemoveCommand is the command to group the peers commands
|
// PeersRemoveCommand is the command to group the peers commands
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
package main
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/command/flagset"
|
"github.com/ethereum/go-ethereum/internal/cli/flagset"
|
||||||
"github.com/ethereum/go-ethereum/command/server/proto"
|
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PeersStatusCommand is the command to group the peers commands
|
// PeersStatusCommand is the command to group the peers commands
|
||||||
47
internal/cli/server/chains/developer.go
Normal file
47
internal/cli/server/chains/developer.go
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
package chains
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetDeveloperChain returns the developer mode configs.
|
||||||
|
func GetDeveloperChain(period uint64, faucet common.Address) *Chain {
|
||||||
|
// Override the default period to the user requested one
|
||||||
|
config := *params.AllCliqueProtocolChanges
|
||||||
|
config.Clique = ¶ms.CliqueConfig{
|
||||||
|
Period: period,
|
||||||
|
Epoch: config.Clique.Epoch,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble and return the chain having genesis with the
|
||||||
|
// precompiles and faucet pre-funded
|
||||||
|
return &Chain{
|
||||||
|
Hash: common.Hash{},
|
||||||
|
NetworkId: 1337,
|
||||||
|
Genesis: &core.Genesis{
|
||||||
|
Config: &config,
|
||||||
|
ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, crypto.SignatureLength)...),
|
||||||
|
GasLimit: 11500000,
|
||||||
|
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||||
|
Difficulty: big.NewInt(1),
|
||||||
|
Alloc: map[common.Address]core.GenesisAccount{
|
||||||
|
common.BytesToAddress([]byte{1}): {Balance: big.NewInt(1)}, // ECRecover
|
||||||
|
common.BytesToAddress([]byte{2}): {Balance: big.NewInt(1)}, // SHA256
|
||||||
|
common.BytesToAddress([]byte{3}): {Balance: big.NewInt(1)}, // RIPEMD
|
||||||
|
common.BytesToAddress([]byte{4}): {Balance: big.NewInt(1)}, // Identity
|
||||||
|
common.BytesToAddress([]byte{5}): {Balance: big.NewInt(1)}, // ModExp
|
||||||
|
common.BytesToAddress([]byte{6}): {Balance: big.NewInt(1)}, // ECAdd
|
||||||
|
common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul
|
||||||
|
common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing
|
||||||
|
common.BytesToAddress([]byte{9}): {Balance: big.NewInt(1)}, // BLAKE2b
|
||||||
|
faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Bootnodes: []string{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,12 +14,14 @@ import (
|
||||||
|
|
||||||
godebug "runtime/debug"
|
godebug "runtime/debug"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/command/server/chains"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/fdlimit"
|
"github.com/ethereum/go-ethereum/common/fdlimit"
|
||||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||||
"github.com/ethereum/go-ethereum/eth/gasprice"
|
"github.com/ethereum/go-ethereum/eth/gasprice"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/cli/server/chains"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
|
|
@ -91,6 +93,9 @@ type Config struct {
|
||||||
|
|
||||||
// GRPC has the grpc server related settings
|
// GRPC has the grpc server related settings
|
||||||
GRPC *GRPCConfig
|
GRPC *GRPCConfig
|
||||||
|
|
||||||
|
// Developer has the developer mode related settings
|
||||||
|
Developer *DeveloperConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
type P2PConfig struct {
|
type P2PConfig struct {
|
||||||
|
|
@ -365,6 +370,14 @@ type AccountsConfig struct {
|
||||||
UseLightweightKDF bool `hcl:"use-lightweight-kdf,optional"`
|
UseLightweightKDF bool `hcl:"use-lightweight-kdf,optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DeveloperConfig struct {
|
||||||
|
// Enabled enables the developer mode
|
||||||
|
Enabled bool `hcl:"dev,optional"`
|
||||||
|
|
||||||
|
// Period is the block period to use in developer mode
|
||||||
|
Period uint64 `hcl:"period,optional"`
|
||||||
|
}
|
||||||
|
|
||||||
func DefaultConfig() *Config {
|
func DefaultConfig() *Config {
|
||||||
return &Config{
|
return &Config{
|
||||||
Chain: "mainnet",
|
Chain: "mainnet",
|
||||||
|
|
@ -486,6 +499,10 @@ func DefaultConfig() *Config {
|
||||||
GRPC: &GRPCConfig{
|
GRPC: &GRPCConfig{
|
||||||
Addr: ":3131",
|
Addr: ":3131",
|
||||||
},
|
},
|
||||||
|
Developer: &DeveloperConfig{
|
||||||
|
Enabled: false,
|
||||||
|
Period: 0,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -573,6 +590,9 @@ func readConfigFile(path string) (*Config, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) loadChain() error {
|
func (c *Config) loadChain() error {
|
||||||
|
if c.Developer.Enabled {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
chain, ok := chains.GetChain(c.Chain)
|
chain, ok := chains.GetChain(c.Chain)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("chain '%s' not found", c.Chain)
|
return fmt.Errorf("chain '%s' not found", c.Chain)
|
||||||
|
|
@ -585,7 +605,7 @@ func (c *Config) loadChain() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// depending on the chain we have different cache values
|
// depending on the chain we have different cache values
|
||||||
if c.Chain != "mainnet" {
|
if c.Chain == "mainnet" {
|
||||||
c.Cache.Cache = 4096
|
c.Cache.Cache = 4096
|
||||||
} else {
|
} else {
|
||||||
c.Cache.Cache = 1024
|
c.Cache.Cache = 1024
|
||||||
|
|
@ -593,14 +613,19 @@ func (c *Config) loadChain() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) buildEth() (*ethconfig.Config, error) {
|
func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) {
|
||||||
dbHandles, err := makeDatabaseHandles()
|
dbHandles, err := makeDatabaseHandles()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
n := ethconfig.Defaults
|
n := ethconfig.Defaults
|
||||||
n.NetworkId = c.chain.NetworkId
|
|
||||||
n.Genesis = c.chain.Genesis
|
// only update for non-developer mode as we don't yet
|
||||||
|
// have the chain object for it.
|
||||||
|
if !c.Developer.Enabled {
|
||||||
|
n.NetworkId = c.chain.NetworkId
|
||||||
|
n.Genesis = c.chain.Genesis
|
||||||
|
}
|
||||||
n.HeimdallURL = c.Heimdall.URL
|
n.HeimdallURL = c.Heimdall.URL
|
||||||
n.WithoutHeimdall = c.Heimdall.Without
|
n.WithoutHeimdall = c.Heimdall.Without
|
||||||
|
|
||||||
|
|
@ -640,6 +665,55 @@ func (c *Config) buildEth() (*ethconfig.Config, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update for developer mode
|
||||||
|
if c.Developer.Enabled {
|
||||||
|
// Get a keystore
|
||||||
|
var ks *keystore.KeyStore
|
||||||
|
if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 {
|
||||||
|
ks = keystores[0].(*keystore.KeyStore)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new developer account or reuse existing one
|
||||||
|
var (
|
||||||
|
developer accounts.Account
|
||||||
|
passphrase string
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
// etherbase has been set above, configuring the miner address from command line flags.
|
||||||
|
if n.Miner.Etherbase != (common.Address{}) {
|
||||||
|
developer = accounts.Account{Address: n.Miner.Etherbase}
|
||||||
|
} else if accs := ks.Accounts(); len(accs) > 0 {
|
||||||
|
developer = ks.Accounts()[0]
|
||||||
|
} else {
|
||||||
|
developer, err = ks.NewAccount(passphrase)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create developer account: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := ks.Unlock(developer, passphrase); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to unlock developer account: %v", err)
|
||||||
|
}
|
||||||
|
log.Info("Using developer account", "address", developer.Address)
|
||||||
|
|
||||||
|
// get developer mode chain config
|
||||||
|
c.chain = chains.GetDeveloperChain(c.Developer.Period, developer.Address)
|
||||||
|
|
||||||
|
// update the parameters
|
||||||
|
n.NetworkId = c.chain.NetworkId
|
||||||
|
n.Genesis = c.chain.Genesis
|
||||||
|
|
||||||
|
// Update cache
|
||||||
|
c.Cache.Cache = 1024
|
||||||
|
|
||||||
|
// Update sync mode
|
||||||
|
c.SyncMode = "full"
|
||||||
|
|
||||||
|
// update miner gas price
|
||||||
|
if n.Miner.GasPrice == nil {
|
||||||
|
n.Miner.GasPrice = big.NewInt(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// discovery (this params should be in node.Config)
|
// discovery (this params should be in node.Config)
|
||||||
{
|
{
|
||||||
n.EthDiscoveryURLs = c.P2P.Discovery.DNS
|
n.EthDiscoveryURLs = c.P2P.Discovery.DNS
|
||||||
|
|
@ -786,6 +860,17 @@ func (c *Config) buildNode() (*node.Config, error) {
|
||||||
GraphQLVirtualHosts: c.JsonRPC.VHost,
|
GraphQLVirtualHosts: c.JsonRPC.VHost,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dev mode
|
||||||
|
if c.Developer.Enabled {
|
||||||
|
cfg.UseLightweightKDF = true
|
||||||
|
|
||||||
|
// disable p2p networking
|
||||||
|
c.P2P.NoDiscover = true
|
||||||
|
cfg.P2P.ListenAddr = ""
|
||||||
|
cfg.P2P.NoDial = true
|
||||||
|
cfg.P2P.DiscoveryV5 = false
|
||||||
|
}
|
||||||
|
|
||||||
// enable jsonrpc endpoints
|
// enable jsonrpc endpoints
|
||||||
{
|
{
|
||||||
if c.JsonRPC.Http.Enabled {
|
if c.JsonRPC.Http.Enabled {
|
||||||
|
|
@ -804,23 +889,26 @@ func (c *Config) buildNode() (*node.Config, error) {
|
||||||
}
|
}
|
||||||
cfg.P2P.NAT = natif
|
cfg.P2P.NAT = natif
|
||||||
|
|
||||||
// Discovery
|
// only check for non-developer modes
|
||||||
// if no bootnodes are defined, use the ones from the chain file.
|
if !c.Developer.Enabled {
|
||||||
bootnodes := c.P2P.Discovery.Bootnodes
|
// Discovery
|
||||||
if len(bootnodes) == 0 {
|
// if no bootnodes are defined, use the ones from the chain file.
|
||||||
bootnodes = c.chain.Bootnodes
|
bootnodes := c.P2P.Discovery.Bootnodes
|
||||||
}
|
if len(bootnodes) == 0 {
|
||||||
if cfg.P2P.BootstrapNodes, err = parseBootnodes(bootnodes); err != nil {
|
bootnodes = c.chain.Bootnodes
|
||||||
return nil, err
|
}
|
||||||
}
|
if cfg.P2P.BootstrapNodes, err = parseBootnodes(bootnodes); err != nil {
|
||||||
if cfg.P2P.BootstrapNodesV5, err = parseBootnodes(c.P2P.Discovery.BootnodesV5); err != nil {
|
return nil, err
|
||||||
return nil, err
|
}
|
||||||
}
|
if cfg.P2P.BootstrapNodesV5, err = parseBootnodes(c.P2P.Discovery.BootnodesV5); err != nil {
|
||||||
if cfg.P2P.StaticNodes, err = parseBootnodes(c.P2P.Discovery.StaticNodes); err != nil {
|
return nil, err
|
||||||
return nil, err
|
}
|
||||||
}
|
if cfg.P2P.StaticNodes, err = parseBootnodes(c.P2P.Discovery.StaticNodes); err != nil {
|
||||||
if cfg.P2P.TrustedNodes, err = parseBootnodes(c.P2P.Discovery.TrustedNodes); err != nil {
|
return nil, err
|
||||||
return nil, err
|
}
|
||||||
|
if cfg.P2P.TrustedNodes, err = parseBootnodes(c.P2P.Discovery.TrustedNodes); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.P2P.NoDiscover {
|
if c.P2P.NoDiscover {
|
||||||
|
|
@ -16,7 +16,7 @@ func TestConfigDefault(t *testing.T) {
|
||||||
_, err := config.buildNode()
|
_, err := config.buildNode()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
_, err = config.buildEth()
|
_, err = config.buildEth(nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/ethereum/go-ethereum/command/flagset"
|
"github.com/ethereum/go-ethereum/internal/cli/flagset"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Command) Flags() *flagset.Flagset {
|
func (c *Command) Flags() *flagset.Flagset {
|
||||||
|
|
@ -461,5 +461,17 @@ func (c *Command) Flags() *flagset.Flagset {
|
||||||
Usage: "Address and port to bind the GRPC server",
|
Usage: "Address and port to bind the GRPC server",
|
||||||
Value: &c.cliConfig.GRPC.Addr,
|
Value: &c.cliConfig.GRPC.Addr,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// developer
|
||||||
|
f.BoolFlag(&flagset.BoolFlag{
|
||||||
|
Name: "dev",
|
||||||
|
Usage: "Enable developer mode with ephemeral proof-of-authority network and a pre-funded developer account, mining enabled",
|
||||||
|
Value: &c.cliConfig.Developer.Enabled,
|
||||||
|
})
|
||||||
|
f.Uint64Flag(&flagset.Uint64Flag{
|
||||||
|
Name: "dev.period",
|
||||||
|
Usage: "Block period to use in developer mode (0 = mine only if transaction pending)",
|
||||||
|
Value: &c.cliConfig.Developer.Period,
|
||||||
|
})
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -7,7 +7,7 @@ import "google/protobuf/empty.proto";
|
||||||
option go_package = "/command/server/proto";
|
option go_package = "/command/server/proto";
|
||||||
|
|
||||||
service Bor {
|
service Bor {
|
||||||
rpc Pprof(PprofRequest) returns (PprofResponse);
|
rpc Pprof(PprofRequest) returns (stream PprofResponse);
|
||||||
|
|
||||||
rpc PeersAdd(PeersAddRequest) returns (PeersAddResponse);
|
rpc PeersAdd(PeersAddRequest) returns (PeersAddResponse);
|
||||||
|
|
||||||
|
|
@ -20,8 +20,24 @@ service Bor {
|
||||||
rpc ChainSetHead(ChainSetHeadRequest) returns (ChainSetHeadResponse);
|
rpc ChainSetHead(ChainSetHeadRequest) returns (ChainSetHeadResponse);
|
||||||
|
|
||||||
rpc Status(google.protobuf.Empty) returns (StatusResponse);
|
rpc Status(google.protobuf.Empty) returns (StatusResponse);
|
||||||
|
|
||||||
|
rpc ChainWatch(ChainWatchRequest) returns (stream ChainWatchResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ChainWatchRequest {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
message ChainWatchResponse {
|
||||||
|
repeated BlockStub oldchain = 1;
|
||||||
|
repeated BlockStub newchain = 2;
|
||||||
|
string type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BlockStub {
|
||||||
|
string hash = 1;
|
||||||
|
uint64 number = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message PeersAddRequest {
|
message PeersAddRequest {
|
||||||
string enode = 1;
|
string enode = 1;
|
||||||
|
|
@ -77,6 +93,13 @@ message StatusResponse {
|
||||||
int64 numPeers = 3;
|
int64 numPeers = 3;
|
||||||
string syncMode = 4;
|
string syncMode = 4;
|
||||||
Syncing syncing = 5;
|
Syncing syncing = 5;
|
||||||
|
repeated Fork forks = 6;
|
||||||
|
|
||||||
|
message Fork {
|
||||||
|
string name = 1;
|
||||||
|
int64 block = 2;
|
||||||
|
bool disabled = 3;
|
||||||
|
}
|
||||||
|
|
||||||
message Syncing {
|
message Syncing {
|
||||||
int64 startingBlock = 1;
|
int64 startingBlock = 1;
|
||||||
|
|
@ -105,6 +128,18 @@ message PprofRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
message PprofResponse {
|
message PprofResponse {
|
||||||
string payload = 1;
|
oneof event {
|
||||||
map<string, string> headers = 2;
|
Open open = 1;
|
||||||
|
Input input = 2;
|
||||||
|
google.protobuf.Empty eof = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Open {
|
||||||
|
map<string, string> headers = 1;
|
||||||
|
int64 size = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Input {
|
||||||
|
bytes data = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,13 +1,17 @@
|
||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// - protoc-gen-go-grpc v1.2.0
|
||||||
|
// - protoc v3.17.3
|
||||||
|
// source: command/server/proto/server.proto
|
||||||
|
|
||||||
package proto
|
package proto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
empty "github.com/golang/protobuf/ptypes/empty"
|
|
||||||
grpc "google.golang.org/grpc"
|
grpc "google.golang.org/grpc"
|
||||||
codes "google.golang.org/grpc/codes"
|
codes "google.golang.org/grpc/codes"
|
||||||
status "google.golang.org/grpc/status"
|
status "google.golang.org/grpc/status"
|
||||||
|
emptypb "google.golang.org/protobuf/types/known/emptypb"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
|
@ -19,13 +23,14 @@ const _ = grpc.SupportPackageIsVersion7
|
||||||
//
|
//
|
||||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||||
type BorClient interface {
|
type BorClient interface {
|
||||||
Pprof(ctx context.Context, in *PprofRequest, opts ...grpc.CallOption) (*PprofResponse, error)
|
Pprof(ctx context.Context, in *PprofRequest, opts ...grpc.CallOption) (Bor_PprofClient, error)
|
||||||
PeersAdd(ctx context.Context, in *PeersAddRequest, opts ...grpc.CallOption) (*PeersAddResponse, error)
|
PeersAdd(ctx context.Context, in *PeersAddRequest, opts ...grpc.CallOption) (*PeersAddResponse, error)
|
||||||
PeersRemove(ctx context.Context, in *PeersRemoveRequest, opts ...grpc.CallOption) (*PeersRemoveResponse, error)
|
PeersRemove(ctx context.Context, in *PeersRemoveRequest, opts ...grpc.CallOption) (*PeersRemoveResponse, error)
|
||||||
PeersList(ctx context.Context, in *PeersListRequest, opts ...grpc.CallOption) (*PeersListResponse, error)
|
PeersList(ctx context.Context, in *PeersListRequest, opts ...grpc.CallOption) (*PeersListResponse, error)
|
||||||
PeersStatus(ctx context.Context, in *PeersStatusRequest, opts ...grpc.CallOption) (*PeersStatusResponse, error)
|
PeersStatus(ctx context.Context, in *PeersStatusRequest, opts ...grpc.CallOption) (*PeersStatusResponse, error)
|
||||||
ChainSetHead(ctx context.Context, in *ChainSetHeadRequest, opts ...grpc.CallOption) (*ChainSetHeadResponse, error)
|
ChainSetHead(ctx context.Context, in *ChainSetHeadRequest, opts ...grpc.CallOption) (*ChainSetHeadResponse, error)
|
||||||
Status(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*StatusResponse, error)
|
Status(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*StatusResponse, error)
|
||||||
|
ChainWatch(ctx context.Context, in *ChainWatchRequest, opts ...grpc.CallOption) (Bor_ChainWatchClient, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type borClient struct {
|
type borClient struct {
|
||||||
|
|
@ -36,13 +41,36 @@ func NewBorClient(cc grpc.ClientConnInterface) BorClient {
|
||||||
return &borClient{cc}
|
return &borClient{cc}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *borClient) Pprof(ctx context.Context, in *PprofRequest, opts ...grpc.CallOption) (*PprofResponse, error) {
|
func (c *borClient) Pprof(ctx context.Context, in *PprofRequest, opts ...grpc.CallOption) (Bor_PprofClient, error) {
|
||||||
out := new(PprofResponse)
|
stream, err := c.cc.NewStream(ctx, &Bor_ServiceDesc.Streams[0], "/proto.Bor/Pprof", opts...)
|
||||||
err := c.cc.Invoke(ctx, "/proto.Bor/Pprof", in, out, opts...)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return out, nil
|
x := &borPprofClient{stream}
|
||||||
|
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := x.ClientStream.CloseSend(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return x, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bor_PprofClient interface {
|
||||||
|
Recv() (*PprofResponse, error)
|
||||||
|
grpc.ClientStream
|
||||||
|
}
|
||||||
|
|
||||||
|
type borPprofClient struct {
|
||||||
|
grpc.ClientStream
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *borPprofClient) Recv() (*PprofResponse, error) {
|
||||||
|
m := new(PprofResponse)
|
||||||
|
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *borClient) PeersAdd(ctx context.Context, in *PeersAddRequest, opts ...grpc.CallOption) (*PeersAddResponse, error) {
|
func (c *borClient) PeersAdd(ctx context.Context, in *PeersAddRequest, opts ...grpc.CallOption) (*PeersAddResponse, error) {
|
||||||
|
|
@ -90,7 +118,7 @@ func (c *borClient) ChainSetHead(ctx context.Context, in *ChainSetHeadRequest, o
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *borClient) Status(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*StatusResponse, error) {
|
func (c *borClient) Status(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*StatusResponse, error) {
|
||||||
out := new(StatusResponse)
|
out := new(StatusResponse)
|
||||||
err := c.cc.Invoke(ctx, "/proto.Bor/Status", in, out, opts...)
|
err := c.cc.Invoke(ctx, "/proto.Bor/Status", in, out, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -99,17 +127,50 @@ func (c *borClient) Status(ctx context.Context, in *empty.Empty, opts ...grpc.Ca
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *borClient) ChainWatch(ctx context.Context, in *ChainWatchRequest, opts ...grpc.CallOption) (Bor_ChainWatchClient, error) {
|
||||||
|
stream, err := c.cc.NewStream(ctx, &Bor_ServiceDesc.Streams[1], "/proto.Bor/ChainWatch", opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
x := &borChainWatchClient{stream}
|
||||||
|
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := x.ClientStream.CloseSend(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return x, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bor_ChainWatchClient interface {
|
||||||
|
Recv() (*ChainWatchResponse, error)
|
||||||
|
grpc.ClientStream
|
||||||
|
}
|
||||||
|
|
||||||
|
type borChainWatchClient struct {
|
||||||
|
grpc.ClientStream
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *borChainWatchClient) Recv() (*ChainWatchResponse, error) {
|
||||||
|
m := new(ChainWatchResponse)
|
||||||
|
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
// BorServer is the server API for Bor service.
|
// BorServer is the server API for Bor service.
|
||||||
// All implementations must embed UnimplementedBorServer
|
// All implementations must embed UnimplementedBorServer
|
||||||
// for forward compatibility
|
// for forward compatibility
|
||||||
type BorServer interface {
|
type BorServer interface {
|
||||||
Pprof(context.Context, *PprofRequest) (*PprofResponse, error)
|
Pprof(*PprofRequest, Bor_PprofServer) error
|
||||||
PeersAdd(context.Context, *PeersAddRequest) (*PeersAddResponse, error)
|
PeersAdd(context.Context, *PeersAddRequest) (*PeersAddResponse, error)
|
||||||
PeersRemove(context.Context, *PeersRemoveRequest) (*PeersRemoveResponse, error)
|
PeersRemove(context.Context, *PeersRemoveRequest) (*PeersRemoveResponse, error)
|
||||||
PeersList(context.Context, *PeersListRequest) (*PeersListResponse, error)
|
PeersList(context.Context, *PeersListRequest) (*PeersListResponse, error)
|
||||||
PeersStatus(context.Context, *PeersStatusRequest) (*PeersStatusResponse, error)
|
PeersStatus(context.Context, *PeersStatusRequest) (*PeersStatusResponse, error)
|
||||||
ChainSetHead(context.Context, *ChainSetHeadRequest) (*ChainSetHeadResponse, error)
|
ChainSetHead(context.Context, *ChainSetHeadRequest) (*ChainSetHeadResponse, error)
|
||||||
Status(context.Context, *empty.Empty) (*StatusResponse, error)
|
Status(context.Context, *emptypb.Empty) (*StatusResponse, error)
|
||||||
|
ChainWatch(*ChainWatchRequest, Bor_ChainWatchServer) error
|
||||||
mustEmbedUnimplementedBorServer()
|
mustEmbedUnimplementedBorServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,8 +178,8 @@ type BorServer interface {
|
||||||
type UnimplementedBorServer struct {
|
type UnimplementedBorServer struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (UnimplementedBorServer) Pprof(context.Context, *PprofRequest) (*PprofResponse, error) {
|
func (UnimplementedBorServer) Pprof(*PprofRequest, Bor_PprofServer) error {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method Pprof not implemented")
|
return status.Errorf(codes.Unimplemented, "method Pprof not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedBorServer) PeersAdd(context.Context, *PeersAddRequest) (*PeersAddResponse, error) {
|
func (UnimplementedBorServer) PeersAdd(context.Context, *PeersAddRequest) (*PeersAddResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method PeersAdd not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method PeersAdd not implemented")
|
||||||
|
|
@ -135,9 +196,12 @@ func (UnimplementedBorServer) PeersStatus(context.Context, *PeersStatusRequest)
|
||||||
func (UnimplementedBorServer) ChainSetHead(context.Context, *ChainSetHeadRequest) (*ChainSetHeadResponse, error) {
|
func (UnimplementedBorServer) ChainSetHead(context.Context, *ChainSetHeadRequest) (*ChainSetHeadResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method ChainSetHead not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method ChainSetHead not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedBorServer) Status(context.Context, *empty.Empty) (*StatusResponse, error) {
|
func (UnimplementedBorServer) Status(context.Context, *emptypb.Empty) (*StatusResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method Status not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method Status not implemented")
|
||||||
}
|
}
|
||||||
|
func (UnimplementedBorServer) ChainWatch(*ChainWatchRequest, Bor_ChainWatchServer) error {
|
||||||
|
return status.Errorf(codes.Unimplemented, "method ChainWatch not implemented")
|
||||||
|
}
|
||||||
func (UnimplementedBorServer) mustEmbedUnimplementedBorServer() {}
|
func (UnimplementedBorServer) mustEmbedUnimplementedBorServer() {}
|
||||||
|
|
||||||
// UnsafeBorServer may be embedded to opt out of forward compatibility for this service.
|
// UnsafeBorServer may be embedded to opt out of forward compatibility for this service.
|
||||||
|
|
@ -151,22 +215,25 @@ func RegisterBorServer(s grpc.ServiceRegistrar, srv BorServer) {
|
||||||
s.RegisterService(&Bor_ServiceDesc, srv)
|
s.RegisterService(&Bor_ServiceDesc, srv)
|
||||||
}
|
}
|
||||||
|
|
||||||
func _Bor_Pprof_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
func _Bor_Pprof_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||||
in := new(PprofRequest)
|
m := new(PprofRequest)
|
||||||
if err := dec(in); err != nil {
|
if err := stream.RecvMsg(m); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
if interceptor == nil {
|
return srv.(BorServer).Pprof(m, &borPprofServer{stream})
|
||||||
return srv.(BorServer).Pprof(ctx, in)
|
}
|
||||||
}
|
|
||||||
info := &grpc.UnaryServerInfo{
|
type Bor_PprofServer interface {
|
||||||
Server: srv,
|
Send(*PprofResponse) error
|
||||||
FullMethod: "/proto.Bor/Pprof",
|
grpc.ServerStream
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
|
||||||
return srv.(BorServer).Pprof(ctx, req.(*PprofRequest))
|
type borPprofServer struct {
|
||||||
}
|
grpc.ServerStream
|
||||||
return interceptor(ctx, in, info, handler)
|
}
|
||||||
|
|
||||||
|
func (x *borPprofServer) Send(m *PprofResponse) error {
|
||||||
|
return x.ServerStream.SendMsg(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func _Bor_PeersAdd_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
func _Bor_PeersAdd_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
|
@ -260,7 +327,7 @@ func _Bor_ChainSetHead_Handler(srv interface{}, ctx context.Context, dec func(in
|
||||||
}
|
}
|
||||||
|
|
||||||
func _Bor_Status_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
func _Bor_Status_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
in := new(empty.Empty)
|
in := new(emptypb.Empty)
|
||||||
if err := dec(in); err != nil {
|
if err := dec(in); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -272,11 +339,32 @@ func _Bor_Status_Handler(srv interface{}, ctx context.Context, dec func(interfac
|
||||||
FullMethod: "/proto.Bor/Status",
|
FullMethod: "/proto.Bor/Status",
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(BorServer).Status(ctx, req.(*empty.Empty))
|
return srv.(BorServer).Status(ctx, req.(*emptypb.Empty))
|
||||||
}
|
}
|
||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _Bor_ChainWatch_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||||
|
m := new(ChainWatchRequest)
|
||||||
|
if err := stream.RecvMsg(m); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return srv.(BorServer).ChainWatch(m, &borChainWatchServer{stream})
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bor_ChainWatchServer interface {
|
||||||
|
Send(*ChainWatchResponse) error
|
||||||
|
grpc.ServerStream
|
||||||
|
}
|
||||||
|
|
||||||
|
type borChainWatchServer struct {
|
||||||
|
grpc.ServerStream
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *borChainWatchServer) Send(m *ChainWatchResponse) error {
|
||||||
|
return x.ServerStream.SendMsg(m)
|
||||||
|
}
|
||||||
|
|
||||||
// Bor_ServiceDesc is the grpc.ServiceDesc for Bor service.
|
// Bor_ServiceDesc is the grpc.ServiceDesc for Bor service.
|
||||||
// It's only intended for direct use with grpc.RegisterService,
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
// and not to be introspected or modified (even as a copy)
|
// and not to be introspected or modified (even as a copy)
|
||||||
|
|
@ -284,10 +372,6 @@ var Bor_ServiceDesc = grpc.ServiceDesc{
|
||||||
ServiceName: "proto.Bor",
|
ServiceName: "proto.Bor",
|
||||||
HandlerType: (*BorServer)(nil),
|
HandlerType: (*BorServer)(nil),
|
||||||
Methods: []grpc.MethodDesc{
|
Methods: []grpc.MethodDesc{
|
||||||
{
|
|
||||||
MethodName: "Pprof",
|
|
||||||
Handler: _Bor_Pprof_Handler,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
MethodName: "PeersAdd",
|
MethodName: "PeersAdd",
|
||||||
Handler: _Bor_PeersAdd_Handler,
|
Handler: _Bor_PeersAdd_Handler,
|
||||||
|
|
@ -313,6 +397,17 @@ var Bor_ServiceDesc = grpc.ServiceDesc{
|
||||||
Handler: _Bor_Status_Handler,
|
Handler: _Bor_Status_Handler,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{},
|
Streams: []grpc.StreamDesc{
|
||||||
|
{
|
||||||
|
StreamName: "Pprof",
|
||||||
|
Handler: _Bor_Pprof_Handler,
|
||||||
|
ServerStreams: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
StreamName: "ChainWatch",
|
||||||
|
Handler: _Bor_ChainWatch_Handler,
|
||||||
|
ServerStreams: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
Metadata: "command/server/proto/server.proto",
|
Metadata: "command/server/proto/server.proto",
|
||||||
}
|
}
|
||||||
|
|
@ -11,11 +11,11 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
"github.com/ethereum/go-ethereum/command/server/proto"
|
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/eth/tracers"
|
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||||
"github.com/ethereum/go-ethereum/ethstats"
|
"github.com/ethereum/go-ethereum/ethstats"
|
||||||
"github.com/ethereum/go-ethereum/graphql"
|
"github.com/ethereum/go-ethereum/graphql"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
"github.com/ethereum/go-ethereum/metrics/influxdb"
|
"github.com/ethereum/go-ethereum/metrics/influxdb"
|
||||||
|
|
@ -69,11 +69,22 @@ func NewServer(config *Config) (*Server, error) {
|
||||||
}
|
}
|
||||||
srv.node = stack
|
srv.node = stack
|
||||||
|
|
||||||
|
// setup account manager (only keystore)
|
||||||
|
{
|
||||||
|
keydir := stack.KeyStoreDir()
|
||||||
|
n, p := keystore.StandardScryptN, keystore.StandardScryptP
|
||||||
|
if config.Accounts.UseLightweightKDF {
|
||||||
|
n, p = keystore.LightScryptN, keystore.LightScryptP
|
||||||
|
}
|
||||||
|
stack.AccountManager().AddBackend(keystore.NewKeyStore(keydir, n, p))
|
||||||
|
}
|
||||||
|
|
||||||
// register the ethereum backend
|
// register the ethereum backend
|
||||||
ethCfg, err := config.buildEth()
|
ethCfg, err := config.buildEth(stack)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
backend, err := eth.New(stack, ethCfg)
|
backend, err := eth.New(stack, ethCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -97,18 +108,8 @@ func NewServer(config *Config) (*Server, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup account manager (only keystore)
|
// sealing (if enabled) or in dev mode
|
||||||
{
|
if config.Sealer.Enabled || config.Developer.Enabled {
|
||||||
keydir := stack.KeyStoreDir()
|
|
||||||
n, p := keystore.StandardScryptN, keystore.StandardScryptP
|
|
||||||
if config.Accounts.UseLightweightKDF {
|
|
||||||
n, p = keystore.LightScryptN, keystore.LightScryptP
|
|
||||||
}
|
|
||||||
stack.AccountManager().AddBackend(keystore.NewKeyStore(keydir, n, p))
|
|
||||||
}
|
|
||||||
|
|
||||||
// sealing (if enabled)
|
|
||||||
if config.Sealer.Enabled {
|
|
||||||
if err := backend.StartMining(1); err != nil {
|
if err := backend.StartMining(1); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
41
internal/cli/server/server_test.go
Normal file
41
internal/cli/server/server_test.go
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestServer_DeveloperMode(t *testing.T) {
|
||||||
|
|
||||||
|
// get the default config
|
||||||
|
config := DefaultConfig()
|
||||||
|
|
||||||
|
// enable developer mode
|
||||||
|
config.Developer.Enabled = true
|
||||||
|
config.Developer.Period = 2 // block time
|
||||||
|
|
||||||
|
// start the server
|
||||||
|
server, err1 := NewServer(config)
|
||||||
|
if err1 != nil {
|
||||||
|
t.Fatalf("failed to start server: %v", err1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// record the initial block number
|
||||||
|
blockNumber := server.backend.BlockChain().CurrentBlock().Header().Number.Int64()
|
||||||
|
|
||||||
|
var i int64 = 0
|
||||||
|
for i = 0; i < 10; i++ {
|
||||||
|
// We expect the node to mine blocks every `config.Developer.Period` time period
|
||||||
|
time.Sleep(time.Duration(config.Developer.Period) * time.Second)
|
||||||
|
currBlock := server.backend.BlockChain().CurrentBlock().Header().Number.Int64()
|
||||||
|
expected := blockNumber + i + 1
|
||||||
|
if res := assert.Equal(t, currBlock, expected); res == false {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop the server
|
||||||
|
server.Stop()
|
||||||
|
}
|
||||||
|
|
@ -2,23 +2,28 @@ package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/command/server/pprof"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/command/server/proto"
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/cli/server/pprof"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
|
gproto "github.com/golang/protobuf/proto"
|
||||||
"github.com/golang/protobuf/ptypes/empty"
|
"github.com/golang/protobuf/ptypes/empty"
|
||||||
|
grpc_net_conn "github.com/mitchellh/go-grpc-net-conn"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) Pprof(ctx context.Context, req *proto.PprofRequest) (*proto.PprofResponse, error) {
|
func (s *Server) Pprof(req *proto.PprofRequest, stream proto.Bor_PprofServer) error {
|
||||||
var payload []byte
|
var payload []byte
|
||||||
var headers map[string]string
|
var headers map[string]string
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
switch req.Type {
|
switch req.Type {
|
||||||
case proto.PprofRequest_CPU:
|
case proto.PprofRequest_CPU:
|
||||||
payload, headers, err = pprof.CPUProfile(ctx, int(req.Seconds))
|
payload, headers, err = pprof.CPUProfile(ctx, int(req.Seconds))
|
||||||
|
|
@ -28,14 +33,42 @@ func (s *Server) Pprof(ctx context.Context, req *proto.PprofRequest) (*proto.Ppr
|
||||||
payload, headers, err = pprof.Profile(req.Profile, 0, 0)
|
payload, headers, err = pprof.Profile(req.Profile, 0, 0)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := &proto.PprofResponse{
|
// open the stream and send the headers
|
||||||
Payload: hex.EncodeToString(payload),
|
err = stream.Send(&proto.PprofResponse{
|
||||||
Headers: headers,
|
Event: &proto.PprofResponse_Open_{
|
||||||
|
Open: &proto.PprofResponse_Open{
|
||||||
|
Headers: headers,
|
||||||
|
Size: int64(len(payload)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
return resp, nil
|
|
||||||
|
// Wrap our conn around the response.
|
||||||
|
conn := &grpc_net_conn.Conn{
|
||||||
|
Stream: stream,
|
||||||
|
Request: &proto.PprofResponse_Input{},
|
||||||
|
Encode: grpc_net_conn.SimpleEncoder(func(msg gproto.Message) *[]byte {
|
||||||
|
return &msg.(*proto.PprofResponse_Input).Data
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
if _, err := conn.Write(payload); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// send the eof
|
||||||
|
err = stream.Send(&proto.PprofResponse{
|
||||||
|
Event: &proto.PprofResponse_Eof{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) PeersAdd(ctx context.Context, req *proto.PeersAddRequest) (*proto.PeersAddResponse, error) {
|
func (s *Server) PeersAdd(ctx context.Context, req *proto.PeersAddRequest) (*proto.PeersAddResponse, error) {
|
||||||
|
|
@ -124,6 +157,7 @@ func (s *Server) Status(ctx context.Context, _ *empty.Empty) (*proto.StatusRespo
|
||||||
HighestBlock: int64(syncProgress.HighestBlock),
|
HighestBlock: int64(syncProgress.HighestBlock),
|
||||||
CurrentBlock: int64(syncProgress.CurrentBlock),
|
CurrentBlock: int64(syncProgress.CurrentBlock),
|
||||||
},
|
},
|
||||||
|
Forks: gatherForks(s.config.chain.Genesis.Config, s.config.chain.Genesis.Config.Bor),
|
||||||
}
|
}
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
@ -134,3 +168,90 @@ func headerToProtoHeader(h *types.Header) *proto.Header {
|
||||||
Number: h.Number.Uint64(),
|
Number: h.Number.Uint64(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var bigIntT = reflect.TypeOf(new(big.Int)).Kind()
|
||||||
|
|
||||||
|
// gatherForks gathers all the fork numbers via reflection
|
||||||
|
func gatherForks(configList ...interface{}) []*proto.StatusResponse_Fork {
|
||||||
|
var forks []*proto.StatusResponse_Fork
|
||||||
|
|
||||||
|
for _, config := range configList {
|
||||||
|
kind := reflect.TypeOf(config)
|
||||||
|
for kind.Kind() == reflect.Ptr {
|
||||||
|
kind = kind.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
skip := "DAOForkBlock"
|
||||||
|
|
||||||
|
conf := reflect.ValueOf(config).Elem()
|
||||||
|
for i := 0; i < kind.NumField(); i++ {
|
||||||
|
// Fetch the next field and skip non-fork rules
|
||||||
|
field := kind.Field(i)
|
||||||
|
if strings.Contains(field.Name, skip) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !strings.HasSuffix(field.Name, "Block") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fork := &proto.StatusResponse_Fork{
|
||||||
|
Name: strings.TrimSuffix(field.Name, "Block"),
|
||||||
|
}
|
||||||
|
|
||||||
|
val := conf.Field(i)
|
||||||
|
switch field.Type.Kind() {
|
||||||
|
case bigIntT:
|
||||||
|
rule := val.Interface().(*big.Int)
|
||||||
|
if rule != nil {
|
||||||
|
fork.Block = rule.Int64()
|
||||||
|
} else {
|
||||||
|
fork.Disabled = true
|
||||||
|
}
|
||||||
|
case reflect.Uint64:
|
||||||
|
fork.Block = int64(val.Uint())
|
||||||
|
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
forks = append(forks, fork)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return forks
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertBlockToBlockStub(blocks []*types.Block) []*proto.BlockStub {
|
||||||
|
|
||||||
|
var blockStubs []*proto.BlockStub
|
||||||
|
|
||||||
|
for _, block := range blocks {
|
||||||
|
blockStub := &proto.BlockStub{
|
||||||
|
Hash: block.Hash().String(),
|
||||||
|
Number: block.NumberU64(),
|
||||||
|
}
|
||||||
|
blockStubs = append(blockStubs, blockStub)
|
||||||
|
}
|
||||||
|
|
||||||
|
return blockStubs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) ChainWatch(req *proto.ChainWatchRequest, reply proto.Bor_ChainWatchServer) error {
|
||||||
|
|
||||||
|
chain2HeadChanSize := 10
|
||||||
|
|
||||||
|
chain2HeadCh := make(chan core.Chain2HeadEvent, chain2HeadChanSize)
|
||||||
|
headSub := s.backend.APIBackend.SubscribeChain2HeadEvent(chain2HeadCh)
|
||||||
|
defer headSub.Unsubscribe()
|
||||||
|
|
||||||
|
for {
|
||||||
|
msg := <-chain2HeadCh
|
||||||
|
|
||||||
|
err := reply.Send(&proto.ChainWatchResponse{Type: msg.Type,
|
||||||
|
Newchain: convertBlockToBlockStub(msg.NewChain),
|
||||||
|
Oldchain: convertBlockToBlockStub(msg.OldChain),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
43
internal/cli/server/service_test.go
Normal file
43
internal/cli/server/service_test.go
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGatherBlocks(t *testing.T) {
|
||||||
|
type c struct {
|
||||||
|
ABlock *big.Int
|
||||||
|
BBlock *big.Int
|
||||||
|
}
|
||||||
|
type d struct {
|
||||||
|
DBlock uint64
|
||||||
|
}
|
||||||
|
val := &c{
|
||||||
|
BBlock: new(big.Int).SetInt64(1),
|
||||||
|
}
|
||||||
|
val2 := &d{
|
||||||
|
DBlock: 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
expect := []*proto.StatusResponse_Fork{
|
||||||
|
{
|
||||||
|
Name: "A",
|
||||||
|
Disabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "B",
|
||||||
|
Block: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "D",
|
||||||
|
Block: 10,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
res := gatherForks(val, val2)
|
||||||
|
assert.Equal(t, res, expect)
|
||||||
|
}
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
package main
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/command/server/proto"
|
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
|
||||||
"github.com/golang/protobuf/ptypes/empty"
|
"github.com/golang/protobuf/ptypes/empty"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -57,6 +57,13 @@ func printStatus(status *proto.StatusResponse) string {
|
||||||
fmt.Sprintf("Number|%d", h.Number),
|
fmt.Sprintf("Number|%d", h.Number),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
forks := make([]string, len(status.Forks)+1)
|
||||||
|
forks[0] = "Name|Block|Enabled"
|
||||||
|
for i, d := range status.Forks {
|
||||||
|
forks[i+1] = fmt.Sprintf("%s|%d|%v", d.Name, d.Block, !d.Disabled)
|
||||||
|
}
|
||||||
|
|
||||||
full := []string{
|
full := []string{
|
||||||
"General",
|
"General",
|
||||||
formatKV([]string{
|
formatKV([]string{
|
||||||
|
|
@ -73,6 +80,8 @@ func printStatus(status *proto.StatusResponse) string {
|
||||||
fmt.Sprintf("Highest block|%d", status.Syncing.HighestBlock),
|
fmt.Sprintf("Highest block|%d", status.Syncing.HighestBlock),
|
||||||
fmt.Sprintf("Starting block|%d", status.Syncing.StartingBlock),
|
fmt.Sprintf("Starting block|%d", status.Syncing.StartingBlock),
|
||||||
}),
|
}),
|
||||||
|
"\nForks",
|
||||||
|
formatList(forks),
|
||||||
}
|
}
|
||||||
return strings.Join(full, "\n")
|
return strings.Join(full, "\n")
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package main
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -645,7 +645,7 @@ func (s *PublicBlockChainAPI) GetTransactionReceiptsByBlock(ctx context.Context,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(txs) != len(receipts) {
|
if len(txs) != len(receipts) {
|
||||||
return nil, fmt.Errorf("txs length doesn't equal to receipts' length", len(txs), len(receipts))
|
return nil, fmt.Errorf("txs length %d doesn't equal to receipts' length %d", len(txs), len(receipts))
|
||||||
}
|
}
|
||||||
|
|
||||||
txReceipts := make([]map[string]interface{}, 0, len(txs))
|
txReceipts := make([]map[string]interface{}, 0, len(txs))
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,7 @@ type Backend interface {
|
||||||
GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error)
|
GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error)
|
||||||
GetBorBlockTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
|
GetBorBlockTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
|
||||||
GetBorBlockTransactionWithBlockHash(ctx context.Context, txHash common.Hash, blockHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
|
GetBorBlockTransactionWithBlockHash(ctx context.Context, txHash common.Hash, blockHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
|
||||||
|
SubscribeChain2HeadEvent(ch chan<- core.Chain2HeadEvent) event.Subscription
|
||||||
|
|
||||||
ChainConfig() *params.ChainConfig
|
ChainConfig() *params.ChainConfig
|
||||||
Engine() consensus.Engine
|
Engine() consensus.Engine
|
||||||
|
|
|
||||||
|
|
@ -17,3 +17,8 @@ func (b *LesApiBackend) GetRootHash(ctx context.Context, starBlockNr uint64, end
|
||||||
func (b *LesApiBackend) SubscribeStateSyncEvent(ch chan<- core.StateSyncEvent) event.Subscription {
|
func (b *LesApiBackend) SubscribeStateSyncEvent(ch chan<- core.StateSyncEvent) event.Subscription {
|
||||||
return b.eth.blockchain.SubscribeStateSyncEvent(ch)
|
return b.eth.blockchain.SubscribeStateSyncEvent(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SubscribeChain2HeadEvent subscribe head/fork/reorg events.
|
||||||
|
func (b *LesApiBackend) SubscribeChain2HeadEvent(ch chan<- core.Chain2HeadEvent) event.Subscription {
|
||||||
|
return b.eth.BlockChain().SubscribeChain2HeadEvent(ch)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,9 @@ type LightChain struct {
|
||||||
running int32 // whether LightChain is running or stopped
|
running int32 // whether LightChain is running or stopped
|
||||||
procInterrupt int32 // interrupts chain insert
|
procInterrupt int32 // interrupts chain insert
|
||||||
disableCheckFreq int32 // disables header verification
|
disableCheckFreq int32 // disables header verification
|
||||||
|
|
||||||
|
// Bor
|
||||||
|
chain2HeadFeed event.Feed
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLightChain returns a fully initialised light chain using information
|
// NewLightChain returns a fully initialised light chain using information
|
||||||
|
|
@ -597,6 +600,11 @@ func (lc *LightChain) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent)
|
||||||
return lc.scope.Track(new(event.Feed).Subscribe(ch))
|
return lc.scope.Track(new(event.Feed).Subscribe(ch))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SubscribeChain2HeadEvent registers a subscription of Reorg/head/fork events.
|
||||||
|
func (lc *LightChain) SubscribeChain2HeadEvent(ch chan<- core.Chain2HeadEvent) event.Subscription {
|
||||||
|
return lc.scope.Track(lc.chain2HeadFeed.Subscribe(ch))
|
||||||
|
}
|
||||||
|
|
||||||
// DisableCheckFreq disables header validation. This is used for ultralight mode.
|
// DisableCheckFreq disables header validation. This is used for ultralight mode.
|
||||||
func (lc *LightChain) DisableCheckFreq() {
|
func (lc *LightChain) DisableCheckFreq() {
|
||||||
atomic.StoreInt32(&lc.disableCheckFreq, 1)
|
atomic.StoreInt32(&lc.disableCheckFreq, 1)
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,8 @@ public class AndroidTest extends InstrumentationTestCase {
|
||||||
//
|
//
|
||||||
// This method has been adapted from golang.org/x/mobile/bind/java/seq_test.go/runTest
|
// This method has been adapted from golang.org/x/mobile/bind/java/seq_test.go/runTest
|
||||||
func TestAndroid(t *testing.T) {
|
func TestAndroid(t *testing.T) {
|
||||||
|
t.Skip("Bor: We do not test this")
|
||||||
|
|
||||||
// Skip tests on Windows altogether
|
// Skip tests on Windows altogether
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
t.Skip("cannot test Android bindings on Windows, skipping")
|
t.Skip("cannot test Android bindings on Windows, skipping")
|
||||||
|
|
|
||||||
|
|
@ -391,16 +391,16 @@ var (
|
||||||
//
|
//
|
||||||
// This configuration is intentionally not using keyed fields to force anyone
|
// This configuration is intentionally not using keyed fields to force anyone
|
||||||
// adding flags to the config to also have to set these fields.
|
// 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), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), 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), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil, &BorConfig{BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"}}}
|
||||||
|
|
||||||
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
|
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
|
||||||
// and accepted by the Ethereum core developers into the Clique consensus.
|
// and accepted by the Ethereum core developers into the Clique consensus.
|
||||||
//
|
//
|
||||||
// This configuration is intentionally not using keyed fields to force anyone
|
// This configuration is intentionally not using keyed fields to force anyone
|
||||||
// adding flags to the config to also have to set these fields.
|
// 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), big.NewInt(0), big.NewInt(0), big.NewInt(0), 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), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, &BorConfig{BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"}}}
|
||||||
|
|
||||||
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), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), 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), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil, &BorConfig{BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"}}}
|
||||||
TestRules = TestChainConfig.Rules(new(big.Int))
|
TestRules = TestChainConfig.Rules(new(big.Int))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
15
scripts/tools-protobuf.sh
Normal file → Executable file
15
scripts/tools-protobuf.sh
Normal file → Executable file
|
|
@ -1,5 +1,16 @@
|
||||||
curl -LO https://github.com/protocolbuffers/protobuf/releases/download/v3.12.0/protoc-3.12.0-linux-x86_64.zip
|
#!/bin/bash
|
||||||
sudo unzip protoc-3.12.0-linux-x86_64.zip -d /usr/local/bin
|
|
||||||
|
|
||||||
|
# Install protobuf
|
||||||
|
PROTOC_ZIP=protoc-3.12.0-linux-x86_64.zip
|
||||||
|
curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v3.12.0/$PROTOC_ZIP
|
||||||
|
sudo unzip -o $PROTOC_ZIP -d /usr/local bin/protoc
|
||||||
|
sudo unzip -o $PROTOC_ZIP -d /usr/local 'include/*'
|
||||||
|
rm -f $PROTOC_ZIP
|
||||||
|
|
||||||
|
# Change permissions to use the binary
|
||||||
|
sudo chmod 755 -R /usr/local/bin/protoc
|
||||||
|
sudo chmod 755 -R /usr/local/include
|
||||||
|
|
||||||
|
# Install golang extensions (DO NOT CHANGE THE VERSIONS)
|
||||||
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.25.0
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.25.0
|
||||||
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 092a8834dc445e683103689d6f0e75a5d380a190
|
|
||||||
Loading…
Reference in a new issue