diff --git a/build/params.go b/build/params.go index cd2fc738c..2fb892379 100644 --- a/build/params.go +++ b/build/params.go @@ -90,14 +90,14 @@ const InteractivePoRepDelay = 10 // ///// // Devnet settings -const TotalFilecoin = 2000000000 -const MiningRewardTotal = 1400000000 +const TotalFilecoin = 2_000_000_000 +const MiningRewardTotal = 1_400_000_000 const InitialRewardStr = "153856861913558700202" var InitialReward *big.Int -const FilecoinPrecision = 1000000000000000000 +const FilecoinPrecision = 1_000_000_000_000_000_000 // six years // Blocks diff --git a/chain/sync.go b/chain/sync.go index edaabc2a0..80df33d27 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -2,6 +2,7 @@ package chain import ( "context" + "errors" "fmt" "sync" "time" @@ -368,6 +369,10 @@ func (syncer *Syncer) Sync(ctx context.Context, maybeHead *types.TipSet) error { return nil } +func isPermanent(err error) bool { + return !errors.Is(err, ErrTemporal) +} + func (syncer *Syncer) ValidateTipSet(ctx context.Context, fts *store.FullTipSet) error { ctx, span := trace.StartSpan(ctx, "validateTipSet") defer span.End() @@ -379,7 +384,9 @@ func (syncer *Syncer) ValidateTipSet(ctx context.Context, fts *store.FullTipSet) for _, b := range fts.Blocks { if err := syncer.ValidateBlock(ctx, b); err != nil { - syncer.bad.Add(b.Cid()) + if isPermanent(err) { + syncer.bad.Add(b.Cid()) + } return xerrors.Errorf("validating block %s: %w", b.Cid(), err) } @@ -444,6 +451,8 @@ func (syncer *Syncer) validateTickets(ctx context.Context, mworker address.Addre return nil } +var ErrTemporal = errors.New("temporal error") + // Should match up with 'Semantical Validation' in validation.md in the spec func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) error { ctx, span := trace.StartSpan(ctx, "validateBlock") @@ -481,7 +490,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err } if h.Timestamp > uint64(time.Now().Unix()+build.AllowableClockDrift) { - return xerrors.Errorf("block was from the future") + return xerrors.Errorf("block was from the future: %w", ErrTemporal) } if h.Timestamp < baseTs.MinTimestamp()+uint64(build.BlockDelay*len(h.Tickets)) { diff --git a/chain/types/bigint_test.go b/chain/types/bigint_test.go index 7e2cd71f4..5209e7051 100644 --- a/chain/types/bigint_test.go +++ b/chain/types/bigint_test.go @@ -32,3 +32,20 @@ func TestBigIntSerializationRoundTrip(t *testing.T) { } } + +func TestFilRoundTrip(t *testing.T) { + testValues := []string{ + "0", "1", "1.001", "100.10001", "101100", "5000.01", "5000", + } + + for _, v := range testValues { + fval, err := ParseFIL(v) + if err != nil { + t.Fatal(err) + } + + if fval.String() != v { + t.Fatal("mismatch in values!", v, fval.String()) + } + } +} diff --git a/chain/types/fil.go b/chain/types/fil.go index f44336fb5..80de6ced3 100644 --- a/chain/types/fil.go +++ b/chain/types/fil.go @@ -12,7 +12,10 @@ type FIL BigInt func (f FIL) String() string { r := new(big.Rat).SetFrac(f.Int, big.NewInt(build.FilecoinPrecision)) - return strings.TrimRight(r.FloatString(18), "0.") + if r.Sign() == 0 { + return "0" + } + return strings.TrimRight(strings.TrimRight(r.FloatString(18), "0"), ".") } func (f FIL) Format(s fmt.State, ch rune) { diff --git a/cli/client.go b/cli/client.go index 283de413e..f3602624c 100644 --- a/cli/client.go +++ b/cli/client.go @@ -312,7 +312,7 @@ var clientQueryAskCmd = &cli.Command{ } fmt.Printf("Ask: %s\n", maddr) - fmt.Printf("Price per Byte: %s\n", types.FIL(ask.Ask.Price)) + fmt.Printf("Price per GigaByte: %s\n", types.FIL(ask.Ask.Price)) size := cctx.Int64("size") if size == 0 { diff --git a/cli/params.go b/cli/params.go index 6f6017ca3..9e8183b8a 100644 --- a/cli/params.go +++ b/cli/params.go @@ -9,8 +9,14 @@ import ( var fetchParamCmd = &cli.Command{ Name: "fetch-params", Usage: "Fetch proving parameters", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "only-verify-keys", + Usage: "only download the verify keys", + }, + }, Action: func(cctx *cli.Context) error { - if err := build.GetParams(true); err != nil { + if err := build.GetParams(!cctx.Bool("only-verify-keys")); err != nil { return xerrors.Errorf("fetching proof parameters: %w", err) } diff --git a/cmd/lotus-fountain/main.go b/cmd/lotus-fountain/main.go index 6d590bb0c..bd8127683 100644 --- a/cmd/lotus-fountain/main.go +++ b/cmd/lotus-fountain/main.go @@ -3,6 +3,7 @@ package main import ( "context" "fmt" + "net" "net/http" "os" "strconv" @@ -24,7 +25,7 @@ import ( var log = logging.Logger("main") -var sendPerRequest = types.NewInt(500_000_000) +var sendPerRequest, _ = types.ParseFIL("0.005") func main() { logging.SetLogLevel("*", "INFO") @@ -104,7 +105,7 @@ var runCmd = &cli.Command{ TotalRate: time.Second, TotalBurst: 20, IPRate: 10 * time.Minute, - IPBurst: 1, + IPBurst: 2, WalletRate: 1 * time.Hour, WalletBurst: 1, }), @@ -151,7 +152,20 @@ func (h *handler) send(w http.ResponseWriter, r *http.Request) { } // Limit based on IP - limiter = h.limiter.GetIPLimiter(r.RemoteAddr) + + reqIP := r.Header.Get("X-Real-IP") + if reqIP == "" { + h, _, err := net.SplitHostPort(r.RemoteAddr) + if err != nil { + log.Errorf("could not get ip from: %s, err: %s", r.RemoteAddr, err) + } + reqIP = h + } + if i := net.ParseIP(reqIP); i != nil && i.IsLoopback() { + log.Errorf("rate limiting localhost: %s", reqIP) + } + + limiter = h.limiter.GetIPLimiter(reqIP) if !limiter.Allow() { http.Error(w, http.StatusText(http.StatusTooManyRequests), http.StatusTooManyRequests) return @@ -164,7 +178,7 @@ func (h *handler) send(w http.ResponseWriter, r *http.Request) { } smsg, err := h.api.MpoolPushMessage(h.ctx, &types.Message{ - Value: sendPerRequest, + Value: types.BigInt(sendPerRequest), From: h.from, To: to, @@ -229,7 +243,7 @@ func (h *handler) mkminer(w http.ResponseWriter, r *http.Request) { } smsg, err := h.api.MpoolPushMessage(h.ctx, &types.Message{ - Value: sendPerRequest, + Value: types.BigInt(sendPerRequest), From: h.from, To: owner, diff --git a/cmd/lotus-storage-miner/info.go b/cmd/lotus-storage-miner/info.go index 00864ed58..54184a63c 100644 --- a/cmd/lotus-storage-miner/info.go +++ b/cmd/lotus-storage-miner/info.go @@ -36,6 +36,14 @@ var infoCmd = &cli.Command{ fmt.Printf("Miner: %s\n", maddr) + // Sector size + sizeByte, err := api.StateMinerSectorSize(ctx, maddr, nil) + if err != nil { + return err + } + + fmt.Printf("Sector Size: %s\n", sizeStr(sizeByte)) + pow, err := api.StateMinerPower(ctx, maddr, nil) if err != nil { return err @@ -59,13 +67,24 @@ var infoCmd = &cli.Command{ fmt.Println(sinfo) // TODO: grab actr state / info - // * Sector size // * Sealed sectors (count / bytes) // * Power return nil }, } +var Units = []string{"B", "KiB", "MiB", "GiB", "TiB"} + +func sizeStr(size uint64) string { + i := 0 + unitSize := float64(size) + for unitSize >= 1024 && i < len(Units) - 1 { + unitSize = unitSize / 1024 + i++ + } + return fmt.Sprintf("%g %s", unitSize, Units[i]) +} + func sectorsInfo(ctx context.Context, napi api.StorageMiner) (map[string]int, error) { sectors, err := napi.SectorsList(ctx) if err != nil {