2019-07-16 11:35:56 +00:00
|
|
|
package actors_test
|
|
|
|
|
|
|
|
import (
|
2019-09-12 04:12:35 +00:00
|
|
|
"context"
|
|
|
|
"fmt"
|
2019-07-16 11:35:56 +00:00
|
|
|
"testing"
|
|
|
|
|
2019-10-18 04:47:41 +00:00
|
|
|
"github.com/filecoin-project/lotus/build"
|
2019-09-12 23:48:03 +00:00
|
|
|
cbg "github.com/whyrusleeping/cbor-gen"
|
2019-09-10 02:05:24 +00:00
|
|
|
|
2019-10-18 04:47:41 +00:00
|
|
|
. "github.com/filecoin-project/lotus/chain/actors"
|
|
|
|
"github.com/filecoin-project/lotus/chain/address"
|
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
|
|
|
"github.com/filecoin-project/lotus/chain/vm"
|
|
|
|
"github.com/filecoin-project/lotus/chain/wallet"
|
2019-08-27 15:01:17 +00:00
|
|
|
|
2019-09-12 04:12:35 +00:00
|
|
|
cid "github.com/ipfs/go-cid"
|
2019-09-12 23:48:03 +00:00
|
|
|
hamt "github.com/ipfs/go-hamt-ipld"
|
2019-09-13 01:06:06 +00:00
|
|
|
bstore "github.com/ipfs/go-ipfs-blockstore"
|
2019-07-16 11:35:56 +00:00
|
|
|
cbor "github.com/ipfs/go-ipld-cbor"
|
2019-09-12 04:12:35 +00:00
|
|
|
mh "github.com/multiformats/go-multihash"
|
2019-08-27 15:01:17 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
2019-07-16 11:35:56 +00:00
|
|
|
)
|
|
|
|
|
2019-09-12 04:12:35 +00:00
|
|
|
func TestStorageMarketCreateAndSlashMiner(t *testing.T) {
|
2019-08-27 15:01:17 +00:00
|
|
|
var ownerAddr, workerAddr address.Address
|
2019-07-16 11:35:56 +00:00
|
|
|
|
2019-08-27 15:01:17 +00:00
|
|
|
opts := []HarnessOpt{
|
2019-09-12 23:48:03 +00:00
|
|
|
HarnessAddr(&ownerAddr, 1000000),
|
2019-08-29 18:20:59 +00:00
|
|
|
HarnessAddr(&workerAddr, 100000),
|
2019-08-27 15:01:17 +00:00
|
|
|
}
|
2019-07-17 14:30:55 +00:00
|
|
|
|
2019-08-29 18:20:59 +00:00
|
|
|
h := NewHarness(t, opts...)
|
2019-07-17 16:00:59 +00:00
|
|
|
|
2019-08-27 15:01:17 +00:00
|
|
|
var minerAddr address.Address
|
|
|
|
{
|
2019-09-12 23:48:03 +00:00
|
|
|
// cheating the bootstrapping problem
|
2019-09-13 01:06:06 +00:00
|
|
|
cheatStorageMarketTotal(t, h.vm, h.cs.Blockstore())
|
2019-09-12 23:48:03 +00:00
|
|
|
|
2019-10-19 08:06:41 +00:00
|
|
|
ret, _ := h.InvokeWithValue(t, ownerAddr, StoragePowerAddress, SPAMethods.CreateStorageMiner,
|
2019-09-12 23:48:03 +00:00
|
|
|
types.NewInt(500000),
|
2019-09-10 23:03:17 +00:00
|
|
|
&CreateStorageMinerParams{
|
2019-08-27 15:01:17 +00:00
|
|
|
Owner: ownerAddr,
|
|
|
|
Worker: workerAddr,
|
2019-10-16 07:07:16 +00:00
|
|
|
SectorSize: build.SectorSizes[0],
|
2019-08-27 15:01:17 +00:00
|
|
|
PeerID: "fakepeerid",
|
|
|
|
})
|
|
|
|
ApplyOK(t, ret)
|
|
|
|
var err error
|
|
|
|
minerAddr, err = address.NewFromBytes(ret.Return)
|
|
|
|
assert.NoError(t, err)
|
2019-07-16 11:35:56 +00:00
|
|
|
}
|
|
|
|
|
2019-08-27 15:01:17 +00:00
|
|
|
{
|
2019-11-13 23:00:11 +00:00
|
|
|
ret, _ := h.Invoke(t, ownerAddr, StoragePowerAddress, SPAMethods.IsValidMiner,
|
2019-11-14 16:14:52 +00:00
|
|
|
&IsValidMinerParam{Addr: minerAddr})
|
2019-08-27 15:01:17 +00:00
|
|
|
ApplyOK(t, ret)
|
2019-07-16 16:49:48 +00:00
|
|
|
|
2019-08-27 15:01:17 +00:00
|
|
|
var output bool
|
|
|
|
err := cbor.DecodeInto(ret.Return, &output)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("error decoding: %+v", err)
|
|
|
|
}
|
|
|
|
|
2019-11-13 23:35:58 +00:00
|
|
|
if output { // TODO: some state hacking to make this true again
|
|
|
|
t.Fatalf("%s is miner but IsValidMiner call returned true", minerAddr)
|
2019-08-27 15:01:17 +00:00
|
|
|
}
|
2019-08-06 04:17:50 +00:00
|
|
|
}
|
|
|
|
|
2019-08-27 15:01:17 +00:00
|
|
|
{
|
2019-10-19 08:06:41 +00:00
|
|
|
ret, _ := h.Invoke(t, ownerAddr, StoragePowerAddress, SPAMethods.PowerLookup,
|
2019-09-10 23:03:17 +00:00
|
|
|
&PowerLookupParams{Miner: minerAddr})
|
2019-08-27 15:01:17 +00:00
|
|
|
ApplyOK(t, ret)
|
|
|
|
power := types.BigFromBytes(ret.Return)
|
|
|
|
|
|
|
|
if types.BigCmp(power, types.NewInt(0)) != 0 {
|
|
|
|
t.Fatalf("power should be zero, is: %s", power)
|
|
|
|
}
|
2019-08-06 04:17:50 +00:00
|
|
|
}
|
|
|
|
|
2019-08-27 15:01:17 +00:00
|
|
|
{
|
|
|
|
ret, _ := h.Invoke(t, ownerAddr, minerAddr, MAMethods.GetOwner, nil)
|
|
|
|
ApplyOK(t, ret)
|
|
|
|
oA, err := address.NewFromBytes(ret.Return)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, ownerAddr, oA, "return from GetOwner should be equal to the owner")
|
2019-07-16 11:35:56 +00:00
|
|
|
}
|
2019-09-12 04:12:35 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
b1 := fakeBlock(t, minerAddr, 100)
|
|
|
|
b2 := fakeBlock(t, minerAddr, 101)
|
|
|
|
|
|
|
|
signBlock(t, h.w, workerAddr, b1)
|
|
|
|
signBlock(t, h.w, workerAddr, b2)
|
|
|
|
|
2019-10-19 08:06:41 +00:00
|
|
|
ret, _ := h.Invoke(t, ownerAddr, StoragePowerAddress, SPAMethods.ArbitrateConsensusFault,
|
2019-09-13 01:06:06 +00:00
|
|
|
&ArbitrateConsensusFaultParams{
|
2019-09-12 04:12:35 +00:00
|
|
|
Block1: b1,
|
|
|
|
Block2: b2,
|
|
|
|
})
|
|
|
|
ApplyOK(t, ret)
|
|
|
|
}
|
2019-09-12 23:48:03 +00:00
|
|
|
|
|
|
|
{
|
2019-10-19 08:06:41 +00:00
|
|
|
ret, _ := h.Invoke(t, ownerAddr, StoragePowerAddress, SPAMethods.PowerLookup,
|
2019-09-12 23:48:03 +00:00
|
|
|
&PowerLookupParams{Miner: minerAddr})
|
|
|
|
assert.Equal(t, ret.ExitCode, byte(1))
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2019-11-14 16:14:52 +00:00
|
|
|
ret, _ := h.Invoke(t, ownerAddr, StoragePowerAddress, SPAMethods.IsValidMiner, &IsValidMinerParam{minerAddr})
|
2019-09-12 23:48:03 +00:00
|
|
|
ApplyOK(t, ret)
|
|
|
|
assert.Equal(t, ret.Return, cbg.CborBoolFalse)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-13 01:06:06 +00:00
|
|
|
func cheatStorageMarketTotal(t *testing.T, vm *vm.VM, bs bstore.Blockstore) {
|
2019-09-12 23:48:03 +00:00
|
|
|
t.Helper()
|
|
|
|
|
2019-10-19 08:06:41 +00:00
|
|
|
sma, err := vm.StateTree().GetActor(StoragePowerAddress)
|
2019-09-12 23:48:03 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2019-09-13 01:06:06 +00:00
|
|
|
cst := hamt.CSTFromBstore(bs)
|
2019-09-12 23:48:03 +00:00
|
|
|
|
2019-10-11 22:59:36 +00:00
|
|
|
var smastate StoragePowerState
|
2019-09-12 23:48:03 +00:00
|
|
|
if err := cst.Get(context.TODO(), sma.Head, &smastate); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
smastate.TotalStorage = types.NewInt(10000)
|
|
|
|
|
|
|
|
c, err := cst.Put(context.TODO(), &smastate)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
sma.Head = c
|
|
|
|
|
2019-10-19 08:06:41 +00:00
|
|
|
if err := vm.StateTree().SetActor(StoragePowerAddress, sma); err != nil {
|
2019-09-12 23:48:03 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2019-09-12 04:12:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func fakeBlock(t *testing.T, minerAddr address.Address, ts uint64) *types.BlockHeader {
|
|
|
|
c := fakeCid(t, 1)
|
2019-09-27 23:55:15 +00:00
|
|
|
return &types.BlockHeader{Height: 5, Miner: minerAddr, Timestamp: ts, ParentStateRoot: c, Messages: c, ParentMessageReceipts: c, BLSAggregate: types.Signature{Type: types.KTBLS}}
|
2019-09-12 04:12:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func fakeCid(t *testing.T, s int) cid.Cid {
|
|
|
|
t.Helper()
|
|
|
|
c, err := cid.NewPrefixV1(cid.Raw, mh.IDENTITY).Sum([]byte(fmt.Sprintf("%d", s)))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
|
|
|
func signBlock(t *testing.T, w *wallet.Wallet, worker address.Address, blk *types.BlockHeader) {
|
|
|
|
t.Helper()
|
|
|
|
sb, err := blk.SigningBytes()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
sig, err := w.Sign(context.TODO(), worker, sb)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
blk.BlockSig = *sig
|
2019-07-16 11:35:56 +00:00
|
|
|
}
|