Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into feat/break-on-stop-…
Browse files Browse the repository at this point in the history
…sleep
  • Loading branch information
magik6k committed Sep 16, 2020
2 parents a6b7791 + ecd115c commit 3b00c68
Show file tree
Hide file tree
Showing 18 changed files with 308 additions and 71 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
/lotus-stats
/lotus-bench
/lotus-gateway
/lotus-pcr
/bench.json
/lotuspond/front/node_modules
/lotuspond/front/build
Expand Down
2 changes: 1 addition & 1 deletion chain/stmgr/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcs beacon.Schedule

sectors, err := GetSectorsForWinningPoSt(ctx, pv, sm, lbst, maddr, prand)
if err != nil {
return nil, xerrors.Errorf("getting wpost proving set: %w", err)
return nil, xerrors.Errorf("getting winning post proving set: %w", err)
}

if len(sectors) == 0 {
Expand Down
25 changes: 4 additions & 21 deletions chain/store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"github.com/filecoin-project/specs-actors/actors/util/adt"

"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/journal"
bstore "github.com/filecoin-project/lotus/lib/blockstore"
Expand Down Expand Up @@ -767,32 +766,16 @@ type BlockMessages struct {
func (cs *ChainStore) BlockMsgsForTipset(ts *types.TipSet) ([]BlockMessages, error) {
applied := make(map[address.Address]uint64)

cst := cbor.NewCborStore(cs.bs)
st, err := state.LoadStateTree(cst, ts.Blocks()[0].ParentStateRoot)
if err != nil {
return nil, xerrors.Errorf("failed to load state tree")
}

preloadAddr := func(a address.Address) error {
if _, ok := applied[a]; !ok {
act, err := st.GetActor(a)
if err != nil {
return err
}

applied[a] = act.Nonce
}
return nil
}

selectMsg := func(m *types.Message) (bool, error) {
if err := preloadAddr(m.From); err != nil {
return false, err
// The first match for a sender is guaranteed to have correct nonce -- the block isn't valid otherwise
if _, ok := applied[m.From]; !ok {
applied[m.From] = m.Nonce
}

if applied[m.From] != m.Nonce {
return false, nil
}

applied[m.From]++

return true, nil
Expand Down
2 changes: 1 addition & 1 deletion chain/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -991,7 +991,7 @@ func (syncer *Syncer) VerifyWinningPoStProof(ctx context.Context, h *types.Block

rand, err := store.DrawRandomness(rbase.Data, crypto.DomainSeparationTag_WinningPoStChallengeSeed, h.Height, buf.Bytes())
if err != nil {
return xerrors.Errorf("failed to get randomness for verifying winningPost proof: %w", err)
return xerrors.Errorf("failed to get randomness for verifying winning post proof: %w", err)
}

mid, err := address.IDFromAddress(h.Miner)
Expand Down
43 changes: 43 additions & 0 deletions chain/sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,49 @@ func TestDuplicateNonce(t *testing.T) {
require.Equal(t, includedMsg, mft[0].VMMessage().Cid(), "messages for tipset didn't contain expected message")
}

// This test asserts that a block that includes a message with bad nonce can't be synced. A nonce is "bad" if it can't
// be applied on the parent state.
func TestBadNonce(t *testing.T) {
H := 10
tu := prepSyncTest(t, H)

base := tu.g.CurTipset

// Produce a message from the banker with a bad nonce
makeBadMsg := func() *types.SignedMessage {

ba, err := tu.nds[0].StateGetActor(context.TODO(), tu.g.Banker(), base.TipSet().Key())
require.NoError(t, err)
msg := types.Message{
To: tu.g.Banker(),
From: tu.g.Banker(),

Nonce: ba.Nonce + 5,

Value: types.NewInt(1),

Method: 0,

GasLimit: 100_000_000,
GasFeeCap: types.NewInt(0),
GasPremium: types.NewInt(0),
}

sig, err := tu.g.Wallet().Sign(context.TODO(), tu.g.Banker(), msg.Cid().Bytes())
require.NoError(t, err)

return &types.SignedMessage{
Message: msg,
Signature: *sig,
}
}

msgs := make([][]*types.SignedMessage, 1)
msgs[0] = []*types.SignedMessage{makeBadMsg()}

tu.mineOnBlock(base, 0, []int{0}, true, true, msgs)
}

func BenchmarkSyncBasic(b *testing.B) {
for i := 0; i < b.N; i++ {
runSyncBenchLength(b, 100)
Expand Down
19 changes: 12 additions & 7 deletions chain/vm/burn.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ type GasOutputs struct {
GasBurned int64
}

// ZeroGasOutputs returns a logically zeroed GasOutputs.
func ZeroGasOutputs() GasOutputs {
return GasOutputs{
BaseFeeBurn: big.Zero(),
OverEstimationBurn: big.Zero(),
MinerPenalty: big.Zero(),
MinerTip: big.Zero(),
Refund: big.Zero(),
}
}

// ComputeGasOverestimationBurn computes amount of gas to be refunded and amount of gas to be burned
// Result is (refund, burn)
func ComputeGasOverestimationBurn(gasUsed, gasLimit int64) (int64, int64) {
Expand Down Expand Up @@ -58,13 +69,7 @@ func ComputeGasOverestimationBurn(gasUsed, gasLimit int64) (int64, int64) {

func ComputeGasOutputs(gasUsed, gasLimit int64, baseFee, feeCap, gasPremium abi.TokenAmount) GasOutputs {
gasUsedBig := big.NewInt(gasUsed)
out := GasOutputs{
BaseFeeBurn: big.Zero(),
OverEstimationBurn: big.Zero(),
MinerPenalty: big.Zero(),
MinerTip: big.Zero(),
Refund: big.Zero(),
}
out := ZeroGasOutputs()

baseFeeToPay := baseFee
if baseFee.Cmp(feeCap.Int) > 0 {
Expand Down
30 changes: 15 additions & 15 deletions chain/vm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,14 +355,14 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
msgGasCost := msgGas.Total()
// this should never happen, but is currently still exercised by some tests
if msgGasCost > msg.GasLimit {
gasOutputs := ZeroGasOutputs()
gasOutputs.MinerPenalty = types.BigMul(vm.baseFee, abi.NewTokenAmount(msgGasCost))
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
ExitCode: exitcode.SysErrOutOfGas,
GasUsed: 0,
},
GasCosts: GasOutputs{
MinerPenalty: types.BigMul(vm.baseFee, abi.NewTokenAmount(msgGasCost)),
},
GasCosts: gasOutputs,
Duration: time.Since(start),
}, nil
}
Expand All @@ -374,15 +374,15 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
// this should never happen, but is currently still exercised by some tests
if err != nil {
if xerrors.Is(err, types.ErrActorNotFound) {
gasOutputs := ZeroGasOutputs()
gasOutputs.MinerPenalty = minerPenaltyAmount
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
ExitCode: exitcode.SysErrSenderInvalid,
GasUsed: 0,
},
ActorErr: aerrors.Newf(exitcode.SysErrSenderInvalid, "actor not found: %s", msg.From),
GasCosts: GasOutputs{
MinerPenalty: minerPenaltyAmount,
},
GasCosts: gasOutputs,
Duration: time.Since(start),
}, nil
}
Expand All @@ -391,20 +391,22 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,

// this should never happen, but is currently still exercised by some tests
if !fromActor.Code.Equals(builtin.AccountActorCodeID) {
gasOutputs := ZeroGasOutputs()
gasOutputs.MinerPenalty = minerPenaltyAmount
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
ExitCode: exitcode.SysErrSenderInvalid,
GasUsed: 0,
},
ActorErr: aerrors.Newf(exitcode.SysErrSenderInvalid, "send from not account actor: %s", fromActor.Code),
GasCosts: GasOutputs{
MinerPenalty: minerPenaltyAmount,
},
GasCosts: gasOutputs,
Duration: time.Since(start),
}, nil
}

if msg.Nonce != fromActor.Nonce {
gasOutputs := ZeroGasOutputs()
gasOutputs.MinerPenalty = minerPenaltyAmount
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
ExitCode: exitcode.SysErrSenderStateInvalid,
Expand All @@ -413,25 +415,23 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
ActorErr: aerrors.Newf(exitcode.SysErrSenderStateInvalid,
"actor nonce invalid: msg:%d != state:%d", msg.Nonce, fromActor.Nonce),

GasCosts: GasOutputs{
MinerPenalty: minerPenaltyAmount,
},
GasCosts: gasOutputs,
Duration: time.Since(start),
}, nil
}

gascost := types.BigMul(types.NewInt(uint64(msg.GasLimit)), msg.GasFeeCap)
if fromActor.Balance.LessThan(gascost) {
gasOutputs := ZeroGasOutputs()
gasOutputs.MinerPenalty = minerPenaltyAmount
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
ExitCode: exitcode.SysErrSenderStateInvalid,
GasUsed: 0,
},
ActorErr: aerrors.Newf(exitcode.SysErrSenderStateInvalid,
"actor balance less than needed: %s < %s", types.FIL(fromActor.Balance), types.FIL(gascost)),
GasCosts: GasOutputs{
MinerPenalty: minerPenaltyAmount,
},
GasCosts: gasOutputs,
Duration: time.Since(start),
}, nil
}
Expand Down
7 changes: 7 additions & 0 deletions cli/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"text/tabwriter"
"time"

"github.com/filecoin-project/specs-actors/actors/builtin"

tm "github.com/buger/goterm"
"github.com/docker/go-units"
"github.com/fatih/color"
Expand Down Expand Up @@ -527,6 +529,11 @@ func interactiveDeal(cctx *cli.Context) error {
continue
}

if days < int(build.MinDealDuration/builtin.EpochsInDay) {
printErr(xerrors.Errorf("minimum duration is %d days", int(build.MinDealDuration/builtin.EpochsInDay)))
continue
}

state = "miner"
case "miner":
fmt.Print("Miner Address (t0..): ")
Expand Down
4 changes: 2 additions & 2 deletions cmd/lotus-bench/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ var sealBenchCmd = &cli.Command{
return err
}
if !ok {
log.Error("post verification failed")
log.Error("window post verification failed")
}

verifyWindowpost1 := time.Now()
Expand All @@ -403,7 +403,7 @@ var sealBenchCmd = &cli.Command{
return err
}
if !ok {
log.Error("post verification failed")
log.Error("window post verification failed")
}

verifyWindowpost2 := time.Now()
Expand Down
29 changes: 29 additions & 0 deletions conformance/chaos/actor.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ const (
// MethodAbortWith is the identifier for the method that panics optionally with
// a passed exit code.
MethodAbortWith
// MethodInspectRuntime is the identifier for the method that returns the
// current runtime values.
MethodInspectRuntime
)

// Exports defines the methods this actor exposes publicly.
Expand All @@ -77,6 +80,7 @@ func (a Actor) Exports() []interface{} {
MethodSend: a.Send,
MethodMutateState: a.MutateState,
MethodAbortWith: a.AbortWith,
MethodInspectRuntime: a.InspectRuntime,
}
}

Expand Down Expand Up @@ -247,3 +251,28 @@ func (a Actor) AbortWith(rt runtime.Runtime, args *AbortWithArgs) *abi.EmptyValu
}
return nil
}

// InspectRuntimeReturn is the return value for the Actor.InspectRuntime method.
type InspectRuntimeReturn struct {
Caller address.Address
Receiver address.Address
ValueReceived abi.TokenAmount
CurrEpoch abi.ChainEpoch
CurrentBalance abi.TokenAmount
State State
}

// InspectRuntime returns a copy of the serializable values available in the Runtime.
func (a Actor) InspectRuntime(rt runtime.Runtime, _ *abi.EmptyValue) *InspectRuntimeReturn {
rt.ValidateImmediateCallerAcceptAny()
var st State
rt.StateReadonly(&st)
return &InspectRuntimeReturn{
Caller: rt.Caller(),
Receiver: rt.Receiver(),
ValueReceived: rt.ValueReceived(),
CurrEpoch: rt.CurrEpoch(),
CurrentBalance: rt.CurrentBalance(),
State: st,
}
}
26 changes: 26 additions & 0 deletions conformance/chaos/actor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/support/mock"
atesting "github.com/filecoin-project/specs-actors/support/testing"
)
Expand Down Expand Up @@ -151,3 +152,28 @@ func TestAbortWithUncontrolled(t *testing.T) {
})
rt.Verify()
}

func TestInspectRuntime(t *testing.T) {
caller := atesting.NewIDAddr(t, 100)
receiver := atesting.NewIDAddr(t, 101)
builder := mock.NewBuilder(context.Background(), receiver)

rt := builder.Build(t)
rt.SetCaller(caller, builtin.AccountActorCodeID)
rt.StateCreate(&State{})
var a Actor

rt.ExpectValidateCallerAny()
ret := rt.Call(a.InspectRuntime, abi.Empty)
rtr, ok := ret.(*InspectRuntimeReturn)
if !ok {
t.Fatal("invalid return value")
}
if rtr.Caller != caller {
t.Fatal("unexpected runtime caller")
}
if rtr.Receiver != receiver {
t.Fatal("unexpected runtime receiver")
}
rt.Verify()
}
Loading

0 comments on commit 3b00c68

Please sign in to comment.