Merge pull request #6467 from filecoin-project/refactor/itests-paych

This commit is contained in:
raulk 2021-06-15 10:59:13 +01:00 committed by GitHub
commit c5b7e48cd1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 69 additions and 144 deletions

View File

@ -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")
} }

View File

@ -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")

View File

@ -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
} }