Merge pull request #7450 from filecoin-project/arajasek-patch-1

StateSearchMsg: Correct usage of the allowReplaced flag
This commit is contained in:
Aayush Rajasekaran 2021-10-06 00:25:02 -04:00 committed by GitHub
commit a324b3fce0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 160 additions and 14 deletions

View File

@ -297,6 +297,10 @@ func NewGeneratorWithUpgradeSchedule(us stmgr.UpgradeSchedule) (*ChainGen, error
return NewGeneratorWithSectorsAndUpgradeSchedule(1, us)
}
func (cg *ChainGen) Blockstore() blockstore.Blockstore {
return cg.bs
}
func (cg *ChainGen) StateManager() *stmgr.StateManager {
return cg.sm
}

View File

@ -252,22 +252,27 @@ func (sm *StateManager) tipsetExecutedMessage(ts *types.TipSet, msg cid.Cid, vmm
if m.VMMessage().From == vmm.From { // cheaper to just check origin first
if m.VMMessage().Nonce == vmm.Nonce {
if allowReplaced && m.VMMessage().EqualCall(vmm) {
if m.Cid() != msg {
log.Warnw("found message with equal nonce and call params but different CID",
"wanted", msg, "found", m.Cid(), "nonce", vmm.Nonce, "from", vmm.From)
}
pr, err := sm.cs.GetParentReceipt(ts.Blocks()[0], i)
if err != nil {
return nil, cid.Undef, err
}
return pr, m.Cid(), nil
if !m.VMMessage().EqualCall(vmm) {
// this is an entirely different message, fail
return nil, cid.Undef, xerrors.Errorf("found message with equal nonce as the one we are looking for that is NOT a valid replacement message (F:%s n %d, TS: %s n%d)",
msg, vmm.Nonce, m.Cid(), m.VMMessage().Nonce)
}
// this should be that message
return nil, cid.Undef, xerrors.Errorf("found message with equal nonce as the one we are looking for (F:%s n %d, TS: %s n%d)",
msg, vmm.Nonce, m.Cid(), m.VMMessage().Nonce)
if m.Cid() != msg {
if !allowReplaced {
log.Warnw("found message with equal nonce and call params but different CID",
"wanted", msg, "found", m.Cid(), "nonce", vmm.Nonce, "from", vmm.From)
return nil, cid.Undef, xerrors.Errorf("found message with equal nonce as the one we are looking for (F:%s n %d, TS: %s n%d)",
msg, vmm.Nonce, m.Cid(), m.VMMessage().Nonce)
}
}
pr, err := sm.cs.GetParentReceipt(ts.Blocks()[0], i)
if err != nil {
return nil, cid.Undef, err
}
return pr, m.Cid(), nil
}
if m.VMMessage().Nonce < vmm.Nonce {
return nil, cid.Undef, nil // don't bother looking further

View File

@ -0,0 +1,137 @@
package stmgr_test
import (
"context"
"testing"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/lotus/chain/gen"
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
)
func TestSearchForMessageReplacements(t *testing.T) {
ctx := context.Background()
cg, err := gen.NewGenerator()
if err != nil {
t.Fatal(err)
}
mts1, err := cg.NextTipSet()
if err != nil {
t.Fatal(err)
}
m := mts1.Messages[0]
mts2, err := cg.NextTipSet()
if err != nil {
t.Fatal(err)
}
// Step 1: Searching for the executed msg with replacements allowed succeeds
ts, r, mcid, err := cg.StateManager().SearchForMessage(ctx, mts2.TipSet.TipSet(), m.Cid(), 100, true)
if err != nil {
t.Fatal(err)
}
if !ts.Equals(mts2.TipSet.TipSet()) {
t.Fatal("searched tipset wasn't as expected")
}
if r.ExitCode != 0 {
t.Fatal("searched msg wasn't successfully executed")
}
if mcid != m.Cid() {
t.Fatal("searched msg wasn't identical to queried msg as expected")
}
// Step 2: Searching for the executed msg with replacements disallowed also succeeds
ts, r, mcid, err = cg.StateManager().SearchForMessage(ctx, mts2.TipSet.TipSet(), m.Cid(), 100, true)
if err != nil {
t.Fatal(err)
}
if !ts.Equals(mts2.TipSet.TipSet()) {
t.Fatal("searched tipset wasn't as expected")
}
if r.ExitCode != 0 {
t.Fatal("searched msg wasn't successfully executed")
}
if mcid != m.Cid() {
t.Fatal("searched msg wasn't identical to queried msg as expected")
}
// rm is a valid replacement message for m
rm := m.Message
rm.GasLimit = m.Message.GasLimit + 1
rmb, err := rm.ToStorageBlock()
if err != nil {
t.Fatal(err)
}
err = cg.Blockstore().Put(rmb)
if err != nil {
t.Fatal(err)
}
// Step 3: Searching for the replacement msg with replacements allowed succeeds
ts, r, mcid, err = cg.StateManager().SearchForMessage(ctx, mts2.TipSet.TipSet(), rm.Cid(), 100, true)
if err != nil {
t.Fatal(err)
}
if !ts.Equals(mts2.TipSet.TipSet()) {
t.Fatal("searched tipset wasn't as expected")
}
if r.ExitCode != 0 {
t.Fatal("searched msg wasn't successfully executed")
}
if mcid == rm.Cid() {
t.Fatal("searched msg was identical to queried msg, not as expected")
}
if mcid != m.Cid() {
t.Fatal("searched msg wasn't identical to executed msg as expected")
}
// Step 4: Searching for the replacement msg with replacements disallowed fails
_, _, _, err = cg.StateManager().SearchForMessage(ctx, mts2.TipSet.TipSet(), rm.Cid(), 100, false)
if err == nil {
t.Fatal("expected search to fail")
}
// nrm is NOT a valid replacement message for m
nrm := m.Message
nrm.Value = big.Add(m.Message.Value, m.Message.Value)
nrmb, err := nrm.ToStorageBlock()
if err != nil {
t.Fatal(err)
}
err = cg.Blockstore().Put(nrmb)
if err != nil {
t.Fatal(err)
}
// Step 5: Searching for the not-replacement msg with replacements allowed fails
_, _, _, err = cg.StateManager().SearchForMessage(ctx, mts2.TipSet.TipSet(), nrm.Cid(), 100, true)
if err == nil {
t.Fatal("expected search to fail")
}
// Step 6: Searching for the not-replacement msg with replacements disallowed also fails
_, _, _, err = cg.StateManager().SearchForMessage(ctx, mts2.TipSet.TipSet(), nrm.Cid(), 100, false)
if err == nil {
t.Fatal("expected search to fail")
}
}