Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
99cba96f26 | |||
f272879e5a | |||
72dd51e25a | |||
799a469000 | |||
f4d81178d8 | |||
310d2e7ef4 | |||
3ecde4e2aa | |||
a355b401db | |||
cba33029a8 | |||
9702badd83 | |||
067dc2cbf5 |
@ -182,10 +182,8 @@ func DecryptKey(keyjson []byte, auth string) (*Key, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
key, err := crypto.ToECDSA(keyBytes)
|
key := crypto.ToECDSAUnsafe(keyBytes)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &Key{
|
return &Key{
|
||||||
Id: uuid.UUID(keyId),
|
Id: uuid.UUID(keyId),
|
||||||
Address: crypto.PubkeyToAddress(key.PublicKey),
|
Address: crypto.PubkeyToAddress(key.PublicKey),
|
||||||
|
@ -74,10 +74,8 @@ func decryptPreSaleKey(fileContent []byte, password string) (key *Key, err error
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ethPriv := crypto.Keccak256(plainText)
|
ethPriv := crypto.Keccak256(plainText)
|
||||||
ecKey, err := crypto.ToECDSA(ethPriv)
|
ecKey := crypto.ToECDSAUnsafe(ethPriv)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
key = &Key{
|
key = &Key{
|
||||||
Id: nil,
|
Id: nil,
|
||||||
Address: crypto.PubkeyToAddress(ecKey.PublicKey),
|
Address: crypto.PubkeyToAddress(ecKey.PublicKey),
|
||||||
|
@ -2,7 +2,7 @@ FROM alpine:3.5
|
|||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
apk add --update go git make gcc musl-dev linux-headers ca-certificates && \
|
apk add --update go git make gcc musl-dev linux-headers ca-certificates && \
|
||||||
git clone --depth 1 --branch release/1.5 https://github.com/ethereum/go-ethereum && \
|
git clone --depth 1 --branch release/1.6 https://github.com/ethereum/go-ethereum && \
|
||||||
(cd go-ethereum && make geth) && \
|
(cd go-ethereum && make geth) && \
|
||||||
cp go-ethereum/build/bin/geth /geth && \
|
cp go-ethereum/build/bin/geth /geth && \
|
||||||
apk del go git make gcc musl-dev linux-headers && \
|
apk del go git make gcc musl-dev linux-headers && \
|
||||||
|
@ -251,7 +251,7 @@ func (pool *TxPool) resetState() {
|
|||||||
}
|
}
|
||||||
// Check the queue and move transactions over to the pending if possible
|
// Check the queue and move transactions over to the pending if possible
|
||||||
// or remove those that have become invalid
|
// or remove those that have become invalid
|
||||||
pool.promoteExecutables(currentState)
|
pool.promoteExecutables(currentState, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop terminates the transaction pool.
|
// Stop terminates the transaction pool.
|
||||||
@ -339,17 +339,6 @@ func (pool *TxPool) Pending() (map[common.Address]types.Transactions, error) {
|
|||||||
pool.mu.Lock()
|
pool.mu.Lock()
|
||||||
defer pool.mu.Unlock()
|
defer pool.mu.Unlock()
|
||||||
|
|
||||||
state, err := pool.currentState()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// check queue first
|
|
||||||
pool.promoteExecutables(state)
|
|
||||||
|
|
||||||
// invalidate any txs
|
|
||||||
pool.demoteUnexecutables(state)
|
|
||||||
|
|
||||||
pending := make(map[common.Address]types.Transactions)
|
pending := make(map[common.Address]types.Transactions)
|
||||||
for addr, list := range pool.pending {
|
for addr, list := range pool.pending {
|
||||||
pending[addr] = list.Flatten()
|
pending[addr] = list.Flatten()
|
||||||
@ -551,13 +540,14 @@ func (pool *TxPool) Add(tx *types.Transaction) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
state, err := pool.currentState()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// If we added a new transaction, run promotion checks and return
|
// If we added a new transaction, run promotion checks and return
|
||||||
if !replace {
|
if !replace {
|
||||||
pool.promoteExecutables(state)
|
state, err := pool.currentState()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
from, _ := types.Sender(pool.signer, tx) // already validated
|
||||||
|
pool.promoteExecutables(state, []common.Address{from})
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -568,24 +558,26 @@ func (pool *TxPool) AddBatch(txs []*types.Transaction) error {
|
|||||||
defer pool.mu.Unlock()
|
defer pool.mu.Unlock()
|
||||||
|
|
||||||
// Add the batch of transaction, tracking the accepted ones
|
// Add the batch of transaction, tracking the accepted ones
|
||||||
replaced, added := true, 0
|
dirty := make(map[common.Address]struct{})
|
||||||
for _, tx := range txs {
|
for _, tx := range txs {
|
||||||
if replace, err := pool.add(tx); err == nil {
|
if replace, err := pool.add(tx); err == nil {
|
||||||
added++
|
|
||||||
if !replace {
|
if !replace {
|
||||||
replaced = false
|
from, _ := types.Sender(pool.signer, tx) // already validated
|
||||||
|
dirty[from] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Only reprocess the internal state if something was actually added
|
// Only reprocess the internal state if something was actually added
|
||||||
if added > 0 {
|
if len(dirty) > 0 {
|
||||||
state, err := pool.currentState()
|
state, err := pool.currentState()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !replaced {
|
addrs := make([]common.Address, 0, len(dirty))
|
||||||
pool.promoteExecutables(state)
|
for addr, _ := range dirty {
|
||||||
|
addrs = append(addrs, addr)
|
||||||
}
|
}
|
||||||
|
pool.promoteExecutables(state, addrs)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -662,12 +654,23 @@ func (pool *TxPool) removeTx(hash common.Hash) {
|
|||||||
// promoteExecutables moves transactions that have become processable from the
|
// promoteExecutables moves transactions that have become processable from the
|
||||||
// future queue to the set of pending transactions. During this process, all
|
// future queue to the set of pending transactions. During this process, all
|
||||||
// invalidated transactions (low nonce, low balance) are deleted.
|
// invalidated transactions (low nonce, low balance) are deleted.
|
||||||
func (pool *TxPool) promoteExecutables(state *state.StateDB) {
|
func (pool *TxPool) promoteExecutables(state *state.StateDB, accounts []common.Address) {
|
||||||
gaslimit := pool.gasLimit()
|
gaslimit := pool.gasLimit()
|
||||||
|
|
||||||
|
// Gather all the accounts potentially needing updates
|
||||||
|
if accounts == nil {
|
||||||
|
accounts = make([]common.Address, 0, len(pool.queue))
|
||||||
|
for addr, _ := range pool.queue {
|
||||||
|
accounts = append(accounts, addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
// Iterate over all accounts and promote any executable transactions
|
// Iterate over all accounts and promote any executable transactions
|
||||||
queued := uint64(0)
|
queued := uint64(0)
|
||||||
for addr, list := range pool.queue {
|
for _, addr := range accounts {
|
||||||
|
list := pool.queue[addr]
|
||||||
|
if list == nil {
|
||||||
|
continue // Just in case someone calls with a non existing account
|
||||||
|
}
|
||||||
// Drop all transactions that are deemed too old (low nonce)
|
// Drop all transactions that are deemed too old (low nonce)
|
||||||
for _, tx := range list.Forward(state.GetNonce(addr)) {
|
for _, tx := range list.Forward(state.GetNonce(addr)) {
|
||||||
hash := tx.Hash()
|
hash := tx.Hash()
|
||||||
|
@ -175,7 +175,7 @@ func TestTransactionQueue(t *testing.T) {
|
|||||||
pool.resetState()
|
pool.resetState()
|
||||||
pool.enqueueTx(tx.Hash(), tx)
|
pool.enqueueTx(tx.Hash(), tx)
|
||||||
|
|
||||||
pool.promoteExecutables(currentState)
|
pool.promoteExecutables(currentState, []common.Address{from})
|
||||||
if len(pool.pending) != 1 {
|
if len(pool.pending) != 1 {
|
||||||
t.Error("expected valid txs to be 1 is", len(pool.pending))
|
t.Error("expected valid txs to be 1 is", len(pool.pending))
|
||||||
}
|
}
|
||||||
@ -184,7 +184,7 @@ func TestTransactionQueue(t *testing.T) {
|
|||||||
from, _ = deriveSender(tx)
|
from, _ = deriveSender(tx)
|
||||||
currentState.SetNonce(from, 2)
|
currentState.SetNonce(from, 2)
|
||||||
pool.enqueueTx(tx.Hash(), tx)
|
pool.enqueueTx(tx.Hash(), tx)
|
||||||
pool.promoteExecutables(currentState)
|
pool.promoteExecutables(currentState, []common.Address{from})
|
||||||
if _, ok := pool.pending[from].txs.items[tx.Nonce()]; ok {
|
if _, ok := pool.pending[from].txs.items[tx.Nonce()]; ok {
|
||||||
t.Error("expected transaction to be in tx pool")
|
t.Error("expected transaction to be in tx pool")
|
||||||
}
|
}
|
||||||
@ -206,7 +206,7 @@ func TestTransactionQueue(t *testing.T) {
|
|||||||
pool.enqueueTx(tx2.Hash(), tx2)
|
pool.enqueueTx(tx2.Hash(), tx2)
|
||||||
pool.enqueueTx(tx3.Hash(), tx3)
|
pool.enqueueTx(tx3.Hash(), tx3)
|
||||||
|
|
||||||
pool.promoteExecutables(currentState)
|
pool.promoteExecutables(currentState, []common.Address{from})
|
||||||
|
|
||||||
if len(pool.pending) != 1 {
|
if len(pool.pending) != 1 {
|
||||||
t.Error("expected tx pool to be 1, got", len(pool.pending))
|
t.Error("expected tx pool to be 1, got", len(pool.pending))
|
||||||
@ -304,16 +304,16 @@ func TestTransactionDoubleNonce(t *testing.T) {
|
|||||||
t.Errorf("second transaction insert failed (%v) or not reported replacement (%v)", err, replace)
|
t.Errorf("second transaction insert failed (%v) or not reported replacement (%v)", err, replace)
|
||||||
}
|
}
|
||||||
state, _ := pool.currentState()
|
state, _ := pool.currentState()
|
||||||
pool.promoteExecutables(state)
|
pool.promoteExecutables(state, []common.Address{addr})
|
||||||
if pool.pending[addr].Len() != 1 {
|
if pool.pending[addr].Len() != 1 {
|
||||||
t.Error("expected 1 pending transactions, got", pool.pending[addr].Len())
|
t.Error("expected 1 pending transactions, got", pool.pending[addr].Len())
|
||||||
}
|
}
|
||||||
if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() {
|
if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() {
|
||||||
t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash())
|
t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash())
|
||||||
}
|
}
|
||||||
// Add the thid transaction and ensure it's not saved (smaller price)
|
// Add the third transaction and ensure it's not saved (smaller price)
|
||||||
pool.add(tx3)
|
pool.add(tx3)
|
||||||
pool.promoteExecutables(state)
|
pool.promoteExecutables(state, []common.Address{addr})
|
||||||
if pool.pending[addr].Len() != 1 {
|
if pool.pending[addr].Len() != 1 {
|
||||||
t.Error("expected 1 pending transactions, got", pool.pending[addr].Len())
|
t.Error("expected 1 pending transactions, got", pool.pending[addr].Len())
|
||||||
}
|
}
|
||||||
@ -1087,7 +1087,7 @@ func benchmarkFuturePromotion(b *testing.B, size int) {
|
|||||||
// Benchmark the speed of pool validation
|
// Benchmark the speed of pool validation
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
pool.promoteExecutables(state)
|
pool.promoteExecutables(state, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,9 +68,6 @@ func Keccak512(data ...[]byte) []byte {
|
|||||||
return d.Sum(nil)
|
return d.Sum(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: For backward compatibility as other packages depend on these
|
|
||||||
func Sha3Hash(data ...[]byte) common.Hash { return Keccak256Hash(data...) }
|
|
||||||
|
|
||||||
// Creates an ethereum address given the bytes and the nonce
|
// Creates an ethereum address given the bytes and the nonce
|
||||||
func CreateAddress(b common.Address, nonce uint64) common.Address {
|
func CreateAddress(b common.Address, nonce uint64) common.Address {
|
||||||
data, _ := rlp.EncodeToBytes([]interface{}{b, nonce})
|
data, _ := rlp.EncodeToBytes([]interface{}{b, nonce})
|
||||||
@ -79,9 +76,24 @@ func CreateAddress(b common.Address, nonce uint64) common.Address {
|
|||||||
|
|
||||||
// ToECDSA creates a private key with the given D value.
|
// ToECDSA creates a private key with the given D value.
|
||||||
func ToECDSA(d []byte) (*ecdsa.PrivateKey, error) {
|
func ToECDSA(d []byte) (*ecdsa.PrivateKey, error) {
|
||||||
|
return toECDSA(d, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToECDSAUnsafe blidly converts a binary blob to a private key. It should almost
|
||||||
|
// never be used unless you are sure the input is valid and want to avoid hitting
|
||||||
|
// errors due to bad origin encoding (0 prefixes cut off).
|
||||||
|
func ToECDSAUnsafe(d []byte) *ecdsa.PrivateKey {
|
||||||
|
priv, _ := toECDSA(d, false)
|
||||||
|
return priv
|
||||||
|
}
|
||||||
|
|
||||||
|
// toECDSA creates a private key with the given D value. The strict parameter
|
||||||
|
// controls whether the key's length should be enforced at the curve size or
|
||||||
|
// it can also accept legacy encodings (0 prefixes).
|
||||||
|
func toECDSA(d []byte, strict bool) (*ecdsa.PrivateKey, error) {
|
||||||
priv := new(ecdsa.PrivateKey)
|
priv := new(ecdsa.PrivateKey)
|
||||||
priv.PublicKey.Curve = S256()
|
priv.PublicKey.Curve = S256()
|
||||||
if 8*len(d) != priv.Params().BitSize {
|
if strict && 8*len(d) != priv.Params().BitSize {
|
||||||
return nil, fmt.Errorf("invalid length, need %d bits", priv.Params().BitSize)
|
return nil, fmt.Errorf("invalid length, need %d bits", priv.Params().BitSize)
|
||||||
}
|
}
|
||||||
priv.D = new(big.Int).SetBytes(d)
|
priv.D = new(big.Int).SetBytes(d)
|
||||||
@ -89,11 +101,12 @@ func ToECDSA(d []byte) (*ecdsa.PrivateKey, error) {
|
|||||||
return priv, nil
|
return priv, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func FromECDSA(prv *ecdsa.PrivateKey) []byte {
|
// FromECDSA exports a private key into a binary dump.
|
||||||
if prv == nil {
|
func FromECDSA(priv *ecdsa.PrivateKey) []byte {
|
||||||
|
if priv == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return math.PaddedBigBytes(prv.D, 32)
|
return math.PaddedBigBytes(priv.D, priv.Params().BitSize/8)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToECDSAPub(pub []byte) *ecdsa.PublicKey {
|
func ToECDSAPub(pub []byte) *ecdsa.PublicKey {
|
||||||
@ -121,7 +134,6 @@ func HexToECDSA(hexkey string) (*ecdsa.PrivateKey, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LoadECDSA loads a secp256k1 private key from the given file.
|
// LoadECDSA loads a secp256k1 private key from the given file.
|
||||||
// The key data is expected to be hex-encoded.
|
|
||||||
func LoadECDSA(file string) (*ecdsa.PrivateKey, error) {
|
func LoadECDSA(file string) (*ecdsa.PrivateKey, error) {
|
||||||
buf := make([]byte, 64)
|
buf := make([]byte, 64)
|
||||||
fd, err := os.Open(file)
|
fd, err := os.Open(file)
|
||||||
|
@ -36,7 +36,7 @@ var testPrivHex = "289c2857d4598e37fb9647507e47a309d6133539bf21a8b9cb6df88fd5232
|
|||||||
// These tests are sanity checks.
|
// These tests are sanity checks.
|
||||||
// They should ensure that we don't e.g. use Sha3-224 instead of Sha3-256
|
// They should ensure that we don't e.g. use Sha3-224 instead of Sha3-256
|
||||||
// and that the sha3 library uses keccak-f permutation.
|
// and that the sha3 library uses keccak-f permutation.
|
||||||
func TestSha3Hash(t *testing.T) {
|
func TestKeccak256Hash(t *testing.T) {
|
||||||
msg := []byte("abc")
|
msg := []byte("abc")
|
||||||
exp, _ := hex.DecodeString("4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45")
|
exp, _ := hex.DecodeString("4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45")
|
||||||
checkhash(t, "Sha3-256-array", func(in []byte) []byte { h := Keccak256Hash(in); return h[:] }, msg, exp)
|
checkhash(t, "Sha3-256-array", func(in []byte) []byte { h := Keccak256Hash(in); return h[:] }, msg, exp)
|
||||||
|
@ -31,6 +31,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/mclock"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
@ -119,7 +120,7 @@ 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() {
|
func (s *Service) loop() {
|
||||||
// Subscribe tso chain events to execute updates on
|
// Subscribe to chain events to execute updates on
|
||||||
var emux *event.TypeMux
|
var emux *event.TypeMux
|
||||||
if s.eth != nil {
|
if s.eth != nil {
|
||||||
emux = s.eth.EventMux()
|
emux = s.eth.EventMux()
|
||||||
@ -132,6 +133,46 @@ func (s *Service) loop() {
|
|||||||
txSub := emux.Subscribe(core.TxPreEvent{})
|
txSub := emux.Subscribe(core.TxPreEvent{})
|
||||||
defer txSub.Unsubscribe()
|
defer txSub.Unsubscribe()
|
||||||
|
|
||||||
|
// Start a goroutine that exhausts the subsciptions 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
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
// Notify of chain head events, but drop if too frequent
|
||||||
|
case head, ok := <-headSub.Chan():
|
||||||
|
if !ok { // node stopped
|
||||||
|
close(quitCh)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case headCh <- head.Data.(core.ChainHeadEvent).Block:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify of new transaction events, but drop if too frequent
|
||||||
|
case _, ok := <-txSub.Chan():
|
||||||
|
if !ok { // node stopped
|
||||||
|
close(quitCh)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if time.Duration(mclock.Now()-lastTx) < time.Second {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
lastTx = mclock.Now()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case txCh <- struct{}{}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
// Loop reporting until termination
|
// Loop reporting until termination
|
||||||
for {
|
for {
|
||||||
// Resolve the URL, defaulting to TLS, but falling back to none too
|
// Resolve the URL, defaulting to TLS, but falling back to none too
|
||||||
@ -151,7 +192,7 @@ func (s *Service) loop() {
|
|||||||
if conf, err = websocket.NewConfig(url, "http://localhost/"); err != nil {
|
if conf, err = websocket.NewConfig(url, "http://localhost/"); err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
conf.Dialer = &net.Dialer{Timeout: 3 * time.Second}
|
conf.Dialer = &net.Dialer{Timeout: 5 * time.Second}
|
||||||
if conn, err = websocket.DialConfig(conf); err == nil {
|
if conn, err = websocket.DialConfig(conf); err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -181,6 +222,10 @@ func (s *Service) loop() {
|
|||||||
|
|
||||||
for err == nil {
|
for err == nil {
|
||||||
select {
|
select {
|
||||||
|
case <-quitCh:
|
||||||
|
conn.Close()
|
||||||
|
return
|
||||||
|
|
||||||
case <-fullReport.C:
|
case <-fullReport.C:
|
||||||
if err = s.report(conn); err != nil {
|
if err = s.report(conn); err != nil {
|
||||||
log.Warn("Full stats report failed", "err", err)
|
log.Warn("Full stats report failed", "err", err)
|
||||||
@ -189,30 +234,14 @@ func (s *Service) loop() {
|
|||||||
if err = s.reportHistory(conn, list); err != nil {
|
if err = s.reportHistory(conn, list); err != nil {
|
||||||
log.Warn("Requested history report failed", "err", err)
|
log.Warn("Requested history report failed", "err", err)
|
||||||
}
|
}
|
||||||
case head, ok := <-headSub.Chan():
|
case head := <-headCh:
|
||||||
if !ok { // node stopped
|
if err = s.reportBlock(conn, head); err != nil {
|
||||||
conn.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err = s.reportBlock(conn, head.Data.(core.ChainHeadEvent).Block); err != nil {
|
|
||||||
log.Warn("Block stats report failed", "err", err)
|
log.Warn("Block stats report failed", "err", err)
|
||||||
}
|
}
|
||||||
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 _, ok := <-txSub.Chan():
|
case <-txCh:
|
||||||
if !ok { // node stopped
|
|
||||||
conn.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Exhaust events to avoid reporting too frequently
|
|
||||||
for exhausted := false; !exhausted; {
|
|
||||||
select {
|
|
||||||
case <-headSub.Chan():
|
|
||||||
default:
|
|
||||||
exhausted = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
@ -398,7 +427,7 @@ func (s *Service) reportLatency(conn *websocket.Conn) error {
|
|||||||
select {
|
select {
|
||||||
case <-s.pongCh:
|
case <-s.pongCh:
|
||||||
// Pong delivered, report the latency
|
// Pong delivered, report the latency
|
||||||
case <-time.After(3 * time.Second):
|
case <-time.After(5 * time.Second):
|
||||||
// Ping timeout, abort
|
// Ping timeout, abort
|
||||||
return errors.New("ping timed out")
|
return errors.New("ping timed out")
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
VersionMajor = 1 // Major version component of the current release
|
VersionMajor = 1 // Major version component of the current release
|
||||||
VersionMinor = 6 // Minor version component of the current release
|
VersionMinor = 6 // Minor version component of the current release
|
||||||
VersionPatch = 2 // Patch version component of the current release
|
VersionPatch = 3 // Patch version component of the current release
|
||||||
VersionMeta = "stable" // Version metadata to append to the version string
|
VersionMeta = "stable" // Version metadata to append to the version string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user