aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraaronbuchwald <[email protected]>2020-12-14 19:32:25 -0500
committerGitHub <[email protected]>2020-12-14 19:32:25 -0500
commit95cc7cb766d5bb23a771da35b3774159b2e1e1d1 (patch)
tree25b8a74353b87544f62f25f23ce0f721861a80f1
parentac8d216710a533e1dae2f1215ff41e7f0fc2effe (diff)
parentde9c3bc629f7e712b3cd84b280db6a32b9bc7030 (diff)
Merge pull request #70 from ava-labs/fix-linting
Fix linting and add to CI
-rwxr-xr-x.ci/lint.sh12
-rw-r--r--.github/workflows/ci.yml14
-rw-r--r--.golangci.yml50
-rw-r--r--accounts/keystore/account_cache.go2
-rw-r--r--consensus/dummy/consensus.go3
-rw-r--r--core/state/statedb.go1
-rw-r--r--core/types/block.go2
-rw-r--r--core/vm/instructions.go1
-rw-r--r--coreth.go4
-rw-r--r--eth/backend.go25
-rw-r--r--eth/gasprice/gasprice.go2
-rw-r--r--eth/protocol.go221
-rw-r--r--ethclient/ethclient.go14
-rw-r--r--ethstats/ethstats.go785
-rw-r--r--node/api.go1
-rw-r--r--node/config.go2
-rw-r--r--node/node.go1
-rw-r--r--notes/copied-list.txt3
-rw-r--r--notes/hacked-list.txt2
-rw-r--r--plugin/evm/error.go2
-rw-r--r--plugin/evm/service.go3
21 files changed, 110 insertions, 1040 deletions
diff --git a/.ci/lint.sh b/.ci/lint.sh
new file mode 100755
index 0000000..cde7292
--- /dev/null
+++ b/.ci/lint.sh
@@ -0,0 +1,12 @@
+# binary will be $(go env GOPATH)/bin/golangci-lint
+curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.30.0
+# or install it into ./bin/
+curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.30.0
+# In alpine linux (as it does not come with curl by default)
+wget -O- -nv https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.30.0
+
+export PATH=$PATH:$(go env GOPATH)/bin
+
+golangci-lint --version
+
+golangci-lint run --max-same-issues 0 \ No newline at end of file
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 31ae101..b371b2f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -2,6 +2,20 @@ name: CI
on: [pull_request, push]
jobs:
+ lint:
+ name: Golang v${{ matrix.go }} (${{ matrix.os }})
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ go: ['1.15']
+ os: [ubuntu-18.04]
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-go@v1
+ with:
+ go-version: ${{ matrix.go }}
+ - run: .ci/lint.sh
+ shell: bash
test:
name: Golang v${{ matrix.go }} (${{ matrix.os }})
runs-on: ${{ matrix.os }}
diff --git a/.golangci.yml b/.golangci.yml
new file mode 100644
index 0000000..18b325e
--- /dev/null
+++ b/.golangci.yml
@@ -0,0 +1,50 @@
+# This file configures github.com/golangci/golangci-lint.
+
+run:
+ timeout: 3m
+ tests: true
+ # default is true. Enables skipping of directories:
+ # vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
+ skip-dirs-use-default: true
+ skip-files:
+ - core/genesis_alloc.go
+
+linters:
+ disable-all: true
+ enable:
+ - deadcode
+ - goconst
+ - goimports
+ - gosimple
+ - govet
+ - ineffassign
+ - misspell
+ # - staticcheck
+ - unconvert
+ # - unused
+ - varcheck
+
+linters-settings:
+ gofmt:
+ simplify: true
+ goconst:
+ min-len: 3 # minimum length of string constant
+ min-occurrences: 6 # minimum number of occurrences
+
+issues:
+ exclude-rules:
+ - path: crypto/blake2b/
+ linters:
+ - deadcode
+ - path: crypto/bn256/cloudflare
+ linters:
+ - deadcode
+ - path: p2p/discv5/
+ linters:
+ - deadcode
+ - path: core/vm/instructions_test.go
+ linters:
+ - goconst
+ - path: cmd/faucet/
+ linters:
+ - deadcode
diff --git a/accounts/keystore/account_cache.go b/accounts/keystore/account_cache.go
index 76bd552..7ae4d37 100644
--- a/accounts/keystore/account_cache.go
+++ b/accounts/keystore/account_cache.go
@@ -28,9 +28,9 @@ import (
"time"
"github.com/ava-labs/coreth/accounts"
+ mapset "github.com/deckarep/golang-set"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
- mapset "github.com/deckarep/golang-set"
)
// Minimum amount of time between cache reloads. This limit applies if the platform does
diff --git a/consensus/dummy/consensus.go b/consensus/dummy/consensus.go
index da63673..866ff97 100644
--- a/consensus/dummy/consensus.go
+++ b/consensus/dummy/consensus.go
@@ -3,11 +3,12 @@ package dummy
import (
"errors"
"fmt"
- "golang.org/x/crypto/sha3"
"math/big"
"runtime"
"time"
+ "golang.org/x/crypto/sha3"
+
"github.com/ava-labs/coreth/consensus"
"github.com/ava-labs/coreth/core/state"
"github.com/ava-labs/coreth/core/types"
diff --git a/core/state/statedb.go b/core/state/statedb.go
index c4d926d..f75428b 100644
--- a/core/state/statedb.go
+++ b/core/state/statedb.go
@@ -43,7 +43,6 @@ type revision struct {
var (
// emptyRoot is the known root hash of an empty trie.
emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
- zeroRoot = common.HexToHash("0000000000000000000000000000000000000000000000000000000000000000")
)
type proofList [][]byte
diff --git a/core/types/block.go b/core/types/block.go
index 8e23488..b293ae7 100644
--- a/core/types/block.go
+++ b/core/types/block.go
@@ -86,7 +86,7 @@ type Header struct {
Extra []byte `json:"extraData" gencodec:"required"`
MixDigest common.Hash `json:"mixHash"`
Nonce BlockNonce `json:"nonce"`
- ExtDataHash common.Hash `json:"extDataHash" gencodec:"required"`
+ ExtDataHash common.Hash `json:"extDataHash" gencodec:"required"`
}
// field type overrides for gencodec
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index e1eb25e..3e1da26 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -18,6 +18,7 @@ package vm
import (
"errors"
+
"github.com/ava-labs/coreth/core/types"
"github.com/ava-labs/coreth/params"
"github.com/ethereum/go-ethereum/common"
diff --git a/coreth.go b/coreth.go
index 351a14d..25e9da2 100644
--- a/coreth.go
+++ b/coreth.go
@@ -40,10 +40,6 @@ type ETHChain struct {
bcb *eth.BackendCallbacks
}
-func isLocalBlock(block *types.Block) bool {
- return false
-}
-
// NewETHChain creates an Ethereum blockchain with the given configs.
func NewETHChain(config *eth.Config, nodecfg *node.Config, etherBase *common.Address, chainDB ethdb.Database) *ETHChain {
if config == nil {
diff --git a/eth/backend.go b/eth/backend.go
index 728ec4d..9fb8f38 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -23,7 +23,6 @@ import (
"math/big"
"runtime"
"sync"
- //"sync/atomic"
"github.com/ava-labs/coreth/accounts"
"github.com/ava-labs/coreth/consensus"
@@ -53,6 +52,16 @@ import (
"github.com/ethereum/go-ethereum/rlp"
)
+// ProtocolVersions are the supported versions of the eth protocol (first is primary).
+var ProtocolVersions = []uint{eth65, eth64, eth63}
+
+// Constants to match up protocol versions and messages
+const (
+ eth63 = 63
+ eth64 = 64
+ eth65 = 65
+)
+
type BackendCallbacks struct {
OnQueryAcceptedBlock func() *types.Block
}
@@ -498,13 +507,13 @@ func (s *Ethereum) Start() error {
s.startBloomHandlers(params.BloomBitsBlocks)
// Figure out a max peers count based on the server limits
- maxPeers := s.p2pServer.MaxPeers
- if s.config.LightServ > 0 {
- if s.config.LightPeers >= s.p2pServer.MaxPeers {
- return fmt.Errorf("invalid peer config: light peer count (%d) >= total peer count (%d)", s.config.LightPeers, s.p2pServer.MaxPeers)
- }
- maxPeers -= s.config.LightPeers
- }
+ // maxPeers := s.p2pServer.MaxPeers
+ // if s.config.LightServ > 0 {
+ // if s.config.LightPeers >= s.p2pServer.MaxPeers {
+ // return fmt.Errorf("invalid peer config: light peer count (%d) >= total peer count (%d)", s.config.LightPeers, s.p2pServer.MaxPeers)
+ // }
+ // maxPeers -= s.config.LightPeers
+ // }
// Start the networking layer and the light server if requested
//s.protocolManager.Start(maxPeers)
return nil
diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go
index 14476ab..33810b2 100644
--- a/eth/gasprice/gasprice.go
+++ b/eth/gasprice/gasprice.go
@@ -29,8 +29,6 @@ import (
"github.com/ethereum/go-ethereum/log"
)
-const sampleNumber = 3 // Number of transactions sampled in a block
-
var DefaultMaxPrice = big.NewInt(500 * params.GWei)
type Config struct {
diff --git a/eth/protocol.go b/eth/protocol.go
deleted file mode 100644
index ef5dcde..0000000
--- a/eth/protocol.go
+++ /dev/null
@@ -1,221 +0,0 @@
-// Copyright 2014 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
-package eth
-
-import (
- "fmt"
- "io"
- "math/big"
-
- "github.com/ava-labs/coreth/core"
- "github.com/ava-labs/coreth/core/forkid"
- "github.com/ava-labs/coreth/core/types"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/event"
- "github.com/ethereum/go-ethereum/rlp"
-)
-
-// Constants to match up protocol versions and messages
-const (
- eth63 = 63
- eth64 = 64
- eth65 = 65
-)
-
-// protocolName is the official short name of the protocol used during capability negotiation.
-const protocolName = "eth"
-
-// ProtocolVersions are the supported versions of the eth protocol (first is primary).
-var ProtocolVersions = []uint{eth65, eth64, eth63}
-
-// protocolLengths are the number of implemented message corresponding to different protocol versions.
-var protocolLengths = map[uint]uint64{eth65: 17, eth64: 17, eth63: 17}
-
-const protocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message
-
-// eth protocol message codes
-const (
- StatusMsg = 0x00
- NewBlockHashesMsg = 0x01
- TransactionMsg = 0x02
- GetBlockHeadersMsg = 0x03
- BlockHeadersMsg = 0x04
- GetBlockBodiesMsg = 0x05
- BlockBodiesMsg = 0x06
- NewBlockMsg = 0x07
- GetNodeDataMsg = 0x0d
- NodeDataMsg = 0x0e
- GetReceiptsMsg = 0x0f
- ReceiptsMsg = 0x10
-
- // New protocol message codes introduced in eth65
- //
- // Previously these message ids were used by some legacy and unsupported
- // eth protocols, reown them here.
- NewPooledTransactionHashesMsg = 0x08
- GetPooledTransactionsMsg = 0x09
- PooledTransactionsMsg = 0x0a
-)
-
-type errCode int
-
-const (
- ErrMsgTooLarge = iota
- ErrDecode
- ErrInvalidMsgCode
- ErrProtocolVersionMismatch
- ErrNetworkIDMismatch
- ErrGenesisMismatch
- ErrForkIDRejected
- ErrNoStatusMsg
- ErrExtraStatusMsg
-)
-
-func (e errCode) String() string {
- return errorToString[int(e)]
-}
-
-// XXX change once legacy code is out
-var errorToString = map[int]string{
- ErrMsgTooLarge: "Message too long",
- ErrDecode: "Invalid message",
- ErrInvalidMsgCode: "Invalid message code",
- ErrProtocolVersionMismatch: "Protocol version mismatch",
- ErrNetworkIDMismatch: "Network ID mismatch",
- ErrGenesisMismatch: "Genesis mismatch",
- ErrForkIDRejected: "Fork ID rejected",
- ErrNoStatusMsg: "No status message",
- ErrExtraStatusMsg: "Extra status message",
-}
-
-type txPool interface {
- // Has returns an indicator whether txpool has a transaction
- // cached with the given hash.
- Has(hash common.Hash) bool
-
- // Get retrieves the transaction from local txpool with given
- // tx hash.
- Get(hash common.Hash) *types.Transaction
-
- // AddRemotes should add the given transactions to the pool.
- AddRemotes([]*types.Transaction) []error
-
- // Pending should return pending transactions.
- // The slice should be modifiable by the caller.
- Pending() (map[common.Address]types.Transactions, error)
-
- // SubscribeNewTxsEvent should return an event subscription of
- // NewTxsEvent and send events to the given channel.
- SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription
-}
-
-// statusData63 is the network packet for the status message for eth/63.
-type statusData63 struct {
- ProtocolVersion uint32
- NetworkId uint64
- TD *big.Int
- CurrentBlock common.Hash
- GenesisBlock common.Hash
-}
-
-// statusData is the network packet for the status message for eth/64 and later.
-type statusData struct {
- ProtocolVersion uint32
- NetworkID uint64
- TD *big.Int
- Head common.Hash
- Genesis common.Hash
- ForkID forkid.ID
-}
-
-// newBlockHashesData is the network packet for the block announcements.
-type newBlockHashesData []struct {
- Hash common.Hash // Hash of one particular block being announced
- Number uint64 // Number of one particular block being announced
-}
-
-// getBlockHeadersData represents a block header query.
-type getBlockHeadersData struct {
- Origin hashOrNumber // Block from which to retrieve headers
- Amount uint64 // Maximum number of headers to retrieve
- Skip uint64 // Blocks to skip between consecutive headers
- Reverse bool // Query direction (false = rising towards latest, true = falling towards genesis)
-}
-
-// hashOrNumber is a combined field for specifying an origin block.
-type hashOrNumber struct {
- Hash common.Hash // Block hash from which to retrieve headers (excludes Number)
- Number uint64 // Block hash from which to retrieve headers (excludes Hash)
-}
-
-// EncodeRLP is a specialized encoder for hashOrNumber to encode only one of the
-// two contained union fields.
-func (hn *hashOrNumber) EncodeRLP(w io.Writer) error {
- if hn.Hash == (common.Hash{}) {
- return rlp.Encode(w, hn.Number)
- }
- if hn.Number != 0 {
- return fmt.Errorf("both origin hash (%x) and number (%d) provided", hn.Hash, hn.Number)
- }
- return rlp.Encode(w, hn.Hash)
-}
-
-// DecodeRLP is a specialized decoder for hashOrNumber to decode the contents
-// into either a block hash or a block number.
-func (hn *hashOrNumber) DecodeRLP(s *rlp.Stream) error {
- _, size, _ := s.Kind()
- origin, err := s.Raw()
- if err == nil {
- switch {
- case size == 32:
- err = rlp.DecodeBytes(origin, &hn.Hash)
- case size <= 8:
- err = rlp.DecodeBytes(origin, &hn.Number)
- default:
- err = fmt.Errorf("invalid input size %d for origin", size)
- }
- }
- return err
-}
-
-// newBlockData is the network packet for the block propagation message.
-type newBlockData struct {
- Block *types.Block
- TD *big.Int
-}
-
-// sanityCheck verifies that the values are reasonable, as a DoS protection
-func (request *newBlockData) sanityCheck() error {
- if err := request.Block.SanityCheck(); err != nil {
- return err
- }
- //TD at mainnet block #7753254 is 76 bits. If it becomes 100 million times
- // larger, it will still fit within 100 bits
- if tdlen := request.TD.BitLen(); tdlen > 100 {
- return fmt.Errorf("too large block TD: bitlen %d", tdlen)
- }
- return nil
-}
-
-// blockBody represents the data content of a single block.
-type blockBody struct {
- Transactions []*types.Transaction // Transactions contained within a block
- Uncles []*types.Header // Uncles contained within a block
-}
-
-// blockBodiesData is the network packet for block content distribution.
-type blockBodiesData []*blockBody
diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go
index 6dd4df8..8470d64 100644
--- a/ethclient/ethclient.go
+++ b/ethclient/ethclient.go
@@ -324,13 +324,13 @@ func toBlockNumArg(number *big.Int) string {
return hexutil.EncodeBig(number)
}
-type rpcProgress struct {
- StartingBlock hexutil.Uint64
- CurrentBlock hexutil.Uint64
- HighestBlock hexutil.Uint64
- PulledStates hexutil.Uint64
- KnownStates hexutil.Uint64
-}
+// type rpcProgress struct {
+// StartingBlock hexutil.Uint64
+// CurrentBlock hexutil.Uint64
+// HighestBlock hexutil.Uint64
+// PulledStates hexutil.Uint64
+// KnownStates hexutil.Uint64
+// }
// SyncProgress retrieves the current progress of the sync algorithm. If there's
// no sync currently running, it returns nil.
diff --git a/ethstats/ethstats.go b/ethstats/ethstats.go
deleted file mode 100644
index 3dd06e3..0000000
--- a/ethstats/ethstats.go
+++ /dev/null
@@ -1,785 +0,0 @@
-// Copyright 2016 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
-// Package ethstats implements the network stats reporting service.
-package ethstats
-
-import (
- "context"
- "encoding/json"
- "errors"
- "fmt"
- "math/big"
- "net/http"
- "regexp"
- "runtime"
- "strconv"
- "strings"
- "sync"
- "time"
-
- "github.com/ava-labs/coreth/consensus"
- "github.com/ava-labs/coreth/core"
- "github.com/ava-labs/coreth/core/types"
- "github.com/ava-labs/coreth/eth"
- "github.com/ava-labs/coreth/miner"
- "github.com/ava-labs/coreth/node"
- "github.com/ava-labs/coreth/rpc"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/mclock"
- "github.com/ethereum/go-ethereum/eth/downloader"
- "github.com/ethereum/go-ethereum/event"
- "github.com/ethereum/go-ethereum/les"
- "github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/p2p"
- "github.com/gorilla/websocket"
-)
-
-const (
- // historyUpdateRange is the number of blocks a node should report upon login or
- // history request.
- historyUpdateRange = 50
-
- // txChanSize is the size of channel listening to NewTxsEvent.
- // The number is referenced from the size of tx pool.
- txChanSize = 4096
- // chainHeadChanSize is the size of channel listening to ChainHeadEvent.
- chainHeadChanSize = 10
-)
-
-// backend encompasses the bare-minimum functionality needed for ethstats reporting
-type backend interface {
- SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
- SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription
- CurrentHeader() *types.Header
- HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
- GetTd(ctx context.Context, hash common.Hash) *big.Int
- Stats() (pending int, queued int)
- Downloader() *downloader.Downloader
-}
-
-// fullNodeBackend encompasses the functionality necessary for a full node
-// reporting to ethstats
-type fullNodeBackend interface {
- backend
- Miner() *miner.Miner
- BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)
- CurrentBlock() *types.Block
- SuggestPrice(ctx context.Context) (*big.Int, error)
-}
-
-// Service implements an Ethereum netstats reporting daemon that pushes local
-// chain statistics up to a monitoring server.
-type Service struct {
- server *p2p.Server // Peer-to-peer server to retrieve networking infos
- backend backend
- engine consensus.Engine // Consensus engine to retrieve variadic block fields
-
- node string // Name of the node to display on the monitoring page
- pass string // Password to authorize access to the monitoring page
- host string // Remote address of the monitoring service
-
- pongCh chan struct{} // Pong notifications are fed into this channel
- histCh chan []uint64 // History request block numbers are fed into this channel
-
-}
-
-// connWrapper is a wrapper to prevent concurrent-write or concurrent-read on the
-// websocket.
-//
-// From Gorilla websocket docs:
-// Connections support one concurrent reader and one concurrent writer.
-// Applications are responsible for ensuring that no more than one goroutine calls the write methods
-// - NextWriter, SetWriteDeadline, WriteMessage, WriteJSON, EnableWriteCompression, SetCompressionLevel
-// concurrently and that no more than one goroutine calls the read methods
-// - NextReader, SetReadDeadline, ReadMessage, ReadJSON, SetPongHandler, SetPingHandler
-// concurrently.
-// The Close and WriteControl methods can be called concurrently with all other methods.
-type connWrapper struct {
- conn *websocket.Conn
-
- rlock sync.Mutex
- wlock sync.Mutex
-}
-
-func newConnectionWrapper(conn *websocket.Conn) *connWrapper {
- return &connWrapper{conn: conn}
-}
-
-// WriteJSON wraps corresponding method on the websocket but is safe for concurrent calling
-func (w *connWrapper) WriteJSON(v interface{}) error {
- w.wlock.Lock()
- defer w.wlock.Unlock()
-
- return w.conn.WriteJSON(v)
-}
-
-// ReadJSON wraps corresponding method on the websocket but is safe for concurrent calling
-func (w *connWrapper) ReadJSON(v interface{}) error {
- w.rlock.Lock()
- defer w.rlock.Unlock()
-
- return w.conn.ReadJSON(v)
-}
-
-// Close wraps corresponding method on the websocket but is safe for concurrent calling
-func (w *connWrapper) Close() error {
- // The Close and WriteControl methods can be called concurrently with all other methods,
- // so the mutex is not used here
- return w.conn.Close()
-}
-
-// New returns a monitoring service ready for stats reporting.
-func New(node *node.Node, backend backend, engine consensus.Engine, url string) error {
- // Parse the netstats connection url
- re := regexp.MustCompile("([^:@]*)(:([^@]*))?@(.+)")
- parts := re.FindStringSubmatch(url)
- if len(parts) != 5 {
- return fmt.Errorf("invalid netstats url: \"%s\", should be nodename:secret@host:port", url)
- }
- ethstats := &Service{
- backend: backend,
- engine: engine,
- server: node.Server(),
- node: parts[1],
- pass: parts[3],
- host: parts[4],
- pongCh: make(chan struct{}),
- histCh: make(chan []uint64, 1),
- }
-
- node.RegisterLifecycle(ethstats)
- return nil
-}
-
-// Start implements node.Lifecycle, starting up the monitoring and reporting daemon.
-func (s *Service) Start() error {
- go s.loop()
-
- log.Info("Stats daemon started")
- return nil
-}
-
-// Stop implements node.Lifecycle, terminating the monitoring and reporting daemon.
-func (s *Service) Stop() error {
- log.Info("Stats daemon stopped")
- return nil
-}
-
-// loop keeps trying to connect to the netstats server, reporting chain events
-// until termination.
-func (s *Service) loop() {
- // Subscribe to chain events to execute updates on
- chainHeadCh := make(chan core.ChainHeadEvent, chainHeadChanSize)
- headSub := s.backend.SubscribeChainHeadEvent(chainHeadCh)
- defer headSub.Unsubscribe()
-
- txEventCh := make(chan core.NewTxsEvent, txChanSize)
- txSub := s.backend.SubscribeNewTxsEvent(txEventCh)
- defer txSub.Unsubscribe()
-
- // Start a goroutine that exhausts the subscriptions to avoid events piling up
- var (
- quitCh = make(chan struct{})
- headCh = make(chan *types.Block, 1)
- txCh = make(chan struct{}, 1)
- )
- go func() {
- var lastTx mclock.AbsTime
-
- HandleLoop:
- for {
- select {
- // Notify of chain head events, but drop if too frequent
- case head := <-chainHeadCh:
- select {
- case headCh <- head.Block:
- default:
- }
-
- // Notify of new transaction events, but drop if too frequent
- case <-txEventCh:
- if time.Duration(mclock.Now()-lastTx) < time.Second {
- continue
- }
- lastTx = mclock.Now()
-
- select {
- case txCh <- struct{}{}:
- default:
- }
-
- // node stopped
- case <-txSub.Err():
- break HandleLoop
- case <-headSub.Err():
- break HandleLoop
- }
- }
- close(quitCh)
- }()
-
- // Resolve the URL, defaulting to TLS, but falling back to none too
- path := fmt.Sprintf("%s/api", s.host)
- urls := []string{path}
-
- // url.Parse and url.IsAbs is unsuitable (https://github.com/golang/go/issues/19779)
- if !strings.Contains(path, "://") {
- urls = []string{"wss://" + path, "ws://" + path}
- }
-
- errTimer := time.NewTimer(0)
- defer errTimer.Stop()
- // Loop reporting until termination
- for {
- select {
- case <-quitCh:
- return
- case <-errTimer.C:
- // Establish a websocket connection to the server on any supported URL
- var (
- conn *connWrapper
- err error
- )
- dialer := websocket.Dialer{HandshakeTimeout: 5 * time.Second}
- header := make(http.Header)
- header.Set("origin", "http://localhost")
- for _, url := range urls {
- c, _, e := dialer.Dial(url, header)
- err = e
- if err == nil {
- conn = newConnectionWrapper(c)
- break
- }
- }
- if err != nil {
- log.Warn("Stats server unreachable", "err", err)
- errTimer.Reset(10 * time.Second)
- continue
- }
- // Authenticate the client with the server
- if err = s.login(conn); err != nil {
- log.Warn("Stats login failed", "err", err)
- conn.Close()
- errTimer.Reset(10 * time.Second)
- continue
- }
- go s.readLoop(conn)
-
- // Send the initial stats so our node looks decent from the get go
- if err = s.report(conn); err != nil {
- log.Warn("Initial stats report failed", "err", err)
- conn.Close()
- errTimer.Reset(0)
- continue
- }
- // Keep sending status updates until the connection breaks
- fullReport := time.NewTicker(15 * time.Second)
-
- for err == nil {
- select {
- case <-quitCh:
- fullReport.Stop()
- // Make sure the connection is closed
- conn.Close()
- return
-
- case <-fullReport.C:
- if err = s.report(conn); err != nil {
- log.Warn("Full stats report failed", "err", err)
- }
- case list := <-s.histCh:
- if err = s.reportHistory(conn, list); err != nil {
- log.Warn("Requested history report failed", "err", err)
- }
- case head := <-headCh:
- if err = s.reportBlock(conn, head); err != nil {
- log.Warn("Block stats report failed", "err", err)
- }
- if err = s.reportPending(conn); err != nil {
- log.Warn("Post-block transaction stats report failed", "err", err)
- }
- case <-txCh:
- if err = s.reportPending(conn); err != nil {
- log.Warn("Transaction stats report failed", "err", err)
- }
- }
- }
- fullReport.Stop()
-
- // Close the current connection and establish a new one
- conn.Close()
- errTimer.Reset(0)
- }
- }
-}
-
-// readLoop loops as long as the connection is alive and retrieves data packets
-// from the network socket. If any of them match an active request, it forwards
-// it, if they themselves are requests it initiates a reply, and lastly it drops
-// unknown packets.
-func (s *Service) readLoop(conn *connWrapper) {
- // If the read loop exists, close the connection
- defer conn.Close()
-
- for {
- // Retrieve the next generic network packet and bail out on error
- var blob json.RawMessage
- if err := conn.ReadJSON(&blob); err != nil {
- log.Warn("Failed to retrieve stats server message", "err", err)
- return
- }
- // If the network packet is a system ping, respond to it directly
- var ping string
- if err := json.Unmarshal(blob, &ping); err == nil && strings.HasPrefix(ping, "primus::ping::") {
- if err := conn.WriteJSON(strings.Replace(ping, "ping", "pong", -1)); err != nil {
- log.Warn("Failed to respond to system ping message", "err", err)
- return
- }
- continue
- }
- // Not a system ping, try to decode an actual state message
- var msg map[string][]interface{}
- if err := json.Unmarshal(blob, &msg); err != nil {
- log.Warn("Failed to decode stats server message", "err", err)
- return
- }
- log.Trace("Received message from stats server", "msg", msg)
- if len(msg["emit"]) == 0 {
- log.Warn("Stats server sent non-broadcast", "msg", msg)
- return
- }
- command, ok := msg["emit"][0].(string)
- if !ok {
- log.Warn("Invalid stats server message type", "type", msg["emit"][0])
- return
- }
- // If the message is a ping reply, deliver (someone must be listening!)
- if len(msg["emit"]) == 2 && command == "node-pong" {
- select {
- case s.pongCh <- struct{}{}:
- // Pong delivered, continue listening
- continue
- default:
- // Ping routine dead, abort
- log.Warn("Stats server pinger seems to have died")
- return
- }
- }
- // If the message is a history request, forward to the event processor
- if len(msg["emit"]) == 2 && command == "history" {
- // Make sure the request is valid and doesn't crash us
- request, ok := msg["emit"][1].(map[string]interface{})
- if !ok {
- log.Warn("Invalid stats history request", "msg", msg["emit"][1])
- select {
- case s.histCh <- nil: // Treat it as an no indexes request
- default:
- }
- continue
- }
- list, ok := request["list"].([]interface{})
- if !ok {
- log.Warn("Invalid stats history block list", "list", request["list"])
- return
- }
- // Convert the block number list to an integer list
- numbers := make([]uint64, len(list))
- for i, num := range list {
- n, ok := num.(float64)
- if !ok {
- log.Warn("Invalid stats history block number", "number", num)
- return
- }
- numbers[i] = uint64(n)
- }
- select {
- case s.histCh <- numbers:
- continue
- default:
- }
- }
- // Report anything else and continue
- log.Info("Unknown stats message", "msg", msg)
- }
-}
-
-// nodeInfo is the collection of meta information about a node that is displayed
-// on the monitoring page.
-type nodeInfo struct {
- Name string `json:"name"`
- Node string `json:"node"`
- Port int `json:"port"`
- Network string `json:"net"`
- Protocol string `json:"protocol"`
- API string `json:"api"`
- Os string `json:"os"`
- OsVer string `json:"os_v"`
- Client string `json:"client"`
- History bool `json:"canUpdateHistory"`
-}
-
-// authMsg is the authentication infos needed to login to a monitoring server.
-type authMsg struct {
- ID string `json:"id"`
- Info nodeInfo `json:"info"`
- Secret string `json:"secret"`
-}
-
-// login tries to authorize the client at the remote server.
-func (s *Service) login(conn *connWrapper) error {
- // Construct and send the login authentication
- infos := s.server.NodeInfo()
-
- var network, protocol string
- if info := infos.Protocols["eth"]; info != nil {
- network = fmt.Sprintf("%d", info.(*eth.NodeInfo).Network)
- protocol = fmt.Sprintf("eth/%d", eth.ProtocolVersions[0])
- } else {
- network = fmt.Sprintf("%d", infos.Protocols["les"].(*les.NodeInfo).Network)
- protocol = fmt.Sprintf("les/%d", les.ClientProtocolVersions[0])
- }
- auth := &authMsg{
- ID: s.node,
- Info: nodeInfo{
- Name: s.node,
- Node: infos.Name,
- Port: infos.Ports.Listener,
- Network: network,
- Protocol: protocol,
- API: "No",
- Os: runtime.GOOS,
- OsVer: runtime.GOARCH,
- Client: "0.1.1",
- History: true,
- },
- Secret: s.pass,
- }
- login := map[string][]interface{}{
- "emit": {"hello", auth},
- }
- if err := conn.WriteJSON(login); err != nil {
- return err
- }
- // Retrieve the remote ack or connection termination
- var ack map[string][]string
- if err := conn.ReadJSON(&ack); err != nil || len(ack["emit"]) != 1 || ack["emit"][0] != "ready" {
- return errors.New("unauthorized")
- }
- return nil
-}
-
-// report collects all possible data to report and send it to the stats server.
-// This should only be used on reconnects or rarely to avoid overloading the
-// server. Use the individual methods for reporting subscribed events.
-func (s *Service) report(conn *connWrapper) error {
- if err := s.reportLatency(conn); err != nil {
- return err
- }
- if err := s.reportBlock(conn, nil); err != nil {
- return err
- }
- if err := s.reportPending(conn); err != nil {
- return err
- }
- if err := s.reportStats(conn); err != nil {
- return err
- }
- return nil
-}
-
-// reportLatency sends a ping request to the server, measures the RTT time and
-// finally sends a latency update.
-func (s *Service) reportLatency(conn *connWrapper) error {
- // Send the current time to the ethstats server
- start := time.Now()
-
- ping := map[string][]interface{}{
- "emit": {"node-ping", map[string]string{
- "id": s.node,
- "clientTime": start.String(),
- }},
- }
- if err := conn.WriteJSON(ping); err != nil {
- return err
- }
- // Wait for the pong request to arrive back
- select {
- case <-s.pongCh:
- // Pong delivered, report the latency
- case <-time.After(5 * time.Second):
- // Ping timeout, abort
- return errors.New("ping timed out")
- }
- latency := strconv.Itoa(int((time.Since(start) / time.Duration(2)).Nanoseconds() / 1000000))
-
- // Send back the measured latency
- log.Trace("Sending measured latency to ethstats", "latency", latency)
-
- stats := map[string][]interface{}{
- "emit": {"latency", map[string]string{
- "id": s.node,
- "latency": latency,
- }},
- }
- return conn.WriteJSON(stats)
-}
-
-// blockStats is the information to report about individual blocks.
-type blockStats struct {
- Number *big.Int `json:"number"`
- Hash common.Hash `json:"hash"`
- ParentHash common.Hash `json:"parentHash"`
- Timestamp *big.Int `json:"timestamp"`
- Miner common.Address `json:"miner"`
- GasUsed uint64 `json:"gasUsed"`
- GasLimit uint64 `json:"gasLimit"`
- Diff string `json:"difficulty"`
- TotalDiff string `json:"totalDifficulty"`
- Txs []txStats `json:"transactions"`
- TxHash common.Hash `json:"transactionsRoot"`
- Root common.Hash `json:"stateRoot"`
- Uncles uncleStats `json:"uncles"`
-}
-
-// txStats is the information to report about individual transactions.
-type txStats struct {
- Hash common.Hash `json:"hash"`
-}
-
-// uncleStats is a custom wrapper around an uncle array to force serializing
-// empty arrays instead of returning null for them.
-type uncleStats []*types.Header
-
-func (s uncleStats) MarshalJSON() ([]byte, error) {
- if uncles := ([]*types.Header)(s); len(uncles) > 0 {
- return json.Marshal(uncles)
- }
- return []byte("[]"), nil
-}
-
-// reportBlock retrieves the current chain head and reports it to the stats server.
-func (s *Service) reportBlock(conn *connWrapper, block *types.Block) error {
- // Gather the block details from the header or block chain
- details := s.assembleBlockStats(block)
-
- // Assemble the block report and send it to the server
- log.Trace("Sending new block to ethstats", "number", details.Number, "hash", details.Hash)
-
- stats := map[string]interface{}{
- "id": s.node,
- "block": details,
- }
- report := map[string][]interface{}{
- "emit": {"block", stats},
- }
- return conn.WriteJSON(report)
-}
-
-// assembleBlockStats retrieves any required metadata to report a single block
-// and assembles the block stats. If block is nil, the current head is processed.
-func (s *Service) assembleBlockStats(block *types.Block) *blockStats {
- // Gather the block infos from the local blockchain
- var (
- header *types.Header
- td *big.Int
- txs []txStats
- uncles []*types.Header
- )
-
- // check if backend is a full node
- fullBackend, ok := s.backend.(fullNodeBackend)
- if ok {
- if block == nil {
- block = fullBackend.CurrentBlock()
- }
- header = block.Header()
- td = fullBackend.GetTd(context.Background(), header.Hash())
-
- txs = make([]txStats, len(block.Transactions()))
- for i, tx := range block.Transactions() {
- txs[i].Hash = tx.Hash()
- }
- uncles = block.Uncles()
- } else {
- // Light nodes would need on-demand lookups for transactions/uncles, skip
- if block != nil {
- header = block.Header()
- } else {
- header = s.backend.CurrentHeader()
- }
- td = s.backend.GetTd(context.Background(), header.Hash())
- txs = []txStats{}
- }
-
- // Assemble and return the block stats
- author, _ := s.engine.Author(header)
-
- return &blockStats{
- Number: header.Number,
- Hash: header.Hash(),
- ParentHash: header.ParentHash,
- Timestamp: new(big.Int).SetUint64(header.Time),
- Miner: author,
- GasUsed: header.GasUsed,
- GasLimit: header.GasLimit,
- Diff: header.Difficulty.String(),
- TotalDiff: td.String(),
- Txs: txs,
- TxHash: header.TxHash,
- Root: header.Root,
- Uncles: uncles,
- }
-}
-
-// reportHistory retrieves the most recent batch of blocks and reports it to the
-// stats server.
-func (s *Service) reportHistory(conn *connWrapper, list []uint64) error {
- // Figure out the indexes that need reporting
- indexes := make([]uint64, 0, historyUpdateRange)
- if len(list) > 0 {
- // Specific indexes requested, send them back in particular
- indexes = append(indexes, list...)
- } else {
- // No indexes requested, send back the top ones
- head := s.backend.CurrentHeader().Number.Int64()
- start := head - historyUpdateRange + 1
- if start < 0 {
- start = 0
- }
- for i := uint64(start); i <= uint64(head); i++ {
- indexes = append(indexes, i)
- }
- }
- // Gather the batch of blocks to report
- history := make([]*blockStats, len(indexes))
- for i, number := range indexes {
- fullBackend, ok := s.backend.(fullNodeBackend)
- // Retrieve the next block if it's known to us
- var block *types.Block
- if ok {
- block, _ = fullBackend.BlockByNumber(context.Background(), rpc.BlockNumber(number)) // TODO ignore error here ?
- } else {
- if header, _ := s.backend.HeaderByNumber(context.Background(), rpc.BlockNumber(number)); header != nil {
- block = types.NewBlockWithHeader(header)
- }
- }
- // If we do have the block, add to the history and continue
- if block != nil {
- history[len(history)-1-i] = s.assembleBlockStats(block)
- continue
- }
- // Ran out of blocks, cut the report short and send
- history = history[len(history)-i:]
- break
- }
- // Assemble the history report and send it to the server
- if len(history) > 0 {
- log.Trace("Sending historical blocks to ethstats", "first", history[0].Number, "last", history[len(history)-1].Number)
- } else {
- log.Trace("No history to send to stats server")
- }
- stats := map[string]interface{}{
- "id": s.node,
- "history": history,
- }
- report := map[string][]interface{}{
- "emit": {"history", stats},
- }
- return conn.WriteJSON(report)
-}
-
-// pendStats is the information to report about pending transactions.
-type pendStats struct {
- Pending int `json:"pending"`
-}
-
-// reportPending retrieves the current number of pending transactions and reports
-// it to the stats server.
-func (s *Service) reportPending(conn *connWrapper) error {
- // Retrieve the pending count from the local blockchain
- pending, _ := s.backend.Stats()
- // Assemble the transaction stats and send it to the server
- log.Trace("Sending pending transactions to ethstats", "count", pending)
-
- stats := map[string]interface{}{
- "id": s.node,
- "stats": &pendStats{
- Pending: pending,
- },
- }
- report := map[string][]interface{}{
- "emit": {"pending", stats},
- }
- return conn.WriteJSON(report)
-}
-
-// nodeStats is the information to report about the local node.
-type nodeStats struct {
- Active bool `json:"active"`
- Syncing bool `json:"syncing"`
- Mining bool `json:"mining"`
- Hashrate int `json:"hashrate"`
- Peers int `json:"peers"`
- GasPrice int `json:"gasPrice"`
- Uptime int `json:"uptime"`
-}
-
-// reportStats retrieves various stats about the node at the networking and
-// mining layer and reports it to the stats server.
-func (s *Service) reportStats(conn *connWrapper) error {
- // Gather the syncing and mining infos from the local miner instance
- var (
- mining bool
- hashrate int
- syncing bool
- gasprice int
- )
- // check if backend is a full node
- fullBackend, ok := s.backend.(fullNodeBackend)
- if ok {
- mining = fullBackend.Miner().Mining()
- hashrate = int(fullBackend.Miner().HashRate())
-
- sync := fullBackend.Downloader().Progress()
- syncing = fullBackend.CurrentHeader().Number.Uint64() >= sync.HighestBlock
-
- price, _ := fullBackend.SuggestPrice(context.Background())
- gasprice = int(price.Uint64())
- } else {
- sync := s.backend.Downloader().Progress()
- syncing = s.backend.CurrentHeader().Number.Uint64() >= sync.HighestBlock
- }
- // Assemble the node stats and send it to the server
- log.Trace("Sending node details to ethstats")
-
- stats := map[string]interface{}{
- "id": s.node,
- "stats": &nodeStats{
- Active: true,
- Mining: mining,
- Hashrate: hashrate,
- Peers: s.server.PeerCount(),
- GasPrice: gasprice,
- Syncing: syncing,
- Uptime: 100,
- },
- }
- report := map[string][]interface{}{
- "emit": {"stats", stats},
- }
- return conn.WriteJSON(report)
-}
diff --git a/node/api.go b/node/api.go
index 4589d25..af6ae69 100644
--- a/node/api.go
+++ b/node/api.go
@@ -19,7 +19,6 @@ package node
import (
"context"
"fmt"
- //"strings"
"github.com/ava-labs/coreth/internal/debug"
"github.com/ava-labs/coreth/rpc"
diff --git a/node/config.go b/node/config.go
index 57bb7a1..73b59e7 100644
--- a/node/config.go
+++ b/node/config.go
@@ -30,7 +30,7 @@ import (
"github.com/ava-labs/coreth/accounts/external"
"github.com/ava-labs/coreth/accounts/keystore"
"github.com/ava-labs/coreth/accounts/scwallet"
- //"github.com/ava-labs/coreth/accounts/usbwallet"
+
"github.com/ava-labs/coreth/rpc"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
diff --git a/node/node.go b/node/node.go
index e0a6424..341f213 100644
--- a/node/node.go
+++ b/node/node.go
@@ -55,7 +55,6 @@ type Node struct {
const (
initializingState = iota
- runningState
closedState
)
diff --git a/notes/copied-list.txt b/notes/copied-list.txt
index 94353ff..e098f57 100644
--- a/notes/copied-list.txt
+++ b/notes/copied-list.txt
@@ -70,10 +70,7 @@
./eth/filters/api.go
./eth/filters/filter.go
./eth/filters/filter_system.go
-./eth/gasprice/gasprice.go
./eth/metrics.go
-./eth/protocol.go
-./ethstats/ethstats.go
./eth/tracers/internal/tracers/tracers.go
./eth/tracers/tracer.go
./eth/tracers/tracers.go
diff --git a/notes/hacked-list.txt b/notes/hacked-list.txt
index f4545ba..f951ffc 100644
--- a/notes/hacked-list.txt
+++ b/notes/hacked-list.txt
@@ -28,6 +28,7 @@
./eth/api_tracer.go
./eth/backend.go
./eth/config.go
+./eth/gasprice/gasprice.go
./eth/gen_config.go
./eth/tracers/internal/tracers/assets.go
./ethclient/ethclient.go
@@ -44,3 +45,4 @@
./rpc/client.go
./rpc/types.go
./interfaces.go
+./accounts/keystore/account_cache.go (minor formatting change to pass linting)
diff --git a/plugin/evm/error.go b/plugin/evm/error.go
index 0554349..d65d28b 100644
--- a/plugin/evm/error.go
+++ b/plugin/evm/error.go
@@ -3,7 +3,7 @@
package evm
-// TxError provides the ability for errors to be distinguished as permenant or
+// TxError provides the ability for errors to be distinguished as permanent or
// temporary
type TxError interface {
error
diff --git a/plugin/evm/service.go b/plugin/evm/service.go
index e0b73eb..8c9e16c 100644
--- a/plugin/evm/service.go
+++ b/plugin/evm/service.go
@@ -330,7 +330,6 @@ func (service *AvaxAPI) GetUTXOs(r *http.Request, args *api.GetUTXOsArgs, reply
return fmt.Errorf("number of addresses given, %d, exceeds maximum, %d", len(args.Addresses), maxGetUTXOsAddrs)
}
- sourceChain := ids.ID{}
if args.SourceChain == "" {
return errNoSourceChain
}
@@ -339,7 +338,7 @@ func (service *AvaxAPI) GetUTXOs(r *http.Request, args *api.GetUTXOsArgs, reply
if err != nil {
return fmt.Errorf("problem parsing source chainID %q: %w", args.SourceChain, err)
}
- sourceChain = chainID
+ sourceChain := chainID
addrSet := ids.ShortSet{}
for _, addrStr := range args.Addresses {