lotus/tvx/messages_create_actor.go
Anton Evangelatov 5353210814
generate test-vectors based on tests from chain-validation project (#181)
* Read a subset of filecoin state over the full node API

* wip

* import export wip

* extract actors from message

* generate car for any state

* library for providing a pruned statetree

* test vector schema draft + example 'message' class test vector.

* message => messages test vector class.

* fixup

* wip

* use lb.NewBlockstore with ID

* fixup lotus-soup, and generate

* fix deals

* magic params

* work on schema / export of test vector

* fixup

* wip deserialise state tree

* pass at building a test case from a message

* progress loading / serializing

* recreation of ipld nodes

* generation of vector creates json

* kick off tvx tool.

* wip

* wip

* retain init actor state.

* initial test with printed out state

* remove testing.T, but keep require and assert libraries

* wip refactor state tree plucking.

* simplified

* removed factories

* remove builder.Build ; remove interface - use concrete iface

* comment out validateState

* remove Validator

* remove TestDriverBuilder

* remove client

* remove box

* remove gen

* remove factories

* remove KeyManager interfafce

* moved stuff around

* remove ValidationConfig

* extract randomness

* extract config and key_manager

* extract statewrapper

* extract applier

* rename factories to various

* flatten chain-validation package

* initial marshal of test vector

* do not require schema package

* fixup

* run all messages tests

* better names

* run all messages tests

* remove Indent setting from JSON encoder for now

* refactor, and actually running successfully ;-)

* remove irrelevant files; rename extract-msg command.

* remove root CID from state_tree object in schema.

* add tvx/lotus package; adjust .gitignore.

* tidy up command flag management.

* add comment.

* remove validateState and trackState

* remove xerrors

* remove NewVM

* remove commented out RootCID sets

* enable more tests

* add all `message_application` tests

* delete all.json

* update Message struct

* fix message serialization

* support multiple messages

* gofmt

* remove custom Message and SignedMessage types

* update tests with gzip and adhere to new schema for compressed CAR

* improved iface for Marshal

* update Validation

* remove test-suites and utils

* better names for chain. methods

* go mod tidy

* remove top-level dummyT

Co-authored-by: Will Scott <will@cypherpunk.email>
Co-authored-by: Raúl Kripalani <raul@protocol.ai>
2020-08-05 19:40:09 +02:00

217 lines
5.2 KiB
Go

package main
import (
"encoding/json"
"os"
"github.com/hashicorp/go-multierror"
"github.com/urfave/cli/v2"
"github.com/filecoin-project/go-address"
abi_spec "github.com/filecoin-project/specs-actors/actors/abi"
big_spec "github.com/filecoin-project/specs-actors/actors/abi/big"
exitcode_spec "github.com/filecoin-project/specs-actors/actors/runtime/exitcode"
"github.com/filecoin-project/oni/tvx/chain"
"github.com/filecoin-project/oni/tvx/drivers"
)
var suiteMessagesCmd = &cli.Command{
Name: "suite-messages",
Description: "",
Action: suiteMessages,
}
func suiteMessages(c *cli.Context) error {
var err *multierror.Error
err = multierror.Append(MessageTest_AccountActorCreation())
err = multierror.Append(MessageTest_InitActorSequentialIDAddressCreate())
err = multierror.Append(MessageTest_MessageApplicationEdgecases())
return err.ErrorOrNil()
}
func MessageTest_AccountActorCreation() error {
testCases := []struct {
desc string
existingActorType address.Protocol
existingActorBal abi_spec.TokenAmount
newActorAddr address.Address
newActorInitBal abi_spec.TokenAmount
expExitCode exitcode_spec.ExitCode
}{
{
"success create SECP256K1 account actor",
address.SECP256K1,
abi_spec.NewTokenAmount(10_000_000_000),
chain.MustNewSECP256K1Addr("publickeyfoo"),
abi_spec.NewTokenAmount(10_000),
exitcode_spec.Ok,
},
{
"success create BLS account actor",
address.SECP256K1,
abi_spec.NewTokenAmount(10_000_000_000),
chain.MustNewBLSAddr(1),
abi_spec.NewTokenAmount(10_000),
exitcode_spec.Ok,
},
{
"fail create SECP256K1 account actor insufficient balance",
address.SECP256K1,
abi_spec.NewTokenAmount(9_999),
chain.MustNewSECP256K1Addr("publickeybar"),
abi_spec.NewTokenAmount(10_000),
exitcode_spec.SysErrSenderStateInvalid,
},
{
"fail create BLS account actor insufficient balance",
address.SECP256K1,
abi_spec.NewTokenAmount(9_999),
chain.MustNewBLSAddr(1),
abi_spec.NewTokenAmount(10_000),
exitcode_spec.SysErrSenderStateInvalid,
},
// TODO add edge case tests that have insufficient balance after gas fees
}
for _, tc := range testCases {
err := func() error {
td := drivers.NewTestDriver()
v := newEmptyMessageVector()
existingAccountAddr, _ := td.NewAccountActor(tc.existingActorType, tc.existingActorBal)
preroot := td.GetStateRoot()
msg := td.MessageProducer.Transfer(existingAccountAddr, tc.newActorAddr, chain.Value(tc.newActorInitBal), chain.Nonce(0))
b, err := msg.Serialize()
if err != nil {
return err
}
v.ApplyMessages = []HexEncodedBytes{b}
result := td.ApplyFailure(
msg,
tc.expExitCode,
)
// new actor balance will only exist if message was applied successfully.
if tc.expExitCode.IsSuccess() {
td.AssertBalance(tc.newActorAddr, tc.newActorInitBal)
td.AssertBalance(existingAccountAddr, big_spec.Sub(big_spec.Sub(tc.existingActorBal, result.Receipt.GasUsed.Big()), tc.newActorInitBal))
}
postroot := td.GetStateRoot()
v.CAR = td.MustMarshalGzippedCAR(preroot, postroot)
v.Pre.StateTree.RootCID = preroot
v.Post.StateTree.RootCID = postroot
// encode and output
enc := json.NewEncoder(os.Stdout)
if err := enc.Encode(&v); err != nil {
return err
}
return nil
}()
if err != nil {
return err
}
}
return nil
}
func MessageTest_InitActorSequentialIDAddressCreate() error {
td := drivers.NewTestDriver()
v := newEmptyMessageVector()
var initialBal = abi_spec.NewTokenAmount(200_000_000_000)
var toSend = abi_spec.NewTokenAmount(10_000)
sender, _ := td.NewAccountActor(drivers.SECP, initialBal)
receiver, receiverID := td.NewAccountActor(drivers.SECP, initialBal)
firstPaychAddr := chain.MustNewIDAddr(chain.MustIdFromAddress(receiverID) + 1)
secondPaychAddr := chain.MustNewIDAddr(chain.MustIdFromAddress(receiverID) + 2)
firstInitRet := td.ComputeInitActorExecReturn(sender, 0, 0, firstPaychAddr)
secondInitRet := td.ComputeInitActorExecReturn(sender, 1, 0, secondPaychAddr)
preroot := td.GetStateRoot()
msg1 := td.MessageProducer.CreatePaymentChannelActor(sender, receiver, chain.Value(toSend), chain.Nonce(0))
td.ApplyExpect(
msg1,
chain.MustSerialize(&firstInitRet),
)
b1, err := msg1.Serialize()
if err != nil {
return err
}
v.ApplyMessages = append(v.ApplyMessages, b1)
msg2 := td.MessageProducer.CreatePaymentChannelActor(sender, receiver, chain.Value(toSend), chain.Nonce(1))
td.ApplyExpect(
msg2,
chain.MustSerialize(&secondInitRet),
)
b2, err := msg2.Serialize()
if err != nil {
return err
}
v.ApplyMessages = append(v.ApplyMessages, b2)
postroot := td.GetStateRoot()
v.CAR = td.MustMarshalGzippedCAR(preroot, postroot)
v.Pre.StateTree.RootCID = preroot
v.Post.StateTree.RootCID = postroot
// encode and output
enc := json.NewEncoder(os.Stdout)
if err := enc.Encode(&v); err != nil {
return err
}
return nil
}
func newEmptyMessageVector() TestVector {
return TestVector{
Class: ClassMessage,
Selector: "",
Meta: &Metadata{
ID: "TK",
Version: "TK",
Gen: GenerationData{
Source: "TK",
Version: "TK",
},
},
Pre: &Preconditions{
StateTree: &StateTree{},
},
Post: &Postconditions{
StateTree: &StateTree{},
},
}
}