diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index 7a9993bb7..5c1d43129 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -86,6 +86,7 @@ func init() { } ExampleValues[reflect.TypeOf(addr)] = addr + ExampleValues[reflect.TypeOf(&addr)] = &addr pid, err := peer.Decode("12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf") if err != nil { diff --git a/api/types.go b/api/types.go index 625b770c5..8db5120a8 100644 --- a/api/types.go +++ b/api/types.go @@ -299,6 +299,7 @@ type MinerInfo struct { SectorSize abi.SectorSize WindowPoStPartitionSectors uint64 ConsensusFaultElapsed abi.ChainEpoch + PendingOwnerAddress *address.Address Beneficiary address.Address BeneficiaryTerm *miner.BeneficiaryTerm PendingBeneficiaryTerm *miner.PendingBeneficiaryChange diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 2db0ffd7c..57f88c609 100644 Binary files a/build/openrpc/full.json.gz and b/build/openrpc/full.json.gz differ diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz index d24728864..abf3dc973 100644 Binary files a/build/openrpc/gateway.json.gz and b/build/openrpc/gateway.json.gz differ diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 1272f0691..d403bd185 100644 Binary files a/build/openrpc/miner.json.gz and b/build/openrpc/miner.json.gz differ diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index a08d3a53d..0cec0db81 100644 Binary files a/build/openrpc/worker.json.gz and b/build/openrpc/worker.json.gz differ diff --git a/chain/gen/slashfilter/slashfilter.go b/chain/gen/slashfilter/slashfilter.go index 986586267..6221818d4 100644 --- a/chain/gen/slashfilter/slashfilter.go +++ b/chain/gen/slashfilter/slashfilter.go @@ -11,7 +11,6 @@ import ( "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/types" ) @@ -28,10 +27,6 @@ func New(dstore ds.Batching) *SlashFilter { } func (f *SlashFilter) MinedBlock(ctx context.Context, bh *types.BlockHeader, parentEpoch abi.ChainEpoch) error { - if build.IsNearUpgrade(bh.Height, build.UpgradeOrangeHeight) { - return nil - } - epochKey := ds.NewKey(fmt.Sprintf("/%s/%d", bh.Miner, bh.Height)) { // double-fork mining (2 blocks at one epoch) diff --git a/chain/messagepool/selection_test.go b/chain/messagepool/selection_test.go index c3a5c6d6f..17e0f34f4 100644 --- a/chain/messagepool/selection_test.go +++ b/chain/messagepool/selection_test.go @@ -13,6 +13,7 @@ import ( "os" "sort" "testing" + "time" "github.com/ipfs/go-cid" "github.com/ipfs/go-datastore" @@ -1690,3 +1691,188 @@ readLoop: } } + +func TestRealWorldSelectionTiming(t *testing.T) { + //stm: @TOKEN_WALLET_NEW_001, @TOKEN_WALLET_SIGN_001, @CHAIN_MEMPOOL_SELECT_001 + + // load test-messages.json.gz and rewrite the messages so that + // 1) we map each real actor to a test actor so that we can sign the messages + // 2) adjust the nonces so that they start from 0 + file, err := os.Open("test-messages2.json.gz") + if err != nil { + t.Fatal(err) + } + + gzr, err := gzip.NewReader(file) + if err != nil { + t.Fatal(err) + } + + dec := json.NewDecoder(gzr) + + var msgs []*types.SignedMessage + baseNonces := make(map[address.Address]uint64) + +readLoop: + for { + m := new(types.SignedMessage) + err := dec.Decode(m) + switch err { + case nil: + msgs = append(msgs, m) + nonce, ok := baseNonces[m.Message.From] + if !ok || m.Message.Nonce < nonce { + baseNonces[m.Message.From] = m.Message.Nonce + } + + case io.EOF: + break readLoop + + default: + t.Fatal(err) + } + } + + actorMap := make(map[address.Address]address.Address) + actorWallets := make(map[address.Address]api.Wallet) + + for _, m := range msgs { + baseNonce := baseNonces[m.Message.From] + + localActor, ok := actorMap[m.Message.From] + if !ok { + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + if err != nil { + t.Fatal(err) + } + + a, err := w.WalletNew(context.Background(), types.KTSecp256k1) + if err != nil { + t.Fatal(err) + } + + actorMap[m.Message.From] = a + actorWallets[a] = w + localActor = a + } + + w, ok := actorWallets[localActor] + if !ok { + t.Fatalf("failed to lookup wallet for actor %s", localActor) + } + + m.Message.From = localActor + m.Message.Nonce -= baseNonce + + sig, err := w.WalletSign(context.TODO(), localActor, m.Message.Cid().Bytes(), api.MsgMeta{}) + if err != nil { + t.Fatal(err) + } + + m.Signature = *sig + } + + mp, tma := makeTestMpool() + + block := tma.nextBlockWithHeight(uint64(build.UpgradeHyggeHeight) + 10) + ts := mock.TipSet(block) + tma.applyBlock(t, block) + + for _, a := range actorMap { + tma.setBalance(a, 1000000) + } + + tma.baseFee = types.NewInt(800_000_000) + + sort.Slice(msgs, func(i, j int) bool { + return msgs[i].Message.Nonce < msgs[j].Message.Nonce + }) + + // add the messages + for _, m := range msgs { + mustAdd(t, mp, m) + } + + // do message selection and check block packing + minGasLimit := int64(0.9 * float64(build.BlockGasLimit)) + + // greedy first + start := time.Now() + selected, err := mp.SelectMessages(context.Background(), ts, 1.0) + if err != nil { + t.Fatal(err) + } + t.Logf("selected %d messages in %s", len(selected), time.Since(start)) + + gasLimit := int64(0) + for _, m := range selected { + gasLimit += m.Message.GasLimit + } + if gasLimit < minGasLimit { + t.Fatalf("failed to pack with tq=1.0; packed %d, minimum packing: %d", gasLimit, minGasLimit) + } + + // high quality ticket + start = time.Now() + selected, err = mp.SelectMessages(context.Background(), ts, .8) + if err != nil { + t.Fatal(err) + } + t.Logf("selected %d messages in %s", len(selected), time.Since(start)) + + gasLimit = int64(0) + for _, m := range selected { + gasLimit += m.Message.GasLimit + } + if gasLimit < minGasLimit { + t.Fatalf("failed to pack with tq=0.8; packed %d, minimum packing: %d", gasLimit, minGasLimit) + } + + // mid quality ticket + start = time.Now() + selected, err = mp.SelectMessages(context.Background(), ts, .4) + if err != nil { + t.Fatal(err) + } + t.Logf("selected %d messages in %s", len(selected), time.Since(start)) + + gasLimit = int64(0) + for _, m := range selected { + gasLimit += m.Message.GasLimit + } + if gasLimit < minGasLimit { + t.Fatalf("failed to pack with tq=0.4; packed %d, minimum packing: %d", gasLimit, minGasLimit) + } + + // low quality ticket + start = time.Now() + selected, err = mp.SelectMessages(context.Background(), ts, .1) + if err != nil { + t.Fatal(err) + } + t.Logf("selected %d messages in %s", len(selected), time.Since(start)) + + gasLimit = int64(0) + for _, m := range selected { + gasLimit += m.Message.GasLimit + } + if gasLimit < minGasLimit { + t.Fatalf("failed to pack with tq=0.1; packed %d, minimum packing: %d", gasLimit, minGasLimit) + } + + // very low quality ticket + start = time.Now() + selected, err = mp.SelectMessages(context.Background(), ts, .01) + if err != nil { + t.Fatal(err) + } + t.Logf("selected %d messages in %s", len(selected), time.Since(start)) + + gasLimit = int64(0) + for _, m := range selected { + gasLimit += m.Message.GasLimit + } + if gasLimit < minGasLimit { + t.Fatalf("failed to pack with tq=0.01; packed %d, minimum packing: %d", gasLimit, minGasLimit) + } +} diff --git a/chain/messagepool/test-messages2.json.gz b/chain/messagepool/test-messages2.json.gz new file mode 100644 index 000000000..9d2cfbfe4 Binary files /dev/null and b/chain/messagepool/test-messages2.json.gz differ diff --git a/documentation/en/api-v0-methods.md b/documentation/en/api-v0-methods.md index 431d90acd..2acc969d3 100644 --- a/documentation/en/api-v0-methods.md +++ b/documentation/en/api-v0-methods.md @@ -4202,7 +4202,7 @@ Inputs: Response: ```json { - "Channel": "\u003cempty\u003e", + "Channel": "f01234", "From": "f01234", "To": "f01234", "ConfirmedAmt": "0", @@ -4233,7 +4233,7 @@ Inputs: Response: ```json { - "Channel": "\u003cempty\u003e", + "Channel": "f01234", "From": "f01234", "To": "f01234", "ConfirmedAmt": "0", @@ -4953,7 +4953,7 @@ Response: }, "Nonce": 42, "Balance": "0", - "Address": "\u003cempty\u003e" + "Address": "f01234" } } ``` @@ -5242,7 +5242,7 @@ Response: }, "Nonce": 42, "Balance": "0", - "Address": "\u003cempty\u003e" + "Address": "f01234" } ``` @@ -5985,6 +5985,7 @@ Response: "SectorSize": 34359738368, "WindowPoStPartitionSectors": 42, "ConsensusFaultElapsed": 10101, + "PendingOwnerAddress": "f01234", "Beneficiary": "f01234", "BeneficiaryTerm": { "Quota": "0", diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index 645df4f9d..e3c97eecf 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -5576,7 +5576,7 @@ Inputs: Response: ```json { - "Channel": "\u003cempty\u003e", + "Channel": "f01234", "From": "f01234", "To": "f01234", "ConfirmedAmt": "0", @@ -5607,7 +5607,7 @@ Inputs: Response: ```json { - "Channel": "\u003cempty\u003e", + "Channel": "f01234", "From": "f01234", "To": "f01234", "ConfirmedAmt": "0", @@ -6390,7 +6390,7 @@ Response: }, "Nonce": 42, "Balance": "0", - "Address": "\u003cempty\u003e" + "Address": "f01234" } } ``` @@ -6730,7 +6730,7 @@ Response: }, "Nonce": 42, "Balance": "0", - "Address": "\u003cempty\u003e" + "Address": "f01234" } ``` @@ -7505,6 +7505,7 @@ Response: "SectorSize": 34359738368, "WindowPoStPartitionSectors": 42, "ConsensusFaultElapsed": 10101, + "PendingOwnerAddress": "f01234", "Beneficiary": "f01234", "BeneficiaryTerm": { "Quota": "0", diff --git a/itests/kit/blockminer.go b/itests/kit/blockminer.go index 02876ebb3..bd527910d 100644 --- a/itests/kit/blockminer.go +++ b/itests/kit/blockminer.go @@ -184,7 +184,8 @@ func (bm *BlockMiner) MineBlocksMustPost(ctx context.Context, blocktime time.Dur dlinfo, err := bm.miner.FullNode.StateMinerProvingDeadline(ctx, bm.miner.ActorAddr, ts.Key()) require.NoError(bm.t, err) - if ts.Height()+1+abi.ChainEpoch(nulls) >= dlinfo.Last() { // Next block brings us past the last epoch in dline, we need to wait for miner to post + if ts.Height()+5+abi.ChainEpoch(nulls) >= dlinfo.Last() { // Next block brings us past the last epoch in dline, we need to wait for miner to post + bm.t.Logf("forcing post to get in before deadline closes at %d", dlinfo.Last()) bm.forcePoSt(ctx, ts, dlinfo) } @@ -216,7 +217,8 @@ func (bm *BlockMiner) MineBlocksMustPost(ctx context.Context, blocktime time.Dur } if !success { // if we are mining a new null block and it brings us past deadline boundary we need to wait for miner to post - if ts.Height()+1+abi.ChainEpoch(nulls+i) >= dlinfo.Last() { + if ts.Height()+5+abi.ChainEpoch(nulls+i) >= dlinfo.Last() { + bm.t.Logf("forcing post to get in before deadline closes at %d", dlinfo.Last()) bm.forcePoSt(ctx, ts, dlinfo) } } diff --git a/node/impl/full/state.go b/node/impl/full/state.go index 45b14d3f7..78f450626 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -180,6 +180,7 @@ func (m *StateModule) StateMinerInfo(ctx context.Context, actor address.Address, SectorSize: info.SectorSize, WindowPoStPartitionSectors: info.WindowPoStPartitionSectors, ConsensusFaultElapsed: info.ConsensusFaultElapsed, + PendingOwnerAddress: info.PendingOwnerAddress, Beneficiary: info.Beneficiary, BeneficiaryTerm: &info.BeneficiaryTerm, PendingBeneficiaryTerm: info.PendingBeneficiaryTerm,