specs-actors: Import miner/power/cron/paych code
This commit is contained in:
parent
07ae3e49a3
commit
91ca4a841a
@ -1,48 +1,9 @@
|
||||
package actors
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/cron"
|
||||
)
|
||||
|
||||
type CronActor struct{}
|
||||
type CronActor = cron.Actor
|
||||
|
||||
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
|
||||
}
|
||||
type CronActorState = cron.State
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,302 +1,9 @@
|
||||
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"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||
)
|
||||
|
||||
type PaymentChannelActor struct{}
|
||||
type PaymentChannelActor = paych.Actor
|
||||
|
||||
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 uint64(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 = uint64(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 uint64(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 nil, nil
|
||||
}
|
||||
type PaymentChannelActorState = paych.State
|
||||
|
@ -1,832 +1,12 @@
|
||||
package actors
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/filecoin-project/go-amt-ipld/v2"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
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"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
||||
)
|
||||
|
||||
type StoragePowerActor struct{}
|
||||
type StoragePowerActor = power.Actor
|
||||
|
||||
type spaMethods struct {
|
||||
Constructor uint64
|
||||
CreateStorageMiner uint64
|
||||
ArbitrateConsensusFault uint64
|
||||
UpdateStorage uint64
|
||||
GetTotalStorage uint64
|
||||
PowerLookup uint64
|
||||
IsValidMiner uint64
|
||||
PledgeCollateralForSize uint64
|
||||
CheckProofSubmissions uint64
|
||||
}
|
||||
var SPAMethods = builtin.MethodsPower
|
||||
|
||||
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 abi.SectorSize
|
||||
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 nil, 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")
|
||||
}
|
||||
|
||||
|
||||
return nil, 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
|
||||
}
|
||||
|
||||
return nil, 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 < uint64(vmctx.BlockHeight()); i++ {
|
||||
height := i + 1
|
||||
|
||||
err := checkProofSubmissionsAtH(vmctx, &self, height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
self.LastMinerCheck = uint64(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)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
type StoragePowerState = power.State
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -14,6 +14,7 @@ import (
|
||||
"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/builtin"
|
||||
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
@ -178,11 +179,12 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
|
||||
}
|
||||
|
||||
// all block miners created a valid post, go update the actor state
|
||||
panic("sys actor call")
|
||||
postSubmitMsg := &types.Message{
|
||||
From: actors.NetworkAddress,
|
||||
Nonce: netact.Nonce,
|
||||
To: b.Miner,
|
||||
Method: actors.MAMethods.SubmitElectionPoSt,
|
||||
Method: builtin.MethodsMiner.OnVerifiedElectionPoSt,
|
||||
GasPrice: types.NewInt(0),
|
||||
GasLimit: types.NewInt(10000000000),
|
||||
Value: types.NewInt(0),
|
||||
@ -274,7 +276,7 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
|
||||
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 {
|
||||
|
@ -23,10 +23,11 @@ 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)
|
||||
|
||||
panic("TODO")
|
||||
ret, err := cs.call(ctx, &types.Message{
|
||||
From: actors.StoragePowerAddress,
|
||||
To: actors.StoragePowerAddress,
|
||||
Method: actors.SPAMethods.GetTotalStorage,
|
||||
Method: 999, // actors.SPAMethods.GetTotalStorage,
|
||||
}, ts)
|
||||
if err != nil {
|
||||
return types.EmptyInt, xerrors.Errorf("failed to get total power from chain: %w", err)
|
||||
|
@ -680,7 +680,6 @@ func (t *Message) UnmarshalCBOR(r io.Reader) error {
|
||||
if maj != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type for uint64 field")
|
||||
}
|
||||
t.Method = uint64(extra)
|
||||
// t.Params ([]uint8) (slice)
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
|
@ -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,7 +23,7 @@ type Message struct {
|
||||
GasPrice BigInt
|
||||
GasLimit BigInt
|
||||
|
||||
Method uint64 // TODO: decide
|
||||
Method abi.MethodNum
|
||||
Params []byte
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ type VMContext interface {
|
||||
Message() *Message
|
||||
Origin() address.Address
|
||||
Ipld() cbor.IpldStore
|
||||
Send(to address.Address, method uint64, value BigInt, params []byte) ([]byte, aerrors.ActorError)
|
||||
Send(to address.Address, method abi.MethodNum, value BigInt, params []byte) ([]byte, aerrors.ActorError)
|
||||
BlockHeight() abi.ChainEpoch
|
||||
GasUsed() BigInt
|
||||
Storage() Storage
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/ipfs/go-cid"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
@ -47,7 +48,7 @@ func NewInvoker() *invoker {
|
||||
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 {
|
||||
return nil, aerrors.Newf(254, "cannot invoke methods on account actors")
|
||||
@ -58,7 +59,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)
|
||||
|
@ -128,7 +128,7 @@ func (rs *runtimeShim) Send(to address.Address, method abi.MethodNum, m runtime.
|
||||
rs.Abort(exitcode.SysErrInvalidParameters, "failed to marshal input parameters: %s", err)
|
||||
}
|
||||
|
||||
ret, err := rs.vmctx.Send(to, uint64(method), types.BigInt(value), buf.Bytes())
|
||||
ret, err := rs.vmctx.Send(to, method, types.BigInt(value), buf.Bytes())
|
||||
if err != nil {
|
||||
if err.IsFatal() {
|
||||
panic(err)
|
||||
|
@ -134,7 +134,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() {
|
||||
@ -627,7 +627,7 @@ 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() {
|
||||
|
Loading…
Reference in New Issue
Block a user