Merge pull request #2979 from karalabe/ethclient-sync-api
ethereum, ethclient: add SyncProgress API endpoint
This commit is contained in:
commit
6fb8ae2bd6
|
@ -19,6 +19,7 @@ package downloader
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
ethereum "github.com/ethereum/go-ethereum"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
@ -73,9 +74,10 @@ func (api *PublicDownloaderAPI) eventLoop() {
|
||||||
var notification interface{}
|
var notification interface{}
|
||||||
switch event.Data.(type) {
|
switch event.Data.(type) {
|
||||||
case StartEvent:
|
case StartEvent:
|
||||||
result := &SyncingResult{Syncing: true}
|
notification = &SyncingResult{
|
||||||
result.Status.Origin, result.Status.Current, result.Status.Height, result.Status.Pulled, result.Status.Known = api.d.Progress()
|
Syncing: true,
|
||||||
notification = result
|
Status: api.d.Progress(),
|
||||||
|
}
|
||||||
case DoneEvent, FailedEvent:
|
case DoneEvent, FailedEvent:
|
||||||
notification = false
|
notification = false
|
||||||
}
|
}
|
||||||
|
@ -117,19 +119,10 @@ func (api *PublicDownloaderAPI) Syncing(ctx context.Context) (*rpc.Subscription,
|
||||||
return rpcSub, nil
|
return rpcSub, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Progress gives progress indications when the node is synchronising with the Ethereum network.
|
|
||||||
type Progress struct {
|
|
||||||
Origin uint64 `json:"startingBlock"`
|
|
||||||
Current uint64 `json:"currentBlock"`
|
|
||||||
Height uint64 `json:"highestBlock"`
|
|
||||||
Pulled uint64 `json:"pulledStates"`
|
|
||||||
Known uint64 `json:"knownStates"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SyncingResult provides information about the current synchronisation status for this node.
|
// SyncingResult provides information about the current synchronisation status for this node.
|
||||||
type SyncingResult struct {
|
type SyncingResult struct {
|
||||||
Syncing bool `json:"syncing"`
|
Syncing bool `json:"syncing"`
|
||||||
Status Progress `json:"status"`
|
Status ethereum.SyncProgress `json:"status"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// uninstallSyncSubscriptionRequest uninstalles a syncing subscription in the API event loop.
|
// uninstallSyncSubscriptionRequest uninstalles a syncing subscription in the API event loop.
|
||||||
|
|
|
@ -28,6 +28,7 @@ import (
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
ethereum "github.com/ethereum/go-ethereum"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
@ -211,7 +212,7 @@ func New(stateDb ethdb.Database, mux *event.TypeMux, hasHeader headerCheckFn, ha
|
||||||
// In addition, during the state download phase of fast synchronisation the number
|
// In addition, during the state download phase of fast synchronisation the number
|
||||||
// of processed and the total number of known states are also returned. Otherwise
|
// of processed and the total number of known states are also returned. Otherwise
|
||||||
// these are zero.
|
// these are zero.
|
||||||
func (d *Downloader) Progress() (uint64, uint64, uint64, uint64, uint64) {
|
func (d *Downloader) Progress() ethereum.SyncProgress {
|
||||||
// Fetch the pending state count outside of the lock to prevent unforeseen deadlocks
|
// Fetch the pending state count outside of the lock to prevent unforeseen deadlocks
|
||||||
pendingStates := uint64(d.queue.PendingNodeData())
|
pendingStates := uint64(d.queue.PendingNodeData())
|
||||||
|
|
||||||
|
@ -228,7 +229,13 @@ func (d *Downloader) Progress() (uint64, uint64, uint64, uint64, uint64) {
|
||||||
case LightSync:
|
case LightSync:
|
||||||
current = d.headHeader().Number.Uint64()
|
current = d.headHeader().Number.Uint64()
|
||||||
}
|
}
|
||||||
return d.syncStatsChainOrigin, current, d.syncStatsChainHeight, d.syncStatsStateDone, d.syncStatsStateDone + pendingStates
|
return ethereum.SyncProgress{
|
||||||
|
StartingBlock: d.syncStatsChainOrigin,
|
||||||
|
CurrentBlock: current,
|
||||||
|
HighestBlock: d.syncStatsChainHeight,
|
||||||
|
PulledStates: d.syncStatsStateDone,
|
||||||
|
KnownStates: d.syncStatsStateDone + pendingStates,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synchronising returns whether the downloader is currently retrieving blocks.
|
// Synchronising returns whether the downloader is currently retrieving blocks.
|
||||||
|
|
|
@ -1377,8 +1377,8 @@ func testSyncProgress(t *testing.T, protocol int, mode SyncMode) {
|
||||||
<-progress
|
<-progress
|
||||||
}
|
}
|
||||||
// Retrieve the sync progress and ensure they are zero (pristine sync)
|
// Retrieve the sync progress and ensure they are zero (pristine sync)
|
||||||
if origin, current, latest, _, _ := tester.downloader.Progress(); origin != 0 || current != 0 || latest != 0 {
|
if progress := tester.downloader.Progress(); progress.StartingBlock != 0 || progress.CurrentBlock != 0 || progress.HighestBlock != 0 {
|
||||||
t.Fatalf("Pristine progress mismatch: have %v/%v/%v, want %v/%v/%v", origin, current, latest, 0, 0, 0)
|
t.Fatalf("Pristine progress mismatch: have %v/%v/%v, want %v/%v/%v", progress.StartingBlock, progress.CurrentBlock, progress.HighestBlock, 0, 0, 0)
|
||||||
}
|
}
|
||||||
// Synchronise half the blocks and check initial progress
|
// Synchronise half the blocks and check initial progress
|
||||||
tester.newPeer("peer-half", protocol, hashes[targetBlocks/2:], headers, blocks, receipts)
|
tester.newPeer("peer-half", protocol, hashes[targetBlocks/2:], headers, blocks, receipts)
|
||||||
|
@ -1392,8 +1392,8 @@ func testSyncProgress(t *testing.T, protocol int, mode SyncMode) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
<-starting
|
<-starting
|
||||||
if origin, current, latest, _, _ := tester.downloader.Progress(); origin != 0 || current != 0 || latest != uint64(targetBlocks/2+1) {
|
if progress := tester.downloader.Progress(); progress.StartingBlock != 0 || progress.CurrentBlock != 0 || progress.HighestBlock != uint64(targetBlocks/2+1) {
|
||||||
t.Fatalf("Initial progress mismatch: have %v/%v/%v, want %v/%v/%v", origin, current, latest, 0, 0, targetBlocks/2+1)
|
t.Fatalf("Initial progress mismatch: have %v/%v/%v, want %v/%v/%v", progress.StartingBlock, progress.CurrentBlock, progress.HighestBlock, 0, 0, targetBlocks/2+1)
|
||||||
}
|
}
|
||||||
progress <- struct{}{}
|
progress <- struct{}{}
|
||||||
pending.Wait()
|
pending.Wait()
|
||||||
|
@ -1409,15 +1409,15 @@ func testSyncProgress(t *testing.T, protocol int, mode SyncMode) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
<-starting
|
<-starting
|
||||||
if origin, current, latest, _, _ := tester.downloader.Progress(); origin != uint64(targetBlocks/2+1) || current != uint64(targetBlocks/2+1) || latest != uint64(targetBlocks) {
|
if progress := tester.downloader.Progress(); progress.StartingBlock != uint64(targetBlocks/2+1) || progress.CurrentBlock != uint64(targetBlocks/2+1) || progress.HighestBlock != uint64(targetBlocks) {
|
||||||
t.Fatalf("Completing progress mismatch: have %v/%v/%v, want %v/%v/%v", origin, current, latest, targetBlocks/2+1, targetBlocks/2+1, targetBlocks)
|
t.Fatalf("Completing progress mismatch: have %v/%v/%v, want %v/%v/%v", progress.StartingBlock, progress.CurrentBlock, progress.HighestBlock, targetBlocks/2+1, targetBlocks/2+1, targetBlocks)
|
||||||
}
|
}
|
||||||
progress <- struct{}{}
|
progress <- struct{}{}
|
||||||
pending.Wait()
|
pending.Wait()
|
||||||
|
|
||||||
// Check final progress after successful sync
|
// Check final progress after successful sync
|
||||||
if origin, current, latest, _, _ := tester.downloader.Progress(); origin != uint64(targetBlocks/2+1) || current != uint64(targetBlocks) || latest != uint64(targetBlocks) {
|
if progress := tester.downloader.Progress(); progress.StartingBlock != uint64(targetBlocks/2+1) || progress.CurrentBlock != uint64(targetBlocks) || progress.HighestBlock != uint64(targetBlocks) {
|
||||||
t.Fatalf("Final progress mismatch: have %v/%v/%v, want %v/%v/%v", origin, current, latest, targetBlocks/2+1, targetBlocks, targetBlocks)
|
t.Fatalf("Final progress mismatch: have %v/%v/%v, want %v/%v/%v", progress.StartingBlock, progress.CurrentBlock, progress.HighestBlock, targetBlocks/2+1, targetBlocks, targetBlocks)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1450,8 +1450,8 @@ func testForkedSyncProgress(t *testing.T, protocol int, mode SyncMode) {
|
||||||
<-progress
|
<-progress
|
||||||
}
|
}
|
||||||
// Retrieve the sync progress and ensure they are zero (pristine sync)
|
// Retrieve the sync progress and ensure they are zero (pristine sync)
|
||||||
if origin, current, latest, _, _ := tester.downloader.Progress(); origin != 0 || current != 0 || latest != 0 {
|
if progress := tester.downloader.Progress(); progress.StartingBlock != 0 || progress.CurrentBlock != 0 || progress.HighestBlock != 0 {
|
||||||
t.Fatalf("Pristine progress mismatch: have %v/%v/%v, want %v/%v/%v", origin, current, latest, 0, 0, 0)
|
t.Fatalf("Pristine progress mismatch: have %v/%v/%v, want %v/%v/%v", progress.StartingBlock, progress.CurrentBlock, progress.HighestBlock, 0, 0, 0)
|
||||||
}
|
}
|
||||||
// Synchronise with one of the forks and check progress
|
// Synchronise with one of the forks and check progress
|
||||||
tester.newPeer("fork A", protocol, hashesA, headersA, blocksA, receiptsA)
|
tester.newPeer("fork A", protocol, hashesA, headersA, blocksA, receiptsA)
|
||||||
|
@ -1465,8 +1465,8 @@ func testForkedSyncProgress(t *testing.T, protocol int, mode SyncMode) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
<-starting
|
<-starting
|
||||||
if origin, current, latest, _, _ := tester.downloader.Progress(); origin != 0 || current != 0 || latest != uint64(len(hashesA)-1) {
|
if progress := tester.downloader.Progress(); progress.StartingBlock != 0 || progress.CurrentBlock != 0 || progress.HighestBlock != uint64(len(hashesA)-1) {
|
||||||
t.Fatalf("Initial progress mismatch: have %v/%v/%v, want %v/%v/%v", origin, current, latest, 0, 0, len(hashesA)-1)
|
t.Fatalf("Initial progress mismatch: have %v/%v/%v, want %v/%v/%v", progress.StartingBlock, progress.CurrentBlock, progress.HighestBlock, 0, 0, len(hashesA)-1)
|
||||||
}
|
}
|
||||||
progress <- struct{}{}
|
progress <- struct{}{}
|
||||||
pending.Wait()
|
pending.Wait()
|
||||||
|
@ -1485,15 +1485,15 @@ func testForkedSyncProgress(t *testing.T, protocol int, mode SyncMode) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
<-starting
|
<-starting
|
||||||
if origin, current, latest, _, _ := tester.downloader.Progress(); origin != uint64(common) || current != uint64(len(hashesA)-1) || latest != uint64(len(hashesB)-1) {
|
if progress := tester.downloader.Progress(); progress.StartingBlock != uint64(common) || progress.CurrentBlock != uint64(len(hashesA)-1) || progress.HighestBlock != uint64(len(hashesB)-1) {
|
||||||
t.Fatalf("Forking progress mismatch: have %v/%v/%v, want %v/%v/%v", origin, current, latest, common, len(hashesA)-1, len(hashesB)-1)
|
t.Fatalf("Forking progress mismatch: have %v/%v/%v, want %v/%v/%v", progress.StartingBlock, progress.CurrentBlock, progress.HighestBlock, common, len(hashesA)-1, len(hashesB)-1)
|
||||||
}
|
}
|
||||||
progress <- struct{}{}
|
progress <- struct{}{}
|
||||||
pending.Wait()
|
pending.Wait()
|
||||||
|
|
||||||
// Check final progress after successful sync
|
// Check final progress after successful sync
|
||||||
if origin, current, latest, _, _ := tester.downloader.Progress(); origin != uint64(common) || current != uint64(len(hashesB)-1) || latest != uint64(len(hashesB)-1) {
|
if progress := tester.downloader.Progress(); progress.StartingBlock != uint64(common) || progress.CurrentBlock != uint64(len(hashesB)-1) || progress.HighestBlock != uint64(len(hashesB)-1) {
|
||||||
t.Fatalf("Final progress mismatch: have %v/%v/%v, want %v/%v/%v", origin, current, latest, common, len(hashesB)-1, len(hashesB)-1)
|
t.Fatalf("Final progress mismatch: have %v/%v/%v, want %v/%v/%v", progress.StartingBlock, progress.CurrentBlock, progress.HighestBlock, common, len(hashesB)-1, len(hashesB)-1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1526,8 +1526,8 @@ func testFailedSyncProgress(t *testing.T, protocol int, mode SyncMode) {
|
||||||
<-progress
|
<-progress
|
||||||
}
|
}
|
||||||
// Retrieve the sync progress and ensure they are zero (pristine sync)
|
// Retrieve the sync progress and ensure they are zero (pristine sync)
|
||||||
if origin, current, latest, _, _ := tester.downloader.Progress(); origin != 0 || current != 0 || latest != 0 {
|
if progress := tester.downloader.Progress(); progress.StartingBlock != 0 || progress.CurrentBlock != 0 || progress.HighestBlock != 0 {
|
||||||
t.Fatalf("Pristine progress mismatch: have %v/%v/%v, want %v/%v/%v", origin, current, latest, 0, 0, 0)
|
t.Fatalf("Pristine progress mismatch: have %v/%v/%v, want %v/%v/%v", progress.StartingBlock, progress.CurrentBlock, progress.HighestBlock, 0, 0, 0)
|
||||||
}
|
}
|
||||||
// Attempt a full sync with a faulty peer
|
// Attempt a full sync with a faulty peer
|
||||||
tester.newPeer("faulty", protocol, hashes, headers, blocks, receipts)
|
tester.newPeer("faulty", protocol, hashes, headers, blocks, receipts)
|
||||||
|
@ -1546,8 +1546,8 @@ func testFailedSyncProgress(t *testing.T, protocol int, mode SyncMode) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
<-starting
|
<-starting
|
||||||
if origin, current, latest, _, _ := tester.downloader.Progress(); origin != 0 || current != 0 || latest != uint64(targetBlocks) {
|
if progress := tester.downloader.Progress(); progress.StartingBlock != 0 || progress.CurrentBlock != 0 || progress.HighestBlock != uint64(targetBlocks) {
|
||||||
t.Fatalf("Initial progress mismatch: have %v/%v/%v, want %v/%v/%v", origin, current, latest, 0, 0, targetBlocks)
|
t.Fatalf("Initial progress mismatch: have %v/%v/%v, want %v/%v/%v", progress.StartingBlock, progress.CurrentBlock, progress.HighestBlock, 0, 0, targetBlocks)
|
||||||
}
|
}
|
||||||
progress <- struct{}{}
|
progress <- struct{}{}
|
||||||
pending.Wait()
|
pending.Wait()
|
||||||
|
@ -1563,15 +1563,15 @@ func testFailedSyncProgress(t *testing.T, protocol int, mode SyncMode) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
<-starting
|
<-starting
|
||||||
if origin, current, latest, _, _ := tester.downloader.Progress(); origin != 0 || current > uint64(targetBlocks/2) || latest != uint64(targetBlocks) {
|
if progress := tester.downloader.Progress(); progress.StartingBlock != 0 || progress.CurrentBlock > uint64(targetBlocks/2) || progress.HighestBlock != uint64(targetBlocks) {
|
||||||
t.Fatalf("Completing progress mismatch: have %v/%v/%v, want %v/0-%v/%v", origin, current, latest, 0, targetBlocks/2, targetBlocks)
|
t.Fatalf("Completing progress mismatch: have %v/%v/%v, want %v/0-%v/%v", progress.StartingBlock, progress.CurrentBlock, progress.HighestBlock, 0, targetBlocks/2, targetBlocks)
|
||||||
}
|
}
|
||||||
progress <- struct{}{}
|
progress <- struct{}{}
|
||||||
pending.Wait()
|
pending.Wait()
|
||||||
|
|
||||||
// Check final progress after successful sync
|
// Check final progress after successful sync
|
||||||
if origin, current, latest, _, _ := tester.downloader.Progress(); origin > uint64(targetBlocks/2) || current != uint64(targetBlocks) || latest != uint64(targetBlocks) {
|
if progress := tester.downloader.Progress(); progress.StartingBlock > uint64(targetBlocks/2) || progress.CurrentBlock != uint64(targetBlocks) || progress.HighestBlock != uint64(targetBlocks) {
|
||||||
t.Fatalf("Final progress mismatch: have %v/%v/%v, want 0-%v/%v/%v", origin, current, latest, targetBlocks/2, targetBlocks, targetBlocks)
|
t.Fatalf("Final progress mismatch: have %v/%v/%v, want 0-%v/%v/%v", progress.StartingBlock, progress.CurrentBlock, progress.HighestBlock, targetBlocks/2, targetBlocks, targetBlocks)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1603,8 +1603,8 @@ func testFakedSyncProgress(t *testing.T, protocol int, mode SyncMode) {
|
||||||
<-progress
|
<-progress
|
||||||
}
|
}
|
||||||
// Retrieve the sync progress and ensure they are zero (pristine sync)
|
// Retrieve the sync progress and ensure they are zero (pristine sync)
|
||||||
if origin, current, latest, _, _ := tester.downloader.Progress(); origin != 0 || current != 0 || latest != 0 {
|
if progress := tester.downloader.Progress(); progress.StartingBlock != 0 || progress.CurrentBlock != 0 || progress.HighestBlock != 0 {
|
||||||
t.Fatalf("Pristine progress mismatch: have %v/%v/%v, want %v/%v/%v", origin, current, latest, 0, 0, 0)
|
t.Fatalf("Pristine progress mismatch: have %v/%v/%v, want %v/%v/%v", progress.StartingBlock, progress.CurrentBlock, progress.HighestBlock, 0, 0, 0)
|
||||||
}
|
}
|
||||||
// Create and sync with an attacker that promises a higher chain than available
|
// Create and sync with an attacker that promises a higher chain than available
|
||||||
tester.newPeer("attack", protocol, hashes, headers, blocks, receipts)
|
tester.newPeer("attack", protocol, hashes, headers, blocks, receipts)
|
||||||
|
@ -1624,8 +1624,8 @@ func testFakedSyncProgress(t *testing.T, protocol int, mode SyncMode) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
<-starting
|
<-starting
|
||||||
if origin, current, latest, _, _ := tester.downloader.Progress(); origin != 0 || current != 0 || latest != uint64(targetBlocks+3) {
|
if progress := tester.downloader.Progress(); progress.StartingBlock != 0 || progress.CurrentBlock != 0 || progress.HighestBlock != uint64(targetBlocks+3) {
|
||||||
t.Fatalf("Initial progress mismatch: have %v/%v/%v, want %v/%v/%v", origin, current, latest, 0, 0, targetBlocks+3)
|
t.Fatalf("Initial progress mismatch: have %v/%v/%v, want %v/%v/%v", progress.StartingBlock, progress.CurrentBlock, progress.HighestBlock, 0, 0, targetBlocks+3)
|
||||||
}
|
}
|
||||||
progress <- struct{}{}
|
progress <- struct{}{}
|
||||||
pending.Wait()
|
pending.Wait()
|
||||||
|
@ -1641,15 +1641,15 @@ func testFakedSyncProgress(t *testing.T, protocol int, mode SyncMode) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
<-starting
|
<-starting
|
||||||
if origin, current, latest, _, _ := tester.downloader.Progress(); origin != 0 || current > uint64(targetBlocks) || latest != uint64(targetBlocks) {
|
if progress := tester.downloader.Progress(); progress.StartingBlock != 0 || progress.CurrentBlock > uint64(targetBlocks) || progress.HighestBlock != uint64(targetBlocks) {
|
||||||
t.Fatalf("Completing progress mismatch: have %v/%v/%v, want %v/0-%v/%v", origin, current, latest, 0, targetBlocks, targetBlocks)
|
t.Fatalf("Completing progress mismatch: have %v/%v/%v, want %v/0-%v/%v", progress.StartingBlock, progress.CurrentBlock, progress.HighestBlock, 0, targetBlocks, targetBlocks)
|
||||||
}
|
}
|
||||||
progress <- struct{}{}
|
progress <- struct{}{}
|
||||||
pending.Wait()
|
pending.Wait()
|
||||||
|
|
||||||
// Check final progress after successful sync
|
// Check final progress after successful sync
|
||||||
if origin, current, latest, _, _ := tester.downloader.Progress(); origin > uint64(targetBlocks) || current != uint64(targetBlocks) || latest != uint64(targetBlocks) {
|
if progress := tester.downloader.Progress(); progress.StartingBlock > uint64(targetBlocks) || progress.CurrentBlock != uint64(targetBlocks) || progress.HighestBlock != uint64(targetBlocks) {
|
||||||
t.Fatalf("Final progress mismatch: have %v/%v/%v, want 0-%v/%v/%v", origin, current, latest, targetBlocks, targetBlocks, targetBlocks)
|
t.Fatalf("Final progress mismatch: have %v/%v/%v, want 0-%v/%v/%v", progress.StartingBlock, progress.CurrentBlock, progress.HighestBlock, targetBlocks, targetBlocks, targetBlocks)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -191,6 +191,39 @@ func toBlockNumArg(number *big.Int) string {
|
||||||
return fmt.Sprintf("%#x", number)
|
return fmt.Sprintf("%#x", number)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type rpcProgress struct {
|
||||||
|
StartingBlock rpc.HexNumber
|
||||||
|
CurrentBlock rpc.HexNumber
|
||||||
|
HighestBlock rpc.HexNumber
|
||||||
|
PulledStates rpc.HexNumber
|
||||||
|
KnownStates rpc.HexNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
// SyncProgress retrieves the current progress of the sync algorithm. If there's
|
||||||
|
// no sync currently running, it returns nil.
|
||||||
|
func (ec *Client) SyncProgress(ctx context.Context) (*ethereum.SyncProgress, error) {
|
||||||
|
var raw json.RawMessage
|
||||||
|
if err := ec.c.CallContext(ctx, &raw, "eth_syncing"); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Handle the possible response types
|
||||||
|
var syncing bool
|
||||||
|
if err := json.Unmarshal(raw, &syncing); err == nil {
|
||||||
|
return nil, nil // Not syncing (always false)
|
||||||
|
}
|
||||||
|
var progress *rpcProgress
|
||||||
|
if err := json.Unmarshal(raw, &progress); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ðereum.SyncProgress{
|
||||||
|
StartingBlock: progress.StartingBlock.Uint64(),
|
||||||
|
CurrentBlock: progress.CurrentBlock.Uint64(),
|
||||||
|
HighestBlock: progress.HighestBlock.Uint64(),
|
||||||
|
PulledStates: progress.PulledStates.Uint64(),
|
||||||
|
KnownStates: progress.KnownStates.Uint64(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// SubscribeNewHead subscribes to notifications about the current blockchain head
|
// SubscribeNewHead subscribes to notifications about the current blockchain head
|
||||||
// on the given channel.
|
// on the given channel.
|
||||||
func (ec *Client) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) {
|
func (ec *Client) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import "github.com/ethereum/go-ethereum"
|
||||||
var (
|
var (
|
||||||
_ = ethereum.ChainReader(&Client{})
|
_ = ethereum.ChainReader(&Client{})
|
||||||
_ = ethereum.ChainStateReader(&Client{})
|
_ = ethereum.ChainStateReader(&Client{})
|
||||||
|
_ = ethereum.ChainSyncReader(&Client{})
|
||||||
_ = ethereum.ChainHeadEventer(&Client{})
|
_ = ethereum.ChainHeadEventer(&Client{})
|
||||||
_ = ethereum.ContractCaller(&Client{})
|
_ = ethereum.ContractCaller(&Client{})
|
||||||
_ = ethereum.GasEstimator(&Client{})
|
_ = ethereum.GasEstimator(&Client{})
|
||||||
|
|
|
@ -67,6 +67,22 @@ type ChainStateReader interface {
|
||||||
NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error)
|
NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SyncProgress gives progress indications when the node is synchronising with
|
||||||
|
// the Ethereum network.
|
||||||
|
type SyncProgress struct {
|
||||||
|
StartingBlock uint64 // Block number where sync began
|
||||||
|
CurrentBlock uint64 // Current block number where sync is at
|
||||||
|
HighestBlock uint64 // Highest alleged block number in the chain
|
||||||
|
PulledStates uint64 // Number of state trie entries already downloaded
|
||||||
|
KnownStates uint64 // Total number os state trie entries known about
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChainSyncReader wraps access to the node's current sync status. If there's no
|
||||||
|
// sync currently running, it returns nil.
|
||||||
|
type ChainSyncReader interface {
|
||||||
|
SyncProgress(ctx context.Context) (*SyncProgress, error)
|
||||||
|
}
|
||||||
|
|
||||||
// A ChainHeadEventer returns notifications whenever the canonical head block is updated.
|
// A ChainHeadEventer returns notifications whenever the canonical head block is updated.
|
||||||
type ChainHeadEventer interface {
|
type ChainHeadEventer interface {
|
||||||
SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (Subscription, error)
|
SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (Subscription, error)
|
||||||
|
|
|
@ -73,19 +73,19 @@ func (s *PublicEthereumAPI) ProtocolVersion() *rpc.HexNumber {
|
||||||
// - pulledStates: number of state entries processed until now
|
// - pulledStates: number of state entries processed until now
|
||||||
// - knownStates: number of known state entries that still need to be pulled
|
// - knownStates: number of known state entries that still need to be pulled
|
||||||
func (s *PublicEthereumAPI) Syncing() (interface{}, error) {
|
func (s *PublicEthereumAPI) Syncing() (interface{}, error) {
|
||||||
origin, current, height, pulled, known := s.b.Downloader().Progress()
|
progress := s.b.Downloader().Progress()
|
||||||
|
|
||||||
// Return not syncing if the synchronisation already completed
|
// Return not syncing if the synchronisation already completed
|
||||||
if current >= height {
|
if progress.CurrentBlock >= progress.HighestBlock {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
// Otherwise gather the block sync stats
|
// Otherwise gather the block sync stats
|
||||||
return map[string]interface{}{
|
return map[string]interface{}{
|
||||||
"startingBlock": rpc.NewHexNumber(origin),
|
"startingBlock": rpc.NewHexNumber(progress.StartingBlock),
|
||||||
"currentBlock": rpc.NewHexNumber(current),
|
"currentBlock": rpc.NewHexNumber(progress.CurrentBlock),
|
||||||
"highestBlock": rpc.NewHexNumber(height),
|
"highestBlock": rpc.NewHexNumber(progress.HighestBlock),
|
||||||
"pulledStates": rpc.NewHexNumber(pulled),
|
"pulledStates": rpc.NewHexNumber(progress.PulledStates),
|
||||||
"knownStates": rpc.NewHexNumber(known),
|
"knownStates": rpc.NewHexNumber(progress.KnownStates),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue