Merge pull request #1243 from filecoin-project/feat/specs-actors
Spec Actors integration
This commit is contained in:
commit
1b6646b55a
@ -6,11 +6,16 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-filestore"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
@ -19,19 +24,21 @@ import (
|
||||
type FullNode interface {
|
||||
Common
|
||||
|
||||
// TODO: TipSetKeys
|
||||
|
||||
// chain
|
||||
|
||||
// ChainNotify returns channel with chain head updates
|
||||
// First message is guaranteed to be of len == 1, and type == 'current'
|
||||
ChainNotify(context.Context) (<-chan []*store.HeadChange, error)
|
||||
ChainHead(context.Context) (*types.TipSet, error)
|
||||
ChainGetRandomness(context.Context, types.TipSetKey, int64) ([]byte, error)
|
||||
ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error)
|
||||
ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error)
|
||||
ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error)
|
||||
ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error)
|
||||
ChainGetParentReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error)
|
||||
ChainGetParentMessages(context.Context, cid.Cid) ([]Message, error)
|
||||
ChainGetTipSetByHeight(context.Context, uint64, types.TipSetKey) (*types.TipSet, error)
|
||||
ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error)
|
||||
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
||||
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
||||
ChainSetHead(context.Context, types.TipSetKey) error
|
||||
@ -60,17 +67,17 @@ type FullNode interface {
|
||||
|
||||
// miner
|
||||
|
||||
MinerCreateBlock(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error)
|
||||
MinerCreateBlock(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error)
|
||||
|
||||
// // UX ?
|
||||
|
||||
// wallet
|
||||
|
||||
WalletNew(context.Context, string) (address.Address, error)
|
||||
WalletNew(context.Context, crypto.SigType) (address.Address, error)
|
||||
WalletHas(context.Context, address.Address) (bool, error)
|
||||
WalletList(context.Context) ([]address.Address, error)
|
||||
WalletBalance(context.Context, address.Address) (types.BigInt, error)
|
||||
WalletSign(context.Context, address.Address, []byte) (*types.Signature, error)
|
||||
WalletSign(context.Context, address.Address, []byte) (*crypto.Signature, error)
|
||||
WalletSignMessage(context.Context, address.Address, *types.Message) (*types.SignedMessage, error)
|
||||
WalletDefaultAddress(context.Context) (address.Address, error)
|
||||
WalletSetDefault(context.Context, address.Address) error
|
||||
@ -87,7 +94,7 @@ type FullNode interface {
|
||||
ClientHasLocal(ctx context.Context, root cid.Cid) (bool, error)
|
||||
ClientFindData(ctx context.Context, root cid.Cid) ([]QueryOffer, error)
|
||||
ClientRetrieve(ctx context.Context, order RetrievalOrder, path string) error
|
||||
ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*types.SignedStorageAsk, error)
|
||||
ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error)
|
||||
|
||||
// ClientUnimport removes references to the specified file from filestore
|
||||
//ClientUnimport(path string)
|
||||
@ -102,29 +109,29 @@ type FullNode interface {
|
||||
StateReplay(context.Context, types.TipSetKey, cid.Cid) (*ReplayResults, error)
|
||||
StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error)
|
||||
StateReadState(ctx context.Context, act *types.Actor, tsk types.TipSetKey) (*ActorState, error)
|
||||
StateListMessages(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht uint64) ([]cid.Cid, error)
|
||||
StateListMessages(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error)
|
||||
|
||||
StateMinerSectors(context.Context, address.Address, types.TipSetKey) ([]*ChainSectorInfo, error)
|
||||
StateMinerProvingSet(context.Context, address.Address, types.TipSetKey) ([]*ChainSectorInfo, error)
|
||||
StateMinerPower(context.Context, address.Address, types.TipSetKey) (MinerPower, error)
|
||||
StateMinerWorker(context.Context, address.Address, types.TipSetKey) (address.Address, error)
|
||||
StateMinerPeerID(ctx context.Context, m address.Address, tsk types.TipSetKey) (peer.ID, error)
|
||||
StateMinerElectionPeriodStart(ctx context.Context, actor address.Address, tsk types.TipSetKey) (uint64, error)
|
||||
StateMinerSectorSize(context.Context, address.Address, types.TipSetKey) (uint64, error)
|
||||
StateMinerFaults(context.Context, address.Address, types.TipSetKey) ([]uint64, error)
|
||||
StateMinerPostState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*miner.PoStState, error)
|
||||
StateMinerSectorSize(context.Context, address.Address, types.TipSetKey) (abi.SectorSize, error)
|
||||
StateMinerFaults(context.Context, address.Address, types.TipSetKey) ([]abi.SectorNumber, error)
|
||||
StatePledgeCollateral(context.Context, types.TipSetKey) (types.BigInt, error)
|
||||
StateWaitMsg(context.Context, cid.Cid) (*MsgWait, error)
|
||||
StateListMiners(context.Context, types.TipSetKey) ([]address.Address, error)
|
||||
StateListActors(context.Context, types.TipSetKey) ([]address.Address, error)
|
||||
StateMarketBalance(context.Context, address.Address, types.TipSetKey) (actors.StorageParticipantBalance, error)
|
||||
StateMarketParticipants(context.Context, types.TipSetKey) (map[string]actors.StorageParticipantBalance, error)
|
||||
StateMarketDeals(context.Context, types.TipSetKey) (map[string]actors.OnChainDeal, error)
|
||||
StateMarketStorageDeal(context.Context, uint64, types.TipSetKey) (*actors.OnChainDeal, error)
|
||||
StateMarketBalance(context.Context, address.Address, types.TipSetKey) (MarketBalance, error)
|
||||
StateMarketParticipants(context.Context, types.TipSetKey) (map[string]MarketBalance, error)
|
||||
StateMarketDeals(context.Context, types.TipSetKey) (map[string]MarketDeal, error)
|
||||
StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*MarketDeal, error)
|
||||
StateLookupID(context.Context, address.Address, types.TipSetKey) (address.Address, error)
|
||||
StateChangedActors(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error)
|
||||
StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
|
||||
StateMinerSectorCount(context.Context, address.Address, types.TipSetKey) (MinerSectors, error)
|
||||
StateCompute(context.Context, uint64, []*types.Message, types.TipSetKey) (cid.Cid, error)
|
||||
StateCompute(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (cid.Cid, error)
|
||||
|
||||
MsigGetAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error)
|
||||
|
||||
@ -137,12 +144,12 @@ type FullNode interface {
|
||||
PaychClose(context.Context, address.Address) (cid.Cid, error)
|
||||
PaychAllocateLane(ctx context.Context, ch address.Address) (uint64, error)
|
||||
PaychNewPayment(ctx context.Context, from, to address.Address, vouchers []VoucherSpec) (*PaymentInfo, error)
|
||||
PaychVoucherCheckValid(context.Context, address.Address, *types.SignedVoucher) error
|
||||
PaychVoucherCheckSpendable(context.Context, address.Address, *types.SignedVoucher, []byte, []byte) (bool, error)
|
||||
PaychVoucherCreate(context.Context, address.Address, types.BigInt, uint64) (*types.SignedVoucher, error)
|
||||
PaychVoucherAdd(context.Context, address.Address, *types.SignedVoucher, []byte, types.BigInt) (types.BigInt, error)
|
||||
PaychVoucherList(context.Context, address.Address) ([]*types.SignedVoucher, error)
|
||||
PaychVoucherSubmit(context.Context, address.Address, *types.SignedVoucher) (cid.Cid, error)
|
||||
PaychVoucherCheckValid(context.Context, address.Address, *paych.SignedVoucher) error
|
||||
PaychVoucherCheckSpendable(context.Context, address.Address, *paych.SignedVoucher, []byte, []byte) (bool, error)
|
||||
PaychVoucherCreate(context.Context, address.Address, types.BigInt, uint64) (*paych.SignedVoucher, error)
|
||||
PaychVoucherAdd(context.Context, address.Address, *paych.SignedVoucher, []byte, types.BigInt) (types.BigInt, error)
|
||||
PaychVoucherList(context.Context, address.Address) ([]*paych.SignedVoucher, error)
|
||||
PaychVoucherSubmit(context.Context, address.Address, *paych.SignedVoucher) (cid.Cid, error)
|
||||
}
|
||||
|
||||
type MinerSectors struct {
|
||||
@ -187,9 +194,8 @@ type Message struct {
|
||||
}
|
||||
|
||||
type ChainSectorInfo struct {
|
||||
SectorID uint64
|
||||
CommD []byte
|
||||
CommR []byte
|
||||
Info miner.SectorOnChainInfo
|
||||
ID abi.SectorNumber
|
||||
}
|
||||
|
||||
type ActorState struct {
|
||||
@ -218,15 +224,15 @@ type ChannelInfo struct {
|
||||
type PaymentInfo struct {
|
||||
Channel address.Address
|
||||
ChannelMessage *cid.Cid
|
||||
Vouchers []*types.SignedVoucher
|
||||
Vouchers []*paych.SignedVoucher
|
||||
}
|
||||
|
||||
type VoucherSpec struct {
|
||||
Amount types.BigInt
|
||||
TimeLock uint64
|
||||
MinClose uint64
|
||||
Amount types.BigInt
|
||||
TimeLock abi.ChainEpoch
|
||||
MinSettle abi.ChainEpoch
|
||||
|
||||
Extra *types.ModVerifyParams
|
||||
Extra *paych.ModVerifyParams
|
||||
}
|
||||
|
||||
type MinerPower struct {
|
||||
@ -261,6 +267,16 @@ func (o *QueryOffer) Order(client address.Address) RetrievalOrder {
|
||||
}
|
||||
}
|
||||
|
||||
type MarketBalance struct {
|
||||
Escrow big.Int
|
||||
Locked big.Int
|
||||
}
|
||||
|
||||
type MarketDeal struct {
|
||||
Proposal market.DealProposal
|
||||
State market.DealState
|
||||
}
|
||||
|
||||
type RetrievalOrder struct {
|
||||
// TODO: make this less unixfs specific
|
||||
Root cid.Cid
|
||||
@ -290,7 +306,7 @@ type ActiveSync struct {
|
||||
Target *types.TipSet
|
||||
|
||||
Stage SyncStateStage
|
||||
Height uint64
|
||||
Height abi.ChainEpoch
|
||||
|
||||
Start time.Time
|
||||
End time.Time
|
||||
|
@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
|
||||
"github.com/filecoin-project/go-sectorbuilder"
|
||||
)
|
||||
|
||||
@ -86,20 +88,20 @@ type StorageMiner interface {
|
||||
|
||||
ActorAddress(context.Context) (address.Address, error)
|
||||
|
||||
ActorSectorSize(context.Context, address.Address) (uint64, error)
|
||||
ActorSectorSize(context.Context, address.Address) (abi.SectorSize, error)
|
||||
|
||||
// Temp api for testing
|
||||
PledgeSector(context.Context) error
|
||||
|
||||
// Get the status of a given sector by ID
|
||||
SectorsStatus(context.Context, uint64) (SectorInfo, error)
|
||||
SectorsStatus(context.Context, abi.SectorNumber) (SectorInfo, error)
|
||||
|
||||
// List all staged sectors
|
||||
SectorsList(context.Context) ([]uint64, error)
|
||||
SectorsList(context.Context) ([]abi.SectorNumber, error)
|
||||
|
||||
SectorsRefs(context.Context) (map[string][]SealedRef, error)
|
||||
|
||||
SectorsUpdate(context.Context, uint64, SectorState) error
|
||||
SectorsUpdate(context.Context, abi.SectorNumber, SectorState) error
|
||||
|
||||
WorkerStats(context.Context) (sectorbuilder.WorkerStats, error)
|
||||
|
||||
@ -119,12 +121,12 @@ type SectorLog struct {
|
||||
}
|
||||
|
||||
type SectorInfo struct {
|
||||
SectorID uint64
|
||||
SectorID abi.SectorNumber
|
||||
State SectorState
|
||||
CommD []byte
|
||||
CommR []byte
|
||||
Proof []byte
|
||||
Deals []uint64
|
||||
Deals []abi.DealID
|
||||
Ticket sectorbuilder.SealTicket
|
||||
Seed sectorbuilder.SealSeed
|
||||
Retries uint64
|
||||
@ -135,9 +137,9 @@ type SectorInfo struct {
|
||||
}
|
||||
|
||||
type SealedRef struct {
|
||||
SectorID uint64
|
||||
SectorID abi.SectorNumber
|
||||
Offset uint64
|
||||
Size uint64
|
||||
Size abi.UnpaddedPieceSize
|
||||
}
|
||||
|
||||
type SealedRefs struct {
|
||||
|
@ -3,15 +3,20 @@ package apistruct
|
||||
import (
|
||||
"context"
|
||||
|
||||
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/go-fil-markets/storagemarket"
|
||||
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
@ -44,24 +49,24 @@ type FullNodeStruct struct {
|
||||
CommonStruct
|
||||
|
||||
Internal struct {
|
||||
ChainNotify func(context.Context) (<-chan []*store.HeadChange, error) `perm:"read"`
|
||||
ChainHead func(context.Context) (*types.TipSet, error) `perm:"read"`
|
||||
ChainGetRandomness func(context.Context, types.TipSetKey, int64) ([]byte, error) `perm:"read"`
|
||||
ChainGetBlock func(context.Context, cid.Cid) (*types.BlockHeader, error) `perm:"read"`
|
||||
ChainGetTipSet func(context.Context, types.TipSetKey) (*types.TipSet, error) `perm:"read"`
|
||||
ChainGetBlockMessages func(context.Context, cid.Cid) (*api.BlockMessages, error) `perm:"read"`
|
||||
ChainGetParentReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"`
|
||||
ChainGetParentMessages func(context.Context, cid.Cid) ([]api.Message, error) `perm:"read"`
|
||||
ChainGetTipSetByHeight func(context.Context, uint64, types.TipSetKey) (*types.TipSet, error) `perm:"read"`
|
||||
ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"`
|
||||
ChainHasObj func(context.Context, cid.Cid) (bool, error) `perm:"read"`
|
||||
ChainSetHead func(context.Context, types.TipSetKey) error `perm:"admin"`
|
||||
ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"`
|
||||
ChainTipSetWeight func(context.Context, types.TipSetKey) (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"`
|
||||
ChainGetPath func(context.Context, types.TipSetKey, types.TipSetKey) ([]*store.HeadChange, error) `perm:"read"`
|
||||
ChainExport func(context.Context, types.TipSetKey) (<-chan []byte, error) `perm:"read"`
|
||||
ChainNotify func(context.Context) (<-chan []*store.HeadChange, error) `perm:"read"`
|
||||
ChainHead func(context.Context) (*types.TipSet, error) `perm:"read"`
|
||||
ChainGetRandomness func(context.Context, types.TipSetKey, crypto.DomainSeparationTag, abi.ChainEpoch, []byte) (abi.Randomness, error) `perm:"read"`
|
||||
ChainGetBlock func(context.Context, cid.Cid) (*types.BlockHeader, error) `perm:"read"`
|
||||
ChainGetTipSet func(context.Context, types.TipSetKey) (*types.TipSet, error) `perm:"read"`
|
||||
ChainGetBlockMessages func(context.Context, cid.Cid) (*api.BlockMessages, error) `perm:"read"`
|
||||
ChainGetParentReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"`
|
||||
ChainGetParentMessages func(context.Context, cid.Cid) ([]api.Message, error) `perm:"read"`
|
||||
ChainGetTipSetByHeight func(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) `perm:"read"`
|
||||
ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"`
|
||||
ChainHasObj func(context.Context, cid.Cid) (bool, error) `perm:"read"`
|
||||
ChainSetHead func(context.Context, types.TipSetKey) error `perm:"admin"`
|
||||
ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"`
|
||||
ChainTipSetWeight func(context.Context, types.TipSetKey) (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"`
|
||||
ChainGetPath func(context.Context, types.TipSetKey, types.TipSetKey) ([]*store.HeadChange, error) `perm:"read"`
|
||||
ChainExport func(context.Context, types.TipSetKey) (<-chan []byte, error) `perm:"read"`
|
||||
|
||||
SyncState func(context.Context) (*api.SyncState, error) `perm:"read"`
|
||||
SyncSubmitBlock func(ctx context.Context, blk *types.BlockMsg) error `perm:"write"`
|
||||
@ -70,18 +75,18 @@ type FullNodeStruct struct {
|
||||
SyncCheckBad func(ctx context.Context, bcid cid.Cid) (string, error) `perm:"read"`
|
||||
|
||||
MpoolPending func(context.Context, types.TipSetKey) ([]*types.SignedMessage, error) `perm:"read"`
|
||||
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"`
|
||||
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"`
|
||||
|
||||
MinerCreateBlock func(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error) `perm:"write"`
|
||||
MinerCreateBlock func(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error) `perm:"write"`
|
||||
|
||||
WalletNew func(context.Context, string) (address.Address, error) `perm:"write"`
|
||||
WalletNew func(context.Context, crypto.SigType) (address.Address, error) `perm:"write"`
|
||||
WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"`
|
||||
WalletList func(context.Context) ([]address.Address, error) `perm:"write"`
|
||||
WalletBalance func(context.Context, address.Address) (types.BigInt, error) `perm:"read"`
|
||||
WalletSign func(context.Context, address.Address, []byte) (*types.Signature, error) `perm:"sign"`
|
||||
WalletSign func(context.Context, address.Address, []byte) (*crypto.Signature, error) `perm:"sign"`
|
||||
WalletSignMessage func(context.Context, address.Address, *types.Message) (*types.SignedMessage, error) `perm:"sign"`
|
||||
WalletDefaultAddress func(context.Context) (address.Address, error) `perm:"write"`
|
||||
WalletSetDefault func(context.Context, address.Address) error `perm:"admin"`
|
||||
@ -96,34 +101,34 @@ type FullNodeStruct struct {
|
||||
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"`
|
||||
ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error) `perm:"read"`
|
||||
|
||||
StateMinerSectors func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"`
|
||||
StateMinerProvingSet func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"`
|
||||
StateMinerPower func(context.Context, address.Address, types.TipSetKey) (api.MinerPower, error) `perm:"read"`
|
||||
StateMinerWorker func(context.Context, address.Address, types.TipSetKey) (address.Address, error) `perm:"read"`
|
||||
StateMinerPeerID func(ctx context.Context, m address.Address, tsk types.TipSetKey) (peer.ID, error) `perm:"read"`
|
||||
StateMinerElectionPeriodStart func(ctx context.Context, actor address.Address, tsk types.TipSetKey) (uint64, error) `perm:"read"`
|
||||
StateMinerSectorSize func(context.Context, address.Address, types.TipSetKey) (uint64, error) `perm:"read"`
|
||||
StateMinerFaults func(context.Context, address.Address, types.TipSetKey) ([]uint64, error) `perm:"read"`
|
||||
StateCall func(context.Context, *types.Message, types.TipSetKey) (*api.MethodCall, error) `perm:"read"`
|
||||
StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.ReplayResults, error) `perm:"read"`
|
||||
StateGetActor func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) `perm:"read"`
|
||||
StateReadState func(context.Context, *types.Actor, types.TipSetKey) (*api.ActorState, error) `perm:"read"`
|
||||
StatePledgeCollateral func(context.Context, types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
||||
StateWaitMsg func(context.Context, cid.Cid) (*api.MsgWait, error) `perm:"read"`
|
||||
StateListMiners func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
|
||||
StateListActors func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
|
||||
StateMarketBalance func(context.Context, address.Address, types.TipSetKey) (actors.StorageParticipantBalance, error) `perm:"read"`
|
||||
StateMarketParticipants func(context.Context, types.TipSetKey) (map[string]actors.StorageParticipantBalance, error) `perm:"read"`
|
||||
StateMarketDeals func(context.Context, types.TipSetKey) (map[string]actors.OnChainDeal, error) `perm:"read"`
|
||||
StateMarketStorageDeal func(context.Context, uint64, types.TipSetKey) (*actors.OnChainDeal, error) `perm:"read"`
|
||||
StateLookupID func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (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.TipSetKey) (*types.MessageReceipt, error) `perm:"read"`
|
||||
StateMinerSectorCount func(context.Context, address.Address, types.TipSetKey) (api.MinerSectors, error) `perm:"read"`
|
||||
StateListMessages func(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht uint64) ([]cid.Cid, error) `perm:"read"`
|
||||
StateCompute func(context.Context, uint64, []*types.Message, types.TipSetKey) (cid.Cid, error) `perm:"read"`
|
||||
StateMinerSectors func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"`
|
||||
StateMinerProvingSet func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"`
|
||||
StateMinerPower func(context.Context, address.Address, types.TipSetKey) (api.MinerPower, error) `perm:"read"`
|
||||
StateMinerWorker func(context.Context, address.Address, types.TipSetKey) (address.Address, error) `perm:"read"`
|
||||
StateMinerPeerID func(ctx context.Context, m address.Address, tsk types.TipSetKey) (peer.ID, error) `perm:"read"`
|
||||
StateMinerPostState func(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*miner.PoStState, error) `perm:"read"`
|
||||
StateMinerSectorSize func(context.Context, address.Address, types.TipSetKey) (abi.SectorSize, error) `perm:"read"`
|
||||
StateMinerFaults func(context.Context, address.Address, types.TipSetKey) ([]abi.SectorNumber, error) `perm:"read"`
|
||||
StateCall func(context.Context, *types.Message, types.TipSetKey) (*api.MethodCall, error) `perm:"read"`
|
||||
StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.ReplayResults, error) `perm:"read"`
|
||||
StateGetActor func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) `perm:"read"`
|
||||
StateReadState func(context.Context, *types.Actor, types.TipSetKey) (*api.ActorState, error) `perm:"read"`
|
||||
StatePledgeCollateral func(context.Context, types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
||||
StateWaitMsg func(context.Context, cid.Cid) (*api.MsgWait, error) `perm:"read"`
|
||||
StateListMiners func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
|
||||
StateListActors func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"`
|
||||
StateMarketBalance func(context.Context, address.Address, types.TipSetKey) (api.MarketBalance, error) `perm:"read"`
|
||||
StateMarketParticipants func(context.Context, types.TipSetKey) (map[string]api.MarketBalance, error) `perm:"read"`
|
||||
StateMarketDeals func(context.Context, types.TipSetKey) (map[string]api.MarketDeal, error) `perm:"read"`
|
||||
StateMarketStorageDeal func(context.Context, abi.DealID, types.TipSetKey) (*api.MarketDeal, error) `perm:"read"`
|
||||
StateLookupID func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (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.TipSetKey) (*types.MessageReceipt, error) `perm:"read"`
|
||||
StateMinerSectorCount func(context.Context, address.Address, types.TipSetKey) (api.MinerSectors, error) `perm:"read"`
|
||||
StateListMessages func(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"`
|
||||
StateCompute func(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (cid.Cid, error) `perm:"read"`
|
||||
|
||||
MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
||||
|
||||
@ -135,13 +140,13 @@ type FullNodeStruct struct {
|
||||
PaychClose func(context.Context, address.Address) (cid.Cid, error) `perm:"sign"`
|
||||
PaychAllocateLane func(context.Context, address.Address) (uint64, error) `perm:"sign"`
|
||||
PaychNewPayment func(ctx context.Context, from, to address.Address, vouchers []api.VoucherSpec) (*api.PaymentInfo, error) `perm:"sign"`
|
||||
PaychVoucherCheck func(context.Context, *types.SignedVoucher) error `perm:"read"`
|
||||
PaychVoucherCheckValid func(context.Context, address.Address, *types.SignedVoucher) error `perm:"read"`
|
||||
PaychVoucherCheckSpendable func(context.Context, address.Address, *types.SignedVoucher, []byte, []byte) (bool, error) `perm:"read"`
|
||||
PaychVoucherAdd func(context.Context, address.Address, *types.SignedVoucher, []byte, types.BigInt) (types.BigInt, error) `perm:"write"`
|
||||
PaychVoucherCreate func(context.Context, address.Address, types.BigInt, uint64) (*types.SignedVoucher, error) `perm:"sign"`
|
||||
PaychVoucherList func(context.Context, address.Address) ([]*types.SignedVoucher, error) `perm:"write"`
|
||||
PaychVoucherSubmit func(context.Context, address.Address, *types.SignedVoucher) (cid.Cid, error) `perm:"sign"`
|
||||
PaychVoucherCheck func(context.Context, *paych.SignedVoucher) error `perm:"read"`
|
||||
PaychVoucherCheckValid func(context.Context, address.Address, *paych.SignedVoucher) error `perm:"read"`
|
||||
PaychVoucherCheckSpendable func(context.Context, address.Address, *paych.SignedVoucher, []byte, []byte) (bool, error) `perm:"read"`
|
||||
PaychVoucherAdd func(context.Context, address.Address, *paych.SignedVoucher, []byte, types.BigInt) (types.BigInt, error) `perm:"write"`
|
||||
PaychVoucherCreate func(context.Context, address.Address, big.Int, uint64) (*paych.SignedVoucher, error) `perm:"sign"`
|
||||
PaychVoucherList func(context.Context, address.Address) ([]*paych.SignedVoucher, error) `perm:"write"`
|
||||
PaychVoucherSubmit func(context.Context, address.Address, *paych.SignedVoucher) (cid.Cid, error) `perm:"sign"`
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,15 +158,15 @@ type StorageMinerStruct struct {
|
||||
CommonStruct
|
||||
|
||||
Internal struct {
|
||||
ActorAddress func(context.Context) (address.Address, error) `perm:"read"`
|
||||
ActorSectorSize func(context.Context, address.Address) (uint64, error) `perm:"read"`
|
||||
ActorAddress func(context.Context) (address.Address, error) `perm:"read"`
|
||||
ActorSectorSize func(context.Context, address.Address) (abi.SectorSize, error) `perm:"read"`
|
||||
|
||||
PledgeSector func(context.Context) error `perm:"write"`
|
||||
|
||||
SectorsStatus func(context.Context, uint64) (api.SectorInfo, error) `perm:"read"`
|
||||
SectorsList func(context.Context) ([]uint64, error) `perm:"read"`
|
||||
SectorsRefs func(context.Context) (map[string][]api.SealedRef, error) `perm:"read"`
|
||||
SectorsUpdate func(context.Context, uint64, api.SectorState) error `perm:"write"`
|
||||
SectorsStatus func(context.Context, abi.SectorNumber) (api.SectorInfo, error) `perm:"read"`
|
||||
SectorsList func(context.Context) ([]abi.SectorNumber, error) `perm:"read"`
|
||||
SectorsRefs func(context.Context) (map[string][]api.SealedRef, error) `perm:"read"`
|
||||
SectorsUpdate func(context.Context, abi.SectorNumber, api.SectorState) error `perm:"write"`
|
||||
|
||||
WorkerStats func(context.Context) (sectorbuilder.WorkerStats, error) `perm:"read"`
|
||||
|
||||
@ -251,7 +256,7 @@ func (c *FullNodeStruct) ClientRetrieve(ctx context.Context, order api.Retrieval
|
||||
return c.Internal.ClientRetrieve(ctx, order, path)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*types.SignedStorageAsk, error) {
|
||||
func (c *FullNodeStruct) ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*storagemarket.SignedStorageAsk, error) {
|
||||
return c.Internal.ClientQueryAsk(ctx, p, miner)
|
||||
}
|
||||
|
||||
@ -271,7 +276,7 @@ func (c *FullNodeStruct) MpoolSub(ctx context.Context) (<-chan api.MpoolUpdate,
|
||||
return c.Internal.MpoolSub(ctx)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base types.TipSetKey, ticket *types.Ticket, eproof *types.EPostProof, msgs []*types.SignedMessage, height, ts uint64) (*types.BlockMsg, error) {
|
||||
func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base types.TipSetKey, ticket *types.Ticket, eproof *types.EPostProof, msgs []*types.SignedMessage, height abi.ChainEpoch, ts uint64) (*types.BlockMsg, error) {
|
||||
return c.Internal.MinerCreateBlock(ctx, addr, base, ticket, eproof, msgs, height, ts)
|
||||
}
|
||||
|
||||
@ -279,15 +284,15 @@ func (c *FullNodeStruct) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
||||
return c.Internal.ChainHead(ctx)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, round int64) ([]byte, error) {
|
||||
return c.Internal.ChainGetRandomness(ctx, pts, round)
|
||||
func (c *FullNodeStruct) ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) {
|
||||
return c.Internal.ChainGetRandomness(ctx, tsk, personalization, randEpoch, entropy)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ChainGetTipSetByHeight(ctx context.Context, h uint64, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||
func (c *FullNodeStruct) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||
return c.Internal.ChainGetTipSetByHeight(ctx, h, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) WalletNew(ctx context.Context, typ string) (address.Address, error) {
|
||||
func (c *FullNodeStruct) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) {
|
||||
return c.Internal.WalletNew(ctx, typ)
|
||||
}
|
||||
|
||||
@ -303,7 +308,7 @@ func (c *FullNodeStruct) WalletBalance(ctx context.Context, a address.Address) (
|
||||
return c.Internal.WalletBalance(ctx, a)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) WalletSign(ctx context.Context, k address.Address, msg []byte) (*types.Signature, error) {
|
||||
func (c *FullNodeStruct) WalletSign(ctx context.Context, k address.Address, msg []byte) (*crypto.Signature, error) {
|
||||
return c.Internal.WalletSign(ctx, k, msg)
|
||||
}
|
||||
|
||||
@ -431,15 +436,15 @@ func (c *FullNodeStruct) StateMinerPeerID(ctx context.Context, m address.Address
|
||||
return c.Internal.StateMinerPeerID(ctx, m, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateMinerElectionPeriodStart(ctx context.Context, actor address.Address, tsk types.TipSetKey) (uint64, error) {
|
||||
return c.Internal.StateMinerElectionPeriodStart(ctx, actor, tsk)
|
||||
func (c *FullNodeStruct) StateMinerPostState(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*miner.PoStState, error) {
|
||||
return c.Internal.StateMinerPostState(ctx, actor, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateMinerSectorSize(ctx context.Context, actor address.Address, tsk types.TipSetKey) (uint64, error) {
|
||||
func (c *FullNodeStruct) StateMinerSectorSize(ctx context.Context, actor address.Address, tsk types.TipSetKey) (abi.SectorSize, error) {
|
||||
return c.Internal.StateMinerSectorSize(ctx, actor, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateMinerFaults(ctx context.Context, actor address.Address, tsk types.TipSetKey) ([]uint64, error) {
|
||||
func (c *FullNodeStruct) StateMinerFaults(ctx context.Context, actor address.Address, tsk types.TipSetKey) ([]abi.SectorNumber, error) {
|
||||
return c.Internal.StateMinerFaults(ctx, actor, tsk)
|
||||
}
|
||||
|
||||
@ -474,19 +479,19 @@ func (c *FullNodeStruct) StateListActors(ctx context.Context, tsk types.TipSetKe
|
||||
return c.Internal.StateListActors(ctx, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (actors.StorageParticipantBalance, error) {
|
||||
func (c *FullNodeStruct) StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MarketBalance, error) {
|
||||
return c.Internal.StateMarketBalance(ctx, addr, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateMarketParticipants(ctx context.Context, tsk types.TipSetKey) (map[string]actors.StorageParticipantBalance, error) {
|
||||
func (c *FullNodeStruct) StateMarketParticipants(ctx context.Context, tsk types.TipSetKey) (map[string]api.MarketBalance, error) {
|
||||
return c.Internal.StateMarketParticipants(ctx, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateMarketDeals(ctx context.Context, tsk types.TipSetKey) (map[string]actors.OnChainDeal, error) {
|
||||
func (c *FullNodeStruct) StateMarketDeals(ctx context.Context, tsk types.TipSetKey) (map[string]api.MarketDeal, error) {
|
||||
return c.Internal.StateMarketDeals(ctx, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateMarketStorageDeal(ctx context.Context, dealid uint64, tsk types.TipSetKey) (*actors.OnChainDeal, error) {
|
||||
func (c *FullNodeStruct) StateMarketStorageDeal(ctx context.Context, dealid abi.DealID, tsk types.TipSetKey) (*api.MarketDeal, error) {
|
||||
return c.Internal.StateMarketStorageDeal(ctx, dealid, tsk)
|
||||
}
|
||||
|
||||
@ -502,11 +507,11 @@ func (c *FullNodeStruct) StateGetReceipt(ctx context.Context, msg cid.Cid, tsk t
|
||||
return c.Internal.StateGetReceipt(ctx, msg, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateListMessages(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht uint64) ([]cid.Cid, error) {
|
||||
func (c *FullNodeStruct) StateListMessages(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) {
|
||||
return c.Internal.StateListMessages(ctx, match, tsk, toht)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) StateCompute(ctx context.Context, height uint64, msgs []*types.Message, tsk types.TipSetKey) (cid.Cid, error) {
|
||||
func (c *FullNodeStruct) StateCompute(ctx context.Context, height abi.ChainEpoch, msgs []*types.Message, tsk types.TipSetKey) (cid.Cid, error) {
|
||||
return c.Internal.StateCompute(ctx, height, msgs, tsk)
|
||||
}
|
||||
|
||||
@ -530,23 +535,23 @@ func (c *FullNodeStruct) PaychStatus(ctx context.Context, pch address.Address) (
|
||||
return c.Internal.PaychStatus(ctx, pch)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) PaychVoucherCheckValid(ctx context.Context, addr address.Address, sv *types.SignedVoucher) error {
|
||||
func (c *FullNodeStruct) PaychVoucherCheckValid(ctx context.Context, addr address.Address, sv *paych.SignedVoucher) error {
|
||||
return c.Internal.PaychVoucherCheckValid(ctx, addr, sv)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) PaychVoucherCheckSpendable(ctx context.Context, addr address.Address, sv *types.SignedVoucher, secret []byte, proof []byte) (bool, error) {
|
||||
func (c *FullNodeStruct) PaychVoucherCheckSpendable(ctx context.Context, addr address.Address, sv *paych.SignedVoucher, secret []byte, proof []byte) (bool, error) {
|
||||
return c.Internal.PaychVoucherCheckSpendable(ctx, addr, sv, secret, proof)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) PaychVoucherAdd(ctx context.Context, addr address.Address, sv *types.SignedVoucher, proof []byte, minDelta types.BigInt) (types.BigInt, error) {
|
||||
func (c *FullNodeStruct) PaychVoucherAdd(ctx context.Context, addr address.Address, sv *paych.SignedVoucher, proof []byte, minDelta types.BigInt) (types.BigInt, error) {
|
||||
return c.Internal.PaychVoucherAdd(ctx, addr, sv, proof, minDelta)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) PaychVoucherCreate(ctx context.Context, pch address.Address, amt types.BigInt, lane uint64) (*types.SignedVoucher, error) {
|
||||
func (c *FullNodeStruct) PaychVoucherCreate(ctx context.Context, pch address.Address, amt types.BigInt, lane uint64) (*paych.SignedVoucher, error) {
|
||||
return c.Internal.PaychVoucherCreate(ctx, pch, amt, lane)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) PaychVoucherList(ctx context.Context, pch address.Address) ([]*types.SignedVoucher, error) {
|
||||
func (c *FullNodeStruct) PaychVoucherList(ctx context.Context, pch address.Address) ([]*paych.SignedVoucher, error) {
|
||||
return c.Internal.PaychVoucherList(ctx, pch)
|
||||
}
|
||||
|
||||
@ -562,7 +567,7 @@ func (c *FullNodeStruct) PaychNewPayment(ctx context.Context, from, to address.A
|
||||
return c.Internal.PaychNewPayment(ctx, from, to, vouchers)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) PaychVoucherSubmit(ctx context.Context, ch address.Address, sv *types.SignedVoucher) (cid.Cid, error) {
|
||||
func (c *FullNodeStruct) PaychVoucherSubmit(ctx context.Context, ch address.Address, sv *paych.SignedVoucher) (cid.Cid, error) {
|
||||
return c.Internal.PaychVoucherSubmit(ctx, ch, sv)
|
||||
}
|
||||
|
||||
@ -570,7 +575,7 @@ func (c *StorageMinerStruct) ActorAddress(ctx context.Context) (address.Address,
|
||||
return c.Internal.ActorAddress(ctx)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) ActorSectorSize(ctx context.Context, addr address.Address) (uint64, error) {
|
||||
func (c *StorageMinerStruct) ActorSectorSize(ctx context.Context, addr address.Address) (abi.SectorSize, error) {
|
||||
return c.Internal.ActorSectorSize(ctx, addr)
|
||||
}
|
||||
|
||||
@ -579,12 +584,12 @@ func (c *StorageMinerStruct) PledgeSector(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// Get the status of a given sector by ID
|
||||
func (c *StorageMinerStruct) SectorsStatus(ctx context.Context, sid uint64) (api.SectorInfo, error) {
|
||||
func (c *StorageMinerStruct) SectorsStatus(ctx context.Context, sid abi.SectorNumber) (api.SectorInfo, error) {
|
||||
return c.Internal.SectorsStatus(ctx, sid)
|
||||
}
|
||||
|
||||
// List all staged sectors
|
||||
func (c *StorageMinerStruct) SectorsList(ctx context.Context) ([]uint64, error) {
|
||||
func (c *StorageMinerStruct) SectorsList(ctx context.Context) ([]abi.SectorNumber, error) {
|
||||
return c.Internal.SectorsList(ctx)
|
||||
}
|
||||
|
||||
@ -592,7 +597,7 @@ func (c *StorageMinerStruct) SectorsRefs(ctx context.Context) (map[string][]api.
|
||||
return c.Internal.SectorsRefs(ctx)
|
||||
}
|
||||
|
||||
func (c *StorageMinerStruct) SectorsUpdate(ctx context.Context, id uint64, state api.SectorState) error {
|
||||
func (c *StorageMinerStruct) SectorsUpdate(ctx context.Context, id abi.SectorNumber, state api.SectorState) error {
|
||||
return c.Internal.SectorsUpdate(ctx, id, state)
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,8 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
xerrors "golang.org/x/xerrors"
|
||||
)
|
||||
@ -60,7 +61,7 @@ func (t *PaymentInfo) MarshalCBOR(w io.Writer) error {
|
||||
}
|
||||
}
|
||||
|
||||
// t.Vouchers ([]*types.SignedVoucher) (slice)
|
||||
// t.Vouchers ([]*paych.SignedVoucher) (slice)
|
||||
if len("Vouchers") > cbg.MaxLength {
|
||||
return xerrors.Errorf("Value in field \"Vouchers\" was too long")
|
||||
}
|
||||
@ -152,7 +153,7 @@ func (t *PaymentInfo) UnmarshalCBOR(r io.Reader) error {
|
||||
}
|
||||
|
||||
}
|
||||
// t.Vouchers ([]*types.SignedVoucher) (slice)
|
||||
// t.Vouchers ([]*paych.SignedVoucher) (slice)
|
||||
case "Vouchers":
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
@ -168,11 +169,11 @@ func (t *PaymentInfo) UnmarshalCBOR(r io.Reader) error {
|
||||
return fmt.Errorf("expected cbor array")
|
||||
}
|
||||
if extra > 0 {
|
||||
t.Vouchers = make([]*types.SignedVoucher, extra)
|
||||
t.Vouchers = make([]*paych.SignedVoucher, extra)
|
||||
}
|
||||
for i := 0; i < int(extra); i++ {
|
||||
|
||||
var v types.SignedVoucher
|
||||
var v paych.SignedVoucher
|
||||
if err := v.UnmarshalCBOR(br); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -196,7 +197,7 @@ func (t *SealedRef) MarshalCBOR(w io.Writer) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.SectorID (uint64) (uint64)
|
||||
// t.SectorID (abi.SectorNumber) (uint64)
|
||||
if len("SectorID") > cbg.MaxLength {
|
||||
return xerrors.Errorf("Value in field \"SectorID\" was too long")
|
||||
}
|
||||
@ -228,7 +229,7 @@ func (t *SealedRef) MarshalCBOR(w io.Writer) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.Size (uint64) (uint64)
|
||||
// t.Size (abi.UnpaddedPieceSize) (uint64)
|
||||
if len("Size") > cbg.MaxLength {
|
||||
return xerrors.Errorf("Value in field \"Size\" was too long")
|
||||
}
|
||||
@ -243,6 +244,7 @@ func (t *SealedRef) MarshalCBOR(w io.Writer) error {
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.Size))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -276,39 +278,51 @@ func (t *SealedRef) UnmarshalCBOR(r io.Reader) error {
|
||||
}
|
||||
|
||||
switch name {
|
||||
// t.SectorID (uint64) (uint64)
|
||||
// t.SectorID (abi.SectorNumber) (uint64)
|
||||
case "SectorID":
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
{
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if maj != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type for uint64 field")
|
||||
}
|
||||
t.SectorID = abi.SectorNumber(extra)
|
||||
|
||||
}
|
||||
if maj != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type for uint64 field")
|
||||
}
|
||||
t.SectorID = uint64(extra)
|
||||
// t.Offset (uint64) (uint64)
|
||||
case "Offset":
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
{
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if maj != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type for uint64 field")
|
||||
}
|
||||
t.Offset = uint64(extra)
|
||||
|
||||
}
|
||||
if maj != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type for uint64 field")
|
||||
}
|
||||
t.Offset = uint64(extra)
|
||||
// t.Size (uint64) (uint64)
|
||||
// t.Size (abi.UnpaddedPieceSize) (uint64)
|
||||
case "Size":
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
{
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if maj != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type for uint64 field")
|
||||
}
|
||||
t.Size = abi.UnpaddedPieceSize(extra)
|
||||
|
||||
}
|
||||
if maj != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type for uint64 field")
|
||||
}
|
||||
t.Size = uint64(extra)
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unknown struct field %d: '%s'", i, name)
|
||||
|
@ -74,9 +74,9 @@ func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
deal, err := client.ClientStartDeal(ctx, fcid, addr, maddr, types.NewInt(40000000), 100)
|
||||
deal, err := client.ClientStartDeal(ctx, fcid, addr, maddr, types.NewInt(1000000), 100)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
t.Fatalf("%+v", err)
|
||||
}
|
||||
|
||||
// TODO: this sleep is only necessary because deals don't immediately get logged in the dealstore, we should fix this
|
||||
|
@ -4,12 +4,12 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
)
|
||||
|
||||
type SignFunc = func(context.Context, []byte) (*types.Signature, error)
|
||||
type SignFunc = func(context.Context, []byte) (*crypto.Signature, error)
|
||||
|
||||
type Signer func(context.Context, address.Address, []byte) (*types.Signature, error)
|
||||
type Signer func(context.Context, address.Address, []byte) (*crypto.Signature, error)
|
||||
|
||||
type Signable interface {
|
||||
Sign(context.Context, SignFunc) error
|
||||
@ -17,7 +17,7 @@ type Signable interface {
|
||||
|
||||
func SignWith(ctx context.Context, signer Signer, addr address.Address, signable ...Signable) error {
|
||||
for _, s := range signable {
|
||||
err := s.Sign(ctx, func(ctx context.Context, b []byte) (*types.Signature, error) {
|
||||
err := s.Sign(ctx, func(ctx context.Context, b []byte) (*crypto.Signature, error) {
|
||||
return signer(ctx, addr, b)
|
||||
})
|
||||
if err != nil {
|
||||
|
177
bin/dist_get
177
bin/dist_get
@ -1,177 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
GOCC=${GOCC=go}
|
||||
|
||||
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."
|
||||
}
|
||||
|
||||
unarchive() {
|
||||
ua_archivetype="$1"
|
||||
ua_infile="$2"
|
||||
ua_outfile="$3"
|
||||
ua_distname="$4"
|
||||
ua_binpostfix=""
|
||||
ua_os=$(uname -o)
|
||||
|
||||
if [ "$ua_os" = "Msys" ] || [ "$ua_os" = "Cygwin" ] ; then
|
||||
ua_binpostfix=".exe"
|
||||
fi
|
||||
ua_outfile="$ua_outfile$ua_binpostfix"
|
||||
|
||||
if ! check_writable "$ua_outfile"; then
|
||||
die "unarchive error: cannot write to $ua_outfile"
|
||||
fi
|
||||
|
||||
case "$ua_archivetype" in
|
||||
tar.gz)
|
||||
if have_binary tar; then
|
||||
echo "==> using 'tar' to extract binary from archive"
|
||||
< "$ua_infile" tar -Ozxf - "$ua_distname/$ua_distname$ua_binpostfix" > "$ua_outfile" \
|
||||
|| die "tar has failed"
|
||||
else
|
||||
die "no binary on system for extracting tar files"
|
||||
fi
|
||||
;;
|
||||
zip)
|
||||
if have_binary unzip; then
|
||||
echo "==> using 'unzip' to extract binary from archive"
|
||||
unzip -p "$ua_infile" "$ua_distname/$ua_distname$ua_binpostfix" > "$ua_outfile" \
|
||||
|| die "unzip has failed"
|
||||
else
|
||||
die "no installed method for extracting .zip archives"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
die "unrecognized archive type '$ua_archivetype'"
|
||||
esac
|
||||
|
||||
chmod +x "$ua_outfile" || die "chmod has failed"
|
||||
}
|
||||
|
||||
get_go_vars() {
|
||||
if [ ! -z "$GOOS" ] && [ ! -z "$GOARCH" ]; then
|
||||
printf "%s-%s" "$GOOS" "$GOARCH"
|
||||
elif have_binary go; then
|
||||
printf "%s-%s" "$($GOCC env GOOS)" "$($GOCC env GOARCH)"
|
||||
else
|
||||
die "no way of determining system GOOS and GOARCH\nPlease manually set GOOS and GOARCH then retry."
|
||||
fi
|
||||
}
|
||||
|
||||
mkurl() {
|
||||
m_root="$1"
|
||||
m_name="$2"
|
||||
m_vers="$3"
|
||||
m_archive="$4"
|
||||
m_govars=$(get_go_vars) || die "could not get go env vars"
|
||||
|
||||
echo "https://ipfs.io$m_root/$m_name/$m_vers/${m_name}_${m_vers}_$m_govars.$m_archive"
|
||||
}
|
||||
|
||||
distroot="$1"
|
||||
distname="$2"
|
||||
outpath="$3"
|
||||
version="$4"
|
||||
|
||||
if [ -z "$distroot" ] || [ -z "$distname" ] || [ -z "$outpath" ] || [ -z "$version" ]; then
|
||||
die "usage: dist_get <distroot> <distname> <outpath> <version>"
|
||||
fi
|
||||
|
||||
case $version in
|
||||
v*)
|
||||
# correct input
|
||||
;;
|
||||
*)
|
||||
echo "invalid version '$version'" >&2
|
||||
die "versions must begin with 'v', for example: v0.4.0"
|
||||
;;
|
||||
esac
|
||||
|
||||
# TODO: don't depend on the go tool being installed to detect this
|
||||
goenv=$(get_go_vars) || die "could not get go env vars"
|
||||
|
||||
case $goenv in
|
||||
linux-*)
|
||||
archive="tar.gz"
|
||||
;;
|
||||
darwin-*)
|
||||
archive="tar.gz"
|
||||
;;
|
||||
windows-*)
|
||||
archive="zip"
|
||||
;;
|
||||
freebsd-*)
|
||||
archive="tar.gz"
|
||||
;;
|
||||
openbsd-*)
|
||||
archive="tar.gz"
|
||||
;;
|
||||
*)
|
||||
echo "unrecognized system environment: $goenv" >&2
|
||||
die "currently only linux, darwin, windows and freebsd are supported by this script"
|
||||
esac
|
||||
|
||||
|
||||
mkdir -p bin/tmp
|
||||
|
||||
url=$(mkurl "$distroot" "$distname" "$version" "$archive")
|
||||
tmpfi="bin/tmp/$distname.$archive"
|
||||
|
||||
download "$url" "$tmpfi"
|
||||
if [ $? -ne 0 ]; then
|
||||
die "failed to download $url to $tmpfi"
|
||||
fi
|
||||
|
||||
unarchive "$archive" "$tmpfi" "$outpath" "$distname"
|
||||
if [ $? -ne 0 ]; then
|
||||
die "failed to extract archive $tmpfi"
|
||||
fi
|
@ -2,11 +2,15 @@
|
||||
|
||||
package build
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
InsecurePoStValidation = true
|
||||
}
|
||||
|
||||
var SectorSizes = []uint64{1024}
|
||||
var SectorSizes = []abi.SectorSize{1024}
|
||||
|
||||
// Seconds
|
||||
const BlockDelay = 6
|
||||
|
@ -2,6 +2,8 @@ package build
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
)
|
||||
|
||||
// Core network constants
|
||||
@ -12,7 +14,7 @@ import (
|
||||
const UnixfsChunkSize uint64 = 1 << 20
|
||||
const UnixfsLinksPerLevel = 1024
|
||||
|
||||
func SupportedSectorSize(ssize uint64) bool {
|
||||
func SupportedSectorSize(ssize abi.SectorSize) bool {
|
||||
for _, ss := range SectorSizes {
|
||||
if ssize == ss {
|
||||
return true
|
||||
|
@ -2,7 +2,12 @@
|
||||
|
||||
package build
|
||||
|
||||
var SectorSizes = []uint64{
|
||||
import (
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||
)
|
||||
|
||||
var SectorSizes = []abi.SectorSize{
|
||||
32 << 30,
|
||||
}
|
||||
|
||||
@ -15,16 +20,13 @@ const PropagationDelay = 6
|
||||
// ElectionPeriodStart before starting fallback post computation
|
||||
//
|
||||
// Epochs
|
||||
const FallbackPoStDelay = 30
|
||||
const FallbackPoStDelay = miner.ProvingPeriod
|
||||
|
||||
// SlashablePowerDelay is the number of epochs after ElectionPeriodStart, after
|
||||
// which the miner is slashed
|
||||
//
|
||||
// Epochs
|
||||
const SlashablePowerDelay = 200
|
||||
|
||||
// Epochs
|
||||
const InteractivePoRepDelay = 8
|
||||
const SlashablePowerDelay = miner.ProvingPeriod * 3 // TODO: remove
|
||||
|
||||
// Epochs
|
||||
const InteractivePoRepConfidence = 6
|
||||
|
@ -5,7 +5,7 @@ import "fmt"
|
||||
var CurrentCommit string
|
||||
|
||||
// BuildVersion is the local build version, set by build system
|
||||
const BuildVersion = "0.2.8"
|
||||
const BuildVersion = "0.3.0"
|
||||
|
||||
var UserVersion = BuildVersion + CurrentCommit
|
||||
|
||||
@ -31,7 +31,7 @@ func (ve Version) EqMajorMinor(v2 Version) bool {
|
||||
}
|
||||
|
||||
// APIVersion is a semver version of the rpc api exposed
|
||||
var APIVersion Version = newVer(0, 1, 6)
|
||||
var APIVersion Version = newVer(0, 2, 0)
|
||||
|
||||
const (
|
||||
majorMask = 0xff0000
|
||||
|
@ -1,48 +0,0 @@
|
||||
package actors
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
type CronActor struct{}
|
||||
|
||||
type callTuple struct {
|
||||
addr address.Address
|
||||
method uint64
|
||||
}
|
||||
|
||||
var CronActors = []callTuple{
|
||||
{StoragePowerAddress, SPAMethods.CheckProofSubmissions},
|
||||
}
|
||||
|
||||
type CronActorState struct{}
|
||||
|
||||
type cAMethods struct {
|
||||
EpochTick uint64
|
||||
}
|
||||
|
||||
var CAMethods = cAMethods{2}
|
||||
|
||||
func (ca CronActor) Exports() []interface{} {
|
||||
return []interface{}{
|
||||
1: nil,
|
||||
2: ca.EpochTick,
|
||||
}
|
||||
}
|
||||
|
||||
func (ca CronActor) EpochTick(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
|
||||
if vmctx.Message().From != CronAddress {
|
||||
return nil, aerrors.New(1, "EpochTick is only callable as a part of tipset state computation")
|
||||
}
|
||||
|
||||
for _, call := range CronActors {
|
||||
_, err := vmctx.Send(call.addr, call.method, types.NewInt(0), nil)
|
||||
if err != nil {
|
||||
return nil, err // todo: this very bad?
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
@ -1,239 +0,0 @@
|
||||
package actors
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-hamt-ipld"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
mh "github.com/multiformats/go-multihash"
|
||||
)
|
||||
|
||||
var log = logging.Logger("actors")
|
||||
|
||||
var EmptyCBOR cid.Cid
|
||||
|
||||
const (
|
||||
GasCreateActor = 100
|
||||
)
|
||||
|
||||
var BuiltInActors map[cid.Cid]bool
|
||||
|
||||
func init() {
|
||||
|
||||
n, err := cbor.WrapObject(map[string]string{}, mh.SHA2_256, -1)
|
||||
if err != nil {
|
||||
panic(err) // ok
|
||||
}
|
||||
|
||||
EmptyCBOR = n.Cid()
|
||||
}
|
||||
|
||||
type InitActor struct{}
|
||||
|
||||
type InitActorState struct {
|
||||
AddressMap cid.Cid
|
||||
|
||||
NextID uint64
|
||||
}
|
||||
|
||||
type iAMethods struct {
|
||||
Exec uint64
|
||||
}
|
||||
|
||||
var IAMethods = iAMethods{2}
|
||||
|
||||
func (ia InitActor) Exports() []interface{} {
|
||||
return []interface{}{
|
||||
1: nil,
|
||||
2: ia.Exec,
|
||||
}
|
||||
}
|
||||
|
||||
type ExecParams struct {
|
||||
Code cid.Cid
|
||||
Params []byte
|
||||
}
|
||||
|
||||
func CreateExecParams(act cid.Cid, obj cbg.CBORMarshaler) ([]byte, aerrors.ActorError) {
|
||||
encparams, err := SerializeParams(obj)
|
||||
if err != nil {
|
||||
return nil, aerrors.Wrap(err, "creating ExecParams")
|
||||
}
|
||||
|
||||
return SerializeParams(&ExecParams{
|
||||
Code: act,
|
||||
Params: encparams,
|
||||
})
|
||||
}
|
||||
|
||||
func (ia InitActor) Exec(act *types.Actor, vmctx types.VMContext, p *ExecParams) ([]byte, aerrors.ActorError) {
|
||||
beginState := vmctx.Storage().GetHead()
|
||||
|
||||
var self InitActorState
|
||||
if err := vmctx.Storage().Get(beginState, &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := vmctx.ChargeGas(GasCreateActor); err != nil {
|
||||
return nil, aerrors.Wrap(err, "run out of gas")
|
||||
}
|
||||
|
||||
// Make sure that only the actors defined in the spec can be launched.
|
||||
if !IsBuiltinActor(p.Code) {
|
||||
return nil, aerrors.New(1,
|
||||
"cannot launch actor instance that is not a builtin actor")
|
||||
}
|
||||
|
||||
// Ensure that singletons can be only launched once.
|
||||
// TODO: do we want to enforce this? If so how should actors be marked as such?
|
||||
if IsSingletonActor(p.Code) {
|
||||
return nil, aerrors.New(1, "cannot launch another actor of this type")
|
||||
}
|
||||
|
||||
// This generates a unique address for this actor that is stable across message
|
||||
// reordering
|
||||
creator := vmctx.Message().From
|
||||
nonce := vmctx.Message().Nonce
|
||||
addr, err := ComputeActorAddress(creator, nonce)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set up the actor itself
|
||||
actor := types.Actor{
|
||||
Code: p.Code,
|
||||
Balance: types.NewInt(0),
|
||||
Head: EmptyCBOR,
|
||||
Nonce: 0,
|
||||
}
|
||||
|
||||
// The call to the actors constructor will set up the initial state
|
||||
// from the given parameters, setting `actor.Head` to a new value when successful.
|
||||
// TODO: can constructors fail?
|
||||
//actor.Constructor(p.Params)
|
||||
|
||||
// Store the mapping of address to actor ID.
|
||||
idAddr, nerr := self.AddActor(vmctx.Ipld(), addr)
|
||||
if nerr != nil {
|
||||
return nil, aerrors.Escalate(err, "adding new actor mapping")
|
||||
}
|
||||
|
||||
// NOTE: This is a privileged call that only the init actor is allowed to make
|
||||
// FIXME: Had to comment this because state is not in interface
|
||||
state, err := vmctx.StateTree()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := state.SetActor(idAddr, &actor); err != nil {
|
||||
if xerrors.Is(err, types.ErrActorNotFound) {
|
||||
return nil, aerrors.Absorb(err, 1, "SetActor, actor not found")
|
||||
}
|
||||
return nil, aerrors.Escalate(err, "inserting new actor into state tree")
|
||||
}
|
||||
|
||||
// '1' is reserved for constructor methods
|
||||
_, err = vmctx.Send(idAddr, 1, vmctx.Message().Value, p.Params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c, err := vmctx.Storage().Put(&self)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := vmctx.Storage().Commit(beginState, c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return idAddr.Bytes(), nil
|
||||
}
|
||||
|
||||
func IsBuiltinActor(code cid.Cid) bool {
|
||||
return BuiltInActors[code]
|
||||
}
|
||||
|
||||
func IsSingletonActor(code cid.Cid) bool {
|
||||
return code == StoragePowerCodeCid || code == StorageMarketCodeCid || code == InitCodeCid || code == CronCodeCid
|
||||
}
|
||||
|
||||
func (ias *InitActorState) AddActor(cst cbor.IpldStore, addr address.Address) (address.Address, error) {
|
||||
nid := ias.NextID
|
||||
|
||||
amap, err := hamt.LoadNode(context.TODO(), cst, ias.AddressMap)
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
if err := amap.Set(context.TODO(), string(addr.Bytes()), nid); err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
if err := amap.Flush(context.TODO()); err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
ncid, err := cst.Put(context.TODO(), amap)
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
ias.AddressMap = ncid
|
||||
ias.NextID++
|
||||
|
||||
return NewIDAddress(nid)
|
||||
}
|
||||
|
||||
func (ias *InitActorState) Lookup(cst cbor.IpldStore, addr address.Address) (address.Address, error) {
|
||||
amap, err := hamt.LoadNode(context.TODO(), cst, ias.AddressMap)
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("ias lookup failed loading hamt node: %w", err)
|
||||
}
|
||||
|
||||
var val interface{}
|
||||
err = amap.Find(context.TODO(), string(addr.Bytes()), &val)
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("ias lookup failed to do find: %w", err)
|
||||
}
|
||||
|
||||
ival, ok := val.(uint64)
|
||||
if !ok {
|
||||
return address.Undef, fmt.Errorf("invalid value in init actor state, expected uint64, got %T", val)
|
||||
}
|
||||
|
||||
return address.NewIDAddress(ival)
|
||||
}
|
||||
|
||||
type AccountActorState struct {
|
||||
Address address.Address
|
||||
}
|
||||
|
||||
func ComputeActorAddress(creator address.Address, nonce uint64) (address.Address, ActorError) {
|
||||
buf := new(bytes.Buffer)
|
||||
_, err := buf.Write(creator.Bytes())
|
||||
if err != nil {
|
||||
return address.Undef, aerrors.Escalate(err, "could not write address")
|
||||
}
|
||||
|
||||
err = binary.Write(buf, binary.BigEndian, nonce)
|
||||
if err != nil {
|
||||
return address.Undef, aerrors.Escalate(err, "could not write nonce")
|
||||
}
|
||||
|
||||
addr, err := address.NewActorAddress(buf.Bytes())
|
||||
if err != nil {
|
||||
return address.Undef, aerrors.Escalate(err, "could not create address")
|
||||
}
|
||||
return addr, nil
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,281 +0,0 @@
|
||||
package actors_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"math"
|
||||
"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/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/lib/rlepluslazy"
|
||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
"github.com/stretchr/testify/assert"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
)
|
||||
|
||||
func TestMinerCommitSectors(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})
|
||||
|
||||
}
|
||||
|
||||
type badRuns struct {
|
||||
done bool
|
||||
}
|
||||
|
||||
func (br *badRuns) HasNext() bool {
|
||||
return !br.done
|
||||
}
|
||||
|
||||
func (br *badRuns) NextRun() (rlepluslazy.Run, error) {
|
||||
br.done = true
|
||||
return rlepluslazy.Run{true, math.MaxInt64}, nil
|
||||
}
|
||||
|
||||
var _ rlepluslazy.RunIterator = (*badRuns)(nil)
|
||||
|
||||
func TestMinerSubmitBadFault(t *testing.T) {
|
||||
oldSS, oldMin := build.SectorSizes, build.MinimumMinerPower
|
||||
build.SectorSizes, build.MinimumMinerPower = []uint64{1024}, 1024
|
||||
defer func() {
|
||||
build.SectorSizes, build.MinimumMinerPower = oldSS, oldMin
|
||||
}()
|
||||
|
||||
var worker, client address.Address
|
||||
var minerAddr address.Address
|
||||
opts := []HarnessOpt{
|
||||
HarnessAddr(&worker, 1000000),
|
||||
HarnessAddr(&client, 1000000),
|
||||
HarnessAddMiner(&minerAddr, &worker),
|
||||
}
|
||||
|
||||
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})
|
||||
|
||||
st, err := getMinerState(context.TODO(), h.vm.StateTree(), h.bs, minerAddr)
|
||||
assert.NoError(t, err)
|
||||
expectedPower := st.Power
|
||||
if types.BigCmp(expectedPower, types.NewInt(1024)) != 0 {
|
||||
t.Errorf("Expected power of 1024, got %s", expectedPower)
|
||||
}
|
||||
|
||||
badnum := uint64(0)
|
||||
badnum--
|
||||
bf = types.NewBitField()
|
||||
bf.Set(badnum)
|
||||
bf.Set(badnum - 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{1})
|
||||
|
||||
st, err = getMinerState(context.TODO(), h.vm.StateTree(), h.bs, minerAddr)
|
||||
assert.NoError(t, err)
|
||||
currentPower := st.Power
|
||||
if types.BigCmp(expectedPower, currentPower) != 0 {
|
||||
t.Errorf("power changed and shouldn't have: %s != %s", expectedPower, currentPower)
|
||||
}
|
||||
|
||||
bf.Set(badnum - 2)
|
||||
ret, _ = h.Invoke(t, worker, minerAddr, actors.MAMethods.DeclareFaults, &actors.DeclareFaultsParams{bf})
|
||||
if ret.ExitCode != 3 {
|
||||
t.Errorf("expected exit code 3, got %d: %+v", ret.ExitCode, ret.ActorErr)
|
||||
}
|
||||
assertSectorIDs(h, t, minerAddr, []uint64{1})
|
||||
|
||||
rle, err := rlepluslazy.EncodeRuns(&badRuns{}, []byte{})
|
||||
assert.NoError(t, err)
|
||||
|
||||
bf, err = types.NewBitFieldFromBytes(rle)
|
||||
assert.NoError(t, err)
|
||||
ret, _ = h.Invoke(t, worker, minerAddr, actors.MAMethods.DeclareFaults, &actors.DeclareFaultsParams{bf})
|
||||
if ret.ExitCode != 3 {
|
||||
t.Errorf("expected exit code 3, got %d: %+v", ret.ExitCode, ret.ActorErr)
|
||||
}
|
||||
assertSectorIDs(h, t, minerAddr, []uint64{1})
|
||||
|
||||
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)
|
||||
deal := h.makeFakeDeal(t, minerAddr, worker, client, s)
|
||||
ret, _ := h.Invoke(t, worker, actors.StorageMarketAddress, actors.SMAMethods.PublishStorageDeals,
|
||||
&actors.PublishStorageDealsParams{
|
||||
Deals: []actors.StorageDealProposal{*deal},
|
||||
})
|
||||
ApplyOK(t, ret)
|
||||
var dealIds actors.PublishStorageDealResponse
|
||||
if err := dealIds.UnmarshalCBOR(bytes.NewReader(ret.Return)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
dealid := dealIds.DealIDs[0]
|
||||
|
||||
ret, _ = h.Invoke(t, worker, minerAddr, actors.MAMethods.PreCommitSector,
|
||||
&actors.SectorPreCommitInfo{
|
||||
SectorNumber: sid,
|
||||
CommR: []byte("cats"),
|
||||
SealEpoch: 10,
|
||||
DealIDs: []uint64{dealid},
|
||||
})
|
||||
ApplyOK(t, ret)
|
||||
|
||||
h.BlockHeight += 100
|
||||
ret, _ = h.Invoke(t, worker, minerAddr, actors.MAMethods.ProveCommitSector,
|
||||
&actors.SectorProveCommitInfo{
|
||||
Proof: []byte("prooofy"),
|
||||
SectorID: sid,
|
||||
DealIDs: []uint64{dealid}, // TODO: weird that i have to pass this again
|
||||
})
|
||||
ApplyOK(t, ret)
|
||||
}
|
||||
|
||||
func assertSectorIDs(h *Harness, t *testing.T, maddr address.Address, ids []uint64) {
|
||||
t.Helper()
|
||||
sectors, err := getMinerSectorSet(context.TODO(), h.vm.StateTree(), h.bs, maddr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(sectors) != len(ids) {
|
||||
t.Fatal("miner has wrong number of sectors in their sector set")
|
||||
}
|
||||
|
||||
all := make(map[uint64]bool)
|
||||
for _, s := range sectors {
|
||||
all[s.SectorID] = true
|
||||
}
|
||||
|
||||
for _, id := range ids {
|
||||
if !all[id] {
|
||||
t.Fatal("expected to find sector ID: ", id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getMinerState(ctx context.Context, st types.StateTree, bs blockstore.Blockstore, maddr address.Address) (*actors.StorageMinerActorState, error) {
|
||||
mact, err := st.GetActor(maddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cst := cbor.NewCborStore(bs)
|
||||
|
||||
var mstate actors.StorageMinerActorState
|
||||
if err := cst.Get(ctx, mact.Head, &mstate); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &mstate, nil
|
||||
}
|
||||
|
||||
func getMinerSectorSet(ctx context.Context, st types.StateTree, bs blockstore.Blockstore, maddr address.Address) ([]*api.ChainSectorInfo, error) {
|
||||
mstate, err := getMinerState(ctx, st, bs, maddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return stmgr.LoadSectorsFromSet(ctx, bs, mstate.Sectors)
|
||||
}
|
||||
|
||||
func (h *Harness) makeFakeDeal(t *testing.T, miner, worker, client address.Address, size uint64) *actors.StorageDealProposal {
|
||||
data := make([]byte, size)
|
||||
rand.Read(data)
|
||||
commP, err := sectorbuilder.GeneratePieceCommitment(bytes.NewReader(data), size)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
prop := actors.StorageDealProposal{
|
||||
PieceRef: commP[:],
|
||||
PieceSize: size,
|
||||
|
||||
Client: client,
|
||||
Provider: miner,
|
||||
|
||||
ProposalExpiration: 10000,
|
||||
Duration: 150,
|
||||
|
||||
StoragePricePerEpoch: types.NewInt(1),
|
||||
StorageCollateral: types.NewInt(0),
|
||||
}
|
||||
|
||||
if err := api.SignWith(context.TODO(), h.w.Sign, client, &prop); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return &prop
|
||||
}
|
@ -1,302 +0,0 @@
|
||||
package actors
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"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/types"
|
||||
)
|
||||
|
||||
type PaymentChannelActor struct{}
|
||||
|
||||
type PaymentInfo struct {
|
||||
PayChActor address.Address
|
||||
Payer address.Address
|
||||
ChannelMessage *cid.Cid
|
||||
|
||||
Vouchers []*types.SignedVoucher
|
||||
}
|
||||
|
||||
type LaneState struct {
|
||||
Closed bool
|
||||
Redeemed types.BigInt
|
||||
Nonce uint64
|
||||
}
|
||||
|
||||
type PaymentChannelActorState struct {
|
||||
From address.Address
|
||||
To address.Address
|
||||
|
||||
ToSend types.BigInt
|
||||
|
||||
ClosingAt uint64
|
||||
MinCloseHeight uint64
|
||||
|
||||
// TODO: needs to be map[uint64]*laneState
|
||||
// waiting on refmt#35 to be fixed
|
||||
LaneStates map[string]*LaneState
|
||||
}
|
||||
|
||||
func (pca PaymentChannelActor) Exports() []interface{} {
|
||||
return []interface{}{
|
||||
1: pca.Constructor,
|
||||
2: pca.UpdateChannelState,
|
||||
3: pca.Close,
|
||||
4: pca.Collect,
|
||||
5: pca.GetOwner,
|
||||
6: pca.GetToSend,
|
||||
}
|
||||
}
|
||||
|
||||
type pcaMethods struct {
|
||||
Constructor uint64
|
||||
UpdateChannelState uint64
|
||||
Close uint64
|
||||
Collect uint64
|
||||
GetOwner uint64
|
||||
GetToSend uint64
|
||||
}
|
||||
|
||||
var PCAMethods = pcaMethods{1, 2, 3, 4, 5, 6}
|
||||
|
||||
type PCAConstructorParams struct {
|
||||
To address.Address
|
||||
}
|
||||
|
||||
func (pca PaymentChannelActor) Constructor(act *types.Actor, vmctx types.VMContext, params *PCAConstructorParams) ([]byte, ActorError) {
|
||||
var self PaymentChannelActorState
|
||||
self.From = vmctx.Origin()
|
||||
self.To = params.To
|
||||
self.LaneStates = make(map[string]*LaneState)
|
||||
|
||||
storage := vmctx.Storage()
|
||||
c, err := storage.Put(&self)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := storage.Commit(EmptyCBOR, c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type PCAUpdateChannelStateParams struct {
|
||||
Sv types.SignedVoucher
|
||||
Secret []byte
|
||||
Proof []byte
|
||||
}
|
||||
|
||||
func hash(b []byte) []byte {
|
||||
s := blake2b.Sum256(b)
|
||||
return s[:]
|
||||
}
|
||||
|
||||
type PaymentVerifyParams struct {
|
||||
Extra []byte
|
||||
Proof []byte
|
||||
}
|
||||
|
||||
func (pca PaymentChannelActor) UpdateChannelState(act *types.Actor, vmctx types.VMContext, params *PCAUpdateChannelStateParams) ([]byte, ActorError) {
|
||||
var self PaymentChannelActorState
|
||||
oldstate := vmctx.Storage().GetHead()
|
||||
storage := vmctx.Storage()
|
||||
if err := storage.Get(oldstate, &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sv := params.Sv
|
||||
|
||||
vb, nerr := sv.SigningBytes()
|
||||
if nerr != nil {
|
||||
return nil, aerrors.Absorb(nerr, 1, "failed to serialize signedvoucher")
|
||||
}
|
||||
|
||||
if err := vmctx.VerifySignature(sv.Signature, self.From, vb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if vmctx.BlockHeight() < sv.TimeLock {
|
||||
return nil, aerrors.New(2, "cannot use this voucher yet!")
|
||||
}
|
||||
|
||||
if len(sv.SecretPreimage) > 0 {
|
||||
if !bytes.Equal(hash(params.Secret), sv.SecretPreimage) {
|
||||
return nil, aerrors.New(3, "incorrect secret!")
|
||||
}
|
||||
}
|
||||
|
||||
if sv.Extra != nil {
|
||||
encoded, err := SerializeParams(&PaymentVerifyParams{sv.Extra.Data, params.Proof})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = vmctx.Send(sv.Extra.Actor, sv.Extra.Method, types.NewInt(0), encoded)
|
||||
if err != nil {
|
||||
return nil, aerrors.Newf(4, "spend voucher verification failed: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
ls, ok := self.LaneStates[fmt.Sprint(sv.Lane)]
|
||||
if !ok {
|
||||
ls = new(LaneState)
|
||||
ls.Redeemed = types.NewInt(0) // TODO: kinda annoying that this doesnt default to a usable value
|
||||
self.LaneStates[fmt.Sprint(sv.Lane)] = ls
|
||||
}
|
||||
if ls.Closed {
|
||||
return nil, aerrors.New(5, "cannot redeem a voucher on a closed lane")
|
||||
}
|
||||
|
||||
if ls.Nonce > sv.Nonce {
|
||||
return nil, aerrors.New(6, "voucher has an outdated nonce, cannot redeem")
|
||||
}
|
||||
|
||||
mergeValue := types.NewInt(0)
|
||||
for _, merge := range sv.Merges {
|
||||
if merge.Lane == sv.Lane {
|
||||
return nil, aerrors.New(7, "voucher cannot merge its own lane")
|
||||
}
|
||||
|
||||
ols := self.LaneStates[fmt.Sprint(merge.Lane)]
|
||||
|
||||
if ols.Nonce >= merge.Nonce {
|
||||
return nil, aerrors.New(8, "merge in voucher has outdated nonce, cannot redeem")
|
||||
}
|
||||
|
||||
mergeValue = types.BigAdd(mergeValue, ols.Redeemed)
|
||||
ols.Nonce = merge.Nonce
|
||||
}
|
||||
|
||||
ls.Nonce = sv.Nonce
|
||||
balanceDelta := types.BigSub(sv.Amount, types.BigAdd(mergeValue, ls.Redeemed))
|
||||
ls.Redeemed = sv.Amount
|
||||
|
||||
newSendBalance := types.BigAdd(self.ToSend, balanceDelta)
|
||||
if newSendBalance.LessThan(types.NewInt(0)) {
|
||||
// TODO: is this impossible?
|
||||
return nil, aerrors.New(9, "voucher would leave channel balance negative")
|
||||
}
|
||||
|
||||
if newSendBalance.GreaterThan(act.Balance) {
|
||||
return nil, aerrors.New(10, "not enough funds in channel to cover voucher")
|
||||
}
|
||||
|
||||
log.Info("vals: ", newSendBalance, sv.Amount, balanceDelta, mergeValue, ls.Redeemed)
|
||||
self.ToSend = newSendBalance
|
||||
|
||||
if sv.MinCloseHeight != 0 {
|
||||
if self.ClosingAt != 0 && self.ClosingAt < sv.MinCloseHeight {
|
||||
self.ClosingAt = sv.MinCloseHeight
|
||||
}
|
||||
if self.MinCloseHeight < sv.MinCloseHeight {
|
||||
self.MinCloseHeight = sv.MinCloseHeight
|
||||
}
|
||||
}
|
||||
|
||||
ncid, err := storage.Put(&self)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := storage.Commit(oldstate, ncid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (pca PaymentChannelActor) Close(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, aerrors.ActorError) {
|
||||
var self PaymentChannelActorState
|
||||
storage := vmctx.Storage()
|
||||
oldstate := storage.GetHead()
|
||||
if err := storage.Get(oldstate, &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if vmctx.Message().From != self.From && vmctx.Message().From != self.To {
|
||||
return nil, aerrors.New(1, "not authorized to close channel")
|
||||
}
|
||||
|
||||
if self.ClosingAt != 0 {
|
||||
return nil, aerrors.New(2, "channel already closing")
|
||||
}
|
||||
|
||||
self.ClosingAt = vmctx.BlockHeight() + build.PaymentChannelClosingDelay
|
||||
if self.ClosingAt < self.MinCloseHeight {
|
||||
self.ClosingAt = self.MinCloseHeight
|
||||
}
|
||||
|
||||
ncid, err := storage.Put(&self)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := storage.Commit(oldstate, ncid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (pca PaymentChannelActor) Collect(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, aerrors.ActorError) {
|
||||
var self PaymentChannelActorState
|
||||
storage := vmctx.Storage()
|
||||
oldstate := storage.GetHead()
|
||||
if err := storage.Get(oldstate, &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if self.ClosingAt == 0 {
|
||||
return nil, aerrors.New(1, "payment channel not closing or closed")
|
||||
}
|
||||
|
||||
if vmctx.BlockHeight() < self.ClosingAt {
|
||||
return nil, aerrors.New(2, "payment channel not closed yet")
|
||||
}
|
||||
_, err := vmctx.Send(self.From, 0, types.BigSub(act.Balance, self.ToSend), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = vmctx.Send(self.To, 0, self.ToSend, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
self.ToSend = types.NewInt(0)
|
||||
|
||||
ncid, err := storage.Put(&self)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := storage.Commit(oldstate, ncid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (pca PaymentChannelActor) GetOwner(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, aerrors.ActorError) {
|
||||
var self PaymentChannelActorState
|
||||
storage := vmctx.Storage()
|
||||
if err := storage.Get(storage.GetHead(), &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return self.From.Bytes(), nil
|
||||
}
|
||||
|
||||
func (pca PaymentChannelActor) GetToSend(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, aerrors.ActorError) {
|
||||
var self PaymentChannelActorState
|
||||
storage := vmctx.Storage()
|
||||
if err := storage.Get(storage.GetHead(), &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return self.ToSend.Bytes(), nil
|
||||
}
|
@ -1,681 +0,0 @@
|
||||
package actors
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"sort"
|
||||
|
||||
"go.opencensus.io/trace"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-amt-ipld/v2"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-hamt-ipld"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
cborutil "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/types"
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
)
|
||||
|
||||
type StorageMarketActor struct{}
|
||||
|
||||
type smaMethods struct {
|
||||
Constructor uint64
|
||||
WithdrawBalance uint64
|
||||
AddBalance uint64
|
||||
CheckLockedBalance uint64
|
||||
PublishStorageDeals uint64
|
||||
HandleCronAction uint64
|
||||
SettleExpiredDeals uint64
|
||||
ProcessStorageDealsPayment uint64
|
||||
SlashStorageDealCollateral uint64
|
||||
GetLastExpirationFromDealIDs uint64
|
||||
ActivateStorageDeals uint64
|
||||
ComputeDataCommitment uint64
|
||||
}
|
||||
|
||||
var SMAMethods = smaMethods{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
|
||||
|
||||
func (sma StorageMarketActor) Exports() []interface{} {
|
||||
return []interface{}{
|
||||
2: sma.WithdrawBalance,
|
||||
3: sma.AddBalance,
|
||||
// 4: sma.CheckLockedBalance,
|
||||
5: sma.PublishStorageDeals,
|
||||
// 6: sma.HandleCronAction,
|
||||
// 7: sma.SettleExpiredDeals,
|
||||
// 8: sma.ProcessStorageDealsPayment,
|
||||
// 9: sma.SlashStorageDealCollateral,
|
||||
// 10: sma.GetLastExpirationFromDealIDs,
|
||||
11: sma.ActivateStorageDeals, // TODO: move under PublishStorageDeals after specs team approves
|
||||
12: sma.ComputeDataCommitment,
|
||||
}
|
||||
}
|
||||
|
||||
type StorageParticipantBalance struct {
|
||||
Locked types.BigInt
|
||||
Available types.BigInt
|
||||
}
|
||||
|
||||
type StorageMarketState struct {
|
||||
Balances cid.Cid // hamt<addr, StorageParticipantBalance>
|
||||
Deals cid.Cid // amt<StorageDeal>
|
||||
|
||||
NextDealID uint64 // TODO: spec
|
||||
}
|
||||
|
||||
// TODO: Drop in favour of car storage
|
||||
type SerializationMode = uint64
|
||||
|
||||
const (
|
||||
SerializationUnixFSv0 = iota
|
||||
// IPLD / car
|
||||
)
|
||||
|
||||
type StorageDealProposal struct {
|
||||
PieceRef []byte // cid bytes // TODO: spec says to use cid.Cid, probably not a good idea
|
||||
PieceSize uint64
|
||||
|
||||
Client address.Address
|
||||
Provider address.Address
|
||||
|
||||
ProposalExpiration uint64
|
||||
Duration uint64 // TODO: spec
|
||||
|
||||
StoragePricePerEpoch types.BigInt
|
||||
StorageCollateral types.BigInt
|
||||
|
||||
ProposerSignature *types.Signature
|
||||
}
|
||||
|
||||
func (sdp *StorageDealProposal) TotalStoragePrice() types.BigInt {
|
||||
return types.BigMul(sdp.StoragePricePerEpoch, types.NewInt(sdp.Duration))
|
||||
}
|
||||
|
||||
type SignFunc = func(context.Context, []byte) (*types.Signature, error)
|
||||
|
||||
func (sdp *StorageDealProposal) Sign(ctx context.Context, sign SignFunc) error {
|
||||
if sdp.ProposerSignature != nil {
|
||||
return xerrors.New("signature already present in StorageDealProposal")
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
if err := sdp.MarshalCBOR(&buf); err != nil {
|
||||
return err
|
||||
}
|
||||
sig, err := sign(ctx, buf.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sdp.ProposerSignature = sig
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sdp *StorageDealProposal) Cid() (cid.Cid, error) {
|
||||
nd, err := cborutil.AsIpld(sdp)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
return nd.Cid(), nil
|
||||
}
|
||||
|
||||
func (sdp *StorageDealProposal) Verify(worker address.Address) error {
|
||||
if sdp.Client != worker || worker == address.Undef {
|
||||
unsigned := *sdp
|
||||
unsigned.ProposerSignature = nil
|
||||
var buf bytes.Buffer
|
||||
if err := unsigned.MarshalCBOR(&buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := sigs.Verify(sdp.ProposerSignature, sdp.Client, buf.Bytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type OnChainDeal struct {
|
||||
PieceRef []byte // cid bytes // TODO: spec says to use cid.Cid, probably not a good idea
|
||||
PieceSize uint64
|
||||
|
||||
Client address.Address
|
||||
Provider address.Address
|
||||
|
||||
ProposalExpiration uint64
|
||||
Duration uint64 // TODO: spec
|
||||
|
||||
StoragePricePerEpoch types.BigInt
|
||||
StorageCollateral types.BigInt
|
||||
ActivationEpoch uint64 // 0 = inactive
|
||||
}
|
||||
|
||||
type WithdrawBalanceParams struct {
|
||||
Balance types.BigInt
|
||||
}
|
||||
|
||||
func (sma StorageMarketActor) WithdrawBalance(act *types.Actor, vmctx types.VMContext, params *WithdrawBalanceParams) ([]byte, ActorError) {
|
||||
// TODO: (spec) this should be 2-stage
|
||||
|
||||
var self StorageMarketState
|
||||
old := vmctx.Storage().GetHead()
|
||||
if err := vmctx.Storage().Get(old, &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, bnd, err := GetMarketBalances(vmctx.Context(), vmctx.Ipld(), self.Balances, vmctx.Message().From)
|
||||
if err != nil {
|
||||
return nil, aerrors.Wrap(err, "could not get balance")
|
||||
}
|
||||
|
||||
balance := b[0]
|
||||
|
||||
if balance.Available.LessThan(params.Balance) {
|
||||
return nil, aerrors.Newf(1, "can not withdraw more funds than available: %s > %s", params.Balance, b[0].Available)
|
||||
}
|
||||
|
||||
balance.Available = types.BigSub(balance.Available, params.Balance)
|
||||
|
||||
_, err = vmctx.Send(vmctx.Message().From, 0, params.Balance, nil)
|
||||
if err != nil {
|
||||
return nil, aerrors.Wrap(err, "sending funds failed")
|
||||
}
|
||||
|
||||
bcid, err := setMarketBalances(vmctx, bnd, map[address.Address]StorageParticipantBalance{
|
||||
vmctx.Message().From: balance,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
self.Balances = bcid
|
||||
|
||||
nroot, err := vmctx.Storage().Put(&self)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, vmctx.Storage().Commit(old, nroot)
|
||||
}
|
||||
|
||||
func (sma StorageMarketActor) AddBalance(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
|
||||
var self StorageMarketState
|
||||
old := vmctx.Storage().GetHead()
|
||||
if err := vmctx.Storage().Get(old, &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, bnd, err := GetMarketBalances(vmctx.Context(), vmctx.Ipld(), self.Balances, vmctx.Message().From)
|
||||
if err != nil {
|
||||
return nil, aerrors.Wrap(err, "could not get balance")
|
||||
}
|
||||
|
||||
balance := b[0]
|
||||
|
||||
balance.Available = types.BigAdd(balance.Available, vmctx.Message().Value)
|
||||
|
||||
bcid, err := setMarketBalances(vmctx, bnd, map[address.Address]StorageParticipantBalance{
|
||||
vmctx.Message().From: balance,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
self.Balances = bcid
|
||||
|
||||
nroot, err := vmctx.Storage().Put(&self)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, vmctx.Storage().Commit(old, nroot)
|
||||
}
|
||||
|
||||
func setMarketBalances(vmctx types.VMContext, nd *hamt.Node, set map[address.Address]StorageParticipantBalance) (cid.Cid, ActorError) {
|
||||
keys := make([]address.Address, 0, len(set))
|
||||
for k := range set {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Slice(keys, func(i, j int) bool {
|
||||
return bytes.Compare(keys[i].Bytes(), keys[j].Bytes()) < 0
|
||||
})
|
||||
for _, addr := range keys {
|
||||
balance := set[addr]
|
||||
if err := nd.Set(vmctx.Context(), string(addr.Bytes()), &balance); err != nil {
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "setting new balance")
|
||||
}
|
||||
}
|
||||
if err := nd.Flush(vmctx.Context()); err != nil {
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "flushing balance hamt")
|
||||
}
|
||||
|
||||
c, err := vmctx.Ipld().Put(vmctx.Context(), nd)
|
||||
if err != nil {
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "failed to balances storage")
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func GetMarketBalances(ctx context.Context, store cbor.IpldStore, 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")
|
||||
}
|
||||
|
||||
out := make([]StorageParticipantBalance, len(addrs))
|
||||
|
||||
for i, a := range addrs {
|
||||
var balance StorageParticipantBalance
|
||||
err = nd.Find(ctx, string(a.Bytes()), &balance)
|
||||
switch err {
|
||||
case hamt.ErrNotFound:
|
||||
out[i] = StorageParticipantBalance{
|
||||
Locked: types.NewInt(0),
|
||||
Available: types.NewInt(0),
|
||||
}
|
||||
case nil:
|
||||
out[i] = balance
|
||||
default:
|
||||
return nil, nil, aerrors.HandleExternalError(err, "failed to do set lookup")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return out, nd, nil
|
||||
}
|
||||
|
||||
/*
|
||||
func (sma StorageMarketActor) CheckLockedBalance(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
type PublishStorageDealsParams struct {
|
||||
Deals []StorageDealProposal
|
||||
}
|
||||
|
||||
type PublishStorageDealResponse struct {
|
||||
DealIDs []uint64
|
||||
}
|
||||
|
||||
func (sma StorageMarketActor) PublishStorageDeals(act *types.Actor, vmctx types.VMContext, params *PublishStorageDealsParams) ([]byte, ActorError) {
|
||||
var self StorageMarketState
|
||||
old := vmctx.Storage().GetHead()
|
||||
if err := vmctx.Storage().Get(old, &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
deals, err := amt.LoadAMT(vmctx.Context(), vmctx.Ipld(), self.Deals)
|
||||
if err != nil {
|
||||
return nil, aerrors.HandleExternalError(err, "loading deals amt")
|
||||
}
|
||||
|
||||
// todo: handle duplicate deals
|
||||
|
||||
if len(params.Deals) == 0 {
|
||||
return nil, aerrors.New(1, "no storage deals in params.Deals")
|
||||
}
|
||||
|
||||
out := PublishStorageDealResponse{
|
||||
DealIDs: make([]uint64, len(params.Deals)),
|
||||
}
|
||||
|
||||
workerBytes, aerr := vmctx.Send(params.Deals[0].Provider, MAMethods.GetWorkerAddr, types.NewInt(0), nil)
|
||||
if aerr != nil {
|
||||
return nil, aerr
|
||||
}
|
||||
providerWorker, err := address.NewFromBytes(workerBytes)
|
||||
if err != nil {
|
||||
return nil, aerrors.HandleExternalError(err, "parsing provider worker address bytes")
|
||||
}
|
||||
|
||||
// TODO: REVIEW: Do we want to check if provider exists in the power actor?
|
||||
|
||||
for i, deal := range params.Deals {
|
||||
if err := self.validateDeal(vmctx, deal, providerWorker); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err := deals.Set(vmctx.Context(), self.NextDealID, &OnChainDeal{
|
||||
PieceRef: deal.PieceRef,
|
||||
PieceSize: deal.PieceSize,
|
||||
|
||||
Client: deal.Client,
|
||||
Provider: deal.Provider,
|
||||
|
||||
ProposalExpiration: deal.ProposalExpiration,
|
||||
Duration: deal.Duration,
|
||||
|
||||
StoragePricePerEpoch: deal.StoragePricePerEpoch,
|
||||
StorageCollateral: deal.StorageCollateral,
|
||||
ActivationEpoch: 0,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, aerrors.HandleExternalError(err, "setting deal in deal AMT")
|
||||
}
|
||||
out.DealIDs[i] = self.NextDealID
|
||||
|
||||
self.NextDealID++
|
||||
}
|
||||
|
||||
dealsCid, err := deals.Flush(vmctx.Context())
|
||||
if err != nil {
|
||||
return nil, aerrors.HandleExternalError(err, "saving deals AMT")
|
||||
}
|
||||
|
||||
self.Deals = dealsCid
|
||||
|
||||
nroot, err := vmctx.Storage().Put(&self)
|
||||
if err != nil {
|
||||
return nil, aerrors.HandleExternalError(err, "storing state failed")
|
||||
}
|
||||
|
||||
aerr = vmctx.Storage().Commit(old, nroot)
|
||||
if aerr != nil {
|
||||
return nil, aerr
|
||||
}
|
||||
|
||||
var outBuf bytes.Buffer
|
||||
if err := out.MarshalCBOR(&outBuf); err != nil {
|
||||
return nil, aerrors.HandleExternalError(err, "serialising output")
|
||||
}
|
||||
|
||||
return outBuf.Bytes(), nil
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
if vmctx.Message().From != providerWorker {
|
||||
return aerrors.New(2, "Deals must be submitted by the miner worker")
|
||||
}
|
||||
|
||||
if err := deal.Verify(providerWorker); err != nil {
|
||||
return aerrors.Absorb(err, 3, "verifying proposer signature")
|
||||
}
|
||||
|
||||
// TODO: do some caching (changes gas so needs to be in spec too)
|
||||
b, bnd, aerr := GetMarketBalances(ctx, vmctx.Ipld(), st.Balances, deal.Client, providerWorker)
|
||||
if aerr != nil {
|
||||
return aerrors.Wrap(aerr, "getting client, and provider balances")
|
||||
}
|
||||
clientBalance := b[0]
|
||||
providerBalance := b[1]
|
||||
|
||||
totalPrice := deal.TotalStoragePrice()
|
||||
|
||||
if clientBalance.Available.LessThan(totalPrice) {
|
||||
return aerrors.Newf(5, "client doesn't have enough available funds to cover storage price; %d < %d", clientBalance.Available, totalPrice)
|
||||
}
|
||||
|
||||
clientBalance = lockFunds(clientBalance, totalPrice)
|
||||
|
||||
// TODO: REVIEW: Not clear who pays for this
|
||||
if providerBalance.Available.LessThan(deal.StorageCollateral) {
|
||||
return aerrors.Newf(6, "provider doesn't have enough available funds to cover StorageCollateral; %d < %d", providerBalance.Available, deal.StorageCollateral)
|
||||
}
|
||||
|
||||
providerBalance = lockFunds(providerBalance, deal.StorageCollateral)
|
||||
|
||||
// TODO: piece checks (e.g. size > sectorSize)?
|
||||
|
||||
bcid, aerr := setMarketBalances(vmctx, bnd, map[address.Address]StorageParticipantBalance{
|
||||
deal.Client: clientBalance,
|
||||
providerWorker: providerBalance,
|
||||
})
|
||||
if aerr != nil {
|
||||
return aerr
|
||||
}
|
||||
|
||||
st.Balances = bcid
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type ActivateStorageDealsParams struct {
|
||||
Deals []uint64
|
||||
}
|
||||
|
||||
func (sma StorageMarketActor) ActivateStorageDeals(act *types.Actor, vmctx types.VMContext, params *ActivateStorageDealsParams) ([]byte, ActorError) {
|
||||
ctx := vmctx.Context()
|
||||
var self StorageMarketState
|
||||
old := vmctx.Storage().GetHead()
|
||||
if err := vmctx.Storage().Get(old, &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
deals, err := amt.LoadAMT(ctx, vmctx.Ipld(), self.Deals)
|
||||
if err != nil {
|
||||
return nil, aerrors.HandleExternalError(err, "loading deals amt")
|
||||
}
|
||||
|
||||
for _, deal := range params.Deals {
|
||||
var dealInfo OnChainDeal
|
||||
if err := deals.Get(ctx, deal, &dealInfo); err != nil {
|
||||
if _, is := err.(*amt.ErrNotFound); is {
|
||||
return nil, aerrors.New(3, "deal not found")
|
||||
}
|
||||
return nil, aerrors.HandleExternalError(err, "getting deal info failed")
|
||||
}
|
||||
|
||||
if vmctx.Message().From != dealInfo.Provider {
|
||||
return nil, aerrors.New(1, "ActivateStorageDeals can only be called by the deal provider")
|
||||
}
|
||||
|
||||
if vmctx.BlockHeight() > dealInfo.ProposalExpiration {
|
||||
return nil, aerrors.New(2, "deal cannot be activated: proposal expired")
|
||||
}
|
||||
|
||||
if dealInfo.ActivationEpoch > 0 {
|
||||
// this probably can't happen in practice
|
||||
return nil, aerrors.New(3, "deal already active")
|
||||
}
|
||||
|
||||
dealInfo.ActivationEpoch = vmctx.BlockHeight()
|
||||
|
||||
if err := deals.Set(ctx, deal, &dealInfo); err != nil {
|
||||
return nil, aerrors.HandleExternalError(err, "setting deal info in AMT failed")
|
||||
}
|
||||
}
|
||||
|
||||
dealsCid, err := deals.Flush(ctx)
|
||||
if err != nil {
|
||||
return nil, aerrors.HandleExternalError(err, "saving deals AMT")
|
||||
}
|
||||
|
||||
self.Deals = dealsCid
|
||||
|
||||
nroot, err := vmctx.Storage().Put(&self)
|
||||
if err != nil {
|
||||
return nil, aerrors.HandleExternalError(err, "storing state failed")
|
||||
}
|
||||
|
||||
aerr := vmctx.Storage().Commit(old, nroot)
|
||||
if aerr != nil {
|
||||
return nil, aerr
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type ProcessStorageDealsPaymentParams struct {
|
||||
DealIDs []uint64
|
||||
}
|
||||
|
||||
func (sma StorageMarketActor) ProcessStorageDealsPayment(act *types.Actor, vmctx types.VMContext, params *ProcessStorageDealsPaymentParams) ([]byte, ActorError) {
|
||||
ctx := vmctx.Context()
|
||||
var self StorageMarketState
|
||||
old := vmctx.Storage().GetHead()
|
||||
if err := vmctx.Storage().Get(old, &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
deals, err := amt.LoadAMT(ctx, vmctx.Ipld(), self.Deals)
|
||||
if err != nil {
|
||||
return nil, aerrors.HandleExternalError(err, "loading deals amt")
|
||||
}
|
||||
|
||||
// TODO: Would be nice if send could assert actor type
|
||||
workerBytes, aerr := vmctx.Send(vmctx.Message().From, MAMethods.GetWorkerAddr, types.NewInt(0), nil)
|
||||
if aerr != nil {
|
||||
return nil, aerr
|
||||
}
|
||||
providerWorker, err := address.NewFromBytes(workerBytes)
|
||||
if err != nil {
|
||||
return nil, aerrors.HandleExternalError(err, "parsing provider worker address bytes")
|
||||
}
|
||||
|
||||
for _, deal := range params.DealIDs {
|
||||
var dealInfo OnChainDeal
|
||||
if err := deals.Get(ctx, deal, &dealInfo); err != nil {
|
||||
if _, is := err.(*amt.ErrNotFound); is {
|
||||
return nil, aerrors.New(2, "deal not found")
|
||||
}
|
||||
return nil, aerrors.HandleExternalError(err, "getting deal info failed")
|
||||
}
|
||||
|
||||
if dealInfo.Provider != vmctx.Message().From {
|
||||
return nil, aerrors.New(3, "ProcessStorageDealsPayment can only be called by deal provider")
|
||||
}
|
||||
|
||||
if vmctx.BlockHeight() < dealInfo.ActivationEpoch {
|
||||
// TODO: This is probably fatal
|
||||
return nil, aerrors.New(4, "ActivationEpoch lower than block height")
|
||||
}
|
||||
|
||||
if vmctx.BlockHeight() > dealInfo.ActivationEpoch+dealInfo.Duration {
|
||||
// Deal expired, miner should drop it
|
||||
// TODO: process payment for the remainder of last proving period
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
toPay := types.BigMul(dealInfo.StoragePricePerEpoch, types.NewInt(build.SlashablePowerDelay))
|
||||
|
||||
b, bnd, aerr := GetMarketBalances(vmctx.Context(), vmctx.Ipld(), self.Balances, dealInfo.Client, providerWorker)
|
||||
if aerr != nil {
|
||||
return nil, aerr
|
||||
}
|
||||
clientBal := b[0]
|
||||
providerBal := b[1]
|
||||
|
||||
clientBal.Locked, providerBal.Available = transferFunds(clientBal.Locked, providerBal.Available, toPay)
|
||||
|
||||
// TODO: call set once
|
||||
bcid, aerr := setMarketBalances(vmctx, bnd, map[address.Address]StorageParticipantBalance{
|
||||
dealInfo.Client: clientBal,
|
||||
providerWorker: providerBal,
|
||||
})
|
||||
if aerr != nil {
|
||||
return nil, aerr
|
||||
}
|
||||
|
||||
self.Balances = bcid
|
||||
}
|
||||
|
||||
nroot, err := vmctx.Storage().Put(&self)
|
||||
if err != nil {
|
||||
return nil, aerrors.HandleExternalError(err, "storing state failed")
|
||||
}
|
||||
|
||||
aerr = vmctx.Storage().Commit(old, nroot)
|
||||
if aerr != nil {
|
||||
return nil, aerr
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func lockFunds(p StorageParticipantBalance, amt types.BigInt) StorageParticipantBalance {
|
||||
p.Available, p.Locked = transferFunds(p.Available, p.Locked, amt)
|
||||
return p
|
||||
}
|
||||
|
||||
func transferFunds(from, to, amt types.BigInt) (types.BigInt, types.BigInt) {
|
||||
// TODO: some asserts
|
||||
return types.BigSub(from, amt), types.BigAdd(to, amt)
|
||||
}
|
||||
|
||||
type ComputeDataCommitmentParams struct {
|
||||
DealIDs []uint64
|
||||
SectorSize uint64
|
||||
}
|
||||
|
||||
func (sma StorageMarketActor) ComputeDataCommitment(act *types.Actor, vmctx types.VMContext, params *ComputeDataCommitmentParams) ([]byte, ActorError) {
|
||||
ctx := vmctx.Context()
|
||||
var self StorageMarketState
|
||||
old := vmctx.Storage().GetHead()
|
||||
if err := vmctx.Storage().Get(old, &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
deals, err := amt.LoadAMT(ctx, vmctx.Ipld(), self.Deals)
|
||||
if err != nil {
|
||||
return nil, aerrors.HandleExternalError(err, "loading deals amt")
|
||||
}
|
||||
|
||||
if len(params.DealIDs) == 0 {
|
||||
return nil, aerrors.New(3, "no deal IDs")
|
||||
}
|
||||
|
||||
var pieces []sectorbuilder.PublicPieceInfo
|
||||
for _, deal := range params.DealIDs {
|
||||
var dealInfo OnChainDeal
|
||||
if err := deals.Get(ctx, deal, &dealInfo); err != nil {
|
||||
if _, is := err.(*amt.ErrNotFound); is {
|
||||
return nil, aerrors.New(4, "deal not found")
|
||||
}
|
||||
return nil, aerrors.HandleExternalError(err, "getting deal info failed")
|
||||
}
|
||||
|
||||
if dealInfo.Provider != vmctx.Message().From {
|
||||
return nil, aerrors.New(5, "referenced deal was not from caller")
|
||||
}
|
||||
|
||||
var commP [32]byte
|
||||
copy(commP[:], dealInfo.PieceRef)
|
||||
|
||||
pieces = append(pieces, sectorbuilder.PublicPieceInfo{
|
||||
Size: dealInfo.PieceSize,
|
||||
CommP: commP,
|
||||
})
|
||||
}
|
||||
|
||||
commd, err := sectorbuilder.GenerateDataCommitment(params.SectorSize, pieces)
|
||||
if err != nil {
|
||||
return nil, aerrors.Absorb(err, 6, "failed to generate data commitment from pieces")
|
||||
}
|
||||
|
||||
return commd[:], nil
|
||||
}
|
||||
|
||||
/*
|
||||
func (sma StorageMarketActor) HandleCronAction(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
|
||||
|
||||
}
|
||||
|
||||
func (sma StorageMarketActor) SettleExpiredDeals(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
|
||||
|
||||
}
|
||||
|
||||
func (sma StorageMarketActor) SlashStorageDealCollateral(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
|
||||
|
||||
}
|
||||
|
||||
func (sma StorageMarketActor) GetLastExpirationFromDealIDs(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
|
||||
|
||||
}
|
||||
*/
|
@ -1,845 +0,0 @@
|
||||
package actors
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/filecoin-project/go-amt-ipld/v2"
|
||||
cid "github.com/ipfs/go-cid"
|
||||
hamt "github.com/ipfs/go-hamt-ipld"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"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/types"
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
)
|
||||
|
||||
type StoragePowerActor struct{}
|
||||
|
||||
type spaMethods struct {
|
||||
Constructor uint64
|
||||
CreateStorageMiner uint64
|
||||
ArbitrateConsensusFault uint64
|
||||
UpdateStorage uint64
|
||||
GetTotalStorage uint64
|
||||
PowerLookup uint64
|
||||
IsValidMiner uint64
|
||||
PledgeCollateralForSize uint64
|
||||
CheckProofSubmissions uint64
|
||||
}
|
||||
|
||||
var SPAMethods = spaMethods{1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||
|
||||
func (spa StoragePowerActor) Exports() []interface{} {
|
||||
return []interface{}{
|
||||
//1: spa.StoragePowerConstructor,
|
||||
2: spa.CreateStorageMiner,
|
||||
3: spa.ArbitrateConsensusFault,
|
||||
4: spa.UpdateStorage,
|
||||
5: spa.GetTotalStorage,
|
||||
6: spa.PowerLookup,
|
||||
7: spa.IsValidMiner,
|
||||
8: spa.PledgeCollateralForSize,
|
||||
9: spa.CheckProofSubmissions,
|
||||
}
|
||||
}
|
||||
|
||||
type StoragePowerState struct {
|
||||
Miners cid.Cid
|
||||
ProvingBuckets cid.Cid // amt[ProvingPeriodBucket]hamt[minerAddress]struct{}
|
||||
MinerCount uint64
|
||||
LastMinerCheck uint64
|
||||
|
||||
TotalStorage types.BigInt
|
||||
}
|
||||
|
||||
type CreateStorageMinerParams struct {
|
||||
Owner address.Address
|
||||
Worker address.Address
|
||||
SectorSize uint64
|
||||
PeerID peer.ID
|
||||
}
|
||||
|
||||
func (spa StoragePowerActor) CreateStorageMiner(act *types.Actor, vmctx types.VMContext, params *CreateStorageMinerParams) ([]byte, ActorError) {
|
||||
if !build.SupportedSectorSize(params.SectorSize) {
|
||||
return nil, aerrors.Newf(1, "Unsupported sector size: %d", params.SectorSize)
|
||||
}
|
||||
|
||||
var self StoragePowerState
|
||||
old := vmctx.Storage().GetHead()
|
||||
if err := vmctx.Storage().Get(old, &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reqColl, err := pledgeCollateralForSize(vmctx, types.NewInt(0), self.TotalStorage, self.MinerCount+1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if vmctx.Message().Value.LessThan(reqColl) {
|
||||
return nil, aerrors.Newf(1, "not enough funds passed to cover required miner collateral (needed %s, got %s)", reqColl, vmctx.Message().Value)
|
||||
}
|
||||
|
||||
minerCid := StorageMinerCodeCid
|
||||
|
||||
encoded, err := CreateExecParams(minerCid, &StorageMinerConstructorParams{
|
||||
Owner: params.Owner,
|
||||
Worker: params.Worker,
|
||||
SectorSize: params.SectorSize,
|
||||
PeerID: params.PeerID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret, err := vmctx.Send(InitAddress, IAMethods.Exec, vmctx.Message().Value, encoded)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
naddr, nerr := address.NewFromBytes(ret)
|
||||
if nerr != nil {
|
||||
return nil, aerrors.Absorb(nerr, 2, "could not read address of new actor")
|
||||
}
|
||||
|
||||
ncid, err := MinerSetAdd(context.TODO(), vmctx, self.Miners, naddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
self.Miners = ncid
|
||||
self.MinerCount++
|
||||
|
||||
nroot, err := vmctx.Storage().Put(&self)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := vmctx.Storage().Commit(old, nroot); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return naddr.Bytes(), nil
|
||||
}
|
||||
|
||||
type ArbitrateConsensusFaultParams struct {
|
||||
Block1 *types.BlockHeader
|
||||
Block2 *types.BlockHeader
|
||||
}
|
||||
|
||||
func (spa StoragePowerActor) ArbitrateConsensusFault(act *types.Actor, vmctx types.VMContext, params *ArbitrateConsensusFaultParams) ([]byte, ActorError) {
|
||||
if params == nil || params.Block1 == nil || params.Block2 == nil {
|
||||
return nil, aerrors.New(1, "failed to parse params")
|
||||
}
|
||||
|
||||
if params.Block1.Miner != params.Block2.Miner {
|
||||
return nil, aerrors.New(2, "blocks must be from the same miner")
|
||||
}
|
||||
|
||||
if params.Block1.Cid() == params.Block2.Cid() {
|
||||
return nil, aerrors.New(3, "blocks must be different")
|
||||
}
|
||||
|
||||
rval, err := vmctx.Send(params.Block1.Miner, MAMethods.GetWorkerAddr, types.NewInt(0), nil)
|
||||
if err != nil {
|
||||
return nil, aerrors.Wrap(err, "failed to get miner worker")
|
||||
}
|
||||
|
||||
worker, oerr := address.NewFromBytes(rval)
|
||||
if oerr != nil {
|
||||
// REVIEW: should this be fatal? i can't think of a real situation that would get us here
|
||||
return nil, aerrors.Absorb(oerr, 3, "response from 'GetWorkerAddr' was not a valid address")
|
||||
}
|
||||
|
||||
if err := sigs.CheckBlockSignature(params.Block1, vmctx.Context(), worker); err != nil {
|
||||
return nil, aerrors.Absorb(err, 4, "block1 did not have valid signature")
|
||||
}
|
||||
|
||||
if err := sigs.CheckBlockSignature(params.Block2, vmctx.Context(), worker); err != nil {
|
||||
return nil, aerrors.Absorb(err, 5, "block2 did not have valid signature")
|
||||
}
|
||||
|
||||
// see the "Consensus Faults" section of the faults spec (faults.md)
|
||||
// for details on these slashing conditions.
|
||||
if !shouldSlash(params.Block1, params.Block2) {
|
||||
return nil, aerrors.New(6, "blocks do not prove a slashable offense")
|
||||
}
|
||||
|
||||
var self StoragePowerState
|
||||
old := vmctx.Storage().GetHead()
|
||||
if err := vmctx.Storage().Get(old, &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if types.BigCmp(self.TotalStorage, types.NewInt(0)) == 0 {
|
||||
return nil, aerrors.Fatal("invalid state, storage power actor has zero total storage")
|
||||
}
|
||||
|
||||
miner := params.Block1.Miner
|
||||
if has, err := MinerSetHas(vmctx, self.Miners, miner); err != nil {
|
||||
return nil, aerrors.Wrapf(err, "failed to check miner in set")
|
||||
} else if !has {
|
||||
return nil, aerrors.New(7, "either already slashed or not a miner")
|
||||
}
|
||||
|
||||
minerPower, err := powerLookup(context.TODO(), vmctx, &self, miner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
slashedCollateral, err := pledgeCollateralForSize(vmctx, minerPower, self.TotalStorage, self.MinerCount)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
enc, err := SerializeParams(&MinerSlashConsensusFault{
|
||||
Slasher: vmctx.Message().From,
|
||||
AtHeight: params.Block1.Height,
|
||||
SlashedCollateral: slashedCollateral,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = vmctx.Send(miner, MAMethods.SlashConsensusFault, types.NewInt(0), enc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Remove the miner from the list of network miners
|
||||
ncid, err := MinerSetRemove(context.TODO(), vmctx, self.Miners, miner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
self.Miners = ncid
|
||||
self.MinerCount--
|
||||
|
||||
self.TotalStorage = types.BigSub(self.TotalStorage, minerPower)
|
||||
|
||||
nroot, err := vmctx.Storage().Put(&self)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := vmctx.Storage().Commit(old, nroot); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func cidArrContains(a []cid.Cid, b cid.Cid) bool {
|
||||
for _, c := range a {
|
||||
if b == c {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func shouldSlash(block1, block2 *types.BlockHeader) bool {
|
||||
// First slashing condition, blocks have the same ticket round
|
||||
if block1.Height == block2.Height {
|
||||
return true
|
||||
}
|
||||
|
||||
/* Second slashing condition requires having access to the parent tipset blocks
|
||||
// This might not always be available, needs some thought on the best way to deal with this
|
||||
|
||||
|
||||
// Second slashing condition, miner ignored own block when mining
|
||||
// Case A: block2 could have been in block1's parent set but is not
|
||||
b1ParentHeight := block1.Height - len(block1.Tickets)
|
||||
|
||||
block1ParentTipSet := block1.Parents
|
||||
if !cidArrContains(block1.Parents, block2.Cid()) &&
|
||||
b1ParentHeight == block2.Height &&
|
||||
block1ParentTipSet.ParentCids == block2.ParentCids {
|
||||
return true
|
||||
}
|
||||
|
||||
// Case B: block1 could have been in block2's parent set but is not
|
||||
block2ParentTipSet := parentOf(block2)
|
||||
if !block2Parent.contains(block1) &&
|
||||
block2ParentTipSet.Height == block1.Height &&
|
||||
block2ParentTipSet.ParentCids == block1.ParentCids {
|
||||
return true
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
type UpdateStorageParams struct {
|
||||
Delta types.BigInt
|
||||
NextSlashDeadline uint64
|
||||
PreviousSlashDeadline uint64
|
||||
}
|
||||
|
||||
func (spa StoragePowerActor) UpdateStorage(act *types.Actor, vmctx types.VMContext, params *UpdateStorageParams) ([]byte, ActorError) {
|
||||
ctx := vmctx.Context()
|
||||
var self StoragePowerState
|
||||
old := vmctx.Storage().GetHead()
|
||||
if err := vmctx.Storage().Get(old, &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
has, err := MinerSetHas(vmctx, self.Miners, vmctx.Message().From)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !has {
|
||||
return nil, aerrors.New(1, "update storage must only be called by a miner actor")
|
||||
}
|
||||
|
||||
self.TotalStorage = types.BigAdd(self.TotalStorage, params.Delta)
|
||||
|
||||
previousBucket := params.PreviousSlashDeadline % build.SlashablePowerDelay
|
||||
nextBucket := params.NextSlashDeadline % build.SlashablePowerDelay
|
||||
|
||||
if previousBucket == nextBucket && params.PreviousSlashDeadline != 0 {
|
||||
nroot, err := vmctx.Storage().Put(&self)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := vmctx.Storage().Commit(old, nroot); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil // Nothing to do
|
||||
}
|
||||
|
||||
buckets, eerr := amt.LoadAMT(ctx, vmctx.Ipld(), self.ProvingBuckets)
|
||||
if eerr != nil {
|
||||
return nil, aerrors.HandleExternalError(eerr, "loading proving buckets amt")
|
||||
}
|
||||
|
||||
if params.PreviousSlashDeadline != 0 { // delete from previous bucket
|
||||
err := deleteMinerFromBucket(vmctx, buckets, previousBucket)
|
||||
if err != nil {
|
||||
return nil, aerrors.Wrapf(err, "delete from bucket %d, next %d", previousBucket, nextBucket)
|
||||
}
|
||||
}
|
||||
|
||||
err = addMinerToBucket(vmctx, buckets, nextBucket)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
self.ProvingBuckets, eerr = buckets.Flush(ctx)
|
||||
if eerr != nil {
|
||||
return nil, aerrors.HandleExternalError(eerr, "flushing proving buckets")
|
||||
}
|
||||
|
||||
nroot, err := vmctx.Storage().Put(&self)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := vmctx.Storage().Commit(old, nroot); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func deleteMinerFromBucket(vmctx types.VMContext, buckets *amt.Root, previousBucket uint64) aerrors.ActorError {
|
||||
ctx := vmctx.Context()
|
||||
var bucket cid.Cid
|
||||
err := buckets.Get(ctx, previousBucket, &bucket)
|
||||
switch err.(type) {
|
||||
case *amt.ErrNotFound:
|
||||
return aerrors.HandleExternalError(err, "proving bucket missing")
|
||||
case nil: // noop
|
||||
default:
|
||||
return aerrors.HandleExternalError(err, "getting proving bucket")
|
||||
}
|
||||
|
||||
bhamt, err := hamt.LoadNode(vmctx.Context(), vmctx.Ipld(), bucket)
|
||||
if err != nil {
|
||||
return aerrors.HandleExternalError(err, "failed to load proving bucket")
|
||||
}
|
||||
err = bhamt.Delete(vmctx.Context(), string(vmctx.Message().From.Bytes()))
|
||||
if err != nil {
|
||||
return aerrors.HandleExternalError(err, "deleting miner from proving bucket")
|
||||
}
|
||||
|
||||
err = bhamt.Flush(vmctx.Context())
|
||||
if err != nil {
|
||||
return aerrors.HandleExternalError(err, "flushing previous proving bucket")
|
||||
}
|
||||
|
||||
bucket, err = vmctx.Ipld().Put(vmctx.Context(), bhamt)
|
||||
if err != nil {
|
||||
return aerrors.HandleExternalError(err, "putting previous proving bucket hamt")
|
||||
}
|
||||
|
||||
err = buckets.Set(ctx, previousBucket, bucket)
|
||||
if err != nil {
|
||||
return aerrors.HandleExternalError(err, "setting previous proving bucket cid in amt")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func addMinerToBucket(vmctx types.VMContext, buckets *amt.Root, nextBucket uint64) aerrors.ActorError {
|
||||
ctx := vmctx.Context()
|
||||
var bhamt *hamt.Node
|
||||
var bucket cid.Cid
|
||||
err := buckets.Get(ctx, nextBucket, &bucket)
|
||||
switch err.(type) {
|
||||
case *amt.ErrNotFound:
|
||||
bhamt = hamt.NewNode(vmctx.Ipld())
|
||||
case nil:
|
||||
bhamt, err = hamt.LoadNode(vmctx.Context(), vmctx.Ipld(), bucket)
|
||||
if err != nil {
|
||||
return aerrors.HandleExternalError(err, "failed to load proving bucket")
|
||||
}
|
||||
default:
|
||||
return aerrors.HandleExternalError(err, "getting proving bucket")
|
||||
}
|
||||
|
||||
err = bhamt.Set(vmctx.Context(), string(vmctx.Message().From.Bytes()), CborNull)
|
||||
if err != nil {
|
||||
return aerrors.HandleExternalError(err, "setting miner in proving bucket")
|
||||
}
|
||||
|
||||
err = bhamt.Flush(vmctx.Context())
|
||||
if err != nil {
|
||||
return aerrors.HandleExternalError(err, "flushing previous proving bucket")
|
||||
}
|
||||
|
||||
bucket, err = vmctx.Ipld().Put(vmctx.Context(), bhamt)
|
||||
if err != nil {
|
||||
return aerrors.HandleExternalError(err, "putting previous proving bucket hamt")
|
||||
}
|
||||
|
||||
err = buckets.Set(ctx, nextBucket, bucket)
|
||||
if err != nil {
|
||||
return aerrors.HandleExternalError(err, "setting previous proving bucket cid in amt")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (spa StoragePowerActor) GetTotalStorage(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
|
||||
var self StoragePowerState
|
||||
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return self.TotalStorage.Bytes(), nil
|
||||
}
|
||||
|
||||
type PowerLookupParams struct {
|
||||
Miner address.Address
|
||||
}
|
||||
|
||||
func (spa StoragePowerActor) PowerLookup(act *types.Actor, vmctx types.VMContext, params *PowerLookupParams) ([]byte, ActorError) {
|
||||
var self StoragePowerState
|
||||
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
|
||||
return nil, aerrors.Wrap(err, "getting head")
|
||||
}
|
||||
|
||||
pow, err := powerLookup(context.TODO(), vmctx, &self, params.Miner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return pow.Bytes(), nil
|
||||
}
|
||||
|
||||
func powerLookup(ctx context.Context, vmctx types.VMContext, self *StoragePowerState, miner address.Address) (types.BigInt, ActorError) {
|
||||
has, err := MinerSetHas(vmctx, self.Miners, miner)
|
||||
if err != nil {
|
||||
return types.EmptyInt, err
|
||||
}
|
||||
|
||||
if !has {
|
||||
// A miner could be registered with storage power actor, but removed for some reasons, e.g. consensus fault
|
||||
return types.EmptyInt, aerrors.New(1, "miner not registered with storage power actor, or removed already")
|
||||
}
|
||||
|
||||
// TODO: Use local amt
|
||||
ret, err := vmctx.Send(miner, MAMethods.GetPower, types.NewInt(0), nil)
|
||||
if err != nil {
|
||||
return types.EmptyInt, aerrors.Wrap(err, "invoke Miner.GetPower")
|
||||
}
|
||||
|
||||
return types.BigFromBytes(ret), nil
|
||||
}
|
||||
|
||||
type IsValidMinerParam struct {
|
||||
Addr address.Address
|
||||
}
|
||||
|
||||
func (spa StoragePowerActor) IsValidMiner(act *types.Actor, vmctx types.VMContext, param *IsValidMinerParam) ([]byte, ActorError) {
|
||||
var self StoragePowerState
|
||||
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
has, err := MinerSetHas(vmctx, self.Miners, param.Addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !has {
|
||||
log.Warnf("Miner INVALID: not in set: %s", param.Addr)
|
||||
|
||||
return cbg.CborBoolFalse, nil
|
||||
}
|
||||
|
||||
ret, err := vmctx.Send(param.Addr, MAMethods.IsSlashed, types.NewInt(0), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
slashed := bytes.Equal(ret, cbg.CborBoolTrue)
|
||||
|
||||
if slashed {
|
||||
log.Warnf("Miner INVALID: /SLASHED/ : %s", param.Addr)
|
||||
}
|
||||
|
||||
return cbg.EncodeBool(!slashed), nil
|
||||
}
|
||||
|
||||
type PledgeCollateralParams struct {
|
||||
Size types.BigInt
|
||||
}
|
||||
|
||||
func (spa StoragePowerActor) PledgeCollateralForSize(act *types.Actor, vmctx types.VMContext, param *PledgeCollateralParams) ([]byte, ActorError) {
|
||||
var self StoragePowerState
|
||||
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
totalCollateral, err := pledgeCollateralForSize(vmctx, param.Size, self.TotalStorage, self.MinerCount)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return totalCollateral.Bytes(), nil
|
||||
}
|
||||
|
||||
func pledgeCollateralForSize(vmctx types.VMContext, size, totalStorage types.BigInt, minerCount uint64) (types.BigInt, aerrors.ActorError) {
|
||||
netBalance, err := vmctx.GetBalance(NetworkAddress)
|
||||
if err != nil {
|
||||
return types.EmptyInt, err
|
||||
}
|
||||
|
||||
// TODO: the spec says to also grab 'total vested filecoin' and include it as available
|
||||
// If we don't factor that in, we effectively assume all of the locked up filecoin is 'available'
|
||||
// the blocker on that right now is that its hard to tell how much filecoin is unlocked
|
||||
|
||||
availableFilecoin := types.BigSub(
|
||||
types.BigMul(types.NewInt(build.TotalFilecoin), types.NewInt(build.FilecoinPrecision)),
|
||||
netBalance,
|
||||
)
|
||||
|
||||
totalPowerCollateral := types.BigDiv(
|
||||
types.BigMul(
|
||||
availableFilecoin,
|
||||
types.NewInt(build.PowerCollateralProportion),
|
||||
),
|
||||
types.NewInt(build.CollateralPrecision),
|
||||
)
|
||||
|
||||
totalPerCapitaCollateral := types.BigDiv(
|
||||
types.BigMul(
|
||||
availableFilecoin,
|
||||
types.NewInt(build.PerCapitaCollateralProportion),
|
||||
),
|
||||
types.NewInt(build.CollateralPrecision),
|
||||
)
|
||||
|
||||
// REVIEW: for bootstrapping purposes, we skip the power portion of the
|
||||
// collateral if there is no collateral in the network yet
|
||||
powerCollateral := types.NewInt(0)
|
||||
if types.BigCmp(totalStorage, types.NewInt(0)) != 0 {
|
||||
powerCollateral = types.BigDiv(
|
||||
types.BigMul(
|
||||
totalPowerCollateral,
|
||||
size,
|
||||
),
|
||||
totalStorage,
|
||||
)
|
||||
}
|
||||
|
||||
perCapCollateral := types.BigDiv(
|
||||
totalPerCapitaCollateral,
|
||||
types.NewInt(minerCount),
|
||||
)
|
||||
|
||||
return types.BigAdd(powerCollateral, perCapCollateral), nil
|
||||
}
|
||||
|
||||
func (spa StoragePowerActor) CheckProofSubmissions(act *types.Actor, vmctx types.VMContext, param *struct{}) ([]byte, ActorError) {
|
||||
if vmctx.Message().From != CronAddress {
|
||||
return nil, aerrors.New(1, "CheckProofSubmissions is only callable from the cron actor")
|
||||
}
|
||||
|
||||
var self StoragePowerState
|
||||
old := vmctx.Storage().GetHead()
|
||||
if err := vmctx.Storage().Get(old, &self); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := self.LastMinerCheck; i < vmctx.BlockHeight(); i++ {
|
||||
height := i + 1
|
||||
|
||||
err := checkProofSubmissionsAtH(vmctx, &self, height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
self.LastMinerCheck = vmctx.BlockHeight()
|
||||
|
||||
nroot, aerr := vmctx.Storage().Put(&self)
|
||||
if aerr != nil {
|
||||
return nil, aerr
|
||||
}
|
||||
|
||||
if err := vmctx.Storage().Commit(old, nroot); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func checkProofSubmissionsAtH(vmctx types.VMContext, self *StoragePowerState, height uint64) aerrors.ActorError {
|
||||
ctx := vmctx.Context()
|
||||
bucketID := height % build.SlashablePowerDelay
|
||||
|
||||
buckets, eerr := amt.LoadAMT(ctx, vmctx.Ipld(), self.ProvingBuckets)
|
||||
if eerr != nil {
|
||||
return aerrors.HandleExternalError(eerr, "loading proving buckets amt")
|
||||
}
|
||||
|
||||
var bucket cid.Cid
|
||||
err := buckets.Get(ctx, bucketID, &bucket)
|
||||
switch err.(type) {
|
||||
case *amt.ErrNotFound:
|
||||
return nil // nothing to do
|
||||
case nil:
|
||||
default:
|
||||
return aerrors.HandleExternalError(err, "getting proving bucket")
|
||||
}
|
||||
|
||||
bhamt, err := hamt.LoadNode(vmctx.Context(), vmctx.Ipld(), bucket)
|
||||
if err != nil {
|
||||
return aerrors.HandleExternalError(err, "failed to load proving bucket")
|
||||
}
|
||||
|
||||
forRemoval := make([]address.Address, 0)
|
||||
|
||||
err = bhamt.ForEach(vmctx.Context(), func(k string, val interface{}) error {
|
||||
_, span := trace.StartSpan(vmctx.Context(), "StoragePowerActor.CheckProofSubmissions.loop")
|
||||
defer span.End()
|
||||
|
||||
maddr, err := address.NewFromBytes([]byte(k))
|
||||
if err != nil {
|
||||
return aerrors.Escalate(err, "parsing miner address")
|
||||
}
|
||||
|
||||
has, aerr := MinerSetHas(vmctx, self.Miners, maddr)
|
||||
if aerr != nil {
|
||||
return aerr
|
||||
}
|
||||
|
||||
if !has {
|
||||
forRemoval = append(forRemoval, maddr)
|
||||
}
|
||||
|
||||
span.AddAttributes(trace.StringAttribute("miner", maddr.String()))
|
||||
|
||||
params, err := SerializeParams(&CheckMinerParams{NetworkPower: self.TotalStorage})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ret, err := vmctx.Send(maddr, MAMethods.CheckMiner, types.NewInt(0), params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(ret) == 0 {
|
||||
return nil // miner is fine
|
||||
}
|
||||
|
||||
var power types.BigInt
|
||||
if err := power.UnmarshalCBOR(bytes.NewReader(ret)); err != nil {
|
||||
return xerrors.Errorf("unmarshaling CheckMiner response (%x): %w", ret, err)
|
||||
}
|
||||
|
||||
if power.GreaterThan(types.NewInt(0)) {
|
||||
log.Warnf("slashing miner %s for missed PoSt (%s B, H: %d, Bucket: %d)", maddr, power, height, bucketID)
|
||||
|
||||
self.TotalStorage = types.BigSub(self.TotalStorage, power)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return aerrors.HandleExternalError(err, "iterating miners in proving bucket")
|
||||
}
|
||||
|
||||
if len(forRemoval) > 0 {
|
||||
nBucket, err := MinerSetRemove(vmctx.Context(), vmctx, bucket, forRemoval...)
|
||||
|
||||
if err != nil {
|
||||
return aerrors.Wrap(err, "could not remove miners from set")
|
||||
}
|
||||
|
||||
eerr := buckets.Set(ctx, bucketID, nBucket)
|
||||
if err != nil {
|
||||
return aerrors.HandleExternalError(eerr, "could not set the bucket")
|
||||
}
|
||||
ncid, eerr := buckets.Flush(ctx)
|
||||
if err != nil {
|
||||
return aerrors.HandleExternalError(eerr, "could not flush buckets")
|
||||
}
|
||||
self.ProvingBuckets = ncid
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func MinerSetHas(vmctx types.VMContext, rcid cid.Cid, maddr address.Address) (bool, aerrors.ActorError) {
|
||||
nd, err := hamt.LoadNode(vmctx.Context(), vmctx.Ipld(), rcid)
|
||||
if err != nil {
|
||||
return false, aerrors.HandleExternalError(err, "failed to load miner set")
|
||||
}
|
||||
|
||||
err = nd.Find(vmctx.Context(), string(maddr.Bytes()), nil)
|
||||
switch err {
|
||||
case hamt.ErrNotFound:
|
||||
return false, nil
|
||||
case nil:
|
||||
return true, nil
|
||||
default:
|
||||
return false, aerrors.HandleExternalError(err, "failed to do set lookup")
|
||||
}
|
||||
}
|
||||
|
||||
func MinerSetList(ctx context.Context, cst cbor.IpldStore, rcid cid.Cid) ([]address.Address, error) {
|
||||
nd, err := hamt.LoadNode(ctx, cst, rcid)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to load miner set: %w", err)
|
||||
}
|
||||
|
||||
var out []address.Address
|
||||
err = nd.ForEach(ctx, func(k string, val interface{}) error {
|
||||
addr, err := address.NewFromBytes([]byte(k))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out = append(out, addr)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func MinerSetAdd(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, maddr address.Address) (cid.Cid, aerrors.ActorError) {
|
||||
nd, err := hamt.LoadNode(ctx, vmctx.Ipld(), rcid)
|
||||
if err != nil {
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "failed to load miner set")
|
||||
}
|
||||
|
||||
mkey := string(maddr.Bytes())
|
||||
err = nd.Find(ctx, mkey, nil)
|
||||
if err == nil {
|
||||
return cid.Undef, aerrors.New(20, "miner already in set")
|
||||
}
|
||||
|
||||
if !xerrors.Is(err, hamt.ErrNotFound) {
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "failed to do miner set check")
|
||||
}
|
||||
|
||||
if err := nd.Set(ctx, mkey, uint64(1)); err != nil {
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "adding miner address to set failed")
|
||||
}
|
||||
|
||||
if err := nd.Flush(ctx); err != nil {
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "failed to flush miner set")
|
||||
}
|
||||
|
||||
c, err := vmctx.Ipld().Put(ctx, nd)
|
||||
if err != nil {
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "failed to persist miner set to storage")
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func MinerSetRemove(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, maddrs ...address.Address) (cid.Cid, aerrors.ActorError) {
|
||||
nd, err := hamt.LoadNode(ctx, vmctx.Ipld(), rcid)
|
||||
if err != nil {
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "failed to load miner set")
|
||||
}
|
||||
|
||||
for _, maddr := range maddrs {
|
||||
mkey := string(maddr.Bytes())
|
||||
switch nd.Delete(ctx, mkey) {
|
||||
default:
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "failed to delete miner from set")
|
||||
case hamt.ErrNotFound:
|
||||
return cid.Undef, aerrors.New(1, "miner not found in set on delete")
|
||||
case nil:
|
||||
}
|
||||
}
|
||||
|
||||
if err := nd.Flush(ctx); err != nil {
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "failed to flush miner set")
|
||||
}
|
||||
|
||||
c, err := vmctx.Ipld().Put(ctx, nd)
|
||||
if err != nil {
|
||||
return cid.Undef, aerrors.HandleExternalError(err, "failed to persist miner set to storage")
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
type cbgNull struct{}
|
||||
|
||||
var CborNull = &cbgNull{}
|
||||
|
||||
func (cbgNull) MarshalCBOR(w io.Writer) error {
|
||||
n, err := w.Write(cbg.CborNull)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n != 1 {
|
||||
return xerrors.New("expected to write 1 byte")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cbgNull) UnmarshalCBOR(r io.Reader) error {
|
||||
b := [1]byte{}
|
||||
n, err := r.Read(b[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n != 1 {
|
||||
return xerrors.New("expected 1 byte")
|
||||
}
|
||||
if !bytes.Equal(b[:], cbg.CborNull) {
|
||||
return xerrors.New("expected cbor null")
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
package actors
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
mh "github.com/multiformats/go-multihash"
|
||||
)
|
||||
|
||||
var AccountCodeCid cid.Cid
|
||||
var CronCodeCid cid.Cid
|
||||
var StoragePowerCodeCid cid.Cid
|
||||
var StorageMarketCodeCid cid.Cid
|
||||
var StorageMinerCodeCid cid.Cid
|
||||
var MultisigCodeCid cid.Cid
|
||||
var InitCodeCid cid.Cid
|
||||
var PaymentChannelCodeCid cid.Cid
|
||||
|
||||
var SystemAddress = mustIDAddress(0)
|
||||
var InitAddress = mustIDAddress(1)
|
||||
var RewardActor = mustIDAddress(2)
|
||||
var CronAddress = mustIDAddress(3)
|
||||
var StoragePowerAddress = mustIDAddress(4)
|
||||
var StorageMarketAddress = mustIDAddress(5)
|
||||
|
||||
var NetworkAddress = mustIDAddress(17) // TODO: needs to be removed in favor of reward actor
|
||||
|
||||
var BurntFundsAddress = mustIDAddress(99)
|
||||
|
||||
func mustIDAddress(i uint64) address.Address {
|
||||
a, err := address.NewIDAddress(i)
|
||||
if err != nil {
|
||||
panic(err) // ok
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func init() {
|
||||
pref := cid.NewPrefixV1(cid.Raw, mh.IDENTITY)
|
||||
mustSum := func(s string) cid.Cid {
|
||||
c, err := pref.Sum([]byte(s))
|
||||
if err != nil {
|
||||
panic(err) // ok
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
AccountCodeCid = mustSum("fil/1/account") // TODO: spec
|
||||
CronCodeCid = mustSum("fil/1/cron")
|
||||
StoragePowerCodeCid = mustSum("fil/1/power")
|
||||
StorageMarketCodeCid = mustSum("fil/1/market")
|
||||
StorageMinerCodeCid = mustSum("fil/1/miner")
|
||||
MultisigCodeCid = mustSum("fil/1/multisig")
|
||||
InitCodeCid = mustSum("fil/1/init")
|
||||
PaymentChannelCodeCid = mustSum("fil/1/paych")
|
||||
|
||||
BuiltInActors = map[cid.Cid]bool{
|
||||
StorageMarketCodeCid: true,
|
||||
StoragePowerCodeCid: true,
|
||||
StorageMinerCodeCid: true,
|
||||
AccountCodeCid: true,
|
||||
InitCodeCid: true,
|
||||
MultisigCodeCid: true,
|
||||
PaymentChannelCodeCid: true,
|
||||
}
|
||||
}
|
@ -7,15 +7,16 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/gen/genesis"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
dstore "github.com/ipfs/go-datastore"
|
||||
bstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
|
||||
. "github.com/filecoin-project/lotus/chain/actors"
|
||||
"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/chain/vm"
|
||||
dstore "github.com/ipfs/go-datastore"
|
||||
bstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
)
|
||||
|
||||
func blsaddr(n uint64) address.Address {
|
||||
@ -40,7 +41,7 @@ func setupVMTestEnv(t *testing.T) (*vm.VM, []address.Address, bstore.Blockstore)
|
||||
from: types.NewInt(1000000),
|
||||
maddr: types.NewInt(0),
|
||||
}
|
||||
st, err := gen.MakeInitialStateTree(bs, actors)
|
||||
st, err := genesis.MakeInitialStateTree(bs, actors)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1,14 +0,0 @@
|
||||
package actors
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||
)
|
||||
|
||||
func NewIDAddress(id uint64) (address.Address, ActorError) {
|
||||
a, err := address.NewIDAddress(id)
|
||||
if err != nil {
|
||||
return address.Undef, aerrors.Escalate(err, "could not create ID Address")
|
||||
}
|
||||
return a, nil
|
||||
}
|
@ -48,6 +48,26 @@ func Newf(retCode uint8, format string, args ...interface{}) ActorError {
|
||||
}
|
||||
}
|
||||
|
||||
// todo: bit hacky
|
||||
func NewfSkip(skip int, retCode uint8, format string, args ...interface{}) ActorError {
|
||||
if retCode == 0 {
|
||||
return &actorError{
|
||||
fatal: true,
|
||||
retCode: 0,
|
||||
|
||||
msg: "tried creating an error and setting RetCode to 0",
|
||||
frame: xerrors.Caller(skip),
|
||||
err: fmt.Errorf(format, args...),
|
||||
}
|
||||
}
|
||||
return &actorError{
|
||||
retCode: retCode,
|
||||
|
||||
msg: fmt.Sprintf(format, args...),
|
||||
frame: xerrors.Caller(skip),
|
||||
}
|
||||
}
|
||||
|
||||
func Fatal(message string, args ...interface{}) ActorError {
|
||||
return &actorError{
|
||||
fatal: true,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +0,0 @@
|
||||
package actors
|
||||
|
||||
import "github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||
|
||||
type ActorError = aerrors.ActorError
|
@ -1,46 +0,0 @@
|
||||
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())
|
||||
}
|
||||
}
|
@ -6,6 +6,8 @@ import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
|
||||
"github.com/filecoin-project/go-sectorbuilder"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
@ -17,8 +19,9 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/gen"
|
||||
"github.com/filecoin-project/lotus/chain/gen/genesis"
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
@ -49,7 +52,7 @@ type Harness struct {
|
||||
Nonces map[address.Address]uint64
|
||||
GasCharges map[address.Address]types.BigInt
|
||||
Rand vm.Rand
|
||||
BlockHeight uint64
|
||||
BlockHeight abi.ChainEpoch
|
||||
|
||||
lastBalanceCheck map[address.Address]types.BigInt
|
||||
|
||||
@ -181,7 +184,7 @@ func NewHarness(t *testing.T, options ...HarnessOpt) *Harness {
|
||||
}
|
||||
}
|
||||
|
||||
st, err := gen.MakeInitialStateTree(h.bs, h.HI.Addrs)
|
||||
st, err := genesis.MakeInitialStateTree(h.bs, h.HI.Addrs)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -191,7 +194,7 @@ func NewHarness(t *testing.T, options ...HarnessOpt) *Harness {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
stateroot, err = gen.SetupStorageMarketActor(h.bs, stateroot, nil)
|
||||
stateroot, err = genesis.SetupStorageMarketActor(h.bs, stateroot, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -7,10 +7,6 @@ import (
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
)
|
||||
|
||||
var (
|
||||
EmptyStructCBOR = []byte{0xa0}
|
||||
)
|
||||
|
||||
func SerializeParams(i cbg.CBORMarshaler) ([]byte, aerrors.ActorError) {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := i.MarshalCBOR(buf); err != nil {
|
||||
|
@ -22,8 +22,8 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
incrt "github.com/filecoin-project/lotus/lib/increadtimeout"
|
||||
"github.com/filecoin-project/lotus/lib/peermgr"
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
"github.com/filecoin-project/lotus/peermgr"
|
||||
)
|
||||
|
||||
type BlockSync struct {
|
||||
|
@ -7,7 +7,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"
|
||||
)
|
||||
@ -38,14 +38,17 @@ func (t *BlockSyncRequest) MarshalCBOR(w io.Writer) error {
|
||||
}
|
||||
|
||||
// t.RequestLength (uint64) (uint64)
|
||||
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.RequestLength))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.Options (uint64) (uint64)
|
||||
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.Options))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -92,24 +95,32 @@ func (t *BlockSyncRequest) UnmarshalCBOR(r io.Reader) error {
|
||||
|
||||
// t.RequestLength (uint64) (uint64)
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
{
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if maj != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type for uint64 field")
|
||||
}
|
||||
t.RequestLength = uint64(extra)
|
||||
|
||||
}
|
||||
if maj != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type for uint64 field")
|
||||
}
|
||||
t.RequestLength = uint64(extra)
|
||||
// t.Options (uint64) (uint64)
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
{
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if maj != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type for uint64 field")
|
||||
}
|
||||
t.Options = uint64(extra)
|
||||
|
||||
}
|
||||
if maj != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type for uint64 field")
|
||||
}
|
||||
t.Options = uint64(extra)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -137,6 +148,7 @@ func (t *BlockSyncResponse) MarshalCBOR(w io.Writer) error {
|
||||
}
|
||||
|
||||
// t.Status (uint64) (uint64)
|
||||
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.Status))); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -199,14 +211,18 @@ func (t *BlockSyncResponse) UnmarshalCBOR(r io.Reader) error {
|
||||
|
||||
// t.Status (uint64) (uint64)
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
{
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if maj != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type for uint64 field")
|
||||
}
|
||||
t.Status = uint64(extra)
|
||||
|
||||
}
|
||||
if maj != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type for uint64 field")
|
||||
}
|
||||
t.Status = uint64(extra)
|
||||
// t.Message (string) (string)
|
||||
|
||||
{
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/ipfs/go-cid"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"golang.org/x/xerrors"
|
||||
@ -19,7 +20,7 @@ import (
|
||||
var log = logging.Logger("events")
|
||||
|
||||
// `curH`-`ts.Height` = `confidence`
|
||||
type HeightHandler func(ctx context.Context, ts *types.TipSet, curH uint64) error
|
||||
type HeightHandler func(ctx context.Context, ts *types.TipSet, curH abi.ChainEpoch) error
|
||||
type RevertHandler func(ctx context.Context, ts *types.TipSet) error
|
||||
|
||||
type heightHandler struct {
|
||||
@ -33,7 +34,7 @@ type heightHandler struct {
|
||||
type eventApi interface {
|
||||
ChainNotify(context.Context) (<-chan []*store.HeadChange, error)
|
||||
ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error)
|
||||
ChainGetTipSetByHeight(context.Context, uint64, types.TipSetKey) (*types.TipSet, error)
|
||||
ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error)
|
||||
StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
|
||||
|
||||
StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) // optional / for CalledMsg
|
||||
@ -65,11 +66,11 @@ func NewEvents(ctx context.Context, api eventApi) *Events {
|
||||
heightEvents: heightEvents{
|
||||
tsc: tsc,
|
||||
ctx: ctx,
|
||||
gcConfidence: uint64(gcConfidence),
|
||||
gcConfidence: abi.ChainEpoch(gcConfidence),
|
||||
|
||||
heightTriggers: map[uint64]*heightHandler{},
|
||||
htTriggerHeights: map[uint64][]uint64{},
|
||||
htHeights: map[uint64][]uint64{},
|
||||
htTriggerHeights: map[abi.ChainEpoch][]uint64{},
|
||||
htHeights: map[abi.ChainEpoch][]uint64{},
|
||||
},
|
||||
|
||||
calledEvents: calledEvents{
|
||||
@ -82,7 +83,7 @@ func NewEvents(ctx context.Context, api eventApi) *Events {
|
||||
revertQueue: map[msgH][]triggerH{},
|
||||
triggers: map[triggerId]*callHandler{},
|
||||
matchers: map[triggerId][]MatchFunc{},
|
||||
timeouts: map[uint64]map[triggerId]int{},
|
||||
timeouts: map[abi.ChainEpoch]map[triggerId]int{},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"math"
|
||||
"sync"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/ipfs/go-cid"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
@ -12,20 +13,20 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
const NoTimeout = math.MaxUint64
|
||||
const NoTimeout = math.MaxInt64
|
||||
|
||||
type triggerId = uint64
|
||||
|
||||
// msgH is the block height at which a message was present / event has happened
|
||||
type msgH = uint64
|
||||
type msgH = abi.ChainEpoch
|
||||
|
||||
// triggerH is the block height at which the listener will be notified about the
|
||||
// message (msgH+confidence)
|
||||
type triggerH = uint64
|
||||
type triggerH = abi.ChainEpoch
|
||||
|
||||
// `ts` is the tipset, in which the `msg` is included.
|
||||
// `curH`-`ts.Height` = `confidence`
|
||||
type CalledHandler func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH uint64) (more bool, err error)
|
||||
type CalledHandler func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH abi.ChainEpoch) (more bool, err error)
|
||||
|
||||
// CheckFunc is used for atomicity guarantees. If the condition the callbacks
|
||||
// wait for has already happened in tipset `ts`
|
||||
@ -39,7 +40,7 @@ type MatchFunc func(msg *types.Message) (bool, error)
|
||||
|
||||
type callHandler struct {
|
||||
confidence int
|
||||
timeout uint64
|
||||
timeout abi.ChainEpoch
|
||||
|
||||
disabled bool // TODO: GC after gcConfidence reached
|
||||
|
||||
@ -50,7 +51,7 @@ type callHandler struct {
|
||||
type queuedEvent struct {
|
||||
trigger triggerId
|
||||
|
||||
h uint64
|
||||
h abi.ChainEpoch
|
||||
msg *types.Message
|
||||
|
||||
called bool
|
||||
@ -77,7 +78,7 @@ type calledEvents struct {
|
||||
revertQueue map[msgH][]triggerH
|
||||
|
||||
// [timeoutH+confidence][triggerId]{calls}
|
||||
timeouts map[uint64]map[triggerId]int
|
||||
timeouts map[abi.ChainEpoch]map[triggerId]int
|
||||
}
|
||||
|
||||
func (e *calledEvents) headChangeCalled(rev, app []*types.TipSet) error {
|
||||
@ -129,7 +130,7 @@ func (e *calledEvents) checkNewCalls(ts *types.TipSet) {
|
||||
for _, matchFn := range matchFns {
|
||||
ok, err := matchFn(msg)
|
||||
if err != nil {
|
||||
log.Warnf("event matcher failed: %s")
|
||||
log.Warnf("event matcher failed: %s", err)
|
||||
continue
|
||||
}
|
||||
matched = ok
|
||||
@ -153,11 +154,11 @@ func (e *calledEvents) queueForConfidence(triggerId uint64, msg *types.Message,
|
||||
// messages are not applied in the tipset they are included in
|
||||
appliedH := ts.Height() + 1
|
||||
|
||||
triggerH := appliedH + uint64(trigger.confidence)
|
||||
triggerH := appliedH + abi.ChainEpoch(trigger.confidence)
|
||||
|
||||
byOrigH, ok := e.confQueue[triggerH]
|
||||
if !ok {
|
||||
byOrigH = map[uint64][]*queuedEvent{}
|
||||
byOrigH = map[abi.ChainEpoch][]*queuedEvent{}
|
||||
e.confQueue[triggerH] = byOrigH
|
||||
}
|
||||
|
||||
@ -231,9 +232,9 @@ func (e *calledEvents) applyTimeouts(ts *types.TipSet) {
|
||||
continue
|
||||
}
|
||||
|
||||
timeoutTs, err := e.tsc.get(ts.Height() - uint64(trigger.confidence))
|
||||
timeoutTs, err := e.tsc.get(ts.Height() - abi.ChainEpoch(trigger.confidence))
|
||||
if err != nil {
|
||||
log.Errorf("events: applyTimeouts didn't find tipset for event; wanted %d; current %d", ts.Height()-uint64(trigger.confidence), ts.Height())
|
||||
log.Errorf("events: applyTimeouts didn't find tipset for event; wanted %d; current %d", ts.Height()-abi.ChainEpoch(trigger.confidence), ts.Height())
|
||||
}
|
||||
|
||||
more, err := trigger.handle(nil, nil, timeoutTs, ts.Height())
|
||||
@ -304,7 +305,7 @@ func (e *calledEvents) messagesForTs(ts *types.TipSet, consume func(*types.Messa
|
||||
// containing the message. The tipset passed as the argument is the tipset
|
||||
// that is being dropped. Note that the message dropped may be re-applied
|
||||
// in a different tipset in small amount of time.
|
||||
func (e *calledEvents) Called(check CheckFunc, hnd CalledHandler, rev RevertHandler, confidence int, timeout uint64, mf MatchFunc) error {
|
||||
func (e *calledEvents) Called(check CheckFunc, hnd CalledHandler, rev RevertHandler, confidence int, timeout abi.ChainEpoch, mf MatchFunc) error {
|
||||
e.lk.Lock()
|
||||
defer e.lk.Unlock()
|
||||
|
||||
@ -322,7 +323,7 @@ func (e *calledEvents) Called(check CheckFunc, hnd CalledHandler, rev RevertHand
|
||||
|
||||
e.triggers[id] = &callHandler{
|
||||
confidence: confidence,
|
||||
timeout: timeout + uint64(confidence),
|
||||
timeout: timeout + abi.ChainEpoch(confidence),
|
||||
|
||||
disabled: !more,
|
||||
|
||||
@ -333,15 +334,15 @@ func (e *calledEvents) Called(check CheckFunc, hnd CalledHandler, rev RevertHand
|
||||
e.matchers[id] = append(e.matchers[id], mf)
|
||||
|
||||
if timeout != NoTimeout {
|
||||
if e.timeouts[timeout+uint64(confidence)] == nil {
|
||||
e.timeouts[timeout+uint64(confidence)] = map[uint64]int{}
|
||||
if e.timeouts[timeout+abi.ChainEpoch(confidence)] == nil {
|
||||
e.timeouts[timeout+abi.ChainEpoch(confidence)] = map[uint64]int{}
|
||||
}
|
||||
e.timeouts[timeout+uint64(confidence)][id] = 0
|
||||
e.timeouts[timeout+abi.ChainEpoch(confidence)][id] = 0
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *calledEvents) CalledMsg(ctx context.Context, hnd CalledHandler, rev RevertHandler, confidence int, timeout uint64, msg store.ChainMsg) error {
|
||||
func (e *calledEvents) CalledMsg(ctx context.Context, hnd CalledHandler, rev RevertHandler, confidence int, timeout abi.ChainEpoch, msg store.ChainMsg) error {
|
||||
return e.Called(e.CheckMsg(ctx, msg, hnd), hnd, rev, confidence, timeout, e.MatchMsg(msg.VMMessage()))
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"go.opencensus.io/trace"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
@ -12,7 +13,7 @@ import (
|
||||
type heightEvents struct {
|
||||
lk sync.Mutex
|
||||
tsc *tipSetCache
|
||||
gcConfidence uint64
|
||||
gcConfidence abi.ChainEpoch
|
||||
|
||||
ctr triggerId
|
||||
|
||||
@ -35,7 +36,7 @@ func (e *heightEvents) headChangeAt(rev, app []*types.TipSet) error {
|
||||
// TODO: log error if h below gcconfidence
|
||||
// revert height-based triggers
|
||||
|
||||
revert := func(h uint64, ts *types.TipSet) {
|
||||
revert := func(h abi.ChainEpoch, ts *types.TipSet) {
|
||||
for _, tid := range e.htHeights[h] {
|
||||
ctx, span := trace.StartSpan(ctx, "events.HeightRevert")
|
||||
|
||||
@ -80,7 +81,7 @@ func (e *heightEvents) headChangeAt(rev, app []*types.TipSet) error {
|
||||
|
||||
// height triggers
|
||||
|
||||
apply := func(h uint64, ts *types.TipSet) error {
|
||||
apply := func(h abi.ChainEpoch, ts *types.TipSet) error {
|
||||
for _, tid := range e.htTriggerHeights[h] {
|
||||
hnd := e.heightTriggers[tid]
|
||||
if hnd.called {
|
||||
@ -88,7 +89,7 @@ func (e *heightEvents) headChangeAt(rev, app []*types.TipSet) error {
|
||||
}
|
||||
hnd.called = true
|
||||
|
||||
triggerH := h - uint64(hnd.confidence)
|
||||
triggerH := h - abi.ChainEpoch(hnd.confidence)
|
||||
|
||||
incTs, err := e.tsc.getNonNull(triggerH)
|
||||
if err != nil {
|
||||
@ -139,13 +140,13 @@ func (e *heightEvents) headChangeAt(rev, app []*types.TipSet) error {
|
||||
// specified height, `RevertHandler` will be called.
|
||||
//
|
||||
// ts passed to handlers is the tipset at the specified, or above, if lower tipsets were null
|
||||
func (e *heightEvents) ChainAt(hnd HeightHandler, rev RevertHandler, confidence int, h uint64) error {
|
||||
func (e *heightEvents) ChainAt(hnd HeightHandler, rev RevertHandler, confidence int, h abi.ChainEpoch) error {
|
||||
|
||||
e.lk.Lock() // Tricky locking, check your locks if you modify this function!
|
||||
|
||||
bestH := e.tsc.best().Height()
|
||||
|
||||
if bestH >= h+uint64(confidence) {
|
||||
if bestH >= h+abi.ChainEpoch(confidence) {
|
||||
ts, err := e.tsc.getNonNull(h)
|
||||
if err != nil {
|
||||
log.Warnf("events.ChainAt: calling HandleFunc with nil tipset, not found in cache: %s", err)
|
||||
@ -168,11 +169,11 @@ func (e *heightEvents) ChainAt(hnd HeightHandler, rev RevertHandler, confidence
|
||||
|
||||
defer e.lk.Unlock()
|
||||
|
||||
if bestH >= h+uint64(confidence)+e.gcConfidence {
|
||||
if bestH >= h+abi.ChainEpoch(confidence)+e.gcConfidence {
|
||||
return nil
|
||||
}
|
||||
|
||||
triggerAt := h + uint64(confidence)
|
||||
triggerAt := h + abi.ChainEpoch(confidence)
|
||||
|
||||
id := e.ctr
|
||||
e.ctr++
|
||||
|
@ -6,6 +6,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
|
||||
@ -31,7 +34,7 @@ type fakeMsg struct {
|
||||
|
||||
type fakeCS struct {
|
||||
t *testing.T
|
||||
h uint64
|
||||
h abi.ChainEpoch
|
||||
tsc *tipSetCache
|
||||
|
||||
msgs map[cid.Cid]fakeMsg
|
||||
@ -48,11 +51,11 @@ func (fcs *fakeCS) StateGetActor(ctx context.Context, actor address.Address, tsk
|
||||
panic("Not Implemented")
|
||||
}
|
||||
|
||||
func (fcs *fakeCS) ChainGetTipSetByHeight(context.Context, uint64, types.TipSetKey) (*types.TipSet, error) {
|
||||
func (fcs *fakeCS) ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) {
|
||||
panic("Not Implemented")
|
||||
}
|
||||
|
||||
func makeTs(t *testing.T, h uint64, msgcid cid.Cid) *types.TipSet {
|
||||
func makeTs(t *testing.T, h abi.ChainEpoch, msgcid cid.Cid) *types.TipSet {
|
||||
a, _ := address.NewFromString("t00")
|
||||
b, _ := address.NewFromString("t02")
|
||||
var ts, err = types.NewTipSet([]*types.BlockHeader{
|
||||
@ -66,8 +69,8 @@ func makeTs(t *testing.T, h uint64, msgcid cid.Cid) *types.TipSet {
|
||||
Messages: msgcid,
|
||||
ParentMessageReceipts: dummyCid,
|
||||
|
||||
BlockSig: &types.Signature{Type: types.KTBLS},
|
||||
BLSAggregate: types.Signature{Type: types.KTBLS},
|
||||
BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS},
|
||||
BLSAggregate: crypto.Signature{Type: crypto.SigTypeBLS},
|
||||
},
|
||||
{
|
||||
Height: h,
|
||||
@ -79,8 +82,8 @@ func makeTs(t *testing.T, h uint64, msgcid cid.Cid) *types.TipSet {
|
||||
Messages: msgcid,
|
||||
ParentMessageReceipts: dummyCid,
|
||||
|
||||
BlockSig: &types.Signature{Type: types.KTBLS},
|
||||
BLSAggregate: types.Signature{Type: types.KTBLS},
|
||||
BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS},
|
||||
BLSAggregate: crypto.Signature{Type: crypto.SigTypeBLS},
|
||||
},
|
||||
})
|
||||
|
||||
@ -206,7 +209,7 @@ func TestAt(t *testing.T) {
|
||||
var applied bool
|
||||
var reverted bool
|
||||
|
||||
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
|
||||
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
|
||||
require.Equal(t, 5, int(ts.Height()))
|
||||
require.Equal(t, 8, int(curH))
|
||||
applied = true
|
||||
@ -271,7 +274,7 @@ func TestAtDoubleTrigger(t *testing.T) {
|
||||
var applied bool
|
||||
var reverted bool
|
||||
|
||||
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
|
||||
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
|
||||
require.Equal(t, 5, int(ts.Height()))
|
||||
require.Equal(t, 8, int(curH))
|
||||
applied = true
|
||||
@ -313,8 +316,8 @@ func TestAtNullTrigger(t *testing.T) {
|
||||
var applied bool
|
||||
var reverted bool
|
||||
|
||||
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
|
||||
require.Equal(t, uint64(6), ts.Height())
|
||||
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
|
||||
require.Equal(t, abi.ChainEpoch(6), ts.Height())
|
||||
require.Equal(t, 8, int(curH))
|
||||
applied = true
|
||||
return nil
|
||||
@ -347,7 +350,7 @@ func TestAtNullConf(t *testing.T) {
|
||||
var applied bool
|
||||
var reverted bool
|
||||
|
||||
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
|
||||
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
|
||||
require.Equal(t, 5, int(ts.Height()))
|
||||
require.Equal(t, 8, int(curH))
|
||||
applied = true
|
||||
@ -388,7 +391,7 @@ func TestAtStart(t *testing.T) {
|
||||
var applied bool
|
||||
var reverted bool
|
||||
|
||||
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
|
||||
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
|
||||
require.Equal(t, 5, int(ts.Height()))
|
||||
require.Equal(t, 8, int(curH))
|
||||
applied = true
|
||||
@ -422,7 +425,7 @@ func TestAtStartConfidence(t *testing.T) {
|
||||
var applied bool
|
||||
var reverted bool
|
||||
|
||||
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
|
||||
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
|
||||
require.Equal(t, 5, int(ts.Height()))
|
||||
require.Equal(t, 11, int(curH))
|
||||
applied = true
|
||||
@ -450,8 +453,8 @@ func TestAtChained(t *testing.T) {
|
||||
var applied bool
|
||||
var reverted bool
|
||||
|
||||
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
|
||||
return events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
|
||||
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
|
||||
return events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
|
||||
require.Equal(t, 10, int(ts.Height()))
|
||||
applied = true
|
||||
return nil
|
||||
@ -486,8 +489,8 @@ func TestAtChainedConfidence(t *testing.T) {
|
||||
var applied bool
|
||||
var reverted bool
|
||||
|
||||
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
|
||||
return events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
|
||||
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
|
||||
return events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
|
||||
require.Equal(t, 10, int(ts.Height()))
|
||||
applied = true
|
||||
return nil
|
||||
@ -520,7 +523,7 @@ func TestAtChainedConfidenceNull(t *testing.T) {
|
||||
var applied bool
|
||||
var reverted bool
|
||||
|
||||
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH uint64) error {
|
||||
err := events.ChainAt(func(_ context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
|
||||
applied = true
|
||||
require.Equal(t, 6, int(ts.Height()))
|
||||
return nil
|
||||
@ -534,7 +537,7 @@ func TestAtChainedConfidenceNull(t *testing.T) {
|
||||
require.Equal(t, false, reverted)
|
||||
}
|
||||
|
||||
func matchAddrMethod(to address.Address, m uint64) func(msg *types.Message) (bool, error) {
|
||||
func matchAddrMethod(to address.Address, m abi.MethodNum) func(msg *types.Message) (bool, error) {
|
||||
return func(msg *types.Message) (bool, error) {
|
||||
return to == msg.To && m == msg.Method, nil
|
||||
}
|
||||
@ -560,11 +563,11 @@ func TestCalled(t *testing.T) {
|
||||
var applied, reverted bool
|
||||
var appliedMsg *types.Message
|
||||
var appliedTs *types.TipSet
|
||||
var appliedH uint64
|
||||
var appliedH abi.ChainEpoch
|
||||
|
||||
err = events.Called(func(ts *types.TipSet) (d bool, m bool, e error) {
|
||||
return false, true, nil
|
||||
}, func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH uint64) (bool, error) {
|
||||
}, func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH abi.ChainEpoch) (bool, error) {
|
||||
require.Equal(t, false, applied)
|
||||
applied = true
|
||||
appliedMsg = msg
|
||||
@ -610,12 +613,12 @@ func TestCalled(t *testing.T) {
|
||||
require.Equal(t, false, applied)
|
||||
require.Equal(t, false, reverted)
|
||||
|
||||
require.Equal(t, uint64(7), appliedTs.Height())
|
||||
require.Equal(t, abi.ChainEpoch(7), appliedTs.Height())
|
||||
require.Equal(t, "bafkqaaa", appliedTs.Blocks()[0].Messages.String())
|
||||
require.Equal(t, uint64(10), appliedH)
|
||||
require.Equal(t, abi.ChainEpoch(10), appliedH)
|
||||
require.Equal(t, t0123, appliedMsg.To)
|
||||
require.Equal(t, uint64(1), appliedMsg.Nonce)
|
||||
require.Equal(t, uint64(5), appliedMsg.Method)
|
||||
require.Equal(t, abi.MethodNum(5), appliedMsg.Method)
|
||||
|
||||
// revert some blocks, keep the message
|
||||
|
||||
@ -647,12 +650,12 @@ func TestCalled(t *testing.T) {
|
||||
require.Equal(t, false, reverted)
|
||||
applied = false
|
||||
|
||||
require.Equal(t, uint64(9), appliedTs.Height())
|
||||
require.Equal(t, abi.ChainEpoch(9), appliedTs.Height())
|
||||
require.Equal(t, "bafkqaaa", appliedTs.Blocks()[0].Messages.String())
|
||||
require.Equal(t, uint64(12), appliedH)
|
||||
require.Equal(t, abi.ChainEpoch(12), appliedH)
|
||||
require.Equal(t, t0123, appliedMsg.To)
|
||||
require.Equal(t, uint64(2), appliedMsg.Nonce)
|
||||
require.Equal(t, uint64(5), appliedMsg.Method)
|
||||
require.Equal(t, abi.MethodNum(5), appliedMsg.Method)
|
||||
|
||||
// revert and apply at different height
|
||||
|
||||
@ -668,12 +671,12 @@ func TestCalled(t *testing.T) {
|
||||
reverted = false
|
||||
applied = false
|
||||
|
||||
require.Equal(t, uint64(11), appliedTs.Height())
|
||||
require.Equal(t, abi.ChainEpoch(11), appliedTs.Height())
|
||||
require.Equal(t, "bafkqaaa", appliedTs.Blocks()[0].Messages.String())
|
||||
require.Equal(t, uint64(14), appliedH)
|
||||
require.Equal(t, abi.ChainEpoch(14), appliedH)
|
||||
require.Equal(t, t0123, appliedMsg.To)
|
||||
require.Equal(t, uint64(2), appliedMsg.Nonce)
|
||||
require.Equal(t, uint64(5), appliedMsg.Method)
|
||||
require.Equal(t, abi.MethodNum(5), appliedMsg.Method)
|
||||
|
||||
// call method again
|
||||
|
||||
@ -765,11 +768,11 @@ func TestCalledTimeout(t *testing.T) {
|
||||
|
||||
err = events.Called(func(ts *types.TipSet) (d bool, m bool, e error) {
|
||||
return false, true, nil
|
||||
}, func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH uint64) (bool, error) {
|
||||
}, func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH abi.ChainEpoch) (bool, error) {
|
||||
called = true
|
||||
require.Nil(t, msg)
|
||||
require.Equal(t, uint64(20), ts.Height())
|
||||
require.Equal(t, uint64(23), curH)
|
||||
require.Equal(t, abi.ChainEpoch(20), ts.Height())
|
||||
require.Equal(t, abi.ChainEpoch(23), curH)
|
||||
return false, nil
|
||||
}, func(_ context.Context, ts *types.TipSet) error {
|
||||
t.Fatal("revert on timeout")
|
||||
@ -800,11 +803,11 @@ func TestCalledTimeout(t *testing.T) {
|
||||
|
||||
err = events.Called(func(ts *types.TipSet) (d bool, m bool, e error) {
|
||||
return true, true, nil
|
||||
}, func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH uint64) (bool, error) {
|
||||
}, func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH abi.ChainEpoch) (bool, error) {
|
||||
called = true
|
||||
require.Nil(t, msg)
|
||||
require.Equal(t, uint64(20), ts.Height())
|
||||
require.Equal(t, uint64(23), curH)
|
||||
require.Equal(t, abi.ChainEpoch(20), ts.Height())
|
||||
require.Equal(t, abi.ChainEpoch(23), curH)
|
||||
return false, nil
|
||||
}, func(_ context.Context, ts *types.TipSet) error {
|
||||
t.Fatal("revert on timeout")
|
||||
@ -839,14 +842,14 @@ func TestCalledOrder(t *testing.T) {
|
||||
|
||||
err = events.Called(func(ts *types.TipSet) (d bool, m bool, e error) {
|
||||
return false, true, nil
|
||||
}, func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH uint64) (bool, error) {
|
||||
}, func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH abi.ChainEpoch) (bool, error) {
|
||||
switch at {
|
||||
case 0:
|
||||
require.Equal(t, uint64(1), msg.Nonce)
|
||||
require.Equal(t, uint64(4), ts.Height())
|
||||
require.Equal(t, abi.ChainEpoch(4), ts.Height())
|
||||
case 1:
|
||||
require.Equal(t, uint64(2), msg.Nonce)
|
||||
require.Equal(t, uint64(5), ts.Height())
|
||||
require.Equal(t, abi.ChainEpoch(5), ts.Height())
|
||||
default:
|
||||
t.Fatal("apply should only get called twice, at: ", at)
|
||||
}
|
||||
@ -855,9 +858,9 @@ func TestCalledOrder(t *testing.T) {
|
||||
}, func(_ context.Context, ts *types.TipSet) error {
|
||||
switch at {
|
||||
case 2:
|
||||
require.Equal(t, uint64(5), ts.Height())
|
||||
require.Equal(t, abi.ChainEpoch(5), ts.Height())
|
||||
case 3:
|
||||
require.Equal(t, uint64(4), ts.Height())
|
||||
require.Equal(t, abi.ChainEpoch(4), ts.Height())
|
||||
default:
|
||||
t.Fatal("revert should only get called twice, at: ", at)
|
||||
}
|
||||
|
@ -3,12 +3,13 @@ package events
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
type tsByHFunc func(context.Context, uint64, types.TipSetKey) (*types.TipSet, error)
|
||||
type tsByHFunc func(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error)
|
||||
|
||||
// tipSetCache implements a simple ring-buffer cache to keep track of recent
|
||||
// tipsets
|
||||
@ -77,7 +78,7 @@ func (tsc *tipSetCache) revert(ts *types.TipSet) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tsc *tipSetCache) getNonNull(height uint64) (*types.TipSet, error) {
|
||||
func (tsc *tipSetCache) getNonNull(height abi.ChainEpoch) (*types.TipSet, error) {
|
||||
for {
|
||||
ts, err := tsc.get(height)
|
||||
if err != nil {
|
||||
@ -90,7 +91,7 @@ func (tsc *tipSetCache) getNonNull(height uint64) (*types.TipSet, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (tsc *tipSetCache) get(height uint64) (*types.TipSet, error) {
|
||||
func (tsc *tipSetCache) get(height abi.ChainEpoch) (*types.TipSet, error) {
|
||||
if tsc.len == 0 {
|
||||
log.Warnf("tipSetCache.get: cache is empty, requesting from storage (h=%d)", height)
|
||||
return tsc.storage(context.TODO(), height, types.EmptyTSK)
|
||||
|
@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
@ -11,12 +13,12 @@ import (
|
||||
)
|
||||
|
||||
func TestTsCache(t *testing.T) {
|
||||
tsc := newTSCache(50, func(context.Context, uint64, types.TipSetKey) (*types.TipSet, error) {
|
||||
tsc := newTSCache(50, func(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) {
|
||||
t.Fatal("storage call")
|
||||
return &types.TipSet{}, nil
|
||||
})
|
||||
|
||||
h := uint64(75)
|
||||
h := abi.ChainEpoch(75)
|
||||
|
||||
a, _ := address.NewFromString("t00")
|
||||
|
||||
@ -27,8 +29,8 @@ func TestTsCache(t *testing.T) {
|
||||
ParentStateRoot: dummyCid,
|
||||
Messages: dummyCid,
|
||||
ParentMessageReceipts: dummyCid,
|
||||
BlockSig: &types.Signature{Type: types.KTBLS},
|
||||
BLSAggregate: types.Signature{Type: types.KTBLS},
|
||||
BlockSig: &types.Signature{Type: crypto.SigTypeBLS},
|
||||
BLSAggregate: types.Signature{Type: crypto.SigTypeBLS},
|
||||
}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -54,12 +56,12 @@ func TestTsCache(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTsCacheNulls(t *testing.T) {
|
||||
tsc := newTSCache(50, func(context.Context, uint64, types.TipSetKey) (*types.TipSet, error) {
|
||||
tsc := newTSCache(50, func(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) {
|
||||
t.Fatal("storage call")
|
||||
return &types.TipSet{}, nil
|
||||
})
|
||||
|
||||
h := uint64(75)
|
||||
h := abi.ChainEpoch(75)
|
||||
|
||||
a, _ := address.NewFromString("t00")
|
||||
add := func() {
|
||||
@ -69,8 +71,8 @@ func TestTsCacheNulls(t *testing.T) {
|
||||
ParentStateRoot: dummyCid,
|
||||
Messages: dummyCid,
|
||||
ParentMessageReceipts: dummyCid,
|
||||
BlockSig: &types.Signature{Type: types.KTBLS},
|
||||
BLSAggregate: types.Signature{Type: types.KTBLS},
|
||||
BlockSig: &types.Signature{Type: crypto.SigTypeBLS},
|
||||
BLSAggregate: types.Signature{Type: crypto.SigTypeBLS},
|
||||
}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
220
chain/gen/gen.go
220
chain/gen/gen.go
@ -4,26 +4,29 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
commcid "github.com/filecoin-project/go-fil-commcid"
|
||||
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
block "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-blockservice"
|
||||
"github.com/ipfs/go-car"
|
||||
"github.com/ipfs/go-cid"
|
||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
offline "github.com/ipfs/go-ipfs-exchange-offline"
|
||||
format "github.com/ipfs/go-ipld-format"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"github.com/ipfs/go-merkledag"
|
||||
peer "github.com/libp2p/go-libp2p-core/peer"
|
||||
|
||||
ffi "github.com/filecoin-project/filecoin-ffi"
|
||||
"github.com/filecoin-project/go-address"
|
||||
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
genesis2 "github.com/filecoin-project/lotus/chain/gen/genesis"
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
@ -33,6 +36,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/genesis"
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
"github.com/filecoin-project/lotus/storage/sbmock"
|
||||
|
||||
"go.opencensus.io/trace"
|
||||
"golang.org/x/xerrors"
|
||||
@ -54,7 +58,7 @@ type ChainGen struct {
|
||||
genesis *types.BlockHeader
|
||||
CurTipset *store.FullTipSet
|
||||
|
||||
Timestamper func(*types.TipSet, uint64) uint64
|
||||
Timestamper func(*types.TipSet, abi.ChainEpoch) uint64
|
||||
|
||||
GetMessages func(*ChainGen) ([]*types.SignedMessage, error)
|
||||
|
||||
@ -112,74 +116,81 @@ func NewGenerator() (*ChainGen, error) {
|
||||
return nil, xerrors.Errorf("creating memrepo wallet failed: %w", err)
|
||||
}
|
||||
|
||||
banker, err := w.GenerateKey(types.KTSecp256k1)
|
||||
banker, err := w.GenerateKey(crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to generate banker key: %w", err)
|
||||
}
|
||||
|
||||
receievers := make([]address.Address, msgsPerBlock)
|
||||
for r := range receievers {
|
||||
receievers[r], err = w.GenerateKey(types.KTBLS)
|
||||
receievers[r], err = w.GenerateKey(crypto.SigTypeBLS)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to generate receiver key: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
maddr1, err := address.NewFromString("t0300")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
maddr1 := genesis2.MinerAddress(0)
|
||||
|
||||
m1temp, err := ioutil.TempDir("", "preseal")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
genm1, err := seed.PreSeal(maddr1, 1024, 0, 1, m1temp, []byte("some randomness"))
|
||||
genm1, k1, err := seed.PreSeal(maddr1, 1024, 0, 1, m1temp, []byte("some randomness"), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
maddr2, err := address.NewFromString("t0301")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
maddr2 := genesis2.MinerAddress(1)
|
||||
|
||||
m2temp, err := ioutil.TempDir("", "preseal")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
genm2, err := seed.PreSeal(maddr2, 1024, 0, 1, m2temp, []byte("some randomness"))
|
||||
genm2, k2, err := seed.PreSeal(maddr2, 1024, 0, 1, m2temp, []byte("some randomness"), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mk1, err := w.Import(&genm1.Key)
|
||||
mk1, err := w.Import(k1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mk2, err := w.Import(&genm2.Key)
|
||||
mk2, err := w.Import(k2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
minercfg := &GenMinerCfg{
|
||||
PeerIDs: []peer.ID{"peerID1", "peerID2"},
|
||||
PreSeals: map[string]genesis.GenesisMiner{
|
||||
maddr1.String(): *genm1,
|
||||
maddr2.String(): *genm2,
|
||||
sys := vm.Syscalls(&genFakeVerifier{})
|
||||
|
||||
tpl := genesis.Template{
|
||||
Accounts: []genesis.Actor{
|
||||
{
|
||||
Type: genesis.TAccount,
|
||||
Balance: types.FromFil(40000),
|
||||
Meta: (&genesis.AccountMeta{Owner: mk1}).ActorMeta(),
|
||||
},
|
||||
{
|
||||
Type: genesis.TAccount,
|
||||
Balance: types.FromFil(40000),
|
||||
Meta: (&genesis.AccountMeta{Owner: mk2}).ActorMeta(),
|
||||
},
|
||||
{
|
||||
Type: genesis.TAccount,
|
||||
Balance: types.FromFil(50000),
|
||||
Meta: (&genesis.AccountMeta{Owner: banker}).ActorMeta(),
|
||||
},
|
||||
},
|
||||
MinerAddrs: []address.Address{maddr1, maddr2},
|
||||
Miners: []genesis.Miner{
|
||||
*genm1,
|
||||
*genm2,
|
||||
},
|
||||
NetworkName: "",
|
||||
Timestamp: 100000,
|
||||
}
|
||||
|
||||
sys := vm.Syscalls(sectorbuilder.ProofVerifier)
|
||||
|
||||
genb, err := MakeGenesisBlock(bs, sys, map[address.Address]types.BigInt{
|
||||
mk1: types.FromFil(40000),
|
||||
mk2: types.FromFil(40000),
|
||||
banker: types.FromFil(50000),
|
||||
}, minercfg, 100000)
|
||||
genb, err := genesis2.MakeGenesisBlock(context.TODO(), bs, sys, tpl)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("make genesis block failed: %w", err)
|
||||
}
|
||||
@ -193,17 +204,15 @@ func NewGenerator() (*ChainGen, error) {
|
||||
return nil, xerrors.Errorf("set genesis failed: %w", err)
|
||||
}
|
||||
|
||||
if len(minercfg.MinerAddrs) == 0 {
|
||||
return nil, xerrors.Errorf("MakeGenesisBlock failed to set miner address")
|
||||
}
|
||||
|
||||
mgen := make(map[address.Address]ElectionPoStProver)
|
||||
for _, m := range minercfg.MinerAddrs {
|
||||
mgen[m] = &eppProvider{}
|
||||
for i := range tpl.Miners {
|
||||
mgen[genesis2.MinerAddress(uint64(i))] = &eppProvider{}
|
||||
}
|
||||
|
||||
sm := stmgr.NewStateManager(cs)
|
||||
|
||||
miners := []address.Address{maddr1, maddr2}
|
||||
|
||||
gen := &ChainGen{
|
||||
bs: bs,
|
||||
cs: cs,
|
||||
@ -213,7 +222,7 @@ func NewGenerator() (*ChainGen, error) {
|
||||
w: w,
|
||||
|
||||
GetMessages: getRandomMessages,
|
||||
Miners: minercfg.MinerAddrs,
|
||||
Miners: miners,
|
||||
eppProvs: mgen,
|
||||
banker: banker,
|
||||
receivers: receievers,
|
||||
@ -246,16 +255,32 @@ func (cg *ChainGen) GenesisCar() ([]byte, error) {
|
||||
|
||||
out := new(bytes.Buffer)
|
||||
|
||||
if err := car.WriteCar(context.TODO(), dserv, []cid.Cid{cg.Genesis().Cid()}, out); err != nil {
|
||||
if err := car.WriteCarWithWalker(context.TODO(), dserv, []cid.Cid{cg.Genesis().Cid()}, out, CarWalkFunc); err != nil {
|
||||
return nil, xerrors.Errorf("genesis car write car failed: %w", err)
|
||||
}
|
||||
|
||||
return out.Bytes(), nil
|
||||
}
|
||||
|
||||
func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, round int64) (*types.EPostProof, *types.Ticket, error) {
|
||||
func CarWalkFunc(nd format.Node) (out []*format.Link, err error) {
|
||||
for _, link := range nd.Links() {
|
||||
if link.Cid.Prefix().MhType == uint64(commcid.FC_SEALED_V1) || link.Cid.Prefix().MhType == uint64(commcid.FC_UNSEALED_V1) {
|
||||
continue
|
||||
}
|
||||
out = append(out, link)
|
||||
}
|
||||
|
||||
lastTicket := pts.MinTicket()
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, round int64) (*types.EPostProof, *types.Ticket, error) {
|
||||
mc := &mca{w: cg.w, sm: cg.sm}
|
||||
|
||||
// TODO: REVIEW: Am I doing this correctly?
|
||||
ticketRand, err := mc.ChainGetRandomness(ctx, pts.Key(), crypto.DomainSeparationTag_TicketProduction, pts.Height(), m.Bytes())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
st := pts.ParentState()
|
||||
|
||||
@ -264,7 +289,7 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
|
||||
return nil, nil, xerrors.Errorf("get miner worker: %w", err)
|
||||
}
|
||||
|
||||
vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, m, DSepTicket, lastTicket.VRFProof)
|
||||
vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, ticketRand)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("compute VRF: %w", err)
|
||||
}
|
||||
@ -273,7 +298,7 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
|
||||
VRFProof: vrfout,
|
||||
}
|
||||
|
||||
eproofin, err := IsRoundWinner(ctx, pts, round, m, cg.eppProvs[m], &mca{w: cg.w, sm: cg.sm})
|
||||
eproofin, err := IsRoundWinner(ctx, pts, round, m, cg.eppProvs[m], mc)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("checking round winner failed: %w", err)
|
||||
}
|
||||
@ -319,7 +344,7 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad
|
||||
}
|
||||
|
||||
if proof != nil {
|
||||
fblk, err := cg.makeBlock(base, m, proof, t, uint64(round), msgs)
|
||||
fblk, err := cg.makeBlock(base, m, proof, t, abi.ChainEpoch(round), msgs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("making a block for next tipset failed: %w", err)
|
||||
}
|
||||
@ -341,13 +366,13 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, eproof *types.EPostProof, ticket *types.Ticket, height uint64, msgs []*types.SignedMessage) (*types.FullBlock, error) {
|
||||
func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, eproof *types.EPostProof, ticket *types.Ticket, height abi.ChainEpoch, msgs []*types.SignedMessage) (*types.FullBlock, error) {
|
||||
|
||||
var ts uint64
|
||||
if cg.Timestamper != nil {
|
||||
ts = cg.Timestamper(parents, height-parents.Height())
|
||||
} else {
|
||||
ts = parents.MinTimestamp() + ((height - parents.Height()) * build.BlockDelay)
|
||||
ts = parents.MinTimestamp() + uint64((height-parents.Height())*build.BlockDelay)
|
||||
}
|
||||
|
||||
fblk, err := MinerCreateBlock(context.TODO(), cg.sm, cg.w, m, parents, ticket, eproof, msgs, height, ts)
|
||||
@ -417,17 +442,17 @@ func (cg *ChainGen) YieldRepo() (repo.Repo, error) {
|
||||
}
|
||||
|
||||
type MiningCheckAPI interface {
|
||||
ChainGetRandomness(context.Context, types.TipSetKey, int64) ([]byte, error)
|
||||
ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error)
|
||||
|
||||
StateMinerPower(context.Context, address.Address, types.TipSetKey) (api.MinerPower, error)
|
||||
|
||||
StateMinerWorker(context.Context, address.Address, types.TipSetKey) (address.Address, error)
|
||||
|
||||
StateMinerSectorSize(context.Context, address.Address, types.TipSetKey) (uint64, error)
|
||||
StateMinerSectorSize(context.Context, address.Address, types.TipSetKey) (abi.SectorSize, error)
|
||||
|
||||
StateMinerProvingSet(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error)
|
||||
|
||||
WalletSign(context.Context, address.Address, []byte) (*types.Signature, error)
|
||||
WalletSign(context.Context, address.Address, []byte) (*crypto.Signature, error)
|
||||
}
|
||||
|
||||
type mca struct {
|
||||
@ -435,8 +460,13 @@ type mca struct {
|
||||
sm *stmgr.StateManager
|
||||
}
|
||||
|
||||
func (mca mca) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, lb int64) ([]byte, error) {
|
||||
return mca.sm.ChainStore().GetRandomness(ctx, pts.Cids(), int64(lb))
|
||||
func (mca mca) ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) {
|
||||
pts, err := mca.sm.ChainStore().LoadTipSet(tsk)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("loading tipset key: %w", err)
|
||||
}
|
||||
|
||||
return mca.sm.ChainStore().GetRandomness(ctx, pts.Cids(), personalization, int64(randEpoch), entropy)
|
||||
}
|
||||
|
||||
func (mca mca) StateMinerPower(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (api.MinerPower, error) {
|
||||
@ -463,7 +493,7 @@ func (mca mca) StateMinerWorker(ctx context.Context, maddr address.Address, tsk
|
||||
return stmgr.GetMinerWorkerRaw(ctx, mca.sm, ts.ParentState(), maddr)
|
||||
}
|
||||
|
||||
func (mca mca) StateMinerSectorSize(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (uint64, error) {
|
||||
func (mca mca) StateMinerSectorSize(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (abi.SectorSize, error) {
|
||||
ts, err := mca.sm.ChainStore().LoadTipSet(tsk)
|
||||
if err != nil {
|
||||
return 0, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||
@ -479,7 +509,7 @@ func (mca mca) StateMinerProvingSet(ctx context.Context, maddr address.Address,
|
||||
return stmgr.GetMinerProvingSet(ctx, mca.sm, ts, maddr)
|
||||
}
|
||||
|
||||
func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*types.Signature, error) {
|
||||
func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*crypto.Signature, error) {
|
||||
return mca.w.Sign(ctx, a, v)
|
||||
}
|
||||
|
||||
@ -493,7 +523,7 @@ type eppProvider struct{}
|
||||
func (epp *eppProvider) GenerateCandidates(ctx context.Context, _ sectorbuilder.SortedPublicSectorInfo, eprand []byte) ([]sectorbuilder.EPostCandidate, error) {
|
||||
return []sectorbuilder.EPostCandidate{
|
||||
{
|
||||
SectorID: 1,
|
||||
SectorNum: 1,
|
||||
PartialTicket: [32]byte{},
|
||||
Ticket: [32]byte{},
|
||||
SectorChallengeIndex: 1,
|
||||
@ -514,7 +544,7 @@ type ProofInput struct {
|
||||
}
|
||||
|
||||
func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner address.Address, epp ElectionPoStProver, a MiningCheckAPI) (*ProofInput, error) {
|
||||
r, err := a.ChainGetRandomness(ctx, ts.Key(), round-build.EcRandomnessLookback)
|
||||
epostRand, err := a.ChainGetRandomness(ctx, ts.Key(), crypto.DomainSeparationTag_ElectionPoStChallengeSeed, abi.ChainEpoch(round-build.EcRandomnessLookback), miner.Bytes())
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("chain get randomness: %w", err)
|
||||
}
|
||||
@ -524,7 +554,7 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add
|
||||
return nil, xerrors.Errorf("failed to get miner worker: %w", err)
|
||||
}
|
||||
|
||||
vrfout, err := ComputeVRF(ctx, a.WalletSign, mworker, miner, DSepElectionPost, r)
|
||||
vrfout, err := ComputeVRF(ctx, a.WalletSign, mworker, epostRand)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to compute VRF: %w", err)
|
||||
}
|
||||
@ -539,11 +569,15 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add
|
||||
|
||||
var sinfos []ffi.PublicSectorInfo
|
||||
for _, s := range pset {
|
||||
cr, err := commcid.CIDToReplicaCommitmentV1(s.Info.Info.SealedCID)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("get sealed cid: %w", err)
|
||||
}
|
||||
var commRa [32]byte
|
||||
copy(commRa[:], s.CommR)
|
||||
copy(commRa[:], cr)
|
||||
sinfos = append(sinfos, ffi.PublicSectorInfo{
|
||||
SectorID: s.SectorID,
|
||||
CommR: commRa,
|
||||
SectorNum: s.ID,
|
||||
CommR: commRa,
|
||||
})
|
||||
}
|
||||
sectors := sectorbuilder.NewSortedPublicSectorInfo(sinfos)
|
||||
@ -599,7 +633,7 @@ func ComputeProof(ctx context.Context, epp ElectionPoStProver, pi *ProofInput) (
|
||||
copy(part, win.PartialTicket[:])
|
||||
ept.Candidates = append(ept.Candidates, types.EPostTicket{
|
||||
Partial: part,
|
||||
SectorID: win.SectorID,
|
||||
SectorID: win.SectorNum,
|
||||
ChallengeIndex: win.SectorChallengeIndex,
|
||||
})
|
||||
}
|
||||
@ -607,42 +641,14 @@ func ComputeProof(ctx context.Context, epp ElectionPoStProver, pi *ProofInput) (
|
||||
return &ept, nil
|
||||
}
|
||||
|
||||
type SignFunc func(context.Context, address.Address, []byte) (*types.Signature, error)
|
||||
type SignFunc func(context.Context, address.Address, []byte) (*crypto.Signature, error)
|
||||
|
||||
const (
|
||||
DSepTicket = 1
|
||||
DSepElectionPost = 2
|
||||
)
|
||||
|
||||
func hashVRFBase(personalization uint64, miner address.Address, input []byte) ([]byte, error) {
|
||||
if miner.Protocol() != address.ID {
|
||||
return nil, xerrors.Errorf("miner address for compute VRF must be an ID address")
|
||||
}
|
||||
|
||||
var persbuf [8]byte
|
||||
binary.LittleEndian.PutUint64(persbuf[:], personalization)
|
||||
|
||||
h := sha256.New()
|
||||
h.Write(persbuf[:])
|
||||
h.Write([]byte{0})
|
||||
h.Write(input)
|
||||
h.Write([]byte{0})
|
||||
h.Write(miner.Bytes())
|
||||
|
||||
return h.Sum(nil), nil
|
||||
}
|
||||
|
||||
func VerifyVRF(ctx context.Context, worker, miner address.Address, p uint64, input, vrfproof []byte) error {
|
||||
func VerifyVRF(ctx context.Context, worker address.Address, vrfBase, vrfproof []byte) error {
|
||||
_, span := trace.StartSpan(ctx, "VerifyVRF")
|
||||
defer span.End()
|
||||
|
||||
vrfBase, err := hashVRFBase(p, miner, input)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("computing vrf base failed: %w", err)
|
||||
}
|
||||
|
||||
sig := &types.Signature{
|
||||
Type: types.KTBLS,
|
||||
sig := &crypto.Signature{
|
||||
Type: crypto.SigTypeBLS,
|
||||
Data: vrfproof,
|
||||
}
|
||||
|
||||
@ -653,20 +659,34 @@ func VerifyVRF(ctx context.Context, worker, miner address.Address, p uint64, inp
|
||||
return nil
|
||||
}
|
||||
|
||||
func ComputeVRF(ctx context.Context, sign SignFunc, worker, miner address.Address, p uint64, input []byte) ([]byte, error) {
|
||||
sigInput, err := hashVRFBase(p, miner, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func ComputeVRF(ctx context.Context, sign SignFunc, worker address.Address, sigInput []byte) ([]byte, error) {
|
||||
sig, err := sign(ctx, worker, sigInput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if sig.Type != types.KTBLS {
|
||||
if sig.Type != crypto.SigTypeBLS {
|
||||
return nil, fmt.Errorf("miner worker address was not a BLS key")
|
||||
}
|
||||
|
||||
return sig.Data, nil
|
||||
}
|
||||
|
||||
type genFakeVerifier struct{}
|
||||
|
||||
var _ sectorbuilder.Verifier = (*genFakeVerifier)(nil)
|
||||
|
||||
func (m genFakeVerifier) VerifyElectionPost(ctx context.Context, sectorSize abi.SectorSize, sectorInfo sectorbuilder.SortedPublicSectorInfo, challengeSeed []byte, proof []byte, candidates []sectorbuilder.EPostCandidate, proverID address.Address) (bool, error) {
|
||||
panic("nyi")
|
||||
}
|
||||
func (m genFakeVerifier) GenerateDataCommitment(ssize abi.PaddedPieceSize, pieces []ffi.PublicPieceInfo) ([sectorbuilder.CommLen]byte, error) {
|
||||
return sbmock.MockVerifier.GenerateDataCommitment(ssize, pieces)
|
||||
}
|
||||
|
||||
func (m genFakeVerifier) VerifySeal(sectorSize abi.SectorSize, commR, commD []byte, proverID address.Address, ticket []byte, seed []byte, sectorID abi.SectorNumber, proof []byte) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (m genFakeVerifier) VerifyFallbackPost(ctx context.Context, sectorSize abi.SectorSize, sectorInfo sectorbuilder.SortedPublicSectorInfo, challengeSeed []byte, proof []byte, candidates []sectorbuilder.EPostCandidate, proverID address.Address, faults uint64) (bool, error) {
|
||||
panic("nyi")
|
||||
}
|
||||
|
@ -3,20 +3,25 @@ package gen
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
|
||||
)
|
||||
|
||||
func init() {
|
||||
build.SectorSizes = []uint64{1024}
|
||||
build.SectorSizes = []abi.SectorSize{1024}
|
||||
build.MinimumMinerPower = 1024
|
||||
}
|
||||
|
||||
func testGeneration(t testing.TB, n int, msgs int) {
|
||||
g, err := NewGenerator()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
t.Fatalf("%+v", err)
|
||||
}
|
||||
|
||||
g.msgsPerBlock = msgs
|
||||
@ -24,7 +29,7 @@ func testGeneration(t testing.TB, n int, msgs int) {
|
||||
for i := 0; i < n; i++ {
|
||||
mts, err := g.NextTipSet()
|
||||
if err != nil {
|
||||
t.Fatalf("error at H:%d, %s", i, err)
|
||||
t.Fatalf("error at H:%d, %+v", i, err)
|
||||
}
|
||||
_ = mts
|
||||
}
|
||||
|
286
chain/gen/genesis/genesis.go
Normal file
286
chain/gen/genesis/genesis.go
Normal file
@ -0,0 +1,286 @@
|
||||
package genesis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/filecoin-project/go-amt-ipld/v2"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/account"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
"github.com/filecoin-project/specs-actors/actors/runtime"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-datastore"
|
||||
bstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/genesis"
|
||||
)
|
||||
|
||||
const AccountStart = 100
|
||||
const MinerStart = 1000
|
||||
const MaxAccounts = MinerStart - AccountStart
|
||||
|
||||
var log = logging.Logger("genesis")
|
||||
|
||||
type GenesisBootstrap struct {
|
||||
Genesis *types.BlockHeader
|
||||
}
|
||||
|
||||
/*
|
||||
From a list of parameters, create a genesis block / initial state
|
||||
|
||||
The process:
|
||||
- Bootstrap state (MakeInitialStateTree)
|
||||
- Create empty state
|
||||
- Create system actor
|
||||
- Make init actor
|
||||
- Create accounts mappings
|
||||
- Set NextID to MinerStart
|
||||
- Setup Reward (1.4B fil)
|
||||
- Setup Cron
|
||||
- Create empty power actor
|
||||
- Create empty market
|
||||
- Setup burnt fund address
|
||||
- Initialize account / msig balances
|
||||
- Instantiate early vm with genesis syscalls
|
||||
- Create miners
|
||||
- Each:
|
||||
- power.CreateMiner, set msg value to PowerBalance
|
||||
- market.AddFunds with correct value
|
||||
- market.PublishDeals for related sectors
|
||||
- Set precommits
|
||||
- Commit presealed sectors
|
||||
|
||||
Data Types:
|
||||
|
||||
PreSeal :{
|
||||
CommR CID
|
||||
CommD CID
|
||||
SectorID SectorNumber
|
||||
Deal market.DealProposal # Start at 0, self-deal!
|
||||
}
|
||||
|
||||
Genesis: {
|
||||
Accounts: [ # non-miner, non-singleton actors, max len = MaxAccounts
|
||||
{
|
||||
Type: "account" / "multisig",
|
||||
Value: "attofil",
|
||||
[Meta: {msig settings, account key..}]
|
||||
},...
|
||||
],
|
||||
Miners: [
|
||||
{
|
||||
Owner, Worker Addr # ID
|
||||
MarketBalance, PowerBalance TokenAmount
|
||||
SectorSize uint64
|
||||
PreSeals []PreSeal
|
||||
},...
|
||||
],
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template genesis.Template) (*state.StateTree, error) {
|
||||
// Create empty state tree
|
||||
|
||||
cst := cbor.NewCborStore(bs)
|
||||
_, err := cst.Put(context.TODO(), []struct{}{})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("putting empty object: %w", err)
|
||||
}
|
||||
|
||||
state, err := state.NewStateTree(cst)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("making new state tree: %w", err)
|
||||
}
|
||||
|
||||
emptyobject, err := cst.Put(context.TODO(), []struct{}{})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed putting empty object: %w", err)
|
||||
}
|
||||
|
||||
// Create system actor
|
||||
|
||||
sysact, err := SetupSystemActor(bs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setup init actor: %w", err)
|
||||
}
|
||||
if err := state.SetActor(builtin.SystemActorAddr, sysact); err != nil {
|
||||
return nil, xerrors.Errorf("set init actor: %w", err)
|
||||
}
|
||||
|
||||
// Create init actor
|
||||
|
||||
initact, err := SetupInitActor(bs, template.NetworkName, template.Accounts)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setup init actor: %w", err)
|
||||
}
|
||||
if err := state.SetActor(builtin.InitActorAddr, initact); err != nil {
|
||||
return nil, xerrors.Errorf("set init actor: %w", err)
|
||||
}
|
||||
|
||||
// Setup reward
|
||||
err = state.SetActor(builtin.RewardActorAddr, &types.Actor{
|
||||
Code: builtin.RewardActorCodeID,
|
||||
Balance: big.Int{Int: build.InitialReward},
|
||||
Head: emptyobject, // TODO ?
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("set network account actor: %w", err)
|
||||
}
|
||||
|
||||
// Setup cron
|
||||
cronact, err := SetupCronActor(bs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setup cron actor: %w", err)
|
||||
}
|
||||
if err := state.SetActor(builtin.CronActorAddr, cronact); err != nil {
|
||||
return nil, xerrors.Errorf("set cron actor: %w", err)
|
||||
}
|
||||
|
||||
// Create empty power actor
|
||||
spact, err := SetupStoragePowerActor(bs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setup storage market actor: %w", err)
|
||||
}
|
||||
if err := state.SetActor(builtin.StoragePowerActorAddr, spact); err != nil {
|
||||
return nil, xerrors.Errorf("set storage market actor: %w", err)
|
||||
}
|
||||
|
||||
// Create empty market actor
|
||||
marketact, err := SetupStorageMarketActor(bs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setup storage market actor: %w", err)
|
||||
}
|
||||
if err := state.SetActor(builtin.StorageMarketActorAddr, marketact); err != nil {
|
||||
return nil, xerrors.Errorf("set market actor: %w", err)
|
||||
}
|
||||
|
||||
// Setup burnt-funds
|
||||
err = state.SetActor(builtin.BurntFundsActorAddr, &types.Actor{
|
||||
Code: builtin.AccountActorCodeID,
|
||||
Balance: types.NewInt(0),
|
||||
Head: emptyobject,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("set burnt funds account actor: %w", err)
|
||||
}
|
||||
|
||||
// Create accounts
|
||||
for id, info := range template.Accounts {
|
||||
if info.Type != genesis.TAccount {
|
||||
return nil, xerrors.New("unsupported account type") // TODO: msigs
|
||||
}
|
||||
|
||||
ida, err := address.NewIDAddress(uint64(AccountStart + id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ainfo genesis.AccountMeta
|
||||
if err := json.Unmarshal(info.Meta, &ainfo); err != nil {
|
||||
return nil, xerrors.Errorf("unmarshaling account meta: %w", err)
|
||||
}
|
||||
|
||||
st, err := cst.Put(ctx, &account.State{Address: ainfo.Owner})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = state.SetActor(ida, &types.Actor{
|
||||
Code: builtin.AccountActorCodeID,
|
||||
Balance: info.Balance,
|
||||
Head: st,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setting account from actmap: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return state, nil
|
||||
}
|
||||
|
||||
func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys runtime.Syscalls, template genesis.Template) (*GenesisBootstrap, error) {
|
||||
st, err := MakeInitialStateTree(ctx, bs, template)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("make initial state tree failed: %w", err)
|
||||
}
|
||||
|
||||
stateroot, err := st.Flush(ctx)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("flush state tree failed: %w", err)
|
||||
}
|
||||
|
||||
// temp chainstore
|
||||
cs := store.NewChainStore(bs, datastore.NewMapDatastore(), sys)
|
||||
stateroot, err = SetupStorageMiners(ctx, cs, stateroot, template.Miners)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setup storage miners failed: %w", err)
|
||||
}
|
||||
|
||||
cst := cbor.NewCborStore(bs)
|
||||
|
||||
emptyroot, err := amt.FromArray(ctx, cst, nil)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("amt build failed: %w", err)
|
||||
}
|
||||
|
||||
mm := &types.MsgMeta{
|
||||
BlsMessages: emptyroot,
|
||||
SecpkMessages: emptyroot,
|
||||
}
|
||||
mmb, err := mm.ToStorageBlock()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("serializing msgmeta failed: %w", err)
|
||||
}
|
||||
if err := bs.Put(mmb); err != nil {
|
||||
return nil, xerrors.Errorf("putting msgmeta block to blockstore: %w", err)
|
||||
}
|
||||
|
||||
log.Infof("Empty Genesis root: %s", emptyroot)
|
||||
|
||||
genesisticket := &types.Ticket{
|
||||
VRFProof: []byte("vrf proof0000000vrf proof0000000"),
|
||||
}
|
||||
|
||||
b := &types.BlockHeader{
|
||||
Miner: builtin.InitActorAddr,
|
||||
Ticket: genesisticket,
|
||||
EPostProof: types.EPostProof{
|
||||
Proof: []byte("not a real proof"),
|
||||
PostRand: []byte("i guess this is kinda random"),
|
||||
},
|
||||
Parents: []cid.Cid{},
|
||||
Height: 0,
|
||||
ParentWeight: types.NewInt(0),
|
||||
ParentStateRoot: stateroot,
|
||||
Messages: mmb.Cid(),
|
||||
ParentMessageReceipts: emptyroot,
|
||||
BLSAggregate: crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("signatureeee")},
|
||||
BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("block signatureeee")},
|
||||
Timestamp: template.Timestamp,
|
||||
}
|
||||
|
||||
sb, err := b.ToStorageBlock()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("serializing block header failed: %w", err)
|
||||
}
|
||||
|
||||
if err := bs.Put(sb); err != nil {
|
||||
return nil, xerrors.Errorf("putting header to blockstore: %w", err)
|
||||
}
|
||||
|
||||
return &GenesisBootstrap{
|
||||
Genesis: b,
|
||||
}, nil
|
||||
}
|
266
chain/gen/genesis/miners.go
Normal file
266
chain/gen/genesis/miners.go
Normal file
@ -0,0 +1,266 @@
|
||||
package genesis
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
|
||||
cborutil "github.com/filecoin-project/go-cbor-util"
|
||||
commcid "github.com/filecoin-project/go-fil-commcid"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
"github.com/ipfs/go-cid"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
"github.com/filecoin-project/lotus/genesis"
|
||||
)
|
||||
|
||||
func MinerAddress(genesisIndex uint64) address.Address {
|
||||
maddr, err := address.NewIDAddress(MinerStart + genesisIndex)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return maddr
|
||||
}
|
||||
|
||||
func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid, miners []genesis.Miner) (cid.Cid, error) {
|
||||
networkPower := big.Zero()
|
||||
for _, m := range miners {
|
||||
networkPower = big.Add(networkPower, big.NewInt(int64(m.SectorSize)*int64(len(m.Sectors))))
|
||||
}
|
||||
|
||||
vm, err := vm.NewVM(sroot, 0, &fakeRand{}, builtin.SystemActorAddr, cs.Blockstore(), cs.VMSys())
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err)
|
||||
}
|
||||
|
||||
err = vm.MutateState(ctx, builtin.StoragePowerActorAddr, func(cst cbor.IpldStore, st *power.State) error {
|
||||
st.TotalNetworkPower = networkPower
|
||||
return nil
|
||||
})
|
||||
|
||||
if len(miners) == 0 {
|
||||
return cid.Undef, xerrors.New("no genesis miners")
|
||||
}
|
||||
|
||||
for i, m := range miners {
|
||||
// Create miner through power actor
|
||||
|
||||
var maddr address.Address
|
||||
{
|
||||
constructorParams := &power.CreateMinerParams{
|
||||
Worker: m.Worker,
|
||||
SectorSize: m.SectorSize,
|
||||
Peer: m.PeerId,
|
||||
}
|
||||
|
||||
params := mustEnc(constructorParams)
|
||||
rval, err := doExecValue(ctx, vm, builtin.StoragePowerActorAddr, m.Owner, m.PowerBalance, builtin.MethodsPower.CreateMiner, params)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err)
|
||||
}
|
||||
|
||||
var ma power.CreateMinerReturn
|
||||
if err := ma.UnmarshalCBOR(bytes.NewReader(rval)); err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
expma := MinerAddress(uint64(i))
|
||||
if ma.IDAddress != expma {
|
||||
return cid.Undef, xerrors.Errorf("miner assigned wrong address: %s != %s", ma.IDAddress, expma)
|
||||
}
|
||||
maddr = ma.IDAddress
|
||||
}
|
||||
|
||||
// Add market funds
|
||||
|
||||
{
|
||||
params := mustEnc(&maddr)
|
||||
_, err := doExecValue(ctx, vm, builtin.StorageMarketActorAddr, m.Worker, m.MarketBalance, builtin.MethodsMarket.AddBalance, params)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err)
|
||||
}
|
||||
}
|
||||
{
|
||||
params := mustEnc(&m.Worker)
|
||||
_, err := doExecValue(ctx, vm, builtin.StorageMarketActorAddr, m.Worker, big.Zero(), builtin.MethodsMarket.AddBalance, params)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Publish preseal deals
|
||||
|
||||
var dealIDs []abi.DealID
|
||||
{
|
||||
params := &market.PublishStorageDealsParams{}
|
||||
for _, preseal := range m.Sectors {
|
||||
|
||||
params.Deals = append(params.Deals, market.ClientDealProposal{
|
||||
Proposal: preseal.Deal,
|
||||
ClientSignature: crypto.Signature{Type: crypto.SigTypeBLS}, // TODO: do we want to sign these? Or do we want to fake signatures for genesis setup?
|
||||
})
|
||||
fmt.Printf("calling publish storage deals on miner %s with worker %s\n", preseal.Deal.Provider, m.Worker)
|
||||
}
|
||||
|
||||
ret, err := doExecValue(ctx, vm, builtin.StorageMarketActorAddr, m.Worker, big.Zero(), builtin.MethodsMarket.PublishStorageDeals, mustEnc(params))
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err)
|
||||
}
|
||||
var ids market.PublishStorageDealsReturn
|
||||
if err := ids.UnmarshalCBOR(bytes.NewReader(ret)); err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
dealIDs = ids.IDs
|
||||
}
|
||||
|
||||
// setup windowed post
|
||||
{
|
||||
err = vm.MutateState(ctx, maddr, func(cst cbor.IpldStore, st *miner.State) error {
|
||||
// TODO: Randomize so all genesis miners don't fall on the same epoch
|
||||
st.PoStState.ProvingPeriodStart = miner.ProvingPeriod
|
||||
return nil
|
||||
})
|
||||
|
||||
payload, err := cborutil.Dump(&miner.CronEventPayload{
|
||||
EventType: miner.CronEventWindowedPoStExpiration,
|
||||
})
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
params := &power.EnrollCronEventParams{
|
||||
EventEpoch: miner.ProvingPeriod,
|
||||
Payload: payload,
|
||||
}
|
||||
|
||||
_, err = doExecValue(ctx, vm, builtin.StoragePowerActorAddr, maddr, big.Zero(), builtin.MethodsPower.EnrollCronEvent, mustEnc(params))
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to verify preseal deals miner: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Commit sectors
|
||||
for pi, preseal := range m.Sectors {
|
||||
// TODO: Maybe check seal (Can just be snark inputs, doesn't go into the genesis file)
|
||||
|
||||
// check deals, get dealWeight
|
||||
dealWeight := big.Zero()
|
||||
{
|
||||
params := &market.VerifyDealsOnSectorProveCommitParams{
|
||||
DealIDs: []abi.DealID{dealIDs[pi]},
|
||||
SectorExpiry: preseal.Deal.EndEpoch,
|
||||
}
|
||||
|
||||
ret, err := doExecValue(ctx, vm, builtin.StorageMarketActorAddr, maddr, big.Zero(), builtin.MethodsMarket.VerifyDealsOnSectorProveCommit, mustEnc(params))
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to verify preseal deals miner: %w", err)
|
||||
}
|
||||
if err := dealWeight.UnmarshalCBOR(bytes.NewReader(ret)); err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
}
|
||||
|
||||
// update power claims
|
||||
pledge := big.Zero()
|
||||
{
|
||||
err = vm.MutateState(ctx, builtin.StoragePowerActorAddr, func(cst cbor.IpldStore, st *power.State) error {
|
||||
weight := &power.SectorStorageWeightDesc{
|
||||
SectorSize: m.SectorSize,
|
||||
Duration: preseal.Deal.Duration(),
|
||||
DealWeight: dealWeight,
|
||||
}
|
||||
|
||||
spower := power.ConsensusPowerForWeight(weight)
|
||||
pledge = power.PledgeForWeight(weight, big.Sub(st.TotalNetworkPower, spower))
|
||||
err := st.AddToClaim(&state.AdtStore{cst}, maddr, spower, pledge)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("add to claim: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("register power claim in power actor: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Put sectors to miner sector sets
|
||||
{
|
||||
newSectorInfo := &miner.SectorOnChainInfo{
|
||||
Info: miner.SectorPreCommitInfo{
|
||||
SectorNumber: preseal.SectorID,
|
||||
SealedCID: commcid.ReplicaCommitmentV1ToCID(preseal.CommR[:]),
|
||||
SealRandEpoch: 0,
|
||||
DealIDs: []abi.DealID{dealIDs[pi]},
|
||||
Expiration: preseal.Deal.EndEpoch,
|
||||
},
|
||||
ActivationEpoch: 0,
|
||||
DealWeight: dealWeight,
|
||||
PledgeRequirement: pledge,
|
||||
}
|
||||
|
||||
err = vm.MutateState(ctx, maddr, func(cst cbor.IpldStore, st *miner.State) error {
|
||||
store := &state.AdtStore{cst}
|
||||
|
||||
if err = st.PutSector(store, newSectorInfo); err != nil {
|
||||
return xerrors.Errorf("failed to prove commit: %v", err)
|
||||
}
|
||||
|
||||
st.ProvingSet = st.Sectors
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return cid.Cid{}, xerrors.Errorf("put to sset: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
sectorBf := abi.NewBitField()
|
||||
sectorBf.Set(uint64(preseal.SectorID))
|
||||
|
||||
payload, err := cborutil.Dump(&miner.CronEventPayload{
|
||||
EventType: miner.CronEventSectorExpiry,
|
||||
Sectors: §orBf,
|
||||
})
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
params := &power.EnrollCronEventParams{
|
||||
EventEpoch: preseal.Deal.EndEpoch,
|
||||
Payload: payload,
|
||||
}
|
||||
|
||||
_, err = doExecValue(ctx, vm, builtin.StoragePowerActorAddr, maddr, big.Zero(), builtin.MethodsPower.EnrollCronEvent, mustEnc(params))
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to verify preseal deals miner: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
c, err := vm.Flush(ctx)
|
||||
return c, err
|
||||
}
|
||||
|
||||
// TODO: copied from actors test harness, deduplicate or remove from here
|
||||
type fakeRand struct{}
|
||||
|
||||
func (fr *fakeRand) GetRandomness(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch int64, entropy []byte) ([]byte, error) {
|
||||
out := make([]byte, 32)
|
||||
rand.New(rand.NewSource(randEpoch)).Read(out)
|
||||
return out, nil
|
||||
}
|
28
chain/gen/genesis/t00_system.go
Normal file
28
chain/gen/genesis/t00_system.go
Normal file
@ -0,0 +1,28 @@
|
||||
package genesis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||
bstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
)
|
||||
|
||||
func SetupSystemActor(bs bstore.Blockstore) (*types.Actor, error) {
|
||||
var st adt.EmptyValue
|
||||
|
||||
cst := cbor.NewCborStore(bs)
|
||||
|
||||
statecid, err := cst.Put(context.TODO(), &st)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
act := &types.Actor{
|
||||
Code: builtin.SystemActorCodeID,
|
||||
Head: statecid,
|
||||
}
|
||||
|
||||
return act, nil
|
||||
}
|
69
chain/gen/genesis/t01_init.go
Normal file
69
chain/gen/genesis/t01_init.go
Normal file
@ -0,0 +1,69 @@
|
||||
package genesis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
|
||||
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
||||
"github.com/ipfs/go-hamt-ipld"
|
||||
bstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/genesis"
|
||||
)
|
||||
|
||||
func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesis.Actor) (*types.Actor, error) {
|
||||
if len(initialActors) > MaxAccounts {
|
||||
return nil, xerrors.New("too many initial actors")
|
||||
}
|
||||
|
||||
var ias init_.State
|
||||
ias.NextID = MinerStart
|
||||
ias.NetworkName = netname
|
||||
|
||||
cst := cbor.NewCborStore(bs)
|
||||
amap := hamt.NewNode(cst, hamt.UseTreeBitWidth(5)) // TODO: use spec adt map
|
||||
|
||||
for i, a := range initialActors {
|
||||
if a.Type != genesis.TAccount {
|
||||
return nil, xerrors.Errorf("unsupported account type: %s", a.Type) // TODO: Support msig (skip here)
|
||||
}
|
||||
|
||||
var ainfo genesis.AccountMeta
|
||||
if err := json.Unmarshal(a.Meta, &ainfo); err != nil {
|
||||
return nil, xerrors.Errorf("unmarshaling account meta: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("init set %s t0%d\n", ainfo.Owner, AccountStart+uint64(i))
|
||||
|
||||
if err := amap.Set(context.TODO(), string(ainfo.Owner.Bytes()), AccountStart+uint64(i)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := amap.Flush(context.TODO()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
amapcid, err := cst.Put(context.TODO(), amap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ias.AddressMap = amapcid
|
||||
|
||||
statecid, err := cst.Put(context.TODO(), &ias)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
act := &types.Actor{
|
||||
Code: builtin.InitActorCodeID,
|
||||
Head: statecid,
|
||||
}
|
||||
|
||||
return act, nil
|
||||
}
|
1
chain/gen/genesis/t02_reward.go
Normal file
1
chain/gen/genesis/t02_reward.go
Normal file
@ -0,0 +1 @@
|
||||
package genesis
|
33
chain/gen/genesis/t03_cron.go
Normal file
33
chain/gen/genesis/t03_cron.go
Normal file
@ -0,0 +1,33 @@
|
||||
package genesis
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/cron"
|
||||
bstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
func SetupCronActor(bs bstore.Blockstore) (*types.Actor, error) {
|
||||
cst := cbor.NewCborStore(bs)
|
||||
cas := &cron.State{Entries: []cron.Entry{{
|
||||
Receiver: builtin.StoragePowerActorAddr,
|
||||
MethodNum: builtin.MethodsPower.OnEpochTickEnd,
|
||||
},
|
||||
}}
|
||||
|
||||
stcid, err := cst.Put(context.TODO(), cas)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.Actor{
|
||||
Code: builtin.CronActorCodeID,
|
||||
Head: stcid,
|
||||
Nonce: 0,
|
||||
Balance: types.NewInt(0),
|
||||
}, nil
|
||||
}
|
46
chain/gen/genesis/t04_power.go
Normal file
46
chain/gen/genesis/t04_power.go
Normal file
@ -0,0 +1,46 @@
|
||||
package genesis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
||||
"github.com/ipfs/go-hamt-ipld"
|
||||
bstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
func SetupStoragePowerActor(bs bstore.Blockstore) (*types.Actor, error) {
|
||||
ctx := context.TODO()
|
||||
cst := cbor.NewCborStore(bs)
|
||||
nd := hamt.NewNode(cst, hamt.UseTreeBitWidth(5))
|
||||
emptyhamt, err := cst.Put(ctx, nd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sms := &power.State{
|
||||
TotalNetworkPower: big.NewInt(1),
|
||||
MinerCount: 0,
|
||||
EscrowTable: emptyhamt,
|
||||
CronEventQueue: emptyhamt,
|
||||
PoStDetectedFaultMiners: emptyhamt,
|
||||
Claims: emptyhamt,
|
||||
NumMinersMeetingMinPower: 0,
|
||||
}
|
||||
|
||||
stcid, err := cst.Put(ctx, sms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.Actor{
|
||||
Code: builtin.StoragePowerActorCodeID,
|
||||
Head: stcid,
|
||||
Nonce: 0,
|
||||
Balance: types.NewInt(0),
|
||||
}, nil
|
||||
}
|
42
chain/gen/genesis/t05_market.go
Normal file
42
chain/gen/genesis/t05_market.go
Normal file
@ -0,0 +1,42 @@
|
||||
package genesis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/ipfs/go-hamt-ipld"
|
||||
|
||||
"github.com/filecoin-project/go-amt-ipld/v2"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||
bstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
func SetupStorageMarketActor(bs bstore.Blockstore) (*types.Actor, error) {
|
||||
cst := cbor.NewCborStore(bs)
|
||||
|
||||
a, err := amt.NewAMT(cst).Flush(context.TODO())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h, err := cst.Put(context.TODO(), hamt.NewNode(cst, hamt.UseTreeBitWidth(5)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sms := market.ConstructState(a, h, h)
|
||||
|
||||
stcid, err := cst.Put(context.TODO(), sms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
act := &types.Actor{
|
||||
Code: builtin.StorageMarketActorCodeID,
|
||||
Head: stcid,
|
||||
Balance: types.NewInt(0),
|
||||
}
|
||||
|
||||
return act, nil
|
||||
}
|
53
chain/gen/genesis/util.go
Normal file
53
chain/gen/genesis/util.go
Normal file
@ -0,0 +1,53 @@
|
||||
package genesis
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
)
|
||||
|
||||
func mustEnc(i cbg.CBORMarshaler) []byte {
|
||||
enc, err := actors.SerializeParams(i)
|
||||
if err != nil {
|
||||
panic(err) // ok
|
||||
}
|
||||
return enc
|
||||
}
|
||||
|
||||
func doExec(ctx context.Context, vm *vm.VM, to, from address.Address, method abi.MethodNum, params []byte) ([]byte, error) {
|
||||
return doExecValue(ctx, vm, to, from, types.NewInt(0), method, params)
|
||||
}
|
||||
|
||||
func doExecValue(ctx context.Context, vm *vm.VM, to, from address.Address, value types.BigInt, method abi.MethodNum, params []byte) ([]byte, error) {
|
||||
act, err := vm.StateTree().GetActor(from)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("doExec failed to get from actor: %w", err)
|
||||
}
|
||||
|
||||
ret, err := vm.ApplyMessage(ctx, &types.Message{
|
||||
To: to,
|
||||
From: from,
|
||||
Method: method,
|
||||
Params: params,
|
||||
GasLimit: types.NewInt(1000000),
|
||||
GasPrice: types.NewInt(0),
|
||||
Value: value,
|
||||
Nonce: act.Nonce,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("doExec apply message failed: %w", err)
|
||||
}
|
||||
|
||||
if ret.ExitCode != 0 {
|
||||
return nil, xerrors.Errorf("failed to call method: %w", ret.ActorErr)
|
||||
}
|
||||
|
||||
return ret.Return, nil
|
||||
}
|
@ -5,6 +5,8 @@ import (
|
||||
|
||||
bls "github.com/filecoin-project/filecoin-ffi"
|
||||
amt "github.com/filecoin-project/go-amt-ipld/v2"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
cid "github.com/ipfs/go-cid"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
@ -18,7 +20,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
)
|
||||
|
||||
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, ticket *types.Ticket, proof *types.EPostProof, msgs []*types.SignedMessage, height, timestamp uint64) (*types.FullBlock, error) {
|
||||
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, ticket *types.Ticket, proof *types.EPostProof, msgs []*types.SignedMessage, height abi.ChainEpoch, timestamp uint64) (*types.FullBlock, error) {
|
||||
st, recpts, err := sm.TipSetState(ctx, parents)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to load tipset state: %w", err)
|
||||
@ -44,9 +46,9 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
|
||||
var secpkMessages []*types.SignedMessage
|
||||
|
||||
var blsMsgCids, secpkMsgCids []cid.Cid
|
||||
var blsSigs []types.Signature
|
||||
var blsSigs []crypto.Signature
|
||||
for _, msg := range msgs {
|
||||
if msg.Signature.TypeCode() == types.IKTBLS {
|
||||
if msg.Signature.Type == crypto.SigTypeBLS {
|
||||
blsSigs = append(blsSigs, msg.Signature)
|
||||
blsMessages = append(blsMessages, &msg.Message)
|
||||
|
||||
@ -131,7 +133,7 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
|
||||
return fullBlock, nil
|
||||
}
|
||||
|
||||
func aggregateSignatures(sigs []types.Signature) (types.Signature, error) {
|
||||
func aggregateSignatures(sigs []crypto.Signature) (crypto.Signature, error) {
|
||||
var blsSigs []bls.Signature
|
||||
for _, s := range sigs {
|
||||
var bsig bls.Signature
|
||||
@ -140,8 +142,8 @@ func aggregateSignatures(sigs []types.Signature) (types.Signature, error) {
|
||||
}
|
||||
|
||||
aggSig := bls.Aggregate(blsSigs)
|
||||
return types.Signature{
|
||||
Type: types.KTBLS,
|
||||
return crypto.Signature{
|
||||
Type: crypto.SigTypeBLS,
|
||||
Data: aggSig[:],
|
||||
}, nil
|
||||
}
|
||||
|
@ -1,676 +0,0 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
amt "github.com/filecoin-project/go-amt-ipld/v2"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-datastore"
|
||||
hamt "github.com/ipfs/go-hamt-ipld"
|
||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
bstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
peer "github.com/libp2p/go-libp2p-core/peer"
|
||||
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/state"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
"github.com/filecoin-project/lotus/genesis"
|
||||
)
|
||||
|
||||
type GenesisBootstrap struct {
|
||||
Genesis *types.BlockHeader
|
||||
}
|
||||
|
||||
func SetupInitActor(bs bstore.Blockstore, addrs []address.Address) (*types.Actor, error) {
|
||||
var ias actors.InitActorState
|
||||
ias.NextID = 100
|
||||
|
||||
cst := cbor.NewCborStore(bs)
|
||||
amap := hamt.NewNode(cst)
|
||||
|
||||
for i, a := range addrs {
|
||||
if err := amap.Set(context.TODO(), string(a.Bytes()), 100+uint64(i)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
ias.NextID += uint64(len(addrs))
|
||||
if err := amap.Flush(context.TODO()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
amapcid, err := cst.Put(context.TODO(), amap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ias.AddressMap = amapcid
|
||||
|
||||
statecid, err := cst.Put(context.TODO(), &ias)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
act := &types.Actor{
|
||||
Code: actors.InitCodeCid,
|
||||
Head: statecid,
|
||||
}
|
||||
|
||||
return act, nil
|
||||
}
|
||||
|
||||
func MakeInitialStateTree(bs bstore.Blockstore, actmap map[address.Address]types.BigInt) (*state.StateTree, error) {
|
||||
cst := cbor.NewCborStore(bs)
|
||||
state, err := state.NewStateTree(cst)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("making new state tree: %w", err)
|
||||
}
|
||||
|
||||
emptyobject, err := cst.Put(context.TODO(), map[string]string{})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed putting empty object: %w", err)
|
||||
}
|
||||
|
||||
var addrs []address.Address
|
||||
for a := range actmap {
|
||||
addrs = append(addrs, a)
|
||||
}
|
||||
|
||||
initact, err := SetupInitActor(bs, addrs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setup init actor: %w", err)
|
||||
}
|
||||
|
||||
if err := state.SetActor(actors.InitAddress, initact); err != nil {
|
||||
return nil, xerrors.Errorf("set init actor: %w", err)
|
||||
}
|
||||
|
||||
cronact, err := SetupCronActor(bs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setup cron actor: %w", err)
|
||||
}
|
||||
|
||||
if err := state.SetActor(actors.CronAddress, cronact); err != nil {
|
||||
return nil, xerrors.Errorf("set cron actor: %w", err)
|
||||
}
|
||||
|
||||
spact, err := SetupStoragePowerActor(bs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setup storage market actor: %w", err)
|
||||
}
|
||||
|
||||
if err := state.SetActor(actors.StoragePowerAddress, spact); err != nil {
|
||||
return nil, xerrors.Errorf("set storage market actor: %w", err)
|
||||
}
|
||||
|
||||
netAmt := types.FromFil(build.TotalFilecoin)
|
||||
for _, amt := range actmap {
|
||||
netAmt = types.BigSub(netAmt, amt)
|
||||
}
|
||||
|
||||
err = state.SetActor(actors.NetworkAddress, &types.Actor{
|
||||
Code: actors.AccountCodeCid,
|
||||
Balance: netAmt,
|
||||
Head: emptyobject,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("set network account actor: %w", err)
|
||||
}
|
||||
|
||||
err = state.SetActor(actors.BurntFundsAddress, &types.Actor{
|
||||
Code: actors.AccountCodeCid,
|
||||
Balance: types.NewInt(0),
|
||||
Head: emptyobject,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("set burnt funds account actor: %w", err)
|
||||
}
|
||||
|
||||
for a, v := range actmap {
|
||||
err = state.SetActor(a, &types.Actor{
|
||||
Code: actors.AccountCodeCid,
|
||||
Balance: v,
|
||||
Head: emptyobject,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setting account from actmap: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return state, nil
|
||||
}
|
||||
|
||||
func SetupCronActor(bs bstore.Blockstore) (*types.Actor, error) {
|
||||
cst := cbor.NewCborStore(bs)
|
||||
cas := &actors.CronActorState{}
|
||||
|
||||
stcid, err := cst.Put(context.TODO(), cas)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.Actor{
|
||||
Code: actors.CronCodeCid,
|
||||
Head: stcid,
|
||||
Nonce: 0,
|
||||
Balance: types.NewInt(0),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func SetupStoragePowerActor(bs bstore.Blockstore) (*types.Actor, error) {
|
||||
ctx := context.TODO()
|
||||
cst := cbor.NewCborStore(bs)
|
||||
nd := hamt.NewNode(cst)
|
||||
emptyhamt, err := cst.Put(ctx, nd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blks := cbor.NewCborStore(bs)
|
||||
emptyamt, err := amt.FromArray(ctx, blks, nil)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("amt build failed: %w", err)
|
||||
}
|
||||
|
||||
sms := &actors.StoragePowerState{
|
||||
Miners: emptyhamt,
|
||||
ProvingBuckets: emptyamt,
|
||||
TotalStorage: types.NewInt(0),
|
||||
}
|
||||
|
||||
stcid, err := cst.Put(ctx, sms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.Actor{
|
||||
Code: actors.StoragePowerCodeCid,
|
||||
Head: stcid,
|
||||
Nonce: 0,
|
||||
Balance: types.NewInt(0),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func SetupStorageMarketActor(bs bstore.Blockstore, sroot cid.Cid, deals []actors.StorageDealProposal) (cid.Cid, error) {
|
||||
ctx := context.TODO()
|
||||
cst := cbor.NewCborStore(bs)
|
||||
nd := hamt.NewNode(cst)
|
||||
emptyHAMT, err := cst.Put(ctx, nd)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
cdeals := make([]cbg.CBORMarshaler, len(deals))
|
||||
for i, deal := range deals {
|
||||
cdeals[i] = &actors.OnChainDeal{
|
||||
PieceRef: deal.PieceRef,
|
||||
PieceSize: deal.PieceSize,
|
||||
Client: deal.Client,
|
||||
Provider: deal.Provider,
|
||||
ProposalExpiration: deal.ProposalExpiration,
|
||||
Duration: deal.Duration,
|
||||
StoragePricePerEpoch: deal.StoragePricePerEpoch,
|
||||
StorageCollateral: deal.StorageCollateral,
|
||||
ActivationEpoch: 1,
|
||||
}
|
||||
}
|
||||
|
||||
dealAmt, err := amt.FromArray(ctx, cst, cdeals)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("amt build failed: %w", err)
|
||||
}
|
||||
|
||||
sms := &actors.StorageMarketState{
|
||||
Balances: emptyHAMT,
|
||||
Deals: dealAmt,
|
||||
NextDealID: uint64(len(deals)),
|
||||
}
|
||||
|
||||
stcid, err := cst.Put(context.TODO(), sms)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
act := &types.Actor{
|
||||
Code: actors.StorageMarketCodeCid,
|
||||
Head: stcid,
|
||||
Nonce: 0,
|
||||
Balance: types.NewInt(0),
|
||||
}
|
||||
|
||||
state, err := state.LoadStateTree(cst, sroot)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("making new state tree: %w", err)
|
||||
}
|
||||
|
||||
if err := state.SetActor(actors.StorageMarketAddress, act); err != nil {
|
||||
return cid.Undef, xerrors.Errorf("set storage market actor: %w", err)
|
||||
}
|
||||
|
||||
return state.Flush(context.TODO())
|
||||
}
|
||||
|
||||
type GenMinerCfg struct {
|
||||
PreSeals map[string]genesis.GenesisMiner
|
||||
|
||||
// The addresses of the created miner, this is set by the genesis setup
|
||||
MinerAddrs []address.Address
|
||||
|
||||
PeerIDs []peer.ID
|
||||
}
|
||||
|
||||
func mustEnc(i cbg.CBORMarshaler) []byte {
|
||||
enc, err := actors.SerializeParams(i)
|
||||
if err != nil {
|
||||
panic(err) // ok
|
||||
}
|
||||
return enc
|
||||
}
|
||||
|
||||
func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid, gmcfg *GenMinerCfg) (cid.Cid, []actors.StorageDealProposal, error) {
|
||||
vm, err := vm.NewVM(sroot, 0, nil, actors.NetworkAddress, cs.Blockstore(), cs.VMSys())
|
||||
if err != nil {
|
||||
return cid.Undef, nil, xerrors.Errorf("failed to create NewVM: %w", err)
|
||||
}
|
||||
|
||||
if len(gmcfg.MinerAddrs) == 0 {
|
||||
return cid.Undef, nil, xerrors.New("no genesis miners")
|
||||
}
|
||||
|
||||
if len(gmcfg.MinerAddrs) != len(gmcfg.PreSeals) {
|
||||
return cid.Undef, nil, xerrors.Errorf("miner address list, and preseal count doesn't match (%d != %d)", len(gmcfg.MinerAddrs), len(gmcfg.PreSeals))
|
||||
}
|
||||
|
||||
var deals []actors.StorageDealProposal
|
||||
|
||||
for i, maddr := range gmcfg.MinerAddrs {
|
||||
ps, psok := gmcfg.PreSeals[maddr.String()]
|
||||
if !psok {
|
||||
return cid.Undef, nil, xerrors.Errorf("no preseal for miner %s", maddr)
|
||||
}
|
||||
|
||||
minerParams := &actors.CreateStorageMinerParams{
|
||||
Owner: ps.Owner,
|
||||
Worker: ps.Worker,
|
||||
SectorSize: ps.SectorSize,
|
||||
PeerID: gmcfg.PeerIDs[i], // TODO: grab from preseal too
|
||||
}
|
||||
|
||||
params := mustEnc(minerParams)
|
||||
|
||||
// TODO: hardcoding 6500 here is a little fragile, it changes any
|
||||
// time anyone changes the initial account allocations
|
||||
rval, err := doExecValue(ctx, vm, actors.StoragePowerAddress, ps.Worker, types.FromFil(6500), actors.SPAMethods.CreateStorageMiner, params)
|
||||
if err != nil {
|
||||
return cid.Undef, nil, xerrors.Errorf("failed to create genesis miner: %w", err)
|
||||
}
|
||||
|
||||
maddrret, err := address.NewFromBytes(rval)
|
||||
if err != nil {
|
||||
return cid.Undef, nil, err
|
||||
}
|
||||
|
||||
_, err = vm.Flush(ctx)
|
||||
if err != nil {
|
||||
return cid.Undef, nil, err
|
||||
}
|
||||
|
||||
cst := cbor.NewCborStore(cs.Blockstore())
|
||||
if err := reassignMinerActorAddress(vm, cst, maddrret, maddr); err != nil {
|
||||
return cid.Undef, nil, err
|
||||
}
|
||||
|
||||
power := types.BigMul(types.NewInt(minerParams.SectorSize), types.NewInt(uint64(len(ps.Sectors))))
|
||||
|
||||
params = mustEnc(&actors.UpdateStorageParams{Delta: power})
|
||||
|
||||
_, err = doExec(ctx, vm, actors.StoragePowerAddress, maddr, actors.SPAMethods.UpdateStorage, params)
|
||||
if err != nil {
|
||||
return cid.Undef, nil, xerrors.Errorf("failed to update total storage: %w", err)
|
||||
}
|
||||
|
||||
// we have to flush the vm here because it buffers stuff internally for perf reasons
|
||||
if _, err := vm.Flush(ctx); err != nil {
|
||||
return cid.Undef, nil, xerrors.Errorf("vm.Flush failed: %w", err)
|
||||
}
|
||||
|
||||
st := vm.StateTree()
|
||||
mact, err := st.GetActor(maddr)
|
||||
if err != nil {
|
||||
return cid.Undef, nil, xerrors.Errorf("get miner actor failed: %w", err)
|
||||
}
|
||||
|
||||
var mstate actors.StorageMinerActorState
|
||||
if err := cst.Get(ctx, mact.Head, &mstate); err != nil {
|
||||
return cid.Undef, nil, xerrors.Errorf("getting miner actor state failed: %w", err)
|
||||
}
|
||||
mstate.Power = types.BigMul(types.NewInt(ps.SectorSize), types.NewInt(uint64(len(ps.Sectors))))
|
||||
|
||||
for _, s := range ps.Sectors {
|
||||
nssroot, err := actors.AddToSectorSet(ctx, cst, mstate.Sectors, s.SectorID, s.CommR[:], s.CommD[:])
|
||||
if err != nil {
|
||||
return cid.Undef, nil, xerrors.Errorf("failed to add fake sector to sector set: %w", err)
|
||||
}
|
||||
mstate.Sectors = nssroot
|
||||
mstate.ProvingSet = nssroot
|
||||
|
||||
deals = append(deals, s.Deal)
|
||||
}
|
||||
|
||||
nstate, err := cst.Put(ctx, &mstate)
|
||||
if err != nil {
|
||||
return cid.Undef, nil, err
|
||||
}
|
||||
|
||||
mact.Head = nstate
|
||||
if err := st.SetActor(maddr, mact); err != nil {
|
||||
return cid.Undef, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
c, err := vm.Flush(ctx)
|
||||
return c, deals, err
|
||||
}
|
||||
|
||||
func reassignMinerActorAddress(vm *vm.VM, cst cbor.IpldStore, from, to address.Address) error {
|
||||
if from == to {
|
||||
return nil
|
||||
}
|
||||
act, err := vm.StateTree().GetActor(from)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("reassign: failed to get 'from' actor: %w", err)
|
||||
}
|
||||
|
||||
_, err = vm.StateTree().GetActor(to)
|
||||
if err == nil {
|
||||
return xerrors.Errorf("cannot reassign actor, target address taken")
|
||||
}
|
||||
if err := vm.StateTree().SetActor(to, act); err != nil {
|
||||
return xerrors.Errorf("failed to reassign actor: %w", err)
|
||||
}
|
||||
|
||||
if err := adjustStorageMarketTracking(vm, cst, from, to); err != nil {
|
||||
return xerrors.Errorf("adjusting storage market tracking: %w", err)
|
||||
}
|
||||
|
||||
// Now, adjust the tracking in the init actor
|
||||
return initActorReassign(vm, cst, from, to)
|
||||
}
|
||||
|
||||
func adjustStorageMarketTracking(vm *vm.VM, cst cbor.IpldStore, from, to address.Address) error {
|
||||
ctx := context.TODO()
|
||||
act, err := vm.StateTree().GetActor(actors.StoragePowerAddress)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("loading storage power actor: %w", err)
|
||||
}
|
||||
|
||||
var spst actors.StoragePowerState
|
||||
if err := cst.Get(ctx, act.Head, &spst); err != nil {
|
||||
return xerrors.Errorf("loading storage power actor state: %w", err)
|
||||
}
|
||||
|
||||
miners, err := hamt.LoadNode(ctx, cst, spst.Miners)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("loading miner set: %w", err)
|
||||
}
|
||||
|
||||
if err := miners.Delete(ctx, string(from.Bytes())); err != nil {
|
||||
return xerrors.Errorf("deleting from spa set: %w", err)
|
||||
}
|
||||
|
||||
if err := miners.Set(ctx, string(to.Bytes()), uint64(1)); err != nil {
|
||||
return xerrors.Errorf("failed setting miner: %w", err)
|
||||
}
|
||||
|
||||
if err := miners.Flush(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nminerscid, err := cst.Put(ctx, miners)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
spst.Miners = nminerscid
|
||||
|
||||
nhead, err := cst.Put(ctx, &spst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
act.Head = nhead
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func initActorReassign(vm *vm.VM, cst cbor.IpldStore, from, to address.Address) error {
|
||||
ctx := context.TODO()
|
||||
initact, err := vm.StateTree().GetActor(actors.InitAddress)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("couldnt get init actor: %w", err)
|
||||
}
|
||||
|
||||
var st actors.InitActorState
|
||||
if err := cst.Get(ctx, initact.Head, &st); err != nil {
|
||||
return xerrors.Errorf("reassign loading init actor state: %w", err)
|
||||
}
|
||||
|
||||
amap, err := hamt.LoadNode(ctx, cst, st.AddressMap)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to load init actor map: %w", err)
|
||||
}
|
||||
|
||||
target, err := address.IDFromAddress(from)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to extract ID: %w", err)
|
||||
}
|
||||
|
||||
var out string
|
||||
halt := xerrors.Errorf("halt")
|
||||
err = amap.ForEach(ctx, func(k string, v interface{}) error {
|
||||
_, val, err := cbg.CborReadHeader(bytes.NewReader(v.(*cbg.Deferred).Raw))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("parsing int in map failed: %w", err)
|
||||
}
|
||||
|
||||
if val == target {
|
||||
out = k
|
||||
return halt
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err == nil {
|
||||
return xerrors.Errorf("could not find from address in init ID map")
|
||||
}
|
||||
if !xerrors.Is(err, halt) {
|
||||
return xerrors.Errorf("finding address in ID map failed: %w", err)
|
||||
}
|
||||
|
||||
if err := amap.Delete(ctx, out); err != nil {
|
||||
return xerrors.Errorf("deleting 'from' entry in amap: %w", err)
|
||||
}
|
||||
|
||||
if err := amap.Set(ctx, out, target); err != nil {
|
||||
return xerrors.Errorf("setting 'to' entry in amap: %w", err)
|
||||
}
|
||||
|
||||
if err := amap.Flush(ctx); err != nil {
|
||||
return xerrors.Errorf("failed to flush amap: %w", err)
|
||||
}
|
||||
|
||||
ncid, err := cst.Put(ctx, amap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
st.AddressMap = ncid
|
||||
|
||||
nacthead, err := cst.Put(ctx, &st)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
initact.Head = nacthead
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func doExec(ctx context.Context, vm *vm.VM, to, from address.Address, method uint64, params []byte) ([]byte, error) {
|
||||
return doExecValue(ctx, vm, to, from, types.NewInt(0), method, params)
|
||||
}
|
||||
|
||||
func doExecValue(ctx context.Context, vm *vm.VM, to, from address.Address, value types.BigInt, method uint64, params []byte) ([]byte, error) {
|
||||
act, err := vm.StateTree().GetActor(from)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("doExec failed to get from actor: %w", err)
|
||||
}
|
||||
|
||||
ret, err := vm.ApplyMessage(context.TODO(), &types.Message{
|
||||
To: to,
|
||||
From: from,
|
||||
Method: method,
|
||||
Params: params,
|
||||
GasLimit: types.NewInt(1000000),
|
||||
GasPrice: types.NewInt(0),
|
||||
Value: value,
|
||||
Nonce: act.Nonce,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("doExec apply message failed: %w", err)
|
||||
}
|
||||
|
||||
if ret.ExitCode != 0 {
|
||||
return nil, fmt.Errorf("failed to call method: %s", ret.ActorErr)
|
||||
}
|
||||
|
||||
return ret.Return, nil
|
||||
}
|
||||
|
||||
func MakeGenesisBlock(bs bstore.Blockstore, sys *types.VMSyscalls, balances map[address.Address]types.BigInt, gmcfg *GenMinerCfg, ts uint64) (*GenesisBootstrap, error) {
|
||||
ctx := context.TODO()
|
||||
|
||||
state, err := MakeInitialStateTree(bs, balances)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("make initial state tree failed: %w", err)
|
||||
}
|
||||
|
||||
stateroot, err := state.Flush(ctx)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("flush state tree failed: %w", err)
|
||||
}
|
||||
|
||||
// temp chainstore
|
||||
cs := store.NewChainStore(bs, datastore.NewMapDatastore(), sys)
|
||||
stateroot, deals, err := SetupStorageMiners(ctx, cs, stateroot, gmcfg)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setup storage miners failed: %w", err)
|
||||
}
|
||||
|
||||
stateroot, err = SetupStorageMarketActor(bs, stateroot, deals)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setup storage market actor: %w", err)
|
||||
}
|
||||
|
||||
stateroot, err = AdjustInitActorStartID(ctx, bs, stateroot, 1000)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to adjust init actor start ID: %w", err)
|
||||
}
|
||||
|
||||
cst := cbor.NewCborStore(bs)
|
||||
|
||||
emptyroot, err := amt.FromArray(ctx, cst, nil)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("amt build failed: %w", err)
|
||||
}
|
||||
|
||||
mm := &types.MsgMeta{
|
||||
BlsMessages: emptyroot,
|
||||
SecpkMessages: emptyroot,
|
||||
}
|
||||
mmb, err := mm.ToStorageBlock()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("serializing msgmeta failed: %w", err)
|
||||
}
|
||||
if err := bs.Put(mmb); err != nil {
|
||||
return nil, xerrors.Errorf("putting msgmeta block to blockstore: %w", err)
|
||||
}
|
||||
|
||||
log.Infof("Empty Genesis root: %s", emptyroot)
|
||||
|
||||
genesisticket := &types.Ticket{
|
||||
VRFProof: []byte("vrf proof0000000vrf proof0000000"),
|
||||
}
|
||||
|
||||
b := &types.BlockHeader{
|
||||
Miner: actors.InitAddress,
|
||||
Ticket: genesisticket,
|
||||
EPostProof: types.EPostProof{
|
||||
Proof: []byte("not a real proof"),
|
||||
PostRand: []byte("i guess this is kinda random"),
|
||||
},
|
||||
Parents: []cid.Cid{},
|
||||
Height: 0,
|
||||
ParentWeight: types.NewInt(0),
|
||||
ParentStateRoot: stateroot,
|
||||
Messages: mmb.Cid(),
|
||||
ParentMessageReceipts: emptyroot,
|
||||
BLSAggregate: types.Signature{Type: types.KTBLS, Data: []byte("signatureeee")},
|
||||
BlockSig: &types.Signature{Type: types.KTBLS, Data: []byte("block signatureeee")},
|
||||
Timestamp: ts,
|
||||
}
|
||||
|
||||
sb, err := b.ToStorageBlock()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("serializing block header failed: %w", err)
|
||||
}
|
||||
|
||||
if err := bs.Put(sb); err != nil {
|
||||
return nil, xerrors.Errorf("putting header to blockstore: %w", err)
|
||||
}
|
||||
|
||||
return &GenesisBootstrap{
|
||||
Genesis: b,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func AdjustInitActorStartID(ctx context.Context, bs blockstore.Blockstore, stateroot cid.Cid, val uint64) (cid.Cid, error) {
|
||||
cst := cbor.NewCborStore(bs)
|
||||
|
||||
tree, err := state.LoadStateTree(cst, stateroot)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
act, err := tree.GetActor(actors.InitAddress)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
var st actors.InitActorState
|
||||
if err := cst.Get(ctx, act.Head, &st); err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
st.NextID = val
|
||||
|
||||
nstate, err := cst.Put(ctx, &st)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
act.Head = nstate
|
||||
|
||||
if err := tree.SetActor(actors.InitAddress, act); err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
return tree.Flush(ctx)
|
||||
}
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
@ -40,7 +41,7 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr address.Address, am
|
||||
return err
|
||||
}
|
||||
|
||||
avail = bal.Available
|
||||
avail = types.BigSub(bal.Escrow, bal.Locked)
|
||||
}
|
||||
|
||||
toAdd := types.NewInt(0)
|
||||
@ -55,13 +56,20 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr address.Address, am
|
||||
|
||||
fm.lk.Unlock()
|
||||
|
||||
var err error
|
||||
params, err := actors.SerializeParams(&addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
smsg, err := fm.mpool.MpoolPushMessage(ctx, &types.Message{
|
||||
To: actors.StorageMarketAddress,
|
||||
To: builtin.StorageMarketActorAddr,
|
||||
From: addr,
|
||||
Value: toAdd,
|
||||
GasPrice: types.NewInt(0),
|
||||
GasLimit: types.NewInt(1000000),
|
||||
Method: actors.SMAMethods.AddBalance,
|
||||
Method: builtin.MethodsMarket.AddBalance,
|
||||
Params: params,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-datastore"
|
||||
@ -342,7 +343,7 @@ func (mp *MessagePool) addSkipChecks(m *types.SignedMessage) error {
|
||||
|
||||
func (mp *MessagePool) addLocked(m *types.SignedMessage) error {
|
||||
log.Debugf("mpooladd: %s %s", m.Message.From, m.Message.Nonce)
|
||||
if m.Signature.Type == types.KTBLS {
|
||||
if m.Signature.Type == crypto.SigTypeBLS {
|
||||
mp.blsSigCache.Add(m.Cid(), m.Signature)
|
||||
}
|
||||
|
||||
@ -656,7 +657,7 @@ func (mp *MessagePool) RecoverSig(msg *types.Message) *types.SignedMessage {
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
sig, ok := val.(types.Signature)
|
||||
sig, ok := val.(crypto.Signature)
|
||||
if !ok {
|
||||
log.Errorf("value in signature cache was not a signature (got %T)", val)
|
||||
return nil
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-datastore"
|
||||
)
|
||||
@ -146,7 +147,7 @@ func TestMessagePool(t *testing.T) {
|
||||
|
||||
a := mock.MkBlock(nil, 1, 1)
|
||||
|
||||
sender, err := w.GenerateKey(types.KTBLS)
|
||||
sender, err := w.GenerateKey(crypto.SigTypeBLS)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -188,7 +189,7 @@ func TestRevertMessages(t *testing.T) {
|
||||
a := mock.MkBlock(nil, 1, 1)
|
||||
b := mock.MkBlock(mock.TipSet(a), 1, 1)
|
||||
|
||||
sender, err := w.GenerateKey(types.KTBLS)
|
||||
sender, err := w.GenerateKey(crypto.SigTypeBLS)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/ipfs/go-cid"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||
@ -68,7 +69,7 @@ type message struct {
|
||||
// TipSet
|
||||
Cids []cid.Cid
|
||||
Blocks []*types.BlockHeader
|
||||
Height uint64
|
||||
Height abi.ChainEpoch
|
||||
Weight types.BigInt
|
||||
Time uint64
|
||||
Nonce uint64
|
||||
|
@ -3,7 +3,10 @@ package state
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||
"github.com/ipfs/go-cid"
|
||||
hamt "github.com/ipfs/go-hamt-ipld"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
@ -12,7 +15,6 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
@ -28,14 +30,14 @@ type StateTree struct {
|
||||
|
||||
func NewStateTree(cst cbor.IpldStore) (*StateTree, error) {
|
||||
return &StateTree{
|
||||
root: hamt.NewNode(cst),
|
||||
root: hamt.NewNode(cst, hamt.UseTreeBitWidth(5)),
|
||||
Store: cst,
|
||||
actorcache: make(map[address.Address]*types.Actor),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) {
|
||||
nd, err := hamt.LoadNode(context.Background(), cst, c)
|
||||
nd, err := hamt.LoadNode(context.Background(), cst, c, hamt.UseTreeBitWidth(5))
|
||||
if err != nil {
|
||||
log.Errorf("loading hamt node %s failed: %s", c, err)
|
||||
return nil, err
|
||||
@ -72,17 +74,21 @@ func (st *StateTree) LookupID(addr address.Address) (address.Address, error) {
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
act, err := st.GetActor(actors.InitAddress)
|
||||
act, err := st.GetActor(builtin.InitActorAddr)
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("getting init actor: %w", err)
|
||||
}
|
||||
|
||||
var ias actors.InitActorState
|
||||
var ias init_.State
|
||||
if err := st.Store.Get(context.TODO(), act.Head, &ias); err != nil {
|
||||
return address.Undef, xerrors.Errorf("loading init actor state: %w", err)
|
||||
}
|
||||
|
||||
return ias.Lookup(st.Store, addr)
|
||||
a, err := ias.ResolveAddress(&AdtStore{st.Store}, addr)
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("resolve address %s: %w", addr, err)
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func (st *StateTree) GetActor(addr address.Address) (*types.Actor, error) {
|
||||
@ -92,8 +98,8 @@ func (st *StateTree) GetActor(addr address.Address) (*types.Actor, error) {
|
||||
|
||||
iaddr, err := st.LookupID(addr)
|
||||
if err != nil {
|
||||
if xerrors.Is(err, hamt.ErrNotFound) {
|
||||
return nil, xerrors.Errorf("resolution lookup failed (%s): %w", addr, types.ErrActorNotFound)
|
||||
if xerrors.Is(err, init_.ErrAddressNotFound) {
|
||||
return nil, xerrors.Errorf("resolution lookup failed (%s): %w", addr, err)
|
||||
}
|
||||
return nil, xerrors.Errorf("address resolution: %w", err)
|
||||
}
|
||||
@ -151,13 +157,13 @@ func (st *StateTree) Snapshot(ctx context.Context) error {
|
||||
|
||||
func (st *StateTree) RegisterNewAddress(addr address.Address, act *types.Actor) (address.Address, error) {
|
||||
var out address.Address
|
||||
err := st.MutateActor(actors.InitAddress, func(initact *types.Actor) error {
|
||||
var ias actors.InitActorState
|
||||
err := st.MutateActor(builtin.InitActorAddr, func(initact *types.Actor) error {
|
||||
var ias init_.State
|
||||
if err := st.Store.Get(context.TODO(), initact.Head, &ias); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
oaddr, err := ias.AddActor(st.Store, addr)
|
||||
oaddr, err := ias.MapAddressToNewID(&AdtStore{st.Store}, addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -182,8 +188,16 @@ func (st *StateTree) RegisterNewAddress(addr address.Address, act *types.Actor)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
type AdtStore struct{ cbor.IpldStore }
|
||||
|
||||
func (a *AdtStore) Context() context.Context {
|
||||
return context.TODO()
|
||||
}
|
||||
|
||||
var _ adt.Store = (*AdtStore)(nil)
|
||||
|
||||
func (st *StateTree) Revert() error {
|
||||
nd, err := hamt.LoadNode(context.Background(), st.Store, st.snapshot)
|
||||
nd, err := hamt.LoadNode(context.Background(), st.Store, st.snapshot, hamt.UseTreeBitWidth(5))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -2,10 +2,10 @@ package state
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"testing"
|
||||
|
||||
address "github.com/filecoin-project/go-address"
|
||||
actors "github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
)
|
||||
@ -27,8 +27,8 @@ func BenchmarkStateTreeSet(b *testing.B) {
|
||||
}
|
||||
err = st.SetActor(a, &types.Actor{
|
||||
Balance: types.NewInt(1258812523),
|
||||
Code: actors.StorageMinerCodeCid,
|
||||
Head: actors.AccountCodeCid,
|
||||
Code: builtin.StorageMinerActorCodeID,
|
||||
Head: builtin.AccountActorCodeID,
|
||||
Nonce: uint64(i),
|
||||
})
|
||||
if err != nil {
|
||||
@ -54,8 +54,8 @@ func BenchmarkStateTreeSetFlush(b *testing.B) {
|
||||
}
|
||||
err = st.SetActor(a, &types.Actor{
|
||||
Balance: types.NewInt(1258812523),
|
||||
Code: actors.StorageMinerCodeCid,
|
||||
Head: actors.AccountCodeCid,
|
||||
Code: builtin.StorageMinerActorCodeID,
|
||||
Head: builtin.AccountActorCodeID,
|
||||
Nonce: uint64(i),
|
||||
})
|
||||
if err != nil {
|
||||
@ -80,8 +80,8 @@ func BenchmarkStateTree10kGetActor(b *testing.B) {
|
||||
}
|
||||
err = st.SetActor(a, &types.Actor{
|
||||
Balance: types.NewInt(1258812523 + uint64(i)),
|
||||
Code: actors.StorageMinerCodeCid,
|
||||
Head: actors.AccountCodeCid,
|
||||
Code: builtin.StorageMinerActorCodeID,
|
||||
Head: builtin.AccountActorCodeID,
|
||||
Nonce: uint64(i),
|
||||
})
|
||||
if err != nil {
|
||||
@ -123,8 +123,8 @@ func TestSetCache(t *testing.T) {
|
||||
|
||||
act := &types.Actor{
|
||||
Balance: types.NewInt(0),
|
||||
Code: actors.StorageMinerCodeCid,
|
||||
Head: actors.AccountCodeCid,
|
||||
Code: builtin.StorageMinerActorCodeID,
|
||||
Head: builtin.AccountActorCodeID,
|
||||
Nonce: 0,
|
||||
}
|
||||
|
||||
|
@ -3,23 +3,24 @@ package stmgr
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/ipfs/go-cid"
|
||||
"go.opencensus.io/trace"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
)
|
||||
|
||||
func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate cid.Cid, r vm.Rand, bheight uint64) (*api.MethodCall, error) {
|
||||
func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate cid.Cid, r vm.Rand, bheight abi.ChainEpoch) (*api.MethodCall, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "statemanager.CallRaw")
|
||||
defer span.End()
|
||||
|
||||
vmi, err := vm.NewVM(bstate, bheight, r, actors.NetworkAddress, sm.cs.Blockstore(), sm.cs.VMSys())
|
||||
vmi, err := vm.NewVM(bstate, bheight, r, builtin.SystemActorAddr, sm.cs.Blockstore(), sm.cs.VMSys())
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to set up vm: %w", err)
|
||||
}
|
||||
|
@ -3,12 +3,13 @@ package stmgr
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/ipfs/go-cid"
|
||||
)
|
||||
|
||||
var ForksAtHeight = map[uint64]func(context.Context, *StateManager, cid.Cid) (cid.Cid, error){}
|
||||
var ForksAtHeight = map[abi.ChainEpoch]func(context.Context, *StateManager, cid.Cid) (cid.Cid, error){}
|
||||
|
||||
func (sm *StateManager) handleStateForks(ctx context.Context, pstate cid.Cid, height, parentH uint64) (_ cid.Cid, err error) {
|
||||
func (sm *StateManager) handleStateForks(ctx context.Context, pstate cid.Cid, height, parentH abi.ChainEpoch) (_ cid.Cid, err error) {
|
||||
for i := parentH; i < height; i++ {
|
||||
f, ok := ForksAtHeight[i]
|
||||
if ok {
|
||||
|
@ -7,6 +7,12 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
||||
"github.com/filecoin-project/specs-actors/actors/runtime"
|
||||
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||
@ -28,7 +34,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
build.SectorSizes = []uint64{1024}
|
||||
build.SectorSizes = []abi.SectorSize{1024}
|
||||
build.MinimumMinerPower = 1024
|
||||
}
|
||||
|
||||
@ -69,10 +75,14 @@ func (ta *testActor) Constructor(act *types.Actor, vmctx types.VMContext, params
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
empty, err := vmctx.Storage().Put(&adt.EmptyValue{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Println("NEW ACTOR ADDRESS IS: ", vmctx.Message().To.String())
|
||||
|
||||
return nil, vmctx.Storage().Commit(actors.EmptyCBOR, c)
|
||||
return nil, vmctx.Storage().Commit(empty, c)
|
||||
}
|
||||
|
||||
func (ta *testActor) TestMethod(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, aerrors.ActorError) {
|
||||
@ -114,8 +124,6 @@ func TestForkHeightTriggers(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
actors.BuiltInActors[actcid] = true
|
||||
|
||||
// predicting the address here... may break if other assumptions change
|
||||
taddr, err := address.NewIDAddress(1000)
|
||||
if err != nil {
|
||||
@ -156,7 +164,7 @@ func TestForkHeightTriggers(t *testing.T) {
|
||||
}
|
||||
|
||||
inv.Register(actcid, &testActor{}, &testActorState{})
|
||||
sm.SetVMConstructor(func(c cid.Cid, h uint64, r vm.Rand, a address.Address, b blockstore.Blockstore, s *types.VMSyscalls) (*vm.VM, error) {
|
||||
sm.SetVMConstructor(func(c cid.Cid, h abi.ChainEpoch, r vm.Rand, a address.Address, b blockstore.Blockstore, s runtime.Syscalls) (*vm.VM, error) {
|
||||
nvm, err := vm.NewVM(c, h, r, a, b, s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -169,15 +177,15 @@ func TestForkHeightTriggers(t *testing.T) {
|
||||
|
||||
var msgs []*types.SignedMessage
|
||||
|
||||
enc, err := actors.SerializeParams(&actors.ExecParams{Code: actcid})
|
||||
enc, err := actors.SerializeParams(&init_.ExecParams{CodeCID: actcid})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
m := &types.Message{
|
||||
From: cg.Banker(),
|
||||
To: actors.InitAddress,
|
||||
Method: actors.IAMethods.Exec,
|
||||
To: builtin.InitActorAddr,
|
||||
Method: builtin.MethodsInit.Exec,
|
||||
Params: enc,
|
||||
GasLimit: types.NewInt(10000),
|
||||
GasPrice: types.NewInt(0),
|
||||
|
@ -7,11 +7,17 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
amt "github.com/filecoin-project/go-amt-ipld/v2"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||
"github.com/filecoin-project/specs-actors/actors/runtime"
|
||||
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
@ -32,7 +38,7 @@ type StateManager struct {
|
||||
stCache map[string][]cid.Cid
|
||||
compWait map[string]chan struct{}
|
||||
stlk sync.Mutex
|
||||
newVM func(cid.Cid, uint64, vm.Rand, address.Address, blockstore.Blockstore, *types.VMSyscalls) (*vm.VM, error)
|
||||
newVM func(cid.Cid, abi.ChainEpoch, vm.Rand, address.Address, blockstore.Blockstore, runtime.Syscalls) (*vm.VM, error)
|
||||
}
|
||||
|
||||
func NewStateManager(cs *store.ChainStore) *StateManager {
|
||||
@ -148,13 +154,13 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
|
||||
return cid.Undef, cid.Undef, xerrors.Errorf("instantiating VM failed: %w", err)
|
||||
}
|
||||
|
||||
netact, err := vmi.StateTree().GetActor(actors.NetworkAddress)
|
||||
rewardActor, err := vmi.StateTree().GetActor(builtin.RewardActorAddr)
|
||||
if err != nil {
|
||||
return cid.Undef, cid.Undef, xerrors.Errorf("failed to get network actor: %w", err)
|
||||
}
|
||||
reward := vm.MiningReward(netact.Balance)
|
||||
for tsi, b := range blks {
|
||||
netact, err = vmi.StateTree().GetActor(actors.NetworkAddress)
|
||||
reward := vm.MiningReward(rewardActor.Balance)
|
||||
for _, b := range blks {
|
||||
rewardActor, err = vmi.StateTree().GetActor(builtin.RewardActorAddr)
|
||||
if err != nil {
|
||||
return cid.Undef, cid.Undef, xerrors.Errorf("failed to get network actor: %w", err)
|
||||
}
|
||||
@ -170,27 +176,9 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
|
||||
return cid.Undef, cid.Undef, xerrors.Errorf("failed to get miner owner actor")
|
||||
}
|
||||
|
||||
if err := vm.Transfer(netact, act, reward); err != nil {
|
||||
if err := vm.Transfer(rewardActor, act, reward); err != nil {
|
||||
return cid.Undef, cid.Undef, xerrors.Errorf("failed to deduct funds from network actor: %w", err)
|
||||
}
|
||||
|
||||
// all block miners created a valid post, go update the actor state
|
||||
postSubmitMsg := &types.Message{
|
||||
From: actors.NetworkAddress,
|
||||
Nonce: netact.Nonce,
|
||||
To: b.Miner,
|
||||
Method: actors.MAMethods.SubmitElectionPoSt,
|
||||
GasPrice: types.NewInt(0),
|
||||
GasLimit: types.NewInt(10000000000),
|
||||
Value: types.NewInt(0),
|
||||
}
|
||||
ret, err := vmi.ApplyMessage(ctx, postSubmitMsg)
|
||||
if err != nil {
|
||||
return cid.Undef, cid.Undef, xerrors.Errorf("submit election post message for block %s (miner %s) invocation failed: %w", b.Cid(), b.Miner, err)
|
||||
}
|
||||
if ret.ExitCode != 0 {
|
||||
return cid.Undef, cid.Undef, xerrors.Errorf("submit election post invocation returned nonzero exit code: %d (err = %s, block = %s, miner = %s, tsi = %d)", ret.ExitCode, ret.ActorErr, b.Cid(), b.Miner, tsi)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: can't use method from chainstore because it doesnt let us know who the block miners were
|
||||
@ -259,19 +247,19 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
|
||||
}
|
||||
|
||||
// TODO: this nonce-getting is a tiny bit ugly
|
||||
ca, err := vmi.StateTree().GetActor(actors.CronAddress)
|
||||
ca, err := vmi.StateTree().GetActor(builtin.SystemActorAddr)
|
||||
if err != nil {
|
||||
return cid.Undef, cid.Undef, err
|
||||
}
|
||||
|
||||
ret, err := vmi.ApplyMessage(ctx, &types.Message{
|
||||
To: actors.CronAddress,
|
||||
From: actors.CronAddress,
|
||||
To: builtin.CronActorAddr,
|
||||
From: builtin.SystemActorAddr,
|
||||
Nonce: ca.Nonce,
|
||||
Value: types.NewInt(0),
|
||||
GasPrice: types.NewInt(0),
|
||||
GasLimit: types.NewInt(1 << 30), // Make super sure this is never too little
|
||||
Method: actors.CAMethods.EpochTick,
|
||||
Method: builtin.MethodsCron.EpochTick,
|
||||
Params: nil,
|
||||
})
|
||||
if err != nil {
|
||||
@ -295,15 +283,27 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
|
||||
return st, rectroot, nil
|
||||
}
|
||||
|
||||
func (sm *StateManager) GetActor(addr address.Address, ts *types.TipSet) (*types.Actor, error) {
|
||||
func (sm *StateManager) parentState(ts *types.TipSet) cid.Cid {
|
||||
if ts == nil {
|
||||
ts = sm.cs.GetHeaviestTipSet()
|
||||
}
|
||||
|
||||
stcid := ts.ParentState()
|
||||
return ts.ParentState()
|
||||
}
|
||||
|
||||
func (sm *StateManager) GetActor(addr address.Address, ts *types.TipSet) (*types.Actor, error) {
|
||||
cst := cbor.NewCborStore(sm.cs.Blockstore())
|
||||
state, err := state.LoadStateTree(cst, stcid)
|
||||
state, err := state.LoadStateTree(cst, sm.parentState(ts))
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("load state tree: %w", err)
|
||||
}
|
||||
|
||||
return state.GetActor(addr)
|
||||
}
|
||||
|
||||
func (sm *StateManager) getActorRaw(addr address.Address, st cid.Cid) (*types.Actor, error) {
|
||||
cst := cbor.NewCborStore(sm.cs.Blockstore())
|
||||
state, err := state.LoadStateTree(cst, st)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("load state tree: %w", err)
|
||||
}
|
||||
@ -335,11 +335,30 @@ func (sm *StateManager) LoadActorState(ctx context.Context, a address.Address, o
|
||||
|
||||
cst := cbor.NewCborStore(sm.cs.Blockstore())
|
||||
if err := cst.Get(ctx, act.Head, out); err != nil {
|
||||
var r cbg.Deferred
|
||||
cst.Get(ctx, act.Head, &r)
|
||||
fmt.Printf("badhead %x\n", r.Raw)
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return act, nil
|
||||
}
|
||||
|
||||
func (sm *StateManager) LoadActorStateRaw(ctx context.Context, a address.Address, out interface{}, st cid.Cid) (*types.Actor, error) {
|
||||
act, err := sm.getActorRaw(a, st)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cst := cbor.NewCborStore(sm.cs.Blockstore())
|
||||
if err := cst.Get(ctx, act.Head, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return act, nil
|
||||
}
|
||||
|
||||
func (sm *StateManager) ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
|
||||
switch addr.Protocol() {
|
||||
case address.BLS, address.SECP256K1:
|
||||
@ -381,6 +400,15 @@ func (sm *StateManager) GetBlsPublicKey(ctx context.Context, addr address.Addres
|
||||
return pubk, nil
|
||||
}
|
||||
|
||||
func (sm *StateManager) LookupID(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
|
||||
cst := cbor.NewCborStore(sm.cs.Blockstore())
|
||||
state, err := state.LoadStateTree(cst, sm.parentState(ts))
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("load state tree: %w", err)
|
||||
}
|
||||
return state.LookupID(addr)
|
||||
}
|
||||
|
||||
func (sm *StateManager) GetReceipt(ctx context.Context, msg cid.Cid, ts *types.TipSet) (*types.MessageReceipt, error) {
|
||||
m, err := sm.cs.GetCMessage(msg)
|
||||
if err != nil {
|
||||
@ -577,7 +605,7 @@ func (sm *StateManager) ListAllActors(ctx context.Context, ts *types.TipSet) ([]
|
||||
}
|
||||
|
||||
cst := cbor.NewCborStore(sm.cs.Blockstore())
|
||||
r, err := hamt.LoadNode(ctx, cst, st)
|
||||
r, err := hamt.LoadNode(ctx, cst, st, hamt.UseTreeBitWidth(5))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -598,18 +626,49 @@ func (sm *StateManager) ListAllActors(ctx context.Context, ts *types.TipSet) ([]
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (sm *StateManager) MarketBalance(ctx context.Context, addr address.Address, ts *types.TipSet) (actors.StorageParticipantBalance, error) {
|
||||
var state actors.StorageMarketState
|
||||
if _, err := sm.LoadActorState(ctx, actors.StorageMarketAddress, &state, ts); err != nil {
|
||||
return actors.StorageParticipantBalance{}, err
|
||||
}
|
||||
cst := cbor.NewCborStore(sm.cs.Blockstore())
|
||||
b, _, err := actors.GetMarketBalances(ctx, cst, state.Balances, addr)
|
||||
func (sm *StateManager) MarketBalance(ctx context.Context, addr address.Address, ts *types.TipSet) (api.MarketBalance, error) {
|
||||
var state market.State
|
||||
_, err := sm.LoadActorState(ctx, builtin.StorageMarketActorAddr, &state, ts)
|
||||
if err != nil {
|
||||
return actors.StorageParticipantBalance{}, err
|
||||
return api.MarketBalance{}, err
|
||||
}
|
||||
|
||||
return b[0], nil
|
||||
addr, err = sm.LookupID(ctx, addr, ts)
|
||||
if err != nil {
|
||||
return api.MarketBalance{}, err
|
||||
}
|
||||
|
||||
var out api.MarketBalance
|
||||
|
||||
et := adt.AsBalanceTable(sm.cs.Store(ctx), state.EscrowTable)
|
||||
ehas, err := et.Has(addr)
|
||||
if err != nil {
|
||||
return api.MarketBalance{}, err
|
||||
}
|
||||
if ehas {
|
||||
out.Escrow, err = et.Get(addr)
|
||||
if err != nil {
|
||||
return api.MarketBalance{}, xerrors.Errorf("getting escrow balance: %w", err)
|
||||
}
|
||||
} else {
|
||||
out.Escrow = big.Zero()
|
||||
}
|
||||
|
||||
lt := adt.AsBalanceTable(sm.cs.Store(ctx), state.LockedTable)
|
||||
lhas, err := lt.Has(addr)
|
||||
if err != nil {
|
||||
return api.MarketBalance{}, err
|
||||
}
|
||||
if lhas {
|
||||
out.Locked, err = lt.Get(addr)
|
||||
if err != nil {
|
||||
return api.MarketBalance{}, xerrors.Errorf("getting locked balance: %w", err)
|
||||
}
|
||||
} else {
|
||||
out.Locked = big.Zero()
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (sm *StateManager) ValidateChain(ctx context.Context, ts *types.TipSet) error {
|
||||
@ -641,6 +700,6 @@ func (sm *StateManager) ValidateChain(ctx context.Context, ts *types.TipSet) err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sm *StateManager) SetVMConstructor(nvm func(cid.Cid, uint64, vm.Rand, address.Address, blockstore.Blockstore, *types.VMSyscalls) (*vm.VM, error)) {
|
||||
func (sm *StateManager) SetVMConstructor(nvm func(cid.Cid, abi.ChainEpoch, vm.Rand, address.Address, blockstore.Blockstore, runtime.Syscalls) (*vm.VM, error)) {
|
||||
sm.newVM = nvm
|
||||
}
|
||||
|
@ -2,17 +2,27 @@ package stmgr
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
|
||||
amt "github.com/filecoin-project/go-amt-ipld/v2"
|
||||
commcid "github.com/filecoin-project/go-fil-commcid"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
||||
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||
|
||||
ffi "github.com/filecoin-project/filecoin-ffi"
|
||||
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
|
||||
|
||||
ffi "github.com/filecoin-project/filecoin-ffi"
|
||||
|
||||
"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/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
@ -26,146 +36,83 @@ import (
|
||||
)
|
||||
|
||||
func GetMinerWorkerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (address.Address, error) {
|
||||
recp, err := sm.CallRaw(ctx, &types.Message{
|
||||
To: maddr,
|
||||
From: maddr,
|
||||
Method: actors.MAMethods.GetWorkerAddr,
|
||||
}, st, nil, 0)
|
||||
var mas miner.State
|
||||
_, err := sm.LoadActorStateRaw(ctx, maddr, &mas, st)
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("callRaw failed: %w", err)
|
||||
return address.Undef, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
||||
}
|
||||
|
||||
if recp.ExitCode != 0 {
|
||||
return address.Undef, xerrors.Errorf("getting miner worker addr failed (exit code %d)", recp.ExitCode)
|
||||
}
|
||||
|
||||
worker, err := address.NewFromBytes(recp.Return)
|
||||
cst := cbor.NewCborStore(sm.cs.Blockstore())
|
||||
state, err := state.LoadStateTree(cst, st)
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
return address.Undef, xerrors.Errorf("load state tree: %w", err)
|
||||
}
|
||||
|
||||
if worker.Protocol() == address.ID {
|
||||
return address.Undef, xerrors.Errorf("need to resolve worker address to a pubkeyaddr")
|
||||
}
|
||||
|
||||
return worker, nil
|
||||
return vm.ResolveToKeyAddr(state, cst, mas.Info.Worker)
|
||||
}
|
||||
|
||||
func GetMinerOwner(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (address.Address, error) {
|
||||
recp, err := sm.CallRaw(ctx, &types.Message{
|
||||
To: maddr,
|
||||
From: maddr,
|
||||
Method: actors.MAMethods.GetOwner,
|
||||
}, st, nil, 0)
|
||||
var mas miner.State
|
||||
_, err := sm.LoadActorStateRaw(ctx, maddr, &mas, st)
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("callRaw failed: %w", err)
|
||||
return address.Undef, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
||||
}
|
||||
|
||||
if recp.ExitCode != 0 {
|
||||
return address.Undef, xerrors.Errorf("getting miner owner addr failed (exit code %d)", recp.ExitCode)
|
||||
}
|
||||
|
||||
owner, err := address.NewFromBytes(recp.Return)
|
||||
cst := cbor.NewCborStore(sm.cs.Blockstore())
|
||||
state, err := state.LoadStateTree(cst, st)
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
return address.Undef, xerrors.Errorf("load state tree: %w", err)
|
||||
}
|
||||
|
||||
if owner.Protocol() == address.ID {
|
||||
return address.Undef, xerrors.Errorf("need to resolve owner address to a pubkeyaddr")
|
||||
}
|
||||
|
||||
return owner, nil
|
||||
return vm.ResolveToKeyAddr(state, cst, mas.Info.Owner)
|
||||
}
|
||||
|
||||
func GetPower(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (types.BigInt, types.BigInt, error) {
|
||||
var err error
|
||||
|
||||
var mpow types.BigInt
|
||||
|
||||
if maddr != address.Undef {
|
||||
enc, aerr := actors.SerializeParams(&actors.PowerLookupParams{maddr})
|
||||
if aerr != nil {
|
||||
return types.EmptyInt, types.EmptyInt, aerr
|
||||
}
|
||||
ret, err := sm.Call(ctx, &types.Message{
|
||||
From: maddr,
|
||||
To: actors.StoragePowerAddress,
|
||||
Method: actors.SPAMethods.PowerLookup,
|
||||
Params: enc,
|
||||
}, ts)
|
||||
if err != nil {
|
||||
return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get miner power from chain: %w", err)
|
||||
}
|
||||
if ret.ExitCode != 0 {
|
||||
return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get miner power from chain (exit code %d)", ret.ExitCode)
|
||||
}
|
||||
|
||||
mpow = types.BigFromBytes(ret.Return)
|
||||
}
|
||||
|
||||
ret, err := sm.Call(ctx, &types.Message{
|
||||
From: actors.StoragePowerAddress,
|
||||
To: actors.StoragePowerAddress,
|
||||
Method: actors.SPAMethods.GetTotalStorage,
|
||||
}, ts)
|
||||
var ps power.State
|
||||
_, err := sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &ps, ts)
|
||||
if err != nil {
|
||||
return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get total power from chain: %w", err)
|
||||
}
|
||||
if ret.ExitCode != 0 {
|
||||
return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get total power from chain (exit code %d)", ret.ExitCode)
|
||||
return big.Zero(), big.Zero(), xerrors.Errorf("(get sset) failed to load power actor state: %w", err)
|
||||
}
|
||||
|
||||
tpow := types.BigFromBytes(ret.Return)
|
||||
var mpow big.Int
|
||||
if maddr != address.Undef {
|
||||
var claim power.Claim
|
||||
if _, err := adt.AsMap(sm.cs.Store(ctx), ps.Claims).Get(adt.AddrKey(maddr), &claim); err != nil {
|
||||
return big.Zero(), big.Zero(), err
|
||||
}
|
||||
|
||||
return mpow, tpow, nil
|
||||
mpow = claim.Power
|
||||
}
|
||||
|
||||
return mpow, ps.TotalNetworkPower, nil
|
||||
}
|
||||
|
||||
func GetMinerPeerID(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (peer.ID, error) {
|
||||
recp, err := sm.Call(ctx, &types.Message{
|
||||
To: maddr,
|
||||
From: maddr,
|
||||
Method: actors.MAMethods.GetPeerID,
|
||||
}, ts)
|
||||
var mas miner.State
|
||||
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
||||
if err != nil {
|
||||
return "", xerrors.Errorf("call failed: %w", err)
|
||||
return "", xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
||||
}
|
||||
|
||||
if recp.ExitCode != 0 {
|
||||
return "", xerrors.Errorf("getting miner peer ID failed (exit code %d)", recp.ExitCode)
|
||||
}
|
||||
|
||||
return peer.IDFromBytes(recp.Return)
|
||||
return mas.Info.PeerId, nil
|
||||
}
|
||||
|
||||
func GetMinerWorker(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (address.Address, error) {
|
||||
recp, err := sm.Call(ctx, &types.Message{
|
||||
To: maddr,
|
||||
From: maddr,
|
||||
Method: actors.MAMethods.GetWorkerAddr,
|
||||
}, ts)
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("call failed: %w", err)
|
||||
}
|
||||
|
||||
if recp.ExitCode != 0 {
|
||||
return address.Undef, xerrors.Errorf("getting miner peer ID failed (exit code %d)", recp.ExitCode)
|
||||
}
|
||||
|
||||
return address.NewFromBytes(recp.Return)
|
||||
return GetMinerWorkerRaw(ctx, sm, sm.parentState(ts), maddr)
|
||||
}
|
||||
|
||||
func GetMinerElectionPeriodStart(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (uint64, error) {
|
||||
var mas actors.StorageMinerActorState
|
||||
func GetMinerPostState(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*miner.PoStState, error) {
|
||||
var mas miner.State
|
||||
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
||||
if err != nil {
|
||||
return 0, xerrors.Errorf("(get eps) failed to load miner actor state: %w", err)
|
||||
return nil, xerrors.Errorf("(get eps) failed to load miner actor state: %w", err)
|
||||
}
|
||||
|
||||
return mas.ElectionPeriodStart, nil
|
||||
return &mas.PoStState, nil
|
||||
}
|
||||
|
||||
func SectorSetSizes(ctx context.Context, sm *StateManager, maddr address.Address, ts *types.TipSet) (api.MinerSectors, error) {
|
||||
var mas actors.StorageMinerActorState
|
||||
var mas miner.State
|
||||
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
||||
if err != nil {
|
||||
return api.MinerSectors{}, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
||||
@ -189,7 +136,7 @@ func SectorSetSizes(ctx context.Context, sm *StateManager, maddr address.Address
|
||||
}
|
||||
|
||||
func GetMinerProvingSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]*api.ChainSectorInfo, error) {
|
||||
var mas actors.StorageMinerActorState
|
||||
var mas miner.State
|
||||
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("(get pset) failed to load miner actor state: %w", err)
|
||||
@ -199,7 +146,7 @@ func GetMinerProvingSet(ctx context.Context, sm *StateManager, ts *types.TipSet,
|
||||
}
|
||||
|
||||
func GetMinerSectorSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]*api.ChainSectorInfo, error) {
|
||||
var mas actors.StorageMinerActorState
|
||||
var mas miner.State
|
||||
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
||||
@ -216,11 +163,15 @@ func GetSectorsForElectionPost(ctx context.Context, sm *StateManager, ts *types.
|
||||
|
||||
var uselessOtherArray []ffi.PublicSectorInfo
|
||||
for _, s := range sectors {
|
||||
cr, err := commcid.CIDToReplicaCommitmentV1(s.Info.Info.SealedCID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var uselessBuffer [32]byte
|
||||
copy(uselessBuffer[:], s.CommR)
|
||||
copy(uselessBuffer[:], cr)
|
||||
uselessOtherArray = append(uselessOtherArray, ffi.PublicSectorInfo{
|
||||
SectorID: s.SectorID,
|
||||
CommR: uselessBuffer,
|
||||
SectorNum: s.ID,
|
||||
CommR: uselessBuffer,
|
||||
})
|
||||
}
|
||||
|
||||
@ -228,34 +179,23 @@ func GetSectorsForElectionPost(ctx context.Context, sm *StateManager, ts *types.
|
||||
return &ssi, nil
|
||||
}
|
||||
|
||||
func GetMinerSectorSize(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (uint64, error) {
|
||||
var mas actors.StorageMinerActorState
|
||||
func GetMinerSectorSize(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (abi.SectorSize, error) {
|
||||
var mas miner.State
|
||||
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
||||
if err != nil {
|
||||
return 0, xerrors.Errorf("(get ssize) failed to load miner actor state: %w", err)
|
||||
}
|
||||
|
||||
cst := cbor.NewCborStore(sm.cs.Blockstore())
|
||||
var minfo actors.MinerInfo
|
||||
if err := cst.Get(ctx, mas.Info, &minfo); err != nil {
|
||||
return 0, xerrors.Errorf("failed to read miner info: %w", err)
|
||||
}
|
||||
|
||||
return minfo.SectorSize, nil
|
||||
return mas.Info.SectorSize, nil
|
||||
}
|
||||
|
||||
func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (uint64, error) {
|
||||
var mas actors.StorageMinerActorState
|
||||
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
||||
if err != nil {
|
||||
return 0, xerrors.Errorf("(get mslash) failed to load miner actor state: %w", err)
|
||||
}
|
||||
|
||||
return mas.SlashedAt, nil
|
||||
log.Warn("stub GetMinerSlashed")
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func GetMinerFaults(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]uint64, error) {
|
||||
var mas actors.StorageMinerActorState
|
||||
func GetMinerFaults(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]abi.SectorNumber, error) {
|
||||
var mas miner.State
|
||||
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("(get ssize) failed to load miner actor state: %w", err)
|
||||
@ -266,36 +206,62 @@ func GetMinerFaults(ctx context.Context, sm *StateManager, ts *types.TipSet, mad
|
||||
return nil, aerrors.HandleExternalError(lerr, "could not load proving set node")
|
||||
}
|
||||
|
||||
return mas.FaultSet.All(2 * ss.Count)
|
||||
faults, err := mas.FaultSet.All(2 * ss.Count)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("reading fault bit set: %w", err)
|
||||
}
|
||||
|
||||
out := make([]abi.SectorNumber, len(faults))
|
||||
for i, fault := range faults {
|
||||
out[i] = abi.SectorNumber(fault)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func GetStorageDeal(ctx context.Context, sm *StateManager, dealId uint64, ts *types.TipSet) (*actors.OnChainDeal, error) {
|
||||
var state actors.StorageMarketState
|
||||
if _, err := sm.LoadActorState(ctx, actors.StorageMarketAddress, &state, ts); err != nil {
|
||||
func GetStorageDeal(ctx context.Context, sm *StateManager, dealId abi.DealID, ts *types.TipSet) (*api.MarketDeal, error) {
|
||||
var state market.State
|
||||
if _, err := sm.LoadActorState(ctx, builtin.StorageMarketActorAddr, &state, ts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
da, err := amt.LoadAMT(ctx, cbor.NewCborStore(sm.ChainStore().Blockstore()), state.Deals)
|
||||
da, err := amt.LoadAMT(ctx, cbor.NewCborStore(sm.ChainStore().Blockstore()), state.Proposals)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ocd actors.OnChainDeal
|
||||
if err := da.Get(ctx, dealId, &ocd); err != nil {
|
||||
var dp market.DealProposal
|
||||
if err := da.Get(ctx, uint64(dealId), &dp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ocd, nil
|
||||
sa := market.AsDealStateArray(sm.ChainStore().Store(ctx), state.States)
|
||||
st, err := sa.Get(dealId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.MarketDeal{
|
||||
Proposal: dp,
|
||||
State: *st,
|
||||
}, 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 {
|
||||
var state power.State
|
||||
if _, err := sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &state, ts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cst := cbor.NewCborStore(sm.ChainStore().Blockstore())
|
||||
miners, err := actors.MinerSetList(ctx, cst, state.Miners)
|
||||
var miners []address.Address
|
||||
err := adt.AsMap(sm.cs.Store(ctx), state.Claims).ForEach(nil, func(k string) error {
|
||||
a, err := address.NewFromBytes([]byte(k))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
miners = append(miners, a)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -311,14 +277,13 @@ func LoadSectorsFromSet(ctx context.Context, bs blockstore.Blockstore, ssc cid.C
|
||||
|
||||
var sset []*api.ChainSectorInfo
|
||||
if err := a.ForEach(ctx, func(i uint64, v *cbg.Deferred) error {
|
||||
var comms [][]byte
|
||||
if err := cbor.DecodeInto(v.Raw, &comms); err != nil {
|
||||
var oci miner.SectorOnChainInfo
|
||||
if err := cbor.DecodeInto(v.Raw, &oci); err != nil {
|
||||
return err
|
||||
}
|
||||
sset = append(sset, &api.ChainSectorInfo{
|
||||
SectorID: i,
|
||||
CommR: comms[0],
|
||||
CommD: comms[1],
|
||||
Info: oci,
|
||||
ID: abi.SectorNumber(i),
|
||||
})
|
||||
return nil
|
||||
}); err != nil {
|
||||
@ -328,7 +293,7 @@ func LoadSectorsFromSet(ctx context.Context, bs blockstore.Blockstore, ssc cid.C
|
||||
return sset, nil
|
||||
}
|
||||
|
||||
func ComputeState(ctx context.Context, sm *StateManager, height uint64, msgs []*types.Message, ts *types.TipSet) (cid.Cid, error) {
|
||||
func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch, msgs []*types.Message, ts *types.TipSet) (cid.Cid, error) {
|
||||
if ts == nil {
|
||||
ts = sm.cs.GetHeaviestTipSet()
|
||||
}
|
||||
@ -344,7 +309,7 @@ func ComputeState(ctx context.Context, sm *StateManager, height uint64, msgs []*
|
||||
}
|
||||
|
||||
r := store.NewChainRand(sm.cs, ts.Cids(), height)
|
||||
vmi, err := vm.NewVM(fstate, height, r, actors.NetworkAddress, sm.cs.Blockstore(), sm.cs.VMSys())
|
||||
vmi, err := vm.NewVM(fstate, height, r, builtin.SystemActorAddr, sm.cs.Blockstore(), sm.cs.VMSys())
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
@ -3,20 +3,26 @@ package store
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
"github.com/minio/blake2b-simd"
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/runtime"
|
||||
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||
"go.opencensus.io/trace"
|
||||
"go.uber.org/multierr"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
|
||||
amt "github.com/filecoin-project/go-amt-ipld/v2"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
@ -51,7 +57,7 @@ type ChainStore struct {
|
||||
pubLk sync.Mutex
|
||||
|
||||
tstLk sync.Mutex
|
||||
tipsets map[uint64][]cid.Cid
|
||||
tipsets map[abi.ChainEpoch][]cid.Cid
|
||||
|
||||
reorgCh chan<- reorg
|
||||
headChangeNotifs []func(rev, app []*types.TipSet) error
|
||||
@ -59,17 +65,17 @@ type ChainStore struct {
|
||||
mmCache *lru.ARCCache
|
||||
tsCache *lru.ARCCache
|
||||
|
||||
vmcalls *types.VMSyscalls
|
||||
vmcalls runtime.Syscalls
|
||||
}
|
||||
|
||||
func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls *types.VMSyscalls) *ChainStore {
|
||||
func NewChainStore(bs bstore.Blockstore, ds dstore.Batching, vmcalls runtime.Syscalls) *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),
|
||||
tipsets: make(map[abi.ChainEpoch][]cid.Cid),
|
||||
mmCache: c,
|
||||
tsCache: tsc,
|
||||
vmcalls: vmcalls,
|
||||
@ -829,7 +835,35 @@ func (cs *ChainStore) Blockstore() bstore.Blockstore {
|
||||
return cs.bs
|
||||
}
|
||||
|
||||
func (cs *ChainStore) VMSys() *types.VMSyscalls {
|
||||
func ActorStore(ctx context.Context, bs blockstore.Blockstore) adt.Store {
|
||||
return &astore{
|
||||
cst: cbor.NewCborStore(bs),
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
type astore struct {
|
||||
cst cbor.IpldStore
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func (a *astore) Context() context.Context {
|
||||
return a.ctx
|
||||
}
|
||||
|
||||
func (a *astore) Get(ctx context.Context, c cid.Cid, out interface{}) error {
|
||||
return a.cst.Get(ctx, c, out)
|
||||
}
|
||||
|
||||
func (a *astore) Put(ctx context.Context, v interface{}) (cid.Cid, error) {
|
||||
return a.cst.Put(ctx, v)
|
||||
}
|
||||
|
||||
func (cs *ChainStore) Store(ctx context.Context) adt.Store {
|
||||
return ActorStore(ctx, cs.bs)
|
||||
}
|
||||
|
||||
func (cs *ChainStore) VMSys() runtime.Syscalls {
|
||||
return cs.vmcalls
|
||||
}
|
||||
|
||||
@ -855,22 +889,30 @@ func (cs *ChainStore) TryFillTipSet(ts *types.TipSet) (*FullTipSet, error) {
|
||||
return NewFullTipSet(out), nil
|
||||
}
|
||||
|
||||
func drawRandomness(t *types.Ticket, round int64) []byte {
|
||||
h := sha256.New()
|
||||
var buf [8]byte
|
||||
binary.LittleEndian.PutUint64(buf[:], uint64(round))
|
||||
|
||||
func drawRandomness(t *types.Ticket, pers crypto.DomainSeparationTag, round int64, entropy []byte) ([]byte, error) {
|
||||
// TODO: Make this spec compliant
|
||||
h := blake2b.New256()
|
||||
if err := binary.Write(h, binary.BigEndian, int64(pers)); err != nil {
|
||||
return nil, xerrors.Errorf("deriving randomness: %w", err)
|
||||
}
|
||||
h.Write(t.VRFProof)
|
||||
h.Write(buf[:])
|
||||
if err := binary.Write(h, binary.BigEndian, round); err != nil {
|
||||
return nil, xerrors.Errorf("deriving randomness: %w", err)
|
||||
}
|
||||
h.Write(entropy)
|
||||
|
||||
return h.Sum(nil)
|
||||
return h.Sum(nil), nil
|
||||
}
|
||||
|
||||
func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, round int64) ([]byte, error) {
|
||||
func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, pers crypto.DomainSeparationTag, round int64, entropy []byte) (out []byte, err error) {
|
||||
_, span := trace.StartSpan(ctx, "store.GetRandomness")
|
||||
defer span.End()
|
||||
span.AddAttributes(trace.Int64Attribute("round", round))
|
||||
|
||||
defer func() {
|
||||
log.Infof("getRand %v %d %d %x -> %x", blks, pers, round, entropy, out)
|
||||
}()
|
||||
|
||||
for {
|
||||
nts, err := cs.LoadTipSet(types.NewTipSetKey(blks...))
|
||||
if err != nil {
|
||||
@ -880,7 +922,7 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, round i
|
||||
mtb := nts.MinTicketBlock()
|
||||
|
||||
if int64(nts.Height()) <= round {
|
||||
return drawRandomness(nts.MinTicketBlock().Ticket, round), nil
|
||||
return drawRandomness(nts.MinTicketBlock().Ticket, pers, round, entropy)
|
||||
}
|
||||
|
||||
// special case for lookback behind genesis block
|
||||
@ -888,10 +930,13 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, round i
|
||||
if mtb.Height == 0 {
|
||||
|
||||
// round is negative
|
||||
thash := drawRandomness(mtb.Ticket, round*-1)
|
||||
thash, err := drawRandomness(mtb.Ticket, pers, round*-1, entropy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// for negative lookbacks, just use the hash of the positive tickethash value
|
||||
h := sha256.Sum256(thash)
|
||||
h := blake2b.Sum256(thash)
|
||||
return h[:], nil
|
||||
}
|
||||
|
||||
@ -899,7 +944,7 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, round i
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *ChainStore) GetTipsetByHeight(ctx context.Context, h uint64, ts *types.TipSet) (*types.TipSet, error) {
|
||||
func (cs *ChainStore) GetTipsetByHeight(ctx context.Context, h abi.ChainEpoch, ts *types.TipSet) (*types.TipSet, error) {
|
||||
if ts == nil {
|
||||
ts = cs.GetHeaviestTipSet()
|
||||
}
|
||||
@ -1007,10 +1052,10 @@ func (cs *ChainStore) Import(r io.Reader) (*types.TipSet, error) {
|
||||
type chainRand struct {
|
||||
cs *ChainStore
|
||||
blks []cid.Cid
|
||||
bh uint64
|
||||
bh abi.ChainEpoch
|
||||
}
|
||||
|
||||
func NewChainRand(cs *ChainStore, blks []cid.Cid, bheight uint64) vm.Rand {
|
||||
func NewChainRand(cs *ChainStore, blks []cid.Cid, bheight abi.ChainEpoch) vm.Rand {
|
||||
return &chainRand{
|
||||
cs: cs,
|
||||
blks: blks,
|
||||
@ -1018,8 +1063,8 @@ func NewChainRand(cs *ChainStore, blks []cid.Cid, bheight uint64) vm.Rand {
|
||||
}
|
||||
}
|
||||
|
||||
func (cr *chainRand) GetRandomness(ctx context.Context, round int64) ([]byte, error) {
|
||||
return cr.cs.GetRandomness(ctx, cr.blks, round)
|
||||
func (cr *chainRand) GetRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round int64, entropy []byte) ([]byte, error) {
|
||||
return cr.cs.GetRandomness(ctx, cr.blks, pers, round, entropy)
|
||||
}
|
||||
|
||||
func (cs *ChainStore) GetTipSetFromKey(tsk types.TipSetKey) (*types.TipSet, error) {
|
||||
|
@ -9,11 +9,12 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
)
|
||||
|
||||
func init() {
|
||||
build.SectorSizes = []uint64{1024}
|
||||
build.SectorSizes = []abi.SectorSize{1024}
|
||||
build.MinimumMinerPower = 1024
|
||||
}
|
||||
|
||||
|
@ -5,9 +5,13 @@ import (
|
||||
"math/big"
|
||||
|
||||
"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"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
big2 "github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
@ -23,19 +27,27 @@ func (cs *ChainStore) Weight(ctx context.Context, ts *types.TipSet) (types.BigIn
|
||||
|
||||
// >>> wFunction(totalPowerAtTipset(ts)) * 2^8 <<< + (wFunction(totalPowerAtTipset(ts)) * len(ts.blocks) * wRatio_num * 2^8) / (e * wRatio_den)
|
||||
|
||||
ret, err := cs.call(ctx, &types.Message{
|
||||
From: actors.StoragePowerAddress,
|
||||
To: actors.StoragePowerAddress,
|
||||
Method: actors.SPAMethods.GetTotalStorage,
|
||||
}, ts)
|
||||
if err != nil {
|
||||
return types.EmptyInt, xerrors.Errorf("failed to get total power from chain: %w", err)
|
||||
}
|
||||
if ret.ExitCode != 0 {
|
||||
return types.EmptyInt, xerrors.Errorf("failed to get total power from chain (exit code %d)", ret.ExitCode)
|
||||
tpow := big2.Zero()
|
||||
{
|
||||
cst := cbor.NewCborStore(cs.Blockstore())
|
||||
state, err := state.LoadStateTree(cst, ts.ParentState())
|
||||
if err != nil {
|
||||
return types.NewInt(0), xerrors.Errorf("load state tree: %w", err)
|
||||
}
|
||||
|
||||
act, err := state.GetActor(builtin.StoragePowerActorAddr)
|
||||
if err != nil {
|
||||
return types.NewInt(0), xerrors.Errorf("get power actor: %w", err)
|
||||
}
|
||||
|
||||
var st power.State
|
||||
if err := cst.Get(ctx, act.Head, &st); err != nil {
|
||||
return types.NewInt(0), xerrors.Errorf("get power actor head: %w", err)
|
||||
}
|
||||
tpow = st.TotalNetworkPower
|
||||
}
|
||||
|
||||
log2P := int64(0)
|
||||
tpow := types.BigFromBytes(ret.Return)
|
||||
if tpow.GreaterThan(zero) {
|
||||
log2P = int64(tpow.BitLen() - 1)
|
||||
} else {
|
||||
@ -60,7 +72,7 @@ func (cs *ChainStore) call(ctx context.Context, msg *types.Message, ts *types.Ti
|
||||
|
||||
r := NewChainRand(cs, ts.Cids(), ts.Height())
|
||||
|
||||
vmi, err := vm.NewVM(bstate, ts.Height(), r, actors.NetworkAddress, cs.bs, cs.vmcalls)
|
||||
vmi, err := vm.NewVM(bstate, ts.Height(), r, builtin.SystemActorAddr, cs.bs, cs.vmcalls)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to set up vm: %w", err)
|
||||
}
|
||||
|
@ -1,18 +1,20 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Gurpartap/async"
|
||||
bls "github.com/filecoin-project/filecoin-ffi"
|
||||
amt "github.com/filecoin-project/go-amt-ipld/v2"
|
||||
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/ipfs/go-cid"
|
||||
dstore "github.com/ipfs/go-datastore"
|
||||
@ -26,11 +28,12 @@ import (
|
||||
"go.opencensus.io/trace"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
bls "github.com/filecoin-project/filecoin-ffi"
|
||||
|
||||
"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/blocksync"
|
||||
"github.com/filecoin-project/lotus/chain/gen"
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
@ -464,30 +467,21 @@ func (syncer *Syncer) ValidateTipSet(ctx context.Context, fts *store.FullTipSet)
|
||||
}
|
||||
|
||||
func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, baseTs *types.TipSet) error {
|
||||
var err error
|
||||
enc, err := actors.SerializeParams(&actors.IsValidMinerParam{Addr: maddr})
|
||||
var spast power.State
|
||||
|
||||
_, err := syncer.sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &spast, baseTs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ret, err := syncer.sm.Call(ctx, &types.Message{
|
||||
To: actors.StoragePowerAddress,
|
||||
From: maddr,
|
||||
Method: actors.SPAMethods.IsValidMiner,
|
||||
Params: enc,
|
||||
}, baseTs)
|
||||
var claim power.Claim
|
||||
exist, err := adt.AsMap(syncer.store.Store(ctx), spast.Claims).Get(adt.AddrKey(maddr), &claim)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("checking if block miner is valid failed: %w", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if ret.ExitCode != 0 {
|
||||
return xerrors.Errorf("StorageMarket.IsValidMiner check failed (exit code %d)", ret.ExitCode)
|
||||
}
|
||||
|
||||
if !bytes.Equal(ret.Return, cbg.CborBoolTrue) {
|
||||
if !exist {
|
||||
return xerrors.New("miner isn't valid")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -520,9 +514,11 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
||||
log.Warn("Got block from the future, but within threshold", h.Timestamp, time.Now().Unix())
|
||||
}
|
||||
|
||||
if h.Timestamp < baseTs.MinTimestamp()+(build.BlockDelay*(h.Height-baseTs.Height())) {
|
||||
if h.Timestamp < baseTs.MinTimestamp()+(build.BlockDelay*uint64(h.Height-baseTs.Height())) {
|
||||
log.Warn("timestamp funtimes: ", h.Timestamp, baseTs.MinTimestamp(), h.Height, baseTs.Height())
|
||||
return xerrors.Errorf("block was generated too soon (h.ts:%d < base.mints:%d + BLOCK_DELAY:%d * deltaH:%d)", h.Timestamp, baseTs.MinTimestamp(), build.BlockDelay, h.Height-baseTs.Height())
|
||||
diff := (baseTs.MinTimestamp() + (build.BlockDelay * uint64(h.Height-baseTs.Height()))) - h.Timestamp
|
||||
|
||||
return xerrors.Errorf("block was generated too soon (h.ts:%d < base.mints:%d + BLOCK_DELAY:%d * deltaH:%d; diff %d)", h.Timestamp, baseTs.MinTimestamp(), build.BlockDelay, h.Height-baseTs.Height(), diff)
|
||||
}
|
||||
|
||||
winnerCheck := async.Err(func() error {
|
||||
@ -545,7 +541,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
||||
return xerrors.Errorf("failed to get sector size for block miner: %w", err)
|
||||
}
|
||||
|
||||
snum := types.BigDiv(mpow, types.NewInt(ssize))
|
||||
snum := types.BigDiv(mpow, types.NewInt(uint64(ssize)))
|
||||
|
||||
if len(h.EPostProof.Candidates) == 0 {
|
||||
return xerrors.Errorf("no candidates")
|
||||
@ -617,10 +613,12 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
||||
})
|
||||
|
||||
tktsCheck := async.Err(func() error {
|
||||
vrfBase := baseTs.MinTicket().VRFProof
|
||||
|
||||
err := gen.VerifyVRF(ctx, waddr, h.Miner, gen.DSepTicket, vrfBase, h.Ticket.VRFProof)
|
||||
vrfBase, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(), crypto.DomainSeparationTag_TicketProduction, int64(baseTs.Height()), h.Miner.Bytes())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to get randomness for verifying election proof: %w", err)
|
||||
}
|
||||
|
||||
err = gen.VerifyVRF(ctx, waddr, vrfBase, h.Ticket.VRFProof)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("validating block tickets failed: %w", err)
|
||||
}
|
||||
@ -654,12 +652,12 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
||||
}
|
||||
|
||||
func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.BlockHeader, baseTs *types.TipSet, waddr address.Address) error {
|
||||
rand, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(), int64(h.Height-build.EcRandomnessLookback))
|
||||
rand, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(), crypto.DomainSeparationTag_ElectionPoStChallengeSeed, int64(h.Height-build.EcRandomnessLookback), h.Miner.Bytes())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to get randomness for verifying election proof: %w", err)
|
||||
}
|
||||
|
||||
if err := VerifyElectionPoStVRF(ctx, h.EPostProof.PostRand, rand, waddr, h.Miner); err != nil {
|
||||
if err := VerifyElectionPoStVRF(ctx, h.EPostProof.PostRand, rand, waddr); err != nil {
|
||||
return xerrors.Errorf("checking eproof failed: %w", err)
|
||||
}
|
||||
|
||||
@ -674,7 +672,7 @@ func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.Bloc
|
||||
copy(partial[:], t.Partial)
|
||||
winners = append(winners, sectorbuilder.EPostCandidate{
|
||||
PartialTicket: partial,
|
||||
SectorID: t.SectorID,
|
||||
SectorNum: t.SectorID,
|
||||
SectorChallengeIndex: t.ChallengeIndex,
|
||||
})
|
||||
}
|
||||
@ -825,7 +823,7 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
|
||||
return nil
|
||||
}
|
||||
|
||||
func (syncer *Syncer) verifyBlsAggregate(ctx context.Context, sig types.Signature, msgs []cid.Cid, pubks []bls.PublicKey) error {
|
||||
func (syncer *Syncer) verifyBlsAggregate(ctx context.Context, sig crypto.Signature, msgs []cid.Cid, pubks []bls.PublicKey) error {
|
||||
_, span := trace.StartSpan(ctx, "syncer.verifyBlsAggregate")
|
||||
defer span.End()
|
||||
span.AddAttributes(
|
||||
@ -1119,8 +1117,8 @@ func persistMessages(bs bstore.Blockstore, bst *blocksync.BSTipSet) error {
|
||||
}
|
||||
}
|
||||
for _, m := range bst.SecpkMessages {
|
||||
if m.Signature.Type != types.KTSecp256k1 {
|
||||
return xerrors.Errorf("unknown signature type on message %s: %q", m.Cid(), m.Signature.TypeCode)
|
||||
if m.Signature.Type != crypto.SigTypeSecp256k1 {
|
||||
return xerrors.Errorf("unknown signature type on message %s: %q", m.Cid(), m.Signature.Type)
|
||||
}
|
||||
//log.Infof("putting secp256k1 message: %s", m.Cid())
|
||||
if _, err := store.PutMessage(bs, m); err != nil {
|
||||
@ -1178,8 +1176,8 @@ func (syncer *Syncer) collectChain(ctx context.Context, ts *types.TipSet) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func VerifyElectionPoStVRF(ctx context.Context, evrf []byte, rand []byte, worker, miner address.Address) error {
|
||||
if err := gen.VerifyVRF(ctx, worker, miner, gen.DSepElectionPost, rand, evrf); err != nil {
|
||||
func VerifyElectionPoStVRF(ctx context.Context, evrf []byte, rand []byte, worker address.Address) error {
|
||||
if err := gen.VerifyVRF(ctx, worker, rand, evrf); err != nil {
|
||||
return xerrors.Errorf("failed to verify post_randomness vrf: %w", err)
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
mocknet "github.com/libp2p/go-libp2p/p2p/net/mock"
|
||||
@ -27,7 +28,7 @@ import (
|
||||
func init() {
|
||||
build.InsecurePoStValidation = true
|
||||
os.Setenv("TRUST_PARAMS", "1")
|
||||
build.SectorSizes = []uint64{1024}
|
||||
build.SectorSizes = []abi.SectorSize{1024}
|
||||
build.MinimumMinerPower = 1024
|
||||
}
|
||||
|
||||
@ -158,7 +159,6 @@ func (tu *syncTestUtil) pushTsExpectErr(to int, fts *store.FullTipSet, experr bo
|
||||
require.NoError(tu.t, err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (tu *syncTestUtil) mineOnBlock(blk *store.FullTipSet, src int, miners []int, wait, fail bool) *store.FullTipSet {
|
||||
@ -398,7 +398,7 @@ func TestSyncBadTimestamp(t *testing.T) {
|
||||
tu.waitUntilSync(0, client)
|
||||
|
||||
base := tu.g.CurTipset
|
||||
tu.g.Timestamper = func(pts *types.TipSet, tl uint64) uint64 {
|
||||
tu.g.Timestamper = func(pts *types.TipSet, tl abi.ChainEpoch) uint64 {
|
||||
return pts.MinTimestamp() + (build.BlockDelay / 2)
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
@ -31,7 +33,7 @@ type SyncerState struct {
|
||||
Target *types.TipSet
|
||||
Base *types.TipSet
|
||||
Stage api.SyncStateStage
|
||||
Height uint64
|
||||
Height abi.ChainEpoch
|
||||
Message string
|
||||
Start time.Time
|
||||
End time.Time
|
||||
@ -66,7 +68,7 @@ func (ss *SyncerState) Init(base, target *types.TipSet) {
|
||||
ss.End = time.Time{}
|
||||
}
|
||||
|
||||
func (ss *SyncerState) SetHeight(h uint64) {
|
||||
func (ss *SyncerState) SetHeight(h abi.ChainEpoch) {
|
||||
if ss == nil {
|
||||
return
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
||||
)
|
||||
|
||||
var ErrActorNotFound = fmt.Errorf("actor not found")
|
||||
var ErrActorNotFound = init_.ErrAddressNotFound
|
||||
|
||||
type Actor struct {
|
||||
Code cid.Cid
|
||||
|
@ -1,27 +0,0 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cbor.RegisterCborType(SignedStorageAsk{})
|
||||
cbor.RegisterCborType(StorageAsk{})
|
||||
}
|
||||
|
||||
type SignedStorageAsk struct {
|
||||
Ask *StorageAsk
|
||||
Signature *Signature
|
||||
}
|
||||
|
||||
type StorageAsk struct {
|
||||
// Price per GiB / Epoch
|
||||
Price BigInt
|
||||
|
||||
MinPieceSize uint64
|
||||
Miner address.Address
|
||||
Timestamp uint64
|
||||
Expiry uint64
|
||||
SeqNo uint64
|
||||
}
|
@ -1,41 +1,21 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
"github.com/polydawn/refmt/obj/atlas"
|
||||
big2 "github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
)
|
||||
|
||||
const BigIntMaxSerializedLen = 128 // is this big enough? or too big?
|
||||
|
||||
var TotalFilecoinInt = FromFil(build.TotalFilecoin)
|
||||
|
||||
func init() {
|
||||
cbor.RegisterCborType(atlas.BuildEntry(BigInt{}).Transform().
|
||||
TransformMarshal(atlas.MakeMarshalTransformFunc(
|
||||
func(i BigInt) ([]byte, error) {
|
||||
return i.cborBytes(), nil
|
||||
})).
|
||||
TransformUnmarshal(atlas.MakeUnmarshalTransformFunc(
|
||||
func(x []byte) (BigInt, error) {
|
||||
return fromCborBytes(x)
|
||||
})).
|
||||
Complete())
|
||||
}
|
||||
|
||||
var EmptyInt = BigInt{}
|
||||
|
||||
type BigInt struct {
|
||||
*big.Int
|
||||
}
|
||||
type BigInt = big2.Int
|
||||
|
||||
func NewInt(i uint64) BigInt {
|
||||
return BigInt{big.NewInt(0).SetUint64(i)}
|
||||
@ -83,50 +63,9 @@ func BigCmp(a, b BigInt) int {
|
||||
return a.Int.Cmp(b.Int)
|
||||
}
|
||||
|
||||
func (bi BigInt) Nil() bool {
|
||||
return bi.Int == nil
|
||||
}
|
||||
|
||||
// LessThan returns true if bi < o
|
||||
func (bi BigInt) LessThan(o BigInt) bool {
|
||||
return BigCmp(bi, o) < 0
|
||||
}
|
||||
|
||||
// GreaterThan returns true if bi > o
|
||||
func (bi BigInt) GreaterThan(o BigInt) bool {
|
||||
return BigCmp(bi, o) > 0
|
||||
}
|
||||
|
||||
// Equals returns true if bi == o
|
||||
func (bi BigInt) Equals(o BigInt) bool {
|
||||
return BigCmp(bi, o) == 0
|
||||
}
|
||||
|
||||
func (bi *BigInt) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(bi.String())
|
||||
}
|
||||
|
||||
func (bi *BigInt) UnmarshalJSON(b []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(b, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
i, ok := big.NewInt(0).SetString(s, 10)
|
||||
if !ok {
|
||||
if string(s) == "<nil>" {
|
||||
return nil
|
||||
}
|
||||
return xerrors.Errorf("failed to parse bigint string: '%s'", string(b))
|
||||
}
|
||||
|
||||
bi.Int = i
|
||||
return nil
|
||||
}
|
||||
|
||||
var sizeUnits = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB"}
|
||||
|
||||
func (bi BigInt) SizeStr() string {
|
||||
func SizeStr(bi BigInt) string {
|
||||
r := new(big.Rat).SetInt(bi.Int)
|
||||
den := big.NewRat(1, 1024)
|
||||
|
||||
@ -139,121 +78,3 @@ func (bi BigInt) SizeStr() string {
|
||||
f, _ := r.Float64()
|
||||
return fmt.Sprintf("%.3g %s", f, sizeUnits[i])
|
||||
}
|
||||
|
||||
func (bi *BigInt) Scan(value interface{}) error {
|
||||
switch value := value.(type) {
|
||||
case string:
|
||||
i, ok := big.NewInt(0).SetString(value, 10)
|
||||
if !ok {
|
||||
if value == "<nil>" {
|
||||
return nil
|
||||
}
|
||||
return xerrors.Errorf("failed to parse bigint string: '%s'", value)
|
||||
}
|
||||
|
||||
bi.Int = i
|
||||
|
||||
return nil
|
||||
case int64:
|
||||
bi.Int = big.NewInt(value)
|
||||
return nil
|
||||
default:
|
||||
return xerrors.Errorf("non-string types unsupported: %T", value)
|
||||
}
|
||||
}
|
||||
|
||||
func (bi *BigInt) cborBytes() []byte {
|
||||
if bi.Int == nil {
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
switch {
|
||||
case bi.Sign() > 0:
|
||||
return append([]byte{0}, bi.Bytes()...)
|
||||
case bi.Sign() < 0:
|
||||
return append([]byte{1}, bi.Bytes()...)
|
||||
default: // bi.Sign() == 0:
|
||||
return []byte{}
|
||||
}
|
||||
}
|
||||
|
||||
func fromCborBytes(buf []byte) (BigInt, error) {
|
||||
if len(buf) == 0 {
|
||||
return NewInt(0), nil
|
||||
}
|
||||
|
||||
var negative bool
|
||||
switch buf[0] {
|
||||
case 0:
|
||||
negative = false
|
||||
case 1:
|
||||
negative = true
|
||||
default:
|
||||
return EmptyInt, fmt.Errorf("big int prefix should be either 0 or 1, got %d", buf[0])
|
||||
}
|
||||
|
||||
i := big.NewInt(0).SetBytes(buf[1:])
|
||||
if negative {
|
||||
i.Neg(i)
|
||||
}
|
||||
|
||||
return BigInt{i}, nil
|
||||
}
|
||||
|
||||
func (bi *BigInt) MarshalCBOR(w io.Writer) error {
|
||||
if bi.Int == nil {
|
||||
zero := NewInt(0)
|
||||
return zero.MarshalCBOR(w)
|
||||
}
|
||||
|
||||
enc := bi.cborBytes()
|
||||
|
||||
header := cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(enc)))
|
||||
if _, err := w.Write(header); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := w.Write(enc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bi *BigInt) UnmarshalCBOR(br io.Reader) error {
|
||||
maj, extra, err := cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if maj != cbg.MajByteString {
|
||||
return fmt.Errorf("cbor input for fil big int was not a byte string (%x)", maj)
|
||||
}
|
||||
|
||||
if extra == 0 {
|
||||
bi.Int = big.NewInt(0)
|
||||
return nil
|
||||
}
|
||||
|
||||
if extra > BigIntMaxSerializedLen {
|
||||
return fmt.Errorf("big integer byte array too long")
|
||||
}
|
||||
|
||||
buf := make([]byte, extra)
|
||||
if _, err := io.ReadFull(br, buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
i, err := fromCborBytes(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*bi = i
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bi *BigInt) IsZero() bool {
|
||||
return bi.Int.Sign() == 0
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ func TestSizeStr(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
assert.Equal(t, c.out, NewInt(c.in).SizeStr(), "input %+v, produced wrong result", c)
|
||||
assert.Equal(t, c.out, SizeStr(NewInt(c.in)), "input %+v, produced wrong result", c)
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,6 +75,6 @@ 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)
|
||||
assert.Equal(t, "5e+04 ZiB", SizeStr(BigInt{Int: ZiB}), "inout %+v, produced wrong result", ZiB)
|
||||
|
||||
}
|
||||
|
@ -1,226 +0,0 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
rlepluslazy "github.com/filecoin-project/lotus/lib/rlepluslazy"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
var ErrBitFieldTooMany = errors.New("to many items in RLE")
|
||||
|
||||
type BitField struct {
|
||||
rle rlepluslazy.RLE
|
||||
|
||||
bits map[uint64]struct{}
|
||||
}
|
||||
|
||||
func NewBitField() BitField {
|
||||
bf, err := NewBitFieldFromBytes([]byte{})
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("creating empty rle: %+v", err))
|
||||
}
|
||||
return bf
|
||||
}
|
||||
|
||||
func NewBitFieldFromBytes(rle []byte) (BitField, error) {
|
||||
bf := BitField{}
|
||||
rlep, err := rlepluslazy.FromBuf(rle)
|
||||
if err != nil {
|
||||
return BitField{}, xerrors.Errorf("could not decode rle+: %w", err)
|
||||
}
|
||||
bf.rle = rlep
|
||||
bf.bits = make(map[uint64]struct{})
|
||||
return bf, nil
|
||||
|
||||
}
|
||||
|
||||
func BitFieldFromSet(setBits []uint64) BitField {
|
||||
res := BitField{bits: make(map[uint64]struct{})}
|
||||
for _, b := range setBits {
|
||||
res.bits[b] = struct{}{}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func MergeBitFields(a, b BitField) (BitField, error) {
|
||||
ra, err := a.rle.RunIterator()
|
||||
if err != nil {
|
||||
return BitField{}, err
|
||||
}
|
||||
|
||||
rb, err := b.rle.RunIterator()
|
||||
if err != nil {
|
||||
return BitField{}, err
|
||||
}
|
||||
|
||||
merge, err := rlepluslazy.Sum(ra, rb)
|
||||
if err != nil {
|
||||
return BitField{}, err
|
||||
}
|
||||
|
||||
mergebytes, err := rlepluslazy.EncodeRuns(merge, nil)
|
||||
if err != nil {
|
||||
return BitField{}, err
|
||||
}
|
||||
|
||||
rle, err := rlepluslazy.FromBuf(mergebytes)
|
||||
if err != nil {
|
||||
return BitField{}, err
|
||||
}
|
||||
|
||||
return BitField{
|
||||
rle: rle,
|
||||
bits: make(map[uint64]struct{}),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (bf BitField) sum() (rlepluslazy.RunIterator, error) {
|
||||
if len(bf.bits) == 0 {
|
||||
return bf.rle.RunIterator()
|
||||
}
|
||||
|
||||
a, err := bf.rle.RunIterator()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
slc := make([]uint64, 0, len(bf.bits))
|
||||
for b := range bf.bits {
|
||||
slc = append(slc, b)
|
||||
}
|
||||
|
||||
b, err := rlepluslazy.RunsFromSlice(slc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := rlepluslazy.Sum(a, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Set ...s bit in the BitField
|
||||
func (bf BitField) Set(bit uint64) {
|
||||
bf.bits[bit] = struct{}{}
|
||||
}
|
||||
|
||||
func (bf BitField) Count() (uint64, error) {
|
||||
s, err := bf.sum()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return rlepluslazy.Count(s)
|
||||
}
|
||||
|
||||
// All returns all set bits
|
||||
func (bf BitField) All(max uint64) ([]uint64, error) {
|
||||
c, err := bf.Count()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("count errror: %w", err)
|
||||
}
|
||||
if c > max {
|
||||
return nil, xerrors.Errorf("expected %d, got %d: %w", max, c, ErrBitFieldTooMany)
|
||||
}
|
||||
|
||||
runs, err := bf.sum()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := rlepluslazy.SliceFromRuns(runs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (bf BitField) AllMap(max uint64) (map[uint64]bool, error) {
|
||||
c, err := bf.Count()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("count errror: %w", err)
|
||||
}
|
||||
if c > max {
|
||||
return nil, xerrors.Errorf("expected %d, got %d: %w", max, c, ErrBitFieldTooMany)
|
||||
}
|
||||
|
||||
runs, err := bf.sum()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := rlepluslazy.SliceFromRuns(runs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := make(map[uint64]bool)
|
||||
for _, i := range res {
|
||||
out[i] = true
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (bf BitField) MarshalCBOR(w io.Writer) error {
|
||||
ints := make([]uint64, 0, len(bf.bits))
|
||||
for i := range bf.bits {
|
||||
ints = append(ints, i)
|
||||
}
|
||||
|
||||
s, err := bf.sum()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rle, err := rlepluslazy.EncodeRuns(s, []byte{})
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
if _, err = w.Write(rle); err != nil {
|
||||
return xerrors.Errorf("writing rle: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bf *BitField) UnmarshalCBOR(r io.Reader) error {
|
||||
br := cbg.GetPeeker(r)
|
||||
|
||||
maj, extra, err := cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if extra > 8192 {
|
||||
return fmt.Errorf("array too large")
|
||||
}
|
||||
|
||||
if maj != cbg.MajByteString {
|
||||
return fmt.Errorf("expected byte array")
|
||||
}
|
||||
|
||||
buf := make([]byte, extra)
|
||||
if _, err := io.ReadFull(br, buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rle, err := rlepluslazy.FromBuf(buf)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("could not decode rle+: %w", err)
|
||||
}
|
||||
bf.rle = rle
|
||||
bf.bits = make(map[uint64]struct{})
|
||||
|
||||
return nil
|
||||
}
|
@ -4,6 +4,9 @@ import (
|
||||
"bytes"
|
||||
"math/big"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
|
||||
block "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/minio/sha256-simd"
|
||||
@ -21,7 +24,7 @@ type Ticket struct {
|
||||
|
||||
type EPostTicket struct {
|
||||
Partial []byte
|
||||
SectorID uint64
|
||||
SectorID abi.SectorNumber
|
||||
ChallengeIndex uint64
|
||||
}
|
||||
|
||||
@ -42,7 +45,7 @@ type BlockHeader struct {
|
||||
|
||||
ParentWeight BigInt // 4
|
||||
|
||||
Height uint64 // 5
|
||||
Height abi.ChainEpoch // 5
|
||||
|
||||
ParentStateRoot cid.Cid // 6
|
||||
|
||||
@ -50,11 +53,11 @@ type BlockHeader struct {
|
||||
|
||||
Messages cid.Cid // 8
|
||||
|
||||
BLSAggregate Signature // 9
|
||||
BLSAggregate crypto.Signature // 9
|
||||
|
||||
Timestamp uint64 // 10
|
||||
|
||||
BlockSig *Signature // 11
|
||||
BlockSig *crypto.Signature // 11
|
||||
|
||||
ForkSignaling uint64 // 12
|
||||
}
|
||||
@ -163,8 +166,8 @@ var blocksPerEpoch = NewInt(build.BlocksPerEpoch)
|
||||
|
||||
const sha256bits = 256
|
||||
|
||||
func IsTicketWinner(partialTicket []byte, ssizeI uint64, snum uint64, totpow BigInt) bool {
|
||||
ssize := NewInt(ssizeI)
|
||||
func IsTicketWinner(partialTicket []byte, ssizeI abi.SectorSize, snum uint64, totpow BigInt) bool {
|
||||
ssize := NewInt(uint64(ssizeI))
|
||||
ssampled := ElectionPostChallengeCount(snum, 0) // TODO: faults in epost?
|
||||
/*
|
||||
Need to check that
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
cid "github.com/ipfs/go-cid"
|
||||
)
|
||||
|
||||
@ -34,12 +35,12 @@ func testBlockHeader(t testing.TB) *BlockHeader {
|
||||
},
|
||||
Parents: []cid.Cid{c, c},
|
||||
ParentMessageReceipts: c,
|
||||
BLSAggregate: Signature{Type: KTBLS, Data: []byte("boo! im a signature")},
|
||||
BLSAggregate: crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("boo! im a signature")},
|
||||
ParentWeight: NewInt(123125126212),
|
||||
Messages: c,
|
||||
Height: 85919298723,
|
||||
ParentStateRoot: c,
|
||||
BlockSig: &Signature{Type: KTBLS, Data: []byte("boo! im a signature")},
|
||||
BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("boo! im a signature")},
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
block "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/multiformats/go-multihash"
|
||||
@ -22,10 +23,26 @@ type Message struct {
|
||||
GasPrice BigInt
|
||||
GasLimit BigInt
|
||||
|
||||
Method uint64 // TODO: decide
|
||||
Method abi.MethodNum
|
||||
Params []byte
|
||||
}
|
||||
|
||||
func (t *Message) BlockMiner() address.Address {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (t *Message) Caller() address.Address {
|
||||
return t.From
|
||||
}
|
||||
|
||||
func (t *Message) Receiver() address.Address {
|
||||
return t.To
|
||||
}
|
||||
|
||||
func (t *Message) ValueReceived() abi.TokenAmount {
|
||||
return t.Value
|
||||
}
|
||||
|
||||
func DecodeMessage(b []byte) (*Message, error) {
|
||||
var msg Message
|
||||
if err := msg.UnmarshalCBOR(bytes.NewReader(b)); err != nil {
|
||||
|
@ -5,9 +5,12 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
"github.com/ipfs/go-cid"
|
||||
)
|
||||
|
||||
func Address(i uint64) address.Address {
|
||||
@ -47,7 +50,7 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types
|
||||
}
|
||||
|
||||
var pcids []cid.Cid
|
||||
var height uint64
|
||||
var height abi.ChainEpoch
|
||||
weight := types.NewInt(weightInc)
|
||||
if parents != nil {
|
||||
pcids = parents.Cids()
|
||||
@ -65,12 +68,12 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types
|
||||
},
|
||||
Parents: pcids,
|
||||
ParentMessageReceipts: c,
|
||||
BLSAggregate: types.Signature{Type: types.KTBLS, Data: []byte("boo! im a signature")},
|
||||
BLSAggregate: crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("boo! im a signature")},
|
||||
ParentWeight: weight,
|
||||
Messages: c,
|
||||
Height: height,
|
||||
ParentStateRoot: c,
|
||||
BlockSig: &types.Signature{Type: types.KTBLS, Data: []byte("boo! im a signature")},
|
||||
BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("boo! im a signature")},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,123 +0,0 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
)
|
||||
|
||||
const SignatureMaxLength = 200
|
||||
|
||||
const (
|
||||
KTSecp256k1 = "secp256k1"
|
||||
KTBLS = "bls"
|
||||
)
|
||||
|
||||
const (
|
||||
IKTUnknown = -1
|
||||
|
||||
IKTSecp256k1 = iota
|
||||
IKTBLS
|
||||
)
|
||||
|
||||
type Signature struct {
|
||||
Type string
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func SignatureFromBytes(x []byte) (Signature, error) {
|
||||
val, nr := binary.Uvarint(x)
|
||||
if nr != 1 {
|
||||
return Signature{}, fmt.Errorf("signatures with type field longer than one byte are invalid")
|
||||
}
|
||||
var ts string
|
||||
switch val {
|
||||
case IKTSecp256k1:
|
||||
ts = KTSecp256k1
|
||||
case IKTBLS:
|
||||
ts = KTBLS
|
||||
default:
|
||||
return Signature{}, fmt.Errorf("unsupported signature type: %d", val)
|
||||
}
|
||||
|
||||
return Signature{
|
||||
Type: ts,
|
||||
Data: x[1:],
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Signature) TypeCode() int {
|
||||
switch s.Type {
|
||||
case KTSecp256k1:
|
||||
return IKTSecp256k1
|
||||
case KTBLS:
|
||||
return IKTBLS
|
||||
default:
|
||||
return IKTUnknown
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Signature) MarshalCBOR(w io.Writer) error {
|
||||
if s == nil {
|
||||
_, err := w.Write(cbg.CborNull)
|
||||
return err
|
||||
}
|
||||
|
||||
header := cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(s.Data)+1))
|
||||
|
||||
if _, err := w.Write(header); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := w.Write([]byte{byte(s.TypeCode())}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := w.Write(s.Data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Signature) UnmarshalCBOR(br io.Reader) error {
|
||||
maj, l, err := cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if maj != cbg.MajByteString {
|
||||
return fmt.Errorf("cbor input for signature was not a byte string")
|
||||
}
|
||||
|
||||
if l > SignatureMaxLength {
|
||||
return fmt.Errorf("cbor byte array for signature was too long")
|
||||
}
|
||||
|
||||
buf := make([]byte, l)
|
||||
if _, err := io.ReadFull(br, buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch buf[0] {
|
||||
default:
|
||||
return fmt.Errorf("invalid signature type in cbor input: %d", buf[0])
|
||||
case IKTSecp256k1:
|
||||
s.Type = KTSecp256k1
|
||||
case IKTBLS:
|
||||
s.Type = KTBLS
|
||||
}
|
||||
s.Data = buf[1:]
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Signature) Equals(o *Signature) bool {
|
||||
if s == nil || o == nil {
|
||||
return s == o
|
||||
}
|
||||
return s.Type == o.Type && bytes.Equal(s.Data, o.Data)
|
||||
}
|
@ -3,12 +3,14 @@ package types
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
)
|
||||
|
||||
func TestSignatureSerializeRoundTrip(t *testing.T) {
|
||||
s := &Signature{
|
||||
s := &crypto.Signature{
|
||||
Data: []byte("foo bar cat dog"),
|
||||
Type: KTBLS,
|
||||
Type: crypto.SigTypeBLS,
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
@ -16,7 +18,7 @@ func TestSignatureSerializeRoundTrip(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var outs Signature
|
||||
var outs crypto.Signature
|
||||
if err := outs.UnmarshalCBOR(buf); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -3,13 +3,14 @@ package types
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
block "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/multiformats/go-multihash"
|
||||
)
|
||||
|
||||
func (m *SignedMessage) ToStorageBlock() (block.Block, error) {
|
||||
if m.Signature.Type == KTBLS {
|
||||
if m.Signature.Type == crypto.SigTypeBLS {
|
||||
return m.Message.ToStorageBlock()
|
||||
}
|
||||
|
||||
@ -28,7 +29,7 @@ func (m *SignedMessage) ToStorageBlock() (block.Block, error) {
|
||||
}
|
||||
|
||||
func (m *SignedMessage) Cid() cid.Cid {
|
||||
if m.Signature.Type == KTBLS {
|
||||
if m.Signature.Type == crypto.SigTypeBLS {
|
||||
return m.Message.Cid()
|
||||
}
|
||||
|
||||
@ -42,7 +43,7 @@ func (m *SignedMessage) Cid() cid.Cid {
|
||||
|
||||
type SignedMessage struct {
|
||||
Message Message
|
||||
Signature Signature
|
||||
Signature crypto.Signature
|
||||
}
|
||||
|
||||
func DecodeSignedMessage(data []byte) (*SignedMessage, error) {
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"io"
|
||||
"sort"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/ipfs/go-cid"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
@ -18,7 +19,7 @@ var log = logging.Logger("types")
|
||||
type TipSet struct {
|
||||
cids []cid.Cid
|
||||
blks []*BlockHeader
|
||||
height uint64
|
||||
height abi.ChainEpoch
|
||||
}
|
||||
|
||||
// why didnt i just export the fields? Because the struct has methods with the
|
||||
@ -26,7 +27,7 @@ type TipSet struct {
|
||||
type ExpTipSet struct {
|
||||
Cids []cid.Cid
|
||||
Blocks []*BlockHeader
|
||||
Height uint64
|
||||
Height abi.ChainEpoch
|
||||
}
|
||||
|
||||
func (ts *TipSet) MarshalJSON() ([]byte, error) {
|
||||
@ -135,7 +136,7 @@ func (ts *TipSet) Key() TipSetKey {
|
||||
return NewTipSetKey(ts.cids...)
|
||||
}
|
||||
|
||||
func (ts *TipSet) Height() uint64 {
|
||||
func (ts *TipSet) Height() abi.ChainEpoch {
|
||||
return ts.height
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,10 @@ package types
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
"github.com/filecoin-project/specs-actors/actors/runtime"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||
|
||||
@ -31,46 +35,22 @@ type VMContext interface {
|
||||
Message() *Message
|
||||
Origin() address.Address
|
||||
Ipld() cbor.IpldStore
|
||||
Send(to address.Address, method uint64, value BigInt, params []byte) ([]byte, aerrors.ActorError)
|
||||
BlockHeight() uint64
|
||||
Send(to address.Address, method abi.MethodNum, value BigInt, params []byte) ([]byte, aerrors.ActorError)
|
||||
BlockHeight() abi.ChainEpoch
|
||||
GasUsed() BigInt
|
||||
Storage() Storage
|
||||
StateTree() (StateTree, aerrors.ActorError)
|
||||
VerifySignature(sig *Signature, from address.Address, data []byte) aerrors.ActorError
|
||||
ActorCodeCID(address.Address) (cid.Cid, error)
|
||||
LookupID(address.Address) (address.Address, error)
|
||||
VerifySignature(sig *crypto.Signature, from address.Address, data []byte) aerrors.ActorError
|
||||
ChargeGas(uint64) aerrors.ActorError
|
||||
GetRandomness(height uint64) ([]byte, aerrors.ActorError)
|
||||
GetRandomness(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) ([]byte, aerrors.ActorError)
|
||||
GetBalance(address.Address) (BigInt, aerrors.ActorError)
|
||||
Sys() *VMSyscalls
|
||||
Sys() runtime.Syscalls
|
||||
|
||||
Context() context.Context
|
||||
}
|
||||
|
||||
const CommitmentBytesLen = 32
|
||||
|
||||
type PublicSectorInfo struct {
|
||||
SectorID uint64
|
||||
CommR [CommitmentBytesLen]byte
|
||||
}
|
||||
|
||||
type Candidate struct {
|
||||
SectorID uint64
|
||||
PartialTicket [32]byte
|
||||
Ticket [32]byte
|
||||
SectorChallengeIndex uint64
|
||||
}
|
||||
|
||||
type VMSyscalls struct {
|
||||
ValidatePoRep func(context.Context, address.Address, uint64, []byte, []byte, []byte, []byte, []byte, uint64) (bool, aerrors.ActorError)
|
||||
VerifyFallbackPost func(ctx context.Context,
|
||||
sectorSize uint64,
|
||||
sectorInfo []PublicSectorInfo,
|
||||
challengeSeed []byte,
|
||||
proof []byte,
|
||||
candidates []Candidate,
|
||||
proverID address.Address,
|
||||
faults uint64) (bool, error)
|
||||
}
|
||||
|
||||
type storageWrapper struct {
|
||||
s Storage
|
||||
}
|
||||
|
@ -1,88 +1,22 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
import(
|
||||
"encoding/base64"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
cborrpc "github.com/filecoin-project/go-cbor-util"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
)
|
||||
|
||||
type SignedVoucher struct {
|
||||
TimeLock uint64
|
||||
SecretPreimage []byte
|
||||
Extra *ModVerifyParams
|
||||
Lane uint64
|
||||
Nonce uint64
|
||||
Amount BigInt
|
||||
MinCloseHeight uint64
|
||||
|
||||
Merges []Merge
|
||||
|
||||
Signature *Signature
|
||||
}
|
||||
|
||||
func (sv *SignedVoucher) SigningBytes() ([]byte, error) {
|
||||
osv := *sv
|
||||
osv.Signature = nil
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
if err := osv.MarshalCBOR(buf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func (sv *SignedVoucher) EncodedString() (string, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := sv.MarshalCBOR(buf); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return base64.RawURLEncoding.EncodeToString(buf.Bytes()), nil
|
||||
}
|
||||
|
||||
func (sv *SignedVoucher) Equals(other *SignedVoucher) bool {
|
||||
// TODO: make this less bad
|
||||
|
||||
selfB, err := cborrpc.Dump(sv)
|
||||
if err != nil {
|
||||
log.Errorf("SignedVoucher.Equals: dump self: %s", err)
|
||||
return false
|
||||
}
|
||||
|
||||
otherB, err := cborrpc.Dump(other)
|
||||
if err != nil {
|
||||
log.Errorf("SignedVoucher.Equals: dump other: %s", err)
|
||||
return false
|
||||
}
|
||||
|
||||
return bytes.Equal(selfB, otherB)
|
||||
}
|
||||
|
||||
func DecodeSignedVoucher(s string) (*SignedVoucher, error) {
|
||||
func DecodeSignedVoucher(s string) (*paych.SignedVoucher, error) {
|
||||
data, err := base64.RawURLEncoding.DecodeString(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var sv SignedVoucher
|
||||
var sv paych.SignedVoucher
|
||||
if err := cbor.DecodeInto(data, &sv); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &sv, nil
|
||||
}
|
||||
|
||||
type Merge struct {
|
||||
Lane uint64
|
||||
Nonce uint64
|
||||
}
|
||||
|
||||
type ModVerifyParams struct {
|
||||
Actor address.Address
|
||||
Method uint64
|
||||
Data []byte
|
||||
}
|
||||
|
@ -2,6 +2,9 @@ package validation
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
|
||||
"github.com/filecoin-project/go-sectorbuilder"
|
||||
|
||||
vchain "github.com/filecoin-project/chain-validation/pkg/chain"
|
||||
@ -33,7 +36,7 @@ func (a *Applier) ApplyMessage(eCtx *vchain.ExecutionContext, state vstate.Wrapp
|
||||
if err != nil {
|
||||
return vchain.MessageReceipt{}, err
|
||||
}
|
||||
lotusVM, err := vm.NewVM(base, eCtx.Epoch, randSrc, minerAddr, st.bs, vm.Syscalls(sectorbuilder.ProofVerifier))
|
||||
lotusVM, err := vm.NewVM(base, abi.ChainEpoch(eCtx.Epoch), randSrc, minerAddr, st.bs, vm.Syscalls(sectorbuilder.ProofVerifier))
|
||||
if err != nil {
|
||||
return vchain.MessageReceipt{}, err
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package validation
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
@ -10,15 +11,16 @@ 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/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
type Signer interface {
|
||||
Sign(ctx context.Context, addr vaddress.Address, msg []byte) (*types.Signature, error)
|
||||
Sign(ctx context.Context, addr vaddress.Address, msg []byte) (*crypto.Signature, error)
|
||||
}
|
||||
|
||||
type MessageFactory struct {
|
||||
@ -53,7 +55,7 @@ func (mf *MessageFactory) MakeMessage(from, to vaddress.Address, method vchain.M
|
||||
valueDec,
|
||||
types.BigInt{gasPrice.Int},
|
||||
types.NewInt(uint64(gasLimit)),
|
||||
methodId,
|
||||
abi.MethodNum(methodId),
|
||||
params,
|
||||
}
|
||||
|
||||
@ -72,18 +74,17 @@ func (mf *MessageFactory) FromActorCodeCid(code vactors.ActorCodeID) cid.Cid {
|
||||
// This will change to a mapping to method ids when method dispatch is updated to use integers.
|
||||
var methods = []uint64{
|
||||
vchain.NoMethod: 0,
|
||||
vchain.InitExec: actors.IAMethods.Exec,
|
||||
vchain.InitExec: uint64(builtin.MethodsInit.Exec),
|
||||
|
||||
vchain.StoragePowerConstructor: actors.SPAMethods.Constructor,
|
||||
vchain.StoragePowerCreateStorageMiner: actors.SPAMethods.CreateStorageMiner,
|
||||
vchain.StoragePowerUpdatePower: actors.SPAMethods.UpdateStorage,
|
||||
vchain.StoragePowerConstructor: uint64(builtin.MethodsPower.Constructor),
|
||||
vchain.StoragePowerCreateStorageMiner: uint64(builtin.MethodsPower.CreateMiner),
|
||||
|
||||
vchain.StorageMinerUpdatePeerID: actors.MAMethods.UpdatePeerID,
|
||||
vchain.StorageMinerGetOwner: actors.MAMethods.GetOwner,
|
||||
vchain.StorageMinerGetPower: actors.MAMethods.GetPower,
|
||||
vchain.StorageMinerGetWorkerAddr: actors.MAMethods.GetWorkerAddr,
|
||||
vchain.StorageMinerGetPeerID: actors.MAMethods.GetPeerID,
|
||||
vchain.StorageMinerGetSectorSize: actors.MAMethods.GetSectorSize,
|
||||
vchain.StorageMinerUpdatePeerID: 0, //actors.MAMethods.UpdatePeerID,
|
||||
vchain.StorageMinerGetOwner: 0, //actors.MAMethods.GetOwner,
|
||||
vchain.StorageMinerGetPower: 0, //actors.MAMethods.GetPower,
|
||||
vchain.StorageMinerGetWorkerAddr: 0, //actors.MAMethods.GetWorkerAddr,
|
||||
vchain.StorageMinerGetPeerID: 0, //actors.MAMethods.GetPeerID,
|
||||
vchain.StorageMinerGetSectorSize: 0, //actors.MAMethods.GetSectorSize,
|
||||
|
||||
vchain.MultiSigConstructor: uint64(builtin.MethodsMultisig.Constructor),
|
||||
vchain.MultiSigPropose: uint64(builtin.MethodsMultisig.Propose),
|
||||
|
@ -20,8 +20,9 @@ import (
|
||||
|
||||
"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/gen"
|
||||
"github.com/filecoin-project/lotus/chain/gen/genesis"
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
@ -132,7 +133,7 @@ func (s *StateWrapper) SetSingletonActor(addr vactors.SingletonActorID, balance
|
||||
|
||||
switch lotusAddr {
|
||||
case actors.InitAddress:
|
||||
initact, err := gen.SetupInitActor(s.bs, nil)
|
||||
initact, err := genesis.SetupInitActor(s.bs, "testing", nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -142,7 +143,7 @@ func (s *StateWrapper) SetSingletonActor(addr vactors.SingletonActorID, balance
|
||||
|
||||
return &actorWrapper{*initact}, s.storage, s.flush(tree)
|
||||
case actors.StorageMarketAddress:
|
||||
nsroot, err := gen.SetupStorageMarketActor(s.bs, s.stateRoot, nil)
|
||||
nsroot, err := genesis.SetupStorageMarketActor(s.bs)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -158,7 +159,7 @@ func (s *StateWrapper) SetSingletonActor(addr vactors.SingletonActorID, balance
|
||||
}
|
||||
return &actorWrapper{*smact}, s.storage, s.flush(tree)
|
||||
case actors.StoragePowerAddress:
|
||||
spact, err := gen.SetupStoragePowerActor(s.bs)
|
||||
spact, err := genesis.SetupStoragePowerActor(s.bs)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -11,11 +11,21 @@ import (
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/cron"
|
||||
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/multisig"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/system"
|
||||
vmr "github.com/filecoin-project/specs-actors/actors/runtime"
|
||||
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/multisig"
|
||||
vmr "github.com/filecoin-project/specs-actors/actors/runtime"
|
||||
)
|
||||
|
||||
type invoker struct {
|
||||
@ -33,20 +43,21 @@ func NewInvoker() *invoker {
|
||||
}
|
||||
|
||||
// add builtInCode using: register(cid, singleton)
|
||||
inv.Register(actors.InitCodeCid, actors.InitActor{}, actors.InitActorState{})
|
||||
inv.Register(actors.CronCodeCid, actors.CronActor{}, actors.CronActorState{})
|
||||
inv.Register(actors.StoragePowerCodeCid, actors.StoragePowerActor{}, actors.StoragePowerState{})
|
||||
inv.Register(actors.StorageMarketCodeCid, actors.StorageMarketActor{}, actors.StorageMarketState{})
|
||||
inv.Register(actors.StorageMinerCodeCid, actors.StorageMinerActor{}, actors.StorageMinerActorState{})
|
||||
inv.Register(actors.MultisigCodeCid, multisig.MultiSigActor{}, multisig.MultiSigActorState{})
|
||||
inv.Register(actors.PaymentChannelCodeCid, actors.PaymentChannelActor{}, actors.PaymentChannelActorState{})
|
||||
inv.Register(builtin.SystemActorCodeID, system.Actor{}, adt.EmptyValue{})
|
||||
inv.Register(builtin.InitActorCodeID, init_.Actor{}, init_.State{})
|
||||
inv.Register(builtin.CronActorCodeID, cron.Actor{}, cron.State{})
|
||||
inv.Register(builtin.StoragePowerActorCodeID, power.Actor{}, power.State{})
|
||||
inv.Register(builtin.StorageMarketActorCodeID, market.Actor{}, market.State{})
|
||||
inv.Register(builtin.StorageMinerActorCodeID, miner.Actor{}, miner.State{})
|
||||
inv.Register(builtin.MultisigActorCodeID, multisig.Actor{}, multisig.State{})
|
||||
inv.Register(builtin.PaymentChannelActorCodeID, paych.Actor{}, paych.State{})
|
||||
|
||||
return inv
|
||||
}
|
||||
|
||||
func (inv *invoker) Invoke(act *types.Actor, vmctx types.VMContext, method uint64, params []byte) ([]byte, aerrors.ActorError) {
|
||||
func (inv *invoker) Invoke(act *types.Actor, vmctx types.VMContext, method abi.MethodNum, params []byte) ([]byte, aerrors.ActorError) {
|
||||
|
||||
if act.Code == actors.AccountCodeCid {
|
||||
if act.Code == builtin.AccountActorCodeID {
|
||||
return nil, aerrors.Newf(254, "cannot invoke methods on account actors")
|
||||
}
|
||||
|
||||
@ -55,7 +66,7 @@ func (inv *invoker) Invoke(act *types.Actor, vmctx types.VMContext, method uint6
|
||||
log.Errorf("no code for actor %s (Addr: %s)", act.Code, vmctx.Message().To)
|
||||
return nil, aerrors.Newf(255, "no code for actor %s(%d)(%s)", act.Code, method, hex.EncodeToString(params))
|
||||
}
|
||||
if method >= uint64(len(code)) || code[method] == nil {
|
||||
if method >= abi.MethodNum(len(code)) || code[method] == nil {
|
||||
return nil, aerrors.Newf(255, "no method %d on actor", method)
|
||||
}
|
||||
return code[method](act, vmctx, params)
|
||||
@ -252,7 +263,7 @@ func DecodeParams(b []byte, out interface{}) error {
|
||||
}
|
||||
|
||||
func DumpActorState(code cid.Cid, b []byte) (interface{}, error) {
|
||||
if code == actors.AccountCodeCid { // Account code special case
|
||||
if code == builtin.AccountActorCodeID { // Account code special case
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,13 @@ package vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/account"
|
||||
"github.com/ipfs/go-cid"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
|
||||
"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/state"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
@ -15,7 +16,7 @@ import (
|
||||
|
||||
func init() {
|
||||
cst := cbor.NewMemCborStore()
|
||||
emptyobject, err := cst.Put(context.TODO(), map[string]string{})
|
||||
emptyobject, err := cst.Put(context.TODO(), []struct{}{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -54,7 +55,7 @@ func makeActor(st *state.StateTree, addr address.Address) (*types.Actor, aerrors
|
||||
}
|
||||
|
||||
func NewBLSAccountActor(st *state.StateTree, addr address.Address) (*types.Actor, aerrors.ActorError) {
|
||||
var acstate actors.AccountActorState
|
||||
var acstate account.State
|
||||
acstate.Address = addr
|
||||
|
||||
c, err := st.Store.Put(context.TODO(), &acstate)
|
||||
@ -63,7 +64,7 @@ func NewBLSAccountActor(st *state.StateTree, addr address.Address) (*types.Actor
|
||||
}
|
||||
|
||||
nact := &types.Actor{
|
||||
Code: actors.AccountCodeCid,
|
||||
Code: builtin.AccountActorCodeID,
|
||||
Balance: types.NewInt(0),
|
||||
Head: c,
|
||||
}
|
||||
@ -73,7 +74,7 @@ func NewBLSAccountActor(st *state.StateTree, addr address.Address) (*types.Actor
|
||||
|
||||
func NewSecp256k1AccountActor(st *state.StateTree, addr address.Address) (*types.Actor, aerrors.ActorError) {
|
||||
nact := &types.Actor{
|
||||
Code: actors.AccountCodeCid,
|
||||
Code: builtin.AccountActorCodeID,
|
||||
Balance: types.NewInt(0),
|
||||
Head: EmptyObjectCid,
|
||||
}
|
||||
|
@ -3,36 +3,62 @@ package vm
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"encoding/binary"
|
||||
"runtime/debug"
|
||||
|
||||
"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/types"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/runtime"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
vmr "github.com/filecoin-project/specs-actors/actors/runtime"
|
||||
"github.com/filecoin-project/specs-actors/actors/runtime/exitcode"
|
||||
"github.com/ipfs/go-cid"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
type runtimeShim struct {
|
||||
vmctx types.VMContext
|
||||
vmr.Runtime
|
||||
}
|
||||
|
||||
var _ runtime.Runtime = (*runtimeShim)(nil)
|
||||
func (rs *runtimeShim) ResolveAddress(address address.Address) (ret address.Address, ok bool) {
|
||||
r, err := rs.vmctx.LookupID(address)
|
||||
if err != nil { // TODO: check notfound
|
||||
rs.Abortf(exitcode.ErrPlaceholder, "resolve address: %v", err)
|
||||
}
|
||||
return r, true
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) Get(c cid.Cid, o vmr.CBORUnmarshaler) bool {
|
||||
err := rs.vmctx.Storage().Get(c, o)
|
||||
if err != nil { // todo: not found
|
||||
rs.Abortf(exitcode.ErrPlaceholder, "storage get: %v", err)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) Put(x vmr.CBORMarshaler) cid.Cid {
|
||||
c, err := rs.vmctx.Storage().Put(x)
|
||||
if err != nil {
|
||||
rs.Abortf(exitcode.ErrPlaceholder, "storage put: %v", err) // todo: spec code?
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
var _ vmr.Runtime = (*runtimeShim)(nil)
|
||||
|
||||
func (rs *runtimeShim) shimCall(f func() interface{}) (rval []byte, aerr aerrors.ActorError) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if ar, ok := r.(aerrors.ActorError); ok {
|
||||
log.Warn("VM.Call failure: ", ar)
|
||||
debug.PrintStack()
|
||||
aerr = ar
|
||||
return
|
||||
}
|
||||
fmt.Println("caught one of those actor errors: ", r)
|
||||
log.Warn("caught one of those actor errors: ", r)
|
||||
debug.PrintStack()
|
||||
log.Errorf("ERROR")
|
||||
aerr = aerrors.Newf(1, "generic spec actors failure")
|
||||
@ -56,14 +82,132 @@ func (rs *runtimeShim) shimCall(f func() interface{}) (rval []byte, aerr aerrors
|
||||
}
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) Message() vmr.Message {
|
||||
var err error
|
||||
|
||||
rawm := *rs.vmctx.Message() // TODO: normalize addresses earlier
|
||||
rawm.From, err = rs.vmctx.LookupID(rawm.From)
|
||||
if err != nil {
|
||||
rs.Abortf(exitcode.ErrPlaceholder, "resolve from address: %v", err)
|
||||
}
|
||||
|
||||
rawm.To, err = rs.vmctx.LookupID(rawm.To)
|
||||
if err != nil {
|
||||
rs.Abortf(exitcode.ErrPlaceholder, "resolve to address: %v", err)
|
||||
}
|
||||
|
||||
return &rawm
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) ValidateImmediateCallerAcceptAny() {
|
||||
return
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) CurrentBalance() abi.TokenAmount {
|
||||
b, err := rs.vmctx.GetBalance(rs.vmctx.Message().To)
|
||||
if err != nil {
|
||||
rs.Abortf(exitcode.ExitCode(err.RetCode()), "get current balance: %v", err)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) GetActorCodeCID(addr address.Address) (ret cid.Cid, ok bool) {
|
||||
ret, err := rs.vmctx.ActorCodeCID(addr)
|
||||
if err != nil {
|
||||
// todo: notfound
|
||||
rs.Abortf(exitcode.ErrPlaceholder, "%v", err)
|
||||
}
|
||||
|
||||
return ret, true
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) GetRandomness(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) abi.Randomness {
|
||||
r, err := rs.vmctx.GetRandomness(personalization, randEpoch, entropy)
|
||||
if err != nil {
|
||||
rs.Abortf(exitcode.SysErrInternal, "getting randomness: %v", err)
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) Store() vmr.Store {
|
||||
return rs
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) NewActorAddress() address.Address {
|
||||
var b bytes.Buffer
|
||||
if err := rs.ImmediateCaller().MarshalCBOR(&b); err != nil { // todo: spec says cbor; why not just bytes?
|
||||
rs.Abortf(exitcode.ErrSerialization, "writing caller address into a buffer: %v", err)
|
||||
}
|
||||
|
||||
var err error
|
||||
st, err := rs.vmctx.StateTree()
|
||||
if err != nil {
|
||||
rs.Abortf(exitcode.SysErrInternal, "getting statetree: %v", err)
|
||||
}
|
||||
act, err := st.GetActor(rs.vmctx.Origin())
|
||||
if err != nil {
|
||||
rs.Abortf(exitcode.SysErrInternal, "getting top level actor: %v", err)
|
||||
}
|
||||
|
||||
if err := binary.Write(&b, binary.BigEndian, act.Nonce); err != nil {
|
||||
rs.Abortf(exitcode.ErrSerialization, "writing nonce address into a buffer: %v", err)
|
||||
}
|
||||
if err := binary.Write(&b, binary.BigEndian, uint64(0)); err != nil { // TODO: expose on vm
|
||||
rs.Abortf(exitcode.ErrSerialization, "writing callSeqNum address into a buffer: %v", err)
|
||||
}
|
||||
addr, err := address.NewActorAddress(b.Bytes())
|
||||
if err != nil {
|
||||
rs.Abortf(exitcode.ErrSerialization, "create actor address: %v", err)
|
||||
}
|
||||
|
||||
return addr
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) CreateActor(codeId cid.Cid, address address.Address) {
|
||||
var err error
|
||||
st, err := rs.vmctx.StateTree()
|
||||
if err != nil {
|
||||
rs.Abortf(exitcode.SysErrInternal, "getting statetree: %v", err)
|
||||
}
|
||||
|
||||
err = st.SetActor(address, &types.Actor{
|
||||
Code: codeId,
|
||||
Head: EmptyObjectCid,
|
||||
Nonce: 0,
|
||||
Balance: big.Zero(),
|
||||
})
|
||||
if err != nil {
|
||||
rs.Abortf(exitcode.SysErrInternal, "creating actor entry: %v", err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) DeleteActor() {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) Syscalls() vmr.Syscalls {
|
||||
return rs.vmctx.Sys()
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) StartSpan(name string) vmr.TraceSpan {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) ValidateImmediateCallerIs(as ...address.Address) {
|
||||
imm, err := rs.vmctx.LookupID(rs.vmctx.Message().From)
|
||||
if err != nil {
|
||||
rs.Abortf(exitcode.ErrIllegalState, "couldn't resolve immediate caller")
|
||||
}
|
||||
|
||||
for _, a := range as {
|
||||
if rs.vmctx.Message().From == a {
|
||||
if imm == a {
|
||||
return
|
||||
}
|
||||
}
|
||||
fmt.Println("Caller: ", rs.vmctx.Message().From, as)
|
||||
panic("we like to panic when people call the wrong methods")
|
||||
rs.Abortf(exitcode.ErrForbidden, "caller %s is not one of %s", rs.vmctx.Message().From, as)
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) ImmediateCaller() address.Address {
|
||||
@ -74,44 +218,20 @@ func (rs *runtimeShim) Context() context.Context {
|
||||
return rs.vmctx.Context()
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) IpldGet(c cid.Cid, o vmr.CBORUnmarshaler) bool {
|
||||
if err := rs.vmctx.Storage().Get(c, o); err != nil {
|
||||
panic(err) // y o o o o o l l l l o o o o o
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) IpldPut(o vmr.CBORMarshaler) cid.Cid {
|
||||
c, err := rs.vmctx.Storage().Put(o)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) Abort(code exitcode.ExitCode, msg string, args ...interface{}) {
|
||||
panic(aerrors.Newf(uint8(code), msg, args...))
|
||||
func (rs *runtimeShim) Abortf(code exitcode.ExitCode, msg string, args ...interface{}) {
|
||||
panic(aerrors.NewfSkip(2, uint8(code), msg, args...))
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) AbortStateMsg(msg string) {
|
||||
rs.Abort(101, msg)
|
||||
panic(aerrors.NewfSkip(3, 101, msg))
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) ValidateImmediateCallerType(...cid.Cid) {
|
||||
log.Info("validate caller type is dumb")
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) CurrentBalance() abi.TokenAmount {
|
||||
b, err := rs.vmctx.GetBalance(rs.vmctx.Message().From)
|
||||
if err != nil {
|
||||
rs.Abort(1, err.Error())
|
||||
}
|
||||
|
||||
return abi.TokenAmount(b)
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) CurrEpoch() abi.ChainEpoch {
|
||||
return abi.ChainEpoch(rs.vmctx.BlockHeight())
|
||||
return rs.vmctx.BlockHeight()
|
||||
}
|
||||
|
||||
type dumbWrapperType struct {
|
||||
@ -122,13 +242,17 @@ func (dwt *dumbWrapperType) Into(um vmr.CBORUnmarshaler) error {
|
||||
return um.UnmarshalCBOR(bytes.NewReader(dwt.val))
|
||||
}
|
||||
|
||||
func (rs *runtimeShim) Send(to address.Address, method abi.MethodNum, m runtime.CBORMarshaler, value abi.TokenAmount) (vmr.SendReturn, exitcode.ExitCode) {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := m.MarshalCBOR(buf); err != nil {
|
||||
rs.Abort(exitcode.SysErrInvalidParameters, "failed to marshal input parameters: %s", err)
|
||||
func (rs *runtimeShim) Send(to address.Address, method abi.MethodNum, m vmr.CBORMarshaler, value abi.TokenAmount) (vmr.SendReturn, exitcode.ExitCode) {
|
||||
var params []byte
|
||||
if m != nil {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := m.MarshalCBOR(buf); err != nil {
|
||||
rs.Abortf(exitcode.SysErrInvalidParameters, "failed to marshal input parameters: %s", err)
|
||||
}
|
||||
params = buf.Bytes()
|
||||
}
|
||||
|
||||
ret, err := rs.vmctx.Send(to, uint64(method), types.BigInt(value), buf.Bytes())
|
||||
ret, err := rs.vmctx.Send(to, method, types.BigInt(value), params)
|
||||
if err != nil {
|
||||
if err.IsFatal() {
|
||||
panic(err)
|
||||
@ -146,6 +270,16 @@ type shimStateHandle struct {
|
||||
rs *runtimeShim
|
||||
}
|
||||
|
||||
func (ssh *shimStateHandle) Create(obj vmr.CBORMarshaler) {
|
||||
c, err := ssh.rs.vmctx.Storage().Put(obj)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := ssh.rs.vmctx.Storage().Commit(EmptyObjectCid, c); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (ssh *shimStateHandle) Readonly(obj vmr.CBORUnmarshaler) {
|
||||
if err := ssh.rs.vmctx.Storage().Get(ssh.rs.vmctx.Storage().GetHead(), obj); err != nil {
|
||||
panic(err)
|
||||
@ -170,15 +304,3 @@ func (ssh *shimStateHandle) Transaction(obj vmr.CBORer, f func() interface{}) in
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (ssh *shimStateHandle) Construct(f func() vmr.CBORMarshaler) {
|
||||
out := f()
|
||||
|
||||
c, err := ssh.rs.vmctx.Storage().Put(out)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := ssh.rs.vmctx.Storage().Commit(actors.EmptyCBOR, c); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
@ -1,69 +1,131 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
ffi "github.com/filecoin-project/filecoin-ffi"
|
||||
"github.com/filecoin-project/go-address"
|
||||
commcid "github.com/filecoin-project/go-fil-commcid"
|
||||
"github.com/filecoin-project/go-sectorbuilder"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"go.opencensus.io/trace"
|
||||
"github.com/filecoin-project/lotus/lib/zerocomm"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
"github.com/filecoin-project/specs-actors/actors/runtime"
|
||||
"github.com/ipfs/go-cid"
|
||||
mh "github.com/multiformats/go-multihash"
|
||||
"golang.org/x/xerrors"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
func init() {
|
||||
mh.Codes[0xf104] = "filecoin"
|
||||
}
|
||||
|
||||
// Actual type is defined in chain/types/vmcontext.go because the VMContext interface is there
|
||||
|
||||
func Syscalls(verifier sectorbuilder.Verifier) *types.VMSyscalls {
|
||||
return &types.VMSyscalls{
|
||||
ValidatePoRep: func(ctx context.Context, maddr address.Address, ssize uint64, commD, commR, ticket, proof, seed []byte, sectorID uint64) (bool, actors.ActorError) {
|
||||
_, span := trace.StartSpan(ctx, "ValidatePoRep")
|
||||
defer span.End()
|
||||
ok, err := verifier.VerifySeal(ssize, commR, commD, maddr, ticket, seed, sectorID, proof)
|
||||
if err != nil {
|
||||
return false, aerrors.Absorb(err, 25, "verify seal failed")
|
||||
}
|
||||
|
||||
return ok, nil
|
||||
},
|
||||
VerifyFallbackPost: func(ctx context.Context,
|
||||
sectorSize uint64,
|
||||
sectorInfo []types.PublicSectorInfo,
|
||||
challengeSeed []byte,
|
||||
proof []byte,
|
||||
candidates []types.Candidate,
|
||||
proverID address.Address,
|
||||
faults uint64) (bool, error) {
|
||||
|
||||
sI := make([]ffi.PublicSectorInfo, len(sectorInfo))
|
||||
for i, v := range sectorInfo {
|
||||
sI[i] = ffi.PublicSectorInfo{
|
||||
SectorID: v.SectorID,
|
||||
CommR: v.CommR,
|
||||
}
|
||||
}
|
||||
|
||||
cand := make([]sectorbuilder.EPostCandidate, len(candidates))
|
||||
for i, v := range candidates {
|
||||
cand[i] = sectorbuilder.EPostCandidate{
|
||||
SectorID: v.SectorID,
|
||||
PartialTicket: v.PartialTicket,
|
||||
Ticket: v.Ticket,
|
||||
SectorChallengeIndex: v.SectorChallengeIndex,
|
||||
}
|
||||
}
|
||||
|
||||
return verifier.VerifyFallbackPost(
|
||||
ctx,
|
||||
sectorSize,
|
||||
sectorbuilder.NewSortedPublicSectorInfo(sI),
|
||||
challengeSeed,
|
||||
proof,
|
||||
cand,
|
||||
proverID,
|
||||
faults,
|
||||
)
|
||||
|
||||
},
|
||||
}
|
||||
func Syscalls(verifier sectorbuilder.Verifier) runtime.Syscalls {
|
||||
return &syscallShim{verifier}
|
||||
}
|
||||
|
||||
type syscallShim struct {
|
||||
verifier sectorbuilder.Verifier
|
||||
}
|
||||
|
||||
func (ss *syscallShim) ComputeUnsealedSectorCID(ssize abi.SectorSize, pieces []abi.PieceInfo) (cid.Cid, error) {
|
||||
// TODO: does this pull in unwanted dependencies?
|
||||
var ffipieces []ffi.PublicPieceInfo
|
||||
var sum abi.PaddedPieceSize
|
||||
for _, p := range pieces {
|
||||
ffipieces = append(ffipieces, ffi.PublicPieceInfo{
|
||||
Size: p.Size.Unpadded(),
|
||||
CommP: cidToCommD(p.PieceCID),
|
||||
})
|
||||
sum += p.Size
|
||||
}
|
||||
|
||||
{
|
||||
// pad remaining space with 0 CommPs
|
||||
toFill := uint64(abi.PaddedPieceSize(ssize) - sum)
|
||||
n := bits.OnesCount64(toFill)
|
||||
for i := 0; i < n; i++ {
|
||||
next := bits.TrailingZeros64(toFill)
|
||||
psize := uint64(1) << next
|
||||
toFill ^= psize
|
||||
|
||||
unpadded := abi.PaddedPieceSize(psize).Unpadded()
|
||||
ffipieces = append(ffipieces, ffi.PublicPieceInfo{
|
||||
Size: unpadded,
|
||||
CommP: zerocomm.ForSize(unpadded),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
commd, err := sectorbuilder.GenerateDataCommitment(ssize, ffipieces)
|
||||
if err != nil {
|
||||
log.Errorf("generate data commitment failed: %s", err)
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
return commcid.DataCommitmentV1ToCID(commd[:]), nil
|
||||
}
|
||||
|
||||
func (ss *syscallShim) HashBlake2b(data []byte) [32]byte {
|
||||
panic("NYI")
|
||||
}
|
||||
|
||||
func (ss *syscallShim) VerifyConsensusFault(a, b []byte) bool {
|
||||
panic("NYI")
|
||||
}
|
||||
|
||||
func (ss *syscallShim) VerifyPoSt(ssize abi.SectorSize, proof abi.PoStVerifyInfo) (bool, error) {
|
||||
panic("NYI")
|
||||
}
|
||||
|
||||
func cidToCommD(c cid.Cid) [32]byte {
|
||||
b := c.Bytes()
|
||||
var out [32]byte
|
||||
copy(out[:], b[len(b)-32:])
|
||||
return out
|
||||
}
|
||||
|
||||
func cidToCommR(c cid.Cid) [32]byte {
|
||||
b := c.Bytes()
|
||||
var out [32]byte
|
||||
copy(out[:], b[len(b)-32:])
|
||||
return out
|
||||
}
|
||||
|
||||
func (ss *syscallShim) VerifySeal(ssize abi.SectorSize, info abi.SealVerifyInfo) (bool, error) {
|
||||
//_, span := trace.StartSpan(ctx, "ValidatePoRep")
|
||||
//defer span.End()
|
||||
|
||||
commD := cidToCommD(info.UnsealedCID)
|
||||
commR := cidToCommR(info.OnChain.SealedCID)
|
||||
|
||||
miner, err := address.NewIDAddress(uint64(info.Miner))
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("weirdly failed to construct address: %w", err)
|
||||
}
|
||||
|
||||
ticket := []byte(info.Randomness)
|
||||
proof := []byte(info.OnChain.Proof)
|
||||
seed := []byte(info.InteractiveRandomness)
|
||||
|
||||
log.Infof("Werif %d r:%x; d:%x; m:%s; t:%x; s:%x; N:%d; p:%x", ssize, commR, commD, miner, ticket, seed, info.SectorID.Number, proof)
|
||||
|
||||
//func(ctx context.Context, maddr address.Address, ssize abi.SectorSize, commD, commR, ticket, proof, seed []byte, sectorID abi.SectorNumber)
|
||||
ok, err := ss.verifier.VerifySeal(ssize, commR[:], commD[:], miner, ticket, seed, info.SectorID.Number, proof)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("failed to validate PoRep: %w", err)
|
||||
}
|
||||
|
||||
return ok, nil
|
||||
}
|
||||
|
||||
func (ss *syscallShim) VerifySignature(sig crypto.Signature, addr address.Address, input []byte) bool {
|
||||
return true
|
||||
/* // TODO: in genesis setup, we are currently faking signatures
|
||||
if err := ss.rt.vmctx.VerifySignature(&sig, addr, input); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
*/
|
||||
}
|
||||
|
@ -4,7 +4,9 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"math/big"
|
||||
"reflect"
|
||||
|
||||
block "github.com/ipfs/go-block-format"
|
||||
cid "github.com/ipfs/go-cid"
|
||||
@ -12,13 +14,20 @@ import (
|
||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
mh "github.com/multiformats/go-multihash"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"go.opencensus.io/trace"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
commcid "github.com/filecoin-project/go-fil-commcid"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/account"
|
||||
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
"github.com/filecoin-project/specs-actors/actors/runtime"
|
||||
|
||||
"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/state"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
@ -50,13 +59,13 @@ type VMContext struct {
|
||||
vm *VM
|
||||
state *state.StateTree
|
||||
msg *types.Message
|
||||
height uint64
|
||||
height abi.ChainEpoch
|
||||
cst cbor.IpldStore
|
||||
|
||||
gasAvailable types.BigInt
|
||||
gasUsed types.BigInt
|
||||
|
||||
sys *types.VMSyscalls
|
||||
sys runtime.Syscalls
|
||||
|
||||
// root cid of the state of the actor this invocation will be on
|
||||
sroot cid.Cid
|
||||
@ -70,16 +79,15 @@ func (vmc *VMContext) Message() *types.Message {
|
||||
return vmc.msg
|
||||
}
|
||||
|
||||
func (vmc *VMContext) GetRandomness(height uint64) ([]byte, aerrors.ActorError) {
|
||||
|
||||
res, err := vmc.vm.rand.GetRandomness(vmc.ctx, int64(height))
|
||||
func (vmc *VMContext) GetRandomness(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) ([]byte, aerrors.ActorError) {
|
||||
res, err := vmc.vm.rand.GetRandomness(vmc.ctx, personalization, int64(randEpoch), entropy)
|
||||
if err != nil {
|
||||
return nil, aerrors.Escalate(err, "could not get randomness")
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (vmc *VMContext) Sys() *types.VMSyscalls {
|
||||
func (vmc *VMContext) Sys() runtime.Syscalls {
|
||||
return vmc.sys
|
||||
}
|
||||
|
||||
@ -133,7 +141,7 @@ func (vmc *VMContext) Origin() address.Address {
|
||||
}
|
||||
|
||||
// Send allows the current execution context to invoke methods on other actors in the system
|
||||
func (vmc *VMContext) Send(to address.Address, method uint64, value types.BigInt, params []byte) ([]byte, aerrors.ActorError) {
|
||||
func (vmc *VMContext) Send(to address.Address, method abi.MethodNum, value types.BigInt, params []byte) ([]byte, aerrors.ActorError) {
|
||||
ctx, span := trace.StartSpan(vmc.ctx, "vmc.Send")
|
||||
defer span.End()
|
||||
if span.IsRecordingEvents() {
|
||||
@ -158,7 +166,7 @@ func (vmc *VMContext) Send(to address.Address, method uint64, value types.BigInt
|
||||
}
|
||||
|
||||
// BlockHeight returns the height of the block this message was added to the chain in
|
||||
func (vmc *VMContext) BlockHeight() uint64 {
|
||||
func (vmc *VMContext) BlockHeight() abi.ChainEpoch {
|
||||
return vmc.height
|
||||
}
|
||||
|
||||
@ -176,16 +184,28 @@ func (vmc *VMContext) ChargeGas(amount uint64) aerrors.ActorError {
|
||||
}
|
||||
|
||||
func (vmc *VMContext) StateTree() (types.StateTree, aerrors.ActorError) {
|
||||
if vmc.msg.To != actors.InitAddress {
|
||||
if vmc.msg.To != builtin.InitActorAddr {
|
||||
return nil, aerrors.Escalate(fmt.Errorf("only init actor can access state tree directly"), "invalid use of StateTree")
|
||||
}
|
||||
|
||||
return vmc.state, nil
|
||||
}
|
||||
|
||||
func (vmc *VMContext) ActorCodeCID(addr address.Address) (ret cid.Cid, err error) {
|
||||
act, err := vmc.state.GetActor(addr)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
return act.Code, nil
|
||||
}
|
||||
|
||||
func (vmc *VMContext) LookupID(a address.Address) (address.Address, error) {
|
||||
return vmc.state.LookupID(a)
|
||||
}
|
||||
|
||||
const GasVerifySignature = 50
|
||||
|
||||
func (vmctx *VMContext) VerifySignature(sig *types.Signature, act address.Address, data []byte) aerrors.ActorError {
|
||||
func (vmctx *VMContext) VerifySignature(sig *crypto.Signature, act address.Address, data []byte) aerrors.ActorError {
|
||||
if err := vmctx.ChargeGas(GasVerifySignature); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -215,11 +235,11 @@ func ResolveToKeyAddr(state types.StateTree, cst cbor.IpldStore, addr address.Ad
|
||||
return address.Undef, aerrors.Newf(1, "failed to find actor: %s", addr)
|
||||
}
|
||||
|
||||
if act.Code != actors.AccountCodeCid {
|
||||
if act.Code != builtin.AccountActorCodeID {
|
||||
return address.Undef, aerrors.New(1, "address was not for an account actor")
|
||||
}
|
||||
|
||||
var aast actors.AccountActorState
|
||||
var aast account.State
|
||||
if err := cst.Get(context.TODO(), act.Head, &aast); err != nil {
|
||||
return address.Undef, aerrors.Escalate(err, fmt.Sprintf("failed to get account actor state for %s", addr))
|
||||
}
|
||||
@ -301,15 +321,15 @@ type VM struct {
|
||||
base cid.Cid
|
||||
cst *cbor.BasicIpldStore
|
||||
buf *bufbstore.BufferedBS
|
||||
blockHeight uint64
|
||||
blockHeight abi.ChainEpoch
|
||||
blockMiner address.Address
|
||||
inv *invoker
|
||||
rand Rand
|
||||
|
||||
Syscalls *types.VMSyscalls
|
||||
Syscalls runtime.Syscalls
|
||||
}
|
||||
|
||||
func NewVM(base cid.Cid, height uint64, r Rand, maddr address.Address, cbs blockstore.Blockstore, syscalls *types.VMSyscalls) (*VM, error) {
|
||||
func NewVM(base cid.Cid, height abi.ChainEpoch, r Rand, maddr address.Address, cbs blockstore.Blockstore, syscalls runtime.Syscalls) (*VM, error) {
|
||||
buf := bufbstore.NewBufferedBstore(cbs)
|
||||
cst := cbor.NewCborStore(buf)
|
||||
state, err := state.LoadStateTree(cst, base)
|
||||
@ -331,7 +351,7 @@ func NewVM(base cid.Cid, height uint64, r Rand, maddr address.Address, cbs block
|
||||
}
|
||||
|
||||
type Rand interface {
|
||||
GetRandomness(ctx context.Context, h int64) ([]byte, error)
|
||||
GetRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round int64, entropy []byte) ([]byte, error)
|
||||
}
|
||||
|
||||
type ApplyRet struct {
|
||||
@ -350,7 +370,7 @@ func (vm *VM) send(ctx context.Context, msg *types.Message, parent *VMContext,
|
||||
|
||||
toActor, err := st.GetActor(msg.To)
|
||||
if err != nil {
|
||||
if xerrors.Is(err, types.ErrActorNotFound) {
|
||||
if xerrors.Is(err, init_.ErrAddressNotFound) {
|
||||
a, err := TryCreateAccountActor(st, msg.To)
|
||||
if err != nil {
|
||||
return nil, aerrors.Absorb(err, 1, "could not create account"), nil
|
||||
@ -543,6 +563,37 @@ func (vm *VM) Flush(ctx context.Context) (cid.Cid, error) {
|
||||
return root, nil
|
||||
}
|
||||
|
||||
// vm.MutateState(idAddr, func(cst cbor.IpldStore, st *ActorStateType) error {...})
|
||||
func (vm *VM) MutateState(ctx context.Context, addr address.Address, fn interface{}) error {
|
||||
act, err := vm.cstate.GetActor(addr)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("actor not found: %w", err)
|
||||
}
|
||||
|
||||
st := reflect.New(reflect.TypeOf(fn).In(1).Elem())
|
||||
if err := vm.cst.Get(ctx, act.Head, st.Interface()); err != nil {
|
||||
return xerrors.Errorf("read actor head: %w", err)
|
||||
}
|
||||
|
||||
out := reflect.ValueOf(fn).Call([]reflect.Value{reflect.ValueOf(vm.cst), st})
|
||||
if !out[0].IsNil() && out[0].Interface().(error) != nil {
|
||||
return out[0].Interface().(error)
|
||||
}
|
||||
|
||||
head, err := vm.cst.Put(ctx, st.Interface())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("put new actor head: %w", err)
|
||||
}
|
||||
|
||||
act.Head = head
|
||||
|
||||
if err := vm.cstate.SetActor(addr, act); err != nil {
|
||||
return xerrors.Errorf("set actor: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func linksForObj(blk block.Block) ([]cid.Cid, error) {
|
||||
switch blk.Cid().Prefix().Codec {
|
||||
case cid.DagCBOR:
|
||||
@ -595,7 +646,7 @@ func copyRec(from, to blockstore.Blockstore, root cid.Cid, cp func(block.Block)
|
||||
}
|
||||
|
||||
for _, link := range links {
|
||||
if link.Prefix().MhType == 0 {
|
||||
if link.Prefix().MhType == mh.IDENTITY || link.Prefix().MhType == uint64(commcid.FC_SEALED_V1) || link.Prefix().MhType == uint64(commcid.FC_UNSEALED_V1) {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -622,11 +673,11 @@ func (vm *VM) StateTree() types.StateTree {
|
||||
return vm.cstate
|
||||
}
|
||||
|
||||
func (vm *VM) SetBlockHeight(h uint64) {
|
||||
func (vm *VM) SetBlockHeight(h abi.ChainEpoch) {
|
||||
vm.blockHeight = h
|
||||
}
|
||||
|
||||
func (vm *VM) Invoke(act *types.Actor, vmctx *VMContext, method uint64, params []byte) ([]byte, aerrors.ActorError) {
|
||||
func (vm *VM) Invoke(act *types.Actor, vmctx *VMContext, method abi.MethodNum, params []byte) ([]byte, aerrors.ActorError) {
|
||||
ctx, span := trace.StartSpan(vmctx.ctx, "vm.Invoke")
|
||||
defer span.End()
|
||||
if span.IsRecordingEvents() {
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
@ -23,6 +24,8 @@ var log = logging.Logger("wallet")
|
||||
const (
|
||||
KNamePrefix = "wallet-"
|
||||
KDefault = "default"
|
||||
KTBLS = "bls"
|
||||
KTSecp256k1 = "secp256k1"
|
||||
)
|
||||
|
||||
type Wallet struct {
|
||||
@ -52,7 +55,7 @@ func KeyWallet(keys ...*Key) *Wallet {
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Wallet) Sign(ctx context.Context, addr address.Address, msg []byte) (*types.Signature, error) {
|
||||
func (w *Wallet) Sign(ctx context.Context, addr address.Address, msg []byte) (*crypto.Signature, error) {
|
||||
ki, err := w.findKey(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -61,7 +64,7 @@ func (w *Wallet) Sign(ctx context.Context, addr address.Address, msg []byte) (*t
|
||||
return nil, xerrors.Errorf("signing using key '%s': %w", addr.String(), types.ErrKeyInfoNotFound)
|
||||
}
|
||||
|
||||
return sigs.Sign(ki.Type, ki.PrivateKey, msg)
|
||||
return sigs.Sign(ActSigType(ki.Type), ki.PrivateKey, msg)
|
||||
}
|
||||
|
||||
func (w *Wallet) findKey(addr address.Address) (*Key, error) {
|
||||
@ -179,19 +182,19 @@ func (w *Wallet) SetDefault(a address.Address) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func GenerateKey(typ string) (*Key, error) {
|
||||
func GenerateKey(typ crypto.SigType) (*Key, error) {
|
||||
pk, err := sigs.Generate(typ)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ki := types.KeyInfo{
|
||||
Type: typ,
|
||||
Type: kstoreSigType(typ),
|
||||
PrivateKey: pk,
|
||||
}
|
||||
return NewKey(ki)
|
||||
}
|
||||
|
||||
func (w *Wallet) GenerateKey(typ string) (address.Address, error) {
|
||||
func (w *Wallet) GenerateKey(typ crypto.SigType) (address.Address, error) {
|
||||
w.lk.Lock()
|
||||
defer w.lk.Unlock()
|
||||
|
||||
@ -240,18 +243,18 @@ func NewKey(keyinfo types.KeyInfo) (*Key, error) {
|
||||
}
|
||||
|
||||
var err error
|
||||
k.PublicKey, err = sigs.ToPublic(k.Type, k.PrivateKey)
|
||||
k.PublicKey, err = sigs.ToPublic(ActSigType(k.Type), k.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch k.Type {
|
||||
case types.KTSecp256k1:
|
||||
case KTSecp256k1:
|
||||
k.Address, err = address.NewSecp256k1Address(k.PublicKey)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("converting Secp256k1 to address: %w", err)
|
||||
}
|
||||
case types.KTBLS:
|
||||
case KTBLS:
|
||||
k.Address, err = address.NewBLSAddress(k.PublicKey)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("converting BLS to address: %w", err)
|
||||
@ -262,3 +265,25 @@ func NewKey(keyinfo types.KeyInfo) (*Key, error) {
|
||||
return k, nil
|
||||
|
||||
}
|
||||
|
||||
func kstoreSigType(typ crypto.SigType) string {
|
||||
switch typ {
|
||||
case crypto.SigTypeBLS:
|
||||
return KTBLS
|
||||
case crypto.SigTypeSecp256k1:
|
||||
return KTSecp256k1
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func ActSigType(typ string) crypto.SigType {
|
||||
switch typ {
|
||||
case KTBLS:
|
||||
return crypto.SigTypeBLS
|
||||
case KTSecp256k1:
|
||||
return crypto.SigTypeSecp256k1
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
38
cli/chain.go
38
cli/chain.go
@ -11,6 +11,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
cborutil "github.com/filecoin-project/go-cbor-util"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
||||
cid "github.com/ipfs/go-cid"
|
||||
"golang.org/x/xerrors"
|
||||
"gopkg.in/urfave/cli.v2"
|
||||
@ -250,7 +255,7 @@ var chainSetHeadCmd = &cli.Command{
|
||||
ts, err = api.ChainGetGenesis(ctx)
|
||||
}
|
||||
if ts == nil && cctx.IsSet("epoch") {
|
||||
ts, err = api.ChainGetTipSetByHeight(ctx, cctx.Uint64("epoch"), types.EmptyTSK)
|
||||
ts, err = api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(cctx.Uint64("epoch")), types.EmptyTSK)
|
||||
}
|
||||
if ts == nil {
|
||||
ts, err = parseTipSet(api, ctx, cctx.Args().Slice())
|
||||
@ -313,7 +318,7 @@ var chainListCmd = &cli.Command{
|
||||
var head *types.TipSet
|
||||
|
||||
if cctx.IsSet("height") {
|
||||
head, err = api.ChainGetTipSetByHeight(ctx, cctx.Uint64("height"), types.EmptyTSK)
|
||||
head, err = api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(cctx.Uint64("height")), types.EmptyTSK)
|
||||
} else {
|
||||
head, err = api.ChainHead(ctx)
|
||||
}
|
||||
@ -446,7 +451,7 @@ var chainBisectCmd = &cli.Command{
|
||||
|
||||
subPath := cctx.Args().Get(2)
|
||||
|
||||
highest, err := api.ChainGetTipSetByHeight(ctx, end, types.EmptyTSK)
|
||||
highest, err := api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(end), types.EmptyTSK)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -460,7 +465,7 @@ var chainBisectCmd = &cli.Command{
|
||||
start = end
|
||||
}
|
||||
|
||||
midTs, err := api.ChainGetTipSetByHeight(ctx, mid, highest.Key())
|
||||
midTs, err := api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(mid), highest.Key())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -506,7 +511,7 @@ var chainBisectCmd = &cli.Command{
|
||||
return nil
|
||||
}
|
||||
|
||||
prev = mid
|
||||
prev = abi.ChainEpoch(mid)
|
||||
}
|
||||
},
|
||||
}
|
||||
@ -594,18 +599,31 @@ var slashConsensusFault = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
params, err := actors.SerializeParams(&actors.ArbitrateConsensusFaultParams{
|
||||
Block1: b1,
|
||||
Block2: b2,
|
||||
bh1, err := cborutil.Dump(b1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bh2, err := cborutil.Dump(b2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
params, err := actors.SerializeParams(&power.ReportConsensusFaultParams{
|
||||
BlockHeader1: bh1,
|
||||
BlockHeader2: bh2,
|
||||
Target: address.Address{},
|
||||
FaultEpoch: 0,
|
||||
FaultType: 0,
|
||||
})
|
||||
|
||||
msg := &types.Message{
|
||||
To: actors.StoragePowerAddress,
|
||||
To: builtin.StoragePowerActorAddr,
|
||||
From: def,
|
||||
Value: types.NewInt(0),
|
||||
GasPrice: types.NewInt(1),
|
||||
GasLimit: types.NewInt(10000000),
|
||||
Method: actors.SPAMethods.ArbitrateConsensusFault,
|
||||
Method: builtin.MethodsPower.ReportConsensusFault,
|
||||
Params: params,
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||
actors "github.com/filecoin-project/lotus/chain/actors"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
@ -291,27 +291,15 @@ var clientQueryAskCmd = &cli.Command{
|
||||
}
|
||||
pid = p
|
||||
} else {
|
||||
ret, err := api.StateCall(ctx, &types.Message{
|
||||
To: maddr,
|
||||
From: maddr,
|
||||
Method: actors.MAMethods.GetPeerID,
|
||||
}, types.EmptyTSK)
|
||||
p, err := api.StateMinerPeerID(ctx, maddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to get peerID for miner: %w", err)
|
||||
}
|
||||
|
||||
if ret.ExitCode != 0 {
|
||||
return fmt.Errorf("call to GetPeerID was unsuccesful (exit code %d)", ret.ExitCode)
|
||||
}
|
||||
if peer.ID(ret.Return) == peer.ID("SETME") {
|
||||
if p == peer.ID("SETME") {
|
||||
return fmt.Errorf("the miner hasn't initialized yet")
|
||||
}
|
||||
|
||||
p, err := peer.IDFromBytes(ret.Return)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pid = p
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
||||
samsig "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
|
||||
cid "github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-hamt-ipld"
|
||||
@ -104,9 +105,9 @@ var msigCreateCmd = &cli.Command{
|
||||
}
|
||||
|
||||
// new actors are created by invoking 'exec' on the init actor with the constructor params
|
||||
execParams := &actors.ExecParams{
|
||||
Code: actors.MultisigCodeCid,
|
||||
Params: enc,
|
||||
execParams := &init_.ExecParams{
|
||||
CodeCID: builtin.MultisigActorCodeID,
|
||||
ConstructorParams: enc,
|
||||
}
|
||||
|
||||
enc, err = actors.SerializeParams(execParams)
|
||||
@ -116,9 +117,9 @@ var msigCreateCmd = &cli.Command{
|
||||
|
||||
// now we create the message to send this with
|
||||
msg := types.Message{
|
||||
To: actors.InitAddress,
|
||||
To: builtin.InitActorAddr,
|
||||
From: sendAddr,
|
||||
Method: actors.IAMethods.Exec,
|
||||
Method: builtin.MethodsInit.Exec,
|
||||
Params: enc,
|
||||
GasPrice: types.NewInt(1),
|
||||
GasLimit: types.NewInt(1000000),
|
||||
@ -186,7 +187,7 @@ var msigInspectCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
var mstate samsig.MultiSigActorState
|
||||
var mstate samsig.State
|
||||
if err := mstate.UnmarshalCBOR(bytes.NewReader(obj)); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -226,19 +227,19 @@ var msigInspectCmd = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
func GetMultisigPending(ctx context.Context, lapi api.FullNode, hroot cid.Cid) (map[int64]*samsig.MultiSigTransaction, error) {
|
||||
func GetMultisigPending(ctx context.Context, lapi api.FullNode, hroot cid.Cid) (map[int64]*samsig.Transaction, error) {
|
||||
bs := apibstore.NewAPIBlockstore(lapi)
|
||||
cst := cbor.NewCborStore(bs)
|
||||
|
||||
nd, err := hamt.LoadNode(ctx, cst, hroot)
|
||||
nd, err := hamt.LoadNode(ctx, cst, hroot, hamt.UseTreeBitWidth(5))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txs := make(map[int64]*samsig.MultiSigTransaction)
|
||||
txs := make(map[int64]*samsig.Transaction)
|
||||
err = nd.ForEach(ctx, func(k string, val interface{}) error {
|
||||
d := val.(*cbg.Deferred)
|
||||
var tx samsig.MultiSigTransaction
|
||||
var tx samsig.Transaction
|
||||
if err := tx.UnmarshalCBOR(bytes.NewReader(d.Raw)); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -255,7 +256,7 @@ func GetMultisigPending(ctx context.Context, lapi api.FullNode, hroot cid.Cid) (
|
||||
return txs, nil
|
||||
}
|
||||
|
||||
func state(tx *samsig.MultiSigTransaction) string {
|
||||
func state(tx *samsig.Transaction) string {
|
||||
/* // TODO(why): I strongly disagree with not having these... but i need to move forward
|
||||
if tx.Complete {
|
||||
return "done"
|
||||
@ -347,7 +348,7 @@ var msigProposeCmd = &cli.Command{
|
||||
To: msig,
|
||||
From: from,
|
||||
Value: types.NewInt(0),
|
||||
Method: uint64(builtin.MethodsMultisig.Propose),
|
||||
Method: builtin.MethodsMultisig.Propose,
|
||||
Params: enc,
|
||||
GasLimit: types.NewInt(100000),
|
||||
GasPrice: types.NewInt(1),
|
||||
@ -432,7 +433,7 @@ var msigApproveCmd = &cli.Command{
|
||||
To: msig,
|
||||
From: from,
|
||||
Value: types.NewInt(0),
|
||||
Method: uint64(builtin.MethodsMultisig.Approve),
|
||||
Method: builtin.MethodsMultisig.Approve,
|
||||
Params: enc,
|
||||
GasLimit: types.NewInt(100000),
|
||||
GasPrice: types.NewInt(1),
|
||||
|
23
cli/paych.go
23
cli/paych.go
@ -1,11 +1,15 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
types "github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||
"gopkg.in/urfave/cli.v2"
|
||||
|
||||
types "github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
var paychCmd = &cli.Command{
|
||||
@ -136,7 +140,7 @@ var paychVoucherCreateCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
enc, err := sv.EncodedString()
|
||||
enc, err := EncodedString(sv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -250,7 +254,7 @@ var paychVoucherListCmd = &cli.Command{
|
||||
|
||||
for _, v := range vouchers {
|
||||
if cctx.Bool("export") {
|
||||
enc, err := v.EncodedString()
|
||||
enc, err := EncodedString(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -291,7 +295,7 @@ var paychVoucherBestSpendableCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
var best *types.SignedVoucher
|
||||
var best *paych.SignedVoucher
|
||||
for _, v := range vouchers {
|
||||
spendable, err := api.PaychVoucherCheckSpendable(ctx, ch, v, nil, nil)
|
||||
if err != nil {
|
||||
@ -308,7 +312,7 @@ var paychVoucherBestSpendableCmd = &cli.Command{
|
||||
return fmt.Errorf("No spendable vouchers for that channel")
|
||||
}
|
||||
|
||||
enc, err := best.EncodedString()
|
||||
enc, err := EncodedString(best)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -364,3 +368,12 @@ var paychVoucherSubmitCmd = &cli.Command{
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func EncodedString(sv *paych.SignedVoucher) (string, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := sv.MarshalCBOR(buf); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return base64.RawURLEncoding.EncodeToString(buf.Bytes()), nil
|
||||
}
|
||||
|
119
cli/state.go
119
cli/state.go
@ -5,19 +5,25 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
actors "github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/miner"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||
miner2 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||
samsig "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/miner"
|
||||
|
||||
"github.com/docker/go-units"
|
||||
"github.com/ipfs/go-cid"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
@ -90,24 +96,16 @@ var stateMinerInfo = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
var mst actors.StorageMinerActorState
|
||||
var mst miner2.State
|
||||
if err := mst.UnmarshalCBOR(bytes.NewReader(aso)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mio, err := api.ChainReadObj(ctx, mst.Info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var mi actors.MinerInfo
|
||||
if err := mi.UnmarshalCBOR(bytes.NewReader(mio)); err != nil {
|
||||
return err
|
||||
}
|
||||
mi := mst.Info
|
||||
|
||||
fmt.Printf("Owner:\t%s\n", mi.Owner)
|
||||
fmt.Printf("Worker:\t%s\n", mi.Worker)
|
||||
fmt.Printf("PeerID:\t%s\n", mi.PeerID)
|
||||
fmt.Printf("PeerID:\t%s\n", mi.PeerId)
|
||||
fmt.Printf("SectorSize:\t%s (%d)\n", units.BytesSize(float64(mi.SectorSize)), mi.SectorSize)
|
||||
|
||||
return nil
|
||||
@ -187,9 +185,9 @@ var statePowerCmd = &cli.Command{
|
||||
if cctx.Args().Present() {
|
||||
mp := power.MinerPower
|
||||
percI := types.BigDiv(types.BigMul(mp, types.NewInt(1000000)), tp)
|
||||
fmt.Printf("%s(%s) / %s(%s) ~= %0.4f%%\n", mp.String(), mp.SizeStr(), tp.String(), tp.SizeStr(), float64(percI.Int64())/10000)
|
||||
fmt.Printf("%s(%s) / %s(%s) ~= %0.4f%%\n", mp.String(), types.SizeStr(mp), tp.String(), types.SizeStr(tp), float64(percI.Int64())/10000)
|
||||
} else {
|
||||
fmt.Printf("%s(%s)\n", tp.String(), tp.SizeStr())
|
||||
fmt.Printf("%s(%s)\n", tp.String(), types.SizeStr(tp))
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -228,7 +226,7 @@ var stateSectorsCmd = &cli.Command{
|
||||
}
|
||||
|
||||
for _, s := range sectors {
|
||||
fmt.Printf("%d: %x %x\n", s.SectorID, s.CommR, s.CommD)
|
||||
fmt.Printf("%d: %x\n", s.Info.Info.SectorNumber, s.Info.Info.SealedCID)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -267,7 +265,7 @@ var stateProvingSetCmd = &cli.Command{
|
||||
}
|
||||
|
||||
for _, s := range sectors {
|
||||
fmt.Printf("%d: %x %x\n", s.SectorID, s.CommR, s.CommD)
|
||||
fmt.Printf("%d: %x\n", s.Info.Info.SectorNumber, s.Info.Info.SealedCID)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -278,8 +276,8 @@ var stateReplaySetCmd = &cli.Command{
|
||||
Name: "replay",
|
||||
Usage: "Replay a particular message within a tipset",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if cctx.Args().Len() < 2 {
|
||||
fmt.Println("usage: <tipset> <message cid>")
|
||||
if cctx.Args().Len() < 1 {
|
||||
fmt.Println("usage: [tipset] <message cid>")
|
||||
fmt.Println("The last cid passed will be used as the message CID")
|
||||
fmt.Println("All preceding ones will be used as the tipset")
|
||||
return nil
|
||||
@ -291,15 +289,6 @@ var stateReplaySetCmd = &cli.Command{
|
||||
return fmt.Errorf("message cid was invalid: %s", err)
|
||||
}
|
||||
|
||||
var tscids []cid.Cid
|
||||
for _, s := range args[:len(args)-1] {
|
||||
c, err := cid.Decode(s)
|
||||
if err != nil {
|
||||
return fmt.Errorf("tipset cid was invalid: %s", err)
|
||||
}
|
||||
tscids = append(tscids, c)
|
||||
}
|
||||
|
||||
api, closer, err := GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -308,19 +297,41 @@ var stateReplaySetCmd = &cli.Command{
|
||||
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
var headers []*types.BlockHeader
|
||||
for _, c := range tscids {
|
||||
h, err := api.ChainGetBlock(ctx, c)
|
||||
var ts *types.TipSet
|
||||
{
|
||||
var tscids []cid.Cid
|
||||
for _, s := range args[:len(args)-1] {
|
||||
c, err := cid.Decode(s)
|
||||
if err != nil {
|
||||
return fmt.Errorf("tipset cid was invalid: %s", err)
|
||||
}
|
||||
tscids = append(tscids, c)
|
||||
}
|
||||
|
||||
if len(tscids) > 0 {
|
||||
var headers []*types.BlockHeader
|
||||
for _, c := range tscids {
|
||||
h, err := api.ChainGetBlock(ctx, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
headers = append(headers, h)
|
||||
}
|
||||
|
||||
ts, err = types.NewTipSet(headers)
|
||||
} else {
|
||||
r, err := api.StateWaitMsg(ctx, mcid)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("finding message in chain: %w", err)
|
||||
}
|
||||
|
||||
ts, err = api.ChainGetTipSet(ctx, r.TipSet.Parents())
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
headers = append(headers, h)
|
||||
}
|
||||
|
||||
ts, err := types.NewTipSet(headers)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, err := api.StateReplay(ctx, ts.Key(), mcid)
|
||||
@ -393,7 +404,7 @@ var stateGetDealSetCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
deal, err := api.StateMarketStorageDeal(ctx, dealid, ts.Key())
|
||||
deal, err := api.StateMarketStorageDeal(ctx, abi.DealID(dealid), ts.Key())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -682,7 +693,7 @@ var stateListMessagesCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
msgs, err := api.StateListMessages(ctx, &types.Message{To: toa, From: froma}, ts.Key(), toh)
|
||||
msgs, err := api.StateListMessages(ctx, &types.Message{To: toa, From: froma}, ts.Key(), abi.ChainEpoch(toh))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -735,7 +746,7 @@ var stateComputeStateCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
h := cctx.Uint64("height")
|
||||
h := abi.ChainEpoch(cctx.Uint64("height"))
|
||||
if h == 0 {
|
||||
if ts == nil {
|
||||
head, err := api.ChainHead(ctx)
|
||||
@ -821,7 +832,7 @@ var stateCallCmd = &cli.Command{
|
||||
&cli.StringFlag{
|
||||
Name: "from",
|
||||
Usage: "",
|
||||
Value: actors.NetworkAddress.String(),
|
||||
Value: builtin.SystemActorAddr.String(),
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "value",
|
||||
@ -888,7 +899,7 @@ var stateCallCmd = &cli.Command{
|
||||
Value: types.BigInt(value),
|
||||
GasLimit: types.NewInt(10000000000),
|
||||
GasPrice: types.NewInt(0),
|
||||
Method: method,
|
||||
Method: abi.MethodNum(method),
|
||||
Params: params,
|
||||
}, ts.Key())
|
||||
if err != nil {
|
||||
@ -962,16 +973,16 @@ func parseParamsForMethod(act cid.Cid, method uint64, args []string) ([]byte, er
|
||||
|
||||
var f interface{}
|
||||
switch act {
|
||||
case actors.StorageMarketCodeCid:
|
||||
f = actors.StorageMarketActor{}.Exports()[method]
|
||||
case actors.StorageMinerCodeCid:
|
||||
f = actors.StorageMinerActor{}.Exports()[method]
|
||||
case actors.StoragePowerCodeCid:
|
||||
f = actors.StoragePowerActor{}.Exports()[method]
|
||||
case actors.MultisigCodeCid:
|
||||
f = samsig.MultiSigActor{}.Exports()[method]
|
||||
case actors.PaymentChannelCodeCid:
|
||||
f = actors.PaymentChannelActor{}.Exports()[method]
|
||||
case builtin.StorageMarketActorCodeID:
|
||||
f = market.Actor{}.Exports()[method]
|
||||
case builtin.StorageMinerActorCodeID:
|
||||
f = miner2.Actor{}.Exports()[method]
|
||||
case builtin.StoragePowerActorCodeID:
|
||||
f = power.Actor{}.Exports()[method]
|
||||
case builtin.MultisigActorCodeID:
|
||||
f = samsig.Actor{}.Exports()[method]
|
||||
case builtin.PaymentChannelActorCodeID:
|
||||
f = paych.Actor{}.Exports()[method]
|
||||
default:
|
||||
return nil, fmt.Errorf("the lazy devs didnt add support for that actor to this call yet")
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
cid "github.com/ipfs/go-cid"
|
||||
"gopkg.in/urfave/cli.v2"
|
||||
|
||||
@ -45,7 +46,7 @@ var syncStatusCmd = &cli.Command{
|
||||
fmt.Printf("worker %d:\n", i)
|
||||
var base, target []cid.Cid
|
||||
var heightDiff int64
|
||||
var theight uint64
|
||||
var theight abi.ChainEpoch
|
||||
if ss.Base != nil {
|
||||
base = ss.Base.Cids()
|
||||
heightDiff = int64(ss.Base.Height())
|
||||
|
@ -10,6 +10,8 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
types "github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
|
||||
"gopkg.in/urfave/cli.v2"
|
||||
)
|
||||
|
||||
@ -44,7 +46,7 @@ var walletNew = &cli.Command{
|
||||
t = "secp256k1"
|
||||
}
|
||||
|
||||
nk, err := api.WalletNew(ctx, t)
|
||||
nk, err := api.WalletNew(ctx, wallet.ActSigType(t))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
"math/rand"
|
||||
"os"
|
||||
"time"
|
||||
@ -59,7 +60,7 @@ var runCmd = &cli.Command{
|
||||
func sendSmallFundsTxs(ctx context.Context, api api.FullNode, from address.Address, rate int) error {
|
||||
var sendSet []address.Address
|
||||
for i := 0; i < 20; i++ {
|
||||
naddr, err := api.WalletNew(ctx, "bls")
|
||||
naddr, err := api.WalletNew(ctx, crypto.SigTypeSecp256k1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/docker/go-units"
|
||||
ffi "github.com/filecoin-project/filecoin-ffi"
|
||||
paramfetch "github.com/filecoin-project/go-paramfetch"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/ipfs/go-datastore"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
@ -32,7 +33,7 @@ import (
|
||||
var log = logging.Logger("lotus-bench")
|
||||
|
||||
type BenchResults struct {
|
||||
SectorSize uint64
|
||||
SectorSize abi.SectorSize
|
||||
|
||||
SealingResults []SealingResult
|
||||
|
||||
@ -139,7 +140,7 @@ func main() {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sectorSize := uint64(sectorSizeInt)
|
||||
sectorSize := abi.SectorSize(sectorSizeInt)
|
||||
|
||||
mds := datastore.NewMapDatastore()
|
||||
cfg := §orbuilder.Config{
|
||||
@ -155,7 +156,7 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
if err := paramfetch.GetParams(build.ParametersJson(), sectorSize); err != nil {
|
||||
if err := paramfetch.GetParams(build.ParametersJson(), uint64(sectorSize)); err != nil {
|
||||
return xerrors.Errorf("getting params: %w", err)
|
||||
}
|
||||
sb, err := sectorbuilder.New(cfg, mds)
|
||||
@ -163,18 +164,16 @@ func main() {
|
||||
return err
|
||||
}
|
||||
|
||||
dataSize := sectorbuilder.UserBytesForSectorSize(sectorSize)
|
||||
|
||||
var sealTimings []SealingResult
|
||||
var sealedSectors []ffi.PublicSectorInfo
|
||||
numSectors := uint64(1)
|
||||
for i := uint64(1); i <= numSectors && robench == ""; i++ {
|
||||
numSectors := abi.SectorNumber(1)
|
||||
for i := abi.SectorNumber(1); i <= numSectors && robench == ""; i++ {
|
||||
start := time.Now()
|
||||
log.Info("Writing piece into sector...")
|
||||
|
||||
r := rand.New(rand.NewSource(100 + int64(i)))
|
||||
|
||||
pi, err := sb.AddPiece(context.TODO(), dataSize, i, r, nil)
|
||||
pi, err := sb.AddPiece(context.TODO(), abi.UnpaddedPieceSize(sectorSize), i, r, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -196,8 +195,8 @@ func main() {
|
||||
precommit := time.Now()
|
||||
|
||||
sealedSectors = append(sealedSectors, ffi.PublicSectorInfo{
|
||||
CommR: pco.CommR,
|
||||
SectorID: i,
|
||||
CommR: pco.CommR,
|
||||
SectorNum: i,
|
||||
})
|
||||
|
||||
seed := sectorbuilder.SealSeed{
|
||||
@ -225,7 +224,7 @@ func main() {
|
||||
|
||||
if !c.Bool("skip-unseal") {
|
||||
log.Info("Unsealing sector")
|
||||
rc, err := sb.ReadPieceFromSealedSector(context.TODO(), 1, 0, dataSize, ticket.TicketBytes[:], commD[:])
|
||||
rc, err := sb.ReadPieceFromSealedSector(context.TODO(), 1, 0, abi.UnpaddedPieceSize(sectorSize), ticket.TicketBytes[:], commD[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -260,7 +259,7 @@ func main() {
|
||||
return err
|
||||
}
|
||||
|
||||
var genmm map[string]genesis.GenesisMiner
|
||||
var genmm map[string]genesis.Miner
|
||||
if err := json.Unmarshal(fdata, &genmm); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -272,15 +271,15 @@ func main() {
|
||||
|
||||
for _, s := range genm.Sectors {
|
||||
sealedSectors = append(sealedSectors, ffi.PublicSectorInfo{
|
||||
CommR: s.CommR,
|
||||
SectorID: s.SectorID,
|
||||
CommR: s.CommR,
|
||||
SectorNum: s.SectorID,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
log.Info("generating election post candidates")
|
||||
sinfos := sectorbuilder.NewSortedPublicSectorInfo(sealedSectors)
|
||||
candidates, err := sb.GenerateEPostCandidates(sinfos, challenge, []uint64{})
|
||||
candidates, err := sb.GenerateEPostCandidates(sinfos, challenge, []abi.SectorNumber{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -355,7 +354,7 @@ func main() {
|
||||
fmt.Printf("unseal: %s (%s)\n", bo.SealingResults[0].Unseal, bps(bo.SectorSize, bo.SealingResults[0].Unseal))
|
||||
}
|
||||
}
|
||||
fmt.Printf("generate candidates: %s (%s)\n", bo.PostGenerateCandidates, bps(bo.SectorSize*uint64(len(bo.SealingResults)), bo.PostGenerateCandidates))
|
||||
fmt.Printf("generate candidates: %s (%s)\n", bo.PostGenerateCandidates, bps(bo.SectorSize*abi.SectorSize(len(bo.SealingResults)), bo.PostGenerateCandidates))
|
||||
fmt.Printf("compute epost proof (cold): %s\n", bo.PostEProofCold)
|
||||
fmt.Printf("compute epost proof (hot): %s\n", bo.PostEProofHot)
|
||||
fmt.Printf("verify epost proof (cold): %s\n", bo.VerifyEPostCold)
|
||||
@ -371,9 +370,9 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
func bps(data uint64, d time.Duration) string {
|
||||
bdata := new(big.Int).SetUint64(data)
|
||||
func bps(data abi.SectorSize, d time.Duration) string {
|
||||
bdata := new(big.Int).SetUint64(uint64(data))
|
||||
bdata = bdata.Mul(bdata, big.NewInt(time.Second.Nanoseconds()))
|
||||
bps := bdata.Div(bdata, big.NewInt(d.Nanoseconds()))
|
||||
return (types.BigInt{bps}).SizeStr() + "/s"
|
||||
return types.SizeStr(types.BigInt{bps}) + "/s"
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
@ -13,7 +12,6 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
@ -267,8 +265,8 @@ create table if not exists deals
|
||||
pieceSize bigint not null,
|
||||
client text not null,
|
||||
provider text not null,
|
||||
expiration decimal not null,
|
||||
duration decimal not null,
|
||||
start decimal not null,
|
||||
end decimal not null,
|
||||
epochPrice decimal not null,
|
||||
collateral decimal not null,
|
||||
constraint deals_pk
|
||||
@ -473,11 +471,11 @@ create temp table mh (like miner_heads excluding constraints) on commit drop;
|
||||
fmt.Sprint(i.psize),
|
||||
i.info.Owner.String(),
|
||||
i.info.Worker.String(),
|
||||
i.info.PeerID.String(),
|
||||
i.info.PeerId.String(),
|
||||
i.info.SectorSize,
|
||||
i.state.Power.String(),
|
||||
i.state.Power.String(), // TODO: SPA
|
||||
i.state.Active,
|
||||
i.state.ElectionPeriodStart,
|
||||
i.state.PoStState.ProvingPeriodStart,
|
||||
i.state.SlashedAt,
|
||||
); err != nil {
|
||||
return err
|
||||
@ -842,7 +840,7 @@ func (st *storage) storeMpoolInclusions(msgs []api.MpoolUpdate) error {
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (st *storage) storeDeals(deals map[string]actors.OnChainDeal) error {
|
||||
func (st *storage) storeDeals(deals map[string]api.MarketDeal) error {
|
||||
tx, err := st.db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -854,7 +852,7 @@ func (st *storage) storeDeals(deals map[string]actors.OnChainDeal) error {
|
||||
return xerrors.Errorf("prep temp: %w", err)
|
||||
}
|
||||
|
||||
stmt, err := tx.Prepare(`copy d (id, pieceref, piecesize, client, "provider", expiration, duration, epochprice, collateral) from stdin `)
|
||||
stmt, err := tx.Prepare(`copy d (id, pieceref, piecesize, client, "provider", "start", "end", epochprice, collateral) from stdin `)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -862,20 +860,20 @@ func (st *storage) storeDeals(deals map[string]actors.OnChainDeal) error {
|
||||
var bloat uint64
|
||||
|
||||
for id, deal := range deals {
|
||||
if len(deal.PieceRef) > 40 {
|
||||
bloat += uint64(len(deal.PieceRef))
|
||||
if len(deal.Proposal.PieceCID.String()) > 100 {
|
||||
bloat += uint64(len(deal.Proposal.PieceCID.String()))
|
||||
continue
|
||||
}
|
||||
if _, err := stmt.Exec(
|
||||
id,
|
||||
hex.EncodeToString(deal.PieceRef),
|
||||
deal.PieceSize,
|
||||
deal.Client.String(),
|
||||
deal.Provider.String(),
|
||||
fmt.Sprint(deal.ProposalExpiration),
|
||||
fmt.Sprint(deal.Duration),
|
||||
deal.StoragePricePerEpoch.String(),
|
||||
deal.StorageCollateral.String(),
|
||||
deal.Proposal.PieceCID.String(),
|
||||
deal.Proposal.PieceSize,
|
||||
deal.Proposal.Client.String(),
|
||||
deal.Proposal.Provider.String(),
|
||||
fmt.Sprint(deal.Proposal.StartEpoch),
|
||||
fmt.Sprint(deal.Proposal.EndEpoch),
|
||||
deal.Proposal.StoragePricePerEpoch.String(),
|
||||
deal.Proposal.ProviderCollateral.String(),
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -915,12 +913,12 @@ func (st *storage) storeDeals(deals map[string]actors.OnChainDeal) error {
|
||||
}
|
||||
|
||||
for id, deal := range deals {
|
||||
if deal.ActivationEpoch == 0 {
|
||||
if deal.State.SectorStartEpoch <= 0 {
|
||||
continue
|
||||
}
|
||||
if _, err := stmt.Exec(
|
||||
id,
|
||||
deal.ActivationEpoch,
|
||||
deal.State.SectorStartEpoch,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user