Commit 8b703dae authored by Luke Champine's avatar Luke Champine

Merge branch 'sync-progress' into 'master'

Sync progress

See merge request !3383
parents 6967d768 c79369d9
Pipeline #41858664 failed with stages
in 116 minutes and 17 seconds
......@@ -6,6 +6,7 @@ import (
"github.com/spf13/cobra"
"gitlab.com/NebulousLabs/Sia/node/api"
"gitlab.com/NebulousLabs/Sia/types"
)
......@@ -16,6 +17,8 @@ var (
Long: "Print the current state of consensus such as current block, block height, and target.",
Run: wrap(consensuscmd),
}
consensusCmdVerbose bool
)
// consensuscmd is the handler for the command `siac consensus`.
......@@ -33,25 +36,30 @@ Target: %v
Difficulty: %v
`, yesNo(cg.Synced), cg.CurrentBlock, cg.Height, cg.Target, cg.Difficulty)
} else {
estimatedHeight := estimatedHeightAt(time.Now())
estimatedHeight := estimatedHeightAt(time.Now(), cg)
estimatedProgress := float64(cg.Height) / float64(estimatedHeight) * 100
if estimatedProgress > 100 {
estimatedProgress = 100
estimatedProgress = 99.9
}
fmt.Printf(`Synced: %v
Height: %v
Progress (estimated): %.1f%%
`, yesNo(cg.Synced), cg.Height, estimatedProgress)
}
if consensusCmdVerbose {
fmt.Println()
fmt.Println("Block Frequency:", cg.BlockFrequency)
fmt.Println("Block Size Limit:", cg.BlockSizeLimit)
fmt.Println("Maturity Delay:", cg.MaturityDelay)
fmt.Println("Genesis Timestamp:", time.Unix(int64(cg.GenesisTimestamp), 0))
}
}
// estimatedHeightAt returns the estimated block height for the given time.
// Block height is estimated by calculating the minutes since a known block in
// the past and dividing by 10 minutes (the block time).
func estimatedHeightAt(t time.Time) types.BlockHeight {
block100kTimestamp := time.Date(2017, time.April, 13, 23, 29, 49, 0, time.UTC)
blockTime := float64(9) // overestimate block time for better UX
diff := t.Sub(block100kTimestamp)
estimatedHeight := 100e3 + (diff.Minutes() / blockTime)
return types.BlockHeight(estimatedHeight + 0.5) // round to the nearest block
func estimatedHeightAt(t time.Time, cg api.ConsensusGET) types.BlockHeight {
gt := cg.GenesisTimestamp
bf := cg.BlockFrequency
return types.BlockHeight(types.Timestamp(t.Unix())-gt) / bf
}
package main
import (
"testing"
"time"
"gitlab.com/NebulousLabs/Sia/types"
)
// TestEstimatedHeightAt tests that the expectedHeightAt function correctly
// estimates the blockheight (and rounds to the nearest block).
func TestEstimatedHeightAt(t *testing.T) {
tests := []struct {
t time.Time
expectedHeight types.BlockHeight
}{
// Test on the same block that is used to estimate the height
{
time.Date(2017, time.April, 13, 23, 29, 49, 0, time.UTC),
100e3,
},
// 4 minutes later
{
time.Date(2017, time.April, 13, 23, 33, 49, 0, time.UTC),
100e3,
},
// 5 minutes later
{
time.Date(2017, time.April, 13, 23, 34, 49, 0, time.UTC),
100e3 + 1,
},
// 15 minutes later
{
time.Date(2017, time.April, 13, 23, 44, 49, 0, time.UTC),
100e3 + 2,
},
// 1 day later
{
time.Date(2017, time.April, 14, 23, 29, 49, 0, time.UTC),
100e3 + 160,
},
}
for _, tt := range tests {
h := estimatedHeightAt(tt.t)
if h != tt.expectedHeight {
t.Errorf("expected an estimated height of %v, but got %v", tt.expectedHeight, h)
}
}
}
......@@ -161,6 +161,7 @@ func main() {
gatewayCmd.AddCommand(gatewayConnectCmd, gatewayDisconnectCmd, gatewayAddressCmd, gatewayListCmd)
root.AddCommand(consensusCmd)
consensusCmd.Flags().BoolVarP(&consensusCmdVerbose, "verbose", "v", false, "Display full consensus information")
utilsCmd.AddCommand(bashcomplCmd, mangenCmd, utilsHastingsCmd, utilsEncodeRawTxnCmd, utilsDecodeRawTxnCmd,
utilsSigHashCmd, utilsCheckSigCmd, utilsVerifySeedCmd)
......
......@@ -113,6 +113,7 @@ The consensus set manages everything related to consensus and keeps the blockcha
## /consensus [GET]
Returns information about the consensus set, such as the current block height.
Also returns the set of constants in use in the consensus code.
### JSON Response
> JSON Response Example
......@@ -124,6 +125,24 @@ Returns information about the consensus set, such as the current block height.
"currentblock": "00000000000008a84884ba827bdc868a17ba9c14011de33ff763bd95779a9cf1", // hash
"target": [0,0,0,0,0,0,11,48,125,79,116,89,136,74,42,27,5,14,10,31,23,53,226,238,202,219,5,204,38,32,59,165], // hash
"difficulty": "1234" // arbitrary-precision integer
"blockfrequency": 600, // seconds per block
"blocksizelimit": 2000000, // bytes
"extremefuturethreshold": 10800, // seconds
"futurethreshold": 10800, // seconds
"genesistimestamp": 1257894000, // Unix time
"maturitydelay": 144, // blocks
"mediantimestampwindow": 11, // blocks
"siafundcount": "10000", // siafund
"siafundportion": "39/1000", // fraction
"initialcoinbase": 300000, // Siacoins (see note in Daemon.md)
"minimumcoinbase": 30000, // Siacoins (see note in Daemon.md)
"roottarget": [0,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], // hash
"rootdepth": [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255], // hash
"siacoinprecision": "1000000000000000000000000" // hastings per siacoin
}
```
**synced** | boolean
......@@ -141,6 +160,48 @@ An immediate child block of this block must have a hash less than this target fo
**difficulty** | arbitrary-precision integer
The difficulty of the current block target.
**blockfrequency** | blocks / second
Target for how frequently new blocks should be mined.
**blocksizelimit** | bytes
Maximum size, in bytes, of a block. Blocks larger than this will be rejected by peers.
**extremefuturethreshold** | seconds
Farthest a block's timestamp can be in the future before the block is rejected outright.
**futurethreshold** | seconds
How far in the future a block can be without being rejected. A block further into the future will not be accepted immediately, but the daemon will attempt to accept the block as soon as it is valid.
**genesistimestamp** | unix timestamp
Timestamp of the genesis block.
**maturitydelay** | number of blocks
Number of children a block must have before it is considered "mature."
**mediantimestampwindow** | number of blocks
Duration of the window used to adjust the difficulty.
**siafundcount** | siafunds
Total number of siafunds.
**siafundportion** | fraction
Fraction of each file contract payout given to siafund holders.
**initialcoinbase** | siacoin
Number of coins given to the miner of the first block. Note that elsewhere in the API currency is typically returned in hastings and as a bignum. This is not the case here.
**minimumcoinbase** | siacoin
Minimum number of coins paid out to the miner of a block (the coinbase decreases with each block). Note that elsewhere in the API currency is typically returned in hastings and as a bignum. This is not the case here.
**roottarget** | hash
Initial target.
**rootdepth** | hash
Initial depth.
**siacoinprecision** | hastings per siacoin
Number of Hastings in one Siacoin.
## /consensus/blocks [GET]
Returns the block for a given id or height.
......@@ -251,90 +312,7 @@ standard success or error response. See [standard responses](#standard-responses
# Daemon
The daemon is responsible for starting and stopping the modules which make up the rest of Sia. It also provides endpoints for viewing build constants.
## /daemon/constants [GET]
Returns the set of constants in use.
### JSON Response
> JSON Response Example
```go
{
"blockfrequency": 600, // seconds per block
"blocksizelimit": 2000000, // bytes
"extremefuturethreshold": 10800, // seconds
"futurethreshold": 10800, // seconds
"genesistimestamp": 1257894000, // Unix time
"maturitydelay": 144, // blocks
"mediantimestampwindow": 11, // blocks
"siafundcount": "10000", // siafund
"siafundportion": "39/1000", // fraction
"targetwindow": 1000, // blocks
"initialcoinbase": 300000, // Siacoins (see note in Daemon.md)
"minimumcoinbase": 30000, // Siacoins (see note in Daemon.md)
"roottarget": [0,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], // hash
"rootdepth": [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255], // hash
"maxtargetadjustmentup": "5/2", // fraction
"maxtargetadjustmentdown": "2/5", // fraction
"siacoinprecision": "1000000000000000000000000" // hastings per siacoin
}
```
**blockfrequency** | blocks / second
Target for how frequently new blocks should be mined.
**blocksizelimit** | bytes
Maximum size, in bytes, of a block. Blocks larger than this will be rejected by peers.
**extremefuturethreshold** | seconds
Farthest a block's timestamp can be in the future before the block is rejected outright.
**futurethreshold** | seconds
How far in the future a block can be without being rejected. A block further into the future will not be accepted immediately, but the daemon will attempt to accept the block as soon as it is valid.
**genesistimestamp** | unix timestamp
Timestamp of the genesis block.
**maturitydelay** | number of blocks
Number of children a block must have before it is considered "mature."
**mediantimestampwindow** | number of blocks
Duration of the window used to adjust the difficulty.
**siafundcount** | siafunds
Total number of siafunds.
**siafundportion** | fraction
Fraction of each file contract payout given to siafund holders.
**targetwindow** | number of blocks
Height of the window used to adjust the difficulty.
**initialcoinbase** | siacoin
Number of coins given to the miner of the first block. Note that elsewhere in the API currency is typically returned in hastings and as a bignum. This is not the case here.
**minimumcoinbase** | siacoin
Minimum number of coins paid out to the miner of a block (the coinbase decreases with each block). Note that elsewhere in the API currency is typically returned in hastings and as a bignum. This is not the case here.
**roottarget** | hash
Initial target.
**rootdepth** | hash
Initial depth.
**maxtargetadjustmentup** | fraction
Largest allowed ratio between the old difficulty and the new difficulty.
**maxtargetadjustmentdown** | fraction
Smallest allowed ratio between the old difficulty and the new difficulty.
**siacoinprecision** | hastings per siacoin
Number of Hastings in one Siacoin.
The daemon is responsible for starting and stopping the modules which make up the rest of Sia.
## /daemon/stop [GET]
......@@ -2763,4 +2741,4 @@ The addresses currently watched by the wallet.
### Response
standard success or error response. See [standard responses](#standard-responses).
\ No newline at end of file
standard success or error response. See [standard responses](#standard-responses).
......@@ -3,6 +3,7 @@ package api
import (
"encoding/json"
"fmt"
"math/big"
"net/http"
"gitlab.com/NebulousLabs/Sia/crypto"
......@@ -14,11 +15,31 @@ import (
// ConsensusGET contains general information about the consensus set, with tags
// to support idiomatic json encodings.
type ConsensusGET struct {
// Consensus status values.
Synced bool `json:"synced"`
Height types.BlockHeight `json:"height"`
CurrentBlock types.BlockID `json:"currentblock"`
Target types.Target `json:"target"`
Difficulty types.Currency `json:"difficulty"`
// Consensus code constants.
BlockFrequency types.BlockHeight `json:"blockfrequency"`
BlockSizeLimit uint64 `json:"blocksizelimit"`
ExtremeFutureThreshold types.Timestamp `json:"extremefuturethreshold"`
FutureThreshold types.Timestamp `json:"futurethreshold"`
GenesisTimestamp types.Timestamp `json:"genesistimestamp"`
MaturityDelay types.BlockHeight `json:"maturitydelay"`
MedianTimestampWindow uint64 `json:"mediantimestampwindow"`
SiafundCount types.Currency `json:"siafundcount"`
SiafundPortion *big.Rat `json:"siafundportion"`
InitialCoinbase uint64 `json:"initialcoinbase"`
MinimumCoinbase uint64 `json:"minimumcoinbase"`
RootTarget types.Target `json:"roottarget"`
RootDepth types.Target `json:"rootdepth"`
SiacoinPrecision types.Currency `json:"siacoinprecision"`
}
// ConsensusHeadersGET contains information from a blocks header.
......@@ -178,6 +199,24 @@ func (api *API) consensusHandler(w http.ResponseWriter, req *http.Request, _ htt
CurrentBlock: cbid,
Target: currentTarget,
Difficulty: currentTarget.Difficulty(),
BlockFrequency: types.BlockFrequency,
BlockSizeLimit: types.BlockSizeLimit,
ExtremeFutureThreshold: types.ExtremeFutureThreshold,
FutureThreshold: types.FutureThreshold,
GenesisTimestamp: types.GenesisTimestamp,
MaturityDelay: types.MaturityDelay,
MedianTimestampWindow: types.MedianTimestampWindow,
SiafundCount: types.SiafundCount,
SiafundPortion: types.SiafundPortion,
InitialCoinbase: types.InitialCoinbase,
MinimumCoinbase: types.MinimumCoinbase,
RootTarget: types.RootTarget,
RootDepth: types.RootDepth,
SiacoinPrecision: types.SiacoinPrecision,
})
}
......
......@@ -34,6 +34,16 @@ func TestIntegrationConsensusGET(t *testing.T) {
if cg.Target != expectedTarget {
t.Error("wrong target returned in consensus GET call")
}
if cg.BlockFrequency != types.BlockFrequency {
t.Error("constant mismatch")
}
if cg.SiafundCount.Cmp(types.SiafundCount) != 0 {
t.Error("constant mismatch")
}
if cg.InitialCoinbase != types.InitialCoinbase {
t.Error("constant mismatch")
}
}
// TestConsensusValidateTransactionSet probes the POST call to
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment