generator; single main() entrypoint for each suite. (#232)

This commit is contained in:
Raúl Kripalani 2020-08-14 18:25:35 +01:00 committed by GitHub
parent 9ba87d4613
commit acbb80920b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 476 additions and 267 deletions

View File

@ -5,10 +5,9 @@ import (
"compress/gzip"
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"github.com/filecoin-project/lotus/chain/state"
"github.com/ipfs/go-cid"
@ -31,8 +30,8 @@ const (
func init() {
// disable logs, as we need a clean stdout output.
log.SetOutput(ioutil.Discard)
log.SetFlags(0)
log.SetOutput(os.Stderr)
log.SetPrefix(">>> ")
}
// TODO use stage.Surgeon with non-proxying blockstore.
@ -131,7 +130,6 @@ func (b *Builder) applyMessage(am *ApplicableMessage) {
Bytes: MustSerialize(am.Message),
Epoch: &am.Epoch,
})
fmt.Println(am.Result.ExitCode)
b.vector.Post.Receipts = append(b.vector.Post.Receipts, &schema.Receipt{
ExitCode: am.Result.ExitCode,
ReturnValue: am.Result.Return,

175
tvx/builders/generator.go Normal file
View File

@ -0,0 +1,175 @@
package builders
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"io"
"log"
"os"
"path/filepath"
"regexp"
"sync"
"github.com/filecoin-project/oni/tvx/schema"
)
// Generator is a batch generator and organizer of test vectors.
//
// Test vector scripts are simple programs (main function). Test vector scripts
// can delegate to the Generator to handle the execution, reporting and capture
// of emitted test vectors into files.
//
// Generator supports the following CLI flags:
//
// -o <directory>
// directory where test vector JSON files will be saved; if omitted,
// vectors will be written to stdout.
//
// -f <regex>
// regex filter to select a subset of vectors to execute; matched against
// the vector's ID.
//
// Scripts can bundle test vectors into "groups". The generator will execute
// each group in parallel, and will write each vector in a file:
// <output_dir>/<group>--<vector_id>.json
type Generator struct {
OutputPath string
Filter *regexp.Regexp
wg sync.WaitGroup
}
type MessageVectorGenItem struct {
Metadata *schema.Metadata
Func func(*Builder)
}
func NewGenerator() *Generator {
// Consume CLI parameters.
var (
outputDir = flag.String("o", "", "directory where test vector JSON files will be saved; if omitted, vectors will be written to stdout")
filter = flag.String("f", "", "regex filter to select a subset of vectors to execute; matched against the vector's ID")
)
flag.Parse()
ret := new(Generator)
// If output directory is provided, we ensure it exists, or create it.
// Else, we'll output to stdout.
if dir := *outputDir; dir != "" {
err := ensureDirectory(dir)
if err != nil {
log.Fatal(err)
}
ret.OutputPath = dir
}
// If a filter has been provided, compile it into a regex.
if *filter != "" {
exp, err := regexp.Compile(*filter)
if err != nil {
log.Fatalf("supplied regex %s is invalid: %s", *filter, err)
}
ret.Filter = exp
}
return ret
}
func (g *Generator) Wait() {
g.wg.Wait()
}
func (g *Generator) MessageVectorGroup(group string, vectors ...*MessageVectorGenItem) {
g.wg.Add(1)
go func() {
defer g.wg.Done()
var wg sync.WaitGroup
for _, item := range vectors {
if id := item.Metadata.ID; g.Filter != nil && !g.Filter.MatchString(id) {
log.Printf("skipping %s", id)
continue
}
var w io.Writer
if g.OutputPath == "" {
w = os.Stdout
} else {
file := filepath.Join(g.OutputPath, fmt.Sprintf("%s--%s.json", group, item.Metadata.ID))
out, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
log.Printf("failed to write to file %s: %s", file, err)
return
}
w = out
}
wg.Add(1)
go func(item *MessageVectorGenItem) {
g.generateOne(w, item, w != os.Stdout)
wg.Done()
}(item)
}
wg.Wait()
}()
}
func (g *Generator) generateOne(w io.Writer, b *MessageVectorGenItem, indent bool) {
log.Printf("generating test vector: %s", b.Metadata.ID)
vector := MessageVector(b.Metadata)
// TODO: currently if an assertion fails, we call os.Exit(1), which
// aborts all ongoing vector generations. The Asserter should
// call runtime.Goexit() instead so only that goroutine is
// cancelled. The assertion error must bubble up somehow.
b.Func(vector)
buf := new(bytes.Buffer)
vector.Finish(buf)
final := buf
if indent {
// reparse and reindent.
final = new(bytes.Buffer)
if err := json.Indent(final, buf.Bytes(), "", "\t"); err != nil {
log.Printf("failed to indent json: %s", err)
}
}
n, err := w.Write(final.Bytes())
if err != nil {
log.Printf("failed to write to output: %s", err)
return
}
log.Printf("generated test vector: %s (size: %d bytes)", b.Metadata.ID, n)
}
// ensureDirectory checks if the provided path is a directory. If yes, it
// returns nil. If the path doesn't exist, it creates the directory and
// returns nil. If the path is not a directory, or another error occurs, an
// error is returned.
func ensureDirectory(path string) error {
switch stat, err := os.Stat(path); {
case os.IsNotExist(err):
// create directory.
log.Printf("creating directory %s", path)
err := os.MkdirAll(path, 0700)
if err != nil {
return fmt.Errorf("failed to create directory %s: %s", path, err)
}
case err == nil && !stat.IsDir():
return fmt.Errorf("path %s exists, but it's not a directory", path)
case err != nil:
return fmt.Errorf("failed to stat directory %s: %w", path, err)
}
return nil
}

View File

@ -1,247 +0,0 @@
package main
import (
"os"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/runtime/exitcode"
. "github.com/filecoin-project/oni/tvx/builders"
"github.com/filecoin-project/oni/tvx/schema"
)
var (
unknown = MustNewIDAddr(10000000)
balance1T = abi.NewTokenAmount(1_000_000_000_000)
transferAmnt = abi.NewTokenAmount(10)
)
func main() {
failCoverReceiptGasCost()
failCoverOnChainSizeGasCost()
failUnknownSender()
failInvalidActorNonce()
failInvalidReceiverMethod()
failInexistentReceiver()
failCoverTransferAccountCreationGasStepwise()
failActorExecutionAborted()
}
func failCoverReceiptGasCost() {
metadata := &schema.Metadata{
ID: "msg-apply-fail-receipt-gas",
Version: "v1",
Desc: "fail to cover gas cost for message receipt on chain",
}
v := MessageVector(metadata)
v.Messages.SetDefaults(GasLimit(1_000_000_000), GasPrice(1))
alice := v.Actors.Account(address.SECP256K1, balance1T)
v.CommitPreconditions()
v.Messages.Sugar().Transfer(alice.ID, alice.ID, Value(transferAmnt), Nonce(0), GasLimit(8))
v.CommitApplies()
v.Assert.EveryMessageResultSatisfies(ExitCode(exitcode.SysErrOutOfGas))
v.Finish(os.Stdout)
}
func failCoverOnChainSizeGasCost() {
metadata := &schema.Metadata{
ID: "msg-apply-fail-onchainsize-gas",
Version: "v1",
Desc: "not enough gas to pay message on-chain-size cost",
}
v := MessageVector(metadata)
v.Messages.SetDefaults(GasLimit(1_000_000_000), GasPrice(10))
alice := v.Actors.Account(address.SECP256K1, balance1T)
v.CommitPreconditions()
v.Messages.Sugar().Transfer(alice.ID, alice.ID, Value(transferAmnt), Nonce(0), GasLimit(1))
v.CommitApplies()
v.Assert.EveryMessageResultSatisfies(ExitCode(exitcode.SysErrOutOfGas))
v.Finish(os.Stdout)
}
func failUnknownSender() {
metadata := &schema.Metadata{
ID: "msg-apply-fail-unknown-sender",
Version: "v1",
Desc: "fail due to lack of gas when sender is unknown",
}
v := MessageVector(metadata)
v.Messages.SetDefaults(GasLimit(1_000_000_000), GasPrice(1))
alice := v.Actors.Account(address.SECP256K1, balance1T)
v.CommitPreconditions()
v.Messages.Sugar().Transfer(unknown, alice.ID, Value(transferAmnt), Nonce(0))
v.CommitApplies()
v.Assert.EveryMessageResultSatisfies(ExitCode(exitcode.SysErrSenderInvalid))
v.Finish(os.Stdout)
}
func failInvalidActorNonce() {
metadata := &schema.Metadata{
ID: "msg-apply-fail-invalid-nonce",
Version: "v1",
Desc: "invalid actor nonce",
}
v := MessageVector(metadata)
v.Messages.SetDefaults(GasLimit(1_000_000_000), GasPrice(1))
alice := v.Actors.Account(address.SECP256K1, balance1T)
v.CommitPreconditions()
// invalid nonce from known account.
msg1 := v.Messages.Sugar().Transfer(alice.ID, alice.ID, Value(transferAmnt), Nonce(1))
// invalid nonce from an unknown account.
msg2 := v.Messages.Sugar().Transfer(unknown, alice.ID, Value(transferAmnt), Nonce(1))
v.CommitApplies()
v.Assert.Equal(msg1.Result.ExitCode, exitcode.SysErrSenderStateInvalid)
v.Assert.Equal(msg2.Result.ExitCode, exitcode.SysErrSenderInvalid)
v.Finish(os.Stdout)
}
func failInvalidReceiverMethod() {
metadata := &schema.Metadata{
ID: "msg-apply-fail-invalid-receiver-method",
Version: "v1",
Desc: "invalid receiver method",
}
v := MessageVector(metadata)
v.Messages.SetDefaults(GasLimit(1_000_000_000), GasPrice(1))
alice := v.Actors.Account(address.SECP256K1, balance1T)
v.CommitPreconditions()
v.Messages.Typed(alice.ID, alice.ID, MarketComputeDataCommitment(nil), Nonce(0), Value(big.Zero()))
v.CommitApplies()
v.Assert.EveryMessageResultSatisfies(ExitCode(exitcode.SysErrInvalidMethod))
v.Finish(os.Stdout)
}
func failInexistentReceiver() {
metadata := &schema.Metadata{
ID: "msg-apply-fail-inexistent-receiver",
Version: "v1",
Desc: "inexistent receiver",
Comment: `Note that this test is not a valid message, since it is using
an unknown actor. However in the event that an invalid message isn't filtered by
block validation we need to ensure behaviour is consistent across VM implementations.`,
}
v := MessageVector(metadata)
v.Messages.SetDefaults(GasLimit(1_000_000_000), GasPrice(1))
alice := v.Actors.Account(address.SECP256K1, balance1T)
v.CommitPreconditions()
// Sending a message to non-existent ID address must produce an error.
unknownID := MustNewIDAddr(10000000)
v.Messages.Sugar().Transfer(alice.ID, unknownID, Value(transferAmnt), Nonce(0))
unknownActor := MustNewActorAddr("1234")
v.Messages.Sugar().Transfer(alice.ID, unknownActor, Value(transferAmnt), Nonce(1))
v.CommitApplies()
v.Assert.EveryMessageResultSatisfies(ExitCode(exitcode.SysErrInvalidReceiver))
v.Finish(os.Stdout)
}
func failCoverTransferAccountCreationGasStepwise() {
metadata := &schema.Metadata{
ID: "msg-apply-fail-transfer-accountcreation-gas",
Version: "v1",
Desc: "fail not enough gas to cover account actor creation on transfer",
}
v := MessageVector(metadata)
v.Messages.SetDefaults(GasLimit(1_000_000_000), GasPrice(1))
var alice, bob, charlie AddressHandle
alice = v.Actors.Account(address.SECP256K1, balance1T)
bob.Robust, charlie.Robust = MustNewSECP256K1Addr("1"), MustNewSECP256K1Addr("2")
v.CommitPreconditions()
var nonce uint64
ref := v.Messages.Sugar().Transfer(alice.Robust, bob.Robust, Value(transferAmnt), Nonce(nonce))
nonce++
v.Messages.ApplyOne(ref)
v.Assert.EveryMessageResultSatisfies(ExitCode(exitcode.Ok))
// decrease the gas cost by `gasStep` for each apply and ensure `SysErrOutOfGas` is always returned.
trueGas := ref.Result.GasUsed
gasStep := trueGas / 100
for tryGas := trueGas - gasStep; tryGas > 0; tryGas -= gasStep {
v.Messages.Sugar().Transfer(alice.Robust, charlie.Robust, Value(transferAmnt), Nonce(nonce), GasPrice(1), GasLimit(tryGas))
nonce++
}
v.CommitApplies()
v.Assert.EveryMessageResultSatisfies(ExitCode(exitcode.SysErrOutOfGas), ref)
v.Finish(os.Stdout)
}
func failActorExecutionAborted() {
metadata := &schema.Metadata{
ID: "msg-apply-fail-actor-execution-illegal-arg",
Version: "v1",
Desc: "abort during actor execution due to illegal argument",
}
// Set up sender and receiver accounts.
var sender, receiver AddressHandle
var paychAddr AddressHandle
v := MessageVector(metadata)
v.Messages.SetDefaults(GasLimit(1_000_000_000), GasPrice(1))
v.Actors.AccountN(address.SECP256K1, balance1T, &sender, &receiver)
paychAddr = AddressHandle{
ID: MustNewIDAddr(MustIDFromAddress(receiver.ID) + 1),
Robust: sender.NextActorAddress(0, 0),
}
v.CommitPreconditions()
// Construct the payment channel.
createMsg := v.Messages.Sugar().CreatePaychActor(sender.Robust, receiver.Robust, Value(abi.NewTokenAmount(10_000)))
// Update the payment channel.
updateMsg := v.Messages.Typed(sender.Robust, paychAddr.Robust, PaychUpdateChannelState(&paych.UpdateChannelStateParams{
Sv: paych.SignedVoucher{
ChannelAddr: paychAddr.Robust,
TimeLockMin: abi.ChainEpoch(10),
Lane: 123,
Nonce: 1,
Amount: big.NewInt(10),
Signature: &crypto.Signature{
Type: crypto.SigTypeBLS,
Data: []byte("Grrr im an invalid signature, I cause panics in the payment channel actor"),
},
}}), Nonce(1), Value(big.Zero()))
v.CommitApplies()
v.Assert.Equal(exitcode.Ok, createMsg.Result.ExitCode)
v.Assert.Equal(exitcode.ErrIllegalArgument, updateMsg.Result.ExitCode)
v.Finish(os.Stdout)
}

View File

@ -0,0 +1,49 @@
package main
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/filecoin-project/specs-actors/actors/crypto"
"github.com/filecoin-project/specs-actors/actors/runtime/exitcode"
. "github.com/filecoin-project/oni/tvx/builders"
)
func failActorExecutionAborted(v *Builder) {
v.Messages.SetDefaults(GasLimit(1_000_000_000), GasPrice(1))
// Set up sender and receiver accounts.
var sender, receiver AddressHandle
var paychAddr AddressHandle
v.Actors.AccountN(address.SECP256K1, balance1T, &sender, &receiver)
paychAddr = AddressHandle{
ID: MustNewIDAddr(MustIDFromAddress(receiver.ID) + 1),
Robust: sender.NextActorAddress(0, 0),
}
v.CommitPreconditions()
// Construct the payment channel.
createMsg := v.Messages.Sugar().CreatePaychActor(sender.Robust, receiver.Robust, Value(abi.NewTokenAmount(10_000)))
// Update the payment channel.
updateMsg := v.Messages.Typed(sender.Robust, paychAddr.Robust, PaychUpdateChannelState(&paych.UpdateChannelStateParams{
Sv: paych.SignedVoucher{
ChannelAddr: paychAddr.Robust,
TimeLockMin: abi.ChainEpoch(10),
Lane: 123,
Nonce: 1,
Amount: big.NewInt(10),
Signature: &crypto.Signature{
Type: crypto.SigTypeBLS,
Data: []byte("Grrr im an invalid signature, I cause panics in the payment channel actor"),
},
}}), Nonce(1), Value(big.Zero()))
v.CommitApplies()
v.Assert.Equal(exitcode.Ok, createMsg.Result.ExitCode)
v.Assert.Equal(exitcode.ErrIllegalArgument, updateMsg.Result.ExitCode)
}

View File

@ -0,0 +1,58 @@
package main
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/runtime/exitcode"
. "github.com/filecoin-project/oni/tvx/builders"
)
func failCoverReceiptGasCost(v *Builder) {
v.Messages.SetDefaults(GasLimit(1_000_000_000), GasPrice(1))
alice := v.Actors.Account(address.SECP256K1, balance1T)
v.CommitPreconditions()
v.Messages.Sugar().Transfer(alice.ID, alice.ID, Value(transferAmnt), Nonce(0), GasLimit(8))
v.CommitApplies()
v.Assert.EveryMessageResultSatisfies(ExitCode(exitcode.SysErrOutOfGas))
}
func failCoverOnChainSizeGasCost(v *Builder) {
v.Messages.SetDefaults(GasLimit(1_000_000_000), GasPrice(10))
alice := v.Actors.Account(address.SECP256K1, balance1T)
v.CommitPreconditions()
v.Messages.Sugar().Transfer(alice.ID, alice.ID, Value(transferAmnt), Nonce(0), GasLimit(1))
v.CommitApplies()
v.Assert.EveryMessageResultSatisfies(ExitCode(exitcode.SysErrOutOfGas))
}
func failCoverTransferAccountCreationGasStepwise(v *Builder) {
v.Messages.SetDefaults(GasLimit(1_000_000_000), GasPrice(1))
var alice, bob, charlie AddressHandle
alice = v.Actors.Account(address.SECP256K1, balance1T)
bob.Robust, charlie.Robust = MustNewSECP256K1Addr("1"), MustNewSECP256K1Addr("2")
v.CommitPreconditions()
var nonce uint64
ref := v.Messages.Sugar().Transfer(alice.Robust, bob.Robust, Value(transferAmnt), Nonce(nonce))
nonce++
v.Messages.ApplyOne(ref)
v.Assert.EveryMessageResultSatisfies(ExitCode(exitcode.Ok))
// decrease the gas cost by `gasStep` for each apply and ensure `SysErrOutOfGas` is always returned.
trueGas := ref.Result.GasUsed
gasStep := trueGas / 100
for tryGas := trueGas - gasStep; tryGas > 0; tryGas -= gasStep {
v.Messages.Sugar().Transfer(alice.Robust, charlie.Robust, Value(transferAmnt), Nonce(nonce), GasPrice(1), GasLimit(tryGas))
nonce++
}
v.CommitApplies()
v.Assert.EveryMessageResultSatisfies(ExitCode(exitcode.SysErrOutOfGas), ref)
}

View File

@ -0,0 +1,38 @@
package main
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/runtime/exitcode"
. "github.com/filecoin-project/oni/tvx/builders"
)
func failInvalidActorNonce(v *Builder) {
v.Messages.SetDefaults(GasLimit(1_000_000_000), GasPrice(1))
alice := v.Actors.Account(address.SECP256K1, balance1T)
v.CommitPreconditions()
// invalid nonce from known account.
msg1 := v.Messages.Sugar().Transfer(alice.ID, alice.ID, Value(transferAmnt), Nonce(1))
// invalid nonce from an unknown account.
msg2 := v.Messages.Sugar().Transfer(unknown, alice.ID, Value(transferAmnt), Nonce(1))
v.CommitApplies()
v.Assert.Equal(msg1.Result.ExitCode, exitcode.SysErrSenderStateInvalid)
v.Assert.Equal(msg2.Result.ExitCode, exitcode.SysErrSenderInvalid)
}
func failInvalidReceiverMethod(v *Builder) {
v.Messages.SetDefaults(GasLimit(1_000_000_000), GasPrice(1))
alice := v.Actors.Account(address.SECP256K1, balance1T)
v.CommitPreconditions()
v.Messages.Typed(alice.ID, alice.ID, MarketComputeDataCommitment(nil), Nonce(0), Value(big.Zero()))
v.CommitApplies()
v.Assert.EveryMessageResultSatisfies(ExitCode(exitcode.SysErrInvalidMethod))
}

View File

@ -0,0 +1,98 @@
package main
import (
"github.com/filecoin-project/specs-actors/actors/abi"
. "github.com/filecoin-project/oni/tvx/builders"
"github.com/filecoin-project/oni/tvx/schema"
)
var (
unknown = MustNewIDAddr(10000000)
balance1T = abi.NewTokenAmount(1_000_000_000_000)
transferAmnt = abi.NewTokenAmount(10)
)
func main() {
g := NewGenerator()
g.MessageVectorGroup("gas_cost",
&MessageVectorGenItem{
Metadata: &schema.Metadata{
ID: "msg-apply-fail-receipt-gas",
Version: "v1",
Desc: "fail to cover gas cost for message receipt on chain",
},
Func: failCoverReceiptGasCost,
},
&MessageVectorGenItem{
Metadata: &schema.Metadata{
ID: "msg-apply-fail-onchainsize-gas",
Version: "v1",
Desc: "not enough gas to pay message on-chain-size cost",
},
Func: failCoverOnChainSizeGasCost,
},
&MessageVectorGenItem{
Metadata: &schema.Metadata{
ID: "msg-apply-fail-transfer-accountcreation-gas",
Version: "v1",
Desc: "fail not enough gas to cover account actor creation on transfer",
},
Func: failCoverTransferAccountCreationGasStepwise,
})
g.MessageVectorGroup("invalid_msgs",
&MessageVectorGenItem{
Metadata: &schema.Metadata{
ID: "msg-apply-fail-invalid-nonce",
Version: "v1",
Desc: "invalid actor nonce",
},
Func: failInvalidActorNonce,
},
&MessageVectorGenItem{
Metadata: &schema.Metadata{
ID: "msg-apply-fail-invalid-receiver-method",
Version: "v1",
Desc: "invalid receiver method",
},
Func: failInvalidReceiverMethod,
},
)
g.MessageVectorGroup("unknown_actors",
&MessageVectorGenItem{
Metadata: &schema.Metadata{
ID: "msg-apply-fail-unknown-sender",
Version: "v1",
Desc: "fail due to lack of gas when sender is unknown",
},
Func: failUnknownSender,
},
&MessageVectorGenItem{
Metadata: &schema.Metadata{
ID: "msg-apply-fail-unknown-receiver",
Version: "v1",
Desc: "inexistent receiver",
Comment: `Note that this test is not a valid message, since it is using
an unknown actor. However in the event that an invalid message isn't filtered by
block validation we need to ensure behaviour is consistent across VM implementations.`,
},
Func: failUnknownReceiver,
},
)
g.MessageVectorGroup("actor_exec",
&MessageVectorGenItem{
Metadata: &schema.Metadata{
ID: "msg-apply-fail-actor-execution-illegal-arg",
Version: "v1",
Desc: "abort during actor execution due to illegal argument",
},
Func: failActorExecutionAborted,
},
)
g.Wait()
}

View File

@ -0,0 +1,37 @@
package main
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/runtime/exitcode"
. "github.com/filecoin-project/oni/tvx/builders"
)
func failUnknownSender(v *Builder) {
v.Messages.SetDefaults(GasLimit(1_000_000_000), GasPrice(1))
alice := v.Actors.Account(address.SECP256K1, balance1T)
v.CommitPreconditions()
v.Messages.Sugar().Transfer(unknown, alice.ID, Value(transferAmnt), Nonce(0))
v.CommitApplies()
v.Assert.EveryMessageResultSatisfies(ExitCode(exitcode.SysErrSenderInvalid))
}
func failUnknownReceiver(v *Builder) {
v.Messages.SetDefaults(GasLimit(1_000_000_000), GasPrice(1))
alice := v.Actors.Account(address.SECP256K1, balance1T)
v.CommitPreconditions()
// Sending a message to non-existent ID address must produce an error.
unknownID := MustNewIDAddr(10000000)
v.Messages.Sugar().Transfer(alice.ID, unknownID, Value(transferAmnt), Nonce(0))
unknownActor := MustNewActorAddr("1234")
v.Messages.Sugar().Transfer(alice.ID, unknownActor, Value(transferAmnt), Nonce(1))
v.CommitApplies()
v.Assert.EveryMessageResultSatisfies(ExitCode(exitcode.SysErrInvalidReceiver))
}

14
tvx/scripts/paych/main.go Normal file
View File

@ -0,0 +1,14 @@
package main
import "github.com/filecoin-project/specs-actors/actors/abi"
var (
initialBal = abi.NewTokenAmount(200_000_000_000)
toSend = abi.NewTokenAmount(10_000)
)
func main() {
happyPathCreate()
happyPathUpdate()
happyPathCollect()
}

View File

@ -15,17 +15,6 @@ import (
"github.com/filecoin-project/oni/tvx/schema"
)
var (
balance200B = abi.NewTokenAmount(200_000_000_000)
toSend = abi.NewTokenAmount(10_000)
)
func main() {
happyPathCreate()
happyPathUpdate()
happyPathCollect()
}
func happyPathCreate() {
metadata := &schema.Metadata{ID: "paych-create-ok", Version: "v1", Desc: "payment channel create"}
@ -34,7 +23,7 @@ func happyPathCreate() {
// Set up sender and receiver accounts.
var sender, receiver AddressHandle
v.Actors.AccountN(address.SECP256K1, balance200B, &sender, &receiver)
v.Actors.AccountN(address.SECP256K1, initialBal, &sender, &receiver)
v.CommitPreconditions()
// Add the constructor message.
@ -79,7 +68,7 @@ func happyPathUpdate() {
v := MessageVector(metadata)
v.Messages.SetDefaults(GasLimit(1_000_000_000), GasPrice(1))
v.Actors.AccountN(address.SECP256K1, balance200B, &sender, &receiver)
v.Actors.AccountN(address.SECP256K1, initialBal, &sender, &receiver)
paychAddr = AddressHandle{
ID: MustNewIDAddr(MustIDFromAddress(receiver.ID) + 1),
Robust: sender.NextActorAddress(0, 0),
@ -136,7 +125,7 @@ func happyPathCollect() {
// Set up sender and receiver accounts.
var sender, receiver AddressHandle
var paychAddr AddressHandle
v.Actors.AccountN(address.SECP256K1, balance200B, &sender, &receiver)
v.Actors.AccountN(address.SECP256K1, initialBal, &sender, &receiver)
paychAddr = AddressHandle{
ID: MustNewIDAddr(MustIDFromAddress(receiver.ID) + 1),
Robust: sender.NextActorAddress(0, 0),
@ -175,7 +164,7 @@ func happyPathCollect() {
// receiver_balance = initial_balance + paych_send - settle_paych_msg_gas - collect_paych_msg_gas
gasUsed := big.Add(big.NewInt(settleMsg.Result.MessageReceipt.GasUsed), big.NewInt(collectMsg.Result.MessageReceipt.GasUsed))
v.Assert.BalanceEq(receiver.Robust, big.Sub(big.Add(toSend, balance200B), gasUsed))
v.Assert.BalanceEq(receiver.Robust, big.Sub(big.Add(toSend, initialBal), gasUsed))
// the paych actor should have been deleted after the collect
v.Assert.ActorMissing(paychAddr.Robust)