Merge remote-tracking branch 'origin/master' into feat/chainwatch-pg

This commit is contained in:
Łukasz Magiera 2020-01-08 15:08:34 +01:00
commit ab922ed1ba
240 changed files with 3241 additions and 4515 deletions

View File

@ -37,14 +37,13 @@ commands:
- restore_cache:
name: Restore parameters cache
keys:
- 'v20-1k-lotus-params-{{ checksum "build/proof-params/parameters.json" }}-{{ checksum "build/paramfetch.go" }}'
- 'v20-1k-lotus-params-{{ checksum "build/proof-params/parameters.json" }}-'
- 'v20-1k-lotus-params'
paths:
- /var/tmp/filecoin-proof-parameters/
- run: ./lotus fetch-params --proving-params 1024
- save_cache:
name: Save parameters cache
key: 'v20-1k-lotus-params-{{ checksum "build/proof-params/parameters.json" }}-{{ checksum "build/paramfetch.go" }}'
key: 'v20-1k-lotus-params'
paths:
- /var/tmp/filecoin-proof-parameters/
@ -157,7 +156,7 @@ jobs:
test-short:
<<: *test
build_macos:
build-macos:
description: build darwin lotus binary
macos:
xcode: "10.0.0"
@ -187,23 +186,20 @@ jobs:
chmod +x $HOME/.bin/jq
- restore_cache:
name: restore go mod and cargo cache
key: v1-go-deps-{{ arch }}-{{ checksum "~/go/src/github.com/filecoin-project/lotus/go.mod" }}
key: v3-go-deps-{{ arch }}-{{ checksum "~/go/src/github.com/filecoin-project/lotus/go.sum" }}
- install-deps
- go/mod-download
- run:
command: make build
command: make buildall
no_output_timeout: 30m
- store_artifacts:
path: lotus
- store_artifacts:
path: lotus-storage-miner
- save_cache:
name: save go mod and cargo cache
key: v1-go-deps-{{ arch }}-{{ checksum "~/go/src/github.com/filecoin-project/lotus/go.mod" }}
name: save cargo cache
key: v3-go-deps-{{ arch }}-{{ checksum "~/go/src/github.com/filecoin-project/lotus/go.sum" }}
paths:
- "~/go/pkg"
- "~/go/src/github.com"
- "~/go/src/golang.org"
- "~/.rustup"
- "~/.cargo"
@ -262,7 +258,4 @@ workflows:
go-test-flags: "--timeout 10m --short"
- mod-tidy-check
- build-all
- build_macos:
filters:
branches:
only: master
- build-macos

27
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,27 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Run '...'
2. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Version (run `lotus --version`):**
**Additional context**
Add any other context about the problem here.

1
.gitignore vendored
View File

@ -12,6 +12,7 @@
/lotuspond/front/build
/cmd/lotus-townhall/townhall/node_modules
/cmd/lotus-townhall/townhall/build
extern/filecoin-ffi/rust/target
**/*.h
**/*.a
**/*.pc

View File

@ -4,10 +4,9 @@ import (
"context"
"fmt"
"github.com/filecoin-project/lotus/build"
"github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/filecoin-project/lotus/build"
)
type Permission = string
@ -40,7 +39,7 @@ type Version struct {
// this api
//
// See APIVersion in build/version.go
APIVersion uint32
APIVersion build.Version
// TODO: git commit / os / genesis cid?
@ -49,6 +48,5 @@ type Version struct {
}
func (v Version) String() string {
vM, vm, vp := build.VersionInts(v.APIVersion)
return fmt.Sprintf("%s+api%d.%d.%d", v.Version, vM, vm, vp)
return fmt.Sprintf("%s+api%s", v.Version, v.APIVersion.String())
}

View File

@ -8,8 +8,8 @@ import (
"github.com/ipfs/go-filestore"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
)
@ -35,15 +35,18 @@ type FullNode interface {
ChainSetHead(context.Context, *types.TipSet) error
ChainGetGenesis(context.Context) (*types.TipSet, error)
ChainTipSetWeight(context.Context, *types.TipSet) (types.BigInt, error)
ChainGetNode(ctx context.Context, p string) (interface{}, error)
ChainGetMessage(context.Context, cid.Cid) (*types.Message, error)
// syncer
SyncState(context.Context) (*SyncState, error)
SyncSubmitBlock(ctx context.Context, blk *types.BlockMsg) error
SyncIncomingBlocks(ctx context.Context) (<-chan *types.BlockHeader, error)
SyncMarkBad(ctx context.Context, bcid cid.Cid) error
// messages
MpoolPending(context.Context, *types.TipSet) ([]*types.SignedMessage, error)
MpoolPush(context.Context, *types.SignedMessage) error // TODO: remove
MpoolPush(context.Context, *types.SignedMessage) (cid.Cid, error)
MpoolPushMessage(context.Context, *types.Message) (*types.SignedMessage, error) // get nonce, sign, push
MpoolGetNonce(context.Context, address.Address) (uint64, error)
MpoolSub(context.Context) (<-chan MpoolUpdate, error)
@ -73,7 +76,7 @@ type FullNode interface {
// ClientImport imports file under the specified path into filestore
ClientImport(ctx context.Context, path string) (cid.Cid, error)
ClientStartDeal(ctx context.Context, data cid.Cid, miner address.Address, epochPrice types.BigInt, blocksDuration uint64) (*cid.Cid, error)
ClientStartDeal(ctx context.Context, data cid.Cid, addr address.Address, miner address.Address, epochPrice types.BigInt, blocksDuration uint64) (*cid.Cid, error)
ClientGetDealInfo(context.Context, cid.Cid) (*DealInfo, error)
ClientListDeals(ctx context.Context) ([]DealInfo, error)
ClientHasLocal(ctx context.Context, root cid.Cid) (bool, error)
@ -94,6 +97,7 @@ type FullNode interface {
StateReplay(context.Context, *types.TipSet, cid.Cid) (*ReplayResults, error)
StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error)
StateReadState(ctx context.Context, act *types.Actor, ts *types.TipSet) (*ActorState, error)
StateListMessages(ctx context.Context, match *types.Message, ts *types.TipSet, toht uint64) ([]cid.Cid, error)
StateMinerSectors(context.Context, address.Address, *types.TipSet) ([]*ChainSectorInfo, error)
StateMinerProvingSet(context.Context, address.Address, *types.TipSet) ([]*ChainSectorInfo, error)

View File

@ -3,8 +3,8 @@ package api
import (
"context"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/lib/sectorbuilder"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-sectorbuilder"
)
// alias because cbor-gen doesn't like non-alias types

View File

@ -3,15 +3,15 @@ package apistruct
import (
"context"
"github.com/filecoin-project/lotus/lib/sectorbuilder"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
)
@ -53,13 +53,16 @@ type FullNodeStruct struct {
ChainSetHead func(context.Context, *types.TipSet) error `perm:"admin"`
ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"`
ChainTipSetWeight func(context.Context, *types.TipSet) (types.BigInt, error) `perm:"read"`
ChainGetNode func(ctx context.Context, p string) (interface{}, error) `perm:"read"`
ChainGetMessage func(context.Context, cid.Cid) (*types.Message, error) `perm:"read"`
SyncState func(context.Context) (*api.SyncState, error) `perm:"read"`
SyncSubmitBlock func(ctx context.Context, blk *types.BlockMsg) error `perm:"write"`
SyncIncomingBlocks func(ctx context.Context) (<-chan *types.BlockHeader, error) `perm:"read"`
SyncMarkBad func(ctx context.Context, bcid cid.Cid) error `perm:"admin"`
MpoolPending func(context.Context, *types.TipSet) ([]*types.SignedMessage, error) `perm:"read"`
MpoolPush func(context.Context, *types.SignedMessage) error `perm:"write"`
MpoolPush func(context.Context, *types.SignedMessage) (cid.Cid, error) `perm:"write"`
MpoolPushMessage func(context.Context, *types.Message) (*types.SignedMessage, error) `perm:"sign"`
MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"`
MpoolSub func(context.Context) (<-chan api.MpoolUpdate, error) `perm:"read"`
@ -77,39 +80,40 @@ type FullNodeStruct struct {
WalletExport func(context.Context, address.Address) (*types.KeyInfo, error) `perm:"admin"`
WalletImport func(context.Context, *types.KeyInfo) (address.Address, error) `perm:"admin"`
ClientImport func(ctx context.Context, path string) (cid.Cid, error) `perm:"admin"`
ClientListImports func(ctx context.Context) ([]api.Import, error) `perm:"write"`
ClientHasLocal func(ctx context.Context, root cid.Cid) (bool, error) `perm:"write"`
ClientFindData func(ctx context.Context, root cid.Cid) ([]api.QueryOffer, error) `perm:"read"`
ClientStartDeal func(ctx context.Context, data cid.Cid, miner address.Address, price types.BigInt, blocksDuration uint64) (*cid.Cid, error) `perm:"admin"`
ClientGetDealInfo func(context.Context, cid.Cid) (*api.DealInfo, error) `perm:"read"`
ClientListDeals func(ctx context.Context) ([]api.DealInfo, error) `perm:"write"`
ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, path string) error `perm:"admin"`
ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*types.SignedStorageAsk, error) `perm:"read"`
ClientImport func(ctx context.Context, path string) (cid.Cid, error) `perm:"admin"`
ClientListImports func(ctx context.Context) ([]api.Import, error) `perm:"write"`
ClientHasLocal func(ctx context.Context, root cid.Cid) (bool, error) `perm:"write"`
ClientFindData func(ctx context.Context, root cid.Cid) ([]api.QueryOffer, error) `perm:"read"`
ClientStartDeal func(ctx context.Context, data cid.Cid, addr address.Address, miner address.Address, price types.BigInt, blocksDuration uint64) (*cid.Cid, error) `perm:"admin"`
ClientGetDealInfo func(context.Context, cid.Cid) (*api.DealInfo, error) `perm:"read"`
ClientListDeals func(ctx context.Context) ([]api.DealInfo, error) `perm:"write"`
ClientRetrieve func(ctx context.Context, order api.RetrievalOrder, path string) error `perm:"admin"`
ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*types.SignedStorageAsk, error) `perm:"read"`
StateMinerSectors func(context.Context, address.Address, *types.TipSet) ([]*api.ChainSectorInfo, error) `perm:"read"`
StateMinerProvingSet func(context.Context, address.Address, *types.TipSet) ([]*api.ChainSectorInfo, error) `perm:"read"`
StateMinerPower func(context.Context, address.Address, *types.TipSet) (api.MinerPower, error) `perm:"read"`
StateMinerWorker func(context.Context, address.Address, *types.TipSet) (address.Address, error) `perm:"read"`
StateMinerPeerID func(ctx context.Context, m address.Address, ts *types.TipSet) (peer.ID, error) `perm:"read"`
StateMinerElectionPeriodStart func(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) `perm:"read"`
StateMinerSectorSize func(context.Context, address.Address, *types.TipSet) (uint64, error) `perm:"read"`
StateCall func(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"`
StateReplay func(context.Context, *types.TipSet, cid.Cid) (*api.ReplayResults, error) `perm:"read"`
StateGetActor func(context.Context, address.Address, *types.TipSet) (*types.Actor, error) `perm:"read"`
StateReadState func(context.Context, *types.Actor, *types.TipSet) (*api.ActorState, error) `perm:"read"`
StatePledgeCollateral func(context.Context, *types.TipSet) (types.BigInt, error) `perm:"read"`
StateWaitMsg func(context.Context, cid.Cid) (*api.MsgWait, error) `perm:"read"`
StateListMiners func(context.Context, *types.TipSet) ([]address.Address, error) `perm:"read"`
StateListActors func(context.Context, *types.TipSet) ([]address.Address, error) `perm:"read"`
StateMarketBalance func(context.Context, address.Address, *types.TipSet) (actors.StorageParticipantBalance, error) `perm:"read"`
StateMarketParticipants func(context.Context, *types.TipSet) (map[string]actors.StorageParticipantBalance, error) `perm:"read"`
StateMarketDeals func(context.Context, *types.TipSet) (map[string]actors.OnChainDeal, error) `perm:"read"`
StateMarketStorageDeal func(context.Context, uint64, *types.TipSet) (*actors.OnChainDeal, error) `perm:"read"`
StateLookupID func(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) `perm:"read"`
StateChangedActors func(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error) `perm:"read"`
StateGetReceipt func(context.Context, cid.Cid, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"`
StateMinerSectorCount func(context.Context, address.Address, *types.TipSet) (api.MinerSectors, error) `perm:"read"`
StateMinerSectors func(context.Context, address.Address, *types.TipSet) ([]*api.ChainSectorInfo, error) `perm:"read"`
StateMinerProvingSet func(context.Context, address.Address, *types.TipSet) ([]*api.ChainSectorInfo, error) `perm:"read"`
StateMinerPower func(context.Context, address.Address, *types.TipSet) (api.MinerPower, error) `perm:"read"`
StateMinerWorker func(context.Context, address.Address, *types.TipSet) (address.Address, error) `perm:"read"`
StateMinerPeerID func(ctx context.Context, m address.Address, ts *types.TipSet) (peer.ID, error) `perm:"read"`
StateMinerElectionPeriodStart func(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) `perm:"read"`
StateMinerSectorSize func(context.Context, address.Address, *types.TipSet) (uint64, error) `perm:"read"`
StateCall func(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"`
StateReplay func(context.Context, *types.TipSet, cid.Cid) (*api.ReplayResults, error) `perm:"read"`
StateGetActor func(context.Context, address.Address, *types.TipSet) (*types.Actor, error) `perm:"read"`
StateReadState func(context.Context, *types.Actor, *types.TipSet) (*api.ActorState, error) `perm:"read"`
StatePledgeCollateral func(context.Context, *types.TipSet) (types.BigInt, error) `perm:"read"`
StateWaitMsg func(context.Context, cid.Cid) (*api.MsgWait, error) `perm:"read"`
StateListMiners func(context.Context, *types.TipSet) ([]address.Address, error) `perm:"read"`
StateListActors func(context.Context, *types.TipSet) ([]address.Address, error) `perm:"read"`
StateMarketBalance func(context.Context, address.Address, *types.TipSet) (actors.StorageParticipantBalance, error) `perm:"read"`
StateMarketParticipants func(context.Context, *types.TipSet) (map[string]actors.StorageParticipantBalance, error) `perm:"read"`
StateMarketDeals func(context.Context, *types.TipSet) (map[string]actors.OnChainDeal, error) `perm:"read"`
StateMarketStorageDeal func(context.Context, uint64, *types.TipSet) (*actors.OnChainDeal, error) `perm:"read"`
StateLookupID func(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) `perm:"read"`
StateChangedActors func(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error) `perm:"read"`
StateGetReceipt func(context.Context, cid.Cid, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"`
StateMinerSectorCount func(context.Context, address.Address, *types.TipSet) (api.MinerSectors, error) `perm:"read"`
StateListMessages func(ctx context.Context, match *types.Message, ts *types.TipSet, toht uint64) ([]cid.Cid, error) `perm:"read"`
MarketEnsureAvailable func(context.Context, address.Address, types.BigInt) error `perm:"sign"`
@ -208,8 +212,8 @@ func (c *FullNodeStruct) ClientFindData(ctx context.Context, root cid.Cid) ([]ap
return c.Internal.ClientFindData(ctx, root)
}
func (c *FullNodeStruct) ClientStartDeal(ctx context.Context, data cid.Cid, miner address.Address, price types.BigInt, blocksDuration uint64) (*cid.Cid, error) {
return c.Internal.ClientStartDeal(ctx, data, miner, price, blocksDuration)
func (c *FullNodeStruct) ClientStartDeal(ctx context.Context, data cid.Cid, addr address.Address, miner address.Address, price types.BigInt, blocksDuration uint64) (*cid.Cid, error) {
return c.Internal.ClientStartDeal(ctx, data, addr, miner, price, blocksDuration)
}
func (c *FullNodeStruct) ClientGetDealInfo(ctx context.Context, deal cid.Cid) (*api.DealInfo, error) {
return c.Internal.ClientGetDealInfo(ctx, deal)
@ -231,7 +235,7 @@ func (c *FullNodeStruct) MpoolPending(ctx context.Context, ts *types.TipSet) ([]
return c.Internal.MpoolPending(ctx, ts)
}
func (c *FullNodeStruct) MpoolPush(ctx context.Context, smsg *types.SignedMessage) error {
func (c *FullNodeStruct) MpoolPush(ctx context.Context, smsg *types.SignedMessage) (cid.Cid, error) {
return c.Internal.MpoolPush(ctx, smsg)
}
@ -343,6 +347,14 @@ func (c *FullNodeStruct) ChainTipSetWeight(ctx context.Context, ts *types.TipSet
return c.Internal.ChainTipSetWeight(ctx, ts)
}
func (c *FullNodeStruct) ChainGetNode(ctx context.Context, p string) (interface{}, error) {
return c.Internal.ChainGetNode(ctx, p)
}
func (c *FullNodeStruct) ChainGetMessage(ctx context.Context, mc cid.Cid) (*types.Message, error) {
return c.Internal.ChainGetMessage(ctx, mc)
}
func (c *FullNodeStruct) SyncState(ctx context.Context) (*api.SyncState, error) {
return c.Internal.SyncState(ctx)
}
@ -355,6 +367,10 @@ func (c *FullNodeStruct) SyncIncomingBlocks(ctx context.Context) (<-chan *types.
return c.Internal.SyncIncomingBlocks(ctx)
}
func (c *FullNodeStruct) SyncMarkBad(ctx context.Context, bcid cid.Cid) error {
return c.Internal.SyncMarkBad(ctx, bcid)
}
func (c *FullNodeStruct) StateMinerSectors(ctx context.Context, addr address.Address, ts *types.TipSet) ([]*api.ChainSectorInfo, error) {
return c.Internal.StateMinerSectors(ctx, addr, ts)
}
@ -442,6 +458,10 @@ func (c *FullNodeStruct) StateGetReceipt(ctx context.Context, msg cid.Cid, ts *t
return c.Internal.StateGetReceipt(ctx, msg, ts)
}
func (c *FullNodeStruct) StateListMessages(ctx context.Context, match *types.Message, ts *types.TipSet, toht uint64) ([]cid.Cid, error) {
return c.Internal.StateListMessages(ctx, match, ts, toht)
}
func (c *FullNodeStruct) MarketEnsureAvailable(ctx context.Context, addr address.Address, amt types.BigInt) error {
return c.Internal.MarketEnsureAvailable(ctx, addr, amt)
}

View File

@ -71,7 +71,11 @@ func TestDealFlow(t *testing.T, b APIBuilder) {
}
}
}()
deal, err := client.ClientStartDeal(ctx, fcid, maddr, types.NewInt(40000000), 100)
addr, err := client.WalletDefaultAddress(ctx)
if err != nil {
t.Fatal(err)
}
deal, err := client.ClientStartDeal(ctx, fcid, addr, maddr, types.NewInt(40000000), 100)
if err != nil {
t.Fatal(err)
}

View File

@ -50,7 +50,7 @@ func (ts *testSuite) testVersion(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if v.Version != build.Version {
if v.Version != build.BuildVersion {
t.Error("Version didn't work properly")
}
}

View File

@ -3,7 +3,7 @@ package api
import (
"context"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types"
)

View File

@ -1,3 +1,4 @@
package build
const ForkCCM = 1750
const ForkNoPowerEPSUpdates = 16450

View File

@ -1,6 +1,12 @@
package build
import rice "github.com/GeertJohan/go.rice"
import (
rice "github.com/GeertJohan/go.rice"
logging "github.com/ipfs/go-log"
)
// moved from now-defunct build/paramfetch.go
var log = logging.Logger("build")
func MaybeGenesis() []byte {
builtinGen, err := rice.FindBox("genesis")

View File

@ -1,189 +0,0 @@
package build
import (
"encoding/hex"
"encoding/json"
"io"
"net/http"
"net/url"
"os"
"path/filepath"
"strconv"
"strings"
"sync"
rice "github.com/GeertJohan/go.rice"
logging "github.com/ipfs/go-log"
"github.com/minio/blake2b-simd"
"go.uber.org/multierr"
"golang.org/x/xerrors"
pb "gopkg.in/cheggaaa/pb.v1"
)
var log = logging.Logger("build")
//const gateway = "http://198.211.99.118/ipfs/"
const gateway = "https://ipfs.io/ipfs/"
const paramdir = "/var/tmp/filecoin-proof-parameters"
const dirEnv = "FIL_PROOFS_PARAMETER_CACHE"
type paramFile struct {
Cid string `json:"cid"`
Digest string `json:"digest"`
SectorSize uint64 `json:"sector_size"`
}
type fetch struct {
wg sync.WaitGroup
fetchLk sync.Mutex
errs []error
}
func getParamDir() string {
if os.Getenv(dirEnv) == "" {
return paramdir
}
return os.Getenv(dirEnv)
}
func GetParams(storageSize uint64) error {
if err := os.Mkdir(getParamDir(), 0755); err != nil && !os.IsExist(err) {
return err
}
var params map[string]paramFile
paramBytes := rice.MustFindBox("proof-params").MustBytes("parameters.json")
if err := json.Unmarshal(paramBytes, &params); err != nil {
return err
}
ft := &fetch{}
for name, info := range params {
if storageSize != info.SectorSize && strings.HasSuffix(name, ".params") {
continue
}
ft.maybeFetchAsync(name, info)
}
return ft.wait()
}
func (ft *fetch) maybeFetchAsync(name string, info paramFile) {
ft.wg.Add(1)
go func() {
defer ft.wg.Done()
path := filepath.Join(getParamDir(), name)
err := ft.checkFile(path, info)
if !os.IsNotExist(err) && err != nil {
log.Warn(err)
}
if err == nil {
return
}
ft.fetchLk.Lock()
defer ft.fetchLk.Unlock()
if err := doFetch(path, info); err != nil {
ft.errs = append(ft.errs, xerrors.Errorf("fetching file %s failed: %w", path, err))
return
}
err = ft.checkFile(path, info)
if err != nil {
ft.errs = append(ft.errs, xerrors.Errorf("checking file %s failed: %w", path, err))
err := os.Remove(path)
if err != nil {
ft.errs = append(ft.errs, xerrors.Errorf("remove file %s failed: %w", path, err))
}
}
}()
}
func (ft *fetch) checkFile(path string, info paramFile) error {
if os.Getenv("TRUST_PARAMS") == "1" {
log.Warn("Assuming parameter files are ok. DO NOT USE IN PRODUCTION")
return nil
}
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close()
h := blake2b.New512()
if _, err := io.Copy(h, f); err != nil {
return err
}
sum := h.Sum(nil)
strSum := hex.EncodeToString(sum[:16])
if strSum == info.Digest {
log.Infof("Parameter file %s is ok", path)
return nil
}
return xerrors.Errorf("checksum mismatch in param file %s, %s != %s", path, strSum, info.Digest)
}
func (ft *fetch) wait() error {
ft.wg.Wait()
return multierr.Combine(ft.errs...)
}
func doFetch(out string, info paramFile) error {
gw := os.Getenv("IPFS_GATEWAY")
if gw == "" {
gw = gateway
}
log.Infof("Fetching %s from %s", out, gw)
outf, err := os.OpenFile(out, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
return err
}
defer outf.Close()
fStat, err := outf.Stat()
if err != nil {
return err
}
header := http.Header{}
header.Set("Range", "bytes="+strconv.FormatInt(fStat.Size(), 10)+"-")
url, err := url.Parse(gw + info.Cid)
if err != nil {
return err
}
log.Infof("GET %s", url)
req := http.Request{
Method: "GET",
URL: url,
Header: header,
Close: true,
}
resp, err := http.DefaultClient.Do(&req)
if err != nil {
return err
}
defer resp.Body.Close()
bar := pb.New64(resp.ContentLength)
bar.Units = pb.U_BYTES
bar.ShowSpeed = true
bar.Start()
_, err = io.Copy(outf, bar.NewProxyReader(resp.Body))
bar.Finish()
return err
}

View File

@ -31,7 +31,7 @@ const PaymentChannelClosingDelay = 6 * 60 * 60 / BlockDelay // six hours
// Consensus / Network
// Seconds
const AllowableClockDrift = BlockDelay * 2
const AllowableClockDrift = 1
// Epochs
const ForkLengthThreshold = Finality
@ -56,11 +56,6 @@ const SealRandomnessLookback = Finality
// Epochs
const SealRandomnessLookbackLimit = SealRandomnessLookback + 2000
// 1 / n
const SectorChallengeRatioDiv = 25
const MaxFallbackPostChallengeCount = 10
// /////
// Mining

View File

@ -1,20 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
function b64() {
f="$1"
case `uname` in
Darwin)
base64 -i "$f"
;;
Linux)
base64 "$f" -w 0
;;
esac
printf "unsupported system" 1>&2
exit 1
}
sed "s/{{PARAMSJSON}}/$(b64 build/proof-params/parameters.json)/g" build/proof-params/paramfetch.sh.template > ./build/paramfetch.sh
chmod +x ./build/paramfetch.sh

View File

@ -1,103 +0,0 @@
{
"v20-proof-of-spacetime-election-5f585aca354eb68e411c8582ed0efd800792430e4e76d73468c4fc03f1a8d6d2.params": {
"cid": "QmX7tYeNPWae2fjZ3Am6GB9dmHvLqvoz8dKo3PR98VYxH9",
"digest": "39a9edec3355516674f0d12b926be493",
"sector_size": 34359738368
},
"v20-proof-of-spacetime-election-5f585aca354eb68e411c8582ed0efd800792430e4e76d73468c4fc03f1a8d6d2.vk": {
"cid": "QmbNGx7pNbGiEr8ykoHxVXHW2LNSmGdsxKtj1onZCyguCX",
"digest": "0227ae7df4f2affe529ebafbbc7540ee",
"sector_size": 34359738368
},
"v20-proof-of-spacetime-election-a4e18190d4b4657ba1b4d08a341871b2a6f398e327cb9951b28ab141fbdbf49d.params": {
"cid": "QmRGZsNp4mp1cZshcXqt3VMuWscAEsiMa2iepF4CsWWoiv",
"digest": "991041a354b12c280542741f58c7f2ca",
"sector_size": 1024
},
"v20-proof-of-spacetime-election-a4e18190d4b4657ba1b4d08a341871b2a6f398e327cb9951b28ab141fbdbf49d.vk": {
"cid": "QmWpmrhCGVcfqLyqp5oGAnhPmCE5hGTPaauHi25mpQwRSU",
"digest": "91fac550e1f9bccab213830bb0c85bd6",
"sector_size": 1024
},
"v20-proof-of-spacetime-election-a9eb6d90b896a282ec2d3a875c6143e3fcff778f0da1460709e051833651559b.params": {
"cid": "QmenSZXh1EsSyHiSRvA6wb8yaPhYBTjrKehJw96Px5HnN4",
"digest": "6322eacd2773163ddd51f9ca7d645fc4",
"sector_size": 1073741824
},
"v20-proof-of-spacetime-election-a9eb6d90b896a282ec2d3a875c6143e3fcff778f0da1460709e051833651559b.vk": {
"cid": "QmPvZoMKofw6eDhDg5ESJA2QAZP8HvM6qMQk7fw4pq9bQf",
"digest": "0df62745fceac922e3e70847cfc70b52",
"sector_size": 1073741824
},
"v20-proof-of-spacetime-election-bf872523641b1de33553db2a177df13e412d7b3b0103e6696ae0a1cf5d525259.params": {
"cid": "QmVibFqzkZoL8cwQmzj8njPokCQGCCx4pBcUH77bzgJgV9",
"digest": "de9d71e672f286706a1673bd57abdaac",
"sector_size": 16777216
},
"v20-proof-of-spacetime-election-bf872523641b1de33553db2a177df13e412d7b3b0103e6696ae0a1cf5d525259.vk": {
"cid": "QmZa5FX27XyiEXQQLQpHqtMJKLzrcY8wMuj3pxzmSimSyu",
"digest": "7f796d3a0f13499181e44b5eee0cc744",
"sector_size": 16777216
},
"v20-proof-of-spacetime-election-ffc3fb192364238b60977839d14e3154d4a98313e30d46694a12af54b6874975.params": {
"cid": "Qmbt2SWWAmMcYoY3DAiRDXA8fAuqdqRLWucJMSxYmzBCmN",
"digest": "151ae0ae183fc141e8c2bebc28e5cc10",
"sector_size": 268435456
},
"v20-proof-of-spacetime-election-ffc3fb192364238b60977839d14e3154d4a98313e30d46694a12af54b6874975.vk": {
"cid": "QmUxvPu4xdVmjMFihUKoYyEdXBqxsXkvmxRweU7KouWHji",
"digest": "95eb89588e9d1832aca044c3a13178af",
"sector_size": 268435456
},
"v20-stacked-proof-of-replication-117839dacd1ef31e5968a6fd13bcd6fa86638d85c40c9241a1d07c2a954eb89b.params": {
"cid": "QmQZe8eLo2xXbhSDxtyYZNqEjqjdcWGdADywECRvNEZQdX",
"digest": "fcd50e2e08a8560a6bb3418e883567ed",
"sector_size": 268435456
},
"v20-stacked-proof-of-replication-117839dacd1ef31e5968a6fd13bcd6fa86638d85c40c9241a1d07c2a954eb89b.vk": {
"cid": "Qme1hn6QT1covfoUFGDZkqoE1pMTax9FNW3nWWmTNqFe7y",
"digest": "872e244d86499fd659082e3bcf3f13e7",
"sector_size": 268435456
},
"v20-stacked-proof-of-replication-b46f3a1051afbb67f70aae7082da95def62eee943662f3e1bf69837fb08aaae4.params": {
"cid": "QmSfrPDC9jwY4MKrjzhCqDBBAG44wSDM8oE5NuDwWSh2xN",
"digest": "0a338b941c5f17946340de5fc95cab30",
"sector_size": 34359738368
},
"v20-stacked-proof-of-replication-b46f3a1051afbb67f70aae7082da95def62eee943662f3e1bf69837fb08aaae4.vk": {
"cid": "QmTDGynCmnbaZNBP3Bv3F3duC3ecKRubCKeMUiQQZYbGpF",
"digest": "c752e070a6b7aa8b79aa661a6b600b55",
"sector_size": 34359738368
},
"v20-stacked-proof-of-replication-e71093863cadc71de61f38311ee45816633973bbf34849316b147f8d2e66f199.params": {
"cid": "QmXjSSnMUnc7EjQBYtTHhvLU3kXJTbUyhVhJRSTRehh186",
"digest": "efa407fd09202dffd15799a8518e73d3",
"sector_size": 1024
},
"v20-stacked-proof-of-replication-e71093863cadc71de61f38311ee45816633973bbf34849316b147f8d2e66f199.vk": {
"cid": "QmYHW3zhQouDP4okFbXSsRMcZ8bokKGvzxqbv7ZrunPMiG",
"digest": "b2f09a0ccb62da28c890d5b881c8dcd2",
"sector_size": 1024
},
"v20-stacked-proof-of-replication-e99a585174b6a45b254ba4780d72c89ad808c305c6d11711009ade4f39dba8e9.params": {
"cid": "QmUhyfNeLb32LfSkjsUwTFYLXQGMj6JQ8daff4DdVMt79q",
"digest": "b53c1916a63839ec345aa2224e9198b7",
"sector_size": 1073741824
},
"v20-stacked-proof-of-replication-e99a585174b6a45b254ba4780d72c89ad808c305c6d11711009ade4f39dba8e9.vk": {
"cid": "QmWReGfbuoozNErbskmFvqV4q36BY6F2WWb4cVFc3zoYkA",
"digest": "20d58a3fae7343481f8298a2dd493dd7",
"sector_size": 1073741824
},
"v20-stacked-proof-of-replication-f571ee2386f4c65a68e802747f2d78691006fc81a67971c4d9641403fffece16.params": {
"cid": "QmSAHu14Pe8iav6BYCt9XkpHJ73XM7tcpY4d9JK9BST9HU",
"digest": "7698426202c7e07b26ef056d31485b3a",
"sector_size": 16777216
},
"v20-stacked-proof-of-replication-f571ee2386f4c65a68e802747f2d78691006fc81a67971c4d9641403fffece16.vk": {
"cid": "QmaKtFLShnhMGVn7P9UsHjkgqtqRFSwCStqqykBN7u8dax",
"digest": "834408e5c3fce6ec5d1bf64e64cee94e",
"sector_size": 16777216
}
}

View File

@ -1,95 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
PARAMS='{{PARAMSJSON}}'
die() {
echo "$@" >&2
exit 1
}
have_binary() {
type "$1" > /dev/null 2> /dev/null
}
check_writable() {
printf "" > "$1" && rm "$1"
}
try_download() {
url="$1"
output="$2"
command="$3"
util_name="$(set -- $command; echo "$1")"
if ! have_binary "$util_name"; then
return 1
fi
printf '==> Using %s to download "%s" to "%s"\n' "$util_name" "$url" "$output"
if eval "$command"; then
echo "==> Download complete!"
return
else
echo "error: couldn't download with $util_name ($?)"
return 1
fi
}
download() {
dl_url="$1"
dl_output="$2"
test "$#" -eq "2" || die "download requires exactly two arguments, was given $@"
if ! check_writable "$dl_output"; then
die "download error: cannot write to $dl_output"
fi
try_download "$dl_url" "$dl_output" "wget '$dl_url' -O '$dl_output'" && return
try_download "$dl_url" "$dl_output" "curl --silent --fail --output '$dl_output' '$dl_url'" && return
try_download "$dl_url" "$dl_output" "fetch '$dl_url' -o '$dl_output'" && return
try_download "$dl_url" "$dl_output" "http '$dl_url' > '$dl_output'" && return
try_download "$dl_url" "$dl_output" "ftp -o '$dl_output' '$dl_url'" && return
die "Unable to download $dl_url. exiting."
}
fetch_ipget() {
local dest="$1"
local cid="$2"
IPGET_PARAMS="--node=spawn -p=/ip4/138.201.67.219/tcp/4002/ws/ipfs/QmUd6zHcbkbcs7SMxwLs48qZVX3vpcM8errYS7xEczwRMA -p=/ip4/138.201.67.218/tcp/4002/ws/ipfs/QmbVWZQhCGrS7DhgLqWbgvdmKN7JueKCREVanfnVpgyq8x -p=/ip4/94.130.135.167/tcp/4002/ws/ipfs/QmUEMvxS2e7iDrereVYc5SWPauXPyNwxcy9BXZrC1QTcHE -p=/ip4/138.201.68.74/tcp/4001/ipfs/QmdnXwLrC8p1ueiq2Qya8joNvk3TVVDAut7PrikmZwubtR -p=/ip4/138.201.67.220/tcp/4001/ipfs/QmNSYxZAiJHeLdkBg38roksAR9So7Y5eojks1yjEcUtZ7i"
./bin/ipget $IPGET_PARAMS -o "$dest" "$cid"
}
fetch_gateway() {
local dest="$1"
local cid="$2"
local url="http://198.211.99.118/ipfs/$cid"
download "$url" "$dest"
}
OUT_DIR="/var/tmp/filecoin-proof-parameters"
mkdir -p $OUT_DIR
printf $PARAMS | base64 -d | jq '. | to_entries | map("'$OUT_DIR'/\(.key) \(.value.cid) \(.value.digest)") | .[]' --raw-output | \
while read -r dest cid digest; do
if [[ -f "$dest" ]]; then
b2=$(b2sum "$dest" | head -c 32)
if [[ "$digest" == "$b2" ]]; then
echo "$dest exists and has correct hash"
continue
else
echo "$dest has incorrect hash"
rm -f "$dest"
fi
fi
echo "downloading $dest"
fetch_gateway "$dest" "$cid"
done

View File

@ -1,34 +1,44 @@
package build
import "fmt"
var CurrentCommit string
// Version is the local build version, set by build system
const Version = "0.1.1"
// BuildVersion is the local build version, set by build system
const BuildVersion = "0.1.5"
var UserVersion = Version + CurrentCommit
var UserVersion = BuildVersion + CurrentCommit
// APIVersion is a hex semver version of the rpc api exposed
//
// M M P
// A I A
// J N T
// O O C
// R R H
// |\vv/|
// vv vv
const APIVersion = 0x000101
type Version uint32
func newVer(major, minor, patch uint8) Version {
return Version(uint32(major)<<16 | uint32(minor)<<8 | uint32(patch))
}
// Ints returns (major, minor, patch) versions
func (ve Version) Ints() (uint32, uint32, uint32) {
v := uint32(ve)
return (v & majorOnlyMask) >> 16, (v & minorOnlyMask) >> 8, v & patchOnlyMask
}
func (ve Version) String() string {
vmj, vmi, vp := ve.Ints()
return fmt.Sprintf("%d.%d.%d", vmj, vmi, vp)
}
func (ve Version) EqMajorMinor(v2 Version) bool {
return ve&minorMask == v2&minorMask
}
// APIVersion is a semver version of the rpc api exposed
var APIVersion Version = newVer(0, 1, 6)
const (
MajorMask = 0xff0000
MinorMask = 0xffff00
PatchMask = 0xffffff
majorMask = 0xff0000
minorMask = 0xffff00
patchMask = 0xffffff
MajorOnlyMask = 0xff0000
MinorOnlyMask = 0x00ff00
PatchOnlyMask = 0x0000ff
majorOnlyMask = 0xff0000
minorOnlyMask = 0x00ff00
patchOnlyMask = 0x0000ff
)
// VersionInts returns (major, minor, patch) versions
func VersionInts(version uint32) (uint32, uint32, uint32) {
return (version & MajorOnlyMask) >> 16, (version & MinorOnlyMask) >> 8, version & PatchOnlyMask
}

View File

@ -1,8 +1,8 @@
package actors
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
)

View File

@ -6,8 +6,8 @@ import (
"encoding/binary"
"fmt"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"

View File

@ -8,11 +8,11 @@ import (
ffi "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-sectorbuilder"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sectorbuilder"
"github.com/filecoin-project/go-amt-ipld"
"github.com/ipfs/go-cid"
@ -140,7 +140,10 @@ func (sma StorageMinerActor) Exports() []interface{} {
return []interface{}{
1: sma.StorageMinerConstructor,
2: sma.PreCommitSector,
3: sma.ProveCommitSector,
3: withUpdates(
update{start: 0, method: sma.ProveCommitSectorV0},
update{start: build.ForkNoPowerEPSUpdates, method: sma.ProveCommitSectorV1},
),
4: sma.SubmitFallbackPoSt,
//5: sma.SlashStorageFault,
//6: sma.GetCurrentProvingSet,
@ -155,7 +158,10 @@ func (sma StorageMinerActor) Exports() []interface{} {
//15: sma.ChangeWorker,
16: sma.IsSlashed,
17: sma.CheckMiner,
18: sma.DeclareFaults,
18: withUpdates(
update{start: 0, method: sma.DeclareFaultsV0},
update{start: build.ForkNoPowerEPSUpdates, method: sma.DeclareFaultsV1},
),
19: sma.SlashConsensusFault,
20: sma.SubmitElectionPoSt,
}
@ -238,7 +244,7 @@ func (sma StorageMinerActor) PreCommitSector(act *types.Actor, vmctx types.VMCon
}
if vmctx.Message().From != mi.Worker {
return nil, aerrors.New(1, "not authorized to commit sector for miner")
return nil, aerrors.New(1, "not authorized to precommit sector for miner")
}
// make sure the miner isnt trying to submit a pre-existing sector
@ -291,7 +297,7 @@ type SectorProveCommitInfo struct {
DealIDs []uint64
}
func (sma StorageMinerActor) ProveCommitSector(act *types.Actor, vmctx types.VMContext, params *SectorProveCommitInfo) ([]byte, ActorError) {
func (sma StorageMinerActor) ProveCommitSectorV0(act *types.Actor, vmctx types.VMContext, params *SectorProveCommitInfo) ([]byte, ActorError) {
ctx := vmctx.Context()
oldstate, self, err := loadState(vmctx)
if err != nil {
@ -391,7 +397,114 @@ func (sma StorageMinerActor) ProveCommitSector(act *types.Actor, vmctx types.VMC
}
_, err = vmctx.Send(StorageMarketAddress, SMAMethods.ActivateStorageDeals, types.NewInt(0), activateParams)
return nil, err
return nil, aerrors.Wrapf(err, "calling ActivateStorageDeals failed")
}
func (sma StorageMinerActor) ProveCommitSectorV1(act *types.Actor, vmctx types.VMContext, params *SectorProveCommitInfo) ([]byte, ActorError) {
ctx := vmctx.Context()
oldstate, self, err := loadState(vmctx)
if err != nil {
return nil, err
}
mi, err := loadMinerInfo(vmctx, self)
if err != nil {
return nil, err
}
if vmctx.Message().From != mi.Worker {
return nil, aerrors.New(1, "not authorized to submit sector proof for miner")
}
us, ok := self.PreCommittedSectors[uintToStringKey(params.SectorID)]
if !ok {
return nil, aerrors.New(1, "no pre-commitment found for sector")
}
if us.ReceivedEpoch+build.InteractivePoRepDelay >= vmctx.BlockHeight() {
return nil, aerrors.New(2, "too early for proof submission")
}
delete(self.PreCommittedSectors, uintToStringKey(params.SectorID))
// TODO: ensure normalization to ID address
maddr := vmctx.Message().To
ticket, err := vmctx.GetRandomness(us.Info.SealEpoch - build.SealRandomnessLookback)
if err != nil {
return nil, aerrors.Wrap(err, "failed to get ticket randomness")
}
seed, err := vmctx.GetRandomness(us.ReceivedEpoch + build.InteractivePoRepDelay)
if err != nil {
return nil, aerrors.Wrap(err, "failed to get randomness for prove sector commitment")
}
enc, err := SerializeParams(&ComputeDataCommitmentParams{
DealIDs: params.DealIDs,
SectorSize: mi.SectorSize,
})
if err != nil {
return nil, aerrors.Wrap(err, "failed to serialize ComputeDataCommitmentParams")
}
commD, err := vmctx.Send(StorageMarketAddress, SMAMethods.ComputeDataCommitment, types.NewInt(0), enc)
if err != nil {
return nil, aerrors.Wrapf(err, "failed to compute data commitment (sector %d, deals: %v)", params.SectorID, params.DealIDs)
}
if ok, err := vmctx.Sys().ValidatePoRep(ctx, maddr, mi.SectorSize, commD, us.Info.CommR, ticket, params.Proof, seed, params.SectorID); err != nil {
return nil, err
} else if !ok {
return nil, aerrors.Newf(2, "porep proof was invalid (t:%x; s:%x(%d); p:%s)", ticket, seed, us.ReceivedEpoch+build.InteractivePoRepDelay, truncateHexPrint(params.Proof))
}
// Note: There must exist a unique index in the miner's sector set for each
// sector ID. The `faults`, `recovered`, and `done` parameters of the
// SubmitPoSt method express indices into this sector set.
nssroot, err := AddToSectorSet(ctx, types.WrapStorage(vmctx.Storage()), self.Sectors, params.SectorID, us.Info.CommR, commD)
if err != nil {
return nil, err
}
self.Sectors = nssroot
// if miner is not mining, start their proving period now
// Note: As written here, every miners first PoSt will only be over one sector.
// We could set up a 'grace period' for starting mining that would allow miners
// to submit several sectors for their first proving period. Alternatively, we
// could simply make the 'PreCommitSector' call take multiple sectors at a time.
//
// Note: Proving period is a function of sector size; small sectors take less
// time to prove than large sectors do. Sector size is selected when pledging.
pss, lerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingSet)
if lerr != nil {
return nil, aerrors.HandleExternalError(lerr, "could not load proving set node")
}
if pss.Count == 0 && !self.Active {
self.ProvingSet = self.Sectors
// TODO: probably want to wait until the miner is above a certain
// threshold before starting this
self.ElectionPeriodStart = vmctx.BlockHeight()
}
nstate, err := vmctx.Storage().Put(self)
if err != nil {
return nil, err
}
if err := vmctx.Storage().Commit(oldstate, nstate); err != nil {
return nil, err
}
activateParams, err := SerializeParams(&ActivateStorageDealsParams{
Deals: params.DealIDs,
})
if err != nil {
return nil, err
}
_, err = vmctx.Send(StorageMarketAddress, SMAMethods.ActivateStorageDeals, types.NewInt(0), activateParams)
return nil, aerrors.Wrapf(err, "calling ActivateStorageDeals failed")
}
func truncateHexPrint(b []byte) string {
@ -508,7 +621,7 @@ func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VM
}
if ok, lerr := sectorbuilder.VerifyFallbackPost(vmctx.Context(), mi.SectorSize,
sectorbuilder.NewSortedPublicSectorInfo(sectorInfos), seed[:], params.Proof, candidates, proverID); !ok || lerr != nil {
sectorbuilder.NewSortedPublicSectorInfo(sectorInfos), seed[:], params.Proof, candidates, proverID, 0); !ok || lerr != nil { // TODO: FORK - set faults to len(faults)
if lerr != nil {
// TODO: study PoST errors
return nil, aerrors.Absorb(lerr, 4, "PoST error")
@ -608,8 +721,10 @@ func RemoveFromSectorSet(ctx context.Context, s types.Storage, ss cid.Cid, ids [
return cid.Undef, aerrors.HandleExternalError(err, "could not load sector set node")
}
if err := ssr.BatchDelete(ids); err != nil {
return cid.Undef, aerrors.HandleExternalError(err, "failed to delete from sector set")
for _, id := range ids {
if err := ssr.Delete(id); err != nil {
log.Warnf("failed to delete sector %d from set: %s", id, err)
}
}
ncid, err := ssr.Flush()
@ -808,7 +923,7 @@ type DeclareFaultsParams struct {
Faults types.BitField
}
func (sma StorageMinerActor) DeclareFaults(act *types.Actor, vmctx types.VMContext, params *DeclareFaultsParams) ([]byte, ActorError) {
func (sma StorageMinerActor) DeclareFaultsV0(act *types.Actor, vmctx types.VMContext, params *DeclareFaultsParams) ([]byte, ActorError) {
oldstate, self, aerr := loadState(vmctx)
if aerr != nil {
return nil, aerr
@ -824,7 +939,42 @@ func (sma StorageMinerActor) DeclareFaults(act *types.Actor, vmctx types.VMConte
self.LastFaultSubmission = vmctx.BlockHeight()
nstate, aerr := vmctx.Storage().Put(self)
if err != nil { // TODO: FORK: should be aerr
return nil, aerr
}
if err := vmctx.Storage().Commit(oldstate, nstate); err != nil {
return nil, err
}
return nil, nil
}
func (sma StorageMinerActor) DeclareFaultsV1(act *types.Actor, vmctx types.VMContext, params *DeclareFaultsParams) ([]byte, ActorError) {
oldstate, self, aerr := loadState(vmctx)
if aerr != nil {
return nil, aerr
}
mi, aerr := loadMinerInfo(vmctx, self)
if aerr != nil {
return nil, aerr
}
if vmctx.Message().From != mi.Worker {
return nil, aerrors.New(1, "not authorized to declare faults for miner")
}
nfaults, err := types.MergeBitFields(params.Faults, self.FaultSet)
if err != nil {
return nil, aerrors.Absorb(err, 1, "failed to merge bitfields")
}
self.FaultSet = nfaults
self.LastFaultSubmission = vmctx.BlockHeight()
nstate, aerr := vmctx.Storage().Put(self)
if aerr != nil {
return nil, aerr
}
if err := vmctx.Storage().Commit(oldstate, nstate); err != nil {
@ -910,6 +1060,81 @@ func (sma StorageMinerActor) SubmitElectionPoSt(act *types.Actor, vmctx types.VM
}
func onSuccessfulPoSt(self *StorageMinerActorState, vmctx types.VMContext) aerrors.ActorError {
if vmctx.BlockHeight() >= build.ForkNoPowerEPSUpdates {
return onSuccessfulPoStV1(self, vmctx)
}
return onSuccessfulPoStV0(self, vmctx)
}
func onSuccessfulPoStV0(self *StorageMinerActorState, vmctx types.VMContext) aerrors.ActorError {
var mi MinerInfo
if err := vmctx.Storage().Get(self.Info, &mi); err != nil {
return err
}
pss, nerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingSet)
if nerr != nil {
return aerrors.HandleExternalError(nerr, "failed to load proving set")
}
faults, nerr := self.FaultSet.All()
if nerr != nil {
return aerrors.Absorb(nerr, 1, "invalid bitfield (fatal?)")
}
self.FaultSet = types.NewBitField()
oldPower := self.Power
newPower := types.BigMul(types.NewInt(pss.Count-uint64(len(faults))), types.NewInt(mi.SectorSize))
// If below the minimum size requirement, miners have zero power
if newPower.LessThan(types.NewInt(build.MinimumMinerPower)) {
newPower = types.NewInt(0)
}
self.Power = newPower
delta := types.BigSub(self.Power, oldPower)
if self.SlashedAt != 0 {
self.SlashedAt = 0
delta = self.Power
}
prevSlashingDeadline := self.ElectionPeriodStart + build.SlashablePowerDelay
if !self.Active && newPower.GreaterThan(types.NewInt(0)) {
self.Active = true
prevSlashingDeadline = 0
}
if !(oldPower.IsZero() && newPower.IsZero()) {
enc, err := SerializeParams(&UpdateStorageParams{
Delta: delta,
NextSlashDeadline: vmctx.BlockHeight() + build.SlashablePowerDelay,
PreviousSlashDeadline: prevSlashingDeadline,
})
if err != nil {
return err
}
_, err = vmctx.Send(StoragePowerAddress, SPAMethods.UpdateStorage, types.NewInt(0), enc)
if err != nil {
return aerrors.Wrap(err, "updating storage failed")
}
}
ncid, err := RemoveFromSectorSet(vmctx.Context(), vmctx.Storage(), self.Sectors, faults)
if err != nil {
return err
}
self.Sectors = ncid
self.ProvingSet = ncid
self.ElectionPeriodStart = vmctx.BlockHeight()
return nil
}
func onSuccessfulPoStV1(self *StorageMinerActorState, vmctx types.VMContext) aerrors.ActorError {
// TODO: some sector upkeep stuff that is very haphazard and unclear in the spec
var mi MinerInfo
@ -953,9 +1178,9 @@ func onSuccessfulPoSt(self *StorageMinerActorState, vmctx types.VMContext) aerro
if !(oldPower.IsZero() && newPower.IsZero()) {
enc, err := SerializeParams(&UpdateStorageParams{
Delta: delta,
NextProvingPeriodEnd: vmctx.BlockHeight() + build.SlashablePowerDelay,
PreviousProvingPeriodEnd: prevSlashingDeadline,
Delta: delta,
NextSlashDeadline: vmctx.BlockHeight() + build.SlashablePowerDelay,
PreviousSlashDeadline: prevSlashingDeadline,
})
if err != nil {
return err
@ -963,8 +1188,10 @@ func onSuccessfulPoSt(self *StorageMinerActorState, vmctx types.VMContext) aerro
_, err = vmctx.Send(StoragePowerAddress, SPAMethods.UpdateStorage, types.NewInt(0), enc)
if err != nil {
return err
return aerrors.Wrap(err, "updating storage failed")
}
self.ElectionPeriodStart = vmctx.BlockHeight()
}
ncid, err := RemoveFromSectorSet(vmctx.Context(), vmctx.Storage(), self.Sectors, faults)
@ -974,7 +1201,6 @@ func onSuccessfulPoSt(self *StorageMinerActorState, vmctx types.VMContext) aerro
self.Sectors = ncid
self.ProvingSet = ncid
self.ElectionPeriodStart = vmctx.BlockHeight()
return nil
}

View File

@ -6,13 +6,13 @@ import (
"math/rand"
"testing"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-sectorbuilder"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sectorbuilder"
hamt "github.com/ipfs/go-hamt-ipld"
blockstore "github.com/ipfs/go-ipfs-blockstore"
cbg "github.com/whyrusleeping/cbor-gen"
@ -52,6 +52,71 @@ func TestMinerCommitSectors(t *testing.T) {
assertSectorIDs(h, t, minerAddr, []uint64{1})
}
func TestMinerSubmitBadFault(t *testing.T) {
var worker, client address.Address
var minerAddr address.Address
opts := []HarnessOpt{
HarnessAddr(&worker, 1000000),
HarnessAddr(&client, 1000000),
HarnessActor(&minerAddr, &worker, actors.StorageMinerCodeCid,
func() cbg.CBORMarshaler {
return &actors.StorageMinerConstructorParams{
Owner: worker,
Worker: worker,
SectorSize: 1024,
PeerID: "fakepeerid",
}
}),
}
h := NewHarness(t, opts...)
h.vm.Syscalls.ValidatePoRep = func(ctx context.Context, maddr address.Address, ssize uint64, commD, commR, ticket, proof, seed []byte, sectorID uint64) (bool, aerrors.ActorError) {
// all proofs are valid
return true, nil
}
ret, _ := h.SendFunds(t, worker, minerAddr, types.NewInt(100000))
ApplyOK(t, ret)
ret, _ = h.InvokeWithValue(t, client, actors.StorageMarketAddress, actors.SMAMethods.AddBalance, types.NewInt(2000), nil)
ApplyOK(t, ret)
addSectorToMiner(h, t, minerAddr, worker, client, 1)
assertSectorIDs(h, t, minerAddr, []uint64{1})
bf := types.NewBitField()
bf.Set(6)
ret, _ = h.Invoke(t, worker, minerAddr, actors.MAMethods.DeclareFaults, &actors.DeclareFaultsParams{bf})
ApplyOK(t, ret)
ret, _ = h.Invoke(t, actors.NetworkAddress, minerAddr, actors.MAMethods.SubmitElectionPoSt, nil)
ApplyOK(t, ret)
assertSectorIDs(h, t, minerAddr, []uint64{1})
badnum := uint64(0)
badnum--
bf = types.NewBitField()
bf.Set(badnum)
ret, _ = h.Invoke(t, worker, minerAddr, actors.MAMethods.DeclareFaults, &actors.DeclareFaultsParams{bf})
ApplyOK(t, ret)
ret, _ = h.Invoke(t, actors.NetworkAddress, minerAddr, actors.MAMethods.SubmitElectionPoSt, nil)
ApplyOK(t, ret)
bf = types.NewBitField()
bf.Set(1)
ret, _ = h.Invoke(t, worker, minerAddr, actors.MAMethods.DeclareFaults, &actors.DeclareFaultsParams{bf})
ApplyOK(t, ret)
ret, _ = h.Invoke(t, actors.NetworkAddress, minerAddr, actors.MAMethods.SubmitElectionPoSt, nil)
ApplyOK(t, ret)
assertSectorIDs(h, t, minerAddr, []uint64{})
}
func addSectorToMiner(h *Harness, t *testing.T, minerAddr, worker, client address.Address, sid uint64) {
t.Helper()
s := sectorbuilder.UserBytesForSectorSize(1024)

View File

@ -3,8 +3,8 @@ package actors
import (
"github.com/ipfs/go-cid"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
cbg "github.com/whyrusleeping/cbor-gen"

View File

@ -7,8 +7,8 @@ import (
"github.com/stretchr/testify/assert"
cbg "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
)

View File

@ -7,9 +7,9 @@ import (
"github.com/ipfs/go-cid"
"github.com/minio/blake2b-simd"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
)

View File

@ -4,8 +4,8 @@ import (
"context"
"testing"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet"
)

View File

@ -5,18 +5,19 @@ import (
"context"
"sort"
"go.opencensus.io/trace"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-amt-ipld"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-hamt-ipld"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/go-sectorbuilder"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/cborutil"
"github.com/filecoin-project/lotus/lib/sectorbuilder"
)
type StorageMarketActor struct{}
@ -254,6 +255,9 @@ func setMarketBalances(vmctx types.VMContext, nd *hamt.Node, set map[address.Add
}
func GetMarketBalances(ctx context.Context, store *hamt.CborIpldStore, rcid cid.Cid, addrs ...address.Address) ([]StorageParticipantBalance, *hamt.Node, ActorError) {
ctx, span := trace.StartSpan(ctx, "GetMarketBalances")
defer span.End()
nd, err := hamt.LoadNode(ctx, store, rcid)
if err != nil {
return nil, nil, aerrors.HandleExternalError(err, "failed to load miner set")
@ -381,6 +385,9 @@ func (sma StorageMarketActor) PublishStorageDeals(act *types.Actor, vmctx types.
}
func (st *StorageMarketState) validateDeal(vmctx types.VMContext, deal StorageDealProposal, providerWorker address.Address) aerrors.ActorError {
ctx, span := trace.StartSpan(vmctx.Context(), "validateDeal")
defer span.End()
if vmctx.BlockHeight() > deal.ProposalExpiration {
return aerrors.New(1, "deal proposal already expired")
}
@ -394,7 +401,7 @@ func (st *StorageMarketState) validateDeal(vmctx types.VMContext, deal StorageDe
}
// TODO: do some caching (changes gas so needs to be in spec too)
b, bnd, aerr := GetMarketBalances(vmctx.Context(), vmctx.Ipld(), st.Balances, deal.Client, providerWorker)
b, bnd, aerr := GetMarketBalances(ctx, vmctx.Ipld(), st.Balances, deal.Client, providerWorker)
if aerr != nil {
return aerrors.Wrap(aerr, "getting client, and provider balances")
}

View File

@ -13,9 +13,9 @@ import (
"go.opencensus.io/trace"
xerrors "golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
)
@ -267,9 +267,9 @@ func shouldSlash(block1, block2 *types.BlockHeader) bool {
}
type UpdateStorageParams struct {
Delta types.BigInt
NextProvingPeriodEnd uint64
PreviousProvingPeriodEnd uint64
Delta types.BigInt
NextSlashDeadline uint64
PreviousSlashDeadline uint64
}
func (spa StoragePowerActor) UpdateStorage(act *types.Actor, vmctx types.VMContext, params *UpdateStorageParams) ([]byte, ActorError) {
@ -289,10 +289,10 @@ func (spa StoragePowerActor) UpdateStorage(act *types.Actor, vmctx types.VMConte
self.TotalStorage = types.BigAdd(self.TotalStorage, params.Delta)
previousBucket := params.PreviousProvingPeriodEnd % build.SlashablePowerDelay
nextBucket := params.NextProvingPeriodEnd % build.SlashablePowerDelay
previousBucket := params.PreviousSlashDeadline % build.SlashablePowerDelay
nextBucket := params.NextSlashDeadline % build.SlashablePowerDelay
if previousBucket == nextBucket && params.PreviousProvingPeriodEnd != 0 {
if previousBucket == nextBucket && params.PreviousSlashDeadline != 0 {
nroot, err := vmctx.Storage().Put(&self)
if err != nil {
return nil, err
@ -310,10 +310,10 @@ func (spa StoragePowerActor) UpdateStorage(act *types.Actor, vmctx types.VMConte
return nil, aerrors.HandleExternalError(eerr, "loading proving buckets amt")
}
if params.PreviousProvingPeriodEnd != 0 { // delete from previous bucket
if params.PreviousSlashDeadline != 0 { // delete from previous bucket
err := deleteMinerFromBucket(vmctx, buckets, previousBucket)
if err != nil {
return nil, err
return nil, aerrors.Wrapf(err, "delete from bucket %d, next %d", previousBucket, nextBucket)
}
}
@ -393,7 +393,7 @@ func addMinerToBucket(vmctx types.VMContext, buckets *amt.Root, nextBucket uint6
return aerrors.HandleExternalError(err, "getting proving bucket")
}
err = bhamt.Set(vmctx.Context(), string(vmctx.Message().From.Bytes()), cborNull)
err = bhamt.Set(vmctx.Context(), string(vmctx.Message().From.Bytes()), CborNull)
if err != nil {
return aerrors.HandleExternalError(err, "setting miner in proving bucket")
}
@ -768,7 +768,7 @@ func MinerSetRemove(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, ma
type cbgNull struct{}
var cborNull = &cbgNull{}
var CborNull = &cbgNull{}
func (cbgNull) MarshalCBOR(w io.Writer) error {
n, err := w.Write(cbg.CborNull)

View File

@ -8,8 +8,8 @@ import (
"github.com/filecoin-project/lotus/build"
cbg "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/go-address"
. "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/chain/wallet"

View File

@ -1,7 +1,7 @@
package actors
import (
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/go-address"
"github.com/ipfs/go-cid"
mh "github.com/multiformats/go-multihash"

View File

@ -8,8 +8,8 @@ import (
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/go-address"
. "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"

View File

@ -1,8 +1,8 @@
package actors
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/address"
)
func NewIDAddress(id uint64) (address.Address, ActorError) {

View File

@ -4,6 +4,7 @@ import (
"errors"
"fmt"
hamt "github.com/ipfs/go-hamt-ipld"
"golang.org/x/xerrors"
)
@ -159,6 +160,16 @@ func HandleExternalError(err error, msg string) ActorError {
}
}
if xerrors.Is(err, &hamt.SerializationError{}) {
return &actorError{
fatal: false,
retCode: 253,
msg: msg,
frame: xerrors.Caller(1),
err: err,
}
}
return &actorError{
fatal: true,

View File

@ -5,7 +5,7 @@ import (
"io"
"sort"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/libp2p/go-libp2p-core/peer"
cbg "github.com/whyrusleeping/cbor-gen"
@ -94,6 +94,10 @@ func (t *ExecParams) MarshalCBOR(w io.Writer) error {
}
// t.Params ([]uint8) (slice)
if len(t.Params) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.Params was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Params)))); err != nil {
return err
}
@ -220,6 +224,10 @@ func (t *StorageMinerActorState) MarshalCBOR(w io.Writer) error {
for _, k := range keys {
v := t.PreCommittedSectors[k]
if len(k) > cbg.MaxLength {
return xerrors.Errorf("Value in field k was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(k)))); err != nil {
return err
}
@ -481,6 +489,10 @@ func (t *StorageMinerConstructorParams) MarshalCBOR(w io.Writer) error {
}
// t.PeerID (peer.ID) (string)
if len(t.PeerID) > cbg.MaxLength {
return xerrors.Errorf("Value in field t.PeerID was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.PeerID)))); err != nil {
return err
}
@ -561,6 +573,10 @@ func (t *SectorPreCommitInfo) MarshalCBOR(w io.Writer) error {
}
// t.CommR ([]uint8) (slice)
if len(t.CommR) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.CommR was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.CommR)))); err != nil {
return err
}
@ -574,6 +590,10 @@ func (t *SectorPreCommitInfo) MarshalCBOR(w io.Writer) error {
}
// t.DealIDs ([]uint64) (slice)
if len(t.DealIDs) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.DealIDs was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.DealIDs)))); err != nil {
return err
}
@ -749,6 +769,10 @@ func (t *MinerInfo) MarshalCBOR(w io.Writer) error {
}
// t.PeerID (peer.ID) (string)
if len(t.PeerID) > cbg.MaxLength {
return xerrors.Errorf("Value in field t.PeerID was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.PeerID)))); err != nil {
return err
}
@ -829,6 +853,10 @@ func (t *SubmitFallbackPoStParams) MarshalCBOR(w io.Writer) error {
}
// t.Proof ([]uint8) (slice)
if len(t.Proof) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.Proof was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Proof)))); err != nil {
return err
}
@ -837,6 +865,10 @@ func (t *SubmitFallbackPoStParams) MarshalCBOR(w io.Writer) error {
}
// t.Candidates ([]types.EPostTicket) (slice)
if len(t.Candidates) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.Candidates was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Candidates)))); err != nil {
return err
}
@ -920,6 +952,10 @@ func (t *PaymentVerifyParams) MarshalCBOR(w io.Writer) error {
}
// t.Extra ([]uint8) (slice)
if len(t.Extra) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.Extra was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Extra)))); err != nil {
return err
}
@ -928,6 +964,10 @@ func (t *PaymentVerifyParams) MarshalCBOR(w io.Writer) error {
}
// t.Proof ([]uint8) (slice)
if len(t.Proof) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.Proof was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Proof)))); err != nil {
return err
}
@ -999,6 +1039,10 @@ func (t *UpdatePeerIDParams) MarshalCBOR(w io.Writer) error {
}
// t.PeerID (peer.ID) (string)
if len(t.PeerID) > cbg.MaxLength {
return xerrors.Errorf("Value in field t.PeerID was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.PeerID)))); err != nil {
return err
}
@ -1089,6 +1133,10 @@ func (t *MultiSigActorState) MarshalCBOR(w io.Writer) error {
}
// t.Signers ([]address.Address) (slice)
if len(t.Signers) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.Signers was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Signers)))); err != nil {
return err
}
@ -1124,6 +1172,10 @@ func (t *MultiSigActorState) MarshalCBOR(w io.Writer) error {
}
// t.Transactions ([]actors.MTransaction) (slice)
if len(t.Transactions) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.Transactions was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Transactions)))); err != nil {
return err
}
@ -1266,6 +1318,10 @@ func (t *MultiSigConstructorParams) MarshalCBOR(w io.Writer) error {
}
// t.Signers ([]address.Address) (slice)
if len(t.Signers) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.Signers was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Signers)))); err != nil {
return err
}
@ -1377,6 +1433,10 @@ func (t *MultiSigProposeParams) MarshalCBOR(w io.Writer) error {
}
// t.Params ([]uint8) (slice)
if len(t.Params) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.Params was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Params)))); err != nil {
return err
}
@ -1629,6 +1689,10 @@ func (t *MTransaction) MarshalCBOR(w io.Writer) error {
}
// t.Params ([]uint8) (slice)
if len(t.Params) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.Params was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Params)))); err != nil {
return err
}
@ -1637,6 +1701,10 @@ func (t *MTransaction) MarshalCBOR(w io.Writer) error {
}
// t.Approved ([]address.Address) (slice)
if len(t.Approved) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.Approved was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Approved)))); err != nil {
return err
}
@ -1999,6 +2067,10 @@ func (t *PaymentChannelActorState) MarshalCBOR(w io.Writer) error {
for _, k := range keys {
v := t.LaneStates[k]
if len(k) > cbg.MaxLength {
return xerrors.Errorf("Value in field k was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(k)))); err != nil {
return err
}
@ -2271,6 +2343,10 @@ func (t *PCAUpdateChannelStateParams) MarshalCBOR(w io.Writer) error {
}
// t.Secret ([]uint8) (slice)
if len(t.Secret) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.Secret was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Secret)))); err != nil {
return err
}
@ -2279,6 +2355,10 @@ func (t *PCAUpdateChannelStateParams) MarshalCBOR(w io.Writer) error {
}
// t.Proof ([]uint8) (slice)
if len(t.Proof) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.Proof was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Proof)))); err != nil {
return err
}
@ -2381,6 +2461,10 @@ func (t *PaymentInfo) MarshalCBOR(w io.Writer) error {
}
// t.Vouchers ([]*types.SignedVoucher) (slice)
if len(t.Vouchers) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.Vouchers was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Vouchers)))); err != nil {
return err
}
@ -2613,6 +2697,10 @@ func (t *CreateStorageMinerParams) MarshalCBOR(w io.Writer) error {
}
// t.PeerID (peer.ID) (string)
if len(t.PeerID) > cbg.MaxLength {
return xerrors.Errorf("Value in field t.PeerID was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.PeerID)))); err != nil {
return err
}
@ -2778,13 +2866,13 @@ func (t *UpdateStorageParams) MarshalCBOR(w io.Writer) error {
return err
}
// t.NextProvingPeriodEnd (uint64) (uint64)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.NextProvingPeriodEnd))); err != nil {
// t.NextSlashDeadline (uint64) (uint64)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.NextSlashDeadline))); err != nil {
return err
}
// t.PreviousProvingPeriodEnd (uint64) (uint64)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.PreviousProvingPeriodEnd))); err != nil {
// t.PreviousSlashDeadline (uint64) (uint64)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.PreviousSlashDeadline))); err != nil {
return err
}
return nil
@ -2814,7 +2902,7 @@ func (t *UpdateStorageParams) UnmarshalCBOR(r io.Reader) error {
}
}
// t.NextProvingPeriodEnd (uint64) (uint64)
// t.NextSlashDeadline (uint64) (uint64)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
@ -2823,8 +2911,8 @@ func (t *UpdateStorageParams) UnmarshalCBOR(r io.Reader) error {
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.NextProvingPeriodEnd = uint64(extra)
// t.PreviousProvingPeriodEnd (uint64) (uint64)
t.NextSlashDeadline = uint64(extra)
// t.PreviousSlashDeadline (uint64) (uint64)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
@ -2833,7 +2921,7 @@ func (t *UpdateStorageParams) UnmarshalCBOR(r io.Reader) error {
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.PreviousProvingPeriodEnd = uint64(extra)
t.PreviousSlashDeadline = uint64(extra)
return nil
}
@ -3223,6 +3311,10 @@ func (t *StorageDealProposal) MarshalCBOR(w io.Writer) error {
}
// t.PieceRef ([]uint8) (slice)
if len(t.PieceRef) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.PieceRef was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.PieceRef)))); err != nil {
return err
}
@ -3404,6 +3496,10 @@ func (t *PublishStorageDealsParams) MarshalCBOR(w io.Writer) error {
}
// t.Deals ([]actors.StorageDealProposal) (slice)
if len(t.Deals) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.Deals was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Deals)))); err != nil {
return err
}
@ -3470,6 +3566,10 @@ func (t *PublishStorageDealResponse) MarshalCBOR(w io.Writer) error {
}
// t.DealIDs ([]uint64) (slice)
if len(t.DealIDs) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.DealIDs was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.DealIDs)))); err != nil {
return err
}
@ -3540,6 +3640,10 @@ func (t *ActivateStorageDealsParams) MarshalCBOR(w io.Writer) error {
}
// t.Deals ([]uint64) (slice)
if len(t.Deals) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.Deals was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Deals)))); err != nil {
return err
}
@ -3610,6 +3714,10 @@ func (t *ProcessStorageDealsPaymentParams) MarshalCBOR(w io.Writer) error {
}
// t.DealIDs ([]uint64) (slice)
if len(t.DealIDs) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.DealIDs was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.DealIDs)))); err != nil {
return err
}
@ -3680,6 +3788,10 @@ func (t *OnChainDeal) MarshalCBOR(w io.Writer) error {
}
// t.PieceRef ([]uint8) (slice)
if len(t.PieceRef) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.PieceRef was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.PieceRef)))); err != nil {
return err
}
@ -3850,6 +3962,10 @@ func (t *ComputeDataCommitmentParams) MarshalCBOR(w io.Writer) error {
}
// t.DealIDs ([]uint64) (slice)
if len(t.DealIDs) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.DealIDs was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.DealIDs)))); err != nil {
return err
}
@ -3935,6 +4051,10 @@ func (t *SectorProveCommitInfo) MarshalCBOR(w io.Writer) error {
}
// t.Proof ([]uint8) (slice)
if len(t.Proof) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.Proof was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Proof)))); err != nil {
return err
}
@ -3948,6 +4068,10 @@ func (t *SectorProveCommitInfo) MarshalCBOR(w io.Writer) error {
}
// t.DealIDs ([]uint64) (slice)
if len(t.DealIDs) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.DealIDs was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.DealIDs)))); err != nil {
return err
}

46
chain/actors/forks.go Normal file
View File

@ -0,0 +1,46 @@
package actors
import (
"reflect"
"sort"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/types"
)
type update struct {
start uint64
method interface{}
}
func withUpdates(updates ...update) interface{} {
sort.Slice(updates, func(i, j int) bool { // so we iterate from newest below
return updates[i].start > updates[j].start
})
// <script type="application/javascript">
typ := reflect.TypeOf(updates[0].method)
out := reflect.MakeFunc(typ, func(args []reflect.Value) (results []reflect.Value) {
vmctx := args[1].Interface().(types.VMContext)
for _, u := range updates {
if vmctx.BlockHeight() >= u.start {
return reflect.ValueOf(u.method).Call(args)
}
}
return reflect.ValueOf(notFound(vmctx)).Call([]reflect.Value{})
})
return out.Interface()
// </script>
}
func notFound(vmctx types.VMContext) func() ([]byte, ActorError) {
return func() ([]byte, ActorError) {
return nil, aerrors.Fatal("no code for method %d at height %d", vmctx.Message().Method, vmctx.BlockHeight())
}
}

View File

@ -14,8 +14,8 @@ import (
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store"

View File

@ -1,415 +0,0 @@
package address
import (
"bytes"
"encoding/json"
"fmt"
"io"
"strconv"
bls "github.com/filecoin-project/filecoin-ffi"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/minio/blake2b-simd"
"github.com/multiformats/go-varint"
"github.com/polydawn/refmt/obj/atlas"
"golang.org/x/xerrors"
cbg "github.com/whyrusleeping/cbor-gen"
)
func init() {
cbor.RegisterCborType(addressAtlasEntry)
}
var addressAtlasEntry = atlas.BuildEntry(Address{}).Transform().
TransformMarshal(atlas.MakeMarshalTransformFunc(
func(a Address) (string, error) {
return string(a.Bytes()), nil
})).
TransformUnmarshal(atlas.MakeUnmarshalTransformFunc(
func(x string) (Address, error) {
return NewFromBytes([]byte(x))
})).
Complete()
// Address is the go type that represents an address in the filecoin network.
type Address struct{ str string }
// Undef is the type that represents an undefined address.
var Undef = Address{}
// Network represents which network an address belongs to.
type Network = byte
const (
// Mainnet is the main network.
Mainnet Network = iota
// Testnet is the test network.
Testnet
)
// MainnetPrefix is the main network prefix.
const MainnetPrefix = "f"
// TestnetPrefix is the main network prefix.
const TestnetPrefix = "t"
// Protocol represents which protocol an address uses.
type Protocol = byte
const (
// ID represents the address ID protocol.
ID Protocol = iota
// SECP256K1 represents the address SECP256K1 protocol.
SECP256K1
// Actor represents the address Actor protocol.
Actor
// BLS represents the address BLS protocol.
BLS
Unknown = Protocol(255)
)
// Protocol returns the protocol used by the address.
func (a Address) Protocol() Protocol {
if len(a.str) == 0 {
return Unknown
}
return a.str[0]
}
// Payload returns the payload of the address.
func (a Address) Payload() []byte {
return []byte(a.str[1:])
}
// Bytes returns the address as bytes.
func (a Address) Bytes() []byte {
return []byte(a.str)
}
// String returns an address encoded as a string.
func (a Address) String() string {
str, err := encode(Testnet, a)
if err != nil {
panic(err) // I don't know if this one is okay
}
return str
}
// Empty returns true if the address is empty, false otherwise.
func (a Address) Empty() bool {
return a == Undef
}
// Unmarshal unmarshals the cbor bytes into the address.
func (a Address) Unmarshal(b []byte) error {
return cbor.DecodeInto(b, &a)
}
// Marshal marshals the address to cbor.
func (a Address) Marshal() ([]byte, error) {
return cbor.DumpObject(a)
}
// UnmarshalJSON implements the json unmarshal interface.
func (a *Address) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
addr, err := decode(s)
if err != nil {
return err
}
*a = addr
return nil
}
// MarshalJSON implements the json marshal interface.
func (a Address) MarshalJSON() ([]byte, error) {
return []byte(`"` + a.String() + `"`), nil
}
// Format implements the Formatter interface.
func (a Address) Format(f fmt.State, c rune) {
switch c {
case 'v':
if a.Empty() {
fmt.Fprint(f, UndefAddressString) //nolint: errcheck
} else {
fmt.Fprintf(f, "[%x - %x]", a.Protocol(), a.Payload()) // nolint: errcheck
}
case 's':
fmt.Fprintf(f, "%s", a.String()) // nolint: errcheck
default:
fmt.Fprintf(f, "%"+string(c), a.Bytes()) // nolint: errcheck
}
}
func (a *Address) Scan(value interface{}) error {
switch value := value.(type) {
case string:
a1, err := decode(value)
if err != nil {
return err
}
*a = a1
return nil
default:
return xerrors.New("non-string types unsupported")
}
}
// NewIDAddress returns an address using the ID protocol.
func NewIDAddress(id uint64) (Address, error) {
return newAddress(ID, varint.ToUvarint(id))
}
// NewSecp256k1Address returns an address using the SECP256K1 protocol.
func NewSecp256k1Address(pubkey []byte) (Address, error) {
return newAddress(SECP256K1, addressHash(pubkey))
}
// NewActorAddress returns an address using the Actor protocol.
func NewActorAddress(data []byte) (Address, error) {
return newAddress(Actor, addressHash(data))
}
// NewBLSAddress returns an address using the BLS protocol.
func NewBLSAddress(pubkey []byte) (Address, error) {
return newAddress(BLS, pubkey)
}
// NewFromString returns the address represented by the string `addr`.
func NewFromString(addr string) (Address, error) {
return decode(addr)
}
// NewFromBytes return the address represented by the bytes `addr`.
func NewFromBytes(addr []byte) (Address, error) {
if len(addr) == 0 {
return Undef, nil
}
if len(addr) == 1 {
return Undef, ErrInvalidLength
}
return newAddress(addr[0], addr[1:])
}
// Checksum returns the checksum of `ingest`.
func Checksum(ingest []byte) []byte {
return hash(ingest, checksumHashConfig)
}
// ValidateChecksum returns true if the checksum of `ingest` is equal to `expected`>
func ValidateChecksum(ingest, expect []byte) bool {
digest := Checksum(ingest)
return bytes.Equal(digest, expect)
}
func addressHash(ingest []byte) []byte {
return hash(ingest, payloadHashConfig)
}
func newAddress(protocol Protocol, payload []byte) (Address, error) {
switch protocol {
case ID:
_, n, err := varint.FromUvarint(payload)
if err != nil {
return Undef, xerrors.Errorf("could not decode: %v: %w", err, ErrInvalidPayload)
}
if n != len(payload) {
return Undef, xerrors.Errorf("different varint length (v:%d != p:%d): %w",
n, len(payload), ErrInvalidPayload)
}
case SECP256K1, Actor:
if len(payload) != PayloadHashLength {
return Undef, ErrInvalidPayload
}
case BLS:
if len(payload) != bls.PublicKeyBytes {
return Undef, ErrInvalidPayload
}
default:
return Undef, ErrUnknownProtocol
}
explen := 1 + len(payload)
buf := make([]byte, explen)
buf[0] = protocol
copy(buf[1:], payload)
return Address{string(buf)}, nil
}
func encode(network Network, addr Address) (string, error) {
if addr == Undef {
return UndefAddressString, nil
}
var ntwk string
switch network {
case Mainnet:
ntwk = MainnetPrefix
case Testnet:
ntwk = TestnetPrefix
default:
return UndefAddressString, ErrUnknownNetwork
}
var strAddr string
switch addr.Protocol() {
case SECP256K1, Actor, BLS:
cksm := Checksum(append([]byte{addr.Protocol()}, addr.Payload()...))
strAddr = ntwk + fmt.Sprintf("%d", addr.Protocol()) + AddressEncoding.WithPadding(-1).EncodeToString(append(addr.Payload(), cksm[:]...))
case ID:
i, n, err := varint.FromUvarint(addr.Payload())
if err != nil {
return UndefAddressString, xerrors.Errorf("could not decode varint: %w", err)
}
if n != len(addr.Payload()) {
return UndefAddressString, xerrors.Errorf("payload contains additional bytes")
}
strAddr = fmt.Sprintf("%s%d%d", ntwk, addr.Protocol(), i)
default:
return UndefAddressString, ErrUnknownProtocol
}
return strAddr, nil
}
func decode(a string) (Address, error) {
if len(a) == 0 {
return Undef, nil
}
if a == UndefAddressString {
return Undef, nil
}
if len(a) > MaxAddressStringLength || len(a) < 3 {
return Undef, ErrInvalidLength
}
if string(a[0]) != MainnetPrefix && string(a[0]) != TestnetPrefix {
return Undef, ErrUnknownNetwork
}
var protocol Protocol
switch a[1] {
case '0':
protocol = ID
case '1':
protocol = SECP256K1
case '2':
protocol = Actor
case '3':
protocol = BLS
default:
return Undef, ErrUnknownProtocol
}
raw := a[2:]
if protocol == ID {
// 20 is length of math.MaxUint64 as a string
if len(raw) > 20 {
return Undef, ErrInvalidLength
}
id, err := strconv.ParseUint(raw, 10, 64)
if err != nil {
return Undef, ErrInvalidPayload
}
return newAddress(protocol, varint.ToUvarint(id))
}
payloadcksm, err := AddressEncoding.WithPadding(-1).DecodeString(raw)
if err != nil {
return Undef, err
}
payload := payloadcksm[:len(payloadcksm)-ChecksumHashLength]
cksm := payloadcksm[len(payloadcksm)-ChecksumHashLength:]
if protocol == SECP256K1 || protocol == Actor {
if len(payload) != 20 {
return Undef, ErrInvalidPayload
}
}
if !ValidateChecksum(append([]byte{protocol}, payload...), cksm) {
return Undef, ErrInvalidChecksum
}
return newAddress(protocol, payload)
}
func hash(ingest []byte, cfg *blake2b.Config) []byte {
hasher, err := blake2b.New(cfg)
if err != nil {
// If this happens sth is very wrong.
panic(fmt.Sprintf("invalid address hash configuration: %v", err)) // ok
}
if _, err := hasher.Write(ingest); err != nil {
// blake2bs Write implementation never returns an error in its current
// setup. So if this happens sth went very wrong.
panic(fmt.Sprintf("blake2b is unable to process hashes: %v", err)) // ok
}
return hasher.Sum(nil)
}
func (a Address) MarshalCBOR(w io.Writer) error {
if a == Undef {
return fmt.Errorf("cannot marshal undefined address")
}
abytes := a.Bytes()
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(abytes)))); err != nil {
return err
}
if _, err := w.Write(abytes); err != nil {
return err
}
return nil
}
func (a *Address) UnmarshalCBOR(br io.Reader) error {
maj, extra, err := cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajByteString {
return fmt.Errorf("cbor type for address unmarshal was not byte string")
}
if extra > 64 {
return fmt.Errorf("too many bytes to unmarshal for an address")
}
buf := make([]byte, int(extra))
if _, err := io.ReadFull(br, buf); err != nil {
return err
}
addr, err := NewFromBytes(buf)
if err != nil {
return err
}
if addr == Undef {
return fmt.Errorf("cbor input should not contain empty addresses")
}
*a = addr
return nil
}
func IDFromAddress(addr Address) (uint64, error) {
if addr.Protocol() != ID {
return 0, xerrors.Errorf("cannot get id from non id address")
}
i, _, err := varint.FromUvarint(addr.Payload())
return i, err
}

View File

@ -1,542 +0,0 @@
package address
import (
"bytes"
"encoding/base32"
"fmt"
"math"
"math/rand"
"strconv"
"testing"
"time"
ffi "github.com/filecoin-project/filecoin-ffi"
"github.com/multiformats/go-varint"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/lotus/lib/crypto"
)
func init() {
rand.Seed(time.Now().Unix())
}
func TestRandomIDAddress(t *testing.T) {
assert := assert.New(t)
addr, err := NewIDAddress(uint64(rand.Int()))
assert.NoError(err)
assert.Equal(ID, addr.Protocol())
str, err := encode(Testnet, addr)
assert.NoError(err)
maybe, err := decode(str)
assert.NoError(err)
assert.Equal(addr, maybe)
}
var allTestAddresses = []string{
"t00",
"t01",
"t010",
"t0150",
"t0499",
"t01024",
"t01729",
"t0999999",
"t15ihq5ibzwki2b4ep2f46avlkrqzhpqgtga7pdrq",
"t12fiakbhe2gwd5cnmrenekasyn6v5tnaxaqizq6a",
"t1wbxhu3ypkuo6eyp6hjx6davuelxaxrvwb2kuwva",
"t1xtwapqc6nh4si2hcwpr3656iotzmlwumogqbuaa",
"t1xcbgdhkgkwht3hrrnui3jdopeejsoatkzmoltqy",
"t17uoq6tp427uzv7fztkbsnn64iwotfrristwpryy",
"t24vg6ut43yw2h2jqydgbg2xq7x6f4kub3bg6as6i",
"t25nml2cfbljvn4goqtclhifepvfnicv6g7mfmmvq",
"t2nuqrg7vuysaue2pistjjnt3fadsdzvyuatqtfei",
"t24dd4ox4c2vpf5vk5wkadgyyn6qtuvgcpxxon64a",
"t2gfvuyh7v2sx3patm5k23wdzmhyhtmqctasbr23y",
"t3vvmn62lofvhjd2ugzca6sof2j2ubwok6cj4xxbfzz4yuxfkgobpihhd2thlanmsh3w2ptld2gqkn2jvlss4a",
"t3wmuu6crofhqmm3v4enos73okk2l366ck6yc4owxwbdtkmpk42ohkqxfitcpa57pjdcftql4tojda2poeruwa",
"t3s2q2hzhkpiknjgmf4zq3ejab2rh62qbndueslmsdzervrhapxr7dftie4kpnpdiv2n6tvkr743ndhrsw6d3a",
"t3q22fijmmlckhl56rn5nkyamkph3mcfu5ed6dheq53c244hfmnq2i7efdma3cj5voxenwiummf2ajlsbxc65a",
"t3u5zgwa4ael3vuocgc5mfgygo4yuqocrntuuhcklf4xzg5tcaqwbyfabxetwtj4tsam3pbhnwghyhijr5mixa",
}
func TestVectorsIDAddress(t *testing.T) {
testCases := []struct {
input uint64
expected string
}{
{uint64(0), "t00"},
{uint64(1), "t01"},
{uint64(10), "t010"},
{uint64(150), "t0150"},
{uint64(499), "t0499"},
{uint64(1024), "t01024"},
{uint64(1729), "t01729"},
{uint64(999999), "t0999999"},
{math.MaxUint64, fmt.Sprintf("t0%s", strconv.FormatUint(math.MaxUint64, 10))},
}
for _, tc := range testCases {
tc := tc
t.Run(fmt.Sprintf("testing actorID address: %s", tc.expected), func(t *testing.T) {
assert := assert.New(t)
// Round trip encoding and decoding from string
addr, err := NewIDAddress(tc.input)
assert.NoError(err)
assert.Equal(tc.expected, addr.String())
maybeAddr, err := NewFromString(tc.expected)
assert.NoError(err)
assert.Equal(ID, maybeAddr.Protocol())
id, _, err := varint.FromUvarint(maybeAddr.Payload())
assert.NoError(err)
assert.Equal(tc.input, id)
// Round trip to and from bytes
maybeAddrBytes, err := NewFromBytes(maybeAddr.Bytes())
assert.NoError(err)
assert.Equal(maybeAddr, maybeAddrBytes)
// Round trip encoding and decoding json
b, err := addr.MarshalJSON()
assert.NoError(err)
var newAddr Address
err = newAddr.UnmarshalJSON(b)
assert.NoError(err)
assert.Equal(addr, newAddr)
})
}
}
func TestSecp256k1Address(t *testing.T) {
assert := assert.New(t)
sk, err := crypto.GenerateKey()
assert.NoError(err)
addr, err := NewSecp256k1Address(crypto.PublicKey(sk))
assert.NoError(err)
assert.Equal(SECP256K1, addr.Protocol())
str, err := encode(Mainnet, addr)
assert.NoError(err)
maybe, err := decode(str)
assert.NoError(err)
assert.Equal(addr, maybe)
}
func TestVectorSecp256k1Address(t *testing.T) {
testCases := []struct {
input []byte
expected string
}{
{[]byte{4, 148, 2, 250, 195, 126, 100, 50, 164, 22, 163, 160, 202, 84,
38, 181, 24, 90, 179, 178, 79, 97, 52, 239, 162, 92, 228, 135, 200,
45, 46, 78, 19, 191, 69, 37, 17, 224, 210, 36, 84, 33, 248, 97, 59,
193, 13, 114, 250, 33, 102, 102, 169, 108, 59, 193, 57, 32, 211,
255, 35, 63, 208, 188, 5},
"t15ihq5ibzwki2b4ep2f46avlkrqzhpqgtga7pdrq"},
{[]byte{4, 118, 135, 185, 16, 55, 155, 242, 140, 190, 58, 234, 103, 75,
18, 0, 12, 107, 125, 186, 70, 255, 192, 95, 108, 148, 254, 42, 34,
187, 204, 38, 2, 255, 127, 92, 118, 242, 28, 165, 93, 54, 149, 145,
82, 176, 225, 232, 135, 145, 124, 57, 53, 118, 238, 240, 147, 246,
30, 189, 58, 208, 111, 127, 218},
"t12fiakbhe2gwd5cnmrenekasyn6v5tnaxaqizq6a"},
{[]byte{4, 222, 253, 208, 16, 1, 239, 184, 110, 1, 222, 213, 206, 52,
248, 71, 167, 58, 20, 129, 158, 230, 65, 188, 182, 11, 185, 41, 147,
89, 111, 5, 220, 45, 96, 95, 41, 133, 248, 209, 37, 129, 45, 172,
65, 99, 163, 150, 52, 155, 35, 193, 28, 194, 255, 53, 157, 229, 75,
226, 135, 234, 98, 49, 155},
"t1wbxhu3ypkuo6eyp6hjx6davuelxaxrvwb2kuwva"},
{[]byte{4, 3, 237, 18, 200, 20, 182, 177, 13, 46, 224, 157, 149, 180,
104, 141, 178, 209, 128, 208, 169, 163, 122, 107, 106, 125, 182, 61,
41, 129, 30, 233, 115, 4, 121, 216, 239, 145, 57, 233, 18, 73, 202,
189, 57, 50, 145, 207, 229, 210, 119, 186, 118, 222, 69, 227, 224,
133, 163, 118, 129, 191, 54, 69, 210},
"t1xtwapqc6nh4si2hcwpr3656iotzmlwumogqbuaa"},
{[]byte{4, 247, 150, 129, 154, 142, 39, 22, 49, 175, 124, 24, 151, 151,
181, 69, 214, 2, 37, 147, 97, 71, 230, 1, 14, 101, 98, 179, 206, 158,
254, 139, 16, 20, 65, 97, 169, 30, 208, 180, 236, 137, 8, 0, 37, 63,
166, 252, 32, 172, 144, 251, 241, 251, 242, 113, 48, 164, 236, 195,
228, 3, 183, 5, 118},
"t1xcbgdhkgkwht3hrrnui3jdopeejsoatkzmoltqy"},
{[]byte{4, 66, 131, 43, 248, 124, 206, 158, 163, 69, 185, 3, 80, 222,
125, 52, 149, 133, 156, 164, 73, 5, 156, 94, 136, 221, 231, 66, 133,
223, 251, 158, 192, 30, 186, 188, 95, 200, 98, 104, 207, 234, 235,
167, 174, 5, 191, 184, 214, 142, 183, 90, 82, 104, 120, 44, 248, 111,
200, 112, 43, 239, 138, 31, 224},
"t17uoq6tp427uzv7fztkbsnn64iwotfrristwpryy"},
}
for _, tc := range testCases {
tc := tc
t.Run(fmt.Sprintf("testing secp256k1 address: %s", tc.expected), func(t *testing.T) {
assert := assert.New(t)
// Round trip encoding and decoding from string
addr, err := NewSecp256k1Address(tc.input)
assert.NoError(err)
assert.Equal(tc.expected, addr.String())
maybeAddr, err := NewFromString(tc.expected)
assert.NoError(err)
assert.Equal(SECP256K1, maybeAddr.Protocol())
assert.Equal(addressHash(tc.input), maybeAddr.Payload())
// Round trip to and from bytes
maybeAddrBytes, err := NewFromBytes(maybeAddr.Bytes())
assert.NoError(err)
assert.Equal(maybeAddr, maybeAddrBytes)
// Round trip encoding and decoding json
b, err := addr.MarshalJSON()
assert.NoError(err)
var newAddr Address
err = newAddr.UnmarshalJSON(b)
assert.NoError(err)
assert.Equal(addr, newAddr)
})
}
}
func TestRandomActorAddress(t *testing.T) {
assert := assert.New(t)
actorMsg := make([]byte, 20)
rand.Read(actorMsg)
addr, err := NewActorAddress(actorMsg)
assert.NoError(err)
assert.Equal(Actor, addr.Protocol())
str, err := encode(Mainnet, addr)
assert.NoError(err)
maybe, err := decode(str)
assert.NoError(err)
assert.Equal(addr, maybe)
}
func TestVectorActorAddress(t *testing.T) {
testCases := []struct {
input []byte
expected string
}{
{[]byte{118, 18, 129, 144, 205, 240, 104, 209, 65, 128, 68, 172, 192,
62, 11, 103, 129, 151, 13, 96},
"t24vg6ut43yw2h2jqydgbg2xq7x6f4kub3bg6as6i"},
{[]byte{44, 175, 184, 226, 224, 107, 186, 152, 234, 101, 124, 92, 245,
244, 32, 35, 170, 35, 232, 142},
"t25nml2cfbljvn4goqtclhifepvfnicv6g7mfmmvq"},
{[]byte{2, 44, 158, 14, 162, 157, 143, 64, 197, 106, 190, 195, 92, 141,
88, 125, 160, 166, 76, 24},
"t2nuqrg7vuysaue2pistjjnt3fadsdzvyuatqtfei"},
{[]byte{223, 236, 3, 14, 32, 79, 15, 89, 216, 15, 29, 94, 233, 29, 253,
6, 109, 127, 99, 189},
"t24dd4ox4c2vpf5vk5wkadgyyn6qtuvgcpxxon64a"},
{[]byte{61, 58, 137, 232, 221, 171, 84, 120, 50, 113, 108, 109, 70, 140,
53, 96, 201, 244, 127, 216},
"t2gfvuyh7v2sx3patm5k23wdzmhyhtmqctasbr23y"},
}
for _, tc := range testCases {
tc := tc
t.Run(fmt.Sprintf("testing Actor address: %s", tc.expected), func(t *testing.T) {
assert := assert.New(t)
// Round trip encoding and decoding from string
addr, err := NewActorAddress(tc.input)
assert.NoError(err)
assert.Equal(tc.expected, addr.String())
maybeAddr, err := NewFromString(tc.expected)
assert.NoError(err)
assert.Equal(Actor, maybeAddr.Protocol())
assert.Equal(addressHash(tc.input), maybeAddr.Payload())
// Round trip to and from bytes
maybeAddrBytes, err := NewFromBytes(maybeAddr.Bytes())
assert.NoError(err)
assert.Equal(maybeAddr, maybeAddrBytes)
// Round trip encoding and decoding json
b, err := addr.MarshalJSON()
assert.NoError(err)
var newAddr Address
err = newAddr.UnmarshalJSON(b)
assert.NoError(err)
assert.Equal(addr, newAddr)
})
}
}
func TestRandomBLSAddress(t *testing.T) {
assert := assert.New(t)
pk := ffi.PrivateKeyPublicKey(ffi.PrivateKeyGenerate())
addr, err := NewBLSAddress(pk[:])
assert.NoError(err)
assert.Equal(BLS, addr.Protocol())
str, err := encode(Mainnet, addr)
assert.NoError(err)
maybe, err := decode(str)
assert.NoError(err)
assert.Equal(addr, maybe)
}
func TestVectorBLSAddress(t *testing.T) {
testCases := []struct {
input []byte
expected string
}{
{[]byte{173, 88, 223, 105, 110, 45, 78, 145, 234, 134, 200, 129, 233, 56,
186, 78, 168, 27, 57, 94, 18, 121, 123, 132, 185, 207, 49, 75, 149, 70,
112, 94, 131, 156, 122, 153, 214, 6, 178, 71, 221, 180, 249, 172, 122,
52, 20, 221},
"t3vvmn62lofvhjd2ugzca6sof2j2ubwok6cj4xxbfzz4yuxfkgobpihhd2thlanmsh3w2ptld2gqkn2jvlss4a"},
{[]byte{179, 41, 79, 10, 46, 41, 224, 198, 110, 188, 35, 93, 47, 237,
202, 86, 151, 191, 120, 74, 246, 5, 199, 90, 246, 8, 230, 166, 61, 92,
211, 142, 168, 92, 168, 152, 158, 14, 253, 233, 24, 139, 56, 47,
147, 114, 70, 13},
"t3wmuu6crofhqmm3v4enos73okk2l366ck6yc4owxwbdtkmpk42ohkqxfitcpa57pjdcftql4tojda2poeruwa"},
{[]byte{150, 161, 163, 228, 234, 122, 20, 212, 153, 133, 230, 97, 178,
36, 1, 212, 79, 237, 64, 45, 29, 9, 37, 178, 67, 201, 35, 88, 156,
15, 188, 126, 50, 205, 4, 226, 158, 215, 141, 21, 211, 125, 58, 170,
63, 230, 218, 51},
"t3s2q2hzhkpiknjgmf4zq3ejab2rh62qbndueslmsdzervrhapxr7dftie4kpnpdiv2n6tvkr743ndhrsw6d3a"},
{[]byte{134, 180, 84, 37, 140, 88, 148, 117, 247, 209, 111, 90, 172, 1,
138, 121, 246, 193, 22, 157, 32, 252, 51, 146, 29, 216, 181, 206, 28,
172, 108, 52, 143, 144, 163, 96, 54, 36, 246, 174, 185, 27, 100, 81,
140, 46, 128, 149},
"t3q22fijmmlckhl56rn5nkyamkph3mcfu5ed6dheq53c244hfmnq2i7efdma3cj5voxenwiummf2ajlsbxc65a"},
{[]byte{167, 114, 107, 3, 128, 34, 247, 90, 56, 70, 23, 88, 83, 96, 206,
230, 41, 7, 10, 45, 157, 40, 113, 41, 101, 229, 242, 110, 204, 64,
133, 131, 130, 128, 55, 36, 237, 52, 242, 114, 3, 54, 240, 157, 182,
49, 240, 116},
"t3u5zgwa4ael3vuocgc5mfgygo4yuqocrntuuhcklf4xzg5tcaqwbyfabxetwtj4tsam3pbhnwghyhijr5mixa"},
}
for _, tc := range testCases {
tc := tc
t.Run(fmt.Sprintf("testing bls address: %s", tc.expected), func(t *testing.T) {
assert := assert.New(t)
// Round trip encoding and decoding from string
addr, err := NewBLSAddress(tc.input)
assert.NoError(err)
assert.Equal(tc.expected, addr.String())
maybeAddr, err := NewFromString(tc.expected)
assert.NoError(err)
assert.Equal(BLS, maybeAddr.Protocol())
assert.Equal(tc.input, maybeAddr.Payload())
// Round trip to and from bytes
maybeAddrBytes, err := NewFromBytes(maybeAddr.Bytes())
assert.NoError(err)
assert.Equal(maybeAddr, maybeAddrBytes)
// Round trip encoding and decoding json
b, err := addr.MarshalJSON()
assert.NoError(err)
var newAddr Address
err = newAddr.UnmarshalJSON(b)
assert.NoError(err)
assert.Equal(addr, newAddr)
})
}
}
func TestInvalidStringAddresses(t *testing.T) {
testCases := []struct {
input string
expetErr error
}{
{"Q2gfvuyh7v2sx3patm5k23wdzmhyhtmqctasbr23y", ErrUnknownNetwork},
{"t4gfvuyh7v2sx3patm5k23wdzmhyhtmqctasbr23y", ErrUnknownProtocol},
{"t2gfvuyh7v2sx3patm5k23wdzmhyhtmqctasbr24y", ErrInvalidChecksum},
{"t0banananananannnnnnnnn", ErrInvalidLength},
{"t0banananananannnnnnnn", ErrInvalidPayload},
{"t2gfvuyh7v2sx3patm1k23wdzmhyhtmqctasbr24y", base32.CorruptInputError(16)}, // '1' is not in base32 alphabet
{"t2gfvuyh7v2sx3paTm1k23wdzmhyhtmqctasbr24y", base32.CorruptInputError(14)}, // 'T' is not in base32 alphabet
{"t2", ErrInvalidLength},
}
for _, tc := range testCases {
tc := tc
t.Run(fmt.Sprintf("testing string address: %s", tc.expetErr), func(t *testing.T) {
assert := assert.New(t)
_, err := NewFromString(tc.input)
assert.Equal(tc.expetErr, err)
})
}
}
func TestInvalidByteAddresses(t *testing.T) {
testCases := []struct {
input []byte
expetErr error
}{
// Unknown Protocol
{[]byte{4, 4, 4}, ErrUnknownProtocol},
// ID protocol
{[]byte{0}, ErrInvalidLength},
// SECP256K1 Protocol
{append([]byte{1}, make([]byte, PayloadHashLength-1)...), ErrInvalidPayload},
{append([]byte{1}, make([]byte, PayloadHashLength+1)...), ErrInvalidPayload},
// Actor Protocol
{append([]byte{2}, make([]byte, PayloadHashLength-1)...), ErrInvalidPayload},
{append([]byte{2}, make([]byte, PayloadHashLength+1)...), ErrInvalidPayload},
// BLS Protocol
{append([]byte{3}, make([]byte, ffi.PublicKeyBytes-1)...), ErrInvalidPayload},
{append([]byte{3}, make([]byte, ffi.PrivateKeyBytes+1)...), ErrInvalidPayload},
}
for _, tc := range testCases {
tc := tc
t.Run(fmt.Sprintf("testing byte address: %s", tc.expetErr), func(t *testing.T) {
assert := assert.New(t)
_, err := NewFromBytes(tc.input)
assert.Equal(tc.expetErr, err)
})
}
}
func TestChecksum(t *testing.T) {
assert := assert.New(t)
data := []byte("helloworld")
bata := []byte("kittinmittins")
cksm := Checksum(data)
assert.Len(cksm, ChecksumHashLength)
assert.True(ValidateChecksum(data, cksm))
assert.False(ValidateChecksum(bata, cksm))
}
func TestAddressFormat(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
a, err := NewActorAddress([]byte("hello"))
require.NoError(err)
assert.Equal("t2wvjry4bx6bwj6kkhcmvgu5zafqyi5cjzbtet3va", a.String())
assert.Equal("02B5531C7037F06C9F2947132A6A77202C308E8939", fmt.Sprintf("%X", a))
assert.Equal("[2 - b5531c7037f06c9f2947132a6a77202c308e8939]", fmt.Sprintf("%v", a))
assert.Equal("", fmt.Sprintf("%X", Undef))
assert.Equal(UndefAddressString, Undef.String())
assert.Equal(UndefAddressString, fmt.Sprintf("%v", Undef))
}
func TestCborMarshal(t *testing.T) {
for _, a := range allTestAddresses {
addr, err := NewFromString(a)
if err != nil {
t.Fatal(err)
}
buf := new(bytes.Buffer)
if err := addr.MarshalCBOR(buf); err != nil {
t.Fatal(err)
}
/*
// Note: this is commented out because we're currently serializing addresses as cbor "text strings", not "byte strings".
// This is to get around the restriction that refmt only allows string keys in maps.
// if you change it to serialize to byte strings and uncomment this, the tests pass fine
oldbytes, err := cbor.DumpObject(addr)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(oldbytes, buf.Bytes()) {
t.Fatalf("serialization doesnt match old serialization: %s", a)
}
*/
var out Address
if err := out.UnmarshalCBOR(buf); err != nil {
t.Fatal(err)
}
if out != addr {
t.Fatalf("failed to round trip %s", a)
}
}
}
func BenchmarkCborMarshal(b *testing.B) {
addr, err := NewFromString("t15ihq5ibzwki2b4ep2f46avlkrqzhpqgtga7pdrq")
if err != nil {
b.Fatal(err)
}
b.ReportAllocs()
b.ResetTimer()
buf := new(bytes.Buffer)
for i := 0; i < b.N; i++ {
buf.Reset()
if err := addr.MarshalCBOR(buf); err != nil {
b.Fatal(err)
}
}
}
func BenchmarkCborUnmarshal(b *testing.B) {
addr, err := NewFromString("t15ihq5ibzwki2b4ep2f46avlkrqzhpqgtga7pdrq")
if err != nil {
b.Fatal(err)
}
buf := new(bytes.Buffer)
if err := addr.MarshalCBOR(buf); err != nil {
b.Fatal(err)
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
var a Address
if err := a.UnmarshalCBOR(bytes.NewReader(buf.Bytes())); err != nil {
b.Fatal(err)
}
}
}
func TestIDEdgeCase(t *testing.T) {
a, err := NewFromBytes([]byte{0, 0x80})
_ = a.String()
assert.Error(t, err)
}

View File

@ -1,94 +0,0 @@
package address
import (
"fmt"
"math/rand"
"testing"
)
func blsaddr(n int64) Address {
buf := make([]byte, 48)
r := rand.New(rand.NewSource(n))
r.Read(buf)
addr, err := NewBLSAddress(buf)
if err != nil {
panic(err) // ok
}
return addr
}
func makeActorAddresses(n int) [][]byte {
var addrs [][]byte
for i := 0; i < n; i++ {
a, err := NewActorAddress([]byte(fmt.Sprintf("ACTOR ADDRESS %d", i)))
if err != nil {
panic(err) // ok
}
addrs = append(addrs, a.Bytes())
}
return addrs
}
func makeBlsAddresses(n int64) [][]byte {
var addrs [][]byte
for i := int64(0); i < n; i++ {
addrs = append(addrs, blsaddr(n).Bytes())
}
return addrs
}
func makeSecpAddresses(n int) [][]byte {
var addrs [][]byte
for i := 0; i < n; i++ {
r := rand.New(rand.NewSource(int64(i)))
buf := make([]byte, 32)
r.Read(buf)
a, err := NewSecp256k1Address(buf)
if err != nil {
panic(err) // ok
}
addrs = append(addrs, a.Bytes())
}
return addrs
}
func makeIDAddresses(n int) [][]byte {
var addrs [][]byte
for i := 0; i < n; i++ {
a, err := NewIDAddress(uint64(i))
if err != nil {
panic(err) // ok
}
addrs = append(addrs, a.Bytes())
}
return addrs
}
func BenchmarkParseActorAddress(b *testing.B) {
benchTestWithAddrs := func(a [][]byte) func(b *testing.B) {
return func(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := NewFromBytes(a[i%len(a)])
if err != nil {
b.Fatal(err)
}
}
}
}
b.Run("actor", benchTestWithAddrs(makeActorAddresses(20)))
b.Run("bls", benchTestWithAddrs(makeBlsAddresses(20)))
b.Run("secp256k1", benchTestWithAddrs(makeSecpAddresses(20)))
b.Run("id", benchTestWithAddrs(makeIDAddresses(20)))
}

View File

@ -1,65 +0,0 @@
package address
import (
"encoding/base32"
"errors"
"github.com/minio/blake2b-simd"
)
func init() {
var err error
TestAddress, err = NewActorAddress([]byte("satoshi"))
if err != nil {
panic(err)
}
TestAddress2, err = NewActorAddress([]byte("nakamoto"))
if err != nil {
panic(err)
}
}
var (
// TestAddress is an account with some initial funds in it.
TestAddress Address
// TestAddress2 is an account with some initial funds in it.
TestAddress2 Address
)
var (
// ErrUnknownNetwork is returned when encountering an unknown network in an address.
ErrUnknownNetwork = errors.New("unknown address network")
// ErrUnknownProtocol is returned when encountering an unknown protocol in an address.
ErrUnknownProtocol = errors.New("unknown address protocol")
// ErrInvalidPayload is returned when encountering an invalid address payload.
ErrInvalidPayload = errors.New("invalid address payload")
// ErrInvalidLength is returned when encountering an address of invalid length.
ErrInvalidLength = errors.New("invalid address length")
// ErrInvalidChecksum is returned when encountering an invalid address checksum.
ErrInvalidChecksum = errors.New("invalid address checksum")
)
// UndefAddressString is the string used to represent an empty address when encoded to a string.
var UndefAddressString = "<empty>"
// PayloadHashLength defines the hash length taken over addresses using the Actor and SECP256K1 protocols.
const PayloadHashLength = 20
// ChecksumHashLength defines the hash length used for calculating address checksums.
const ChecksumHashLength = 4
// MaxAddressStringLength is the max length of an address encoded as a string
// it include the network prefx, protocol, and bls publickey
const MaxAddressStringLength = 2 + 84
var payloadHashConfig = &blake2b.Config{Size: PayloadHashLength}
var checksumHashConfig = &blake2b.Config{Size: ChecksumHashLength}
const encodeStd = "abcdefghijklmnopqrstuvwxyz234567"
// AddressEncoding defines the base32 config used for address encoding and decoding.
var AddressEncoding = base32.NewEncoding(encodeStd)

View File

@ -1,20 +0,0 @@
package address
import (
"fmt"
)
// NewForTestGetter returns a closure that returns an address unique to that invocation.
// The address is unique wrt the closure returned, not globally.
func NewForTestGetter() func() Address {
i := 0
return func() Address {
s := fmt.Sprintf("address%d", i)
i++
newAddr, err := NewActorAddress([]byte(s))
if err != nil {
panic(err)
}
return newAddr
}
}

View File

@ -0,0 +1,71 @@
package chain
import (
"sort"
"sync"
"time"
"github.com/filecoin-project/lotus/chain/types"
"github.com/hashicorp/golang-lru"
peer "github.com/libp2p/go-libp2p-core/peer"
)
type blockReceiptTracker struct {
lk sync.Mutex
// using an LRU cache because i don't want to handle all the edge cases for
// manual cleanup and maintenance of a fixed size set
cache *lru.Cache
}
type peerSet struct {
peers map[peer.ID]time.Time
}
func newBlockReceiptTracker() *blockReceiptTracker {
c, _ := lru.New(512)
return &blockReceiptTracker{
cache: c,
}
}
func (brt *blockReceiptTracker) Add(p peer.ID, ts *types.TipSet) {
brt.lk.Lock()
defer brt.lk.Unlock()
val, ok := brt.cache.Get(ts.Key())
if !ok {
pset := &peerSet{
peers: map[peer.ID]time.Time{
p: time.Now(),
},
}
brt.cache.Add(ts.Key(), pset)
return
}
val.(*peerSet).peers[p] = time.Now()
}
func (brt *blockReceiptTracker) GetPeers(ts *types.TipSet) []peer.ID {
brt.lk.Lock()
defer brt.lk.Unlock()
val, ok := brt.cache.Get(ts.Key())
if !ok {
return nil
}
ps := val.(*peerSet)
out := make([]peer.ID, 0, len(ps.peers))
for p := range ps.peers {
out = append(out, p)
}
sort.Slice(out, func(i, j int) bool {
return ps.peers[out[i]].Before(ps.peers[out[j]])
})
return out
}

View File

@ -8,9 +8,9 @@ import (
"go.opencensus.io/trace"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/cborutil"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
@ -90,7 +90,7 @@ func (bss *BlockSyncService) HandleStream(s inet.Stream) {
var req BlockSyncRequest
if err := cborutil.ReadCborRPC(bufio.NewReader(s), &req); err != nil {
log.Errorf("failed to read block sync request: %s", err)
log.Warnf("failed to read block sync request: %s", err)
return
}
log.Infof("block sync request for: %s %d", req.Start, req.RequestLength)
@ -102,7 +102,7 @@ func (bss *BlockSyncService) HandleStream(s inet.Stream) {
}
if err := cborutil.WriteCborRPC(s, resp); err != nil {
log.Error("failed to write back response for handle stream: ", err)
log.Warn("failed to write back response for handle stream: ", err)
return
}
}
@ -124,7 +124,7 @@ func (bss *BlockSyncService) processRequest(ctx context.Context, req *BlockSyncR
trace.BoolAttribute("messages", opts.IncludeMessages),
)
chain, err := bss.collectChainSegment(req.Start, req.RequestLength, opts)
chain, err := bss.collectChainSegment(types.NewTipSetKey(req.Start...), req.RequestLength, opts)
if err != nil {
log.Warn("encountered error while responding to block sync request: ", err)
return &BlockSyncResponse{
@ -139,7 +139,7 @@ func (bss *BlockSyncService) processRequest(ctx context.Context, req *BlockSyncR
}, nil
}
func (bss *BlockSyncService) collectChainSegment(start []cid.Cid, length uint64, opts *BSOptions) ([]*BSTipSet, error) {
func (bss *BlockSyncService) collectChainSegment(start types.TipSetKey, length uint64, opts *BSOptions) ([]*BSTipSet, error) {
var bstips []*BSTipSet
cur := start
for {

View File

@ -18,9 +18,9 @@ import (
"go.opencensus.io/trace"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/cborutil"
"github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/peermgr"
)
@ -59,18 +59,18 @@ func (bs *BlockSync) processStatus(req *BlockSyncRequest, res *BlockSyncResponse
}
}
func (bs *BlockSync) GetBlocks(ctx context.Context, tipset []cid.Cid, count int) ([]*types.TipSet, error) {
func (bs *BlockSync) GetBlocks(ctx context.Context, tsk types.TipSetKey, count int) ([]*types.TipSet, error) {
ctx, span := trace.StartSpan(ctx, "bsync.GetBlocks")
defer span.End()
if span.IsRecordingEvents() {
span.AddAttributes(
trace.StringAttribute("tipset", fmt.Sprint(tipset)),
trace.StringAttribute("tipset", fmt.Sprint(tsk.Cids())),
trace.Int64Attribute("count", int64(count)),
)
}
req := &BlockSyncRequest{
Start: tipset,
Start: tsk.Cids(),
RequestLength: uint64(count),
Options: BSOptBlocks,
}
@ -94,13 +94,20 @@ func (bs *BlockSync) GetBlocks(ctx context.Context, tipset []cid.Cid, count int)
res, err := bs.sendRequestToPeer(ctx, p, req)
if err != nil {
oerr = err
log.Warnf("BlockSync request failed for peer %s: %s", p.String(), err)
if !xerrors.Is(err, inet.ErrNoConn) {
log.Warnf("BlockSync request failed for peer %s: %s", p.String(), err)
}
continue
}
if res.Status == 0 {
resp, err := bs.processBlocksResponse(req, res)
if err != nil {
return nil, xerrors.Errorf("success response from peer failed to process: %w", err)
}
bs.syncPeers.logGlobalSuccess(time.Since(start))
return bs.processBlocksResponse(req, res)
bs.host.ConnManager().TagPeer(p, "bsync", 25)
return resp, nil
}
oerr = bs.processStatus(req, res)
if oerr != nil {
@ -110,11 +117,11 @@ func (bs *BlockSync) GetBlocks(ctx context.Context, tipset []cid.Cid, count int)
return nil, xerrors.Errorf("GetBlocks failed with all peers: %w", oerr)
}
func (bs *BlockSync) GetFullTipSet(ctx context.Context, p peer.ID, h []cid.Cid) (*store.FullTipSet, error) {
func (bs *BlockSync) GetFullTipSet(ctx context.Context, p peer.ID, tsk types.TipSetKey) (*store.FullTipSet, error) {
// TODO: round robin through these peers on error
req := &BlockSyncRequest{
Start: h,
Start: tsk.Cids(),
RequestLength: 1,
Options: BSOptBlocks | BSOptMessages,
}
@ -262,6 +269,10 @@ func (bs *BlockSync) sendRequestToPeer(ctx context.Context, p peer.ID, req *Bloc
}
func (bs *BlockSync) processBlocksResponse(req *BlockSyncRequest, res *BlockSyncResponse) ([]*types.TipSet, error) {
if len(res.Chain) == 0 {
return nil, xerrors.Errorf("got no blocks in successful blocksync response")
}
cur, err := types.NewTipSet(res.Chain[0].Blocks)
if err != nil {
return nil, err
@ -275,7 +286,7 @@ func (bs *BlockSync) processBlocksResponse(req *BlockSyncRequest, res *BlockSync
return nil, err
}
if !types.CidArrsEqual(cur.Parents(), nts.Cids()) {
if !types.CidArrsEqual(cur.Parents().Cids(), nts.Cids()) {
return nil, fmt.Errorf("parents of tipset[%d] were not tipset[%d]", bi-1, bi)
}

View File

@ -5,7 +5,7 @@ import (
"io"
"github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-cid"
cid "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
xerrors "golang.org/x/xerrors"
)
@ -24,6 +24,10 @@ func (t *BlockSyncRequest) MarshalCBOR(w io.Writer) error {
}
// t.Start ([]cid.Cid) (slice)
if len(t.Start) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.Start was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Start)))); err != nil {
return err
}
@ -119,6 +123,10 @@ func (t *BlockSyncResponse) MarshalCBOR(w io.Writer) error {
}
// t.Chain ([]*blocksync.BSTipSet) (slice)
if len(t.Chain) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.Chain was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Chain)))); err != nil {
return err
}
@ -134,6 +142,10 @@ func (t *BlockSyncResponse) MarshalCBOR(w io.Writer) error {
}
// t.Message (string) (string)
if len(t.Message) > cbg.MaxLength {
return xerrors.Errorf("Value in field t.Message was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.Message)))); err != nil {
return err
}
@ -218,6 +230,10 @@ func (t *BSTipSet) MarshalCBOR(w io.Writer) error {
}
// t.Blocks ([]*types.BlockHeader) (slice)
if len(t.Blocks) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.Blocks was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Blocks)))); err != nil {
return err
}
@ -228,6 +244,10 @@ func (t *BSTipSet) MarshalCBOR(w io.Writer) error {
}
// t.BlsMessages ([]*types.Message) (slice)
if len(t.BlsMessages) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.BlsMessages was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.BlsMessages)))); err != nil {
return err
}
@ -238,10 +258,18 @@ func (t *BSTipSet) MarshalCBOR(w io.Writer) error {
}
// t.BlsMsgIncludes ([][]uint64) (slice)
if len(t.BlsMsgIncludes) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.BlsMsgIncludes was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.BlsMsgIncludes)))); err != nil {
return err
}
for _, v := range t.BlsMsgIncludes {
if len(v) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field v was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(v)))); err != nil {
return err
}
@ -253,6 +281,10 @@ func (t *BSTipSet) MarshalCBOR(w io.Writer) error {
}
// t.SecpkMessages ([]*types.SignedMessage) (slice)
if len(t.SecpkMessages) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.SecpkMessages was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.SecpkMessages)))); err != nil {
return err
}
@ -263,10 +295,18 @@ func (t *BSTipSet) MarshalCBOR(w io.Writer) error {
}
// t.SecpkMsgIncludes ([][]uint64) (slice)
if len(t.SecpkMsgIncludes) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.SecpkMsgIncludes was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.SecpkMsgIncludes)))); err != nil {
return err
}
for _, v := range t.SecpkMsgIncludes {
if len(v) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field v was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(v)))); err != nil {
return err
}

View File

@ -202,6 +202,10 @@ func (t *Response) MarshalCBOR(w io.Writer) error {
}
// t.Message (string) (string)
if len(t.Message) > cbg.MaxLength {
return xerrors.Errorf("Value in field t.Message was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.Message)))); err != nil {
return err
}
@ -408,6 +412,10 @@ func (t *ClientDealProposal) MarshalCBOR(w io.Writer) error {
}
// t.MinerID (peer.ID) (string)
if len(t.MinerID) > cbg.MaxLength {
return xerrors.Errorf("Value in field t.MinerID was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.MinerID)))); err != nil {
return err
}
@ -539,6 +547,10 @@ func (t *ClientDeal) MarshalCBOR(w io.Writer) error {
}
// t.Miner (peer.ID) (string)
if len(t.Miner) > cbg.MaxLength {
return xerrors.Errorf("Value in field t.Miner was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.Miner)))); err != nil {
return err
}
@ -672,6 +684,10 @@ func (t *MinerDeal) MarshalCBOR(w io.Writer) error {
}
// t.Client (peer.ID) (string)
if len(t.Client) > cbg.MaxLength {
return xerrors.Errorf("Value in field t.Client was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.Client)))); err != nil {
return err
}

View File

@ -10,17 +10,17 @@ import (
"github.com/libp2p/go-libp2p-core/peer"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/go-statestore"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/events"
"github.com/filecoin-project/lotus/chain/market"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/lotus/lib/cborutil"
"github.com/filecoin-project/lotus/lib/statestore"
"github.com/filecoin-project/lotus/node/impl/full"
"github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/retrieval/discovery"
@ -259,7 +259,7 @@ func (c *Client) Start(ctx context.Context, p ClientDealProposal) (cid.Cid, erro
func (c *Client) QueryAsk(ctx context.Context, p peer.ID, a address.Address) (*types.SignedStorageAsk, error) {
s, err := c.h.NewStream(ctx, p, AskProtocolID)
if err != nil {
return nil, err
return nil, xerrors.Errorf("failed to open stream to miner: %w", err)
}
req := &AskRequest{

View File

@ -6,12 +6,12 @@ import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/cborutil"
)
type clientHandlerFunc func(ctx context.Context, deal ClientDeal) (func(*ClientDeal), error)

View File

@ -5,6 +5,7 @@ import (
"context"
"runtime"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
"github.com/ipfs/go-cid"
files "github.com/ipfs/go-ipfs-files"
unixfile "github.com/ipfs/go-unixfs/file"
@ -12,11 +13,11 @@ import (
"github.com/libp2p/go-libp2p-core/peer"
"golang.org/x/xerrors"
cborutil "github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/go-statestore"
"github.com/filecoin-project/lotus/datatransfer"
"github.com/filecoin-project/lotus/lib/cborutil"
"github.com/filecoin-project/lotus/lib/padreader"
"github.com/filecoin-project/lotus/lib/sectorbuilder"
"github.com/filecoin-project/lotus/lib/statestore"
"github.com/filecoin-project/lotus/node/modules/dtypes"
)

View File

@ -12,13 +12,13 @@ import (
"github.com/libp2p/go-libp2p-core/peer"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/go-statestore"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/datatransfer"
"github.com/filecoin-project/lotus/lib/cborutil"
"github.com/filecoin-project/lotus/lib/statestore"
"github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/filecoin-project/lotus/storage"
"github.com/filecoin-project/lotus/storage/sectorblocks"

View File

@ -5,10 +5,10 @@ import (
"context"
"time"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/cborutil"
datastore "github.com/ipfs/go-datastore"
inet "github.com/libp2p/go-libp2p-core/network"
"golang.org/x/xerrors"

View File

@ -10,11 +10,11 @@ import (
"github.com/filecoin-project/lotus/node/modules/dtypes"
"github.com/ipld/go-ipld-prime"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/go-statestore"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/cborutil"
"github.com/filecoin-project/lotus/lib/statestore"
"github.com/ipfs/go-cid"
inet "github.com/libp2p/go-libp2p-core/network"

View File

@ -13,13 +13,13 @@ import (
"github.com/libp2p/go-libp2p-core/peer"
xerrors "golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/go-statestore"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/deals"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/cborutil"
"github.com/filecoin-project/lotus/lib/statestore"
)
var blockGenerator = blocksutil.NewBlockGenerator()

View File

@ -4,11 +4,11 @@ import (
"bytes"
"errors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/cborutil"
"github.com/ipfs/go-cid"
)

View File

@ -9,9 +9,9 @@ import (
logging "github.com/ipfs/go-log"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
)

View File

@ -13,8 +13,8 @@ import (
"github.com/multiformats/go-multihash"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
)

View File

@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types"
)

View File

@ -11,6 +11,7 @@ import (
ffi "github.com/filecoin-project/filecoin-ffi"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
"github.com/ipfs/go-blockservice"
"github.com/ipfs/go-car"
offline "github.com/ipfs/go-ipfs-exchange-offline"
@ -19,16 +20,15 @@ import (
"go.opencensus.io/trace"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/lotus/cmd/lotus-seed/seed"
"github.com/filecoin-project/lotus/genesis"
"github.com/filecoin-project/lotus/lib/sectorbuilder"
"github.com/filecoin-project/lotus/node/repo"
block "github.com/ipfs/go-block-format"

View File

@ -10,7 +10,7 @@ import (
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"

View File

@ -15,9 +15,9 @@ import (
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build"
actors "github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"

View File

@ -6,8 +6,8 @@ import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/impl/full"

View File

@ -19,9 +19,9 @@ import (
"go.uber.org/multierr"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
@ -109,7 +109,7 @@ type Provider interface {
StateGetActor(address.Address, *types.TipSet) (*types.Actor, error)
MessagesForBlock(*types.BlockHeader) ([]*types.Message, []*types.SignedMessage, error)
MessagesForTipset(*types.TipSet) ([]store.ChainMsg, error)
LoadTipSet(cids []cid.Cid) (*types.TipSet, error)
LoadTipSet(tsk types.TipSetKey) (*types.TipSet, error)
}
type mpoolProvider struct {
@ -146,8 +146,8 @@ func (mpp *mpoolProvider) MessagesForTipset(ts *types.TipSet) ([]store.ChainMsg,
return mpp.sm.ChainStore().MessagesForTipset(ts)
}
func (mpp *mpoolProvider) LoadTipSet(cids []cid.Cid) (*types.TipSet, error) {
return mpp.sm.ChainStore().LoadTipSet(cids)
func (mpp *mpoolProvider) LoadTipSet(tsk types.TipSetKey) (*types.TipSet, error) {
return mpp.sm.ChainStore().LoadTipSet(tsk)
}
func New(api Provider, ds dtypes.MetadataDS) (*MessagePool, error) {
@ -263,24 +263,24 @@ func (mp *MessagePool) addLocal(m *types.SignedMessage, msgb []byte) error {
return nil
}
func (mp *MessagePool) Push(m *types.SignedMessage) error {
func (mp *MessagePool) Push(m *types.SignedMessage) (cid.Cid, error) {
msgb, err := m.Serialize()
if err != nil {
return err
return cid.Undef, err
}
if err := mp.Add(m); err != nil {
return err
return cid.Undef, err
}
mp.lk.Lock()
if err := mp.addLocal(m, msgb); err != nil {
mp.lk.Unlock()
return err
return cid.Undef, err
}
mp.lk.Unlock()
return mp.api.PubSubPublish(msgTopic, msgb)
return m.Cid(), mp.api.PubSubPublish(msgTopic, msgb)
}
func (mp *MessagePool) Add(m *types.SignedMessage) error {

View File

@ -4,7 +4,7 @@ import (
"fmt"
"testing"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/types/mock"
@ -98,9 +98,9 @@ func (tma *testMpoolApi) MessagesForTipset(ts *types.TipSet) ([]store.ChainMsg,
return out, nil
}
func (tma *testMpoolApi) LoadTipSet(cids []cid.Cid) (*types.TipSet, error) {
func (tma *testMpoolApi) LoadTipSet(tsk types.TipSetKey) (*types.TipSet, error) {
for _, ts := range tma.tipsets {
if types.CidArrsEqual(cids, ts.Cids()) {
if types.CidArrsEqual(tsk.Cids(), ts.Cids()) {
return ts, nil
}
}

View File

@ -9,8 +9,8 @@ import (
logging "github.com/ipfs/go-log"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
)

View File

@ -3,8 +3,8 @@ package state
import (
"testing"
address "github.com/filecoin-project/go-address"
actors "github.com/filecoin-project/lotus/chain/actors"
address "github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
hamt "github.com/ipfs/go-hamt-ipld"
)

View File

@ -0,0 +1,127 @@
package stmgr
import (
"context"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-amt-ipld"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-hamt-ipld"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types"
)
func (sm *StateManager) forkNoPowerEPS(ctx context.Context, pstate cid.Cid) (cid.Cid, error) {
cst := hamt.CSTFromBstore(sm.cs.Blockstore())
st, err := state.LoadStateTree(cst, pstate)
if err != nil {
return cid.Undef, xerrors.Errorf("loading parent state tree: %w", err)
}
if err := st.MutateActor(actors.StoragePowerAddress, func(spa *types.Actor) error {
var head actors.StoragePowerState
if err := cst.Get(ctx, spa.Head, &head); err != nil {
return xerrors.Errorf("reading StoragePower state: %w", err)
}
buckets, err := amt.LoadAMT(amt.WrapBlockstore(sm.cs.Blockstore()), head.ProvingBuckets)
if err != nil {
return xerrors.Errorf("opening proving buckets AMT: %w", err)
}
fixedBuckets := map[uint64]map[address.Address]struct{}{}
if err := buckets.ForEach(func(bucketId uint64, ent *typegen.Deferred) error {
var bcid cid.Cid
if err := cbor.DecodeInto(ent.Raw, &bcid); err != nil {
return xerrors.Errorf("decoding bucket cid: %w", err)
}
bucket, err := hamt.LoadNode(ctx, cst, bcid)
if err != nil {
return xerrors.Errorf("loading bucket hamt: %w", err)
}
return bucket.ForEach(ctx, func(abytes string, _ interface{}) error {
addr, err := address.NewFromBytes([]byte(abytes))
if err != nil {
return xerrors.Errorf("parsing address in proving bucket: %w", err)
}
// now find the correct bucket
miner, err := st.GetActor(addr)
if err != nil {
return xerrors.Errorf("getting miner %s: %w", addr, err)
}
var minerHead actors.StorageMinerActorState
if err := cst.Get(ctx, miner.Head, &minerHead); err != nil {
return xerrors.Errorf("reading miner %s state: %w", addr, err)
}
correctBucket := minerHead.ElectionPeriodStart % build.SlashablePowerDelay
if correctBucket != bucketId {
log.Warnf("miner %s was in wrong proving bucket %d, putting in %d (eps: %d)", addr, bucketId, correctBucket, minerHead.ElectionPeriodStart)
}
if _, ok := fixedBuckets[correctBucket]; !ok {
fixedBuckets[correctBucket] = map[address.Address]struct{}{}
}
fixedBuckets[correctBucket][addr] = struct{}{}
return nil
})
}); err != nil {
return err
}
// /////
// Write fixed buckets
fixed := amt.NewAMT(amt.WrapBlockstore(sm.cs.Blockstore()))
for bucketId, addrss := range fixedBuckets {
bucket := hamt.NewNode(cst)
for addr := range addrss {
if err := bucket.Set(ctx, string(addr.Bytes()), actors.CborNull); err != nil {
return xerrors.Errorf("setting address in bucket: %w", err)
}
}
if err := bucket.Flush(ctx); err != nil {
return xerrors.Errorf("flushing bucket amt: %w", err)
}
bcid, err := cst.Put(context.TODO(), bucket)
if err != nil {
return xerrors.Errorf("put bucket: %w", err)
}
if err := fixed.Set(bucketId, bcid); err != nil {
return xerrors.Errorf("set bucket: %w", err)
}
}
head.ProvingBuckets, err = fixed.Flush()
if err != nil {
return xerrors.Errorf("flushing bucket amt: %w", err)
}
spa.Head, err = cst.Put(ctx, &head)
if err != nil {
return xerrors.Errorf("putting actor head: %w", err)
}
return nil
}); err != nil {
return cid.Undef, err
}
return st.Flush()
}

25
chain/stmgr/forks.go Normal file
View File

@ -0,0 +1,25 @@
package stmgr
import (
"context"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/build"
)
func (sm *StateManager) handleStateForks(ctx context.Context, pstate cid.Cid, height, parentH uint64) (_ cid.Cid, err error) {
for i := parentH; i < height; i++ {
switch i {
case build.ForkNoPowerEPSUpdates:
pstate, err = sm.forkNoPowerEPS(ctx, pstate)
if err != nil {
return cid.Undef, xerrors.Errorf("executing state fork in epoch %d: %w", i, err)
}
log.Infof("forkNoPowerEPS state: %s", pstate)
}
}
return pstate, nil
}

View File

@ -5,9 +5,9 @@ import (
"fmt"
"sync"
"github.com/filecoin-project/go-address"
amt "github.com/filecoin-project/go-amt-ipld"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
@ -120,6 +120,17 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
}
pstate := blks[0].ParentStateRoot
if len(blks[0].Parents) > 0 { // don't support forks on genesis
parent, err := sm.cs.GetBlock(blks[0].Parents[0])
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("getting parent block: %w", err)
}
pstate, err = sm.handleStateForks(ctx, blks[0].ParentStateRoot, blks[0].Height, parent.Height)
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("error handling state forks: %w", err)
}
}
cids := make([]cid.Cid, len(blks))
for i, v := range blks {

View File

@ -4,12 +4,13 @@ import (
"context"
ffi "github.com/filecoin-project/filecoin-ffi"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sectorbuilder"
amt "github.com/filecoin-project/go-amt-ipld"
cid "github.com/ipfs/go-cid"
@ -270,6 +271,21 @@ func GetStorageDeal(ctx context.Context, sm *StateManager, dealId uint64, ts *ty
return &ocd, nil
}
func ListMinerActors(ctx context.Context, sm *StateManager, ts *types.TipSet) ([]address.Address, error) {
var state actors.StoragePowerState
if _, err := sm.LoadActorState(ctx, actors.StoragePowerAddress, &state, ts); err != nil {
return nil, err
}
cst := hamt.CSTFromBstore(sm.ChainStore().Blockstore())
miners, err := actors.MinerSetList(ctx, cst, state.Miners)
if err != nil {
return nil, err
}
return miners, nil
}
func LoadSectorsFromSet(ctx context.Context, bs blockstore.Blockstore, ssc cid.Cid) ([]*api.ChainSectorInfo, error) {
blks := amt.WrapBlockstore(bs)
a, err := amt.LoadAMT(blks, ssc)

View File

@ -7,8 +7,8 @@ import (
"encoding/json"
"sync"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/vm"
"go.opencensus.io/trace"
@ -50,16 +50,19 @@ type ChainStore struct {
headChangeNotifs []func(rev, app []*types.TipSet) error
mmCache *lru.ARCCache
tsCache *lru.ARCCache
}
func NewChainStore(bs bstore.Blockstore, ds dstore.Batching) *ChainStore {
c, _ := lru.NewARC(2048)
tsc, _ := lru.NewARC(4096)
cs := &ChainStore{
bs: bs,
ds: ds,
bestTips: pubsub.New(64),
tipsets: make(map[uint64][]cid.Cid),
mmCache: c,
tsCache: tsc,
}
cs.reorgCh = cs.reorgWorker(context.TODO())
@ -107,7 +110,7 @@ func (cs *ChainStore) Load() error {
return xerrors.Errorf("failed to unmarshal stored chain head: %w", err)
}
ts, err := cs.LoadTipSet(tscids)
ts, err := cs.LoadTipSet(types.NewTipSetKey(tscids...))
if err != nil {
return xerrors.Errorf("loading tipset: %w", err)
}
@ -336,9 +339,14 @@ func (cs *ChainStore) GetBlock(c cid.Cid) (*types.BlockHeader, error) {
return types.DecodeBlock(sb.RawData())
}
func (cs *ChainStore) LoadTipSet(cids []cid.Cid) (*types.TipSet, error) {
func (cs *ChainStore) LoadTipSet(tsk types.TipSetKey) (*types.TipSet, error) {
v, ok := cs.tsCache.Get(tsk)
if ok {
return v.(*types.TipSet), nil
}
var blks []*types.BlockHeader
for _, c := range cids {
for _, c := range tsk.Cids() {
b, err := cs.GetBlock(c)
if err != nil {
return nil, xerrors.Errorf("get block %s: %w", c, err)
@ -347,7 +355,14 @@ func (cs *ChainStore) LoadTipSet(cids []cid.Cid) (*types.TipSet, error) {
blks = append(blks, b)
}
return types.NewTipSet(blks)
ts, err := types.NewTipSet(blks)
if err != nil {
return nil, err
}
cs.tsCache.Add(tsk, ts)
return ts, nil
}
// returns true if 'a' is an ancestor of 'b'
@ -817,7 +832,7 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, round i
span.AddAttributes(trace.Int64Attribute("round", round))
for {
nts, err := cs.LoadTipSet(blks)
nts, err := cs.LoadTipSet(types.NewTipSetKey(blks...))
if err != nil {
return nil, err
}

68
chain/store/store_test.go Normal file
View File

@ -0,0 +1,68 @@
package store_test
import (
"context"
"testing"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/repo"
blockstore "github.com/ipfs/go-ipfs-blockstore"
)
func init() {
build.SectorSizes = []uint64{1024}
build.MinimumMinerPower = 1024
}
func BenchmarkGetRandomness(b *testing.B) {
cg, err := gen.NewGenerator()
if err != nil {
b.Fatal(err)
}
var last *types.TipSet
for i := 0; i < 2000; i++ {
ts, err := cg.NextTipSet()
if err != nil {
b.Fatal(err)
}
last = ts.TipSet.TipSet()
}
r, err := cg.YieldRepo()
if err != nil {
b.Fatal(err)
}
lr, err := r.Lock(repo.FullNode)
if err != nil {
b.Fatal(err)
}
bds, err := lr.Datastore("/blocks")
if err != nil {
b.Fatal(err)
}
mds, err := lr.Datastore("/metadata")
if err != nil {
b.Fatal(err)
}
bs := blockstore.NewBlockstore(bds)
cs := store.NewChainStore(bs, mds)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := cs.GetRandomness(context.TODO(), last.Cids(), 500)
if err != nil {
b.Fatal(err)
}
}
}

View File

@ -5,6 +5,7 @@ import (
"time"
logging "github.com/ipfs/go-log"
connmgr "github.com/libp2p/go-libp2p-core/connmgr"
pubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/filecoin-project/lotus/chain"
@ -14,7 +15,7 @@ import (
var log = logging.Logger("sub")
func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *chain.Syncer) {
func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *chain.Syncer, cmgr connmgr.ConnManager) {
for {
msg, err := bsub.Next(ctx)
if err != nil {
@ -54,11 +55,14 @@ func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *cha
if delay := time.Now().Unix() - int64(blk.Header.Timestamp); delay > 5 {
log.Warnf("Received block with large delay %d from miner %s", delay, blk.Header.Miner)
}
s.InformNewBlock(msg.GetFrom(), &types.FullBlock{
if s.InformNewBlock(msg.ReceivedFrom, &types.FullBlock{
Header: blk.Header,
BlsMessages: bmsgs,
SecpkMessages: smsgs,
})
}) {
cmgr.TagPeer(msg.ReceivedFrom, "blkprop", 5)
}
}()
}
}

View File

@ -6,34 +6,37 @@ import (
"crypto/sha256"
"errors"
"fmt"
"sync"
"time"
"github.com/Gurpartap/async"
bls "github.com/filecoin-project/filecoin-ffi"
amt "github.com/filecoin-project/go-amt-ipld"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
"github.com/hashicorp/go-multierror"
"github.com/ipfs/go-cid"
dstore "github.com/ipfs/go-datastore"
hamt "github.com/ipfs/go-hamt-ipld"
bstore "github.com/ipfs/go-ipfs-blockstore"
logging "github.com/ipfs/go-log"
"github.com/libp2p/go-libp2p-core/connmgr"
"github.com/libp2p/go-libp2p-core/peer"
cbg "github.com/whyrusleeping/cbor-gen"
"github.com/whyrusleeping/pubsub"
"go.opencensus.io/trace"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/blocksync"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sectorbuilder"
)
var log = logging.Logger("chain")
@ -41,8 +44,6 @@ var log = logging.Logger("chain")
var LocalIncoming = "incoming"
type Syncer struct {
// The heaviest known tipset in the network.
// The interface for accessing and putting tipsets into local storage
store *store.ChainStore
@ -62,10 +63,14 @@ type Syncer struct {
syncmgr *SyncManager
connmgr connmgr.ConnManager
incoming *pubsub.PubSub
receiptTracker *blockReceiptTracker
}
func NewSyncer(sm *stmgr.StateManager, bsync *blocksync.BlockSync, self peer.ID) (*Syncer, error) {
func NewSyncer(sm *stmgr.StateManager, bsync *blocksync.BlockSync, connmgr connmgr.ConnManager, self peer.ID) (*Syncer, error) {
gen, err := sm.ChainStore().GetGenesis()
if err != nil {
return nil, err
@ -77,12 +82,14 @@ func NewSyncer(sm *stmgr.StateManager, bsync *blocksync.BlockSync, self peer.ID)
}
s := &Syncer{
bad: NewBadBlockCache(),
Genesis: gent,
Bsync: bsync,
store: sm.ChainStore(),
sm: sm,
self: self,
bad: NewBadBlockCache(),
Genesis: gent,
Bsync: bsync,
store: sm.ChainStore(),
sm: sm,
self: self,
receiptTracker: newBlockReceiptTracker(),
connmgr: connmgr,
incoming: pubsub.New(50),
}
@ -102,17 +109,17 @@ func (syncer *Syncer) Stop() {
// InformNewHead informs the syncer about a new potential tipset
// This should be called when connecting to new peers, and additionally
// when receiving new blocks from the network
func (syncer *Syncer) InformNewHead(from peer.ID, fts *store.FullTipSet) {
func (syncer *Syncer) InformNewHead(from peer.ID, fts *store.FullTipSet) bool {
ctx := context.Background()
if fts == nil {
log.Errorf("got nil tipset in InformNewHead")
return
return false
}
for _, b := range fts.Blocks {
if err := syncer.ValidateMsgMeta(b); err != nil {
log.Warnf("invalid block received: %s", err)
return
return false
}
}
@ -124,16 +131,17 @@ func (syncer *Syncer) InformNewHead(from peer.ID, fts *store.FullTipSet) {
if err := syncer.Sync(ctx, fts.TipSet()); err != nil {
log.Errorf("failed to sync our own block %s: %+v", fts.TipSet().Cids(), err)
return false
}
return
return true
}
// TODO: IMPORTANT(GARBAGE) this needs to be put in the 'temporary' side of
// the blockstore
if err := syncer.store.PersistBlockHeaders(fts.TipSet().Blocks()...); err != nil {
log.Warn("failed to persist incoming block header: ", err)
return
return false
}
syncer.Bsync.AddPeer(from)
@ -145,11 +153,12 @@ func (syncer *Syncer) InformNewHead(from peer.ID, fts *store.FullTipSet) {
for _, blk := range fts.TipSet().Blocks() {
miners = append(miners, blk.Miner.String())
}
log.Warnf("incoming tipset from %s does not appear to be better than our best chain, ignoring for now", miners)
return
log.Infof("incoming tipset from %s does not appear to be better than our best chain, ignoring for now", miners)
return false
}
syncer.syncmgr.SetPeerHead(ctx, from, fts.TipSet())
return true
}
func (syncer *Syncer) IncomingBlocks(ctx context.Context) (<-chan *types.BlockHeader, error) {
@ -231,12 +240,12 @@ func (syncer *Syncer) ChainStore() *store.ChainStore {
return syncer.store
}
func (syncer *Syncer) InformNewBlock(from peer.ID, blk *types.FullBlock) {
func (syncer *Syncer) InformNewBlock(from peer.ID, blk *types.FullBlock) bool {
// TODO: search for other blocks that could form a tipset with this block
// and then send that tipset to InformNewHead
fts := &store.FullTipSet{Blocks: []*types.FullBlock{blk}}
syncer.InformNewHead(from, fts)
return syncer.InformNewHead(from, fts)
}
func copyBlockstore(from, to bstore.Blockstore) error {
@ -329,16 +338,16 @@ func computeMsgMeta(bs amt.Blocks, bmsgCids, smsgCids []cbg.CBORMarshaler) (cid.
return mrcid, nil
}
func (syncer *Syncer) FetchTipSet(ctx context.Context, p peer.ID, cids []cid.Cid) (*store.FullTipSet, error) {
if fts, err := syncer.tryLoadFullTipSet(cids); err == nil {
func (syncer *Syncer) FetchTipSet(ctx context.Context, p peer.ID, tsk types.TipSetKey) (*store.FullTipSet, error) {
if fts, err := syncer.tryLoadFullTipSet(tsk); err == nil {
return fts, nil
}
return syncer.Bsync.GetFullTipSet(ctx, p, cids)
return syncer.Bsync.GetFullTipSet(ctx, p, tsk)
}
func (syncer *Syncer) tryLoadFullTipSet(cids []cid.Cid) (*store.FullTipSet, error) {
ts, err := syncer.store.LoadTipSet(cids)
func (syncer *Syncer) tryLoadFullTipSet(tsk types.TipSetKey) (*store.FullTipSet, error) {
ts, err := syncer.store.LoadTipSet(tsk)
if err != nil {
return nil, err
}
@ -398,6 +407,15 @@ func (syncer *Syncer) Sync(ctx context.Context, maybeHead *types.TipSet) error {
return xerrors.Errorf("failed to put synced tipset to chainstore: %w", err)
}
peers := syncer.receiptTracker.GetPeers(maybeHead)
if len(peers) > 0 {
syncer.connmgr.TagPeer(peers[0], "new-block", 40)
for _, p := range peers[1:] {
syncer.connmgr.TagPeer(p, "new-block", 25)
}
}
return nil
}
@ -409,6 +427,8 @@ func (syncer *Syncer) ValidateTipSet(ctx context.Context, fts *store.FullTipSet)
ctx, span := trace.StartSpan(ctx, "validateTipSet")
defer span.End()
span.AddAttributes(trace.Int64Attribute("height", int64(fts.TipSet().Height())))
ts := fts.TipSet()
if ts.Equals(syncer.Genesis) {
return nil
@ -469,7 +489,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
h := b.Header
baseTs, err := syncer.store.LoadTipSet(h.Parents)
baseTs, err := syncer.store.LoadTipSet(types.NewTipSetKey(h.Parents...))
if err != nil {
return xerrors.Errorf("load parent tipset failed (%s): %w", h.Parents, err)
}
@ -480,7 +500,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 > uint64(time.Now().Unix()) {
log.Warn("Got block from the future, but within threshold", h.Timestamp, time.Now().Unix())
@ -676,6 +696,26 @@ func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.Bloc
}
func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock, baseTs *types.TipSet) error {
{
var sigCids []cid.Cid // this is what we get for people not wanting the marshalcbor method on the cid type
var pubks []bls.PublicKey
for _, m := range b.BlsMessages {
sigCids = append(sigCids, m.Cid())
pubk, err := syncer.sm.GetBlsPublicKey(ctx, m.From, baseTs)
if err != nil {
return xerrors.Errorf("failed to load bls public to validate block: %w", err)
}
pubks = append(pubks, pubk)
}
if err := syncer.verifyBlsAggregate(ctx, b.Header.BLSAggregate, sigCids, pubks); err != nil {
return xerrors.Errorf("bls aggregate signature was invalid: %w", err)
}
}
nonces := make(map[address.Address]uint64)
balances := make(map[address.Address]types.BigInt)
@ -719,28 +759,14 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
bs := amt.WrapBlockstore(syncer.store.Blockstore())
var blsCids []cbg.CBORMarshaler
var sigCids []cid.Cid // this is what we get for people not wanting the marshalcbor method on the cid type
var pubks []bls.PublicKey
for i, m := range b.BlsMessages {
if err := checkMsg(m); err != nil {
return xerrors.Errorf("block had invalid bls message at index %d: %w", i, err)
}
sigCids = append(sigCids, m.Cid())
c := cbg.CborCid(m.Cid())
blsCids = append(blsCids, &c)
pubk, err := syncer.sm.GetBlsPublicKey(ctx, m.From, baseTs)
if err != nil {
return xerrors.Errorf("failed to load bls public to validate block: %w", err)
}
pubks = append(pubks, pubk)
}
if err := syncer.verifyBlsAggregate(ctx, b.Header.BLSAggregate, sigCids, pubks); err != nil {
return xerrors.Errorf("bls aggregate signature was invalid: %w", err)
}
var secpkCids []cbg.CBORMarshaler
@ -794,10 +820,19 @@ func (syncer *Syncer) verifyBlsAggregate(ctx context.Context, sig types.Signatur
trace.Int64Attribute("msgCount", int64(len(msgs))),
)
var digests []bls.Digest
for _, c := range msgs {
digests = append(digests, bls.Hash(bls.Message(c.Bytes())))
var wg sync.WaitGroup
digests := make([]bls.Digest, len(msgs))
for i := 0; i < 10; i++ {
wg.Add(1)
go func(w int) {
defer wg.Done()
for j := 0; (j*10)+w < len(msgs); j++ {
digests[j*10+w] = bls.Hash(bls.Message(msgs[j*10+w].Bytes()))
}
}(i)
}
wg.Wait()
var bsig bls.Signature
copy(bsig[:], sig.Data)
@ -828,7 +863,7 @@ func (syncer *Syncer) collectHeaders(ctx context.Context, from *types.TipSet, to
trace.Int64Attribute("toHeight", int64(to.Height())),
)
for _, pcid := range from.Parents() {
for _, pcid := range from.Parents().Cids() {
if syncer.bad.Has(pcid) {
for _, b := range from.Cids() {
syncer.bad.Add(b)
@ -850,7 +885,7 @@ func (syncer *Syncer) collectHeaders(ctx context.Context, from *types.TipSet, to
loop:
for blockSet[len(blockSet)-1].Height() > untilHeight {
for _, bc := range at {
for _, bc := range at.Cids() {
if syncer.bad.Has(bc) {
for _, b := range acceptedBlocks {
syncer.bad.Add(b)
@ -863,7 +898,7 @@ loop:
// If, for some reason, we have a suffix of the chain locally, handle that here
ts, err := syncer.store.LoadTipSet(at)
if err == nil {
acceptedBlocks = append(acceptedBlocks, at...)
acceptedBlocks = append(acceptedBlocks, at.Cids()...)
blockSet = append(blockSet, ts)
at = ts.Parents()
@ -910,16 +945,16 @@ loop:
blockSet = append(blockSet, b)
}
acceptedBlocks = append(acceptedBlocks, at...)
acceptedBlocks = append(acceptedBlocks, at.Cids()...)
ss.SetHeight(blks[len(blks)-1].Height())
at = blks[len(blks)-1].Parents()
}
// We have now ascertained that this is *not* a 'fast forward'
if !types.CidArrsEqual(blockSet[len(blockSet)-1].Parents(), to.Cids()) {
if !types.CidArrsEqual(blockSet[len(blockSet)-1].Parents().Cids(), to.Cids()) {
last := blockSet[len(blockSet)-1]
if types.CidArrsEqual(last.Parents(), to.Parents()) {
if last.Parents() == to.Parents() {
// common case: receiving a block thats potentially part of the same tipset as our best block
return blockSet, nil
}
@ -1002,6 +1037,8 @@ func (syncer *Syncer) iterFullTipsets(ctx context.Context, headers []*types.TipS
ctx, span := trace.StartSpan(ctx, "iterFullTipsets")
defer span.End()
span.AddAttributes(trace.Int64Attribute("num_headers", int64(len(headers))))
windowSize := 200
for i := len(headers) - 1; i >= 0; {
fts, err := syncer.store.TryFillTipSet(headers[i])
@ -1144,3 +1181,7 @@ func (syncer *Syncer) State() []SyncerState {
}
return out
}
func (syncer *Syncer) MarkBad(blk cid.Cid) {
syncer.bad.Add(blk)
}

View File

@ -197,10 +197,10 @@ func (stb *syncTargetBucket) sameChainAs(ts *types.TipSet) bool {
if ts.Equals(t) {
return true
}
if types.CidArrsEqual(ts.Cids(), t.Parents()) {
if ts.Key() == t.Parents() {
return true
}
if types.CidArrsEqual(ts.Parents(), t.Cids()) {
if ts.Parents() == t.Key() {
return true
}
}
@ -293,7 +293,7 @@ func (sm *SyncManager) scheduleIncoming(ts *types.TipSet) {
break
}
if types.CidArrsEqual(ts.Parents(), acts.Cids()) {
if ts.Parents() == acts.Key() {
// sync this next, after that sync process finishes
relatedToActiveSync = true
}

View File

@ -12,9 +12,9 @@ import (
mocknet "github.com/libp2p/go-libp2p/p2p/net/mock"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"

View File

@ -1,7 +1,7 @@
package types
import (
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/go-address"
cbor "github.com/ipfs/go-ipld-cbor"
)

View File

@ -124,6 +124,22 @@ func (bi *BigInt) UnmarshalJSON(b []byte) error {
return nil
}
var sizeUnits = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB"}
func (bi BigInt) SizeStr() string {
r := new(big.Rat).SetInt(bi.Int)
den := big.NewRat(1, 1024)
var i int
for f, _ := r.Float64(); f >= 1024 && i+1 < len(sizeUnits); f, _ = r.Float64() {
i++
r = r.Mul(r, den)
}
f, _ := r.Float64()
return fmt.Sprintf("%.3g %s", f, sizeUnits[i])
}
func (bi *BigInt) Scan(value interface{}) error {
switch value := value.(type) {
case string:

View File

@ -2,7 +2,10 @@ package types
import (
"bytes"
"math/big"
"testing"
"github.com/stretchr/testify/assert"
)
func TestBigIntSerializationRoundTrip(t *testing.T) {
@ -49,3 +52,29 @@ func TestFilRoundTrip(t *testing.T) {
}
}
}
func TestSizeStr(t *testing.T) {
cases := []struct {
in uint64
out string
}{
{0, "0 B"},
{1, "1 B"},
{1024, "1 KiB"},
{2000, "1.95 KiB"},
{5 << 20, "5 MiB"},
{11 << 60, "11 EiB"},
}
for _, c := range cases {
assert.Equal(t, c.out, NewInt(c.in).SizeStr(), "input %+v, produced wrong result", c)
}
}
func TestSizeStrBig(t *testing.T) {
ZiB := big.NewInt(50000)
ZiB = ZiB.Lsh(ZiB, 70)
assert.Equal(t, "5e+04 ZiB", BigInt{Int: ZiB}.SizeStr(), "inout %+v, produced wrong result", ZiB)
}

View File

@ -156,6 +156,10 @@ func (bf BitField) MarshalCBOR(w io.Writer) error {
return err
}
if len(rle) > 8192 {
return xerrors.Errorf("encoded bitfield was too large (%d)", len(rle))
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(rle)))); err != nil {
return err
}

View File

@ -5,6 +5,8 @@ import (
"context"
"math/big"
"github.com/filecoin-project/go-sectorbuilder"
block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
"github.com/minio/sha256-simd"
@ -12,8 +14,9 @@ import (
"go.opencensus.io/trace"
xerrors "golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/address"
)
type Ticket struct {
@ -176,7 +179,7 @@ const sha256bits = 256
func IsTicketWinner(partialTicket []byte, ssizeI uint64, snum uint64, totpow BigInt) bool {
ssize := NewInt(ssizeI)
ssampled := ElectionPostChallengeCount(snum)
ssampled := ElectionPostChallengeCount(snum, 0) // TODO: faults in epost?
/*
Need to check that
(h(vrfout) + 1) / (max(h) + 1) <= e * sectorSize / totalPower
@ -213,12 +216,8 @@ func IsTicketWinner(partialTicket []byte, ssizeI uint64, snum uint64, totpow Big
return lhs.Cmp(rhs) < 0
}
func ElectionPostChallengeCount(sectors uint64) uint64 {
if sectors == 0 {
return 0
}
// ceil(sectors / build.SectorChallengeRatioDiv)
return (sectors-1)/build.SectorChallengeRatioDiv + 1
func ElectionPostChallengeCount(sectors uint64, faults int) uint64 {
return sectorbuilder.ElectionPostChallengeCount(sectors, faults)
}
func (t *Ticket) Equals(ot *Ticket) bool {

View File

@ -6,7 +6,7 @@ import (
"reflect"
"testing"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/go-address"
cid "github.com/ipfs/go-cid"
)

View File

@ -5,7 +5,7 @@ import (
"io"
"math"
"github.com/ipfs/go-cid"
cid "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
xerrors "golang.org/x/xerrors"
)
@ -39,6 +39,10 @@ func (t *BlockHeader) MarshalCBOR(w io.Writer) error {
}
// t.Parents ([]cid.Cid) (slice)
if len(t.Parents) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.Parents was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Parents)))); err != nil {
return err
}
@ -281,6 +285,10 @@ func (t *Ticket) MarshalCBOR(w io.Writer) error {
}
// t.VRFProof ([]uint8) (slice)
if len(t.VRFProof) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.VRFProof was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.VRFProof)))); err != nil {
return err
}
@ -335,6 +343,10 @@ func (t *EPostProof) MarshalCBOR(w io.Writer) error {
}
// t.Proof ([]uint8) (slice)
if len(t.Proof) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.Proof was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Proof)))); err != nil {
return err
}
@ -343,6 +355,10 @@ func (t *EPostProof) MarshalCBOR(w io.Writer) error {
}
// t.PostRand ([]uint8) (slice)
if len(t.PostRand) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.PostRand was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.PostRand)))); err != nil {
return err
}
@ -351,6 +367,10 @@ func (t *EPostProof) MarshalCBOR(w io.Writer) error {
}
// t.Candidates ([]types.EPostTicket) (slice)
if len(t.Candidates) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.Candidates was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Candidates)))); err != nil {
return err
}
@ -451,6 +471,10 @@ func (t *EPostTicket) MarshalCBOR(w io.Writer) error {
}
// t.Partial ([]uint8) (slice)
if len(t.Partial) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.Partial was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Partial)))); err != nil {
return err
}
@ -570,6 +594,10 @@ func (t *Message) MarshalCBOR(w io.Writer) error {
}
// t.Params ([]uint8) (slice)
if len(t.Params) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.Params was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Params)))); err != nil {
return err
}
@ -817,6 +845,10 @@ func (t *SignedVoucher) MarshalCBOR(w io.Writer) error {
}
// t.SecretPreimage ([]uint8) (slice)
if len(t.SecretPreimage) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.SecretPreimage was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.SecretPreimage)))); err != nil {
return err
}
@ -850,6 +882,10 @@ func (t *SignedVoucher) MarshalCBOR(w io.Writer) error {
}
// t.Merges ([]types.Merge) (slice)
if len(t.Merges) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.Merges was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Merges)))); err != nil {
return err
}
@ -1039,6 +1075,10 @@ func (t *ModVerifyParams) MarshalCBOR(w io.Writer) error {
}
// t.Data ([]uint8) (slice)
if len(t.Data) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.Data was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Data)))); err != nil {
return err
}
@ -1270,6 +1310,10 @@ func (t *MessageReceipt) MarshalCBOR(w io.Writer) error {
}
// t.Return ([]uint8) (slice)
if len(t.Return) > cbg.ByteArrayMaxLen {
return xerrors.Errorf("Byte array in field t.Return was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Return)))); err != nil {
return err
}
@ -1356,6 +1400,10 @@ func (t *BlockMsg) MarshalCBOR(w io.Writer) error {
}
// t.BlsMessages ([]cid.Cid) (slice)
if len(t.BlsMessages) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.BlsMessages was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.BlsMessages)))); err != nil {
return err
}
@ -1366,6 +1414,10 @@ func (t *BlockMsg) MarshalCBOR(w io.Writer) error {
}
// t.SecpkMessages ([]cid.Cid) (slice)
if len(t.SecpkMessages) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.SecpkMessages was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.SecpkMessages)))); err != nil {
return err
}
@ -1676,6 +1728,10 @@ func (t *ExpTipSet) MarshalCBOR(w io.Writer) error {
}
// t.Cids ([]cid.Cid) (slice)
if len(t.Cids) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.Cids was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Cids)))); err != nil {
return err
}
@ -1686,6 +1742,10 @@ func (t *ExpTipSet) MarshalCBOR(w io.Writer) error {
}
// t.Blocks ([]*types.BlockHeader) (slice)
if len(t.Blocks) > cbg.MaxLength {
return xerrors.Errorf("Slice value in field t.Blocks was too long")
}
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Blocks)))); err != nil {
return err
}

View File

@ -8,7 +8,7 @@ import (
"github.com/ipfs/go-cid"
"github.com/multiformats/go-multihash"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/go-address"
)
type Message struct {

View File

@ -4,7 +4,7 @@ import (
"context"
"fmt"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/ipfs/go-cid"

View File

@ -6,8 +6,8 @@ import (
"fmt"
bls "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/lib/crypto"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-crypto"
"github.com/minio/blake2b-simd"
)

View File

@ -136,8 +136,8 @@ func (ts *TipSet) Height() uint64 {
return ts.height
}
func (ts *TipSet) Parents() []cid.Cid {
return ts.blks[0].Parents
func (ts *TipSet) Parents() TipSetKey {
return NewTipSetKey(ts.blks[0].Parents...)
}
func (ts *TipSet) Blocks() []*BlockHeader {

View File

@ -4,7 +4,7 @@ import (
"math/rand"
"testing"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/go-address"
)
func blsaddr(n int64) address.Address {

View File

@ -3,9 +3,9 @@ package types
import (
"context"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-amt-ipld"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/address"
cid "github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld"
cbg "github.com/whyrusleeping/cbor-gen"

View File

@ -4,8 +4,8 @@ import (
"bytes"
"encoding/base64"
"github.com/filecoin-project/lotus/chain/address"
cborrpc "github.com/filecoin-project/lotus/lib/cborutil"
"github.com/filecoin-project/go-address"
cborrpc "github.com/filecoin-project/go-cbor-util"
cbor "github.com/ipfs/go-ipld-cbor"
)

View File

@ -4,7 +4,7 @@ import (
"encoding/json"
"testing"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types"
)

View File

@ -7,7 +7,7 @@ import (
vstate "github.com/filecoin-project/chain-validation/pkg/state"
vtypes "github.com/filecoin-project/chain-validation/pkg/state/types"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
)

View File

@ -2,7 +2,6 @@ package validation
import (
"context"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
@ -11,8 +10,8 @@ import (
vaddress "github.com/filecoin-project/chain-validation/pkg/state/address"
vtypes "github.com/filecoin-project/chain-validation/pkg/state/types"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
)
@ -83,5 +82,15 @@ var methods = []uint64{
vchain.StorageMinerGetWorkerAddr: actors.MAMethods.GetWorkerAddr,
vchain.StorageMinerGetPeerID: actors.MAMethods.GetPeerID,
vchain.StorageMinerGetSectorSize: actors.MAMethods.GetSectorSize,
vchain.MultiSigConstructor: actors.MultiSigMethods.MultiSigConstructor,
vchain.MultiSigPropose: actors.MultiSigMethods.Propose,
vchain.MultiSigApprove: actors.MultiSigMethods.Approve,
vchain.MultiSigCancel: actors.MultiSigMethods.Cancel,
vchain.MultiSigClearCompleted: actors.MultiSigMethods.ClearCompleted,
vchain.MultiSigAddSigner: actors.MultiSigMethods.AddSigner,
vchain.MultiSigRemoveSigner: actors.MultiSigMethods.RemoveSigner,
vchain.MultiSigSwapSigner: actors.MultiSigMethods.SwapSigner,
vchain.MultiSigChangeRequirement: actors.MultiSigMethods.ChangeRequirement,
// More to follow...
}

View File

@ -12,8 +12,8 @@ import (
vaddress "github.com/filecoin-project/chain-validation/pkg/state/address"
vtypes "github.com/filecoin-project/chain-validation/pkg/state/types"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/wallet"
)

View File

@ -18,14 +18,14 @@ import (
vaddress "github.com/filecoin-project/chain-validation/pkg/state/address"
vtypes "github.com/filecoin-project/chain-validation/pkg/state/types"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-crypto"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/lotus/lib/crypto"
)
type StateWrapper struct {

View File

@ -8,9 +8,9 @@ import (
hamt "github.com/ipfs/go-hamt-ipld"
bstore "github.com/ipfs/go-ipfs-blockstore"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types"
)

View File

@ -26,3 +26,10 @@ func TestValueTransfer(t *testing.T) {
suites.AccountValueTransferFromUnknownToKnownAccount(t, factory, 0)
suites.AccountValueTransferFromUnknownToUnknownAccount(t, factory, 0)
}
func TestMultiSig(t *testing.T) {
factory := validation.NewFactories()
suites.MultiSigActorConstructor(t, factory)
suites.MultiSigActorProposeApprove(t, factory)
suites.MultiSigActorProposeCancel(t, factory)
}

View File

@ -15,10 +15,10 @@ import (
"go.opencensus.io/trace"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/bufbstore"
@ -86,10 +86,7 @@ func (vmc *VMContext) Sys() *types.VMSyscalls {
func (vmc *VMContext) Put(i cbg.CBORMarshaler) (cid.Cid, aerrors.ActorError) {
c, err := vmc.cst.Put(context.TODO(), i)
if err != nil {
if aerr := vmc.ChargeGas(0); aerr != nil {
return cid.Undef, aerrors.Absorb(err, outOfGasErrCode, "Put out of gas")
}
return cid.Undef, aerrors.Escalate(err, fmt.Sprintf("putting object %T", i))
return cid.Undef, aerrors.HandleExternalError(err, fmt.Sprintf("putting object %T", i))
}
return c, nil
}
@ -97,10 +94,7 @@ func (vmc *VMContext) Put(i cbg.CBORMarshaler) (cid.Cid, aerrors.ActorError) {
func (vmc *VMContext) Get(c cid.Cid, out cbg.CBORUnmarshaler) aerrors.ActorError {
err := vmc.cst.Get(context.TODO(), c, out)
if err != nil {
if aerr := vmc.ChargeGas(0); aerr != nil {
return aerrors.Absorb(err, outOfGasErrCode, "Get out of gas")
}
return aerrors.Escalate(err, "getting cid")
return aerrors.HandleExternalError(err, "getting cid")
}
return nil
}
@ -467,7 +461,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, msg *types.Message) (*ApplyRet,
ret, actorErr, vmctx := vm.send(ctx, msg, nil, msgGasCost)
if aerrors.IsFatal(actorErr) {
return nil, xerrors.Errorf("fatal error: %w", actorErr)
return nil, xerrors.Errorf("[from=%s,to=%s,n=%d,m=%d,h=%d] fatal error: %w", msg.From, msg.To, msg.Nonce, msg.Method, vm.blockHeight, actorErr)
}
if actorErr != nil {
log.Warnf("[from=%s,to=%s,n=%d,m=%d,h=%d] Send actor error: %+v", msg.From, msg.To, msg.Nonce, msg.Method, vm.blockHeight, actorErr)

View File

@ -13,9 +13,9 @@ import (
"github.com/minio/blake2b-simd"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-crypto"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/crypto"
)
var log = logging.Logger("wallet")

View File

@ -28,7 +28,7 @@ var authCreateAdminToken = &cli.Command{
},
Action: func(cctx *cli.Context) error {
napi, closer, err := GetFullNodeAPI(cctx)
napi, closer, err := GetAPI(cctx)
if err != nil {
return err
}

View File

@ -25,6 +25,7 @@ var chainCmd = &cli.Command{
chainGetMsgCmd,
chainSetHeadCmd,
chainListCmd,
chainGetCmd,
},
}
@ -218,6 +219,10 @@ var chainSetHeadCmd = &cli.Command{
Name: "genesis",
Usage: "reset head to genesis",
},
&cli.Uint64Flag{
Name: "epoch",
Usage: "reset head to given epoch",
},
},
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
@ -227,25 +232,23 @@ var chainSetHeadCmd = &cli.Command{
defer closer()
ctx := ReqContext(cctx)
gen := cctx.Bool("genesis")
var ts *types.TipSet
if !cctx.Args().Present() && !gen {
return fmt.Errorf("must pass cids for tipset to set as head")
if cctx.Bool("genesis") {
ts, err = api.ChainGetGenesis(ctx)
}
if ts == nil && cctx.IsSet("epoch") {
ts, err = api.ChainGetTipSetByHeight(ctx, cctx.Uint64("epoch"), nil)
}
if ts == nil {
ts, err = parseTipSet(api, ctx, cctx.Args().Slice())
}
if err != nil {
return err
}
var ts *types.TipSet
if gen {
gents, err := api.ChainGetGenesis(ctx)
if err != nil {
return err
}
ts = gents
} else {
parsedts, err := parseTipSet(api, ctx, cctx.Args().Slice())
if err != nil {
return err
}
ts = parsedts
if ts == nil {
return fmt.Errorf("must pass cids for tipset to set as head")
}
if err := api.ChainSetHead(ctx, ts); err != nil {
@ -319,7 +322,7 @@ var chainListCmd = &cli.Command{
break
}
head, err = api.ChainGetTipSet(ctx, types.NewTipSetKey(head.Parents()...))
head, err = api.ChainGetTipSet(ctx, head.Parents())
if err != nil {
return err
}
@ -334,6 +337,41 @@ var chainListCmd = &cli.Command{
},
}
var chainGetCmd = &cli.Command{
Name: "get",
Usage: "Get chain DAG node by path",
Description: `Get ipld node under a specified path:
lotus chain get /ipfs/[cid]/some/path
Note:
You can use special path elements to traverse through some data structures:
- /ipfs/[cid]/@H:elem - get 'elem' from hamt
- /ipfs/[cid]/@Ha:t01 - get element under Addr(t01).Bytes
- /ipfs/[cid]/@A:10 - get 10th amt element
`,
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
nd, err := api.ChainGetNode(ctx, cctx.Args().First())
if err != nil {
return err
}
b, err := json.MarshalIndent(nd, "", "\t")
if err != nil {
return err
}
fmt.Println(string(b))
return nil
},
}
func printTipSet(format string, ts *types.TipSet) {
format = strings.ReplaceAll(format, "<height>", fmt.Sprint(ts.Height()))
format = strings.ReplaceAll(format, "<time>", time.Unix(int64(ts.MinTimestamp()), 0).Format(time.Stamp))

Some files were not shown because too many files have changed in this diff Show More