Merge pull request #6467 from filecoin-project/refactor/itests-paych
This commit is contained in:
commit
c5b7e48cd1
@ -30,5 +30,5 @@ func SendFunds(ctx context.Context, t *testing.T, sender TestFullNode, recipient
|
|||||||
res, err := sender.StateWaitMsg(ctx, sm.Cid(), 3, api.LookbackNoLimit, true)
|
res, err := sender.StateWaitMsg(ctx, sm.Cid(), 3, api.LookbackNoLimit, true)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, 0, res.Receipt.ExitCode, "did not successfully send funds")
|
require.EqualValues(t, 0, res.Receipt.ExitCode, "did not successfully send funds")
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
func QuietMiningLogs() {
|
func QuietMiningLogs() {
|
||||||
lotuslog.SetupLogLevels()
|
lotuslog.SetupLogLevels()
|
||||||
|
|
||||||
_ = logging.SetLogLevel("miner", "ERROR")
|
_ = logging.SetLogLevel("miner", "ERROR") // set this to INFO to watch mining happen.
|
||||||
_ = logging.SetLogLevel("chainstore", "ERROR")
|
_ = logging.SetLogLevel("chainstore", "ERROR")
|
||||||
_ = logging.SetLogLevel("chain", "ERROR")
|
_ = logging.SetLogLevel("chain", "ERROR")
|
||||||
_ = logging.SetLogLevel("sub", "ERROR")
|
_ = logging.SetLogLevel("sub", "ERROR")
|
||||||
|
@ -2,14 +2,13 @@ package itests
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
"github.com/filecoin-project/go-state-types/big"
|
"github.com/filecoin-project/go-state-types/big"
|
||||||
"github.com/filecoin-project/lotus/itests/kit"
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
cbor "github.com/ipfs/go-ipld-cbor"
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||||||
@ -24,69 +23,52 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/events"
|
"github.com/filecoin-project/lotus/chain/events"
|
||||||
"github.com/filecoin-project/lotus/chain/events/state"
|
"github.com/filecoin-project/lotus/chain/events/state"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
"github.com/filecoin-project/lotus/itests/kit2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPaymentChannelsAPI(t *testing.T) {
|
func TestPaymentChannelsAPI(t *testing.T) {
|
||||||
kit.QuietMiningLogs()
|
kit2.QuietMiningLogs()
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
n, sn := kit.MockMinerBuilder(t, kit.TwoFull, kit.OneMiner)
|
blockTime := 5 * time.Millisecond
|
||||||
|
|
||||||
paymentCreator := n[0]
|
var (
|
||||||
paymentReceiver := n[1]
|
paymentCreator kit2.TestFullNode
|
||||||
miner := sn[0]
|
paymentReceiver kit2.TestFullNode
|
||||||
|
miner kit2.TestMiner
|
||||||
|
)
|
||||||
|
|
||||||
// get everyone connected
|
ens := kit2.NewEnsemble(t, kit2.MockProofs()).
|
||||||
addrs, err := paymentCreator.NetAddrsListen(ctx)
|
FullNode(&paymentCreator).
|
||||||
if err != nil {
|
FullNode(&paymentReceiver).
|
||||||
t.Fatal(err)
|
Miner(&miner, &paymentCreator).
|
||||||
}
|
Start().
|
||||||
|
InterconnectAll()
|
||||||
if err := paymentReceiver.NetConnect(ctx, addrs); err != nil {
|
bms := ens.BeginMining(blockTime)
|
||||||
t.Fatal(err)
|
bm := bms[0]
|
||||||
}
|
|
||||||
|
|
||||||
if err := miner.NetConnect(ctx, addrs); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// start mining blocks
|
|
||||||
bm := kit.NewBlockMiner(t, miner)
|
|
||||||
bm.MineBlocks(ctx, 5*time.Millisecond)
|
|
||||||
t.Cleanup(bm.Stop)
|
|
||||||
|
|
||||||
// send some funds to register the receiver
|
// send some funds to register the receiver
|
||||||
receiverAddr, err := paymentReceiver.WalletNew(ctx, types.KTSecp256k1)
|
receiverAddr, err := paymentReceiver.WalletNew(ctx, types.KTSecp256k1)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
kit.SendFunds(ctx, t, paymentCreator, receiverAddr, abi.NewTokenAmount(1e18))
|
kit2.SendFunds(ctx, t, paymentCreator, receiverAddr, abi.NewTokenAmount(1e18))
|
||||||
|
|
||||||
// setup the payment channel
|
// setup the payment channel
|
||||||
createrAddr, err := paymentCreator.WalletDefaultAddress(ctx)
|
createrAddr, err := paymentCreator.WalletDefaultAddress(ctx)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
channelAmt := int64(7000)
|
channelAmt := int64(7000)
|
||||||
channelInfo, err := paymentCreator.PaychGet(ctx, createrAddr, receiverAddr, abi.NewTokenAmount(channelAmt))
|
channelInfo, err := paymentCreator.PaychGet(ctx, createrAddr, receiverAddr, abi.NewTokenAmount(channelAmt))
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
channel, err := paymentCreator.PaychGetWaitReady(ctx, channelInfo.WaitSentinel)
|
channel, err := paymentCreator.PaychGetWaitReady(ctx, channelInfo.WaitSentinel)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocate three lanes
|
// allocate three lanes
|
||||||
var lanes []uint64
|
var lanes []uint64
|
||||||
for i := 0; i < 3; i++ {
|
for i := 0; i < 3; i++ {
|
||||||
lane, err := paymentCreator.PaychAllocateLane(ctx, channel)
|
lane, err := paymentCreator.PaychAllocateLane(ctx, channel)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
lanes = append(lanes, lane)
|
lanes = append(lanes, lane)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,45 +77,28 @@ func TestPaymentChannelsAPI(t *testing.T) {
|
|||||||
// supersedes the voucher with a value of 1000
|
// supersedes the voucher with a value of 1000
|
||||||
for _, lane := range lanes {
|
for _, lane := range lanes {
|
||||||
vouch1, err := paymentCreator.PaychVoucherCreate(ctx, channel, abi.NewTokenAmount(1000), lane)
|
vouch1, err := paymentCreator.PaychVoucherCreate(ctx, channel, abi.NewTokenAmount(1000), lane)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
require.NotNil(t, vouch1.Voucher, "Not enough funds to create voucher: missing %d", vouch1.Shortfall)
|
||||||
}
|
|
||||||
if vouch1.Voucher == nil {
|
|
||||||
t.Fatal(fmt.Errorf("Not enough funds to create voucher: missing %d", vouch1.Shortfall))
|
|
||||||
}
|
|
||||||
vouch2, err := paymentCreator.PaychVoucherCreate(ctx, channel, abi.NewTokenAmount(2000), lane)
|
vouch2, err := paymentCreator.PaychVoucherCreate(ctx, channel, abi.NewTokenAmount(2000), lane)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
require.NotNil(t, vouch2.Voucher, "Not enough funds to create voucher: missing %d", vouch2.Shortfall)
|
||||||
}
|
|
||||||
if vouch2.Voucher == nil {
|
|
||||||
t.Fatal(fmt.Errorf("Not enough funds to create voucher: missing %d", vouch2.Shortfall))
|
|
||||||
}
|
|
||||||
delta1, err := paymentReceiver.PaychVoucherAdd(ctx, channel, vouch1.Voucher, nil, abi.NewTokenAmount(1000))
|
delta1, err := paymentReceiver.PaychVoucherAdd(ctx, channel, vouch1.Voucher, nil, abi.NewTokenAmount(1000))
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
require.EqualValues(t, abi.NewTokenAmount(1000), delta1, "voucher didn't have the right amount")
|
||||||
}
|
|
||||||
if !delta1.Equals(abi.NewTokenAmount(1000)) {
|
|
||||||
t.Fatal("voucher didn't have the right amount")
|
|
||||||
}
|
|
||||||
delta2, err := paymentReceiver.PaychVoucherAdd(ctx, channel, vouch2.Voucher, nil, abi.NewTokenAmount(1000))
|
delta2, err := paymentReceiver.PaychVoucherAdd(ctx, channel, vouch2.Voucher, nil, abi.NewTokenAmount(1000))
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
require.EqualValues(t, abi.NewTokenAmount(1000), delta2, "voucher didn't have the right amount")
|
||||||
}
|
|
||||||
if !delta2.Equals(abi.NewTokenAmount(1000)) {
|
|
||||||
t.Fatal("voucher didn't have the right amount")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// settle the payment channel
|
// settle the payment channel
|
||||||
settleMsgCid, err := paymentCreator.PaychSettle(ctx, channel)
|
settleMsgCid, err := paymentCreator.PaychSettle(ctx, channel)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := waitForMessage(ctx, t, paymentCreator, settleMsgCid, time.Second*10, "settle")
|
res := waitForMessage(ctx, t, paymentCreator, settleMsgCid, time.Second*10, "settle")
|
||||||
if res.Receipt.ExitCode != 0 {
|
require.EqualValues(t, 0, res.Receipt.ExitCode, "Unable to settle payment channel")
|
||||||
t.Fatal("Unable to settle payment channel")
|
|
||||||
}
|
|
||||||
|
|
||||||
creatorStore := adt.WrapStore(ctx, cbor.NewCborStore(blockstore.NewAPIBlockstore(paymentCreator)))
|
creatorStore := adt.WrapStore(ctx, cbor.NewCborStore(blockstore.NewAPIBlockstore(paymentCreator)))
|
||||||
|
|
||||||
@ -170,9 +135,7 @@ func TestPaymentChannelsAPI(t *testing.T) {
|
|||||||
}, int(build.MessageConfidence)+1, build.Finality, func(oldTs, newTs *types.TipSet) (bool, events.StateChange, error) {
|
}, int(build.MessageConfidence)+1, build.Finality, func(oldTs, newTs *types.TipSet) (bool, events.StateChange, error) {
|
||||||
return preds.OnPaymentChannelActorChanged(channel, preds.OnToSendAmountChanges())(ctx, oldTs.Key(), newTs.Key())
|
return preds.OnPaymentChannelActorChanged(channel, preds.OnToSendAmountChanges())(ctx, oldTs.Key(), newTs.Key())
|
||||||
})
|
})
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-finished:
|
case <-finished:
|
||||||
@ -182,75 +145,49 @@ func TestPaymentChannelsAPI(t *testing.T) {
|
|||||||
|
|
||||||
// Create a new voucher now that some vouchers have already been submitted
|
// Create a new voucher now that some vouchers have already been submitted
|
||||||
vouchRes, err := paymentCreator.PaychVoucherCreate(ctx, channel, abi.NewTokenAmount(1000), 3)
|
vouchRes, err := paymentCreator.PaychVoucherCreate(ctx, channel, abi.NewTokenAmount(1000), 3)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
require.NotNil(t, vouchRes.Voucher, "Not enough funds to create voucher: missing %d", vouchRes.Shortfall)
|
||||||
}
|
|
||||||
if vouchRes.Voucher == nil {
|
|
||||||
t.Fatal(fmt.Errorf("Not enough funds to create voucher: missing %d", vouchRes.Shortfall))
|
|
||||||
}
|
|
||||||
vdelta, err := paymentReceiver.PaychVoucherAdd(ctx, channel, vouchRes.Voucher, nil, abi.NewTokenAmount(1000))
|
vdelta, err := paymentReceiver.PaychVoucherAdd(ctx, channel, vouchRes.Voucher, nil, abi.NewTokenAmount(1000))
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
require.EqualValues(t, abi.NewTokenAmount(1000), vdelta, "voucher didn't have the right amount")
|
||||||
}
|
|
||||||
if !vdelta.Equals(abi.NewTokenAmount(1000)) {
|
|
||||||
t.Fatal("voucher didn't have the right amount")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new voucher whose value would exceed the channel balance
|
// Create a new voucher whose value would exceed the channel balance
|
||||||
excessAmt := abi.NewTokenAmount(1000)
|
excessAmt := abi.NewTokenAmount(1000)
|
||||||
vouchRes, err = paymentCreator.PaychVoucherCreate(ctx, channel, excessAmt, 4)
|
vouchRes, err = paymentCreator.PaychVoucherCreate(ctx, channel, excessAmt, 4)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
require.Nil(t, vouchRes.Voucher, "Expected not to be able to create voucher whose value would exceed channel balance")
|
||||||
}
|
require.EqualValues(t, excessAmt, vouchRes.Shortfall, "Expected voucher shortfall of %d, got %d", excessAmt, vouchRes.Shortfall)
|
||||||
if vouchRes.Voucher != nil {
|
|
||||||
t.Fatal("Expected not to be able to create voucher whose value would exceed channel balance")
|
|
||||||
}
|
|
||||||
if !vouchRes.Shortfall.Equals(excessAmt) {
|
|
||||||
t.Fatal(fmt.Errorf("Expected voucher shortfall of %d, got %d", excessAmt, vouchRes.Shortfall))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a voucher whose value would exceed the channel balance
|
// Add a voucher whose value would exceed the channel balance
|
||||||
vouch := &paych.SignedVoucher{ChannelAddr: channel, Amount: excessAmt, Lane: 4, Nonce: 1}
|
vouch := &paych.SignedVoucher{ChannelAddr: channel, Amount: excessAmt, Lane: 4, Nonce: 1}
|
||||||
vb, err := vouch.SigningBytes()
|
vb, err := vouch.SigningBytes()
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
sig, err := paymentCreator.WalletSign(ctx, createrAddr, vb)
|
sig, err := paymentCreator.WalletSign(ctx, createrAddr, vb)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
vouch.Signature = sig
|
vouch.Signature = sig
|
||||||
_, err = paymentReceiver.PaychVoucherAdd(ctx, channel, vouch, nil, abi.NewTokenAmount(1000))
|
_, err = paymentReceiver.PaychVoucherAdd(ctx, channel, vouch, nil, abi.NewTokenAmount(1000))
|
||||||
if err == nil {
|
require.Errorf(t, err, "Expected shortfall error of %d", excessAmt)
|
||||||
t.Fatal(fmt.Errorf("Expected shortfall error of %d", excessAmt))
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait for the settlement period to pass before collecting
|
// wait for the settlement period to pass before collecting
|
||||||
waitForBlocks(ctx, t, bm, paymentReceiver, receiverAddr, policy.PaychSettleDelay)
|
waitForBlocks(ctx, t, bm, paymentReceiver, receiverAddr, policy.PaychSettleDelay)
|
||||||
|
|
||||||
creatorPreCollectBalance, err := paymentCreator.WalletBalance(ctx, createrAddr)
|
creatorPreCollectBalance, err := paymentCreator.WalletBalance(ctx, createrAddr)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// collect funds (from receiver, though either party can do it)
|
// collect funds (from receiver, though either party can do it)
|
||||||
collectMsg, err := paymentReceiver.PaychCollect(ctx, channel)
|
collectMsg, err := paymentReceiver.PaychCollect(ctx, channel)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
res, err = paymentReceiver.StateWaitMsg(ctx, collectMsg, 3, api.LookbackNoLimit, true)
|
res, err = paymentReceiver.StateWaitMsg(ctx, collectMsg, 3, api.LookbackNoLimit, true)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
require.EqualValues(t, 0, res.Receipt.ExitCode, "unable to collect on payment channel")
|
||||||
}
|
|
||||||
if res.Receipt.ExitCode != 0 {
|
|
||||||
t.Fatal("unable to collect on payment channel")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, check the balance for the creator
|
// Finally, check the balance for the creator
|
||||||
currentCreatorBalance, err := paymentCreator.WalletBalance(ctx, createrAddr)
|
currentCreatorBalance, err := paymentCreator.WalletBalance(ctx, createrAddr)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The highest nonce voucher that the creator sent on each lane is 2000
|
// The highest nonce voucher that the creator sent on each lane is 2000
|
||||||
totalVouchers := int64(len(lanes) * 2000)
|
totalVouchers := int64(len(lanes) * 2000)
|
||||||
@ -260,15 +197,10 @@ func TestPaymentChannelsAPI(t *testing.T) {
|
|||||||
// channel amount - total voucher value
|
// channel amount - total voucher value
|
||||||
expectedRefund := channelAmt - totalVouchers
|
expectedRefund := channelAmt - totalVouchers
|
||||||
delta := big.Sub(currentCreatorBalance, creatorPreCollectBalance)
|
delta := big.Sub(currentCreatorBalance, creatorPreCollectBalance)
|
||||||
if !delta.Equals(abi.NewTokenAmount(expectedRefund)) {
|
require.EqualValues(t, abi.NewTokenAmount(expectedRefund), delta, "did not send correct funds from creator: expected %d, got %d", expectedRefund, delta)
|
||||||
t.Fatalf("did not send correct funds from creator: expected %d, got %d", expectedRefund, delta)
|
|
||||||
}
|
|
||||||
|
|
||||||
// shut down mining
|
|
||||||
bm.Stop()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func waitForBlocks(ctx context.Context, t *testing.T, bm *kit.BlockMiner, paymentReceiver kit.TestFullNode, receiverAddr address.Address, count int) {
|
func waitForBlocks(ctx context.Context, t *testing.T, bm *kit2.BlockMiner, paymentReceiver kit2.TestFullNode, receiverAddr address.Address, count int) {
|
||||||
// We need to add null blocks in batches, if we add too many the chain can't sync
|
// We need to add null blocks in batches, if we add too many the chain can't sync
|
||||||
batchSize := 60
|
batchSize := 60
|
||||||
for i := 0; i < count; i += batchSize {
|
for i := 0; i < count; i += batchSize {
|
||||||
@ -286,30 +218,23 @@ func waitForBlocks(ctx context.Context, t *testing.T, bm *kit.BlockMiner, paymen
|
|||||||
From: receiverAddr,
|
From: receiverAddr,
|
||||||
Value: types.NewInt(0),
|
Value: types.NewInt(0),
|
||||||
}, nil)
|
}, nil)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = paymentReceiver.StateWaitMsg(ctx, m.Cid(), 1, api.LookbackNoLimit, true)
|
_, err = paymentReceiver.StateWaitMsg(ctx, m.Cid(), 1, api.LookbackNoLimit, true)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func waitForMessage(ctx context.Context, t *testing.T, paymentCreator kit.TestFullNode, msgCid cid.Cid, duration time.Duration, desc string) *api.MsgLookup {
|
func waitForMessage(ctx context.Context, t *testing.T, paymentCreator kit2.TestFullNode, msgCid cid.Cid, duration time.Duration, desc string) *api.MsgLookup {
|
||||||
ctx, cancel := context.WithTimeout(ctx, duration)
|
ctx, cancel := context.WithTimeout(ctx, duration)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
fmt.Println("Waiting for", desc)
|
t.Log("Waiting for", desc)
|
||||||
|
|
||||||
res, err := paymentCreator.StateWaitMsg(ctx, msgCid, 1, api.LookbackNoLimit, true)
|
res, err := paymentCreator.StateWaitMsg(ctx, msgCid, 1, api.LookbackNoLimit, true)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
fmt.Println("Error waiting for", desc, err)
|
require.EqualValues(t, 0, res.Receipt.ExitCode, "did not successfully send %s", desc)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
t.Log("Confirmed", desc)
|
||||||
if res.Receipt.ExitCode != 0 {
|
|
||||||
t.Fatalf("did not successfully send %s", desc)
|
|
||||||
}
|
|
||||||
fmt.Println("Confirmed", desc)
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user