lotus/itests/paych_cli_test.go
Jiaying Wang bd10bdf99a
build: release: v1.18.0 (#9652)
* build: Bump version to v1.17.3-dev

* build: set version to v1.18.0-dev

* chore: actors: Allow builtin-actors to return a map of methods (#9342)

* Allow builtin-actors to return a map of methods

* go mod

* Fix tests

* Fix tests, check carefully please

* Delete lotus-pond (#9352)

* feat: add StateNetworkVersion to mpool API

* chore: refactor: rename NewestNetworkVersion

* feat: actors: Integrate datacap actor into lotus (#9348)

* Integrate datacap actor

* Implement datacap actor in chain/builtin

* feat: support typed errors over RPC

* chore: deps: update to go-jsonrpc 0.1.8

* remove duplicate import

* fix: itest: check for closed connection

* chore: refactor: move retry test to API

* address magik supernit

* Add ability to only have single partition per msg for partitions with recovery sectors

* doc gen

* Address comments

* Return beneficiary info from miner state Info()

* Update builtin-actors to dev/20220922-v9 which includes FIP-0045 changes in progress

* Integrate verifreg changes to lotus

* Setup datacap actor

* Update builtin-actors to dev/20220922-v9-1

* Update datacap actor to query datacap instead of verifreg

* update gst

* update markets

* update actors with hamt fix

* update gst

* Update datacap to parse tokens

* Update bundles

* datacap and verifreg actors use ID addresses without protocol byte

* update builtin-actors to rc1

* update go-fil-markets

* Update bundles to rc2

* Integrate the v9 migration

* Add api for getting allocation

* Add upgrade epoch for butterfly

* Tweak PreSeal struct to be infra-friendly

* docsgen

* More tweaking of PreSeal for genesis

* review fixes

* Use fake cid for test

* add butterfly artifacts for oct 5 upgrade

* check datacaps for v8 verifreg match v9 datacap actor

* Remove print statements

* Update to go-state-types master

* Update to go-state-types v0.9.0-rc1

* review fixes

* use go-fil-markets v1.24.0-v17

* Add accessors for allocations and claims maps

* fix: missing permissions tag

* butterfly

* update butterfly artifacts

* sealing pipeline: Prepare deal assigning logic for FIP-45

* sealing pipeline: Get allocationId with StateApi

* use NoAllocationID instead of nil AllocationId

* address review

* Add datacap actor to registry.go

* Add cli for listing allocations and removing expired allocations

* Update to go-state-types master

* deps: upgrade go-merkledag to 0.8.0

* shark params

* Update cli/filplus.go

Co-authored-by: Aayush Rajasekaran <arajasek94@gmail.com>

* revert change to verifreg util

* docsgen-cli

* miss the stuff

* Update FFI

* Update go-state-types to v0.9.0

* Update builtin-actors to v9.0.0

* add calib upgrade epcoh

* update  the upgrade envvar

* kill shark

* Remove fvm splash banner from nv17 upgrade

* check invariance for pending deals and allocations

* check pending verified deal proposal migrated to allocation

* Add check for unsealed CID in precommit sectors

* Fix counting of allocations in nv17 migration test

* make gen

* pass state trees as pointers

* Add assertion that migrations with & without cache are the same

* compare allocation to verified deal proposal

* Fix miner state precommit info

* fix migration test tool

* add changelog

* Update to go-state-types v0.9.1

* Integrate builtin-actors v9.0.1

* chore: ver: bump version for rc3 (#9512)

* Bump version to 1.18.0-rc3

* Update CHANGELOG.md

* Update CHANGELOG.md

Co-authored-by: Aayush Rajasekaran <arajasek94@gmail.com>

* Update CHANGELOG.md

Co-authored-by: Aayush Rajasekaran <arajasek94@gmail.com>

Co-authored-by: Jiaying Wang <42981373+jennijuju@users.noreply.github.com>
Co-authored-by: Aayush Rajasekaran <arajasek94@gmail.com>

* Migration: Use autobatch bs

* Fix autobatch

Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>

* Invoker: Use MethodMeta from go-state-types

* Add a second premigration for nv17

* Add more shed tools for migration checking

* address review

* Lotus release v1.18.0-rc4

* fix: ci: fix app-image build on ci (#9527)

* Remove old go version first

* Add GO_VERSION file

* Use GO_VERSION to set / verify go version

* mv GO_VERSION GO_VERSION_MIN

* Use GO_VERSION_MIN in Makefile check

Co-authored-by: Ian Davis <jungziege@gmail.com>

* Update to latest go-state-types for migration fixes

* go mod tidy

* fix: use api.ErrActorNotFound instead of types.ErrActorNotFound

* fix: add fields to ForkUpgradeParams

* docs: update actors_version_checklist.md

* chore: fix lint

* update to go state type v0.9.6 with market migration fix (#9545)

* update go-state-types to v-0.9.7

* Add invariant checks to migration

* fix invariant check: number of entries in datacap actor should include verifreg

* Invariant checks: Only include not-activated deals

* test: nv17 migration

* Address review

* add lotus-shed invariance method

* Migration cli takes a stateroot cid and a height

* make gen

* Update to builtin-actors v9.0.2

* Failing test that shows that notaries can remove datacap from the verifreg actor

* Test that should pass when the problem is solved

* make gen

* Review fixes

* statemanager call function will return call information even if call errors

* update go-state-types

* update builtin-actors

* bubble up errors properly from ApplyImplicitMessage

* bump to rc5

* set new upgrade heights for calibnet

* set new upgrade height for butterfly

* tweak calibnet upgrade schedule

* clarify changelog note about calibnet

* butterfly

* update calibnet artifacts

* Allow setting local bundles for Debug FVM for av 9+

* fix: autobatch: remove potential deadlock when a block is missing

Check the _underlying_ blockstore instead of recursing. Also, drop the
lock before we do that.

* fix imports

* build: set shark mainnet epoch (#9640)

* chore: build: Lotus release v1.18.0 (#9641)

* Lotus release v1.18.0

* add changelog

* address review

* changelog improvement

Co-authored-by: Jennifer Wang <jiayingw703@gmail.com>
Co-authored-by: Jiaying Wang <42981373+jennijuju@users.noreply.github.com>

Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
Co-authored-by: Łukasz Magiera <magik6k@gmail.com>
Co-authored-by: Łukasz Magiera <magik6k@users.noreply.github.com>
Co-authored-by: Aayush <arajasek94@gmail.com>
Co-authored-by: Geoff Stuart <geoff.vball@gmail.com>
Co-authored-by: Shrenuj Bansal <shrenuj.bansal@protocol.ai>
Co-authored-by: simlecode <69969590+simlecode@users.noreply.github.com>
Co-authored-by: Rod Vagg <rod@vagg.org>
Co-authored-by: Jakub Sztandera <kubuxu@protocol.ai>
Co-authored-by: Ian Davis <jungziege@gmail.com>
Co-authored-by: zenground0 <ZenGround0@users.noreply.github.com>
Co-authored-by: Steven Allen <steven@stebalien.com>
2022-11-15 20:57:23 -05:00

472 lines
17 KiB
Go

// stm: #integration
package itests
import (
"context"
"fmt"
"os"
"regexp"
"strconv"
"strings"
"testing"
"time"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/blockstore"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
"github.com/filecoin-project/lotus/chain/events"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/itests/kit"
)
// TestPaymentChannelsBasic does a basic test to exercise the payment channel CLI
// commands
func TestPaymentChannelsBasic(t *testing.T) {
//stm: @CHAIN_SYNCER_LOAD_GENESIS_001, @CHAIN_SYNCER_FETCH_TIPSET_001,
//stm: @CHAIN_SYNCER_START_001, @CHAIN_SYNCER_SYNC_001, @BLOCKCHAIN_BEACON_VALIDATE_BLOCK_VALUES_01
//stm: @CHAIN_SYNCER_COLLECT_CHAIN_001, @CHAIN_SYNCER_COLLECT_HEADERS_001, @CHAIN_SYNCER_VALIDATE_TIPSET_001
//stm: @CHAIN_SYNCER_NEW_PEER_HEAD_001, @CHAIN_SYNCER_VALIDATE_MESSAGE_META_001, @CHAIN_SYNCER_STOP_001
//stm: @CHAIN_INCOMING_HANDLE_INCOMING_BLOCKS_001, @CHAIN_INCOMING_VALIDATE_BLOCK_PUBSUB_001, @CHAIN_INCOMING_VALIDATE_MESSAGE_PUBSUB_001
_ = os.Setenv("BELLMAN_NO_GPU", "1")
kit.QuietMiningLogs()
blocktime := 5 * time.Millisecond
ctx := context.Background()
var (
paymentCreator kit.TestFullNode
paymentReceiver kit.TestFullNode
)
creatorAddr, receiverAddr := startPaychCreatorReceiverMiner(ctx, t, &paymentCreator, &paymentReceiver, blocktime)
// Create mock CLI
mockCLI := kit.NewMockCLI(ctx, t, cli.Commands, api.NodeFull)
creatorCLI := mockCLI.Client(paymentCreator.ListenAddr)
receiverCLI := mockCLI.Client(paymentReceiver.ListenAddr)
// creator: paych add-funds <creator> <receiver> <amount>
channelAmt := "100000"
chstr := creatorCLI.RunCmd("paych", "add-funds", creatorAddr.String(), receiverAddr.String(), channelAmt)
chAddr, err := address.NewFromString(chstr)
require.NoError(t, err)
// creator: paych voucher create <channel> <amount>
voucherAmt := 100
vamt := strconv.Itoa(voucherAmt)
voucher := creatorCLI.RunCmd("paych", "voucher", "create", chAddr.String(), vamt)
// DEFLAKE: We have observed this test flakily failing when the receiver node hasn't seen the paych create message
// This makes us wait as much as 10 epochs before giving up and failing
retry := 0
_, err = paymentReceiver.StateLookupID(ctx, chAddr, types.EmptyTSK)
for err != nil && xerrors.Is(err, &api.ErrActorNotFound{}) {
time.Sleep(blocktime)
_, err = paymentReceiver.StateLookupID(ctx, chAddr, types.EmptyTSK)
retry++
if retry > 10 {
break
}
}
require.NoError(t, err)
// receiver: paych voucher add <channel> <voucher>
receiverCLI.RunCmd("paych", "voucher", "add", chAddr.String(), voucher)
// creator: paych settle <channel>
creatorCLI.RunCmd("paych", "settle", chAddr.String())
t.Log("wait for chain to reach settle height")
// Wait for the chain to reach the settle height
chState := getPaychState(ctx, t, paymentReceiver, chAddr)
sa, err := chState.SettlingAt()
require.NoError(t, err)
waitForHeight(ctx, t, paymentReceiver, sa)
t.Log("settle height reached")
// receiver: paych collect <channel>
receiverCLI.RunCmd("paych", "collect", chAddr.String())
}
type voucherSpec struct {
serialized string
amt int
lane int
}
// TestPaymentChannelStatus tests the payment channel status CLI command
func TestPaymentChannelStatus(t *testing.T) {
//stm: @CHAIN_SYNCER_LOAD_GENESIS_001, @CHAIN_SYNCER_FETCH_TIPSET_001,
//stm: @CHAIN_SYNCER_START_001, @CHAIN_SYNCER_SYNC_001, @BLOCKCHAIN_BEACON_VALIDATE_BLOCK_VALUES_01
//stm: @CHAIN_SYNCER_COLLECT_CHAIN_001, @CHAIN_SYNCER_COLLECT_HEADERS_001, @CHAIN_SYNCER_VALIDATE_TIPSET_001
//stm: @CHAIN_SYNCER_NEW_PEER_HEAD_001, @CHAIN_SYNCER_VALIDATE_MESSAGE_META_001, @CHAIN_SYNCER_STOP_001
_ = os.Setenv("BELLMAN_NO_GPU", "1")
kit.QuietMiningLogs()
blocktime := 5 * time.Millisecond
ctx := context.Background()
var (
paymentCreator kit.TestFullNode
paymentReceiver kit.TestFullNode
)
creatorAddr, receiverAddr := startPaychCreatorReceiverMiner(ctx, t, &paymentCreator, &paymentReceiver, blocktime)
// Create mock CLI
mockCLI := kit.NewMockCLI(ctx, t, cli.Commands, api.NodeFull)
creatorCLI := mockCLI.Client(paymentCreator.ListenAddr)
// creator: paych status-by-from-to <creator> <receiver>
out := creatorCLI.RunCmd("paych", "status-by-from-to", creatorAddr.String(), receiverAddr.String())
fmt.Println(out)
noChannelState := "Channel does not exist"
require.Regexp(t, regexp.MustCompile(noChannelState), out)
channelAmt := uint64(100)
create := make(chan string)
go func() {
// creator: paych add-funds <creator> <receiver> <amount>
create <- creatorCLI.RunCmd(
"paych",
"add-funds",
creatorAddr.String(),
receiverAddr.String(),
fmt.Sprintf("%d", channelAmt))
}()
// Wait for the output to stop being "Channel does not exist"
for regexp.MustCompile(noChannelState).MatchString(out) {
out = creatorCLI.RunCmd("paych", "status-by-from-to", creatorAddr.String(), receiverAddr.String())
}
fmt.Println(out)
// The next state should be creating channel or channel created, depending
// on timing
stateCreating := regexp.MustCompile("Creating channel").MatchString(out)
stateCreated := regexp.MustCompile("Channel exists").MatchString(out)
require.True(t, stateCreating || stateCreated)
channelAmtAtto := types.BigMul(types.NewInt(channelAmt), types.NewInt(build.FilecoinPrecision))
channelAmtStr := fmt.Sprintf("%s", types.FIL(channelAmtAtto))
if stateCreating {
// If we're in the creating state (most likely) the amount should be pending
require.Regexp(t, regexp.MustCompile("Pending Amt.*"+channelAmtStr), out)
}
// Wait for create channel to complete
chstr := <-create
out = creatorCLI.RunCmd("paych", "status", chstr)
fmt.Println(out)
// Output should have the channel address
require.Regexp(t, regexp.MustCompile("Channel.*"+chstr), out)
// Output should have confirmed amount
require.Regexp(t, regexp.MustCompile("Confirmed.*"+channelAmtStr), out)
chAddr, err := address.NewFromString(chstr)
require.NoError(t, err)
// creator: paych voucher create <channel> <amount>
voucherAmt := uint64(10)
creatorCLI.RunCmd("paych", "voucher", "create", chAddr.String(), fmt.Sprintf("%d", voucherAmt))
out = creatorCLI.RunCmd("paych", "status", chstr)
fmt.Println(out)
voucherAmtAtto := types.BigMul(types.NewInt(voucherAmt), types.NewInt(build.FilecoinPrecision))
voucherAmtStr := fmt.Sprintf("%s", types.FIL(voucherAmtAtto))
// Output should include voucher amount
require.Regexp(t, regexp.MustCompile("Voucher.*"+voucherAmtStr), out)
}
// TestPaymentChannelVouchers does a basic test to exercise some payment
// channel voucher commands
func TestPaymentChannelVouchers(t *testing.T) {
//stm: @CHAIN_SYNCER_LOAD_GENESIS_001, @CHAIN_SYNCER_FETCH_TIPSET_001,
//stm: @CHAIN_SYNCER_START_001, @CHAIN_SYNCER_SYNC_001, @BLOCKCHAIN_BEACON_VALIDATE_BLOCK_VALUES_01
//stm: @CHAIN_SYNCER_COLLECT_CHAIN_001, @CHAIN_SYNCER_COLLECT_HEADERS_001, @CHAIN_SYNCER_VALIDATE_TIPSET_001
//stm: @CHAIN_SYNCER_NEW_PEER_HEAD_001, @CHAIN_SYNCER_VALIDATE_MESSAGE_META_001, @CHAIN_SYNCER_STOP_001
//stm: @CHAIN_INCOMING_HANDLE_INCOMING_BLOCKS_001, @CHAIN_INCOMING_VALIDATE_BLOCK_PUBSUB_001, @CHAIN_INCOMING_VALIDATE_MESSAGE_PUBSUB_001
_ = os.Setenv("BELLMAN_NO_GPU", "1")
kit.QuietMiningLogs()
blocktime := 5 * time.Millisecond
ctx := context.Background()
var (
paymentCreator kit.TestFullNode
paymentReceiver kit.TestFullNode
)
creatorAddr, receiverAddr := startPaychCreatorReceiverMiner(ctx, t, &paymentCreator, &paymentReceiver, blocktime)
// Create mock CLI
mockCLI := kit.NewMockCLI(ctx, t, cli.Commands, api.NodeFull)
creatorCLI := mockCLI.Client(paymentCreator.ListenAddr)
receiverCLI := mockCLI.Client(paymentReceiver.ListenAddr)
// creator: paych add-funds <creator> <receiver> <amount>
channelAmt := "100000"
chstr := creatorCLI.RunCmd("paych", "add-funds", creatorAddr.String(), receiverAddr.String(), channelAmt)
chAddr, err := address.NewFromString(chstr)
require.NoError(t, err)
var vouchers []voucherSpec
// creator: paych voucher create <channel> <amount>
// Note: implied --lane=0
voucherAmt1 := 100
voucher1 := creatorCLI.RunCmd("paych", "voucher", "create", chAddr.String(), strconv.Itoa(voucherAmt1))
vouchers = append(vouchers, voucherSpec{serialized: voucher1, lane: 0, amt: voucherAmt1})
// creator: paych voucher create <channel> <amount> --lane=5
lane5 := "--lane=5"
voucherAmt2 := 50
voucher2 := creatorCLI.RunCmd("paych", "voucher", "create", lane5, chAddr.String(), strconv.Itoa(voucherAmt2))
vouchers = append(vouchers, voucherSpec{serialized: voucher2, lane: 5, amt: voucherAmt2})
// creator: paych voucher create <channel> <amount> --lane=5
voucherAmt3 := 70
voucher3 := creatorCLI.RunCmd("paych", "voucher", "create", lane5, chAddr.String(), strconv.Itoa(voucherAmt3))
vouchers = append(vouchers, voucherSpec{serialized: voucher3, lane: 5, amt: voucherAmt3})
// creator: paych voucher create <channel> <amount> --lane=5
voucherAmt4 := 80
voucher4 := creatorCLI.RunCmd("paych", "voucher", "create", lane5, chAddr.String(), strconv.Itoa(voucherAmt4))
vouchers = append(vouchers, voucherSpec{serialized: voucher4, lane: 5, amt: voucherAmt4})
// creator: paych voucher list <channel> --export
list := creatorCLI.RunCmd("paych", "voucher", "list", "--export", chAddr.String())
// Check that voucher list output is correct on creator
checkVoucherOutput(t, list, vouchers)
// creator: paych voucher best-spendable <channel>
bestSpendable := creatorCLI.RunCmd("paych", "voucher", "best-spendable", "--export", chAddr.String())
// Check that best spendable output is correct on creator
bestVouchers := []voucherSpec{
{serialized: voucher1, lane: 0, amt: voucherAmt1},
{serialized: voucher4, lane: 5, amt: voucherAmt4},
}
checkVoucherOutput(t, bestSpendable, bestVouchers)
// receiver: paych voucher add <voucher>
receiverCLI.RunCmd("paych", "voucher", "add", chAddr.String(), voucher1)
// receiver: paych voucher add <voucher>
receiverCLI.RunCmd("paych", "voucher", "add", chAddr.String(), voucher2)
// receiver: paych voucher add <voucher>
receiverCLI.RunCmd("paych", "voucher", "add", chAddr.String(), voucher3)
// receiver: paych voucher add <voucher>
receiverCLI.RunCmd("paych", "voucher", "add", chAddr.String(), voucher4)
// receiver: paych voucher list <channel> --export
list = receiverCLI.RunCmd("paych", "voucher", "list", "--export", chAddr.String())
// Check that voucher list output is correct on receiver
checkVoucherOutput(t, list, vouchers)
// receiver: paych voucher best-spendable <channel>
bestSpendable = receiverCLI.RunCmd("paych", "voucher", "best-spendable", "--export", chAddr.String())
// Check that best spendable output is correct on receiver
bestVouchers = []voucherSpec{
{serialized: voucher1, lane: 0, amt: voucherAmt1},
{serialized: voucher4, lane: 5, amt: voucherAmt4},
}
checkVoucherOutput(t, bestSpendable, bestVouchers)
// receiver: paych voucher submit <channel> <voucher>
receiverCLI.RunCmd("paych", "voucher", "submit", chAddr.String(), voucher1)
// receiver: paych voucher best-spendable <channel>
bestSpendable = receiverCLI.RunCmd("paych", "voucher", "best-spendable", "--export", chAddr.String())
// Check that best spendable output no longer includes submitted voucher
bestVouchers = []voucherSpec{
{serialized: voucher4, lane: 5, amt: voucherAmt4},
}
checkVoucherOutput(t, bestSpendable, bestVouchers)
// There are three vouchers in lane 5: 50, 70, 80
// Submit the voucher for 50. Best spendable should still be 80.
// receiver: paych voucher submit <channel> <voucher>
receiverCLI.RunCmd("paych", "voucher", "submit", chAddr.String(), voucher2)
// receiver: paych voucher best-spendable <channel>
bestSpendable = receiverCLI.RunCmd("paych", "voucher", "best-spendable", "--export", chAddr.String())
// Check that best spendable output still includes the voucher for 80
bestVouchers = []voucherSpec{
{serialized: voucher4, lane: 5, amt: voucherAmt4},
}
checkVoucherOutput(t, bestSpendable, bestVouchers)
// Submit the voucher for 80
// receiver: paych voucher submit <channel> <voucher>
receiverCLI.RunCmd("paych", "voucher", "submit", chAddr.String(), voucher4)
// receiver: paych voucher best-spendable <channel>
bestSpendable = receiverCLI.RunCmd("paych", "voucher", "best-spendable", "--export", chAddr.String())
// Check that best spendable output no longer includes submitted voucher
bestVouchers = []voucherSpec{}
checkVoucherOutput(t, bestSpendable, bestVouchers)
}
// TestPaymentChannelVoucherCreateShortfall verifies that if a voucher amount
// is greater than what's left in the channel, voucher create fails
func TestPaymentChannelVoucherCreateShortfall(t *testing.T) {
//stm: @CHAIN_SYNCER_LOAD_GENESIS_001, @CHAIN_SYNCER_FETCH_TIPSET_001,
//stm: @CHAIN_SYNCER_START_001, @CHAIN_SYNCER_SYNC_001, @BLOCKCHAIN_BEACON_VALIDATE_BLOCK_VALUES_01
//stm: @CHAIN_SYNCER_COLLECT_CHAIN_001, @CHAIN_SYNCER_COLLECT_HEADERS_001, @CHAIN_SYNCER_VALIDATE_TIPSET_001
//stm: @CHAIN_SYNCER_NEW_PEER_HEAD_001, @CHAIN_SYNCER_VALIDATE_MESSAGE_META_001, @CHAIN_SYNCER_STOP_001
//stm: @CHAIN_INCOMING_HANDLE_INCOMING_BLOCKS_001, @CHAIN_INCOMING_VALIDATE_BLOCK_PUBSUB_001, @CHAIN_INCOMING_VALIDATE_MESSAGE_PUBSUB_001
_ = os.Setenv("BELLMAN_NO_GPU", "1")
kit.QuietMiningLogs()
blocktime := 5 * time.Millisecond
ctx := context.Background()
var (
paymentCreator kit.TestFullNode
paymentReceiver kit.TestFullNode
)
creatorAddr, receiverAddr := startPaychCreatorReceiverMiner(ctx, t, &paymentCreator, &paymentReceiver, blocktime)
// Create mock CLI
mockCLI := kit.NewMockCLI(ctx, t, cli.Commands, api.NodeFull)
creatorCLI := mockCLI.Client(paymentCreator.ListenAddr)
// creator: paych add-funds <creator> <receiver> <amount>
channelAmt := 100
chstr := creatorCLI.RunCmd(
"paych",
"add-funds",
creatorAddr.String(),
receiverAddr.String(),
fmt.Sprintf("%d", channelAmt))
chAddr, err := address.NewFromString(chstr)
require.NoError(t, err)
// creator: paych voucher create <channel> <amount> --lane=1
voucherAmt1 := 60
lane1 := "--lane=1"
voucher1 := creatorCLI.RunCmd(
"paych",
"voucher",
"create",
lane1,
chAddr.String(),
strconv.Itoa(voucherAmt1))
fmt.Println(voucher1)
// creator: paych voucher create <channel> <amount> --lane=2
lane2 := "--lane=2"
voucherAmt2 := 70
_, err = creatorCLI.RunCmdRaw(
"paych",
"voucher",
"create",
lane2,
chAddr.String(),
strconv.Itoa(voucherAmt2))
// Should fail because channel doesn't have required amount
require.Error(t, err)
shortfall := voucherAmt1 + voucherAmt2 - channelAmt
require.Regexp(t, regexp.MustCompile(fmt.Sprintf("shortfall: %d", shortfall)), err.Error())
}
func checkVoucherOutput(t *testing.T, list string, vouchers []voucherSpec) {
lines := strings.Split(list, "\n")
listVouchers := make(map[string]string)
for _, line := range lines {
parts := strings.Split(line, ";")
if len(parts) == 2 {
serialized := strings.TrimSpace(parts[1])
listVouchers[serialized] = strings.TrimSpace(parts[0])
}
}
for _, vchr := range vouchers {
res, ok := listVouchers[vchr.serialized]
require.True(t, ok)
require.Regexp(t, fmt.Sprintf("Lane %d", vchr.lane), res)
require.Regexp(t, fmt.Sprintf("%d", vchr.amt), res)
delete(listVouchers, vchr.serialized)
}
for _, vchr := range listVouchers {
require.Fail(t, "Extra voucher "+vchr)
}
}
// waitForHeight waits for the node to reach the given chain epoch
func waitForHeight(ctx context.Context, t *testing.T, node kit.TestFullNode, height abi.ChainEpoch) {
atHeight := make(chan struct{})
chainEvents, err := events.NewEvents(ctx, node)
require.NoError(t, err)
err = chainEvents.ChainAt(ctx, func(ctx context.Context, ts *types.TipSet, curH abi.ChainEpoch) error {
close(atHeight)
return nil
}, nil, 1, height)
if err != nil {
t.Fatal(err)
}
select {
case <-atHeight:
case <-ctx.Done():
}
}
// getPaychState gets the state of the payment channel with the given address
func getPaychState(ctx context.Context, t *testing.T, node kit.TestFullNode, chAddr address.Address) paych.State {
act, err := node.StateGetActor(ctx, chAddr, types.EmptyTSK)
require.NoError(t, err)
store := cbor.NewCborStore(blockstore.NewAPIBlockstore(node))
chState, err := paych.Load(adt.WrapStore(ctx, store), act)
require.NoError(t, err)
return chState
}
func startPaychCreatorReceiverMiner(ctx context.Context, t *testing.T, paymentCreator *kit.TestFullNode, paymentReceiver *kit.TestFullNode, blocktime time.Duration) (address.Address, address.Address) {
var miner kit.TestMiner
opts := kit.ThroughRPC()
kit.NewEnsemble(t, kit.MockProofs()).
FullNode(paymentCreator, opts).
FullNode(paymentReceiver, opts).
Miner(&miner, paymentCreator, kit.WithAllSubsystems()).
Start().
InterconnectAll().
BeginMining(blocktime)
// Send some funds to the second node
receiverAddr, err := paymentReceiver.WalletDefaultAddress(ctx)
require.NoError(t, err)
kit.SendFunds(ctx, t, paymentCreator, receiverAddr, abi.NewTokenAmount(1e18))
// Get the first node's address
creatorAddr, err := paymentCreator.WalletDefaultAddress(ctx)
require.NoError(t, err)
return creatorAddr, receiverAddr
}